Damjan Jovanovic : kernel32: Stop CopyFile from overwriting a file with itself.

Alexandre Julliard julliard at winehq.org
Wed Jun 16 13:23:21 CDT 2010


Module: wine
Branch: master
Commit: 06de0195d0ac02aabd03beaaffb29cb5b438791e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=06de0195d0ac02aabd03beaaffb29cb5b438791e

Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date:   Wed Jun 16 12:00:59 2010 +0200

kernel32: Stop CopyFile from overwriting a file with itself.

---

 dlls/kernel32/path.c       |   37 +++++++++++++++++++++++++++++++++++++
 dlls/kernel32/tests/file.c |    2 +-
 2 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index c319cb5..f0da96c 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -869,6 +869,24 @@ DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
     return ret;
 }
 
+static BOOL is_same_file(HANDLE h1, HANDLE h2)
+{
+    int fd1;
+    BOOL ret = FALSE;
+    if (wine_server_handle_to_fd(h1, 0, &fd1, NULL) == STATUS_SUCCESS)
+    {
+        int fd2;
+        if (wine_server_handle_to_fd(h2, 0, &fd2, NULL) == STATUS_SUCCESS)
+        {
+            struct stat stat1, stat2;
+            if (fstat(fd1, &stat1) == 0 && fstat(fd2, &stat2) == 0)
+                ret = (stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino);
+            wine_server_release_fd(h2, fd2);
+        }
+        wine_server_release_fd(h1, fd1);
+    }
+    return ret;
+}
 
 /**************************************************************************
  *           CopyFileW   (KERNEL32.@)
@@ -911,6 +929,25 @@ BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists )
         return FALSE;
     }
 
+    if (!fail_if_exists)
+    {
+        BOOL same_file = FALSE;
+        h2 = CreateFileW( dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                         OPEN_EXISTING, 0, 0);
+        if (h2 != INVALID_HANDLE_VALUE)
+        {
+            same_file = is_same_file( h1, h2 );
+            CloseHandle( h2 );
+        }
+        if (same_file)
+        {
+            HeapFree( GetProcessHeap(), 0, buffer );
+            CloseHandle( h1 );
+            SetLastError( ERROR_SHARING_VIOLATION );
+            return FALSE;
+        }
+    }
+
     if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                              fail_if_exists ? CREATE_NEW : CREATE_ALWAYS,
                              info.dwFileAttributes, h1 )) == INVALID_HANDLE_VALUE)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 7e6b3de..c0a36c7 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -593,7 +593,7 @@ static void test_CopyFileA(void)
 
     /* copying a file to itself must fail */
     retok = CopyFileA(source, source, FALSE);
-    todo_wine ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */),
+    ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */),
         "copying a file to itself didn't fail (ret=%d, err=%d)\n", retok, GetLastError());
 
     /* make the source have not zero size */




More information about the wine-cvs mailing list