2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for RtlGetFullPathName_UstrEx
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
8 #define WIN32_NO_STATUS
10 #include <wine/test.h>
11 #include <pseh/pseh2.h>
12 #include <ndk/rtlfuncs.h>
17 RtlGetFullPathName_UstrEx(
18 IN PUNICODE_STRING FileName,
19 IN PUNICODE_STRING StaticString,
20 IN PUNICODE_STRING DynamicString,
21 IN PUNICODE_STRING *StringUsed,
22 IN PSIZE_T FilePartSize OPTIONAL,
23 OUT PBOOLEAN NameInvalid,
24 OUT RTL_PATH_TYPE* PathType,
25 OUT PSIZE_T LengthNeeded OPTIONAL
31 *pRtlGetFullPathName_UstrEx
)(
32 IN PUNICODE_STRING FileName
,
33 IN PUNICODE_STRING StaticString
,
34 IN PUNICODE_STRING DynamicString
,
35 IN PUNICODE_STRING
*StringUsed
,
36 IN PSIZE_T FilePartSize OPTIONAL
,
37 OUT PBOOLEAN NameInvalid
,
38 OUT RTL_PATH_TYPE
* PathType
,
39 OUT PSIZE_T LengthNeeded OPTIONAL
42 #define StartSeh() ExceptionStatus = STATUS_SUCCESS; _SEH2_TRY {
43 #define EndSeh(ExpectedStatus) } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExceptionStatus = _SEH2_GetExceptionCode(); } _SEH2_END; ok(ExceptionStatus == ExpectedStatus, "Exception %lx, expected %lx\n", ExceptionStatus, ExpectedStatus)
45 #define ok_eq_ustr(str1, str2) do { \
46 ok((str1)->Buffer == (str2)->Buffer, "Buffer modified\n"); \
47 ok((str1)->Length == (str2)->Length, "Length modified\n"); \
48 ok((str1)->MaximumLength == (str2)->MaximumLength, "MaximumLength modified\n"); \
54 PCUNICODE_STRING String
,
57 SIZE_T ExpectedLength
= wcslen(Expected
) * sizeof(WCHAR
);
59 BOOLEAN Result
= TRUE
;
62 if (String
->Length
!= ExpectedLength
)
64 ok(0, "String length is %u, expected %lu\n", String
->Length
, (ULONG
)ExpectedLength
);
68 EqualLength
= RtlCompareMemory(String
->Buffer
, Expected
, ExpectedLength
);
69 if (EqualLength
!= ExpectedLength
)
71 ok(0, "String is '%wZ', expected '%S'\n", String
, Expected
);
75 if (String
->Buffer
[String
->Length
/ sizeof(WCHAR
)] != UNICODE_NULL
)
77 ok(0, "Not null terminated\n");
81 /* the function nulls the rest of the buffer! */
82 for (i
= String
->Length
+ sizeof(UNICODE_NULL
); i
< String
->MaximumLength
; i
++)
84 UCHAR Char
= ((PUCHAR
)String
->Buffer
)[i
];
87 ok(0, "Found 0x%x at offset %lu, expected 0x%x\n", Char
, (ULONG
)i
, 0);
88 /* don't count this as a failure unless the string was actually wrong */
90 /* don't flood the log */
105 PUCHAR Array
= Buffer
;
108 for (i
= 0; i
< Size
; i
++)
109 if (Array
[i
] != Value
)
111 trace("Expected %x, found %x at offset %lu\n", Value
, Array
[i
], (ULONG
)i
);
117 #define RtlPathTypeNotSet 123
118 #define InvalidPointer ((PVOID)0x0123456789ABCDEFULL)
120 /* winetest_platform is "windows" for us, so broken() doesn't do what it should :( */
129 PrefixCurrentPathWithoutLastPart
136 /* TODO: don't duplicate this in the other tests */
137 /* TODO: Drive Relative tests don't work yet if the current drive isn't C: */
141 PREFIX_TYPE PrefixType
;
143 RTL_PATH_TYPE PathType
;
144 PREFIX_TYPE FilePartPrefixType
;
148 { L
"C:", PrefixCurrentPath
, L
"", RtlPathTypeDriveRelative
, PrefixCurrentPathWithoutLastPart
},
149 { L
"C:\\", PrefixNone
, L
"C:\\", RtlPathTypeDriveAbsolute
},
150 { L
"C:\\test", PrefixNone
, L
"C:\\test", RtlPathTypeDriveAbsolute
, PrefixCurrentDrive
},
151 { L
"C:\\test\\", PrefixNone
, L
"C:\\test\\", RtlPathTypeDriveAbsolute
},
152 { L
"C:/test/", PrefixNone
, L
"C:\\test\\", RtlPathTypeDriveAbsolute
},
154 { L
"C:\\\\test", PrefixNone
, L
"C:\\test", RtlPathTypeDriveAbsolute
, PrefixCurrentDrive
},
155 { L
"test", PrefixCurrentPath
, L
"\\test", RtlPathTypeRelative
, PrefixCurrentPath
, sizeof(WCHAR
) },
156 { L
"\\test", PrefixCurrentDrive
, L
"test", RtlPathTypeRooted
, PrefixCurrentDrive
},
157 { L
"/test", PrefixCurrentDrive
, L
"test", RtlPathTypeRooted
, PrefixCurrentDrive
},
158 { L
".\\test", PrefixCurrentPath
, L
"\\test", RtlPathTypeRelative
, PrefixCurrentPath
, sizeof(WCHAR
) },
160 { L
"\\.", PrefixCurrentDrive
, L
"", RtlPathTypeRooted
},
161 { L
"\\.\\", PrefixCurrentDrive
, L
"", RtlPathTypeRooted
},
162 { L
"\\\\.", PrefixNone
, L
"\\\\.\\", RtlPathTypeRootLocalDevice
},
163 { L
"\\\\.\\", PrefixNone
, L
"\\\\.\\", RtlPathTypeLocalDevice
},
164 { L
"\\\\.\\Something\\", PrefixNone
, L
"\\\\.\\Something\\", RtlPathTypeLocalDevice
},
166 { L
"\\??\\", PrefixCurrentDrive
, L
"??\\", RtlPathTypeRooted
},
167 { L
"\\??\\C:", PrefixCurrentDrive
, L
"??\\C:", RtlPathTypeRooted
, PrefixCurrentDrive
, 3 * sizeof(WCHAR
) },
168 { L
"\\??\\C:\\", PrefixCurrentDrive
, L
"??\\C:\\", RtlPathTypeRooted
},
169 { L
"\\??\\C:\\test", PrefixCurrentDrive
, L
"??\\C:\\test", RtlPathTypeRooted
, PrefixCurrentDrive
, 6 * sizeof(WCHAR
) },
170 { L
"\\??\\C:\\test\\", PrefixCurrentDrive
, L
"??\\C:\\test\\", RtlPathTypeRooted
},
172 { L
"\\\\??\\", PrefixNone
, L
"\\\\??\\", RtlPathTypeUncAbsolute
},
173 { L
"\\\\??\\C:", PrefixNone
, L
"\\\\??\\C:", RtlPathTypeUncAbsolute
},
174 { L
"\\\\??\\C:\\", PrefixNone
, L
"\\\\??\\C:\\", RtlPathTypeUncAbsolute
},
175 { L
"\\\\??\\C:\\test", PrefixNone
, L
"\\\\??\\C:\\test", RtlPathTypeUncAbsolute
, PrefixNone
, sizeof(L
"\\\\??\\C:\\") },
176 { L
"\\\\??\\C:\\test\\", PrefixNone
, L
"\\\\??\\C:\\test\\", RtlPathTypeUncAbsolute
},
178 NTSTATUS Status
, ExceptionStatus
;
179 UNICODE_STRING FileName
;
180 UNICODE_STRING FullPathName
;
181 WCHAR FullPathNameBuffer
[MAX_PATH
];
182 UNICODE_STRING TempString
;
183 PUNICODE_STRING StringUsed
;
186 RTL_PATH_TYPE PathType
;
188 WCHAR ExpectedPathName
[MAX_PATH
];
189 SIZE_T ExpectedFilePartSize
;
190 const INT TestCount
= sizeof(TestCases
) / sizeof(TestCases
[0]);
194 for (i
= 0; i
< TestCount
; i
++)
196 trace("i = %d\n", i
);
197 switch (TestCases
[i
].PrefixType
)
200 ExpectedPathName
[0] = UNICODE_NULL
;
202 case PrefixCurrentDrive
:
203 GetCurrentDirectoryW(sizeof(ExpectedPathName
) / sizeof(WCHAR
), ExpectedPathName
);
204 ExpectedPathName
[3] = UNICODE_NULL
;
206 case PrefixCurrentPath
:
209 Length
= GetCurrentDirectoryW(sizeof(ExpectedPathName
) / sizeof(WCHAR
), ExpectedPathName
);
210 if (Length
== 3 && TestCases
[i
].FullPathName
[0])
211 ExpectedPathName
[2] = UNICODE_NULL
;
215 skip(0, "Invalid test!\n");
218 wcscat(ExpectedPathName
, TestCases
[i
].FullPathName
);
219 RtlInitUnicodeString(&FileName
, TestCases
[i
].FileName
);
220 RtlInitEmptyUnicodeString(&FullPathName
, FullPathNameBuffer
, sizeof(FullPathNameBuffer
));
221 RtlFillMemory(FullPathName
.Buffer
, FullPathName
.MaximumLength
, 0xAA);
222 TempString
= FileName
;
223 PathType
= RtlPathTypeNotSet
;
224 StringUsed
= InvalidPointer
;
226 NameInvalid
= (BOOLEAN
)-1;
229 Status
= pRtlGetFullPathName_UstrEx(&FileName
,
237 ok(Status
== STATUS_SUCCESS
, "status = %lx\n", Status
);
238 EndSeh(STATUS_SUCCESS
);
239 ok_eq_ustr(&FileName
, &TempString
);
240 ok(FullPathName
.Buffer
== FullPathNameBuffer
, "Buffer modified\n");
241 ok(FullPathName
.MaximumLength
== sizeof(FullPathNameBuffer
), "MaximumLength modified\n");
242 Okay
= CheckStringBuffer(&FullPathName
, ExpectedPathName
);
243 ok(Okay
, "Wrong path name '%wZ', expected '%S'\n", &FullPathName
, ExpectedPathName
);
244 ok(StringUsed
== &FullPathName
, "StringUsed = %p, expected %p\n", StringUsed
, &FullPathName
);
245 switch (TestCases
[i
].FilePartPrefixType
)
248 ExpectedFilePartSize
= 0;
250 case PrefixCurrentDrive
:
251 ExpectedFilePartSize
= sizeof(L
"C:\\");
253 case PrefixCurrentPath
:
254 ExpectedFilePartSize
= GetCurrentDirectoryW(0, NULL
) * sizeof(WCHAR
);
255 if (ExpectedFilePartSize
== sizeof(L
"C:\\"))
256 ExpectedFilePartSize
-= sizeof(WCHAR
);
258 case PrefixCurrentPathWithoutLastPart
:
260 WCHAR CurrentPath
[MAX_PATH
];
262 ExpectedFilePartSize
= GetCurrentDirectoryW(sizeof(CurrentPath
) / sizeof(WCHAR
), CurrentPath
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
263 if (ExpectedFilePartSize
== sizeof(L
"C:\\"))
264 ExpectedFilePartSize
= 0;
267 BackSlash
= wcsrchr(CurrentPath
, L
'\\');
269 ExpectedFilePartSize
-= wcslen(BackSlash
+ 1) * sizeof(WCHAR
);
271 ok(0, "GetCurrentDirectory returned %S\n", CurrentPath
);
276 skip(0, "Invalid test!\n");
279 ExpectedFilePartSize
+= TestCases
[i
].FilePartSize
;
280 if (ExpectedFilePartSize
!= 0)
281 ExpectedFilePartSize
= (ExpectedFilePartSize
- sizeof(UNICODE_NULL
)) / sizeof(WCHAR
);
282 ok(FilePartSize
== ExpectedFilePartSize
,
283 "FilePartSize = %lu, expected %lu\n", (ULONG
)FilePartSize
, (ULONG
)ExpectedFilePartSize
);
284 ok(NameInvalid
== FALSE
, "NameInvalid = %u\n", NameInvalid
);
285 ok(PathType
== TestCases
[i
].PathType
, "PathType = %d, expected %d\n", PathType
, TestCases
[i
].PathType
);
286 ok(LengthNeeded
== 0, "LengthNeeded = %lu\n", (ULONG
)LengthNeeded
);
290 START_TEST(RtlGetFullPathName_UstrEx
)
292 NTSTATUS Status
, ExceptionStatus
;
293 UNICODE_STRING FileName
;
294 UNICODE_STRING TempString
;
295 UNICODE_STRING StaticString
;
296 PUNICODE_STRING StringUsed
;
299 BOOLEAN NameInvalidArray
[sizeof(ULONGLONG
)];
300 RTL_PATH_TYPE PathType
;
304 pRtlGetFullPathName_UstrEx
= (PVOID
)GetProcAddress(GetModuleHandle(L
"ntdll"), "RtlGetFullPathName_UstrEx");
305 if (!pRtlGetFullPathName_UstrEx
)
307 skip("RtlGetFullPathName_UstrEx unavailable\n");
311 /* NULL parameters */
313 pRtlGetFullPathName_UstrEx(NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
314 EndSeh(STATUS_ACCESS_VIOLATION
);
316 RtlInitUnicodeString(&FileName
, NULL
);
317 TempString
= FileName
;
319 pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
320 EndSeh(STATUS_ACCESS_VIOLATION
);
321 ok_eq_ustr(&FileName
, &TempString
);
323 RtlInitUnicodeString(&FileName
, L
"");
324 TempString
= FileName
;
326 pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
327 EndSeh(STATUS_ACCESS_VIOLATION
);
328 ok_eq_ustr(&FileName
, &TempString
);
330 PathType
= RtlPathTypeNotSet
;
332 pRtlGetFullPathName_UstrEx(NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &PathType
, NULL
);
333 EndSeh(STATUS_ACCESS_VIOLATION
);
334 ok(PathType
== RtlPathTypeUnknown
||
335 broken(PathType
== RtlPathTypeNotSet
) /* Win7 */, "PathType = %d\n", PathType
);
337 /* Check what else is initialized before it crashes */
338 PathType
= RtlPathTypeNotSet
;
339 StringUsed
= InvalidPointer
;
341 NameInvalid
= (BOOLEAN
)-1;
344 pRtlGetFullPathName_UstrEx(NULL
, NULL
, NULL
, &StringUsed
, &FilePartSize
, &NameInvalid
, &PathType
, &LengthNeeded
);
345 EndSeh(STATUS_ACCESS_VIOLATION
);
346 ok(StringUsed
== NULL
, "StringUsed = %p\n", StringUsed
);
347 ok(FilePartSize
== 0, "FilePartSize = %lu\n", (ULONG
)FilePartSize
);
348 ok(NameInvalid
== FALSE
, "NameInvalid = %u\n", NameInvalid
);
349 ok(PathType
== RtlPathTypeUnknown
||
350 broken(PathType
== RtlPathTypeNotSet
) /* Win7 */, "PathType = %d\n", PathType
);
351 ok(LengthNeeded
== 0, "LengthNeeded = %lu\n", (ULONG
)LengthNeeded
);
353 RtlInitUnicodeString(&FileName
, L
"");
354 TempString
= FileName
;
355 StringUsed
= InvalidPointer
;
357 NameInvalid
= (BOOLEAN
)-1;
360 pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, &StringUsed
, &FilePartSize
, &NameInvalid
, NULL
, &LengthNeeded
);
361 EndSeh(STATUS_ACCESS_VIOLATION
);
362 ok_eq_ustr(&FileName
, &TempString
);
363 ok(StringUsed
== NULL
, "StringUsed = %p\n", StringUsed
);
364 ok(FilePartSize
== 0, "FilePartSize = %lu\n", (ULONG
)FilePartSize
);
365 ok(NameInvalid
== FALSE
||
366 broken(NameInvalid
== (BOOLEAN
)-1) /* Win7 */, "NameInvalid = %u\n", NameInvalid
);
367 ok(LengthNeeded
== 0, "LengthNeeded = %lu\n", (ULONG
)LengthNeeded
);
369 /* This is the first one that doesn't crash. FileName and PathType cannot be NULL */
370 RtlInitUnicodeString(&FileName
, NULL
);
371 TempString
= FileName
;
372 PathType
= RtlPathTypeNotSet
;
374 Status
= pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, NULL
, NULL
, NULL
, &PathType
, NULL
);
375 ok(Status
== STATUS_OBJECT_NAME_INVALID
, "status = %lx\n", Status
);
376 EndSeh(STATUS_SUCCESS
);
377 ok_eq_ustr(&FileName
, &TempString
);
378 ok(PathType
== RtlPathTypeUnknown
, "PathType = %d\n", PathType
);
380 RtlInitUnicodeString(&FileName
, L
"");
381 TempString
= FileName
;
382 PathType
= RtlPathTypeNotSet
;
384 Status
= pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, NULL
, NULL
, NULL
, &PathType
, NULL
);
385 ok(Status
== STATUS_OBJECT_NAME_INVALID
, "status = %lx\n", Status
);
386 EndSeh(STATUS_SUCCESS
);
387 ok_eq_ustr(&FileName
, &TempString
);
388 ok(PathType
== RtlPathTypeUnknown
, "PathType = %d\n", PathType
);
390 /* Show that NameInvalid is indeed BOOLEAN */
391 RtlInitUnicodeString(&FileName
, L
"");
392 TempString
= FileName
;
393 PathType
= RtlPathTypeNotSet
;
394 RtlFillMemory(NameInvalidArray
, sizeof(NameInvalidArray
), 0x55);
396 Status
= pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, NULL
, NULL
, NameInvalidArray
, &PathType
, NULL
);
397 ok(Status
== STATUS_OBJECT_NAME_INVALID
, "status = %lx\n", Status
);
398 EndSeh(STATUS_SUCCESS
);
399 ok_eq_ustr(&FileName
, &TempString
);
400 ok(PathType
== RtlPathTypeUnknown
, "PathType = %d\n", PathType
);
401 ok(NameInvalidArray
[0] == FALSE
, "NameInvalid = %u\n", NameInvalidArray
[0]);
402 Okay
= CheckBuffer(NameInvalidArray
+ 1, sizeof(NameInvalidArray
) - sizeof(NameInvalidArray
[0]), 0x55);
403 ok(Okay
, "CheckBuffer failed\n");
405 /* Give it a valid path */
406 RtlInitUnicodeString(&FileName
, L
"C:\\test");
407 TempString
= FileName
;
408 PathType
= RtlPathTypeNotSet
;
410 Status
= pRtlGetFullPathName_UstrEx(&FileName
, NULL
, NULL
, NULL
, NULL
, NULL
, &PathType
, NULL
);
411 ok(Status
== STATUS_BUFFER_TOO_SMALL
, "status = %lx\n", Status
);
412 EndSeh(STATUS_SUCCESS
);
413 ok_eq_ustr(&FileName
, &TempString
);
414 ok(PathType
== RtlPathTypeDriveAbsolute
, "PathType = %d\n", PathType
);
416 /* Zero-length static string */
417 RtlInitUnicodeString(&FileName
, L
"C:\\test");
418 TempString
= FileName
;
419 RtlInitUnicodeString(&StaticString
, NULL
);
420 PathType
= RtlPathTypeNotSet
;
422 Status
= pRtlGetFullPathName_UstrEx(&FileName
, &StaticString
, NULL
, NULL
, NULL
, NULL
, &PathType
, NULL
);
423 ok(Status
== STATUS_BUFFER_TOO_SMALL
, "status = %lx\n", Status
);
424 EndSeh(STATUS_SUCCESS
);
425 ok_eq_ustr(&FileName
, &TempString
);
426 ok(PathType
== RtlPathTypeDriveAbsolute
, "PathType = %d\n", PathType
);
428 /* TODO: play around with StaticString and DynamicString */
430 /* Check the actual functionality with different paths */