ReactOS 0.4.17-dev-684-ga6524ef
RtlDosPathNameToNtPathName_U.c
Go to the documentation of this file.
1/*
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
6 */
7/* TODO:
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.
13 */
14
15/* Test to see that ntdll.RtlDosPathNameToNtPathName_U behaves _exactly_
16 * like Windows with all possible input to it.
17 * - relative path.
18 * - absolute paths
19 * - \\.\C:\foo
20 * - \\.\C:\foo\
21 * - \\?\C:\foo
22 * - \\?\C:\foo\
23 * - \??\C:
24 * - \??\C:\
25 *
26 * Caveat: The "\??\*" form behaves different depending on Windows version.
27 * Some tests will fail if there is no C: volume.
28 *
29 * Code is assumed to be compiled as 32-bit "ANSI" (i.e. with _UNICODE) undefined.
30 */
31
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
35
36#ifndef COMPILE_AS_ROSTEST
37# define PRINT_INFO // Also print, in addition to testing
38# include <windows.h>
39# include <stdio.h>
40# include <stddef.h>
41#else /* Compile for ReactOS or wine */
42# include "precomp.h"
43#endif
44
45/*
46BOOLEAN
47NTAPI
48RtlDosPathNameToNtPathName_U(IN PCWSTR DosName,
49 OUT PUNICODE_STRING NtName,
50 OUT PCWSTR *PartName,
51 OUT PRTL_RELATIVE_NAME_U RelativeName)
52*/
53
54#ifndef COMPILE_AS_ROSTEST
55
56typedef struct UNICODE_STRING {
61
62typedef struct _RTLP_CURDIR_REF
63{
67
68typedef struct RTL_RELATIVE_NAME_U {
69 UNICODE_STRING RelativeName;
70 HANDLE ContainingDirectory;
71 PRTLP_CURDIR_REF CurDirRef;
73
74typedef BOOLEAN (__stdcall *RtlDosPathNameToNtPathName_U_t)(PCWSTR,PUNICODE_STRING,PCWSTR*,PRTL_RELATIVE_NAME_U);
75
76static RtlDosPathNameToNtPathName_U_t RtlDosPathNameToNtPathName_U;
77
78#endif // !COMPILE_AS_ROSTEST
79
80
81static void check_result(BOOLEAN bOK, const char* pszErr)
82{
83#ifdef COMPILE_AS_ROSTEST
84 ok(bOK, "%s.\n", pszErr);
85#else
86 if (!bOK) {
87 printf("\a** %s.\n", pszErr);
88 }
89#endif
90}
91
92
93#ifndef COMPILE_AS_ROSTEST
94static void prucs(const char* pszDesc, UNICODE_STRING* pucs)
95{
96 WCHAR wszTmp[512];
97 memcpy(wszTmp, pucs->Buffer, pucs->Length);
98 wszTmp[pucs->Length/2] = 0;
99 printf("%-12s: \"%S\"\n", pszDesc, wszTmp);
100}
101#endif
102
103// Test RtlDosPathNameToNtPathName_U .
104// pwszExpected shall contain the expected result for NtName
105// *without* the leading "\??\".
106// pwszExpectedPartName shall contain the expected result for PartName.
107// NULL Expected means result is expected to be NULL too.
108static void test2(LPCWSTR pwsz, LPCWSTR pwszExpected, LPCWSTR pwszExpectedPartName)
109{
110 UNICODE_STRING NtName;
111 PWSTR PartName;
112 RTL_RELATIVE_NAME_U RelativeName;
113 BOOLEAN bOK;
114
115 bOK = RtlDosPathNameToNtPathName_U(pwsz, &NtName, (PCWSTR*)&PartName, &RelativeName);
116
117 check_result(bOK, "RtlDosPathNameToNtPathName_U failed");
118 if (!bOK) {
119 printf("input: \"%S\"\n", pwsz);
120 return;
121 }
122
123#if !defined(COMPILE_AS_ROSTEST) && defined(PRINT_INFO)
124 printf("--------------------------\n");
125 printf("in : \"%S\"\n", pwsz);
126 prucs("NtName", &NtName);
127 printf("PartName : \"%S\"\n", PartName ? PartName : L"(null)");
128// prucs("RelativeName", &RelativeName.RelativeName);
129#endif
130
131 // Disregarding input, output (NtName) shall always start with "\??\".
132 bOK = NtName.Length >= 8 &&
133 memcmp(NtName.Buffer, L"\\??\\", 8) == 0;
134 check_result(bOK, "NtName does not start with \"\\??\\\"");
135 if (!bOK) {
136 goto Quit;
137 }
138
139 if (pwszExpected) {
140 PWSTR pwszActual = NtName.Buffer + 4;
141 const size_t lenExp = wcslen(pwszExpected);
142 const size_t lenAct = (NtName.Length - 8) / 2;
143 bOK = (lenExp == lenAct) &&
144 memcmp(pwszActual, pwszExpected, lenExp * 2) == 0;
145 check_result(bOK, "NtName does not match expected");
146 if (!bOK)
147 {
148 printf("input: : %2Iu chars \"%S\"\n", wcslen(pwsz), pwsz);
149 printf("Expected: %2Iu chars \"%S\"\n", lenExp, pwszExpected);
150 printf("Actual : %2Iu chars \"%S\"\n", lenAct, lenAct ? pwszActual : L"(null)");
151 goto Quit;
152 }
153 } else
154 if (NtName.Length)
155 {
156 PWSTR pwszActual = NtName.Buffer + 4;
157 const size_t lenAct = (NtName.Length - 8) / 2;
158 check_result(FALSE, "Unexpected NtName (expected NULL)");
159 printf("input: : %2Iu chars \"%S\"\n", wcslen(pwsz), pwsz);
160 printf("Actual : %2Iu chars \"%S\"\n", lenAct, pwszActual);
161 }
162
163 if (pwszExpectedPartName) {
164 const size_t lenExp = wcslen(pwszExpectedPartName);
165 const size_t lenAct = PartName ? wcslen(PartName) : 0;
166 bOK = (lenExp == lenAct) &&
167 wcscmp(PartName, pwszExpectedPartName) == 0;
168 check_result(bOK, "PartName does not match expected");
169 if (!bOK) {
170 printf("input: : %2Iu chars \"%S\"\n", wcslen(pwsz), pwsz);
171 printf("Expected: %2Iu chars \"%S\"\n", lenExp, pwszExpectedPartName);
172 printf("Actual : %2Iu chars \"%S\"\n", lenAct, lenAct ? PartName : L"(null)");
173 goto Quit;
174 }
175 } else
176 if (PartName)
177 {
178 check_result(FALSE, "Unexpected PartName (expected NULL).");
179 printf("input: : %2Iu chars \"%S\"\n", wcslen(pwsz), pwsz);
180 printf("Actual : %2Iu chars %S\n", wcslen(PartName), PartName);
181 }
182
183Quit:
184 RtlFreeHeap(RtlGetProcessHeap(), 0, NtName.Buffer);
185 RtlReleaseRelativeName(&RelativeName);
186}
187
188// NULL Expected means result is expected to be NULL too.
189static void test(const char* psz, const char* pszExpected, const char* pszExpectedPartName)
190{
191 WCHAR wszTmp1[512];
192 WCHAR wszTmp2[512];
193 WCHAR wszTmp3[512];
194 LPCWSTR p2 = 0;
195 LPCWSTR p3 = 0;
196 _swprintf(wszTmp1, L"%S", psz);
197 if (pszExpected) {
198 _swprintf(wszTmp2, L"%S", pszExpected);
199 p2 = wszTmp2;
200 }
201 if (pszExpectedPartName) {
202 _swprintf(wszTmp3, L"%S", pszExpectedPartName);
203 p3 = wszTmp3;
204 }
205 test2(wszTmp1, p2, p3);
206}
207
208
209typedef struct DirComponents
210{
211 char szCD[512];
212 char szCDPlusSlash[512];
214 char szCurDrive[3];
217 char szParentDir[512];
221 const char* pszPD; // parent dir
222 const char* pszPDPlusSlash;
224
225
227{
228 /* While the following code seems to work, it's an unholy mess
229 * and should probably be cleaned up.
230 */
231 BOOLEAN bOK;
232
233 p->pszNextLastCDComponent = 0;
234 p->pszPD = 0;
235 p->pszPDPlusSlash = 0;
236
237 GetCurrentDirectory(sizeof(p->szCD) / sizeof(*p->szCD), p->szCD);
238
239 bOK = strlen(p->szCD) >= 2 && p->szCD[1] == ':';
240 check_result(bOK, "Expected curdir to be a drive letter. It's not");
241
242 if (!bOK) {
243 printf("Curdir is \"%s\"\n", p->szCD);
244 exit(1);
245 }
246
247 bOK = p->szCD[2] == '\\';
248 check_result(bOK, "CD is missing a slash as its third character");
249 if (!bOK) {
250 printf("CD is \"%s\"\n", p->szCD);
251 exit(1);
252 }
253
254 // Note that if executed from the root directory, a backslash is
255 // already appended.
256 strcpy(p->szCDPlusSlash, p->szCD);
257 if (strlen(p->szCD) > 3) {
258 // Append trailing backslash
259 strcat(p->szCDPlusSlash, "\\");
260 }
261
262 memcpy(p->szCurDrive, p->szCD, 2);
263 p->szCurDrive[2] = 0;
264 sprintf(p->szCurDriveSlash, "%s\\", p->szCurDrive);
265
266 p->pszLastCDComponent = strrchr(p->szCD, '\\');
267 if (p->pszLastCDComponent)
268 {
269 // We have a parent directory
270 memcpy(p->szParentDir, p->szCD, p->pszLastCDComponent - p->szCD);
271 p->szParentDir[p->pszLastCDComponent - p->szCD] = 0;
272 p->pszPD = p->szParentDir;
273 if (strlen(p->szParentDir) == 2 && p->szParentDir[1] == ':') {
274 // When run from root directory, this is expected to
275 // have a trailing backslash
276 strcat(p->szParentDir, "\\");
277 }
278 strcpy(p->szParentDirPlusSlash, p->szParentDir);
279 if (p->szParentDirPlusSlash[strlen(p->szParentDirPlusSlash)-1] != '\\') {
280 strcat(p->szParentDirPlusSlash, "\\");
281 }
282 p->pszPDPlusSlash = p->szParentDirPlusSlash;
283
284 // Check if we have a directory above that too.
285 *p->pszLastCDComponent = 0;
286 p->pszNextLastCDComponent = strrchr(p->szCD, '\\');
287 *p->pszLastCDComponent = '\\';
288 if (p->pszNextLastCDComponent) {
289 ++p->pszNextLastCDComponent; // skip the leading slash
290 if (p->pszNextLastCDComponent + 1 >= p->pszLastCDComponent) {
291 p->pszNextLastCDComponent = 0;
292 } else {
293 const size_t siz = p->pszLastCDComponent - p->pszNextLastCDComponent;
294 memcpy(p->szNextLastCDComponent, p->pszNextLastCDComponent, siz);
295 p->szNextLastCDComponent[siz] = 0;
296 p->pszNextLastCDComponent = p->szNextLastCDComponent;
297 }
298 }
299 }
300 if (p->pszLastCDComponent && p->pszLastCDComponent[1] == 0) {
301 // If the backslash is the last character in the path,
302 // this is a NULL-component.
303 p->pszLastCDComponent = 0;
304 } else {
305 ++p->pszLastCDComponent; // skip the leading slash
306 }
307}
308
309
310#ifndef COMPILE_AS_ROSTEST
311static void InitFunctionPointer()
312{
313 HINSTANCE hDll = LoadLibrary("ntdll");
314 if (!hDll) {
315 printf("Major failure. Couldn't even load ntdll!\n");
316 exit(1);
317 }
319 (RtlDosPathNameToNtPathName_U_t)GetProcAddress(hDll, "RtlDosPathNameToNtPathName_U");
321 printf("Major failure. Couldn't get RtlDosPathNameToNtPathName_U!\n");
322 exit(1);
323 }
324}
325
326# if defined(PRINT_INFO)
327static DWORD get_win_ver()
328{
329# ifdef COMPILE_AS_ROSTEST
331 const DWORD dwWinVer = (DWORD)(Peb->OSMinorVersion << 8) | Peb->OSMajorVersion;
332# else
333 const DWORD dwWinVer = GetVersion();
334# endif
335 return dwWinVer;
336}
337# endif /* PRINT_INFO */
338#endif /* !COMPILE_AS_ROSTEST */
339
340
341#ifdef COMPILE_AS_ROSTEST
343#else
344int main()
345#endif
346{
347#if defined(PRINT_INFO)
348 const DWORD dwWinVer = get_win_ver();
349 const BYTE WinVerMaj = (BYTE)dwWinVer;
350 const BYTE WinVerMin = HIBYTE(LOWORD(dwWinVer));
351#endif // PRINT_INFO
352
354 char szTmp[518];
355
356#ifndef COMPILE_AS_ROSTEST
357 InitFunctionPointer();
358#endif
359
361
362#if defined(PRINT_INFO)
363 printf("WinVer: %d.%d\n", WinVerMaj, WinVerMin);
364 printf("pszLastCDComponent \"%s\"\n", cd.pszLastCDComponent);
365 printf("pszNextLastCDComponent \"%s\"\n", cd.pszNextLastCDComponent);
366 printf("pszParentDir \"%s\"\n", cd.pszPD);
367 printf("pszParentDirPlusSlash \"%s\"\n", cd.pszPDPlusSlash);
368#endif
369
370#define PREP0 /* The normal Win32 namespace. Fully parsed. */
371#define PREP1 "\\\\.\\" /* The Win32 Device Namespace. Only partially parsed. */
372#define PREP2 "\\\\?\\" /* The Win32 File Namespace. Only partially parsed. */
373
374 // input name NtName PartName
375 // volume-absolute paths
376 test(PREP1 "C:" , "C:" , "C:");
377 test(PREP2 "C:" , "C:" , "C:");
378 test(PREP0 "C:\\" , "C:\\" , NULL);
379 test(PREP1 "C:\\" , "C:\\" , NULL);
380 test(PREP2 "C:\\" , "C:\\" , NULL);
381 test(PREP0 "C:\\foo" , "C:\\foo" , "foo");
382 test(PREP1 "C:\\foo" , "C:\\foo" , "foo");
383 test(PREP2 "C:\\foo" , "C:\\foo" , "foo");
384 test(PREP0 "C:\\foo\\" , "C:\\foo\\" , NULL);
385 test(PREP1 "C:\\foo\\" , "C:\\foo\\" , NULL);
386 test(PREP2 "C:\\foo\\" , "C:\\foo\\" , NULL);
387 test(PREP0 "C:\\foo\\bar" , "C:\\foo\\bar" , "bar");
388 test(PREP1 "C:\\foo\\bar" , "C:\\foo\\bar" , "bar");
389 test(PREP2 "C:\\foo\\bar" , "C:\\foo\\bar" , "bar");
390 test(PREP0 "C:\\foo\\bar\\", "C:\\foo\\bar\\" , NULL);
391 test(PREP1 "C:\\foo\\bar\\", "C:\\foo\\bar\\" , NULL);
392 test(PREP2 "C:\\foo\\bar\\", "C:\\foo\\bar\\" , NULL);
393 test(PREP0 "C:\\foo\\.." , "C:\\" , NULL);
394 test(PREP1 "C:\\foo\\.." , "C:" , "C:");
395 test(PREP2 "C:\\foo\\.." , "C:\\foo\\.." , "..");
396 test(PREP0 "C:\\foo\\..\\" , "C:\\" , NULL);
397 test(PREP1 "C:\\foo\\..\\" , "C:\\" , NULL);
398 test(PREP2 "C:\\foo\\..\\" , "C:\\foo\\..\\" , NULL);
399 test(PREP0 "C:\\foo." , "C:\\foo" , "foo");
400 test(PREP1 "C:\\foo." , "C:\\foo" , "foo");
401 test(PREP2 "C:\\foo." , "C:\\foo." , "foo.");
402
403 test(PREP0 "C:\\f\\b\\.." , "C:\\f" , "f");
404 test(PREP1 "C:\\f\\b\\.." , "C:\\f" , "f");
405 test(PREP2 "C:\\f\\b\\.." , "C:\\f\\b\\.." , "..");
406 test(PREP0 "C:\\f\\b\\..\\", "C:\\f\\" , NULL);
407 test(PREP1 "C:\\f\\b\\..\\", "C:\\f\\" , NULL);
408 test(PREP2 "C:\\f\\b\\..\\", "C:\\f\\b\\..\\" , NULL);
409
410 // CD-relative paths
411
412 // RtlDosPathNameToNtPathName_U makes no distinction for
413 // special device names, such as "PhysicalDisk0", "HarddiskVolume0"
414 // or "Global??". They all follow the same pattern as a named
415 // filesystem entry, why they implicitly tested by the following
416 // "foo" and "foo\" cases.
417 sprintf(szTmp, "%s%s", cd.szCDPlusSlash, "foo");
418 test(PREP0 "foo" , szTmp , "foo");
419 test(PREP1 "foo" , "foo" , "foo");
420 test(PREP2 "foo" , "foo" , "foo");
421
422 sprintf(szTmp, "%s%s", cd.szCDPlusSlash , "foo\\");
423 test(PREP0 "foo\\" , szTmp , NULL);
424 test(PREP1 "foo\\" , "foo\\" , NULL);
425 test(PREP2 "foo\\" , "foo\\" , NULL);
426
427 test(PREP0 "." , cd.szCD , cd.pszLastCDComponent);
428 test(PREP1 "." , "" , NULL);
429 test(PREP2 "." , "." , ".");
430 test(PREP0 ".\\" , cd.szCDPlusSlash , NULL);
431 test(PREP1 ".\\" , "" , NULL);
432 test(PREP2 ".\\" , ".\\" , NULL);
433 test(PREP0 ".\\." , cd.szCD , cd.pszLastCDComponent);
434 test(PREP1 ".\\." , "" , NULL);
435 test(PREP2 ".\\." , ".\\." , ".");
436 test(PREP0 ".\\.." , cd.pszPD , cd.pszNextLastCDComponent);
437 test(PREP1 ".\\.." , "" , NULL);
438 test(PREP2 ".\\.." , ".\\.." , "..");
439 test(PREP0 ".." , cd.pszPD , cd.pszNextLastCDComponent);
440 test(PREP1 ".." , "" , NULL);
441 test(PREP2 ".." , ".." , "..");
442 test(PREP0 "..\\" , cd.pszPDPlusSlash , NULL);
443 test(PREP1 "..\\" , "" , NULL);
444 test(PREP2 "..\\" , "..\\" , NULL);
445 // malformed
446 test(PREP0 "..." , cd.szCDPlusSlash , NULL);
447 test(PREP1 "..." , "" , NULL);
448 test(PREP2 "..." , "..." , "...");
449
450 // Test well-known "special" DOS device names.
451 test(PREP0 "NUL" , "NUL" , NULL);
452 test(PREP1 "NUL" , "NUL" , "NUL");
453 test(PREP2 "NUL" , "NUL" , "NUL");
454 test(PREP0 "NUL:" , "NUL" , NULL);
455 test(PREP1 "NUL:" , "NUL:" , "NUL:");
456 test(PREP2 "NUL:" , "NUL:" , "NUL:");
457 test(PREP0 "CON" , "CON" , NULL);
458 // NOTE: RtlDosPathNameToNtPathName_U (as currently tested) fails for
459 // the input "\\.\CON" on two widely different Windows versions.
460// test(PREP1 "CON" , "CON" , "CON");
461 test(PREP2 "CON" , "CON" , "CON");
462 test(PREP0 "CON:" , "CON" , NULL);
463 test(PREP1 "CON:" , "CON:" , "CON:");
464 test(PREP2 "CON:" , "CON:" , "CON:");
465
466 sprintf(szTmp, "%s\\%s", cd.szCD, "NUL:\\");
467 test(PREP0 "NUL:\\" , szTmp , NULL);
468 test(PREP1 "NUL:\\" , "NUL:\\" , NULL);
469 test(PREP2 "NUL:\\" , "NUL:\\" , NULL);
470 test(PREP0 "C:NUL" , "NUL" , NULL);
471 test(PREP1 "C:NUL" , "C:NUL" , "C:NUL");
472 test(PREP2 "C:NUL" , "C:NUL" , "C:NUL");
473 test(PREP0 "C:\\NUL" , "NUL" , NULL);
474 test(PREP1 "C:\\NUL" , "C:\\NUL" , "NUL");
475 test(PREP2 "C:\\NUL" , "C:\\NUL" , "NUL");
476 test(PREP0 "C:\\NUL\\" , "C:\\NUL\\" , NULL);
477 test(PREP1 "C:\\NUL\\" , "C:\\NUL\\" , NULL);
478 test(PREP2 "C:\\NUL\\" , "C:\\NUL\\" , NULL);
479
480 // root-paths
481 test(PREP0 "\\" , cd.szCurDriveSlash, NULL);
482 test(PREP1 "\\" , "" , NULL);
483 test(PREP2 "\\" , "\\" , NULL);
484
485 test(PREP0 "\\." , cd.szCurDriveSlash, NULL);
486 test(PREP1 "\\." , "" , NULL);
487 test(PREP2 "\\." , "\\." , ".");
488
489 test(PREP0 "\\.." , cd.szCurDriveSlash, NULL);
490 test(PREP1 "\\.." , "" , NULL);
491 test(PREP2 "\\.." , "\\.." , "..");
492
493 test(PREP0 "\\..." , cd.szCurDriveSlash, NULL);
494 test(PREP1 "\\..." , "" , NULL);
495 test(PREP2 "\\..." , "\\..." , "...");
496
497 // malformed
498 sprintf(szTmp, "%s%s", cd.szCurDrive, "\\C:");
499 test(PREP0 "\\C:" , szTmp , "C:");
500 test(PREP1 "\\C:" , "C:" , "C:");
501 test(PREP2 "\\C:" , "\\C:" , "C:");
502
503 sprintf(szTmp, "%s%s", cd.szCurDrive, "\\C:\\");
504 test(PREP0 "\\C:\\" , szTmp , NULL);
505 test(PREP1 "\\C:\\" , "C:\\" , NULL);
506 test(PREP2 "\\C:\\" , "\\C:\\" , NULL);
507
508 // UNC paths
509 test(PREP0 "\\\\" , "UNC\\" , NULL);
510 test(PREP1 "\\\\" , "" , NULL);
511 test(PREP2 "\\\\" , "\\\\" , NULL);
512 test(PREP0 "\\\\\\" , "UNC\\\\" , NULL);
513 test(PREP1 "\\\\\\" , "" , NULL);
514 test(PREP2 "\\\\\\" , "\\\\\\" , NULL);
515 test(PREP0 "\\\\foo" , "UNC\\foo" , NULL);
516 test(PREP1 "\\\\foo" , "foo" , "foo");
517 test(PREP2 "\\\\foo" , "\\\\foo" , "foo");
518
519 test(PREP0 "\\\\foo\\.." , "UNC\\foo\\" , NULL);
520 test(PREP1 "\\\\foo\\.." , "" , NULL);
521 test(PREP2 "\\\\foo\\.." , "\\\\foo\\.." , "..");
522
523 test(PREP0 "\\\\foo\\" , "UNC\\foo\\" , NULL);
524 test(PREP1 "\\\\foo\\" , "foo\\" , NULL);
525 test(PREP2 "\\\\foo\\" , "\\\\foo\\" , NULL);
526 test(PREP0 "\\\\f\\b" , "UNC\\f\\b" , NULL);
527 test(PREP1 "\\\\f\\b" , "f\\b" , "b");
528 test(PREP2 "\\\\f\\b" , "\\\\f\\b" , "b");
529 test(PREP0 "\\\\f\\b\\" , "UNC\\f\\b\\" , NULL);
530 test(PREP1 "\\\\f\\b\\" , "f\\b\\" , NULL);
531 test(PREP2 "\\\\f\\b\\" , "\\\\f\\b\\" , NULL);
532
533 test(PREP0 "\\\\f\\b\\.." , "UNC\\f\\b" , NULL);
534 test(PREP1 "\\\\f\\b\\.." , "f" , "f");
535 test(PREP2 "\\\\f\\b\\.." , "\\\\f\\b\\.." , "..");
536
537 // strange UNC-paths
538 test(PREP0 "\\\\C:" , "UNC\\C:" , NULL);
539 test(PREP1 "\\\\C:" , "C:" , "C:");
540 test(PREP2 "\\\\C:" , "\\\\C:" , "C:");
541 test(PREP0 "\\\\C:\\" , "UNC\\C:\\" , NULL);
542 test(PREP1 "\\\\C:\\" , "C:\\" , NULL);
543 test(PREP2 "\\\\C:\\" , "\\\\C:\\" , NULL);
544 test(PREP0 "\\\\NUL" , "UNC\\NUL" , NULL);
545 test(PREP1 "\\\\NUL" , "NUL" , "NUL");
546 test(PREP2 "\\\\NUL" , "\\\\NUL" , "NUL");
547 test(PREP0 "\\\\NUL:" , "UNC\\NUL:" , NULL);
548 test(PREP1 "\\\\NUL:" , "NUL:" , "NUL:");
549 test(PREP2 "\\\\NUL:" , "\\\\NUL:" , "NUL:");
550 test(PREP0 "\\\\NUL:\\" , "UNC\\NUL:\\" , NULL);
551 test(PREP1 "\\\\NUL:\\" , "NUL:\\" , NULL);
552 test(PREP2 "\\\\NUL:\\" , "\\\\NUL:\\" , NULL);
553
554 // UNC + forward slashes
555 test(PREP0 "//" , "UNC\\" , NULL);
556 test(PREP1 "//" , "" , NULL);
557 test(PREP2 "//" , "//" , "//");
558 test(PREP0 "//C:" , "UNC\\C:" , NULL);
559 test(PREP1 "//C:" , "C:" , "C:");
560 test(PREP2 "//C:" , "//C:" , "//C:");
561 test(PREP0 "//C:/" , "UNC\\C:\\" , NULL);
562 test(PREP1 "//C:/" , "C:\\" , NULL);
563 test(PREP2 "//C:/" , "//C:/" , "//C:/");
564 test(PREP0 "//." , "" , NULL);
565 test(PREP1 "//." , "" , NULL);
566 test(PREP2 "//." , "//." , "//.");
567 test(PREP0 "//.." , "UNC\\" , NULL);
568 test(PREP1 "//.." , "" , NULL);
569 test(PREP2 "//.." , "//.." , "//..");
570 test(PREP0 "/./" , cd.szCurDriveSlash, NULL);
571 test(PREP1 "/./" , "" , NULL);
572 test(PREP2 "/./" , "/./" , "/./");
573 test(PREP0 "//./" , "" , NULL);
574 test(PREP1 "//./" , "" , NULL);
575 test(PREP2 "//./" , "//./" , "//./");
576
577 test(cd.szCD , cd.szCD , cd.pszLastCDComponent);
578 test(cd.szCDPlusSlash , cd.szCDPlusSlash , NULL);
579
580#if 0
581 // The following tests are "problematic", as they return results based on
582 // what your CD on C: is, whether or not you actually run the program
583 // from C:. For that reason, they are currently disabled.
584 test(PREP0 "C:" , "C:\\"+C_curdir , C_curdir);
585 test(PREP0 "C:NUL\\" , "C:\\"+C_curdir+"\\NUL\\" , NULL);
586#endif
587
588#if 0 // Disabled due to... see the comment inside the block.
589 {
590 char szExp[32];
591 BOOL bValid = FALSE;
592 char szPrepend[32];
593 szPrepend[0] = 0;
594 // Strictly speaking, this "Should Never Happen(tm)", calling
595 // RtlDosPathNameToNtPathName_U with a source already formed as
596 // a full NT name ("\??\"), why it's not the end of the world
597 // that this test is currently disabled.
598 //
599 // Some versions of Windows prepends driveletter + colon
600 // for the process' current volume.
601 // Prepending curdrive is most likely a bug that got fixed in
602 // later versions of Windows, but for compatibility it may
603 // become a requirement to "shim" this.
604 //
605 // Known operating systems prepending "Z:\??\" (assuming the
606 // process' CD is on the volume Z:):
607 // - XP sp2.
608 //
609 // Known operating systems not prepending:
610 // - Win7 64 (as 32-bit)
611 if (WinVerMaj == 5) {
612 sprintf(szPrepend, "%s\\??\\", cd.szCurDrive);
613 }
614
615 sprintf(szExp, "%s%s", szPrepend, "C:");
616 test("\\??\\C:", szExp, "C:");
617
618 sprintf(szExp, "%s%s", szPrepend, "C:\\");
619 test("\\??\\C:\\", szExp, NULL);
620
621}
622#endif
623
624#ifndef COMPILE_AS_ROSTEST
625 return 0;
626#endif
627}
628
#define NtCurrentPeb()
Definition: FLS.c:22
static void InitDirComponents(DirComponents *p)
InitDirComponents & cd
char szTmp[518]
static void check_result(BOOLEAN bOK, const char *pszErr)
unsigned char BOOLEAN
Definition: actypes.h:127
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define GetProcAddress(x, y)
Definition: compat.h:753
PPEB Peb
Definition: dllmain.c:27
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
#define __stdcall
Definition: corecrt.h:120
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3303
#define L(x)
Definition: resources.c:13
int main()
Definition: test.c:6
void test2()
Definition: ehthrow.cxx:284
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
struct _UNICODE_STRING UNICODE_STRING
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define printf
Definition: freeldr.h:103
GLfloat GLfloat p
Definition: glext.h:8902
#define HIBYTE(W)
Definition: jmemdos.c:486
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf
Definition: sprintf.c:45
#define _swprintf(buf, format,...)
Definition: sprintf.c:56
VOID NTAPI RtlReleaseRelativeName(_In_ PRTL_RELATIVE_NAME_U RelativeName)
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
struct _RTLP_CURDIR_REF * PRTLP_CURDIR_REF
struct _RTL_RELATIVE_NAME_U RTL_RELATIVE_NAME_U
struct _RTLP_CURDIR_REF RTLP_CURDIR_REF
struct _RTL_RELATIVE_NAME_U * PRTL_RELATIVE_NAME_U
#define DWORD
Definition: nt_native.h:44
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define LOWORD(l)
Definition: pedump.c:82
short WCHAR
Definition: pedump.c:58
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define test
Definition: rosglue.h:37
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
#define exit(n)
Definition: config.h:202
ULONG OSMinorVersion
Definition: ntddk_ex.h:301
ULONG OSMajorVersion
Definition: ntddk_ex.h:300
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
const uint16_t * LPCWSTR
Definition: typedefs.h:57
_In_ WDFDMATRANSACTION _In_ size_t MaximumLength
#define LoadLibrary
Definition: winbase.h:3583
#define GetCurrentDirectory
Definition: winbase.h:3526
unsigned char BYTE
Definition: xxhash.c:193