kernel32/tests: Some tests for CopyFile2().
This commit is contained in:
parent
2785c83b70
commit
33f61eccfa
@ -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 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 HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD);
|
||||||
static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
|
static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
|
||||||
|
static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
|
||||||
|
|
||||||
/* keep filename and filenameW the same */
|
/* keep filename and filenameW the same */
|
||||||
static const char filename[] = "testfile.xxx";
|
static const char filename[] = "testfile.xxx";
|
||||||
@ -80,6 +81,7 @@ static void InitFunctionPointers(void)
|
|||||||
pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
|
pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
|
||||||
pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
|
pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
|
||||||
pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
|
pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
|
||||||
|
pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test__hread( void )
|
static void test__hread( void )
|
||||||
@ -788,6 +790,234 @@ static void test_CopyFileW(void)
|
|||||||
ok(ret, "DeleteFileW: error %d\n", GetLastError());
|
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.
|
* 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
|
static const struct test_data
|
||||||
{
|
{
|
||||||
@ -3591,7 +3821,8 @@ START_TEST(file)
|
|||||||
test_GetTempFileNameA();
|
test_GetTempFileNameA();
|
||||||
test_CopyFileA();
|
test_CopyFileA();
|
||||||
test_CopyFileW();
|
test_CopyFileW();
|
||||||
test_CreatFile();
|
test_CopyFile2();
|
||||||
|
test_CreateFile();
|
||||||
test_CreateFileA();
|
test_CreateFileA();
|
||||||
test_CreateFileW();
|
test_CreateFileW();
|
||||||
test_DeleteFileA();
|
test_DeleteFileA();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user