1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
28 #pragma warning(disable:4740)
29 #endif
30 
31 #define _WIN32_WINNT 0x0400
32 #include "macros.h"
33 
34 #define	BUFSIZE	16384
35 
36 static DWORD CALLBACK DefCopyProgressRoutine(
37 	LARGE_INTEGER	TotalFileSize,	// total file size, in bytes
38 	LARGE_INTEGER	TotalBytesTransferred,
39 									// total number of bytes transferred
40 	LARGE_INTEGER	StreamSize,		// total number of bytes for this stream
41 	LARGE_INTEGER	StreamBytesTransferred,
42 									// total number of bytes transferred for
43 									// this stream
44 	DWORD		dwStreamNumber,		// the current stream
45 	DWORD		dwCallbackReason,	// reason for callback
46 	HANDLE	hSourceFile,			// handle to the source file
47 	HANDLE	hDestinationFile,		// handle to the destination file
48 	LPVOID	lpData					// passed by CopyFileEx
49 )
50 {
51 	return PROGRESS_CONTINUE;
52 }
53 
54 
55 IMPLEMENT_THUNK( kernel32, WINDOWS, BOOL, WINAPI, CopyFileExA, ( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, LPPROGRESS_ROUTINE  lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags ) )
56 {
57 	BOOL	fSuccess = FALSE; // Assume failure
58 
59 	HANDLE	hSourceFile = CreateFileA(
60 		lpExistingFileNameA,
61 		GENERIC_READ,
62 		FILE_SHARE_READ | FILE_SHARE_WRITE,
63 		NULL,
64 		OPEN_EXISTING,
65 		0,
66 		NULL
67 		);
68 
69 	if ( IsValidHandle(hSourceFile) )
70 	{
71 		LARGE_INTEGER	FileSize, BytesTransferred;
72 		HANDLE	hTargetFile = NULL;
73 
74 		SetLastError( ERROR_SUCCESS );
75 		FileSize.LowPart = GetFileSize( hSourceFile, (LPDWORD)&FileSize.HighPart );
76 		BytesTransferred.QuadPart = 0;
77 
78 		if ( (DWORD)-1 != FileSize.LowPart || ERROR_SUCCESS == GetLastError() )
79 			hTargetFile = CreateFileA(
80 				lpNewFileNameA,
81 				GENERIC_WRITE,
82 				0,
83 				NULL,
84 				(DWORD) ((dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS),
85 				0,
86 				NULL
87 				);
88 
89 		if ( IsValidHandle(hTargetFile) )
90 		{
91 			DWORD dwProgressResult = PROGRESS_CONTINUE;
92 
93 			fSuccess = SetEndOfFile( hTargetFile );
94 
95 			if ( fSuccess )
96 			{
97 				if ( !lpProgressRoutine )
98 					lpProgressRoutine = DefCopyProgressRoutine;
99 
100 				dwProgressResult = lpProgressRoutine(
101 					FileSize,
102 					BytesTransferred,
103 					FileSize,
104 					BytesTransferred,
105 					1,
106 					CALLBACK_STREAM_SWITCH,
107 					hSourceFile,
108 					hTargetFile,
109 					lpData
110 					);
111 
112 				// Suppress further notifications
113 
114 				if ( PROGRESS_QUIET == dwProgressResult )
115 				{
116 					lpProgressRoutine = DefCopyProgressRoutine;
117 					dwProgressResult = PROGRESS_CONTINUE;
118 				}
119 			}
120 
121 			while ( fSuccess && PROGRESS_CONTINUE == dwProgressResult )
122 			{
123 				BYTE	buffer[BUFSIZE];
124 				DWORD	dwBytesRead, dwBytesWritten = 0;
125 
126 				fSuccess = ReadFile( hSourceFile, buffer, BUFSIZE, &dwBytesRead, NULL );
127 
128 				if ( !dwBytesRead ) break;
129 
130 				if ( fSuccess )
131 					fSuccess = WriteFile( hTargetFile, buffer, dwBytesRead, &dwBytesWritten, NULL );
132 
133 				if ( fSuccess )
134 				{
135 					BytesTransferred.QuadPart += (LONGLONG)dwBytesWritten;
136 
137 					if ( pbCancel && *pbCancel )
138 						dwProgressResult = PROGRESS_CANCEL;
139 					else
140 						dwProgressResult = lpProgressRoutine(
141 							FileSize,
142 							BytesTransferred,
143 							FileSize,
144 							BytesTransferred,
145 							1,
146 							CALLBACK_CHUNK_FINISHED,
147 							hSourceFile,
148 							hTargetFile,
149 							lpData
150 							);
151 
152 				}
153 
154 			}
155 
156 			CloseHandle( hTargetFile );
157 
158 			if ( PROGRESS_CANCEL == dwProgressResult )
159 				DeleteFileA( lpNewFileNameA );
160 		}
161 
162 
163 		CloseHandle( hSourceFile );
164 	}
165 
166 	return fSuccess;
167 }