[2/2] kernel32: implement callback and cancellation in CopyFileEx
Daniel Jeliński
djelinski1 at gmail.com
Fri Sep 13 18:25:39 CDT 2013
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20130914/cedb561d/attachment-0001.html>
-------------- next part --------------
From 293bf59641b5453dc75986f29308189ca04c7cde Mon Sep 17 00:00:00 2001
From: Daniel Jelinski <djelinski1 at gmail.com>
Date: Sat, 14 Sep 2013 01:03:51 +0200
Subject: kernel32: implement callback and cancellation in CopyFileEx
The implementation would be much better with ReOpenFile implemented:
http://msdn.microsoft.com/en-us/library/aa365497%28VS.85%29.aspx
Even without ReOpenFile it does what it should.
Fixes progress reporting and cancelling of copy operations in Total Commander (bugs 21966, 22690, 22692).
Presumably also fixes bug 29232, if I got Focht right.
I have no idea what dwStreamNumber is for, but 1 seems to work fine for most uses.
---
dlls/kernel32/path.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-
dlls/kernel32/tests/file.c | 7 ++----
2 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index 1728bfa..397a203 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -1075,6 +1075,8 @@ BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
DWORD count;
BOOL ret = FALSE;
char *buffer;
+ LARGE_INTEGER srcSize, dstSize;
+ DWORD progress_result;
if (!source || !dest)
{
@@ -1134,7 +1136,34 @@ BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
CloseHandle( h1 );
return FALSE;
}
-
+ if (progress)
+ {
+ srcSize.u.LowPart = GetFileSize(h1, (DWORD*)&srcSize.u.HighPart);
+ dstSize.u.LowPart = dstSize.u.HighPart = 0;
+ progress_result = progress(srcSize, dstSize, srcSize, dstSize, 1, CALLBACK_STREAM_SWITCH, h1, h2, param);
+ switch (progress_result)
+ {
+ case PROGRESS_QUIET:
+ progress = NULL;
+ break;
+ case PROGRESS_CANCEL:
+ CloseHandle(h2);
+ h2 = CreateFileW(dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ /* fall through */
+ case PROGRESS_STOP:
+ SetLastError(ERROR_REQUEST_ABORTED);
+ goto done;
+ }
+ }
+ if (cancel_ptr && *cancel_ptr)
+ {
+ CloseHandle(h2);
+ h2 = CreateFileW(dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ SetLastError(ERROR_REQUEST_ABORTED);
+ goto done;
+ }
while (ReadFile( h1, buffer, buffer_size, &count, NULL ) && count)
{
char *p = buffer;
@@ -1145,6 +1174,33 @@ BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
p += res;
count -= res;
}
+ if (progress)
+ {
+ dstSize.u.LowPart = GetFileSize(h2, (DWORD*)&dstSize.u.HighPart);
+ progress_result = progress(srcSize, dstSize, srcSize, dstSize, 1, CALLBACK_CHUNK_FINISHED, h1, h2, param);
+ switch (progress_result)
+ {
+ case PROGRESS_QUIET:
+ progress = NULL;
+ break;
+ case PROGRESS_CANCEL:
+ CloseHandle(h2);
+ h2 = CreateFileW(dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ /* fall through */
+ case PROGRESS_STOP:
+ SetLastError(ERROR_REQUEST_ABORTED);
+ goto done;
+ }
+ }
+ if (cancel_ptr && *cancel_ptr)
+ {
+ CloseHandle(h2);
+ h2 = CreateFileW(dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+ SetLastError(ERROR_REQUEST_ABORTED);
+ goto done;
+ }
}
ret = TRUE;
done:
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 625fc3d..d03f527 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -881,11 +881,8 @@ static void test_CopyFileEx(void)
progressInvoked = 0;
SetLastError(0xdeadbeef);
ret = CopyFileExA(source, dest, progress, (LPVOID)i, &cancel, 0);
- if(progress_tests[i].copy_retval)
- ok(ret == progress_tests[i].copy_retval, "CopyFileExA: unexpected result %d in test %d\n", ret, i);
- else
- todo_wine ok(ret == progress_tests[i].copy_retval, "CopyFileExA: unexpected result %d in test %d\n", ret, i);
- todo_wine ok(progressInvoked == progress_tests[i].progress_count, "Unexpected number of progress reports %d in test %d\n", progressInvoked, i);
+ ok(ret == progress_tests[i].copy_retval, "CopyFileExA: unexpected result %d in test %d\n", ret, i);
+ ok(progressInvoked == progress_tests[i].progress_count, "Unexpected number of progress reports %d in test %d\n", progressInvoked, i);
if(!ret)
ok(GetLastError() == progress_tests[i].lastError, "Unexpected error code 0x%08x in test %i\n", GetLastError(), i);
}
--
1.8.1.2
More information about the wine-patches
mailing list