1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for RtlGetFullPathName_U
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 /*
11 ULONG
12 NTAPI
13 RtlGetFullPathName_U(
14     IN PCWSTR FileName,
15     IN ULONG Size,
16     IN PWSTR Buffer,
17     OUT PWSTR *ShortName
18 );
19 */
20 
21 static
22 BOOLEAN
23 CheckStringBuffer(
24     PCWSTR Buffer,
25     SIZE_T Length,
26     SIZE_T MaximumLength,
27     PCWSTR Expected)
28 {
29     SIZE_T ExpectedLength = wcslen(Expected) * sizeof(WCHAR);
30     SIZE_T EqualLength;
31     BOOLEAN Result = TRUE;
32     SIZE_T i;
33 
34     if (Length != ExpectedLength)
35     {
36         ok(0, "String length is %lu, expected %lu\n", (ULONG)Length, (ULONG)ExpectedLength);
37         Result = FALSE;
38     }
39 
40     EqualLength = RtlCompareMemory(Buffer, Expected, Length);
41     if (EqualLength != Length)
42     {
43         ok(0, "String is '%S', expected '%S'\n", Buffer, Expected);
44         Result = FALSE;
45     }
46 
47     if (Buffer[Length / sizeof(WCHAR)] != UNICODE_NULL)
48     {
49         ok(0, "Not null terminated\n");
50         Result = FALSE;
51     }
52 
53     /* The function nulls the rest of the buffer! */
54     for (i = Length + sizeof(UNICODE_NULL); i < MaximumLength; i++)
55     {
56         UCHAR Char = ((PUCHAR)Buffer)[i];
57         if (Char != 0)
58         {
59             ok(0, "Found 0x%x at offset %lu, expected 0x%x\n", Char, (ULONG)i, 0);
60             /* Don't count this as a failure unless the string was actually wrong */
61             //Result = FALSE;
62             /* Don't flood the log */
63             break;
64         }
65     }
66 
67     return Result;
68 }
69 
70 /* winetest_platform is "windows" for us, so broken() doesn't do what it should :( */
71 #undef broken
72 #define broken(x) 0
73 
74 typedef enum
75 {
76     PrefixNone,
77     PrefixCurrentDrive,
78     PrefixCurrentPath,
79     PrefixCurrentPathWithoutLastPart
80 } PREFIX_TYPE;
81 
82 static
83 VOID
84 RunTestCases(VOID)
85 {
86     /* TODO: don't duplicate this in the other tests */
87     /* TODO: Drive Relative tests don't work yet if the current drive isn't C: */
88     struct
89     {
90         ULONG Line;
91         PCWSTR FileName;
92         PREFIX_TYPE PrefixType;
93         PCWSTR FullPathName;
94         PREFIX_TYPE FilePartPrefixType;
95         SIZE_T FilePartSize;
96     } TestCases[] =
97     {
98 //        { __LINE__, L"C:",                 PrefixCurrentPath, L"", PrefixCurrentPathWithoutLastPart },
99         { __LINE__, L"C:\\",               PrefixNone, L"C:\\" },
100         { __LINE__, L"C:\\test",           PrefixNone, L"C:\\test", PrefixCurrentDrive },
101         { __LINE__, L"C:\\test\\",         PrefixNone, L"C:\\test\\" },
102         { __LINE__, L"C:/test/",           PrefixNone, L"C:\\test\\" },
103 
104         { __LINE__, L"C:\\\\test",         PrefixNone, L"C:\\test", PrefixCurrentDrive },
105         { __LINE__, L"test",               PrefixCurrentPath, L"\\test", PrefixCurrentPath, sizeof(WCHAR) },
106         { __LINE__, L"\\test",             PrefixCurrentDrive, L"test", PrefixCurrentDrive },
107         { __LINE__, L"/test",              PrefixCurrentDrive, L"test", PrefixCurrentDrive },
108         { __LINE__, L".\\test",            PrefixCurrentPath, L"\\test", PrefixCurrentPath, sizeof(WCHAR) },
109 
110         { __LINE__, L"\\.",                PrefixCurrentDrive, L"" },
111         { __LINE__, L"\\.\\",              PrefixCurrentDrive, L"" },
112         { __LINE__, L"\\\\.",              PrefixNone, L"\\\\.\\" },
113         { __LINE__, L"\\\\.\\",            PrefixNone, L"\\\\.\\" },
114         { __LINE__, L"\\\\.\\Something\\", PrefixNone, L"\\\\.\\Something\\" },
115 
116         { __LINE__, L"\\??\\",             PrefixCurrentDrive, L"??\\" },
117         { __LINE__, L"\\??\\C:",           PrefixCurrentDrive, L"??\\C:", PrefixCurrentDrive, 3 * sizeof(WCHAR) },
118         { __LINE__, L"\\??\\C:\\",         PrefixCurrentDrive, L"??\\C:\\" },
119         { __LINE__, L"\\??\\C:\\test",     PrefixCurrentDrive, L"??\\C:\\test", PrefixCurrentDrive, 6 * sizeof(WCHAR) },
120         { __LINE__, L"\\??\\C:\\test\\",   PrefixCurrentDrive, L"??\\C:\\test\\" },
121 
122         { __LINE__, L"\\\\??\\",           PrefixNone, L"\\\\??\\" },
123         { __LINE__, L"\\\\??\\C:",         PrefixNone, L"\\\\??\\C:" },
124         { __LINE__, L"\\\\??\\C:\\",       PrefixNone, L"\\\\??\\C:\\" },
125         { __LINE__, L"\\\\??\\C:\\test",   PrefixNone, L"\\\\??\\C:\\test", PrefixNone, sizeof(L"\\\\??\\C:\\") },
126         { __LINE__, L"\\\\??\\C:\\test\\", PrefixNone, L"\\\\??\\C:\\test\\" },
127     };
128     WCHAR FullPathNameBuffer[MAX_PATH];
129     PWSTR ShortName;
130     SIZE_T Length;
131     WCHAR ExpectedPathName[MAX_PATH];
132     SIZE_T FilePartSize;
133     SIZE_T ExpectedFilePartSize;
134     const INT TestCount = sizeof(TestCases) / sizeof(TestCases[0]);
135     INT i;
136     BOOLEAN Okay;
137 
138     for (i = 0; i < TestCount; i++)
139     {
140         trace("i = %d\n", i);
141         switch (TestCases[i].PrefixType)
142         {
143             case PrefixNone:
144                 ExpectedPathName[0] = UNICODE_NULL;
145                 break;
146             case PrefixCurrentDrive:
147                 GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
148                 ExpectedPathName[3] = UNICODE_NULL;
149                 break;
150             case PrefixCurrentPath:
151                 Length = GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
152                 if (Length == 3 && TestCases[i].FullPathName[0])
153                     ExpectedPathName[2] = UNICODE_NULL;
154                 break;
155             default:
156                 skip("Invalid test!\n");
157                 continue;
158         }
159         wcscat(ExpectedPathName, TestCases[i].FullPathName);
160         RtlFillMemory(FullPathNameBuffer, sizeof(FullPathNameBuffer), 0xAA);
161         Length = 0;
162         StartSeh()
163             Length = RtlGetFullPathName_U(TestCases[i].FileName,
164                                           sizeof(FullPathNameBuffer),
165                                           FullPathNameBuffer,
166                                           &ShortName);
167         EndSeh(STATUS_SUCCESS);
168 
169         Okay = CheckStringBuffer(FullPathNameBuffer, Length, sizeof(FullPathNameBuffer), ExpectedPathName);
170         ok(Okay, "Line %lu: Wrong path name '%S', expected '%S'\n", TestCases[i].Line, FullPathNameBuffer, ExpectedPathName);
171 
172         if (!ShortName)
173             FilePartSize = 0;
174         else
175             FilePartSize = ShortName - FullPathNameBuffer;
176 
177         switch (TestCases[i].FilePartPrefixType)
178         {
179             case PrefixNone:
180                 ExpectedFilePartSize = 0;
181                 break;
182             case PrefixCurrentDrive:
183                 ExpectedFilePartSize = sizeof(L"C:\\");
184                 break;
185             case PrefixCurrentPath:
186                 ExpectedFilePartSize = GetCurrentDirectoryW(0, NULL) * sizeof(WCHAR);
187                 if (ExpectedFilePartSize == sizeof(L"C:\\"))
188                     ExpectedFilePartSize -= sizeof(WCHAR);
189                 break;
190             case PrefixCurrentPathWithoutLastPart:
191             {
192                 WCHAR CurrentPath[MAX_PATH];
193                 PCWSTR BackSlash;
194                 ExpectedFilePartSize = GetCurrentDirectoryW(sizeof(CurrentPath) / sizeof(WCHAR), CurrentPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
195                 if (ExpectedFilePartSize == sizeof(L"C:\\"))
196                     ExpectedFilePartSize = 0;
197                 else
198                 {
199                     BackSlash = wcsrchr(CurrentPath, L'\\');
200                     if (BackSlash)
201                         ExpectedFilePartSize -= wcslen(BackSlash + 1) * sizeof(WCHAR);
202                     else
203                         ok(0, "Line %lu: GetCurrentDirectory returned %S\n", TestCases[i].Line, CurrentPath);
204                 }
205                 break;
206             }
207             default:
208                 skip("Invalid test!\n");
209                 continue;
210         }
211         ExpectedFilePartSize += TestCases[i].FilePartSize;
212         if (ExpectedFilePartSize != 0)
213             ExpectedFilePartSize = (ExpectedFilePartSize - sizeof(UNICODE_NULL)) / sizeof(WCHAR);
214         ok(FilePartSize == ExpectedFilePartSize,
215             "Line %lu: FilePartSize = %lu, expected %lu\n", TestCases[i].Line, (ULONG)FilePartSize, (ULONG)ExpectedFilePartSize);
216     }
217 }
218 
219 START_TEST(RtlGetFullPathName_U)
220 {
221     PCWSTR FileName;
222     PWSTR ShortName;
223     ULONG Length;
224 
225     /* Parameter checks */
226     StartSeh()
227         Length = RtlGetFullPathName_U(NULL, 0, NULL, NULL);
228         ok(Length == 0, "Length = %lu\n", Length);
229     EndSeh(STATUS_SUCCESS);
230 
231     StartSeh()
232         Length = RtlGetFullPathName_U(L"", 0, NULL, NULL);
233         ok(Length == 0, "Length = %lu\n", Length);
234     EndSeh(STATUS_SUCCESS);
235 
236     ShortName = InvalidPointer;
237     StartSeh()
238         Length = RtlGetFullPathName_U(NULL, 0, NULL, &ShortName);
239         ok(Length == 0, "Length = %lu\n", Length);
240     EndSeh(STATUS_SUCCESS);
241     ok(ShortName == InvalidPointer ||
242         broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
243 
244     StartSeh()
245         Length = RtlGetFullPathName_U(L"", 0, NULL, NULL);
246         ok(Length == 0, "Length = %lu\n", Length);
247     EndSeh(STATUS_SUCCESS);
248 
249     ShortName = InvalidPointer;
250     StartSeh()
251         Length = RtlGetFullPathName_U(L"", 0, NULL, &ShortName);
252         ok(Length == 0, "Length = %lu\n", Length);
253     EndSeh(STATUS_SUCCESS);
254     ok(ShortName == InvalidPointer ||
255         broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
256 
257     StartSeh()
258         Length = RtlGetFullPathName_U(L"C:\\test", 0, NULL, NULL);
259         ok(Length == sizeof(L"C:\\test"), "Length = %lu\n", Length);
260     EndSeh(STATUS_SUCCESS);
261 
262     FileName = L"C:\\test";
263     ShortName = InvalidPointer;
264     StartSeh()
265         Length = RtlGetFullPathName_U(FileName, 0, NULL, &ShortName);
266         ok(Length == sizeof(L"C:\\test"), "Length = %lu\n", Length);
267     EndSeh(STATUS_SUCCESS);
268     ok(ShortName == InvalidPointer ||
269         broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
270 
271     /* Check the actual functionality with different paths */
272     RunTestCases();
273 }
274