Reactos
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
12static const WCHAR FileName[] = L"TestFile.xxx";
13static const CHAR FileNameA[] = "TestFile.xxx";
14static const WCHAR FileName2[] = L"TestFile2.xxx";
15
16static BOOL (WINAPI * pPrivMoveFileIdentityW)(LPCWSTR, LPCWSTR, DWORD);
17
18static
19BOOL
20QueryFileInfo(
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
53static
54VOID
55TestPrivMoveFileIdentityW(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
142START_TEST(PrivMoveFileIdentityW)
143{
144 HMODULE hKern = GetModuleHandleA("kernel32.dll");
145 pPrivMoveFileIdentityW = (void *)GetProcAddress(hKern, "PrivMoveFileIdentityW");
146
147 TestPrivMoveFileIdentityW();
148}