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         PCWSTR FileName;
91         PREFIX_TYPE PrefixType;
92         PCWSTR FullPathName;
93         PREFIX_TYPE FilePartPrefixType;
94         SIZE_T FilePartSize;
95     } TestCases[] =
96     {
97         { L"C:",                 PrefixCurrentPath, L"", PrefixCurrentPathWithoutLastPart },
98         { L"C:\\",               PrefixNone, L"C:\\" },
99         { L"C:\\test",           PrefixNone, L"C:\\test", PrefixCurrentDrive },
100         { L"C:\\test\\",         PrefixNone, L"C:\\test\\" },
101         { L"C:/test/",           PrefixNone, L"C:\\test\\" },
102 
103         { L"C:\\\\test",         PrefixNone, L"C:\\test", PrefixCurrentDrive },
104         { L"test",               PrefixCurrentPath, L"\\test", PrefixCurrentPath, sizeof(WCHAR) },
105         { L"\\test",             PrefixCurrentDrive, L"test", PrefixCurrentDrive },
106         { L"/test",              PrefixCurrentDrive, L"test", PrefixCurrentDrive },
107         { L".\\test",            PrefixCurrentPath, L"\\test", PrefixCurrentPath, sizeof(WCHAR) },
108 
109         { L"\\.",                PrefixCurrentDrive, L"" },
110         { L"\\.\\",              PrefixCurrentDrive, L"" },
111         { L"\\\\.",              PrefixNone, L"\\\\.\\" },
112         { L"\\\\.\\",            PrefixNone, L"\\\\.\\" },
113         { L"\\\\.\\Something\\", PrefixNone, L"\\\\.\\Something\\" },
114 
115         { L"\\??\\",             PrefixCurrentDrive, L"??\\" },
116         { L"\\??\\C:",           PrefixCurrentDrive, L"??\\C:", PrefixCurrentDrive, 3 * sizeof(WCHAR) },
117         { L"\\??\\C:\\",         PrefixCurrentDrive, L"??\\C:\\" },
118         { L"\\??\\C:\\test",     PrefixCurrentDrive, L"??\\C:\\test", PrefixCurrentDrive, 6 * sizeof(WCHAR) },
119         { L"\\??\\C:\\test\\",   PrefixCurrentDrive, L"??\\C:\\test\\" },
120 
121         { L"\\\\??\\",           PrefixNone, L"\\\\??\\" },
122         { L"\\\\??\\C:",         PrefixNone, L"\\\\??\\C:" },
123         { L"\\\\??\\C:\\",       PrefixNone, L"\\\\??\\C:\\" },
124         { L"\\\\??\\C:\\test",   PrefixNone, L"\\\\??\\C:\\test", PrefixNone, sizeof(L"\\\\??\\C:\\") },
125         { L"\\\\??\\C:\\test\\", PrefixNone, L"\\\\??\\C:\\test\\" },
126     };
127     WCHAR FullPathNameBuffer[MAX_PATH];
128     PWSTR ShortName;
129     SIZE_T Length;
130     WCHAR ExpectedPathName[MAX_PATH];
131     SIZE_T FilePartSize;
132     SIZE_T ExpectedFilePartSize;
133     const INT TestCount = sizeof(TestCases) / sizeof(TestCases[0]);
134     INT i;
135     BOOLEAN Okay;
136 
137     for (i = 0; i < TestCount; i++)
138     {
139         trace("i = %d\n", i);
140         switch (TestCases[i].PrefixType)
141         {
142             case PrefixNone:
143                 ExpectedPathName[0] = UNICODE_NULL;
144                 break;
145             case PrefixCurrentDrive:
146                 GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
147                 ExpectedPathName[3] = UNICODE_NULL;
148                 break;
149             case PrefixCurrentPath:
150                 Length = GetCurrentDirectoryW(sizeof(ExpectedPathName) / sizeof(WCHAR), ExpectedPathName);
151                 if (Length == 3 && TestCases[i].FullPathName[0])
152                     ExpectedPathName[2] = UNICODE_NULL;
153                 break;
154             default:
155                 skip("Invalid test!\n");
156                 continue;
157         }
158         wcscat(ExpectedPathName, TestCases[i].FullPathName);
159         RtlFillMemory(FullPathNameBuffer, sizeof(FullPathNameBuffer), 0xAA);
160         Length = 0;
161         StartSeh()
162             Length = RtlGetFullPathName_U(TestCases[i].FileName,
163                                           sizeof(FullPathNameBuffer),
164                                           FullPathNameBuffer,
165                                           &ShortName);
166         EndSeh(STATUS_SUCCESS);
167 
168         Okay = CheckStringBuffer(FullPathNameBuffer, Length, sizeof(FullPathNameBuffer), ExpectedPathName);
169         ok(Okay, "Wrong path name '%S', expected '%S'\n", FullPathNameBuffer, ExpectedPathName);
170 
171         if (!ShortName)
172             FilePartSize = 0;
173         else
174             FilePartSize = ShortName - FullPathNameBuffer;
175 
176         switch (TestCases[i].FilePartPrefixType)
177         {
178             case PrefixNone:
179                 ExpectedFilePartSize = 0;
180                 break;
181             case PrefixCurrentDrive:
182                 ExpectedFilePartSize = sizeof(L"C:\\");
183                 break;
184             case PrefixCurrentPath:
185                 ExpectedFilePartSize = GetCurrentDirectoryW(0, NULL) * sizeof(WCHAR);
186                 if (ExpectedFilePartSize == sizeof(L"C:\\"))
187                     ExpectedFilePartSize -= sizeof(WCHAR);
188                 break;
189             case PrefixCurrentPathWithoutLastPart:
190             {
191                 WCHAR CurrentPath[MAX_PATH];
192                 PCWSTR BackSlash;
193                 ExpectedFilePartSize = GetCurrentDirectoryW(sizeof(CurrentPath) / sizeof(WCHAR), CurrentPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
194                 if (ExpectedFilePartSize == sizeof(L"C:\\"))
195                     ExpectedFilePartSize = 0;
196                 else
197                 {
198                     BackSlash = wcsrchr(CurrentPath, L'\\');
199                     if (BackSlash)
200                         ExpectedFilePartSize -= wcslen(BackSlash + 1) * sizeof(WCHAR);
201                     else
202                         ok(0, "GetCurrentDirectory returned %S\n", CurrentPath);
203                 }
204                 break;
205             }
206             default:
207                 skip("Invalid test!\n");
208                 continue;
209         }
210         ExpectedFilePartSize += TestCases[i].FilePartSize;
211         if (ExpectedFilePartSize != 0)
212             ExpectedFilePartSize = (ExpectedFilePartSize - sizeof(UNICODE_NULL)) / sizeof(WCHAR);
213         ok(FilePartSize == ExpectedFilePartSize,
214             "FilePartSize = %lu, expected %lu\n", (ULONG)FilePartSize, (ULONG)ExpectedFilePartSize);
215     }
216 }
217 
218 START_TEST(RtlGetFullPathName_U)
219 {
220     PCWSTR FileName;
221     PWSTR ShortName;
222     ULONG Length;
223 
224     /* Parameter checks */
225     StartSeh()
226         Length = RtlGetFullPathName_U(NULL, 0, NULL, NULL);
227         ok(Length == 0, "Length = %lu\n", Length);
228     EndSeh(STATUS_SUCCESS);
229 
230     StartSeh()
231         Length = RtlGetFullPathName_U(L"", 0, NULL, NULL);
232         ok(Length == 0, "Length = %lu\n", Length);
233     EndSeh(STATUS_SUCCESS);
234 
235     ShortName = InvalidPointer;
236     StartSeh()
237         Length = RtlGetFullPathName_U(NULL, 0, NULL, &ShortName);
238         ok(Length == 0, "Length = %lu\n", Length);
239     EndSeh(STATUS_SUCCESS);
240     ok(ShortName == InvalidPointer ||
241         broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
242 
243     StartSeh()
244         Length = RtlGetFullPathName_U(L"", 0, NULL, NULL);
245         ok(Length == 0, "Length = %lu\n", Length);
246     EndSeh(STATUS_SUCCESS);
247 
248     ShortName = InvalidPointer;
249     StartSeh()
250         Length = RtlGetFullPathName_U(L"", 0, NULL, &ShortName);
251         ok(Length == 0, "Length = %lu\n", Length);
252     EndSeh(STATUS_SUCCESS);
253     ok(ShortName == InvalidPointer ||
254         broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
255 
256     StartSeh()
257         Length = RtlGetFullPathName_U(L"C:\\test", 0, NULL, NULL);
258         ok(Length == sizeof(L"C:\\test"), "Length = %lu\n", Length);
259     EndSeh(STATUS_SUCCESS);
260 
261     FileName = L"C:\\test";
262     ShortName = InvalidPointer;
263     StartSeh()
264         Length = RtlGetFullPathName_U(FileName, 0, NULL, &ShortName);
265         ok(Length == sizeof(L"C:\\test"), "Length = %lu\n", Length);
266     EndSeh(STATUS_SUCCESS);
267     ok(ShortName == InvalidPointer ||
268         broken(ShortName == NULL) /* Win7 */, "ShortName = %p\n", ShortName);
269 
270     /* Check the actual functionality with different paths */
271     RunTestCases();
272 }
273