winmm: Fix a failing mixer test on 98 and ME.
[wine] / dlls / ntdll / tests / path.c
1 /*
2  * Unit test suite for ntdll path functions
3  *
4  * Copyright 2002 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "ntdll_test.h"
22
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
32
33 static void test_RtlDetermineDosPathNameType(void)
34 {
35     struct test
36     {
37         const char *path;
38         UINT ret;
39     };
40
41     static const struct test tests[] =
42     {
43         { "\\\\foo", 1 },
44         { "//foo", 1 },
45         { "\\/foo", 1 },
46         { "/\\foo", 1 },
47         { "\\\\", 1 },
48         { "//", 1 },
49         { "c:\\foo", 2 },
50         { "c:/foo", 2 },
51         { "c://foo", 2 },
52         { "c:\\", 2 },
53         { "c:/", 2 },
54         { "c:foo", 3 },
55         { "c:f\\oo", 3 },
56         { "c:foo/bar", 3 },
57         { "\\foo", 4 },
58         { "/foo", 4 },
59         { "\\", 4 },
60         { "/", 4 },
61         { "foo", 5 },
62         { "", 5 },
63         { "\0:foo", 5 },
64         { "\\\\.\\foo", 6 },
65         { "//./foo", 6 },
66         { "/\\./foo", 6 },
67         { "\\\\.foo", 1 },
68         { "//.foo", 1 },
69         { "\\\\.", 7 },
70         { "//.", 7 },
71         { NULL, 0 }
72     };
73
74     const struct test *test;
75     WCHAR buffer[MAX_PATH];
76     UINT ret;
77
78     for (test = tests; test->path; test++)
79     {
80         pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
81         ret = pRtlDetermineDosPathNameType_U( buffer );
82         ok( ret == test->ret, "Wrong result %d/%d for %s\n", ret, test->ret, test->path );
83     }
84 }
85
86
87 static void test_RtlIsDosDeviceName(void)
88 {
89     struct test
90     {
91         const char *path;
92         WORD pos;
93         WORD len;
94     };
95
96     static const struct test tests[] =
97     {
98         { "\\\\.\\CON",    8, 6 },
99         { "\\\\.\\con",    8, 6 },
100         { "\\\\.\\CON2",   0, 0 },
101         { "",              0, 0 },
102         { "\\\\foo\\nul",  0, 0 },
103         { "c:\\nul:",      6, 6 },
104         { "c:\\nul::",     6, 6 },
105         { "c:\\nul::::::", 6, 6 },
106         { "c:prn     ",    4, 6 },
107         { "c:prn.......",  4, 6 },
108         { "c:prn... ...",  4, 6 },
109         { "c:NUL  ....  ", 4, 6 },
110         { "c: . . .",      0, 0 },
111         { "c:",            0, 0 },
112         { " . . . :",      0, 0 },
113         { ":",             0, 0 },
114         { "c:nul. . . :",  4, 6 },
115         { "c:nul . . :",   4, 6 },
116         { "c:nul0",        0, 0 },
117         { "c:PRN:.txt",    4, 6 },
118         { "c:aux:.txt...", 4, 6 },
119         { "c:prn:.txt:",   4, 6 },
120         { "con:",          0, 6 },
121         { "lpt1:",         0, 8 },
122         { "c:com5:",       4, 8 },
123         { "CoM4:",         0, 8 },
124         { "lpt9:",         0, 8 },
125         { "c:\\lpt0.txt",  0, 0 },
126         { "c:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
127           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
128           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
129           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
130           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
131           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
132           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nul.txt", 1000, 6 },
133         { NULL, 0 }
134     };
135
136     const struct test *test;
137     WCHAR buffer[2000];
138     ULONG ret;
139
140     for (test = tests; test->path; test++)
141     {
142         pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
143         ret = pRtlIsDosDeviceName_U( buffer );
144         ok( ret == MAKELONG( test->len, test->pos ),
145             "Wrong result (%d,%d)/(%d,%d) for %s\n",
146             HIWORD(ret), LOWORD(ret), test->pos, test->len, test->path );
147     }
148
149     pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, "c:prn:aaa", strlen("c:prn:aaa")+1 );
150     ret = pRtlIsDosDeviceName_U( buffer );
151     ok( ret == MAKELONG( 6, 4 ) || /* NT */
152         ret == MAKELONG( 0, 0), /* win9x */
153         "Wrong result (%d,%d)/(4,6) or (0,0) for c:prn:aaa\n", HIWORD(ret), LOWORD(ret) );
154
155     pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, "c:nul:aaa", strlen("c:nul:aaa")+1 );
156     ret = pRtlIsDosDeviceName_U( buffer );
157     ok( ret == MAKELONG( 6, 4 ) || /* NT */
158         ret == MAKELONG( 0, 0), /* win9x */
159         "Wrong result (%d,%d)/(4,6) or (0,0) for c:nul:aaa\n", HIWORD(ret), LOWORD(ret) );
160 }
161
162 static void test_RtlIsNameLegalDOS8Dot3(void)
163 {
164     struct test
165     {
166         const char *path;
167         BOOLEAN result;
168         BOOLEAN spaces;
169     };
170
171     static const struct test tests[] =
172     {
173         { "12345678",     TRUE,  FALSE },
174         { "123 5678",     TRUE,  TRUE  },
175         { "12345678.",    FALSE, 2 /*not set*/ },
176         { "1234 678.",    FALSE, 2 /*not set*/ },
177         { "12345678.a",   TRUE,  FALSE },
178         { "12345678.a ",  FALSE, 2 /*not set*/ },
179         { "12345678.a c", TRUE,  TRUE  },
180         { " 2345678.a ",  FALSE, 2 /*not set*/ },
181         { "1 345678.abc", TRUE,  TRUE },
182         { "1      8.a c", TRUE,  TRUE },
183         { "1 3 5 7 .abc", FALSE, 2 /*not set*/ },
184         { "12345678.  c", TRUE,  TRUE },
185         { "123456789.a",  FALSE, 2 /*not set*/ },
186         { "12345.abcd",   FALSE, 2 /*not set*/ },
187         { "12345.ab d",   FALSE, 2 /*not set*/ },
188         { ".abc",         FALSE, 2 /*not set*/ },
189         { "12.abc.d",     FALSE, 2 /*not set*/ },
190         { ".",            TRUE,  FALSE },
191         { "..",           TRUE,  FALSE },
192         { "...",          FALSE, 2 /*not set*/ },
193         { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", FALSE, 2 /*not set*/ },
194         { NULL, 0 }
195     };
196
197     const struct test *test;
198     UNICODE_STRING ustr;
199     OEM_STRING oem, oem_ret;
200     WCHAR buffer[200];
201     char buff2[12];
202     BOOLEAN ret, spaces;
203
204     ustr.MaximumLength = sizeof(buffer);
205     ustr.Buffer = buffer;
206     for (test = tests; test->path; test++)
207     {
208         char path[100];
209         strcpy(path, test->path);
210         oem.Buffer = path;
211         oem.Length = strlen(test->path);
212         oem.MaximumLength = oem.Length + 1;
213         pRtlOemStringToUnicodeString( &ustr, &oem, FALSE );
214         spaces = 2;
215         oem_ret.Length = oem_ret.MaximumLength = sizeof(buff2);
216         oem_ret.Buffer = buff2;
217         ret = pRtlIsNameLegalDOS8Dot3( &ustr, &oem_ret, &spaces );
218         ok( ret == test->result, "Wrong result %d/%d for '%s'\n", ret, test->result, test->path );
219         ok( spaces == test->spaces, "Wrong spaces value %d/%d for '%s'\n", spaces, test->spaces, test->path );
220         if (strlen(test->path) <= 12)
221         {
222             char str[13];
223             int i;
224             strcpy( str, test->path );
225             for (i = 0; str[i]; i++) str[i] = toupper(str[i]);
226             ok( oem_ret.Length == strlen(test->path), "Wrong length %d/%d for '%s'\n",
227                 oem_ret.Length, lstrlenA(test->path), test->path );
228             ok( !memcmp( oem_ret.Buffer, str, oem_ret.Length ),
229                 "Wrong string '%.*s'/'%s'\n", oem_ret.Length, oem_ret.Buffer, str );
230         }
231     }
232 }
233 static void test_RtlGetFullPathName_U(void)
234 {
235     struct test
236     {
237         const char *path;
238         const char *rname;
239         const char *rfile;
240     };
241
242     static const struct test tests[] =
243         {
244             { "c:/test",                     "c:\\test",         "test"},
245             { "c:/test     ",                "c:\\test",         "test"},
246             { "c:/test.",                    "c:\\test",         "test"},
247             { "c:/test  ....   ..   ",       "c:\\test",         "test"},
248             { "c:/test/  ....   ..   ",      "c:\\test\\",       NULL},
249             { "c:/test/..",                  "c:\\",             NULL},
250             { "c:/test/.. ",                 "c:\\test\\",       NULL},
251             { "c:/TEST",                     "c:\\test",         "test"},
252             { "c:/test/file",                "c:\\test\\file",   "file"},
253             { "c:/test./file",               "c:\\test\\file",   "file"},
254             { "c:/test.. /file",             "c:\\test.. \\file","file"},
255             { "c:/test/././file",            "c:\\test\\file",   "file"},
256             { "c:/test\\.\\.\\file",         "c:\\test\\file",   "file"},
257             { "c:/test/\\.\\.\\file",        "c:\\test\\file",   "file"},
258             { "c:/test\\\\.\\.\\file",       "c:\\test\\file",   "file"},
259             { "c:/test\\test1\\..\\.\\file", "c:\\test\\file",   "file"},
260             { "c:///test\\.\\.\\file//",     "c:\\test\\file\\", NULL},
261             { "c:///test\\..\\file\\..\\//", "c:\\",             NULL},
262             { NULL, NULL, NULL}
263         };
264
265     const struct test *test;
266     WCHAR pathbufW[2*MAX_PATH], rbufferW[MAX_PATH];
267     CHAR  rbufferA[MAX_PATH], rfileA[MAX_PATH];
268     ULONG ret;
269     NTSTATUS status;
270     WCHAR *file_part;
271     DWORD reslen;
272     UINT len;
273
274     for (test = tests; test->path; test++)
275     {
276         len= strlen(test->rname) * sizeof(WCHAR);
277         pRtlMultiByteToUnicodeN(pathbufW , sizeof(pathbufW), NULL, test->path, strlen(test->path)+1 );
278         ret = pRtlGetFullPathName_U( pathbufW,MAX_PATH, rbufferW, &file_part);
279         ok( ret == len, "Wrong result %d/%d for \"%s\"\n", ret, len, test->path );
280         ok(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,(lstrlenW(rbufferW) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
281            "RtlUnicodeToMultiByteN failed\n");
282         ok(lstrcmpiA(rbufferA,test->rname) == 0, "Got \"%s\" expected \"%s\"\n",rbufferA,test->rname);
283         if (file_part)
284         {
285             ok(pRtlUnicodeToMultiByteN(rfileA,MAX_PATH,&reslen,file_part,(lstrlenW(file_part) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
286                "RtlUnicodeToMultiByteN failed\n");
287             ok(test->rfile && !lstrcmpiA(rfileA,test->rfile), "Got \"%s\" expected \"%s\"\n",rfileA,test->rfile);
288         }
289         else
290         {
291             ok( !test->rfile, "Got NULL expected \"%s\"\n", test->rfile );
292         }
293     }
294
295     /* "c:/test../file",              "c:\\test.\\file",  "file"}, */
296     pRtlMultiByteToUnicodeN(pathbufW, sizeof(pathbufW), NULL,
297                             "c:/test../file", strlen("c:/test../file") + 1);
298     ret = pRtlGetFullPathName_U(pathbufW, MAX_PATH, rbufferW, &file_part);
299     ok(ret == strlen("c:\\test.\\file") * sizeof(WCHAR) ||
300        ret == strlen("c:\\test..\\file") * sizeof(WCHAR), /* Vista */
301        "Expected 26 or 28, got %d\n", ret);
302     status = pRtlUnicodeToMultiByteN(rbufferA, MAX_PATH, &reslen, rbufferW,
303                                      (lstrlenW(rbufferW) + 1) * sizeof(WCHAR));
304     ok(status == STATUS_SUCCESS, "RtlUnicodeToMultiByteN failed\n");
305     ok(!lstrcmpiA(rbufferA, "c:\\test.\\file") ||
306        !lstrcmpiA(rbufferA, "c:\\test..\\file"),
307        "Expected \"c:\\test.\\file\" or \"c:\\test..\\file\", got \"%s\"\n", rbufferA);
308     status = pRtlUnicodeToMultiByteN(rfileA, MAX_PATH, &reslen, file_part,
309                                      (lstrlenW(file_part) + 1) * sizeof(WCHAR));
310     ok(status == STATUS_SUCCESS, "RtlUnicodeToMultiByteN failed\n");
311     ok(!lstrcmpiA(rfileA, "file"), "Got \"%s\" expected \"file\"\n", rfileA);
312 }
313
314 START_TEST(path)
315 {
316     HMODULE mod = GetModuleHandleA("ntdll.dll");
317     if (!mod)
318     {
319         win_skip("Not running on NT, skipping tests\n");
320         return;
321     }
322
323     pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
324     pRtlUnicodeToMultiByteN = (void *)GetProcAddress(mod,"RtlUnicodeToMultiByteN");
325     pRtlDetermineDosPathNameType_U = (void *)GetProcAddress(mod,"RtlDetermineDosPathNameType_U");
326     pRtlIsDosDeviceName_U = (void *)GetProcAddress(mod,"RtlIsDosDeviceName_U");
327     pRtlOemStringToUnicodeString = (void *)GetProcAddress(mod,"RtlOemStringToUnicodeString");
328     pRtlIsNameLegalDOS8Dot3 = (void *)GetProcAddress(mod,"RtlIsNameLegalDOS8Dot3");
329     pRtlGetFullPathName_U = (void *)GetProcAddress(mod,"RtlGetFullPathName_U");
330     if (pRtlDetermineDosPathNameType_U)
331         test_RtlDetermineDosPathNameType();
332     if (pRtlIsDosDeviceName_U)
333         test_RtlIsDosDeviceName();
334     if (pRtlIsNameLegalDOS8Dot3)
335         test_RtlIsNameLegalDOS8Dot3();
336     if (pRtlGetFullPathName_U && pRtlMultiByteToUnicodeN)
337         test_RtlGetFullPathName_U();
338 }