1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for RtlDoesFileExists_U*
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 #define ok_bool_file(value, expected, file) do {                                \
11         if (expected)                                                           \
12             ok(value == TRUE, "File '%ls' should exist, but does not\n", file); \
13         else                                                                    \
14             ok(value == FALSE, "File '%ls' should not exist, but does\n", file);\
15     } while (0)
16 
17 #define ok_eq_ustr(str1, str2) do {                                                     \
18         ok((str1)->Buffer        == (str2)->Buffer,        "Buffer modified\n");        \
19         ok((str1)->Length        == (str2)->Length,        "Length modified\n");        \
20         ok((str1)->MaximumLength == (str2)->MaximumLength, "MaximumLength modified\n"); \
21     } while (0)
22 
23 /*
24 BOOLEAN
25 NTAPI
26 RtlDoesFileExists_U(
27     IN PCWSTR FileName
28 );
29 
30 BOOLEAN
31 NTAPI
32 RtlDoesFileExists_UEx(
33     IN PCWSTR FileName,
34     IN BOOLEAN SucceedIfBusy
35 );
36 
37 BOOLEAN
38 NTAPI
39 RtlDoesFileExists_UStr(
40     IN PUNICODE_STRING FileName
41 );
42 
43 BOOLEAN
44 NTAPI
45 RtlDoesFileExists_UstrEx(
46         IN PCUNICODE_STRING FileName,
47         IN BOOLEAN SucceedIfBusy
48 );
49 */
50 
51 static
52 BOOLEAN
53 (NTAPI
54 *RtlDoesFileExists_UEx)(
55     IN PCWSTR FileName,
56     IN BOOLEAN SucceedIfBusy
57 )
58 //= (PVOID)0x7c8187d0 // 2003 sp1 x86
59 //= (PVOID)0x7769aeb2 // win7 sp1 wow64
60 ;
61 
62 static
63 BOOLEAN
64 (NTAPI
65 *RtlDoesFileExists_UStr)(
66     IN PUNICODE_STRING FileName
67 )
68 //= (PVOID)0x7c8474e5 // 2003 sp1 x86
69 //= (PVOID)0x776ff304 // win7 sp1 wow64
70 ;
71 
72 static
73 BOOLEAN
74 (NTAPI
75 *RtlDoesFileExists_UstrEx)(
76         IN PCUNICODE_STRING FileName,
77         IN BOOLEAN SucceedIfBusy
78 )
79 //= (PVOID)0x7c830f89 // 2003 sp1 x86
80 //= (PVOID)0x7769addb // win7 sp1 wow64
81 ;
82 
83 START_TEST(RtlDoesFileExists)
84 {
85     BOOLEAN Ret;
86     struct
87     {
88         PCWSTR FileName;
89         BOOLEAN Exists;
90     } Tests[] =
91     {
92         { L"",                                          FALSE },
93         { L"?",                                         FALSE },
94         { L"*",                                         FALSE },
95         { L":",                                         FALSE },
96         { L";",                                         FALSE },
97         { L"\"",                                        FALSE },
98         { L".",                                         TRUE },
99         { L"..",                                        TRUE },
100         { L"/",                                         TRUE },
101         { L"//",                                        FALSE },
102         { L"///",                                       FALSE },
103         { L"\\/",                                       FALSE },
104         { L"\\//",                                      FALSE },
105         { L"\\\\/",                                     FALSE },
106         { L"\\/\\",                                     FALSE },
107         { L"\\/\\\\",                                   FALSE },
108         { L"\\/\\/\\",                                  FALSE },
109         { L"\\",                                        TRUE },
110         { L"\\\\",                                      FALSE },
111         { L"\\\\\\",                                    FALSE },
112         { L"\\\\.",                                     FALSE },
113         { L"\\\\.\\",                                   FALSE },
114         { L"\\\\.\\GLOBAL??",                           FALSE },
115         { L"\\\\.\\GLOBAL??\\",                         FALSE },
116         { L"\\\\?",                                     FALSE },
117         { L"\\\\??",                                    FALSE },
118         { L"\\\\??\\",                                  FALSE },
119         { L"\\\\??\\C:\\",                              FALSE },
120         { L"\\\\.",                                     FALSE },
121         { L"\\\\.\\",                                   FALSE },
122         { L"C:",                                        TRUE },
123         { L"C:/",                                       TRUE },
124         { L"C:/\\",                                     TRUE },
125         { L"C:\\/",                                     TRUE },
126         { L"C:\\/\\",                                   TRUE },
127         { L"C://",                                      TRUE },
128         { L"C:\\",                                      TRUE },
129         { L"C:\\\\",                                    TRUE },
130         { L"C:\\%ls",                                   TRUE },
131         { L"C:/%ls",                                    TRUE },
132         { L"C://%ls",                                   TRUE },
133         { L"C:\\/%ls",                                  TRUE },
134         { L"C:/\\%ls",                                  TRUE },
135         { L"C:\\/\\%ls",                                TRUE },
136         { L"C:\\%ls\\",                                 TRUE },
137         { L"C:\\%ls\\ThisFolderExists",                 TRUE },
138         { L"C:\\%ls\\ThisFolderExists\\",               TRUE },
139         { L"C:\\%ls\\ThisFolderExists ",                TRUE },
140         { L"C:\\%ls\\ThisFolderExists  ",               TRUE },
141         { L"C:\\%ls\\ThisFolderExists   ",              TRUE },
142         { L"C:\\%ls\\ThisFolderExists:",                FALSE },
143         { L"C:\\%ls\\ThisFolderExists\t",               FALSE },
144         { L"C:\\%ls\\ThisFolderExists\n",               FALSE },
145         { L"C:\\%ls\\ThisFolderExists\r",               FALSE },
146         { L" C:\\%ls\\ThisFolderExists",                FALSE },
147         { L"C:\\%ls\\ ThisFolderExists",                FALSE },
148         { L"C:\\%ls \\ThisFolderExists",                FALSE },
149         { L"C:\\%ls\\ThisDoesntExist",                  FALSE },
150         { L"C:\\\\%ls\\\\ThisFolderExists",             TRUE },
151         { L"C:\\%ls\\ThisFolderExists\\ThisFileExists", TRUE },
152         { L"c:\\%ls\\thisfolderexists\\thisfileexists", TRUE },
153         { L"C:\\%ls\\THISFOLDEREXISTS\\THISFILEEXISTS", TRUE },
154         { L"C:\\%ls\\ThisFolderExists\\SomeProgram.exe",TRUE },
155         { L"C:\\%ls\\ThisFolderExists\\SomeProgram",    FALSE },
156         { L"C:\\%ls\\ThisFolderExists\\With",           FALSE },
157         { L"C:\\%ls\\ThisFolderExists\\With Space",     TRUE },
158         { L"C:\\%ls\\ThisFolderExists\\Without",        TRUE },
159         { L"C:\\%ls\\ThisFolderExists\\Without Space",  FALSE },
160         { L"C:\\%ls abc",                               FALSE },
161         { L"\"C:\\%ls\" abc",                           FALSE },
162         { L"\"C:\\\"",                                  FALSE },
163         { L"C:\\%ls;C:\\",                              FALSE },
164         { L"%%SystemRoot%%",                            FALSE },
165         { L"%%SystemRoot%%\\",                          FALSE },
166         { L"%%SystemRoot%%\\system32",                  FALSE },
167         { L"NUL",                                       FALSE },
168         { L"CON",                                       FALSE },
169         { L"COM1",                                      FALSE },
170         { L"\\?",                                       FALSE },
171         { L"\\??",                                      FALSE },
172         { L"\\??\\",                                    FALSE },
173         { L"\\??\\C",                                   FALSE },
174         { L"\\??\\C:",                                  FALSE },
175         { L"\\??\\C:\\",                                FALSE }, // TRUE on Win7
176         { L"\\??\\C:\\%ls\\ThisFolderExists",           FALSE }, // TRUE on Win7
177     };
178     ULONG i;
179     WCHAR FileName[MAX_PATH];
180     WCHAR CustomPath[MAX_PATH] = L"RtlDoesFileExists_U_TestPath";
181     BOOL Success;
182     HANDLE Handle;
183 
184     if (!RtlDoesFileExists_UEx)
185     {
186         RtlDoesFileExists_UEx = (PVOID)GetProcAddress(GetModuleHandleW(L"ntdll"), "RtlDoesFileExists_UEx");
187         if (!RtlDoesFileExists_UEx)
188             skip("RtlDoesFileExists_UEx unavailable\n");
189     }
190 
191     if (!RtlDoesFileExists_UStr)
192     {
193         RtlDoesFileExists_UStr = (PVOID)GetProcAddress(GetModuleHandleW(L"ntdll"), "RtlDoesFileExists_UStr");
194         if (!RtlDoesFileExists_UStr)
195             skip("RtlDoesFileExists_UStr unavailable\n");
196     }
197 
198     if (!RtlDoesFileExists_UstrEx)
199     {
200         RtlDoesFileExists_UstrEx = (PVOID)GetProcAddress(GetModuleHandleW(L"ntdll"), "RtlDoesFileExists_UstrEx");
201         if (!RtlDoesFileExists_UstrEx)
202             skip("RtlDoesFileExists_UstrEx unavailable\n");
203     }
204 
205     StartSeh()
206         Ret = RtlDoesFileExists_U(NULL);
207         ok(Ret == FALSE, "NULL file exists?!\n");
208     EndSeh(STATUS_SUCCESS);
209 
210     if (RtlDoesFileExists_UEx)
211     {
212         StartSeh()
213             Ret = RtlDoesFileExists_UEx(NULL, TRUE);
214             ok(Ret == FALSE, "NULL file exists?!\n");
215             Ret = RtlDoesFileExists_UEx(NULL, FALSE);
216             ok(Ret == FALSE, "NULL file exists?!\n");
217         EndSeh(STATUS_SUCCESS);
218     }
219 
220     if (RtlDoesFileExists_UStr)
221     {
222         StartSeh() Ret = RtlDoesFileExists_UStr(NULL);      EndSeh(STATUS_ACCESS_VIOLATION);
223     }
224 
225     if (RtlDoesFileExists_UstrEx)
226     {
227         StartSeh() RtlDoesFileExists_UstrEx(NULL, FALSE);   EndSeh(STATUS_ACCESS_VIOLATION);
228         StartSeh() RtlDoesFileExists_UstrEx(NULL, TRUE);    EndSeh(STATUS_ACCESS_VIOLATION);
229     }
230 
231     swprintf(FileName, L"C:\\%ls", CustomPath);
232     /* Make sure this directory doesn't exist */
233     while (GetFileAttributesW(FileName) != INVALID_FILE_ATTRIBUTES)
234     {
235         wcscat(CustomPath, L"X");
236         swprintf(FileName, L"C:\\%ls", CustomPath);
237     }
238     Success = CreateDirectoryW(FileName, NULL);
239     ok(Success, "CreateDirectory failed, results might not be accurate\n");
240     swprintf(FileName, L"C:\\%ls\\ThisFolderExists", CustomPath);
241     Success = CreateDirectoryW(FileName, NULL);
242     ok(Success, "CreateDirectory failed, results might not be accurate\n");
243     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\ThisFileExists", CustomPath);
244     Handle = CreateFileW(FileName, 0, 0, NULL, CREATE_NEW, 0, NULL);
245     ok(Handle != INVALID_HANDLE_VALUE, "CreateFile failed, results might not be accurate\n");
246     if (Handle != INVALID_HANDLE_VALUE)
247     {
248         /* Check SucceedIfBusy behavior */
249         if (RtlDoesFileExists_UEx)
250         {
251             Ret = RtlDoesFileExists_UEx(FileName, TRUE);
252             ok_bool_file(Ret, TRUE, FileName);
253             /* TODO: apparently we have to do something worse to make this fail */
254             Ret = RtlDoesFileExists_UEx(FileName, FALSE);
255             ok_bool_file(Ret, TRUE, FileName);
256         }
257         if (RtlDoesFileExists_UstrEx)
258         {
259             UNICODE_STRING FileNameString;
260             UNICODE_STRING TempString;
261             RtlInitUnicodeString(&FileNameString, FileName);
262             TempString = FileNameString;
263             Ret = RtlDoesFileExists_UstrEx(&FileNameString, TRUE);
264             ok_eq_ustr(&FileNameString, &TempString);
265             ok_bool_file(Ret, TRUE, FileName);
266             /* TODO: apparently we have to do something worse to make this fail */
267             Ret = RtlDoesFileExists_UstrEx(&FileNameString, FALSE);
268             ok_eq_ustr(&FileNameString, &TempString);
269             ok_bool_file(Ret, TRUE, FileName);
270         }
271         CloseHandle(Handle);
272     }
273 
274     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\SomeProgram.exe", CustomPath);
275     Handle = CreateFileW(FileName, 0, 0, NULL, CREATE_NEW, 0, NULL);
276     ok(Handle != INVALID_HANDLE_VALUE, "CreateFile failed, results might not be accurate\n");
277     if (Handle != INVALID_HANDLE_VALUE) CloseHandle(Handle);
278 
279     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\With Space", CustomPath);
280     Handle = CreateFileW(FileName, 0, 0, NULL, CREATE_NEW, 0, NULL);
281     ok(Handle != INVALID_HANDLE_VALUE, "CreateFile failed, results might not be accurate\n");
282     if (Handle != INVALID_HANDLE_VALUE) CloseHandle(Handle);
283 
284     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\Without", CustomPath);
285     Handle = CreateFileW(FileName, 0, 0, NULL, CREATE_NEW, 0, NULL);
286     ok(Handle != INVALID_HANDLE_VALUE, "CreateFile failed, results might not be accurate\n");
287     if (Handle != INVALID_HANDLE_VALUE) CloseHandle(Handle);
288 
289     for (i = 0; i < sizeof(Tests) / sizeof(Tests[0]); i++)
290     {
291         swprintf(FileName, Tests[i].FileName, CustomPath);
292         StartSeh()
293             Ret = RtlDoesFileExists_U(FileName);
294             ok_bool_file(Ret, Tests[i].Exists, FileName);
295         EndSeh(STATUS_SUCCESS);
296         if (RtlDoesFileExists_UEx)
297         {
298             StartSeh()
299                 Ret = RtlDoesFileExists_UEx(FileName, TRUE);
300                 ok_bool_file(Ret, Tests[i].Exists, FileName);
301             EndSeh(STATUS_SUCCESS);
302             StartSeh()
303                 Ret = RtlDoesFileExists_UEx(FileName, FALSE);
304                 ok_bool_file(Ret, Tests[i].Exists, FileName);
305             EndSeh(STATUS_SUCCESS);
306         }
307         /* TODO: use guarded memory to make sure these don't touch the null terminator */
308         if (RtlDoesFileExists_UStr)
309         {
310             UNICODE_STRING FileNameString;
311             UNICODE_STRING TempString;
312             RtlInitUnicodeString(&FileNameString, FileName);
313             TempString = FileNameString;
314             StartSeh()
315                 Ret = RtlDoesFileExists_UStr(&FileNameString);
316                 ok_bool_file(Ret, Tests[i].Exists, FileName);
317             EndSeh(STATUS_SUCCESS);
318             ok_eq_ustr(&FileNameString, &TempString);
319         }
320         if (RtlDoesFileExists_UstrEx)
321         {
322             UNICODE_STRING FileNameString;
323             UNICODE_STRING TempString;
324             RtlInitUnicodeString(&FileNameString, FileName);
325             TempString = FileNameString;
326             StartSeh()
327                 Ret = RtlDoesFileExists_UstrEx(&FileNameString, TRUE);
328                 ok_bool_file(Ret, Tests[i].Exists, FileName);
329             EndSeh(STATUS_SUCCESS);
330             ok_eq_ustr(&FileNameString, &TempString);
331             StartSeh()
332                 Ret = RtlDoesFileExists_UstrEx(&FileNameString, FALSE);
333                 ok_bool_file(Ret, Tests[i].Exists, FileName);
334             EndSeh(STATUS_SUCCESS);
335             ok_eq_ustr(&FileNameString, &TempString);
336         }
337     }
338 
339     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\Without", CustomPath);
340     Success = DeleteFileW(FileName);
341     ok(Success, "DeleteFile failed (%lu), test might leave stale file\n", GetLastError());
342     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\With Space", CustomPath);
343     Success = DeleteFileW(FileName);
344     ok(Success, "DeleteFile failed (%lu), test might leave stale file\n", GetLastError());
345     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\SomeProgram.exe", CustomPath);
346     Success = DeleteFileW(FileName);
347     ok(Success, "DeleteFile failed (%lu), test might leave stale file\n", GetLastError());
348 
349     swprintf(FileName, L"C:\\%ls\\ThisFolderExists\\ThisFileExists", CustomPath);
350     Success = DeleteFileW(FileName);
351     ok(Success, "DeleteFile failed (%lu), test might leave stale file\n", GetLastError());
352     swprintf(FileName, L"C:\\%ls\\ThisFolderExists", CustomPath);
353     Success = RemoveDirectoryW(FileName);
354     ok(Success, "RemoveDirectory failed (%lu), test might leave stale directory\n", GetLastError());
355     swprintf(FileName, L"C:\\%ls", CustomPath);
356     Success = RemoveDirectoryW(FileName);
357     ok(Success, "RemoveDirectory failed (%lu), test might leave stale directory\n", GetLastError());
358 }
359