xref: /trunk/main/sal/systools/win32/uwinapi/CopyFileExA.cpp (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 }