xref: /AOO41X/main/sal/systools/win32/uwinapi/CopyFileExA.cpp (revision fc0bc00825ec02ef04af0b032f1c57b312b79937)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
24 #pragma warning(disable:4740)
25 #endif
26 
27 #define _WIN32_WINNT 0x0400
28 #include "macros.h"
29 
30 #define BUFSIZE 16384
31 
DefCopyProgressRoutine(LARGE_INTEGER TotalFileSize,LARGE_INTEGER TotalBytesTransferred,LARGE_INTEGER StreamSize,LARGE_INTEGER StreamBytesTransferred,DWORD dwStreamNumber,DWORD dwCallbackReason,HANDLE hSourceFile,HANDLE hDestinationFile,LPVOID lpData)32 static DWORD CALLBACK DefCopyProgressRoutine(
33     LARGE_INTEGER   TotalFileSize,  // total file size, in bytes
34     LARGE_INTEGER   TotalBytesTransferred,
35                                     // total number of bytes transferred
36     LARGE_INTEGER   StreamSize,     // total number of bytes for this stream
37     LARGE_INTEGER   StreamBytesTransferred,
38                                     // total number of bytes transferred for
39                                     // this stream
40     DWORD       dwStreamNumber,     // the current stream
41     DWORD       dwCallbackReason,   // reason for callback
42     HANDLE  hSourceFile,            // handle to the source file
43     HANDLE  hDestinationFile,       // handle to the destination file
44     LPVOID  lpData                  // passed by CopyFileEx
45 )
46 {
47     return PROGRESS_CONTINUE;
48 }
49 
50 
51 IMPLEMENT_THUNK( kernel32, WINDOWS, BOOL, WINAPI, CopyFileExA, ( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, LPPROGRESS_ROUTINE  lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags ) )
52 {
53     BOOL    fSuccess = FALSE; // Assume failure
54 
55     HANDLE  hSourceFile = CreateFileA(
56         lpExistingFileNameA,
57         GENERIC_READ,
58         FILE_SHARE_READ | FILE_SHARE_WRITE,
59         NULL,
60         OPEN_EXISTING,
61         0,
62         NULL
63         );
64 
65     if ( IsValidHandle(hSourceFile) )
66     {
67         LARGE_INTEGER   FileSize, BytesTransferred;
68         HANDLE  hTargetFile = NULL;
69 
70         SetLastError( ERROR_SUCCESS );
71         FileSize.LowPart = GetFileSize( hSourceFile, (LPDWORD)&FileSize.HighPart );
72         BytesTransferred.QuadPart = 0;
73 
74         if ( (DWORD)-1 != FileSize.LowPart || ERROR_SUCCESS == GetLastError() )
75             hTargetFile = CreateFileA(
76                 lpNewFileNameA,
77                 GENERIC_WRITE,
78                 0,
79                 NULL,
80                 (DWORD) ((dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS),
81                 0,
82                 NULL
83                 );
84 
85         if ( IsValidHandle(hTargetFile) )
86         {
87             DWORD dwProgressResult = PROGRESS_CONTINUE;
88 
89             fSuccess = SetEndOfFile( hTargetFile );
90 
91             if ( fSuccess )
92             {
93                 if ( !lpProgressRoutine )
94                     lpProgressRoutine = DefCopyProgressRoutine;
95 
96                 dwProgressResult = lpProgressRoutine(
97                     FileSize,
98                     BytesTransferred,
99                     FileSize,
100                     BytesTransferred,
101                     1,
102                     CALLBACK_STREAM_SWITCH,
103                     hSourceFile,
104                     hTargetFile,
105                     lpData
106                     );
107 
108                 // Suppress further notifications
109 
110                 if ( PROGRESS_QUIET == dwProgressResult )
111                 {
112                     lpProgressRoutine = DefCopyProgressRoutine;
113                     dwProgressResult = PROGRESS_CONTINUE;
114                 }
115             }
116 
117             while ( fSuccess && PROGRESS_CONTINUE == dwProgressResult )
118             {
119                 BYTE    buffer[BUFSIZE];
120                 DWORD   dwBytesRead, dwBytesWritten = 0;
121 
122                 fSuccess = ReadFile( hSourceFile, buffer, BUFSIZE, &dwBytesRead, NULL );
123 
124                 if ( !dwBytesRead ) break;
125 
126                 if ( fSuccess )
127                     fSuccess = WriteFile( hTargetFile, buffer, dwBytesRead, &dwBytesWritten, NULL );
128 
129                 if ( fSuccess )
130                 {
131                     BytesTransferred.QuadPart += (LONGLONG)dwBytesWritten;
132 
133                     if ( pbCancel && *pbCancel )
134                         dwProgressResult = PROGRESS_CANCEL;
135                     else
136                         dwProgressResult = lpProgressRoutine(
137                             FileSize,
138                             BytesTransferred,
139                             FileSize,
140                             BytesTransferred,
141                             1,
142                             CALLBACK_CHUNK_FINISHED,
143                             hSourceFile,
144                             hTargetFile,
145                             lpData
146                             );
147 
148                 }
149 
150             }
151 
152             CloseHandle( hTargetFile );
153 
154             if ( PROGRESS_CANCEL == dwProgressResult )
155                 DeleteFileA( lpNewFileNameA );
156         }
157 
158 
159         CloseHandle( hSourceFile );
160     }
161 
162     return fSuccess;
163 }