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