2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for RtlDosPathNameToNtPathName_U
5 * PROGRAMMER: Mike "tamlin" Nordell
8 * - Make the code UNICODE aware. If a user is inside a directory with
9 * non-ANSI characters somewhere in the path, all bets are currently off.
10 * - Remove hard-coded path size limits.
11 * - Un-tabify to match style of other code.
12 * - Clean up cruft. Probably remove the option of running it stand-alone.
15 /* Test to see that ntdll.RtlDosPathNameToNtPathName_U behaves _exactly_
16 * like Windows with all possible input to it.
26 * Caveat: The "\??\*" form behaves different depending on Windows version.
27 * Some tests will fail if there is no C: volume.
29 * Code is assumed to be compiled as 32-bit "ANSI" (i.e. with _UNICODE) undefined.
32 // Enable this define to compile the test as a ReactOS auto-test.
33 // Disable it to compile on plain Win32, to test-run and get info.
34 #define COMPILE_AS_ROSTEST
36 #ifndef COMPILE_AS_ROSTEST
37 # define PRINT_INFO // Also print, in addition to testing
41 #else /* Compile for ReactOS or wine */
43 # define WIN32_NO_STATUS
45 # include <ndk/rtlfuncs.h>
51 RtlDosPathNameToNtPathName_U(IN PCWSTR DosName,
52 OUT PUNICODE_STRING NtName,
54 OUT PRTL_RELATIVE_NAME_U RelativeName)
57 #ifndef COMPILE_AS_ROSTEST
59 typedef struct UNICODE_STRING
{
63 } UNICODE_STRING
, *PUNICODE_STRING
;
65 typedef struct _RTLP_CURDIR_REF
69 } RTLP_CURDIR_REF
, *PRTLP_CURDIR_REF
;
71 typedef struct RTL_RELATIVE_NAME_U
{
72 UNICODE_STRING RelativeName
;
73 HANDLE ContainingDirectory
;
74 PRTLP_CURDIR_REF CurDirRef
;
75 } RTL_RELATIVE_NAME_U
, *PRTL_RELATIVE_NAME_U
;
77 typedef BOOLEAN (__stdcall
*RtlDosPathNameToNtPathName_U_t
)(PCWSTR
,PUNICODE_STRING
,PCWSTR
*,PRTL_RELATIVE_NAME_U
);
79 static RtlDosPathNameToNtPathName_U_t RtlDosPathNameToNtPathName_U
;
81 #endif // !COMPILE_AS_ROSTEST
84 static void check_result(BOOLEAN bOK
, const char* pszErr
)
86 #ifdef COMPILE_AS_ROSTEST
87 ok(bOK
, "%s.\n", pszErr
);
90 printf("\a** %s.\n", pszErr
);
96 #ifndef COMPILE_AS_ROSTEST
97 static void prucs(const char* pszDesc
, UNICODE_STRING
* pucs
)
100 memcpy(wszTmp
, pucs
->Buffer
, pucs
->Length
);
101 wszTmp
[pucs
->Length
/2] = 0;
102 printf("%-12s: \"%S\"\n", pszDesc
, wszTmp
);
106 // Test RtlDosPathNameToNtPathName_U .
107 // pwszExpected shall contain the expected result for NtName
108 // *without* the leading "\??\".
109 // pwszExpectedPartName shall contain the expected result for PartName.
110 // NULL Expected means result is expected to be NULL too.
111 static void test2(LPCWSTR pwsz
, LPCWSTR pwszExpected
, LPCWSTR pwszExpectedPartName
)
113 UNICODE_STRING NtName
;
115 RTL_RELATIVE_NAME_U RelativeName
;
118 bOK
= RtlDosPathNameToNtPathName_U(pwsz
, &NtName
, (PCWSTR
*)&PartName
, &RelativeName
);
120 check_result(bOK
, "RtlDosPathNameToNtPathName_U failed");
122 printf("input: \"%S\"\n", pwsz
);
126 #if !defined(COMPILE_AS_ROSTEST) && defined(PRINT_INFO)
127 printf("--------------------------\n");
128 printf("in : \"%S\"\n", pwsz
);
129 prucs("NtName", &NtName
);
130 printf("PartName : \"%S\"\n", PartName
? PartName
: L
"(null)");
131 // prucs("RelativeName", &RelativeName.RelativeName);
134 // Disregarding input, output (NtName) shall always start with "\??\".
135 bOK
= NtName
.Length
>= 8 &&
136 memcmp(NtName
.Buffer
, L
"\\??\\", 8) == 0;
137 check_result(bOK
, "NtName does not start with \"\\??\\\"");
143 PWSTR pwszActual
= NtName
.Buffer
+ 4;
144 const size_t lenExp
= wcslen(pwszExpected
);
145 const size_t lenAct
= (NtName
.Length
- 8) / 2;
146 bOK
= (lenExp
== lenAct
) &&
147 memcmp(pwszActual
, pwszExpected
, lenExp
* 2) == 0;
148 check_result(bOK
, "NtName does not match expected");
151 printf("input: : %2u chars \"%S\"\n", wcslen(pwsz
), pwsz
);
152 printf("Expected: %2u chars \"%S\"\n", lenExp
, pwszExpected
);
153 printf("Actual : %2u chars \"%S\"\n", lenAct
, lenAct
? pwszActual
: L
"(null)");
159 PWSTR pwszActual
= NtName
.Buffer
+ 4;
160 const size_t lenAct
= (NtName
.Length
- 8) / 2;
161 check_result(FALSE
, "Unexpected NtName (expected NULL)");
162 printf("input: : %2u chars \"%S\"\n", wcslen(pwsz
), pwsz
);
163 printf("Actual : %2u chars \"%S\"\n", lenAct
, pwszActual
);
166 if (pwszExpectedPartName
) {
167 const size_t lenExp
= wcslen(pwszExpectedPartName
);
168 const size_t lenAct
= PartName
? wcslen(PartName
) : 0;
169 bOK
= (lenExp
== lenAct
) &&
170 wcscmp(PartName
, pwszExpectedPartName
) == 0;
171 check_result(bOK
, "PartName does not match expected");
173 printf("input: : %2u chars \"%S\"\n", wcslen(pwsz
), pwsz
);
174 printf("Expected: %2u chars \"%S\"\n", lenExp
, pwszExpectedPartName
);
175 printf("Actual : %2u chars \"%S\"\n", lenAct
, lenAct
? PartName
: L
"(null)");
181 check_result(FALSE
, "Unexpected PartName (expected NULL).");
182 printf("input: : %2u chars \"%S\"\n", wcslen(pwsz
), pwsz
);
183 printf("Actual : %2u chars %S\n", wcslen(PartName
), PartName
);
187 // NULL Expected means result is expected to be NULL too.
188 static void test(const char* psz
, const char* pszExpected
, const char* pszExpectedPartName
)
195 swprintf(wszTmp1
, L
"%S", psz
);
197 swprintf(wszTmp2
, L
"%S", pszExpected
);
200 if (pszExpectedPartName
) {
201 swprintf(wszTmp3
, L
"%S", pszExpectedPartName
);
204 test2(wszTmp1
, p2
, p3
);
208 typedef struct DirComponents
211 char szCDPlusSlash
[512];
212 char* pszLastCDComponent
;
214 char szCurDriveSlash
[4];
215 char szParentDir
[512];
216 char szParentDirPlusSlash
[512];
217 char szNextLastCDComponent
[260];
218 const char* pszNextLastCDComponent
;
219 const char* pszPD
; // parent dir
220 const char* pszPDPlusSlash
;
224 static void InitDirComponents(DirComponents
* p
)
226 /* While the following code seems to work, it's an unholy mess
227 * and should probably be cleaned up.
231 p
->pszNextLastCDComponent
= 0;
233 p
->pszPDPlusSlash
= 0;
235 GetCurrentDirectory(sizeof(p
->szCD
) / sizeof(*p
->szCD
), p
->szCD
);
237 bOK
= strlen(p
->szCD
) >= 2 && p
->szCD
[1] == ':';
238 check_result(bOK
, "Expected curdir to be a drive letter. It's not");
241 printf("Curdir is \"%s\"\n", p
->szCD
);
245 bOK
= p
->szCD
[2] == '\\';
246 check_result(bOK
, "CD is missing a slash as its third character");
248 printf("CD is \"%s\"\n", p
->szCD
);
252 // Note that if executed from the root directory, a backslash is
254 strcpy(p
->szCDPlusSlash
, p
->szCD
);
255 if (strlen(p
->szCD
) > 3) {
256 // Append trailing backslash
257 strcat(p
->szCDPlusSlash
, "\\");
260 memcpy(p
->szCurDrive
, p
->szCD
, 2);
261 p
->szCurDrive
[2] = 0;
262 sprintf(p
->szCurDriveSlash
, "%s\\", p
->szCurDrive
);
264 p
->pszLastCDComponent
= strrchr(p
->szCD
, '\\');
265 if (p
->pszLastCDComponent
)
267 // We have a parent directory
268 memcpy(p
->szParentDir
, p
->szCD
, p
->pszLastCDComponent
- p
->szCD
);
269 p
->szParentDir
[p
->pszLastCDComponent
- p
->szCD
] = 0;
270 p
->pszPD
= p
->szParentDir
;
271 if (strlen(p
->szParentDir
) == 2 && p
->szParentDir
[1] == ':') {
272 // When run from root directory, this is expected to
273 // have a trailing backslash
274 strcat(p
->szParentDir
, "\\");
276 strcpy(p
->szParentDirPlusSlash
, p
->szParentDir
);
277 if (p
->szParentDirPlusSlash
[strlen(p
->szParentDirPlusSlash
)-1] != '\\') {
278 strcat(p
->szParentDirPlusSlash
, "\\");
280 p
->pszPDPlusSlash
= p
->szParentDirPlusSlash
;
282 // Check if we have a directory above that too.
283 *p
->pszLastCDComponent
= 0;
284 p
->pszNextLastCDComponent
= strrchr(p
->szCD
, '\\');
285 *p
->pszLastCDComponent
= '\\';
286 if (p
->pszNextLastCDComponent
) {
287 ++p
->pszNextLastCDComponent
; // skip the leading slash
288 if (p
->pszNextLastCDComponent
+ 1 >= p
->pszLastCDComponent
) {
289 p
->pszNextLastCDComponent
= 0;
291 const size_t siz
= p
->pszLastCDComponent
- p
->pszNextLastCDComponent
;
292 memcpy(p
->szNextLastCDComponent
, p
->pszNextLastCDComponent
, siz
);
293 p
->szNextLastCDComponent
[siz
] = 0;
294 p
->pszNextLastCDComponent
= p
->szNextLastCDComponent
;
298 if (p
->pszLastCDComponent
&& p
->pszLastCDComponent
[1] == 0) {
299 // If the backslash is the last character in the path,
300 // this is a NULL-component.
301 p
->pszLastCDComponent
= 0;
303 ++p
->pszLastCDComponent
; // skip the leading slash
308 #ifndef COMPILE_AS_ROSTEST
309 static void InitFunctionPointer()
311 HINSTANCE hDll
= LoadLibrary("ntdll");
313 printf("Major failure. Couldn't even load ntdll!\n");
316 RtlDosPathNameToNtPathName_U
=
317 (RtlDosPathNameToNtPathName_U_t
)GetProcAddress(hDll
, "RtlDosPathNameToNtPathName_U");
318 if (!RtlDosPathNameToNtPathName_U
) {
319 printf("Major failure. Couldn't get RtlDosPathNameToNtPathName_U!\n");
324 # if defined(PRINT_INFO)
325 static DWORD
get_win_ver()
327 # ifdef COMPILE_AS_ROSTEST
328 PPEB Peb
= NtCurrentPeb();
329 const DWORD dwWinVer
= (DWORD
)(Peb
->OSMinorVersion
<< 8) | Peb
->OSMajorVersion
;
331 const DWORD dwWinVer
= GetVersion();
335 # endif /* PRINT_INFO */
336 #endif /* !COMPILE_AS_ROSTEST */
339 #ifdef COMPILE_AS_ROSTEST
340 START_TEST(RtlDosPathNameToNtPathName_U
)
345 #if defined(PRINT_INFO)
346 const DWORD dwWinVer
= get_win_ver();
347 const BYTE WinVerMaj
= (BYTE
)dwWinVer
;
348 const BYTE WinVerMin
= HIBYTE(LOWORD(dwWinVer
));
354 #ifndef COMPILE_AS_ROSTEST
355 InitFunctionPointer();
358 InitDirComponents(&cd
);
360 #if defined(PRINT_INFO)
361 printf("WinVer: %d.%d\n", WinVerMaj
, WinVerMin
);
362 printf("pszLastCDComponent \"%s\"\n", cd
.pszLastCDComponent
);
363 printf("pszNextLastCDComponent \"%s\"\n", cd
.pszNextLastCDComponent
);
364 printf("pszParentDir \"%s\"\n", cd
.pszPD
);
365 printf("pszParentDirPlusSlash \"%s\"\n", cd
.pszPDPlusSlash
);
368 #define PREP0 /* The normal Win32 namespace. Fully parsed. */
369 #define PREP1 "\\\\.\\" /* The Win32 Device Namespace. Only partially parsed. */
370 #define PREP2 "\\\\?\\" /* The Win32 File Namespace. Only partially parsed. */
372 // input name NtName PartName
373 // volume-absolute paths
374 test(PREP1
"C:" , "C:" , "C:");
375 test(PREP2
"C:" , "C:" , "C:");
376 test(PREP0
"C:\\" , "C:\\" , NULL
);
377 test(PREP1
"C:\\" , "C:\\" , NULL
);
378 test(PREP2
"C:\\" , "C:\\" , NULL
);
379 test(PREP0
"C:\\foo" , "C:\\foo" , "foo");
380 test(PREP1
"C:\\foo" , "C:\\foo" , "foo");
381 test(PREP2
"C:\\foo" , "C:\\foo" , "foo");
382 test(PREP0
"C:\\foo\\" , "C:\\foo\\" , NULL
);
383 test(PREP1
"C:\\foo\\" , "C:\\foo\\" , NULL
);
384 test(PREP2
"C:\\foo\\" , "C:\\foo\\" , NULL
);
385 test(PREP0
"C:\\foo\\bar" , "C:\\foo\\bar" , "bar");
386 test(PREP1
"C:\\foo\\bar" , "C:\\foo\\bar" , "bar");
387 test(PREP2
"C:\\foo\\bar" , "C:\\foo\\bar" , "bar");
388 test(PREP0
"C:\\foo\\bar\\", "C:\\foo\\bar\\" , NULL
);
389 test(PREP1
"C:\\foo\\bar\\", "C:\\foo\\bar\\" , NULL
);
390 test(PREP2
"C:\\foo\\bar\\", "C:\\foo\\bar\\" , NULL
);
391 test(PREP0
"C:\\foo\\.." , "C:\\" , NULL
);
392 test(PREP1
"C:\\foo\\.." , "C:" , "C:");
393 test(PREP2
"C:\\foo\\.." , "C:\\foo\\.." , "..");
394 test(PREP0
"C:\\foo\\..\\" , "C:\\" , NULL
);
395 test(PREP1
"C:\\foo\\..\\" , "C:\\" , NULL
);
396 test(PREP2
"C:\\foo\\..\\" , "C:\\foo\\..\\" , NULL
);
397 test(PREP0
"C:\\foo." , "C:\\foo" , "foo");
398 test(PREP1
"C:\\foo." , "C:\\foo" , "foo");
399 test(PREP2
"C:\\foo." , "C:\\foo." , "foo.");
401 test(PREP0
"C:\\f\\b\\.." , "C:\\f" , "f");
402 test(PREP1
"C:\\f\\b\\.." , "C:\\f" , "f");
403 test(PREP2
"C:\\f\\b\\.." , "C:\\f\\b\\.." , "..");
404 test(PREP0
"C:\\f\\b\\..\\", "C:\\f\\" , NULL
);
405 test(PREP1
"C:\\f\\b\\..\\", "C:\\f\\" , NULL
);
406 test(PREP2
"C:\\f\\b\\..\\", "C:\\f\\b\\..\\" , NULL
);
410 // RtlDosPathNameToNtPathName_U makes no distinction for
411 // special device names, such as "PhysicalDisk0", "HarddiskVolume0"
412 // or "Global??". They all follow the same pattern as a named
413 // filesystem entry, why they implicitly tested by the following
414 // "foo" and "foo\" cases.
415 sprintf(szTmp
, "%s%s", cd
.szCDPlusSlash
, "foo");
416 test(PREP0
"foo" , szTmp
, "foo");
417 test(PREP1
"foo" , "foo" , "foo");
418 test(PREP2
"foo" , "foo" , "foo");
420 sprintf(szTmp
, "%s%s", cd
.szCDPlusSlash
, "foo\\");
421 test(PREP0
"foo\\" , szTmp
, NULL
);
422 test(PREP1
"foo\\" , "foo\\" , NULL
);
423 test(PREP2
"foo\\" , "foo\\" , NULL
);
425 test(PREP0
"." , cd
.szCD
, cd
.pszLastCDComponent
);
426 test(PREP1
"." , "" , NULL
);
427 test(PREP2
"." , "." , ".");
428 test(PREP0
".\\" , cd
.szCDPlusSlash
, NULL
);
429 test(PREP1
".\\" , "" , NULL
);
430 test(PREP2
".\\" , ".\\" , NULL
);
431 test(PREP0
".\\." , cd
.szCD
, cd
.pszLastCDComponent
);
432 test(PREP1
".\\." , "" , NULL
);
433 test(PREP2
".\\." , ".\\." , ".");
434 test(PREP0
".\\.." , cd
.pszPD
, cd
.pszNextLastCDComponent
);
435 test(PREP1
".\\.." , "" , NULL
);
436 test(PREP2
".\\.." , ".\\.." , "..");
437 test(PREP0
".." , cd
.pszPD
, cd
.pszNextLastCDComponent
);
438 test(PREP1
".." , "" , NULL
);
439 test(PREP2
".." , ".." , "..");
440 test(PREP0
"..\\" , cd
.pszPDPlusSlash
, NULL
);
441 test(PREP1
"..\\" , "" , NULL
);
442 test(PREP2
"..\\" , "..\\" , NULL
);
444 test(PREP0
"..." , cd
.szCDPlusSlash
, NULL
);
445 test(PREP1
"..." , "" , NULL
);
446 test(PREP2
"..." , "..." , "...");
448 // Test well-known "special" DOS device names.
449 test(PREP0
"NUL" , "NUL" , NULL
);
450 test(PREP1
"NUL" , "NUL" , "NUL");
451 test(PREP2
"NUL" , "NUL" , "NUL");
452 test(PREP0
"NUL:" , "NUL" , NULL
);
453 test(PREP1
"NUL:" , "NUL:" , "NUL:");
454 test(PREP2
"NUL:" , "NUL:" , "NUL:");
455 test(PREP0
"CON" , "CON" , NULL
);
456 // NOTE: RtlDosPathNameToNtPathName_U (as currently tested) fails for
457 // the input "\\.\CON" on two widely different Windows versions.
458 // test(PREP1 "CON" , "CON" , "CON");
459 test(PREP2
"CON" , "CON" , "CON");
460 test(PREP0
"CON:" , "CON" , NULL
);
461 test(PREP1
"CON:" , "CON:" , "CON:");
462 test(PREP2
"CON:" , "CON:" , "CON:");
464 sprintf(szTmp
, "%s\\%s", cd
.szCD
, "NUL:\\");
465 test(PREP0
"NUL:\\" , szTmp
, NULL
);
466 test(PREP1
"NUL:\\" , "NUL:\\" , NULL
);
467 test(PREP2
"NUL:\\" , "NUL:\\" , NULL
);
468 test(PREP0
"C:NUL" , "NUL" , NULL
);
469 test(PREP1
"C:NUL" , "C:NUL" , "C:NUL");
470 test(PREP2
"C:NUL" , "C:NUL" , "C:NUL");
471 test(PREP0
"C:\\NUL" , "NUL" , NULL
);
472 test(PREP1
"C:\\NUL" , "C:\\NUL" , "NUL");
473 test(PREP2
"C:\\NUL" , "C:\\NUL" , "NUL");
474 test(PREP0
"C:\\NUL\\" , "C:\\NUL\\" , NULL
);
475 test(PREP1
"C:\\NUL\\" , "C:\\NUL\\" , NULL
);
476 test(PREP2
"C:\\NUL\\" , "C:\\NUL\\" , NULL
);
479 test(PREP0
"\\" , cd
.szCurDriveSlash
, NULL
);
480 test(PREP1
"\\" , "" , NULL
);
481 test(PREP2
"\\" , "\\" , NULL
);
483 test(PREP0
"\\." , cd
.szCurDriveSlash
, NULL
);
484 test(PREP1
"\\." , "" , NULL
);
485 test(PREP2
"\\." , "\\." , ".");
487 test(PREP0
"\\.." , cd
.szCurDriveSlash
, NULL
);
488 test(PREP1
"\\.." , "" , NULL
);
489 test(PREP2
"\\.." , "\\.." , "..");
491 test(PREP0
"\\..." , cd
.szCurDriveSlash
, NULL
);
492 test(PREP1
"\\..." , "" , NULL
);
493 test(PREP2
"\\..." , "\\..." , "...");
496 sprintf(szTmp
, "%s%s", cd
.szCurDrive
, "\\C:");
497 test(PREP0
"\\C:" , szTmp
, "C:");
498 test(PREP1
"\\C:" , "C:" , "C:");
499 test(PREP2
"\\C:" , "\\C:" , "C:");
501 sprintf(szTmp
, "%s%s", cd
.szCurDrive
, "\\C:\\");
502 test(PREP0
"\\C:\\" , szTmp
, NULL
);
503 test(PREP1
"\\C:\\" , "C:\\" , NULL
);
504 test(PREP2
"\\C:\\" , "\\C:\\" , NULL
);
507 test(PREP0
"\\\\" , "UNC\\" , NULL
);
508 test(PREP1
"\\\\" , "" , NULL
);
509 test(PREP2
"\\\\" , "\\\\" , NULL
);
510 test(PREP0
"\\\\\\" , "UNC\\\\" , NULL
);
511 test(PREP1
"\\\\\\" , "" , NULL
);
512 test(PREP2
"\\\\\\" , "\\\\\\" , NULL
);
513 test(PREP0
"\\\\foo" , "UNC\\foo" , NULL
);
514 test(PREP1
"\\\\foo" , "foo" , "foo");
515 test(PREP2
"\\\\foo" , "\\\\foo" , "foo");
517 test(PREP0
"\\\\foo\\.." , "UNC\\foo\\" , NULL
);
518 test(PREP1
"\\\\foo\\.." , "" , NULL
);
519 test(PREP2
"\\\\foo\\.." , "\\\\foo\\.." , "..");
521 test(PREP0
"\\\\foo\\" , "UNC\\foo\\" , NULL
);
522 test(PREP1
"\\\\foo\\" , "foo\\" , NULL
);
523 test(PREP2
"\\\\foo\\" , "\\\\foo\\" , NULL
);
524 test(PREP0
"\\\\f\\b" , "UNC\\f\\b" , NULL
);
525 test(PREP1
"\\\\f\\b" , "f\\b" , "b");
526 test(PREP2
"\\\\f\\b" , "\\\\f\\b" , "b");
527 test(PREP0
"\\\\f\\b\\" , "UNC\\f\\b\\" , NULL
);
528 test(PREP1
"\\\\f\\b\\" , "f\\b\\" , NULL
);
529 test(PREP2
"\\\\f\\b\\" , "\\\\f\\b\\" , NULL
);
531 test(PREP0
"\\\\f\\b\\.." , "UNC\\f\\b" , NULL
);
532 test(PREP1
"\\\\f\\b\\.." , "f" , "f");
533 test(PREP2
"\\\\f\\b\\.." , "\\\\f\\b\\.." , "..");
536 test(PREP0
"\\\\C:" , "UNC\\C:" , NULL
);
537 test(PREP1
"\\\\C:" , "C:" , "C:");
538 test(PREP2
"\\\\C:" , "\\\\C:" , "C:");
539 test(PREP0
"\\\\C:\\" , "UNC\\C:\\" , NULL
);
540 test(PREP1
"\\\\C:\\" , "C:\\" , NULL
);
541 test(PREP2
"\\\\C:\\" , "\\\\C:\\" , NULL
);
542 test(PREP0
"\\\\NUL" , "UNC\\NUL" , NULL
);
543 test(PREP1
"\\\\NUL" , "NUL" , "NUL");
544 test(PREP2
"\\\\NUL" , "\\\\NUL" , "NUL");
545 test(PREP0
"\\\\NUL:" , "UNC\\NUL:" , NULL
);
546 test(PREP1
"\\\\NUL:" , "NUL:" , "NUL:");
547 test(PREP2
"\\\\NUL:" , "\\\\NUL:" , "NUL:");
548 test(PREP0
"\\\\NUL:\\" , "UNC\\NUL:\\" , NULL
);
549 test(PREP1
"\\\\NUL:\\" , "NUL:\\" , NULL
);
550 test(PREP2
"\\\\NUL:\\" , "\\\\NUL:\\" , NULL
);
552 // UNC + forward slashes
553 test(PREP0
"//" , "UNC\\" , NULL
);
554 test(PREP1
"//" , "" , NULL
);
555 test(PREP2
"//" , "//" , "//");
556 test(PREP0
"//C:" , "UNC\\C:" , NULL
);
557 test(PREP1
"//C:" , "C:" , "C:");
558 test(PREP2
"//C:" , "//C:" , "//C:");
559 test(PREP0
"//C:/" , "UNC\\C:\\" , NULL
);
560 test(PREP1
"//C:/" , "C:\\" , NULL
);
561 test(PREP2
"//C:/" , "//C:/" , "//C:/");
562 test(PREP0
"//." , "" , NULL
);
563 test(PREP1
"//." , "" , NULL
);
564 test(PREP2
"//." , "//." , "//.");
565 test(PREP0
"//.." , "UNC\\" , NULL
);
566 test(PREP1
"//.." , "" , NULL
);
567 test(PREP2
"//.." , "//.." , "//..");
568 test(PREP0
"/./" , cd
.szCurDriveSlash
, NULL
);
569 test(PREP1
"/./" , "" , NULL
);
570 test(PREP2
"/./" , "/./" , "/./");
571 test(PREP0
"//./" , "" , NULL
);
572 test(PREP1
"//./" , "" , NULL
);
573 test(PREP2
"//./" , "//./" , "//./");
575 test(cd
.szCD
, cd
.szCD
, cd
.pszLastCDComponent
);
576 test(cd
.szCDPlusSlash
, cd
.szCDPlusSlash
, NULL
);
579 // The following tests are "problematic", as they return results based on
580 // what your CD on C: is, whether or not you actually run the program
581 // from C:. For that reason, they are currently disabled.
582 test(PREP0
"C:" , "C:\\"+C_curdir
, C_curdir
);
583 test(PREP0
"C:NUL\\" , "C:\\"+C_curdir
+"\\NUL\\" , NULL
);
586 #if 0 // Disabled due to... see the comment inside the block.
592 // Strictly speaking, this "Should Never Happen(tm)", calling
593 // RtlDosPathNameToNtPathName_U with a source already formed as
594 // a full NT name ("\??\"), why it's not the end of the world
595 // that this test is currently disabled.
597 // Some versions of Windows prepends driveletter + colon
598 // for the process' current volume.
599 // Prepending curdrive is most likely a bug that got fixed in
600 // later versions of Windows, but for compatibility it may
601 // become a requirement to "shim" this.
603 // Known operating systems prepending "Z:\??\" (assuming the
604 // process' CD is on the volume Z:):
607 // Known operating systems not prepending:
608 // - Win7 64 (as 32-bit)
609 if (WinVerMaj
== 5) {
610 sprintf(szPrepend
, "%s\\??\\", cd
.szCurDrive
);
613 sprintf(szExp
, "%s%s", szPrepend
, "C:");
614 test("\\??\\C:", szExp
, "C:");
616 sprintf(szExp
, "%s%s", szPrepend
, "C:\\");
617 test("\\??\\C:\\", szExp
, NULL
);
622 #ifndef COMPILE_AS_ROSTEST