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