--- dlls/kernelbase/file.c | 44 +++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 26 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index e0a75c2ad08..798fb567333 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -497,24 +497,22 @@ BOOL WINAPI DECLSPEC_HOTPATCH AreFileApisANSI(void) BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUTINE progress, void *param, BOOL *cancel_ptr, DWORD flags ) { - static const int buffer_size = 65536; HANDLE h1, h2; FILE_BASIC_INFORMATION info; IO_STATUS_BLOCK io; DWORD count; BOOL ret = FALSE; - char *buffer; + SRV_COPYCHUNK_COPY copychunk = { + .ChunkCount = 1, + .Chunk = { [0] = { .Length = 1UL<<30 } } + }; + SRV_COPYCHUNK_RESPONSE copychunk_resp;
if (!source || !dest) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size ))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - }
TRACE("%s -> %s, %x\n", debugstr_w(source), debugstr_w(dest), flags);
@@ -522,14 +520,12 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE) { WARN("Unable to open source %s\n", debugstr_w(source)); - HeapFree( GetProcessHeap(), 0, buffer ); return FALSE; }
if (!set_ntstatus( NtQueryInformationFile( h1, &io, &info, sizeof(info), FileBasicInformation ))) { WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source)); - HeapFree( GetProcessHeap(), 0, buffer ); CloseHandle( h1 ); return FALSE; } @@ -545,7 +541,6 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT } if (same_file) { - HeapFree( GetProcessHeap(), 0, buffer ); CloseHandle( h1 ); SetLastError( ERROR_SHARING_VIOLATION ); return FALSE; @@ -557,28 +552,25 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT info.FileAttributes, h1 )) == INVALID_HANDLE_VALUE) { WARN("Unable to open dest %s\n", debugstr_w(dest)); - HeapFree( GetProcessHeap(), 0, buffer ); CloseHandle( h1 ); return FALSE; }
- while (ReadFile( h1, buffer, buffer_size, &count, NULL ) && count) + /* wine extension: IOCTL_COPYCHUNK works even on local files */ + ret = DeviceIoControl( h1, IOCTL_PREPARE_COPYCHUNK, NULL, 0, + ©chunk.SourceFile, sizeof(copychunk.SourceFile), &count, NULL ); + if (ret) { - char *p = buffer; - while (count != 0) - { - DWORD res; - if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done; - p += res; - count -= res; - } + do { + ret = DeviceIoControl( h2, IOCTL_COPYCHUNK, ©chunk, sizeof(copychunk), + ©chunk_resp, sizeof(copychunk_resp), &count, NULL ); + copychunk.Chunk[0].SourceOffset.QuadPart += copychunk_resp.TotalBytesWritten; + copychunk.Chunk[0].DestinationOffset.QuadPart += copychunk_resp.TotalBytesWritten; + } while (ret && copychunk_resp.TotalBytesWritten); + /* Maintain the timestamp of source file to destination file */ + info.FileAttributes = 0; + NtSetInformationFile( h2, &io, &info, sizeof(info), FileBasicInformation ); } - ret = TRUE; -done: - /* Maintain the timestamp of source file to destination file */ - info.FileAttributes = 0; - NtSetInformationFile( h2, &io, &info, sizeof(info), FileBasicInformation ); - HeapFree( GetProcessHeap(), 0, buffer ); CloseHandle( h1 ); CloseHandle( h2 ); return ret;