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