1 /*
2  * Unit test suite for directory functions.
3  *
4  * Copyright 2002 Dmitry Timoshkov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winternl.h"
28 
29 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
30 
31 static void init(void)
32 {
33     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
34     pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
35 }
36 
37 #define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,__LINE__)
38 static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
39 {
40     OBJECT_BASIC_INFORMATION obj_info;
41     NTSTATUS status;
42 
43     status = pNtQueryObject(handle, ObjectBasicInformation, &obj_info,
44                             sizeof(obj_info), NULL);
45     ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
46     ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
47         "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
48 }
49 
50 /* If you change something in these tests, please do the same
51  * for GetSystemDirectory tests.
52  */
53 static void test_GetWindowsDirectoryA(void)
54 {
55     UINT len, len_with_null;
56     char buf[MAX_PATH];
57 
58     len_with_null = GetWindowsDirectoryA(NULL, 0);
59     ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
60 
61     lstrcpyA(buf, "foo");
62     len_with_null = GetWindowsDirectoryA(buf, 1);
63     ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
64 
65     lstrcpyA(buf, "foo");
66     len = GetWindowsDirectoryA(buf, len_with_null - 1);
67     ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
68     ok(len == len_with_null, "GetWindowsDirectoryW returned %d, expected %d\n",
69        len, len_with_null);
70 
71     lstrcpyA(buf, "foo");
72     len = GetWindowsDirectoryA(buf, len_with_null);
73     ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer\n");
74     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
75     ok(len == len_with_null-1, "GetWindowsDirectoryA returned %d, expected %d\n",
76        len, len_with_null-1);
77 }
78 
79 static void test_GetWindowsDirectoryW(void)
80 {
81     UINT len, len_with_null;
82     WCHAR buf[MAX_PATH];
83     static const WCHAR fooW[] = {'f','o','o',0};
84 
85     len_with_null = GetWindowsDirectoryW(NULL, 0);
86     if (len_with_null == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
87     {
88         win_skip("GetWindowsDirectoryW is not implemented\n");
89         return;
90     }
91     ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
92 
93     lstrcpyW(buf, fooW);
94     len = GetWindowsDirectoryW(buf, 1);
95     ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
96     ok(len == len_with_null, "GetWindowsDirectoryW returned %d, expected %d\n",
97        len, len_with_null);
98 
99     lstrcpyW(buf, fooW);
100     len = GetWindowsDirectoryW(buf, len_with_null - 1);
101     ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
102     ok(len == len_with_null, "GetWindowsDirectoryW returned %d, expected %d\n",
103        len, len_with_null);
104 
105     lstrcpyW(buf, fooW);
106     len = GetWindowsDirectoryW(buf, len_with_null);
107     ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer\n");
108     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
109     ok(len == len_with_null-1, "GetWindowsDirectoryW returned %d, expected %d\n",
110        len, len_with_null-1);
111 }
112 
113 
114 /* If you change something in these tests, please do the same
115  * for GetWindowsDirectory tests.
116  */
117 static void test_GetSystemDirectoryA(void)
118 {
119     UINT len, len_with_null;
120     char buf[MAX_PATH];
121 
122     len_with_null = GetSystemDirectoryA(NULL, 0);
123     ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
124 
125     lstrcpyA(buf, "foo");
126     len = GetSystemDirectoryA(buf, 1);
127     ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
128     ok(len == len_with_null, "GetSystemDirectoryA returned %d, expected %d\n",
129        len, len_with_null);
130 
131     lstrcpyA(buf, "foo");
132     len = GetSystemDirectoryA(buf, len_with_null - 1);
133     ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
134     ok(len == len_with_null, "GetSystemDirectoryA returned %d, expected %d\n",
135        len, len_with_null);
136 
137     lstrcpyA(buf, "foo");
138     len = GetSystemDirectoryA(buf, len_with_null);
139     ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer\n");
140     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
141     ok(len == len_with_null-1, "GetSystemDirectoryW returned %d, expected %d\n",
142        len, len_with_null-1);
143 }
144 
145 static void test_GetSystemDirectoryW(void)
146 {
147     UINT len, len_with_null;
148     WCHAR buf[MAX_PATH];
149     static const WCHAR fooW[] = {'f','o','o',0};
150 
151     len_with_null = GetSystemDirectoryW(NULL, 0);
152     if (len_with_null == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
153     {
154         win_skip("GetSystemDirectoryW is not available\n");
155         return;
156     }
157     ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
158 
159     lstrcpyW(buf, fooW);
160     len = GetSystemDirectoryW(buf, 1);
161     ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
162     ok(len == len_with_null, "GetSystemDirectoryW returned %d, expected %d\n",
163        len, len_with_null);
164 
165     lstrcpyW(buf, fooW);
166     len = GetSystemDirectoryW(buf, len_with_null - 1);
167     ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
168     ok(len == len_with_null, "GetSystemDirectoryW returned %d, expected %d\n",
169        len, len_with_null);
170 
171     lstrcpyW(buf, fooW);
172     len = GetSystemDirectoryW(buf, len_with_null);
173     ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer\n");
174     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
175     ok(len == len_with_null-1, "GetSystemDirectoryW returned %d, expected %d\n",
176        len, len_with_null-1);
177 }
178 
179 static void test_CreateDirectoryA(void)
180 {
181     char tmpdir[MAX_PATH];
182     WCHAR curdir[MAX_PATH];
183     BOOL ret;
184 
185     ret = CreateDirectoryA(NULL, NULL);
186     ok(ret == FALSE && (GetLastError() == ERROR_PATH_NOT_FOUND ||
187                         GetLastError() == ERROR_INVALID_PARAMETER),
188        "CreateDirectoryA(NULL): ret=%d err=%d\n", ret, GetLastError());
189 
190     ret = CreateDirectoryA("", NULL);
191     ok(ret == FALSE && (GetLastError() == ERROR_BAD_PATHNAME ||
192                         GetLastError() == ERROR_PATH_NOT_FOUND),
193        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
194 
195     ret = GetSystemDirectoryA(tmpdir, MAX_PATH);
196     ok(ret < MAX_PATH, "System directory should fit into MAX_PATH\n");
197 
198     GetCurrentDirectoryW(MAX_PATH, curdir);
199     ret = SetCurrentDirectoryA(tmpdir);
200     ok(ret == TRUE, "could not chdir to the System directory\n");
201 
202     ret = CreateDirectoryA(".", NULL);
203     ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
204        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
205 
206 
207     ret = CreateDirectoryA("..", NULL);
208     ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
209        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
210 
211     GetTempPathA(MAX_PATH, tmpdir);
212     tmpdir[3] = 0; /* truncate the path */
213     ret = CreateDirectoryA(tmpdir, NULL);
214     ok(ret == FALSE && (GetLastError() == ERROR_ALREADY_EXISTS ||
215                         GetLastError() == ERROR_ACCESS_DENIED),
216        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
217 
218     GetTempPathA(MAX_PATH, tmpdir);
219     lstrcatA(tmpdir, "Please Remove Me");
220     ret = CreateDirectoryA(tmpdir, NULL);
221     ok(ret == TRUE,       "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
222 
223     ret = CreateDirectoryA(tmpdir, NULL);
224     ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
225        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
226 
227     ret = RemoveDirectoryA(tmpdir);
228     ok(ret == TRUE,
229        "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
230 
231 
232     lstrcatA(tmpdir, "?");
233     ret = CreateDirectoryA(tmpdir, NULL);
234     ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
235 			GetLastError() == ERROR_PATH_NOT_FOUND),
236        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
237     RemoveDirectoryA(tmpdir);
238 
239     tmpdir[lstrlenA(tmpdir) - 1] = '*';
240     ret = CreateDirectoryA(tmpdir, NULL);
241     ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
242 			GetLastError() == ERROR_PATH_NOT_FOUND),
243        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
244     RemoveDirectoryA(tmpdir);
245 
246     GetTempPathA(MAX_PATH, tmpdir);
247     lstrcatA(tmpdir, "Please Remove Me/Please Remove Me");
248     ret = CreateDirectoryA(tmpdir, NULL);
249     ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND,
250        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
251     RemoveDirectoryA(tmpdir);
252 
253     /* Test behavior with a trailing dot.
254      * The directory should be created without the dot.
255      */
256     GetTempPathA(MAX_PATH, tmpdir);
257     lstrcatA(tmpdir, "Please Remove Me.");
258     ret = CreateDirectoryA(tmpdir, NULL);
259     ok(ret == TRUE,
260        "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
261 
262     lstrcatA(tmpdir, "/Please Remove Me");
263     ret = CreateDirectoryA(tmpdir, NULL);
264     ok(ret == TRUE,
265        "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
266     ret = RemoveDirectoryA(tmpdir);
267     ok(ret == TRUE,
268        "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
269 
270     GetTempPathA(MAX_PATH, tmpdir);
271     lstrcatA(tmpdir, "Please Remove Me");
272     ret = RemoveDirectoryA(tmpdir);
273     ok(ret == TRUE,
274        "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
275 
276     /* Test behavior with two trailing dots.
277      * The directory should be created without the trailing dots.
278      */
279     GetTempPathA(MAX_PATH, tmpdir);
280     lstrcatA(tmpdir, "Please Remove Me..");
281     ret = CreateDirectoryA(tmpdir, NULL);
282     ok(ret == TRUE,
283        "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
284 
285     lstrcatA(tmpdir, "/Please Remove Me");
286     ret = CreateDirectoryA(tmpdir, NULL);
287     ok(ret == TRUE || /* On Win98 */
288        (ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND), /* On NT! */
289        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
290     if (ret == TRUE)
291     {
292         ret = RemoveDirectoryA(tmpdir);
293         ok(ret == TRUE,
294            "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
295     }
296 
297     GetTempPathA(MAX_PATH, tmpdir);
298     lstrcatA(tmpdir, "Please Remove Me");
299     ret = RemoveDirectoryA(tmpdir);
300     ok(ret == TRUE,
301        "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
302 
303     /* Test behavior with a trailing space.
304      * The directory should be created without the trailing space.
305      */
306     GetTempPathA(MAX_PATH, tmpdir);
307     lstrcatA(tmpdir, "Please Remove Me ");
308     ret = CreateDirectoryA(tmpdir, NULL);
309     ok(ret == TRUE,
310        "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
311 
312     lstrcatA(tmpdir, "/Please Remove Me");
313     ret = CreateDirectoryA(tmpdir, NULL);
314     ok(ret == TRUE || /* On Win98 */
315        (ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND), /* On NT! */
316        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
317     if (ret == TRUE)
318     {
319         ret = RemoveDirectoryA(tmpdir);
320         ok(ret == TRUE,
321            "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
322     }
323 
324     GetTempPathA(MAX_PATH, tmpdir);
325     lstrcatA(tmpdir, "Please Remove Me");
326     ret = RemoveDirectoryA(tmpdir);
327     ok(ret == TRUE,
328        "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
329 
330     /* Test behavior with a trailing space.
331      * The directory should be created without the trailing spaces.
332      */
333     GetTempPathA(MAX_PATH, tmpdir);
334     lstrcatA(tmpdir, "Please Remove Me  ");
335     ret = CreateDirectoryA(tmpdir, NULL);
336     ok(ret == TRUE,
337        "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
338 
339     lstrcatA(tmpdir, "/Please Remove Me");
340     ret = CreateDirectoryA(tmpdir, NULL);
341     ok(ret == TRUE || /* On Win98 */
342        (ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND), /* On NT! */
343        "CreateDirectoryA(%s): ret=%d err=%d\n", tmpdir, ret, GetLastError());
344     if (ret == TRUE)
345     {
346         ret = RemoveDirectoryA(tmpdir);
347         ok(ret == TRUE,
348            "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
349     }
350 
351     GetTempPathA(MAX_PATH, tmpdir);
352     lstrcatA(tmpdir, "Please Remove Me");
353     ret = RemoveDirectoryA(tmpdir);
354     ok(ret == TRUE,
355        "RemoveDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
356     SetCurrentDirectoryW(curdir);
357 }
358 
359 static void test_CreateDirectoryW(void)
360 {
361     WCHAR tmpdir[MAX_PATH];
362     BOOL ret;
363     static const WCHAR empty_strW[] = { 0 };
364     static const WCHAR tmp_dir_name[] = {'P','l','e','a','s','e',' ','R','e','m','o','v','e',' ','M','e',0};
365     static const WCHAR dotW[] = {'.',0};
366     static const WCHAR slashW[] = {'/',0};
367     static const WCHAR dotdotW[] = {'.','.',0};
368     static const WCHAR questionW[] = {'?',0};
369     WCHAR curdir[MAX_PATH];
370 
371     ret = CreateDirectoryW(NULL, NULL);
372     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
373     {
374         win_skip("CreateDirectoryW is not available\n");
375         return;
376     }
377     ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND,
378        "should not create NULL path ret %u err %u\n", ret, GetLastError());
379 
380     ret = CreateDirectoryW(empty_strW, NULL);
381     ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND,
382        "should not create empty path ret %u err %u\n", ret, GetLastError());
383 
384     ret = GetSystemDirectoryW(tmpdir, MAX_PATH);
385     ok(ret < MAX_PATH, "System directory should fit into MAX_PATH\n");
386 
387     GetCurrentDirectoryW(MAX_PATH, curdir);
388     ret = SetCurrentDirectoryW(tmpdir);
389     ok(ret == TRUE, "could not chdir to the System directory ret %u err %u\n", ret, GetLastError());
390 
391     ret = CreateDirectoryW(dotW, NULL);
392     ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
393        "should not create existing path ret %u err %u\n", ret, GetLastError());
394 
395     ret = CreateDirectoryW(dotdotW, NULL);
396     ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
397        "should not create existing path ret %u err %u\n", ret, GetLastError());
398 
399     GetTempPathW(MAX_PATH, tmpdir);
400     tmpdir[3] = 0; /* truncate the path */
401     ret = CreateDirectoryW(tmpdir, NULL);
402     ok(ret == FALSE && (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_ALREADY_EXISTS),
403        "should deny access to the drive root ret %u err %u\n", ret, GetLastError());
404 
405     GetTempPathW(MAX_PATH, tmpdir);
406     lstrcatW(tmpdir, tmp_dir_name);
407     ret = CreateDirectoryW(tmpdir, NULL);
408     ok(ret == TRUE, "CreateDirectoryW should always succeed\n");
409 
410     ret = CreateDirectoryW(tmpdir, NULL);
411     ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
412        "should not create existing path ret %u err %u\n", ret, GetLastError());
413 
414     ret = RemoveDirectoryW(tmpdir);
415     ok(ret == TRUE, "RemoveDirectoryW should always succeed\n");
416 
417     lstrcatW(tmpdir, questionW);
418     ret = CreateDirectoryW(tmpdir, NULL);
419     ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
420        "CreateDirectoryW with ? wildcard name should fail with error 183, ret=%s error=%d\n",
421        ret ? " True" : "False", GetLastError());
422     ret = RemoveDirectoryW(tmpdir);
423     ok(ret == FALSE, "RemoveDirectoryW should have failed\n");
424 
425     tmpdir[lstrlenW(tmpdir) - 1] = '*';
426     ret = CreateDirectoryW(tmpdir, NULL);
427     ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
428        "CreateDirectoryW with * wildcard name should fail with error 183, ret=%s error=%d\n",
429        ret ? " True" : "False", GetLastError());
430     ret = RemoveDirectoryW(tmpdir);
431     ok(ret == FALSE, "RemoveDirectoryW should have failed\n");
432 
433     GetTempPathW(MAX_PATH, tmpdir);
434     lstrcatW(tmpdir, tmp_dir_name);
435     lstrcatW(tmpdir, slashW);
436     lstrcatW(tmpdir, tmp_dir_name);
437     ret = CreateDirectoryW(tmpdir, NULL);
438     ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND,
439       "CreateDirectoryW with multiple nonexistent directories in path should fail ret %u err %u\n",
440        ret, GetLastError());
441     ret = RemoveDirectoryW(tmpdir);
442     ok(ret == FALSE, "RemoveDirectoryW should have failed\n");
443 
444     SetCurrentDirectoryW(curdir);
445 }
446 
447 static void test_RemoveDirectoryA(void)
448 {
449     char curdir[MAX_PATH];
450     char tmpdir[MAX_PATH];
451     BOOL ret;
452 
453     GetTempPathA(MAX_PATH, tmpdir);
454     lstrcatA(tmpdir, "Please Remove Me");
455     ret = CreateDirectoryA(tmpdir, NULL);
456     ok(ret == TRUE, "CreateDirectoryA should always succeed\n");
457 
458     GetCurrentDirectoryA(MAX_PATH, curdir);
459     ok(SetCurrentDirectoryA(tmpdir), "SetCurrentDirectoryA failed\n");
460 
461     SetLastError(0xdeadbeef);
462     ok(!RemoveDirectoryA(tmpdir), "RemoveDirectoryA succeeded\n");
463     ok(GetLastError() == ERROR_SHARING_VIOLATION,
464        "Expected ERROR_SHARING_VIOLATION, got %u\n", GetLastError());
465 
466     TEST_GRANTED_ACCESS(NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle,
467                         FILE_TRAVERSE | SYNCHRONIZE);
468 
469     SetCurrentDirectoryA(curdir);
470     ret = RemoveDirectoryA(tmpdir);
471     ok(ret == TRUE, "RemoveDirectoryA should always succeed\n");
472 
473     lstrcatA(tmpdir, "?");
474     ret = RemoveDirectoryA(tmpdir);
475     ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
476 			GetLastError() == ERROR_PATH_NOT_FOUND),
477        "RemoveDirectoryA with ? wildcard name should fail, ret=%s error=%d\n",
478        ret ? " True" : "False", GetLastError());
479 
480     tmpdir[lstrlenA(tmpdir) - 1] = '*';
481     ret = RemoveDirectoryA(tmpdir);
482     ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
483 			GetLastError() == ERROR_PATH_NOT_FOUND),
484        "RemoveDirectoryA with * wildcard name should fail, ret=%s error=%d\n",
485        ret ? " True" : "False", GetLastError());
486 }
487 
488 static void test_RemoveDirectoryW(void)
489 {
490     WCHAR curdir[MAX_PATH];
491     WCHAR tmpdir[MAX_PATH];
492     BOOL ret;
493     static const WCHAR tmp_dir_name[] = {'P','l','e','a','s','e',' ','R','e','m','o','v','e',' ','M','e',0};
494     static const WCHAR questionW[] = {'?',0};
495 
496     GetTempPathW(MAX_PATH, tmpdir);
497     lstrcatW(tmpdir, tmp_dir_name);
498     ret = CreateDirectoryW(tmpdir, NULL);
499     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
500     {
501         win_skip("CreateDirectoryW is not available\n");
502         return;
503     }
504 
505     ok(ret == TRUE, "CreateDirectoryW should always succeed\n");
506 
507     GetCurrentDirectoryW(MAX_PATH, curdir);
508     ok(SetCurrentDirectoryW(tmpdir), "SetCurrentDirectoryW failed\n");
509 
510     SetLastError(0xdeadbeef);
511     ok(!RemoveDirectoryW(tmpdir), "RemoveDirectoryW succeeded\n");
512     ok(GetLastError() == ERROR_SHARING_VIOLATION,
513        "Expected ERROR_SHARING_VIOLATION, got %u\n", GetLastError());
514 
515     TEST_GRANTED_ACCESS(NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle,
516                         FILE_TRAVERSE | SYNCHRONIZE);
517 
518     SetCurrentDirectoryW(curdir);
519     ret = RemoveDirectoryW(tmpdir);
520     ok(ret == TRUE, "RemoveDirectoryW should always succeed\n");
521 
522     lstrcatW(tmpdir, questionW);
523     ret = RemoveDirectoryW(tmpdir);
524     ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
525        "RemoveDirectoryW with wildcard should fail with error 183, ret=%s error=%d\n",
526        ret ? " True" : "False", GetLastError());
527 
528     tmpdir[lstrlenW(tmpdir) - 1] = '*';
529     ret = RemoveDirectoryW(tmpdir);
530     ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
531        "RemoveDirectoryW with * wildcard name should fail with error 183, ret=%s error=%d\n",
532        ret ? " True" : "False", GetLastError());
533 }
534 
535 static void test_SetCurrentDirectoryA(void)
536 {
537     SetLastError(0);
538     ok( !SetCurrentDirectoryA( "\\some_dummy_dir" ), "SetCurrentDirectoryA succeeded\n" );
539     ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %d\n", GetLastError() );
540     ok( !SetCurrentDirectoryA( "\\some_dummy\\subdir" ), "SetCurrentDirectoryA succeeded\n" );
541     ok( GetLastError() == ERROR_PATH_NOT_FOUND, "wrong error %d\n", GetLastError() );
542 }
543 
544 START_TEST(directory)
545 {
546     init();
547 
548     test_GetWindowsDirectoryA();
549     test_GetWindowsDirectoryW();
550 
551     test_GetSystemDirectoryA();
552     test_GetSystemDirectoryW();
553 
554     test_CreateDirectoryA();
555     test_CreateDirectoryW();
556 
557     test_RemoveDirectoryA();
558     test_RemoveDirectoryW();
559 
560     test_SetCurrentDirectoryA();
561 }
562