kernel32: stop CopyFile from overwriting a file with itself (try 2)
Damjan Jovanovic
damjan.jov at gmail.com
Wed Jun 16 05:00:59 CDT 2010
Changelog:
* kernel32: stop CopyFile from overwriting a file with itself
Try 2 compares file handles the unix way.
Damjan Jovanovic
-------------- next part --------------
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-patches
mailing list