[NTDLL_APITEST]
[reactos.git] / rostests / apitests / ntdll / RtlGetFullPathName_Ustr.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for RtlGetFullPathName_Ustr
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
6 */
7
8 #define WIN32_NO_STATUS
9 #include <wine/test.h>
10 #include <pseh/pseh2.h>
11 #include <ndk/rtlfuncs.h>
12
13 /*
14 ULONG
15 NTAPI
16 RtlGetFullPathName_Ustr(
17 IN PCUNICODE_STRING FileName,
18 IN ULONG Size,
19 IN PWSTR Buffer,
20 OUT PCWSTR *ShortName,
21 OUT PBOOLEAN InvalidName,
22 OUT RTL_PATH_TYPE* PathType
23 );
24 */
25
26 /* This seems to be a struct of some kind in Windows 7... returns 0 or 32 in the second member */
27 typedef struct _PATH_TYPE_AND_UNKNOWN
28 {
29 RTL_PATH_TYPE Type;
30 ULONG Unknown;
31 } PATH_TYPE_AND_UNKNOWN;
32
33 static
34 ULONG
35 (NTAPI
36 *RtlGetFullPathName_Ustr)(
37 IN PCUNICODE_STRING FileName,
38 IN ULONG Size,
39 IN PWSTR Buffer,
40 OUT PCWSTR *ShortName,
41 OUT PBOOLEAN InvalidName,
42 OUT PATH_TYPE_AND_UNKNOWN* PathType
43 )
44 //= (PVOID)0x7c83086c // 2003 sp1 x86
45 //= (PVOID)0x7769a3dd // win7 sp1 wow64
46 ;
47
48 #define StartSeh() ExceptionStatus = STATUS_SUCCESS; _SEH2_TRY {
49 #define EndSeh(ExpectedStatus) } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExceptionStatus = _SEH2_GetExceptionCode(); } _SEH2_END; ok(ExceptionStatus == ExpectedStatus, "Exception %lx, expected %lx\n", ExceptionStatus, ExpectedStatus)
50
51 #define ok_eq_ustr(str1, str2) do { \
52 ok((str1)->Buffer == (str2)->Buffer, "Buffer modified\n"); \
53 ok((str1)->Length == (str2)->Length, "Length modified\n"); \
54 ok((str1)->MaximumLength == (str2)->MaximumLength, "MaximumLength modified\n"); \
55 } while (0)
56
57 static
58 BOOLEAN
59 CheckStringBuffer(
60 PCWSTR Buffer,
61 ULONG Length,
62 SIZE_T MaximumLength,
63 PCWSTR Expected)
64 {
65 USHORT ExpectedLength = wcslen(Expected) * sizeof(WCHAR);
66 SIZE_T EqualLength;
67 BOOLEAN Result = TRUE;
68 SIZE_T i;
69
70 if (Length != ExpectedLength)
71 {
72 ok(0, "String length is %u, expected %u\n", Length, ExpectedLength);
73 Result = FALSE;
74 }
75
76 EqualLength = RtlCompareMemory(Buffer, Expected, Length);
77 if (EqualLength != Length)
78 {
79 ok(0, "String is '%S', expected '%S'\n", Buffer, Expected);
80 Result = FALSE;
81 }
82
83 if (Buffer[Length / sizeof(WCHAR)] != UNICODE_NULL)
84 {
85 ok(0, "Not null terminated\n");
86 Result = FALSE;
87 }
88
89 /* The function nulls the rest of the buffer! */
90 for (i = Length + sizeof(UNICODE_NULL); i < MaximumLength; i++)
91 {
92 UCHAR Char = ((PUCHAR)Buffer)[i];
93 if (Char != 0)
94 {
95 ok(0, "Found 0x%x at offset %lu, expected 0x%x\n", Char, (ULONG)i, 0);
96 /* Don't count this as a failure unless the string was actually wrong */
97 //Result = FALSE;
98 /* Don't flood the log */
99 break;
100 }
101 }
102
103 return Result;
104 }
105
106 #define RtlPathTypeNotSet 123
107 #define InvalidPointer ((PVOID)0x0123456789ABCDEFULL)
108
109 /* winetest_platform is "windows" for us, so broken() doesn't do what it should :( */
110 #undef broken
111 #define broken(x) 0
112
113 typedef enum
114 {
115 PrefixNone,
116 PrefixCurrentDrive,
117 PrefixCurrentPath,
118 PrefixCurrentPathWithoutLastPart
119 } PREFIX_TYPE;
120
121 static
122 VOID
123 RunTestCases(VOID)
124 {
125 /* TODO: don't duplicate this here and in the RtlGetFullPathName_U test */
126 struct
127 {
128 PCWSTR FileName;
129 PREFIX_TYPE PrefixType;
130 PCWSTR FullPathName;
131 RTL_PATH_TYPE PathType;
132 PREFIX_TYPE FilePartPrefixType;
133 SIZE_T FilePartSize;
134 } TestCases[] =
135 {
136 { L"C:", PrefixCurrentPath, L"", RtlPathTypeDriveRelative, PrefixCurrentPathWithoutLastPart },
137 { L"C:\\", PrefixNone, L"C:\\", RtlPathTypeDriveAbsolute },
138 { L"C:\\test", PrefixNone, L"C:\\test", RtlPathTypeDriveAbsolute, PrefixCurrentDrive },
139 { L"C:\\test\\", PrefixNone, L"C:\\test\\", RtlPathTypeDriveAbsolute },
140 { L"C:/test/", PrefixNone, L"C:\\test\\", RtlPathTypeDriveAbsolute },
141
142 { L"C:\\\\test", PrefixNone, L"C:\\test", RtlPathTypeDriveAbsolute, PrefixCurrentDrive },
143 { L"test", PrefixCurrentPath, L"\\test", RtlPathTypeRelative, PrefixCurrentPath, sizeof(WCHAR) },
144 { L"\\test", PrefixCurrentDrive, L"test", RtlPathTypeRooted, PrefixCurrentDrive },
145 { L"/test", PrefixCurrentDrive, L"test", RtlPathTypeRooted, PrefixCurrentDrive },
146 { L".\\test", PrefixCurrentPath, L"\\test", RtlPathTypeRelative, PrefixCurrentPath, sizeof(WCHAR) },
147
148 { L"\\.", PrefixCurrentDrive, L"", RtlPathTypeRooted },
149 { L"\\.\\", PrefixCurrentDrive, L"", RtlPathTypeRooted },
150 { L"\\\\.", PrefixNone, L"\\\\.\\", RtlPathTypeRootLocalDevice },
151 { L"\\\\.\\", PrefixNone, L"\\\\.\\", RtlPathTypeLocalDevice },
152 { L"\\\\.\\Something\\", PrefixNone, L"\\\\.\\Something\\", RtlPathTypeLocalDevice },
153
154 { L"\\??\\", PrefixCurrentDrive, L"??\\", RtlPathTypeRooted },
155 { L"\\??\\C:", PrefixCurrentDrive, L"??\\C:", RtlPathTypeRooted, PrefixCurrentDrive, 3 * sizeof(WCHAR) },
156 { L"\\??\\C:\\", PrefixCurrentDrive, L"??\\C:\\", RtlPathTypeRooted },
157 { L"\\??\\C:\\test", PrefixCurrentDrive, L"??\\C:\\test", RtlPathTypeRooted, PrefixCurrentDrive, 6 * sizeof(WCHAR) },
158 { L"\\??\\C:\\test\\", PrefixCurrentDrive, L"??\\C:\\test\\", RtlPathTypeRooted },
159
160 { L"\\\\??\\", PrefixNone, L"\\\\??\\", RtlPathTypeUncAbsolute },
161 { L"\\\\??\\C:", PrefixNone, L"\\\\??\\C:", RtlPathTypeUncAbsolute },
162 { L"\\\\??\\C:\\", PrefixNone, L"\\\\??\\C:\\", RtlPathTypeUncAbsolute },
163 { L"\\\\??\\C:\\test", PrefixNone, L"\\\\??\\C:\\test", RtlPathTypeUncAbsolute, PrefixNone, sizeof(L"\\\\??\\C:\\") },
164 { L"\\\\??\\C:\\test\\", PrefixNone, L"\\\\??\\C:\\test\\", RtlPathTypeUncAbsolute },
165 };
166 NTSTATUS ExceptionStatus;
167 ULONG Length;
168 UNICODE_STRING FileName;
169 WCHAR FullPathNameBuffer[MAX_PATH];
170 UNICODE_STRING TempString;
171 const WCHAR *ShortName;
172 BOOLEAN NameInvalid;
173 PATH_TYPE_AND_UNKNOWN PathType;
174 WCHAR ExpectedPathName[MAX_PATH];
175 SIZE_T ExpectedFilePartSize;
176 const WCHAR *ExpectedShortName;
177 const INT TestCount = sizeof(TestCases) / sizeof(TestCases[0]);
178 INT i;
179
180 for (i = 0; i < TestCount; i++)
181 {
182 trace("i = %d\n", i);
183 switch (TestCases[i].PrefixType)
184 {
185 case PrefixNone:
186 ExpectedPathName[0] = UNICODE_NULL;
187 break;
188 case PrefixCurrentDrive:
189 GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
190 ExpectedPathName[3] = UNICODE_NULL;
191 break;
192 case PrefixCurrentPath:
193 {
194 ULONG Length;
195 Length = GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
196 if (Length == 3 && TestCases[i].FullPathName[0])
197 ExpectedPathName[2] = UNICODE_NULL;
198 break;
199 }
200 default:
201 skip(0, "Invalid test!\n");
202 continue;
203 }
204 wcscat(ExpectedPathName, TestCases[i].FullPathName);
205 RtlInitUnicodeString(&FileName, TestCases[i].FileName);
206 RtlFillMemory(FullPathNameBuffer, sizeof(FullPathNameBuffer), 0xAA);
207 TempString = FileName;
208 PathType.Type = RtlPathTypeNotSet;
209 PathType.Unknown = 1234;
210 ShortName = InvalidPointer;
211 NameInvalid = (BOOLEAN)-1;
212 Length = 1234;
213 StartSeh()
214 Length = RtlGetFullPathName_Ustr(&FileName,
215 sizeof(FullPathNameBuffer),
216 FullPathNameBuffer,
217 &ShortName,
218 &NameInvalid,
219 &PathType);
220 EndSeh(STATUS_SUCCESS);
221 ok_eq_ustr(&FileName, &TempString);
222 ok(CheckStringBuffer(FullPathNameBuffer, Length, sizeof(FullPathNameBuffer), ExpectedPathName),
223 "Wrong path name '%S', expected '%S'\n", FullPathNameBuffer, ExpectedPathName);
224 switch (TestCases[i].FilePartPrefixType)
225 {
226 case PrefixNone:
227 ExpectedFilePartSize = 0;
228 break;
229 case PrefixCurrentDrive:
230 ExpectedFilePartSize = sizeof(L"C:\\");
231 break;
232 case PrefixCurrentPath:
233 ExpectedFilePartSize = GetCurrentDirectoryW(0, NULL) * sizeof(WCHAR);
234 if (ExpectedFilePartSize == sizeof(L"C:\\"))
235 ExpectedFilePartSize -= sizeof(WCHAR);
236 break;
237 case PrefixCurrentPathWithoutLastPart:
238 {
239 WCHAR CurrentPath[MAX_PATH];
240 PCWSTR BackSlash;
241 ExpectedFilePartSize = GetCurrentDirectoryW(sizeof(CurrentPath) / sizeof(WCHAR), CurrentPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
242 if (ExpectedFilePartSize == sizeof(L"C:\\"))
243 ExpectedFilePartSize = 0;
244 else
245 {
246 BackSlash = wcsrchr(CurrentPath, L'\\');
247 if (BackSlash)
248 ExpectedFilePartSize -= wcslen(BackSlash + 1) * sizeof(WCHAR);
249 else
250 ok(0, "GetCurrentDirectory returned %S\n", CurrentPath);
251 }
252 break;
253 }
254 default:
255 skip(0, "Invalid test!\n");
256 continue;
257 }
258 ExpectedFilePartSize += TestCases[i].FilePartSize;
259 if (ExpectedFilePartSize == 0)
260 {
261 ExpectedShortName = NULL;
262 }
263 else
264 {
265 ExpectedFilePartSize = (ExpectedFilePartSize - sizeof(UNICODE_NULL)) / sizeof(WCHAR);
266 ExpectedShortName = FullPathNameBuffer + ExpectedFilePartSize;
267 }
268 ok(ShortName == ExpectedShortName,
269 "ShortName = %p, expected %p\n", ShortName, ExpectedShortName);
270 ok(NameInvalid == FALSE, "NameInvalid = %u\n", NameInvalid);
271 ok(PathType.Type == TestCases[i].PathType, "PathType = %d, expected %d\n", PathType.Type, TestCases[i].PathType);
272 ok(PathType.Unknown == 1234 ||
273 broken(PathType.Unknown == 0) ||
274 broken(PathType.Unknown == 32), "Unknown = %d\n", PathType.Unknown);
275 }
276 }
277
278 START_TEST(RtlGetFullPathName_Ustr)
279 {
280 NTSTATUS ExceptionStatus;
281 ULONG Length;
282 UNICODE_STRING FileName;
283 UNICODE_STRING TempString;
284 PCWSTR ShortName;
285 BOOLEAN NameInvalid;
286 PATH_TYPE_AND_UNKNOWN PathType;
287
288 if (!RtlGetFullPathName_Ustr)
289 return;
290
291 /* NULL parameters */
292 StartSeh()
293 RtlGetFullPathName_Ustr(NULL, 0, NULL, NULL, NULL, NULL);
294 EndSeh(STATUS_ACCESS_VIOLATION);
295
296 RtlInitUnicodeString(&FileName, NULL);
297 TempString = FileName;
298 StartSeh()
299 RtlGetFullPathName_Ustr(&FileName, 0, NULL, NULL, NULL, NULL);
300 EndSeh(STATUS_ACCESS_VIOLATION);
301 ok_eq_ustr(&FileName, &TempString);
302
303 RtlInitUnicodeString(&FileName, L"");
304 TempString = FileName;
305 StartSeh()
306 RtlGetFullPathName_Ustr(&FileName, 0, NULL, NULL, NULL, NULL);
307 EndSeh(STATUS_ACCESS_VIOLATION);
308 ok_eq_ustr(&FileName, &TempString);
309
310 PathType.Type = RtlPathTypeNotSet;
311 PathType.Unknown = 1234;
312 StartSeh()
313 RtlGetFullPathName_Ustr(NULL, 0, NULL, NULL, NULL, &PathType);
314 EndSeh(STATUS_ACCESS_VIOLATION);
315 ok(PathType.Type == RtlPathTypeUnknown ||
316 broken(PathType.Type == RtlPathTypeNotSet) /* Win7 */, "PathType = %d\n", PathType.Type);
317 ok(PathType.Unknown == 1234 ||
318 broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %d\n", PathType.Unknown);
319
320 /* check what else is initialized before it crashes */
321 PathType.Type = RtlPathTypeNotSet;
322 PathType.Unknown = 1234;
323 ShortName = InvalidPointer;
324 NameInvalid = (BOOLEAN)-1;
325 StartSeh()
326 RtlGetFullPathName_Ustr(NULL, 0, NULL, &ShortName, &NameInvalid, &PathType);
327 EndSeh(STATUS_ACCESS_VIOLATION);
328 ok(NameInvalid == FALSE, "NameInvalid = %u\n", NameInvalid);
329 ok(ShortName == InvalidPointer ||
330 broken(ShortName == NULL), "ShortName = %p\n", ShortName);
331 ok(PathType.Type == RtlPathTypeUnknown ||
332 broken(PathType.Type == RtlPathTypeNotSet) /* Win7 */, "PathType = %d\n", PathType.Type);
333 ok(PathType.Unknown == 1234 ||
334 broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %d\n", PathType.Unknown);
335
336 RtlInitUnicodeString(&FileName, L"");
337 TempString = FileName;
338 ShortName = InvalidPointer;
339 NameInvalid = (BOOLEAN)-1;
340 StartSeh()
341 RtlGetFullPathName_Ustr(&FileName, 0, NULL, &ShortName, &NameInvalid, NULL);
342 EndSeh(STATUS_ACCESS_VIOLATION);
343 ok_eq_ustr(&FileName, &TempString);
344 ok(ShortName == InvalidPointer ||
345 broken(ShortName == NULL), "ShortName = %p\n", ShortName);
346 ok(NameInvalid == FALSE ||
347 broken(NameInvalid == (BOOLEAN)-1) /* Win7 */, "NameInvalid = %u\n", NameInvalid);
348
349 /* This is the first one that doesn't crash. FileName and PathType cannot be NULL */
350 RtlInitUnicodeString(&FileName, NULL);
351 TempString = FileName;
352 PathType.Type = RtlPathTypeNotSet;
353 PathType.Unknown = 1234;
354 StartSeh()
355 Length = RtlGetFullPathName_Ustr(&FileName, 0, NULL, NULL, NULL, &PathType);
356 ok(Length == 0, "Length = %lu\n", Length);
357 EndSeh(STATUS_SUCCESS);
358 ok_eq_ustr(&FileName, &TempString);
359 ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
360 ok(PathType.Unknown == 1234 ||
361 broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %d\n", PathType.Unknown);
362
363 RtlInitUnicodeString(&FileName, L"");
364 TempString = FileName;
365 PathType.Type = RtlPathTypeNotSet;
366 PathType.Unknown = 1234;
367 StartSeh()
368 Length = RtlGetFullPathName_Ustr(&FileName, 0, NULL, NULL, NULL, &PathType);
369 ok(Length == 0, "Length = %lu\n", Length);
370 EndSeh(STATUS_SUCCESS);
371 ok_eq_ustr(&FileName, &TempString);
372 ok(PathType.Type == RtlPathTypeUnknown, "PathType = %d\n", PathType.Type);
373 ok(PathType.Unknown == 1234 ||
374 broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %d\n", PathType.Unknown);
375
376 /* Give it a valid path */
377 RtlInitUnicodeString(&FileName, L"C:\\test");
378 TempString = FileName;
379 PathType.Type = RtlPathTypeNotSet;
380 PathType.Unknown = 1234;
381 StartSeh()
382 Length = RtlGetFullPathName_Ustr(&FileName, 0, NULL, NULL, NULL, &PathType);
383 ok(Length == sizeof(L"C:\\test"), "Length = %lu\n", Length);
384 EndSeh(STATUS_SUCCESS);
385 ok_eq_ustr(&FileName, &TempString);
386 ok(PathType.Type == RtlPathTypeDriveAbsolute, "PathType = %d\n", PathType.Type);
387 ok(PathType.Unknown == 1234 ||
388 broken(PathType.Unknown == 0) /* Win7 */, "Unknown = %d\n", PathType.Unknown);
389
390 /* check the actual functionality with different paths */
391 RunTestCases();
392 }