/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #if defined(_MSC_VER) && (_MSC_VER >= 1400) #pragma warning(disable:4740) #endif #define _WIN32_WINNT 0x0400 #include "macros.h" #define BUFSIZE 16384 static DWORD CALLBACK DefCopyProgressRoutine( LARGE_INTEGER TotalFileSize, // total file size, in bytes LARGE_INTEGER TotalBytesTransferred, // total number of bytes transferred LARGE_INTEGER StreamSize, // total number of bytes for this stream LARGE_INTEGER StreamBytesTransferred, // total number of bytes transferred for // this stream DWORD dwStreamNumber, // the current stream DWORD dwCallbackReason, // reason for callback HANDLE hSourceFile, // handle to the source file HANDLE hDestinationFile, // handle to the destination file LPVOID lpData // passed by CopyFileEx ) { return PROGRESS_CONTINUE; } IMPLEMENT_THUNK( kernel32, WINDOWS, BOOL, WINAPI, CopyFileExA, ( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, LPBOOL pbCancel, DWORD dwCopyFlags ) ) { BOOL fSuccess = FALSE; // Assume failure HANDLE hSourceFile = CreateFileA( lpExistingFileNameA, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if ( IsValidHandle(hSourceFile) ) { LARGE_INTEGER FileSize, BytesTransferred; HANDLE hTargetFile = NULL; SetLastError( ERROR_SUCCESS ); FileSize.LowPart = GetFileSize( hSourceFile, (LPDWORD)&FileSize.HighPart ); BytesTransferred.QuadPart = 0; if ( (DWORD)-1 != FileSize.LowPart || ERROR_SUCCESS == GetLastError() ) hTargetFile = CreateFileA( lpNewFileNameA, GENERIC_WRITE, 0, NULL, (DWORD) ((dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS), 0, NULL ); if ( IsValidHandle(hTargetFile) ) { DWORD dwProgressResult = PROGRESS_CONTINUE; fSuccess = SetEndOfFile( hTargetFile ); if ( fSuccess ) { if ( !lpProgressRoutine ) lpProgressRoutine = DefCopyProgressRoutine; dwProgressResult = lpProgressRoutine( FileSize, BytesTransferred, FileSize, BytesTransferred, 1, CALLBACK_STREAM_SWITCH, hSourceFile, hTargetFile, lpData ); // Suppress further notifications if ( PROGRESS_QUIET == dwProgressResult ) { lpProgressRoutine = DefCopyProgressRoutine; dwProgressResult = PROGRESS_CONTINUE; } } while ( fSuccess && PROGRESS_CONTINUE == dwProgressResult ) { BYTE buffer[BUFSIZE]; DWORD dwBytesRead, dwBytesWritten = 0; fSuccess = ReadFile( hSourceFile, buffer, BUFSIZE, &dwBytesRead, NULL ); if ( !dwBytesRead ) break; if ( fSuccess ) fSuccess = WriteFile( hTargetFile, buffer, dwBytesRead, &dwBytesWritten, NULL ); if ( fSuccess ) { BytesTransferred.QuadPart += (LONGLONG)dwBytesWritten; if ( pbCancel && *pbCancel ) dwProgressResult = PROGRESS_CANCEL; else dwProgressResult = lpProgressRoutine( FileSize, BytesTransferred, FileSize, BytesTransferred, 1, CALLBACK_CHUNK_FINISHED, hSourceFile, hTargetFile, lpData ); } } CloseHandle( hTargetFile ); if ( PROGRESS_CANCEL == dwProgressResult ) DeleteFileA( lpNewFileNameA ); } CloseHandle( hSourceFile ); } return fSuccess; }