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"
23 static NTSTATUS (WINAPI
*pRtlMultiByteToUnicodeN
)( LPWSTR dst
, DWORD dstlen
, LPDWORD reslen
,
24 LPCSTR src
, DWORD srclen
);
25 static NTSTATUS (WINAPI
*pRtlUnicodeToMultiByteN
)(LPSTR
,DWORD
,LPDWORD
,LPCWSTR
,DWORD
);
26 static UINT (WINAPI
*pRtlDetermineDosPathNameType_U
)( PCWSTR path
);
27 static ULONG (WINAPI
*pRtlIsDosDeviceName_U
)( PCWSTR dos_name
);
28 static NTSTATUS (WINAPI
*pRtlOemStringToUnicodeString
)(UNICODE_STRING
*, const STRING
*, BOOLEAN
);
29 static BOOLEAN (WINAPI
*pRtlIsNameLegalDOS8Dot3
)(const UNICODE_STRING
*,POEM_STRING
,PBOOLEAN
);
30 static DWORD (WINAPI
*pRtlGetFullPathName_U
)(const WCHAR
*,ULONG
,WCHAR
*,WCHAR
**);
31 static NTSTATUS (WINAPI
*pRtlDosPathNameToNtPathName_U_WithStatus
)(const WCHAR
*, UNICODE_STRING
*, WCHAR
**, CURDIR
*);
33 static void test_RtlDetermineDosPathNameType_U(void)
41 static const struct test tests
[] =
74 const struct test
*test
;
75 WCHAR buffer
[MAX_PATH
];
78 if (!pRtlDetermineDosPathNameType_U
)
80 win_skip("RtlDetermineDosPathNameType_U is not available\n");
84 for (test
= tests
; test
->path
; test
++)
86 pRtlMultiByteToUnicodeN( buffer
, sizeof(buffer
), NULL
, test
->path
, strlen(test
->path
)+1 );
87 ret
= pRtlDetermineDosPathNameType_U( buffer
);
88 ok( ret
== test
->ret
, "Wrong result %d/%d for %s\n", ret
, test
->ret
, test
->path
);
93 static void test_RtlIsDosDeviceName_U(void)
103 static const struct test tests
[] =
105 { "\\\\.\\CON", 8, 6, TRUE
}, /* fails on win8 */
106 { "\\\\.\\con", 8, 6, TRUE
}, /* fails on win8 */
107 { "\\\\.\\CON2", 0, 0 },
109 { "\\\\foo\\nul", 0, 0 },
110 { "c:\\nul:", 6, 6 },
111 { "c:\\nul\\", 0, 0 },
112 { "c:\\nul\\foo", 0, 0 },
113 { "c:\\nul::", 6, 6, TRUE
}, /* fails on nt4 */
114 { "c:\\nul::::::", 6, 6, TRUE
}, /* fails on nt4 */
116 { "c:prn.......", 4, 6 },
117 { "c:prn... ...", 4, 6 },
118 { "c:NUL .... ", 4, 6, TRUE
}, /* fails on nt4 */
119 { "c: . . .", 0, 0 },
121 { " . . . :", 0, 0 },
123 { "c:nul. . . :", 4, 6 },
124 { "c:nul . . :", 4, 6, TRUE
}, /* fails on nt4 */
126 { "c:prn:aaa", 4, 6, TRUE
}, /* fails on win9x */
127 { "c:PRN:.txt", 4, 6 },
128 { "c:aux:.txt...", 4, 6 },
129 { "c:prn:.txt:", 4, 6 },
130 { "c:nul:aaa", 4, 6, TRUE
}, /* fails on win9x */
136 { "c:\\lpt0.txt", 0, 0 },
137 { "c:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
138 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
139 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
140 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
141 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
142 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
143 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nul.txt", 1000, 6 },
147 const struct test
*test
;
151 if (!pRtlIsDosDeviceName_U
)
153 win_skip("RtlIsDosDeviceName_U is not available\n");
157 for (test
= tests
; test
->path
; test
++)
159 pRtlMultiByteToUnicodeN( buffer
, sizeof(buffer
), NULL
, test
->path
, strlen(test
->path
)+1 );
160 ret
= pRtlIsDosDeviceName_U( buffer
);
161 ok( ret
== MAKELONG( test
->len
, test
->pos
) ||
162 (test
->fails
&& broken( ret
== 0 )),
163 "Wrong result (%d,%d)/(%d,%d) for %s\n",
164 HIWORD(ret
), LOWORD(ret
), test
->pos
, test
->len
, test
->path
);
168 static void test_RtlIsNameLegalDOS8Dot3(void)
177 static const struct test tests
[] =
179 { "12345678", TRUE
, FALSE
},
180 { "123 5678", TRUE
, TRUE
},
181 { "12345678.", FALSE
, 2 /*not set*/ },
182 { "1234 678.", FALSE
, 2 /*not set*/ },
183 { "12345678.a", TRUE
, FALSE
},
184 { "12345678.a ", FALSE
, 2 /*not set*/ },
185 { "12345678.a c", TRUE
, TRUE
},
186 { " 2345678.a ", FALSE
, 2 /*not set*/ },
187 { "1 345678.abc", TRUE
, TRUE
},
188 { "1 8.a c", TRUE
, TRUE
},
189 { "1 3 5 7 .abc", FALSE
, 2 /*not set*/ },
190 { "12345678. c", TRUE
, TRUE
},
191 { "123456789.a", FALSE
, 2 /*not set*/ },
192 { "12345.abcd", FALSE
, 2 /*not set*/ },
193 { "12345.ab d", FALSE
, 2 /*not set*/ },
194 { ".abc", FALSE
, 2 /*not set*/ },
195 { "12.abc.d", FALSE
, 2 /*not set*/ },
196 { ".", TRUE
, FALSE
},
197 { "..", TRUE
, FALSE
},
198 { "...", FALSE
, 2 /*not set*/ },
199 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", FALSE
, 2 /*not set*/ },
203 const struct test
*test
;
205 OEM_STRING oem
, oem_ret
;
210 if (!pRtlIsNameLegalDOS8Dot3
)
212 win_skip("RtlIsNameLegalDOS8Dot3 is not available\n");
216 ustr
.MaximumLength
= sizeof(buffer
);
217 ustr
.Buffer
= buffer
;
218 for (test
= tests
; test
->path
; test
++)
221 strcpy(path
, test
->path
);
223 oem
.Length
= strlen(test
->path
);
224 oem
.MaximumLength
= oem
.Length
+ 1;
225 pRtlOemStringToUnicodeString( &ustr
, &oem
, FALSE
);
227 oem_ret
.Length
= oem_ret
.MaximumLength
= sizeof(buff2
);
228 oem_ret
.Buffer
= buff2
;
229 ret
= pRtlIsNameLegalDOS8Dot3( &ustr
, &oem_ret
, &spaces
);
230 ok( ret
== test
->result
, "Wrong result %d/%d for '%s'\n", ret
, test
->result
, test
->path
);
231 ok( spaces
== test
->spaces
, "Wrong spaces value %d/%d for '%s'\n", spaces
, test
->spaces
, test
->path
);
232 if (strlen(test
->path
) <= 12)
236 strcpy( str
, test
->path
);
237 for (i
= 0; str
[i
]; i
++) str
[i
] = toupper(str
[i
]);
238 ok( oem_ret
.Length
== strlen(test
->path
), "Wrong length %d/%d for '%s'\n",
239 oem_ret
.Length
, lstrlenA(test
->path
), test
->path
);
240 ok( !memcmp( oem_ret
.Buffer
, str
, oem_ret
.Length
),
241 "Wrong string '%.*s'/'%s'\n", oem_ret
.Length
, oem_ret
.Buffer
, str
);
245 static void test_RtlGetFullPathName_U(void)
247 static const WCHAR emptyW
[] = {0};
248 static const WCHAR deadbeefW
[] = {'d','e','a','d','b','e','e','f',0};
255 const char *alt_rname
;
256 const char *alt_rfile
;
259 static const struct test tests
[] =
261 { "c:/test", "c:\\test", "test"},
262 { "c:/test ", "c:\\test", "test"},
263 { "c:/test.", "c:\\test", "test"},
264 { "c:/test .... .. ", "c:\\test", "test"},
265 { "c:/test/ .... .. ", "c:\\test\\", NULL
},
266 { "c:/test/..", "c:\\", NULL
},
267 { "c:/test/.. ", "c:\\test\\", NULL
},
268 { "c:/TEST", "c:\\TEST", "TEST"},
269 { "c:/test/file", "c:\\test\\file", "file"},
270 { "c:/test./file", "c:\\test\\file", "file"},
271 { "c:/test.. /file", "c:\\test.. \\file","file"},
272 { "c:/test/././file", "c:\\test\\file", "file"},
273 { "c:/test\\.\\.\\file", "c:\\test\\file", "file"},
274 { "c:/test/\\.\\.\\file", "c:\\test\\file", "file"},
275 { "c:/test\\\\.\\.\\file", "c:\\test\\file", "file"},
276 { "c:/test\\test1\\..\\.\\file", "c:\\test\\file", "file"},
277 { "c:///test\\.\\.\\file//", "c:\\test\\file\\", NULL
,
278 "c:\\test\\file", "file"}, /* nt4 */
279 { "c:///test\\..\\file\\..\\//", "c:\\", NULL
},
280 { "c:/test../file", "c:\\test.\\file", "file",
281 "c:\\test..\\file", "file"}, /* vista */
282 { "c:\\test", "c:\\test", "test"},
286 const struct test
*test
;
287 WCHAR pathbufW
[2*MAX_PATH
], rbufferW
[MAX_PATH
];
288 CHAR rbufferA
[MAX_PATH
], rfileA
[MAX_PATH
];
294 if (!pRtlGetFullPathName_U
)
296 win_skip("RtlGetFullPathName_U is not available\n");
300 file_part
= (WCHAR
*)0xdeadbeef;
301 lstrcpyW(rbufferW
, deadbeefW
);
302 ret
= pRtlGetFullPathName_U(NULL
, MAX_PATH
, rbufferW
, &file_part
);
303 ok(!ret
, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret
);
304 ok(!lstrcmpW(rbufferW
, deadbeefW
),
305 "Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW
));
306 ok(file_part
== (WCHAR
*)0xdeadbeef ||
307 file_part
== NULL
, /* Win7 */
308 "Expected file part pointer to be untouched, got %p\n", file_part
);
310 file_part
= (WCHAR
*)0xdeadbeef;
311 lstrcpyW(rbufferW
, deadbeefW
);
312 ret
= pRtlGetFullPathName_U(emptyW
, MAX_PATH
, rbufferW
, &file_part
);
313 ok(!ret
, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret
);
314 ok(!lstrcmpW(rbufferW
, deadbeefW
),
315 "Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW
));
316 ok(file_part
== (WCHAR
*)0xdeadbeef ||
317 file_part
== NULL
, /* Win7 */
318 "Expected file part pointer to be untouched, got %p\n", file_part
);
320 for (test
= tests
; test
->path
; test
++)
322 len
= strlen(test
->rname
) * sizeof(WCHAR
);
323 pRtlMultiByteToUnicodeN(pathbufW
, sizeof(pathbufW
), NULL
, test
->path
, strlen(test
->path
)+1 );
324 ret
= pRtlGetFullPathName_U( pathbufW
,MAX_PATH
, rbufferW
, &file_part
);
325 ok( ret
== len
|| (test
->alt_rname
&& ret
== strlen(test
->alt_rname
)*sizeof(WCHAR
)),
326 "Wrong result %d/%d for \"%s\"\n", ret
, len
, test
->path
);
327 ok(pRtlUnicodeToMultiByteN(rbufferA
,MAX_PATH
,&reslen
,rbufferW
,(lstrlenW(rbufferW
) + 1) * sizeof(WCHAR
)) == STATUS_SUCCESS
,
328 "RtlUnicodeToMultiByteN failed\n");
329 ok(!lstrcmpA(rbufferA
,test
->rname
) || (test
->alt_rname
&& !lstrcmpA(rbufferA
,test
->alt_rname
)),
330 "Got \"%s\" expected \"%s\"\n",rbufferA
,test
->rname
);
333 ok(pRtlUnicodeToMultiByteN(rfileA
,MAX_PATH
,&reslen
,file_part
,(lstrlenW(file_part
) + 1) * sizeof(WCHAR
)) == STATUS_SUCCESS
,
334 "RtlUnicodeToMultiByteN failed\n");
335 ok((test
->rfile
&& !lstrcmpA(rfileA
,test
->rfile
)) ||
336 (test
->alt_rfile
&& !lstrcmpA(rfileA
,test
->alt_rfile
)),
337 "Got \"%s\" expected \"%s\"\n",rfileA
,test
->rfile
);
341 ok( !test
->rfile
, "Got NULL expected \"%s\"\n", test
->rfile
);
346 static void test_RtlDosPathNameToNtPathName_U_WithStatus(void)
348 static const WCHAR emptyW
[] = { 0 };
349 WCHAR path
[MAX_PATH
];
350 UNICODE_STRING nameW
;
353 if (!pRtlDosPathNameToNtPathName_U_WithStatus
)
355 win_skip("RtlDosPathNameToNtPathName_U_WithStatus() is not supported.\n");
359 GetCurrentDirectoryW( MAX_PATH
, path
);
361 status
= pRtlDosPathNameToNtPathName_U_WithStatus( path
, &nameW
, NULL
, NULL
);
362 ok(!status
, "Failed convert to nt path, %#x.\n", status
);
364 status
= pRtlDosPathNameToNtPathName_U_WithStatus( NULL
, &nameW
, NULL
, NULL
);
365 ok(status
== STATUS_OBJECT_NAME_INVALID
|| broken(status
== STATUS_OBJECT_PATH_NOT_FOUND
) /* W2k3 */,
366 "Unexpected status %#x.\n", status
);
368 status
= pRtlDosPathNameToNtPathName_U_WithStatus( emptyW
, &nameW
, NULL
, NULL
);
369 ok(status
== STATUS_OBJECT_NAME_INVALID
|| broken(status
== STATUS_OBJECT_PATH_NOT_FOUND
) /* W2k3 */,
370 "Unexpected status %#x.\n", status
);
372 RtlFreeUnicodeString( &nameW
);
377 HMODULE mod
= GetModuleHandleA("ntdll.dll");
380 win_skip("Not running on NT, skipping tests\n");
384 pRtlMultiByteToUnicodeN
= (void *)GetProcAddress(mod
,"RtlMultiByteToUnicodeN");
385 pRtlUnicodeToMultiByteN
= (void *)GetProcAddress(mod
,"RtlUnicodeToMultiByteN");
386 pRtlDetermineDosPathNameType_U
= (void *)GetProcAddress(mod
,"RtlDetermineDosPathNameType_U");
387 pRtlIsDosDeviceName_U
= (void *)GetProcAddress(mod
,"RtlIsDosDeviceName_U");
388 pRtlOemStringToUnicodeString
= (void *)GetProcAddress(mod
,"RtlOemStringToUnicodeString");
389 pRtlIsNameLegalDOS8Dot3
= (void *)GetProcAddress(mod
,"RtlIsNameLegalDOS8Dot3");
390 pRtlGetFullPathName_U
= (void *)GetProcAddress(mod
,"RtlGetFullPathName_U");
391 pRtlDosPathNameToNtPathName_U_WithStatus
= (void *)GetProcAddress(mod
, "RtlDosPathNameToNtPathName_U_WithStatus");
393 test_RtlDetermineDosPathNameType_U();
394 test_RtlIsDosDeviceName_U();
395 test_RtlIsNameLegalDOS8Dot3();
396 test_RtlGetFullPathName_U();
397 test_RtlDosPathNameToNtPathName_U_WithStatus();