1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Test for PrivMoveFileIdentityW 5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org> 6 */ 7 8 #include "precomp.h" 9 10 #include <ndk/iofuncs.h> 11 12 static const WCHAR FileName[] = L"TestFile.xxx"; 13 static const CHAR FileNameA[] = "TestFile.xxx"; 14 static const WCHAR FileName2[] = L"TestFile2.xxx"; 15 16 static BOOL (WINAPI * pPrivMoveFileIdentityW)(LPCWSTR, LPCWSTR, DWORD); 17 18 static 19 BOOL 20 QueryFileInfo( 21 LPCWSTR File, 22 PFILE_BASIC_INFORMATION FileBasicInfo, 23 PFILE_STANDARD_INFORMATION FileStandardInfo) 24 { 25 HANDLE hFile; 26 IO_STATUS_BLOCK IoStatusBlock; 27 NTSTATUS Status; 28 29 hFile = CreateFileW(File, FILE_READ_ATTRIBUTES | SYNCHRONIZE, 30 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 31 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_SYNCHRONOUS_IO_NONALERT, 32 NULL); 33 if (hFile == INVALID_HANDLE_VALUE) 34 { 35 return FALSE; 36 } 37 38 Status = NtQueryInformationFile(hFile, &IoStatusBlock, FileBasicInfo, 39 sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); 40 if (!NT_SUCCESS(Status)) 41 { 42 CloseHandle(hFile); 43 return FALSE; 44 } 45 46 Status = NtQueryInformationFile(hFile, &IoStatusBlock, FileStandardInfo, 47 sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); 48 49 CloseHandle(hFile); 50 return NT_SUCCESS(Status); 51 } 52 53 static 54 VOID 55 TestPrivMoveFileIdentityW(VOID) 56 { 57 FILE_BASIC_INFORMATION FileBasicInfo; 58 FILE_STANDARD_INFORMATION FileStandardInfo; 59 LARGE_INTEGER CreationTime, EndOfFile; 60 HANDLE hDest; 61 WCHAR Self[MAX_PATH]; 62 OFSTRUCT ReOpen; 63 BOOL Ret; 64 65 DeleteFileW(FileName); 66 DeleteFileW(FileName2); 67 68 if (GetModuleFileNameW(NULL, Self, MAX_PATH) == 0) 69 { 70 win_skip("Failed finding self\n"); 71 return; 72 } 73 74 if (!QueryFileInfo(Self, &FileBasicInfo, &FileStandardInfo)) 75 { 76 win_skip("Failed querying self\n"); 77 return; 78 } 79 80 CreationTime = FileBasicInfo.CreationTime; 81 EndOfFile = FileStandardInfo.EndOfFile; 82 83 Sleep(150); 84 85 hDest = CreateFileW(FileName, GENERIC_WRITE | SYNCHRONIZE, 86 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 87 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_SYNCHRONOUS_IO_NONALERT, 88 NULL); 89 if (hDest == INVALID_HANDLE_VALUE) 90 { 91 win_skip("Failed creating new\n"); 92 return; 93 } 94 95 CloseHandle(hDest); 96 97 ok(QueryFileInfo(FileName, &FileBasicInfo, &FileStandardInfo) == TRUE, "QueryFileInfo returned FALSE\n"); 98 ok(FileBasicInfo.CreationTime.QuadPart != CreationTime.QuadPart, "Equal creation times\n"); 99 ok(FileStandardInfo.EndOfFile.QuadPart == 0LL, "File wasn't created empty: %I64d\n", FileStandardInfo.EndOfFile.QuadPart); 100 SetLastError(0xdeadbeef); 101 Ret = pPrivMoveFileIdentityW(Self, FileName, 0); 102 ok(Ret == FALSE, "PrivMoveFileIdentityW succeeded unexpectedly\n"); 103 ok(GetLastError() == ERROR_SHARING_VIOLATION, "Last error: %#lx\n", GetLastError()); 104 ok(QueryFileInfo(FileName, &FileBasicInfo, &FileStandardInfo) == TRUE, "QueryFileInfo returned FALSE\n"); 105 ok(FileBasicInfo.CreationTime.QuadPart != CreationTime.QuadPart, "Equal creation times\n"); 106 ok(FileStandardInfo.EndOfFile.QuadPart == 0LL, "File wasn't created empty: %I64d\n", FileStandardInfo.EndOfFile.QuadPart); 107 SetLastError(0xdeadbeef); 108 Ret = pPrivMoveFileIdentityW(Self, FileName, 2); 109 ok(Ret == TRUE, "PrivMoveFileIdentityW failed with %#lx\n", GetLastError()); 110 ok(QueryFileInfo(FileName, &FileBasicInfo, &FileStandardInfo) == TRUE, "QueryFileInfo returned FALSE\n"); 111 ok(FileBasicInfo.CreationTime.QuadPart == CreationTime.QuadPart, "Creation time didn't change\n"); 112 ok(FileStandardInfo.EndOfFile.QuadPart == 0LL, "File not empty anymore: %I64d\n", FileStandardInfo.EndOfFile.QuadPart); 113 ok(QueryFileInfo(Self, &FileBasicInfo, &FileStandardInfo) == TRUE, "QueryFileInfo returned FALSE\n"); 114 ok(FileBasicInfo.CreationTime.QuadPart == CreationTime.QuadPart, "Creation time changed\n"); 115 ok(FileStandardInfo.EndOfFile.QuadPart == EndOfFile.QuadPart, "File size changed: %I64d\n", FileStandardInfo.EndOfFile.QuadPart); 116 117 hDest = CreateFileW(FileName2, GENERIC_WRITE | SYNCHRONIZE, 118 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 119 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_SYNCHRONOUS_IO_NONALERT, 120 NULL); 121 if (hDest == INVALID_HANDLE_VALUE) 122 { 123 win_skip("Failed creating new\n"); 124 return; 125 } 126 127 CloseHandle(hDest); 128 129 ok(QueryFileInfo(FileName2, &FileBasicInfo, &FileStandardInfo) == TRUE, "QueryFileInfo returned FALSE\n"); 130 ok(FileBasicInfo.CreationTime.QuadPart != CreationTime.QuadPart, "Equal creation times\n"); 131 SetLastError(0xdeadbeef); 132 Ret = pPrivMoveFileIdentityW(FileName, FileName2, 3); 133 ok(Ret == TRUE, "PrivMoveFileIdentityW failed with %#lx\n", GetLastError()); 134 ok(QueryFileInfo(FileName2, &FileBasicInfo, &FileStandardInfo) == TRUE, "QueryFileInfo returned FALSE\n"); 135 ok(FileBasicInfo.CreationTime.QuadPart == CreationTime.QuadPart, "Creation time didn't change\n"); 136 ok(OpenFile(FileNameA, &ReOpen, OF_EXIST) == HFILE_ERROR, "Source file still exists\n"); 137 138 DeleteFileW(FileName2); 139 DeleteFileW(FileName); 140 } 141 142 START_TEST(PrivMoveFileIdentityW) 143 { 144 HMODULE hKern = GetModuleHandleA("kernel32.dll"); 145 pPrivMoveFileIdentityW = (void *)GetProcAddress(hKern, "PrivMoveFileIdentityW"); 146 147 TestPrivMoveFileIdentityW(); 148 } 149