kernel32: stop CopyFile from overwriting a file with itself

Damjan Jovanovic damjan.jov at gmail.com
Tue Jun 15 23:02:55 CDT 2010


Changelog:
* kernel32: stop CopyFile from overwriting a file with itself

Damjan Jovanovic
-------------- next part --------------
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index c319cb5..db12515 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -911,6 +911,34 @@ BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists )
         return FALSE;
     }
 
+    if (!fail_if_exists)
+    {
+        BOOL dest_exists = FALSE;
+        h2 = CreateFileW( dest, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                         OPEN_EXISTING, 0, 0);
+        if (h2 != INVALID_HANDLE_VALUE)
+        {
+            BY_HANDLE_FILE_INFORMATION info2;
+            if (GetFileInformationByHandle( h2, &info2 ))
+            {
+                if (info.dwVolumeSerialNumber == info2.dwVolumeSerialNumber &&
+                    info.nFileIndexLow == info2.nFileIndexLow &&
+                    info.nFileIndexHigh == info2.nFileIndexHigh)
+                {
+                    dest_exists = TRUE;
+                }
+            }
+            CloseHandle( h2 );
+        }
+        if (dest_exists)
+        {
+            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-patches mailing list