[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