From 33f61eccfa12ef19fbe04e27971d384f15fac68e Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 12 Sep 2013 11:26:25 +0400 Subject: [PATCH] kernel32/tests: Some tests for CopyFile2(). --- dlls/kernel32/tests/file.c | 235 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 233 insertions(+), 2 deletions(-) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index eff6ad1477c..b0de9682558 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -43,6 +43,7 @@ static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD); static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD); static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG); +static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*); /* keep filename and filenameW the same */ static const char filename[] = "testfile.xxx"; @@ -80,6 +81,7 @@ static void InitFunctionPointers(void) pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx"); pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById"); pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData"); + pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2"); } static void test__hread( void ) @@ -788,6 +790,234 @@ static void test_CopyFileW(void) ok(ret, "DeleteFileW: error %d\n", GetLastError()); } +static void test_CopyFile2(void) +{ + static const WCHAR doesntexistW[] = {'d','o','e','s','n','t','e','x','i','s','t',0}; + static const WCHAR prefix[] = {'p','f','x',0}; + WCHAR source[MAX_PATH], dest[MAX_PATH], temp_path[MAX_PATH]; + COPYFILE2_EXTENDED_PARAMETERS params; + HANDLE hfile, hmapfile; + FILETIME ft1, ft2; + DWORD ret, len; + char buf[10]; + HRESULT hr; + + if (!pCopyFile2) + { + skip("CopyFile2 is not available\n"); + return; + } + + ret = GetTempPathW(MAX_PATH, temp_path); + ok(ret != 0, "GetTempPathW error %d\n", GetLastError()); + ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); + + ret = GetTempFileNameW(temp_path, prefix, 0, source); + ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); + + ret = GetTempFileNameW(temp_path, prefix, 0, dest); + ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); + + /* fail if exists */ + memset(¶ms, 0, sizeof(params)); + params.dwSize = sizeof(params); + params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS; + + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError()); + + /* don't fail if exists */ + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == S_OK, "CopyFile2: error 0x%08x\n", hr); + + /* copying a file to itself must fail */ + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, source, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: copying a file to itself didn't fail, 0x%08x\n", hr); + ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); + + /* make the source have not zero size */ + hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 ); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n"); + ret = WriteFile(hfile, prefix, sizeof(prefix), &len, NULL ); + ok(ret && len == sizeof(prefix), "WriteFile error %d\n", GetLastError()); + ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n"); + + /* get the file time and change it to prove the difference */ + ret = GetFileTime(hfile, NULL, NULL, &ft1); + ok(ret, "GetFileTime error %d\n", GetLastError()); + ft1.dwLowDateTime -= 600000000; /* 60 second */ + ret = SetFileTime(hfile, NULL, NULL, &ft1); + ok(ret, "SetFileTime error %d\n", GetLastError()); + GetFileTime(hfile, NULL, NULL, &ft1); /* get the actual time back */ + CloseHandle(hfile); + + ret = GetTempFileNameW(temp_path, prefix, 0, dest); + ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS; + + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + hr = pCopyFile2(source, dest, ¶ms); + ok(ret, "CopyFile2: error 0x%08x\n", hr); + + /* copying from a read-locked source fails */ + hfile = CreateFileW(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); + + /* in addition, the source is opened before the destination */ + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + SetLastError(0xdeadbeef); + hr = pCopyFile2(doesntexistW, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "CopyFile2: last error %d\n", GetLastError()); + CloseHandle(hfile); + + /* copying from a r+w opened, r shared source succeeds */ + hfile = CreateFileW(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == S_OK, "failed 0x%08x\n", hr); + CloseHandle(hfile); + + /* copying from a delete-locked source mostly succeeds */ + hfile = CreateFileW(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == S_OK, "failed 0x%08x\n", hr); + CloseHandle(hfile); + + /* copying to a write-locked destination fails */ + hfile = CreateFileW(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, FALSE); + ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); + CloseHandle(hfile); + + /* copying to a r+w opened, w shared destination mostly succeeds */ + hfile = CreateFileW(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + hr = pCopyFile2(source, dest, FALSE); + ok(hr == S_OK, "got 0x%08x\n", hr); + CloseHandle(hfile); + + /* copying to a delete-locked destination fails, even when the destination is delete-shared */ + hfile = CreateFileW(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); + CloseHandle(hfile); + + /* copy to a file that's opened the way Wine opens the source */ + hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == S_OK, "got 0x%08x\n", hr); + CloseHandle(hfile); + + /* make sure that destination has correct size */ + hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n"); + ret = GetFileSize(hfile, NULL); + ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret); + + /* make sure that destination has the same filetime */ + ret = GetFileTime(hfile, NULL, NULL, &ft2); + ok(ret, "GetFileTime error %d\n", GetLastError()); + ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n"); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); + + /* make sure that destination still has correct size */ + ret = GetFileSize(hfile, NULL); + ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret); + ret = ReadFile(hfile, buf, sizeof(buf), &len, NULL); + ok(ret && len == sizeof(prefix), "ReadFile: error %d\n", GetLastError()); + ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n"); + + /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */ + hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); + ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + SetLastError(0xdeadbeef); + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError()); + + CloseHandle(hmapfile); + CloseHandle(hfile); + + hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n"); + + /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */ + hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); + ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError()); + + params.dwSize = sizeof(params); + params.dwCopyFlags = 0; + hr = pCopyFile2(source, dest, ¶ms); + ok(hr == HRESULT_FROM_WIN32(ERROR_USER_MAPPED_FILE), "CopyFile2: unexpected error 0x%08x\n", hr); + ok(GetLastError() == ERROR_USER_MAPPED_FILE, "CopyFile2: last error %d\n", GetLastError()); + + CloseHandle(hmapfile); + CloseHandle(hfile); + + DeleteFileW(source); + DeleteFileW(dest); +} /* * Debugging routine to dump a buffer in a hexdump-like fashion. @@ -3179,7 +3409,7 @@ static void test_ReplaceFileW(void) } } -static void test_CreatFile(void) +static void test_CreateFile(void) { static const struct test_data { @@ -3591,7 +3821,8 @@ START_TEST(file) test_GetTempFileNameA(); test_CopyFileA(); test_CopyFileW(); - test_CreatFile(); + test_CopyFile2(); + test_CreateFile(); test_CreateFileA(); test_CreateFileW(); test_DeleteFileA(); -- 2.11.4.GIT