Module: wine Branch: master Commit: 06de0195d0ac02aabd03beaaffb29cb5b438791e URL: http://source.winehq.org/git/wine.git/?a=commit;h=06de0195d0ac02aabd03beaaff...
Author: Damjan Jovanovic damjan.jov@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 */