makefiles: Explicitly create destination dirs when installing symlinks.
[wine/zf.git] / dlls / ntdll / tests / path.c
blobe4adc992a2822e11f8ca8c8500c0a3496ecd5af2
1 /*
2 * Unit test suite for ntdll path functions
4 * Copyright 2002 Alexandre Julliard
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.
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.
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
21 #include "ntdll_test.h"
22 #include "winnls.h"
24 static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
25 LPCSTR src, DWORD srclen );
26 static NTSTATUS (WINAPI *pRtlUnicodeToMultiByteN)(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
27 static UINT (WINAPI *pRtlDetermineDosPathNameType_U)( PCWSTR path );
28 static ULONG (WINAPI *pRtlIsDosDeviceName_U)( PCWSTR dos_name );
29 static NTSTATUS (WINAPI *pRtlOemStringToUnicodeString)(UNICODE_STRING *, const STRING *, BOOLEAN );
30 static BOOLEAN (WINAPI *pRtlIsNameLegalDOS8Dot3)(const UNICODE_STRING*,POEM_STRING,PBOOLEAN);
31 static DWORD (WINAPI *pRtlGetFullPathName_U)(const WCHAR*,ULONG,WCHAR*,WCHAR**);
32 static BOOLEAN (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR*, UNICODE_STRING*, WCHAR**, CURDIR*);
33 static NTSTATUS (WINAPI *pRtlDosPathNameToNtPathName_U_WithStatus)(const WCHAR*, UNICODE_STRING*, WCHAR**, CURDIR*);
35 static void test_RtlDetermineDosPathNameType_U(void)
37 struct test
39 const char *path;
40 UINT ret;
43 static const struct test tests[] =
45 { "\\\\foo", 1 },
46 { "//foo", 1 },
47 { "\\/foo", 1 },
48 { "/\\foo", 1 },
49 { "\\\\", 1 },
50 { "//", 1 },
51 { "c:\\foo", 2 },
52 { "c:/foo", 2 },
53 { "c://foo", 2 },
54 { "c:\\", 2 },
55 { "c:/", 2 },
56 { "c:foo", 3 },
57 { "c:f\\oo", 3 },
58 { "c:foo/bar", 3 },
59 { "\\foo", 4 },
60 { "/foo", 4 },
61 { "\\", 4 },
62 { "/", 4 },
63 { "foo", 5 },
64 { "", 5 },
65 { "\0:foo", 5 },
66 { "\\\\.\\foo", 6 },
67 { "//./foo", 6 },
68 { "/\\./foo", 6 },
69 { "\\\\.foo", 1 },
70 { "//.foo", 1 },
71 { "\\\\.", 7 },
72 { "//.", 7 },
73 { "\\\\?\\foo", 6 },
74 { "//?/foo", 6 },
75 { "/\\?/foo", 6 },
76 { "\\\\?foo", 1 },
77 { "//?foo", 1 },
78 { "\\\\?", 7 },
79 { "//?", 7 },
80 { "CONIN$", 5 },
81 { "CONOUT$", 5 },
82 { "CONERR$", 5 },
83 { "\\\\.\\CONIN$", 6 },
84 { "\\\\.\\CONOUT$", 6 },
85 { NULL, 0 }
88 const struct test *test;
89 WCHAR buffer[MAX_PATH];
90 UINT ret;
92 if (!pRtlDetermineDosPathNameType_U)
94 win_skip("RtlDetermineDosPathNameType_U is not available\n");
95 return;
98 for (test = tests; test->path; test++)
100 pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
101 ret = pRtlDetermineDosPathNameType_U( buffer );
102 ok( ret == test->ret, "Wrong result %d/%d for %s\n", ret, test->ret, test->path );
107 static void test_RtlIsDosDeviceName_U(void)
109 struct test
111 const char *path;
112 WORD pos;
113 WORD len;
114 BOOL fails;
117 static const struct test tests[] =
119 { "\\\\.\\CON", 8, 6, TRUE }, /* fails on win8 */
120 { "\\\\.\\con", 8, 6, TRUE }, /* fails on win8 */
121 { "\\\\.\\CON2", 0, 0 },
122 { "", 0, 0 },
123 { "\\\\foo\\nul", 0, 0 },
124 { "c:\\nul:", 6, 6 },
125 { "c:\\nul\\", 0, 0 },
126 { "c:\\nul\\foo", 0, 0 },
127 { "c:\\nul::", 6, 6, TRUE }, /* fails on nt4 */
128 { "c:\\nul::::::", 6, 6, TRUE }, /* fails on nt4 */
129 { "c:prn ", 4, 6 },
130 { "c:prn.......", 4, 6 },
131 { "c:prn... ...", 4, 6 },
132 { "c:NUL .... ", 4, 6, TRUE }, /* fails on nt4 */
133 { "c: . . .", 0, 0 },
134 { "c:", 0, 0 },
135 { " . . . :", 0, 0 },
136 { ":", 0, 0 },
137 { "c:nul. . . :", 4, 6 },
138 { "c:nul . . :", 4, 6, TRUE }, /* fails on nt4 */
139 { "c:nul0", 0, 0 },
140 { "c:prn:aaa", 4, 6, TRUE }, /* fails on win9x */
141 { "c:PRN:.txt", 4, 6 },
142 { "c:aux:.txt...", 4, 6 },
143 { "c:prn:.txt:", 4, 6 },
144 { "c:nul:aaa", 4, 6, TRUE }, /* fails on win9x */
145 { "con:", 0, 6 },
146 { "lpt1:", 0, 8 },
147 { "c:com5:", 4, 8 },
148 { "CoM4:", 0, 8 },
149 { "lpt9:", 0, 8 },
150 { "c:\\lpt0.txt", 0, 0 },
151 { "CONIN$", 0, 12, TRUE }, /* fails on winxp */
152 { "CONOUT$", 0, 14, TRUE }, /* fails on winxp */
153 { "CONERR$", 0, 0 },
154 { "CON", 0, 6 },
155 { "PIPE", 0, 0 },
156 { "\\??\\CONIN$", 8, 12, TRUE }, /* fails on winxp */
157 { "\\??\\CONOUT$", 8, 14, TRUE }, /* fails on winxp */
158 { "\\??\\CONERR$", 0, 0 },
159 { "\\??\\CON", 8, 6 },
160 { "c:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
161 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
162 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
163 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
164 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
165 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
166 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nul.txt", 1000, 6 },
167 { NULL, 0 }
170 const struct test *test;
171 WCHAR buffer[2000];
172 ULONG ret;
174 if (!pRtlIsDosDeviceName_U)
176 win_skip("RtlIsDosDeviceName_U is not available\n");
177 return;
180 for (test = tests; test->path; test++)
182 pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
183 ret = pRtlIsDosDeviceName_U( buffer );
184 ok( ret == MAKELONG( test->len, test->pos ) ||
185 (test->fails && broken( ret == 0 )),
186 "Wrong result (%d,%d)/(%d,%d) for %s\n",
187 HIWORD(ret), LOWORD(ret), test->pos, test->len, test->path );
191 static void test_RtlIsNameLegalDOS8Dot3(void)
193 struct test
195 const char *path;
196 BOOLEAN result;
197 BOOLEAN spaces;
200 static const struct test tests[] =
202 { "12345678", TRUE, FALSE },
203 { "123 5678", TRUE, TRUE },
204 { "12345678.", FALSE, 2 /*not set*/ },
205 { "1234 678.", FALSE, 2 /*not set*/ },
206 { "12345678.a", TRUE, FALSE },
207 { "12345678.a ", FALSE, 2 /*not set*/ },
208 { "12345678.a c", TRUE, TRUE },
209 { " 2345678.a ", FALSE, 2 /*not set*/ },
210 { "1 345678.abc", TRUE, TRUE },
211 { "1 8.a c", TRUE, TRUE },
212 { "1 3 5 7 .abc", FALSE, 2 /*not set*/ },
213 { "12345678. c", TRUE, TRUE },
214 { "123456789.a", FALSE, 2 /*not set*/ },
215 { "12345.abcd", FALSE, 2 /*not set*/ },
216 { "12345.ab d", FALSE, 2 /*not set*/ },
217 { ".abc", FALSE, 2 /*not set*/ },
218 { "12.abc.d", FALSE, 2 /*not set*/ },
219 { ".", TRUE, FALSE },
220 { "..", TRUE, FALSE },
221 { "...", FALSE, 2 /*not set*/ },
222 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", FALSE, 2 /*not set*/ },
223 { NULL, 0 }
226 const struct test *test;
227 UNICODE_STRING ustr;
228 OEM_STRING oem, oem_ret;
229 WCHAR buffer[200];
230 char buff2[12];
231 BOOLEAN ret, spaces;
233 if (!pRtlIsNameLegalDOS8Dot3)
235 win_skip("RtlIsNameLegalDOS8Dot3 is not available\n");
236 return;
239 ustr.MaximumLength = sizeof(buffer);
240 ustr.Buffer = buffer;
241 for (test = tests; test->path; test++)
243 char path[100];
244 strcpy(path, test->path);
245 oem.Buffer = path;
246 oem.Length = strlen(test->path);
247 oem.MaximumLength = oem.Length + 1;
248 pRtlOemStringToUnicodeString( &ustr, &oem, FALSE );
249 spaces = 2;
250 oem_ret.Length = oem_ret.MaximumLength = sizeof(buff2);
251 oem_ret.Buffer = buff2;
252 ret = pRtlIsNameLegalDOS8Dot3( &ustr, &oem_ret, &spaces );
253 ok( ret == test->result, "Wrong result %d/%d for '%s'\n", ret, test->result, test->path );
254 ok( spaces == test->spaces, "Wrong spaces value %d/%d for '%s'\n", spaces, test->spaces, test->path );
255 if (strlen(test->path) <= 12)
257 STRING test_str;
258 char str[13];
259 strcpy( str, test->path );
260 RtlInitString( &test_str, str );
261 RtlUpperString( &test_str, &test_str );
262 ok( !RtlCompareString(&oem_ret, &test_str, FALSE),
263 "Wrong string '%.*s'/'%s'\n", oem_ret.Length, oem_ret.Buffer, test->path );
267 static void test_RtlGetFullPathName_U(void)
269 static const WCHAR emptyW[] = {0};
270 static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0};
272 struct test
274 const char *path;
275 const char *rname;
276 const char *rfile;
277 const char *alt_rname;
278 const char *alt_rfile;
281 static const struct test tests[] =
283 { "c:/test", "c:\\test", "test"},
284 { "c:/test/", "c:\\test\\", NULL},
285 { "c:/test ", "c:\\test", "test"},
286 { "c:/test.", "c:\\test", "test"},
287 { "c:/test .... .. ", "c:\\test", "test"},
288 { "c:/test/ .... .. ", "c:\\test\\", NULL},
289 { "c:/test/..", "c:\\", NULL},
290 { "c:/test/.. ", "c:\\test\\", NULL},
291 { "c:/TEST", "c:\\TEST", "TEST"},
292 { "c:/test/file", "c:\\test\\file", "file"},
293 { "c:/test./file", "c:\\test\\file", "file"},
294 { "c:/test.. /file", "c:\\test.. \\file","file"},
295 { "c:/test/././file", "c:\\test\\file", "file"},
296 { "c:/test\\.\\.\\file", "c:\\test\\file", "file"},
297 { "c:/test/\\.\\.\\file", "c:\\test\\file", "file"},
298 { "c:/test\\\\.\\.\\file", "c:\\test\\file", "file"},
299 { "c:/test\\test1\\..\\.\\file", "c:\\test\\file", "file"},
300 { "c:///test\\.\\.\\file//", "c:\\test\\file\\", NULL,
301 "c:\\test\\file", "file"}, /* nt4 */
302 { "c:///test\\..\\file\\..\\//", "c:\\", NULL},
303 { "c:/test../file", "c:\\test.\\file", "file",
304 "c:\\test..\\file", "file"}, /* vista */
305 { "c:\\test", "c:\\test", "test"},
306 { "C:\\test", "C:\\test", "test"},
307 { "c:/", "c:\\", NULL},
308 { "c:.", "C:\\windows", "windows"},
309 { "c:foo", "C:\\windows\\foo", "foo"},
310 { "c:foo/bar", "C:\\windows\\foo\\bar", "bar"},
311 { "c:./foo", "C:\\windows\\foo", "foo"},
312 { "\\foo", "C:\\foo", "foo"},
313 { "foo", "C:\\windows\\foo", "foo"},
314 { ".", "C:\\windows", "windows"},
315 { "..", "C:\\", NULL},
316 { "...", "C:\\windows\\", NULL},
317 { "./foo", "C:\\windows\\foo", "foo"},
318 { "foo/..", "C:\\windows", "windows"},
319 { "AUX", "\\\\.\\AUX", NULL},
320 { "COM1", "\\\\.\\COM1", NULL},
321 { "?<>*\"|:", "C:\\windows\\?<>*\"|:", "?<>*\"|:"},
323 { "\\\\foo", "\\\\foo", NULL},
324 { "//foo", "\\\\foo", NULL},
325 { "\\/foo", "\\\\foo", NULL},
326 { "//", "\\\\", NULL},
327 { "//foo/", "\\\\foo\\", NULL},
329 { "//.", "\\\\.\\", NULL},
330 { "//./", "\\\\.\\", NULL},
331 { "//.//", "\\\\.\\", NULL},
332 { "//./foo", "\\\\.\\foo", "foo"},
333 { "//./foo/", "\\\\.\\foo\\", NULL},
334 { "//./foo/bar", "\\\\.\\foo\\bar", "bar"},
335 { "//./foo/.", "\\\\.\\foo", "foo"},
336 { "//./foo/..", "\\\\.\\", NULL},
338 { "//?/", "\\\\?\\", NULL},
339 { "//?//", "\\\\?\\", NULL},
340 { "//?/foo", "\\\\?\\foo", "foo"},
341 { "//?/foo/", "\\\\?\\foo\\", NULL},
342 { "//?/foo/bar", "\\\\?\\foo\\bar", "bar"},
343 { "//?/foo/.", "\\\\?\\foo", "foo"},
344 { "//?/foo/..", "\\\\?\\", NULL},
346 { "CONIN$", "\\\\.\\CONIN$", NULL,
347 "C:\\windows\\CONIN$", "CONIN$"},
348 { "CONOUT$", "\\\\.\\CONOUT$", NULL,
349 "C:\\windows\\CONOUT$", "CONOUT$"},
351 /* RtlGetFullPathName_U() can't understand the global namespace prefix */
352 { "\\??\\foo", "C:\\??\\foo", "foo"},
353 { 0 }
356 const struct test *test;
357 WCHAR pathbufW[2*MAX_PATH], rbufferW[MAX_PATH];
358 char rbufferA[MAX_PATH], rfileA[MAX_PATH], curdir[MAX_PATH];
359 ULONG ret;
360 WCHAR *file_part;
361 DWORD reslen;
362 UINT len;
364 GetCurrentDirectoryA(sizeof(curdir), curdir);
365 SetCurrentDirectoryA("C:\\windows\\");
367 file_part = (WCHAR *)0xdeadbeef;
368 lstrcpyW(rbufferW, deadbeefW);
369 ret = pRtlGetFullPathName_U(NULL, MAX_PATH, rbufferW, &file_part);
370 ok(!ret, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret);
371 ok(!lstrcmpW(rbufferW, deadbeefW),
372 "Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW));
373 ok(file_part == (WCHAR *)0xdeadbeef ||
374 file_part == NULL, /* Win7 */
375 "Expected file part pointer to be untouched, got %p\n", file_part);
377 file_part = (WCHAR *)0xdeadbeef;
378 lstrcpyW(rbufferW, deadbeefW);
379 ret = pRtlGetFullPathName_U(emptyW, MAX_PATH, rbufferW, &file_part);
380 ok(!ret, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret);
381 ok(!lstrcmpW(rbufferW, deadbeefW),
382 "Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW));
383 ok(file_part == (WCHAR *)0xdeadbeef ||
384 file_part == NULL, /* Win7 */
385 "Expected file part pointer to be untouched, got %p\n", file_part);
387 for (test = tests; test->path; test++)
389 len= strlen(test->rname) * sizeof(WCHAR);
390 pRtlMultiByteToUnicodeN(pathbufW , sizeof(pathbufW), NULL, test->path, strlen(test->path)+1 );
391 ret = pRtlGetFullPathName_U( pathbufW,MAX_PATH, rbufferW, &file_part);
392 ok( ret == len || (test->alt_rname && ret == strlen(test->alt_rname)*sizeof(WCHAR)),
393 "Wrong result %d/%d for \"%s\"\n", ret, len, test->path );
394 ok(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,(lstrlenW(rbufferW) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
395 "RtlUnicodeToMultiByteN failed\n");
396 ok(!lstrcmpA(rbufferA,test->rname) || (test->alt_rname && !lstrcmpA(rbufferA,test->alt_rname)),
397 "Got \"%s\" expected \"%s\"\n",rbufferA,test->rname);
398 if (file_part)
400 ok(pRtlUnicodeToMultiByteN(rfileA,MAX_PATH,&reslen,file_part,(lstrlenW(file_part) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
401 "RtlUnicodeToMultiByteN failed\n");
402 ok((test->rfile && !lstrcmpA(rfileA,test->rfile)) ||
403 (test->alt_rfile && !lstrcmpA(rfileA,test->alt_rfile)),
404 "Got \"%s\" expected \"%s\"\n",rfileA,test->rfile);
406 else
408 ok( !test->rfile, "Got NULL expected \"%s\"\n", test->rfile );
412 SetCurrentDirectoryA(curdir);
415 static void test_RtlDosPathNameToNtPathName_U(void)
417 static const WCHAR broken_global_prefix[] = L"\\??\\C:\\??";
419 char curdir[MAX_PATH];
420 UNICODE_STRING nameW;
421 WCHAR *file_part;
422 NTSTATUS status;
423 BOOL ret;
424 int i;
426 static const struct
428 const WCHAR *dos;
429 const WCHAR *nt;
430 int file_offset; /* offset to file part */
431 const WCHAR *alt_nt;
433 tests[] =
435 {L"c:\\", L"\\??\\c:\\", -1},
436 {L"c:/", L"\\??\\c:\\", -1},
437 {L"c:/foo", L"\\??\\c:\\foo", 7},
438 {L"c:/foo.", L"\\??\\c:\\foo", 7},
439 {L"c:/foo/", L"\\??\\c:\\foo\\", -1},
440 {L"c:/foo//", L"\\??\\c:\\foo\\", -1},
441 {L"C:/foo", L"\\??\\C:\\foo", 7},
442 {L"C:/foo/bar", L"\\??\\C:\\foo\\bar", 11},
443 {L"C:/foo/bar", L"\\??\\C:\\foo\\bar", 11},
444 {L"c:.", L"\\??\\C:\\windows", 7},
445 {L"c:foo", L"\\??\\C:\\windows\\foo", 15},
446 {L"c:foo/bar", L"\\??\\C:\\windows\\foo\\bar", 19},
447 {L"c:./foo", L"\\??\\C:\\windows\\foo", 15},
448 {L"c:/./foo", L"\\??\\c:\\foo", 7},
449 {L"c:/..", L"\\??\\c:\\", -1},
450 {L"c:/foo/.", L"\\??\\c:\\foo", 7},
451 {L"c:/foo/./bar", L"\\??\\c:\\foo\\bar", 11},
452 {L"c:/foo/../bar", L"\\??\\c:\\bar", 7},
453 {L"\\foo", L"\\??\\C:\\foo", 7},
454 {L"foo", L"\\??\\C:\\windows\\foo", 15},
455 {L".", L"\\??\\C:\\windows", 7},
456 {L"./", L"\\??\\C:\\windows\\", -1},
457 {L"..", L"\\??\\C:\\", -1},
458 {L"...", L"\\??\\C:\\windows\\", -1},
459 {L"./foo", L"\\??\\C:\\windows\\foo", 15},
460 {L"foo/..", L"\\??\\C:\\windows", 7},
461 {L"AUX" , L"\\??\\AUX", -1},
462 {L"COM1" , L"\\??\\COM1", -1},
463 {L"?<>*\"|:", L"\\??\\C:\\windows\\?<>*\"|:", 15},
464 {L"?:", L"\\??\\?:\\", -1},
466 {L"\\\\foo", L"\\??\\UNC\\foo", -1},
467 {L"//foo", L"\\??\\UNC\\foo", -1},
468 {L"\\/foo", L"\\??\\UNC\\foo", -1},
469 {L"//", L"\\??\\UNC\\", -1},
470 {L"//foo/", L"\\??\\UNC\\foo\\", -1},
472 {L"//.", L"\\??\\", -1},
473 {L"//./", L"\\??\\", -1},
474 {L"//.//", L"\\??\\", -1},
475 {L"//./foo", L"\\??\\foo", 4},
476 {L"//./foo/", L"\\??\\foo\\", -1},
477 {L"//./foo/bar", L"\\??\\foo\\bar", 8},
478 {L"//./foo/.", L"\\??\\foo", 4},
479 {L"//./foo/..", L"\\??\\", -1},
481 {L"//?", L"\\??\\", -1},
482 {L"//?/", L"\\??\\", -1},
483 {L"//?//", L"\\??\\", -1},
484 {L"//?/foo", L"\\??\\foo", 4},
485 {L"//?/foo/", L"\\??\\foo\\", -1},
486 {L"//?/foo/bar", L"\\??\\foo\\bar", 8},
487 {L"//?/foo/.", L"\\??\\foo", 4},
488 {L"//?/foo/..", L"\\??\\", -1},
490 {L"\\\\.", L"\\??\\", -1},
491 {L"\\\\.\\", L"\\??\\", -1},
492 {L"\\\\.\\/", L"\\??\\", -1},
493 {L"\\\\.\\foo", L"\\??\\foo", 4},
494 {L"\\\\.\\foo/", L"\\??\\foo\\", -1},
495 {L"\\\\.\\foo/bar", L"\\??\\foo\\bar", 8},
496 {L"\\\\.\\foo/.", L"\\??\\foo", 4},
497 {L"\\\\.\\foo/..", L"\\??\\", -1},
499 {L"\\\\?", L"\\??\\", -1},
500 {L"\\\\?\\", L"\\??\\", -1},
502 {L"\\\\?\\/", L"\\??\\/", 4},
503 {L"\\\\?\\foo", L"\\??\\foo", 4},
504 {L"\\\\?\\foo/", L"\\??\\foo/", 4},
505 {L"\\\\?\\foo/bar", L"\\??\\foo/bar", 4},
506 {L"\\\\?\\foo/.", L"\\??\\foo/.", 4},
507 {L"\\\\?\\foo/..", L"\\??\\foo/..", 4},
508 {L"\\\\?\\\\", L"\\??\\\\", -1},
509 {L"\\\\?\\\\\\", L"\\??\\\\\\", -1},
510 {L"\\\\?\\foo\\", L"\\??\\foo\\", -1},
511 {L"\\\\?\\foo\\bar",L"\\??\\foo\\bar", 8},
512 {L"\\\\?\\foo\\.", L"\\??\\foo\\.", 8},
513 {L"\\\\?\\foo\\..", L"\\??\\foo\\..", 8},
515 {L"\\??", L"\\??\\C:\\??", 7},
516 {L"\\??\\", L"\\??\\C:\\??\\", -1},
518 {L"\\??\\/", L"\\??\\/", 4},
519 {L"\\??\\foo", L"\\??\\foo", 4},
520 {L"\\??\\foo/", L"\\??\\foo/", 4},
521 {L"\\??\\foo/bar", L"\\??\\foo/bar", 4},
522 {L"\\??\\foo/.", L"\\??\\foo/.", 4},
523 {L"\\??\\foo/..", L"\\??\\foo/..", 4},
524 {L"\\??\\\\", L"\\??\\\\", -1},
525 {L"\\??\\\\\\", L"\\??\\\\\\", -1},
526 {L"\\??\\foo\\", L"\\??\\foo\\", -1},
527 {L"\\??\\foo\\bar", L"\\??\\foo\\bar", 8},
528 {L"\\??\\foo\\.", L"\\??\\foo\\.", 8},
529 {L"\\??\\foo\\..", L"\\??\\foo\\..", 8},
531 {L"CONIN$", L"\\??\\CONIN$", -1, L"\\??\\C:\\windows\\CONIN$" /* winxp */ },
532 {L"CONOUT$", L"\\??\\CONOUT$", -1, L"\\??\\C:\\windows\\CONOUT$" /* winxp */ },
533 {L"cOnOuT$", L"\\??\\cOnOuT$", -1, L"\\??\\C:\\windows\\cOnOuT$" /* winxp */ },
534 {L"CONERR$", L"\\??\\C:\\windows\\CONERR$", 15},
537 GetCurrentDirectoryA(sizeof(curdir), curdir);
538 SetCurrentDirectoryA("C:\\windows\\");
540 ret = pRtlDosPathNameToNtPathName_U(NULL, &nameW, &file_part, NULL);
541 ok(!ret, "Got %d.\n", ret);
543 ret = pRtlDosPathNameToNtPathName_U(L"", &nameW, &file_part, NULL);
544 ok(!ret, "Got %d.\n", ret);
546 ret = pRtlDosPathNameToNtPathName_U(L" ", &nameW, &file_part, NULL);
547 ok(!ret, "Got %d.\n", ret);
549 if (pRtlDosPathNameToNtPathName_U_WithStatus)
551 status = pRtlDosPathNameToNtPathName_U_WithStatus(NULL, &nameW, &file_part, NULL);
552 ok(status == STATUS_OBJECT_NAME_INVALID || status == STATUS_OBJECT_PATH_NOT_FOUND /* 2003 */,
553 "Got status %#x.\n", status);
555 status = pRtlDosPathNameToNtPathName_U_WithStatus(L"", &nameW, &file_part, NULL);
556 ok(status == STATUS_OBJECT_NAME_INVALID || status == STATUS_OBJECT_PATH_NOT_FOUND /* 2003 */,
557 "Got status %#x.\n", status);
559 status = pRtlDosPathNameToNtPathName_U_WithStatus(L" ", &nameW, &file_part, NULL);
560 ok(status == STATUS_OBJECT_NAME_INVALID || status == STATUS_OBJECT_PATH_NOT_FOUND /* 2003 */,
561 "Got status %#x.\n", status);
564 for (i = 0; i < ARRAY_SIZE(tests); ++i)
566 ret = pRtlDosPathNameToNtPathName_U(tests[i].dos, &nameW, &file_part, NULL);
567 ok(ret == TRUE, "%s: Got %d.\n", debugstr_w(tests[i].dos), ret);
569 if (pRtlDosPathNameToNtPathName_U_WithStatus)
571 RtlFreeUnicodeString(&nameW);
572 status = pRtlDosPathNameToNtPathName_U_WithStatus(tests[i].dos, &nameW, &file_part, NULL);
573 ok(status == STATUS_SUCCESS, "%s: Got status %#x.\n", debugstr_w(tests[i].dos), status);
576 if (!wcsncmp(tests[i].dos, L"\\??\\", 4) && tests[i].dos[4] &&
577 broken(!wcsncmp(nameW.Buffer, broken_global_prefix, wcslen(broken_global_prefix))))
579 /* Windows version prior to 2003 don't interpret the \??\ prefix */
580 continue;
583 ok(!wcscmp(nameW.Buffer, tests[i].nt) || broken(!wcscmp(nameW.Buffer, tests[i].alt_nt)), "%s: Expected %s, got %s.\n",
584 debugstr_w(tests[i].dos), debugstr_w(tests[i].nt), debugstr_w(nameW.Buffer));
586 if (!wcscmp(nameW.Buffer, tests[i].nt))
588 if (tests[i].file_offset > 0)
589 ok(file_part == nameW.Buffer + tests[i].file_offset,
590 "%s: Expected file part %s, got %s.\n", debugstr_w(tests[i].dos),
591 debugstr_w(nameW.Buffer + tests[i].file_offset), debugstr_w(file_part));
592 else
593 ok(file_part == NULL, "%s: Expected NULL file part, got %s.\n",
594 debugstr_w(tests[i].dos), debugstr_w(file_part));
597 RtlFreeUnicodeString(&nameW);
600 SetCurrentDirectoryA(curdir);
603 START_TEST(path)
605 HMODULE mod = GetModuleHandleA("ntdll.dll");
606 if (!mod)
608 win_skip("Not running on NT, skipping tests\n");
609 return;
612 pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
613 pRtlUnicodeToMultiByteN = (void *)GetProcAddress(mod,"RtlUnicodeToMultiByteN");
614 pRtlDetermineDosPathNameType_U = (void *)GetProcAddress(mod,"RtlDetermineDosPathNameType_U");
615 pRtlIsDosDeviceName_U = (void *)GetProcAddress(mod,"RtlIsDosDeviceName_U");
616 pRtlOemStringToUnicodeString = (void *)GetProcAddress(mod,"RtlOemStringToUnicodeString");
617 pRtlIsNameLegalDOS8Dot3 = (void *)GetProcAddress(mod,"RtlIsNameLegalDOS8Dot3");
618 pRtlGetFullPathName_U = (void *)GetProcAddress(mod,"RtlGetFullPathName_U");
619 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(mod, "RtlDosPathNameToNtPathName_U");
620 pRtlDosPathNameToNtPathName_U_WithStatus = (void *)GetProcAddress(mod, "RtlDosPathNameToNtPathName_U_WithStatus");
622 test_RtlDetermineDosPathNameType_U();
623 test_RtlIsDosDeviceName_U();
624 test_RtlIsNameLegalDOS8Dot3();
625 test_RtlGetFullPathName_U();
626 test_RtlDosPathNameToNtPathName_U();