2003-04-12 02:10:13 +02:00
|
|
|
/*
|
|
|
|
* Unit test suite for ntdll path functions
|
|
|
|
*
|
|
|
|
* Copyright 2002 Alexandre Julliard
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-05-18 14:49:52 +02:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2003-04-12 02:10:13 +02:00
|
|
|
*/
|
|
|
|
|
2004-08-14 02:42:12 +02:00
|
|
|
#include "ntdll_test.h"
|
2018-08-24 05:50:06 +02:00
|
|
|
#include "winnls.h"
|
2003-04-12 02:10:13 +02:00
|
|
|
|
|
|
|
static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
|
|
|
|
LPCSTR src, DWORD srclen );
|
2004-03-23 00:00:13 +01:00
|
|
|
static NTSTATUS (WINAPI *pRtlUnicodeToMultiByteN)(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD);
|
2003-04-12 02:10:13 +02:00
|
|
|
static UINT (WINAPI *pRtlDetermineDosPathNameType_U)( PCWSTR path );
|
|
|
|
static ULONG (WINAPI *pRtlIsDosDeviceName_U)( PCWSTR dos_name );
|
2003-04-17 01:15:29 +02:00
|
|
|
static NTSTATUS (WINAPI *pRtlOemStringToUnicodeString)(UNICODE_STRING *, const STRING *, BOOLEAN );
|
|
|
|
static BOOLEAN (WINAPI *pRtlIsNameLegalDOS8Dot3)(const UNICODE_STRING*,POEM_STRING,PBOOLEAN);
|
2004-03-23 00:00:13 +01:00
|
|
|
static DWORD (WINAPI *pRtlGetFullPathName_U)(const WCHAR*,ULONG,WCHAR*,WCHAR**);
|
2018-08-24 05:50:06 +02:00
|
|
|
static BOOLEAN (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR*, UNICODE_STRING*, WCHAR**, CURDIR*);
|
2017-10-23 08:48:21 +02:00
|
|
|
static NTSTATUS (WINAPI *pRtlDosPathNameToNtPathName_U_WithStatus)(const WCHAR*, UNICODE_STRING*, WCHAR**, CURDIR*);
|
2003-04-12 02:10:13 +02:00
|
|
|
|
2013-09-25 08:36:33 +02:00
|
|
|
static void test_RtlDetermineDosPathNameType_U(void)
|
2003-04-12 02:10:13 +02:00
|
|
|
{
|
|
|
|
struct test
|
|
|
|
{
|
|
|
|
const char *path;
|
2005-02-14 22:04:45 +01:00
|
|
|
UINT ret;
|
2003-04-12 02:10:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct test tests[] =
|
|
|
|
{
|
|
|
|
{ "\\\\foo", 1 },
|
|
|
|
{ "//foo", 1 },
|
|
|
|
{ "\\/foo", 1 },
|
|
|
|
{ "/\\foo", 1 },
|
|
|
|
{ "\\\\", 1 },
|
|
|
|
{ "//", 1 },
|
|
|
|
{ "c:\\foo", 2 },
|
|
|
|
{ "c:/foo", 2 },
|
|
|
|
{ "c://foo", 2 },
|
|
|
|
{ "c:\\", 2 },
|
|
|
|
{ "c:/", 2 },
|
|
|
|
{ "c:foo", 3 },
|
|
|
|
{ "c:f\\oo", 3 },
|
|
|
|
{ "c:foo/bar", 3 },
|
|
|
|
{ "\\foo", 4 },
|
|
|
|
{ "/foo", 4 },
|
|
|
|
{ "\\", 4 },
|
|
|
|
{ "/", 4 },
|
|
|
|
{ "foo", 5 },
|
|
|
|
{ "", 5 },
|
|
|
|
{ "\0:foo", 5 },
|
|
|
|
{ "\\\\.\\foo", 6 },
|
|
|
|
{ "//./foo", 6 },
|
|
|
|
{ "/\\./foo", 6 },
|
|
|
|
{ "\\\\.foo", 1 },
|
|
|
|
{ "//.foo", 1 },
|
|
|
|
{ "\\\\.", 7 },
|
|
|
|
{ "//.", 7 },
|
2018-08-24 05:50:04 +02:00
|
|
|
{ "\\\\?\\foo", 6 },
|
|
|
|
{ "//?/foo", 6 },
|
|
|
|
{ "/\\?/foo", 6 },
|
|
|
|
{ "\\\\?foo", 1 },
|
|
|
|
{ "//?foo", 1 },
|
|
|
|
{ "\\\\?", 7 },
|
|
|
|
{ "//?", 7 },
|
2003-04-12 02:10:13 +02:00
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct test *test;
|
|
|
|
WCHAR buffer[MAX_PATH];
|
|
|
|
UINT ret;
|
|
|
|
|
2013-09-25 08:36:33 +02:00
|
|
|
if (!pRtlDetermineDosPathNameType_U)
|
|
|
|
{
|
|
|
|
win_skip("RtlDetermineDosPathNameType_U is not available\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-12 02:10:13 +02:00
|
|
|
for (test = tests; test->path; test++)
|
|
|
|
{
|
|
|
|
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
|
|
|
|
ret = pRtlDetermineDosPathNameType_U( buffer );
|
2004-02-07 02:03:17 +01:00
|
|
|
ok( ret == test->ret, "Wrong result %d/%d for %s\n", ret, test->ret, test->path );
|
2003-04-12 02:10:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-25 08:36:33 +02:00
|
|
|
static void test_RtlIsDosDeviceName_U(void)
|
2003-04-12 02:10:13 +02:00
|
|
|
{
|
|
|
|
struct test
|
|
|
|
{
|
|
|
|
const char *path;
|
|
|
|
WORD pos;
|
|
|
|
WORD len;
|
2008-10-29 15:22:06 +01:00
|
|
|
BOOL fails;
|
2003-04-12 02:10:13 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct test tests[] =
|
|
|
|
{
|
2013-11-13 22:08:29 +01:00
|
|
|
{ "\\\\.\\CON", 8, 6, TRUE }, /* fails on win8 */
|
|
|
|
{ "\\\\.\\con", 8, 6, TRUE }, /* fails on win8 */
|
2003-04-12 02:10:13 +02:00
|
|
|
{ "\\\\.\\CON2", 0, 0 },
|
|
|
|
{ "", 0, 0 },
|
|
|
|
{ "\\\\foo\\nul", 0, 0 },
|
|
|
|
{ "c:\\nul:", 6, 6 },
|
2008-10-29 15:22:06 +01:00
|
|
|
{ "c:\\nul\\", 0, 0 },
|
|
|
|
{ "c:\\nul\\foo", 0, 0 },
|
|
|
|
{ "c:\\nul::", 6, 6, TRUE }, /* fails on nt4 */
|
|
|
|
{ "c:\\nul::::::", 6, 6, TRUE }, /* fails on nt4 */
|
2003-04-12 02:10:13 +02:00
|
|
|
{ "c:prn ", 4, 6 },
|
|
|
|
{ "c:prn.......", 4, 6 },
|
|
|
|
{ "c:prn... ...", 4, 6 },
|
2008-10-29 15:22:06 +01:00
|
|
|
{ "c:NUL .... ", 4, 6, TRUE }, /* fails on nt4 */
|
2003-04-12 02:10:13 +02:00
|
|
|
{ "c: . . .", 0, 0 },
|
|
|
|
{ "c:", 0, 0 },
|
|
|
|
{ " . . . :", 0, 0 },
|
|
|
|
{ ":", 0, 0 },
|
|
|
|
{ "c:nul. . . :", 4, 6 },
|
2008-10-29 15:22:06 +01:00
|
|
|
{ "c:nul . . :", 4, 6, TRUE }, /* fails on nt4 */
|
2003-04-12 02:10:13 +02:00
|
|
|
{ "c:nul0", 0, 0 },
|
2008-10-29 15:22:06 +01:00
|
|
|
{ "c:prn:aaa", 4, 6, TRUE }, /* fails on win9x */
|
2003-04-12 02:10:13 +02:00
|
|
|
{ "c:PRN:.txt", 4, 6 },
|
|
|
|
{ "c:aux:.txt...", 4, 6 },
|
|
|
|
{ "c:prn:.txt:", 4, 6 },
|
2008-10-29 15:22:06 +01:00
|
|
|
{ "c:nul:aaa", 4, 6, TRUE }, /* fails on win9x */
|
2003-04-12 02:10:13 +02:00
|
|
|
{ "con:", 0, 6 },
|
|
|
|
{ "lpt1:", 0, 8 },
|
|
|
|
{ "c:com5:", 4, 8 },
|
|
|
|
{ "CoM4:", 0, 8 },
|
|
|
|
{ "lpt9:", 0, 8 },
|
|
|
|
{ "c:\\lpt0.txt", 0, 0 },
|
|
|
|
{ "c:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nul.txt", 1000, 6 },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct test *test;
|
|
|
|
WCHAR buffer[2000];
|
|
|
|
ULONG ret;
|
|
|
|
|
2013-09-25 08:36:33 +02:00
|
|
|
if (!pRtlIsDosDeviceName_U)
|
|
|
|
{
|
|
|
|
win_skip("RtlIsDosDeviceName_U is not available\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-12 02:10:13 +02:00
|
|
|
for (test = tests; test->path; test++)
|
|
|
|
{
|
|
|
|
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
|
|
|
|
ret = pRtlIsDosDeviceName_U( buffer );
|
2008-10-29 15:22:06 +01:00
|
|
|
ok( ret == MAKELONG( test->len, test->pos ) ||
|
|
|
|
(test->fails && broken( ret == 0 )),
|
2004-02-07 02:03:17 +01:00
|
|
|
"Wrong result (%d,%d)/(%d,%d) for %s\n",
|
2003-04-12 02:10:13 +02:00
|
|
|
HIWORD(ret), LOWORD(ret), test->pos, test->len, test->path );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-17 01:15:29 +02:00
|
|
|
static void test_RtlIsNameLegalDOS8Dot3(void)
|
|
|
|
{
|
|
|
|
struct test
|
|
|
|
{
|
2003-10-06 23:03:32 +02:00
|
|
|
const char *path;
|
2003-04-17 01:15:29 +02:00
|
|
|
BOOLEAN result;
|
|
|
|
BOOLEAN spaces;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct test tests[] =
|
|
|
|
{
|
|
|
|
{ "12345678", TRUE, FALSE },
|
|
|
|
{ "123 5678", TRUE, TRUE },
|
|
|
|
{ "12345678.", FALSE, 2 /*not set*/ },
|
|
|
|
{ "1234 678.", FALSE, 2 /*not set*/ },
|
|
|
|
{ "12345678.a", TRUE, FALSE },
|
|
|
|
{ "12345678.a ", FALSE, 2 /*not set*/ },
|
|
|
|
{ "12345678.a c", TRUE, TRUE },
|
|
|
|
{ " 2345678.a ", FALSE, 2 /*not set*/ },
|
|
|
|
{ "1 345678.abc", TRUE, TRUE },
|
|
|
|
{ "1 8.a c", TRUE, TRUE },
|
|
|
|
{ "1 3 5 7 .abc", FALSE, 2 /*not set*/ },
|
|
|
|
{ "12345678. c", TRUE, TRUE },
|
|
|
|
{ "123456789.a", FALSE, 2 /*not set*/ },
|
|
|
|
{ "12345.abcd", FALSE, 2 /*not set*/ },
|
|
|
|
{ "12345.ab d", FALSE, 2 /*not set*/ },
|
|
|
|
{ ".abc", FALSE, 2 /*not set*/ },
|
|
|
|
{ "12.abc.d", FALSE, 2 /*not set*/ },
|
|
|
|
{ ".", TRUE, FALSE },
|
|
|
|
{ "..", TRUE, FALSE },
|
|
|
|
{ "...", FALSE, 2 /*not set*/ },
|
|
|
|
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", FALSE, 2 /*not set*/ },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct test *test;
|
|
|
|
UNICODE_STRING ustr;
|
|
|
|
OEM_STRING oem, oem_ret;
|
|
|
|
WCHAR buffer[200];
|
|
|
|
char buff2[12];
|
|
|
|
BOOLEAN ret, spaces;
|
|
|
|
|
2013-09-25 08:36:33 +02:00
|
|
|
if (!pRtlIsNameLegalDOS8Dot3)
|
|
|
|
{
|
|
|
|
win_skip("RtlIsNameLegalDOS8Dot3 is not available\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-17 01:15:29 +02:00
|
|
|
ustr.MaximumLength = sizeof(buffer);
|
|
|
|
ustr.Buffer = buffer;
|
|
|
|
for (test = tests; test->path; test++)
|
|
|
|
{
|
2003-10-06 23:03:32 +02:00
|
|
|
char path[100];
|
|
|
|
strcpy(path, test->path);
|
|
|
|
oem.Buffer = path;
|
2003-04-17 01:15:29 +02:00
|
|
|
oem.Length = strlen(test->path);
|
|
|
|
oem.MaximumLength = oem.Length + 1;
|
|
|
|
pRtlOemStringToUnicodeString( &ustr, &oem, FALSE );
|
|
|
|
spaces = 2;
|
|
|
|
oem_ret.Length = oem_ret.MaximumLength = sizeof(buff2);
|
|
|
|
oem_ret.Buffer = buff2;
|
|
|
|
ret = pRtlIsNameLegalDOS8Dot3( &ustr, &oem_ret, &spaces );
|
2004-02-07 02:03:17 +01:00
|
|
|
ok( ret == test->result, "Wrong result %d/%d for '%s'\n", ret, test->result, test->path );
|
|
|
|
ok( spaces == test->spaces, "Wrong spaces value %d/%d for '%s'\n", spaces, test->spaces, test->path );
|
2003-04-17 01:15:29 +02:00
|
|
|
if (strlen(test->path) <= 12)
|
|
|
|
{
|
2019-03-26 10:27:06 +01:00
|
|
|
STRING test_str;
|
2003-04-17 01:15:29 +02:00
|
|
|
char str[13];
|
|
|
|
strcpy( str, test->path );
|
2019-03-26 10:27:06 +01:00
|
|
|
RtlInitString( &test_str, str );
|
|
|
|
RtlUpperString( &test_str, &test_str );
|
|
|
|
ok( !RtlCompareString(&oem_ret, &test_str, FALSE),
|
|
|
|
"Wrong string '%.*s'/'%s'\n", oem_ret.Length, oem_ret.Buffer, test->path );
|
2003-04-17 01:15:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-06-27 11:57:28 +02:00
|
|
|
static void test_RtlGetFullPathName_U(void)
|
2004-03-23 00:00:13 +01:00
|
|
|
{
|
2010-06-17 06:40:04 +02:00
|
|
|
static const WCHAR emptyW[] = {0};
|
|
|
|
static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0};
|
|
|
|
|
2004-03-23 00:00:13 +01:00
|
|
|
struct test
|
|
|
|
{
|
|
|
|
const char *path;
|
|
|
|
const char *rname;
|
|
|
|
const char *rfile;
|
2008-11-05 19:58:21 +01:00
|
|
|
const char *alt_rname;
|
|
|
|
const char *alt_rfile;
|
2004-03-23 00:00:13 +01:00
|
|
|
};
|
2003-04-12 02:10:13 +02:00
|
|
|
|
2004-03-23 00:00:13 +01:00
|
|
|
static const struct test tests[] =
|
|
|
|
{
|
|
|
|
{ "c:/test", "c:\\test", "test"},
|
2018-08-24 05:50:05 +02:00
|
|
|
{ "c:/test/", "c:\\test\\", NULL},
|
2004-05-13 07:21:23 +02:00
|
|
|
{ "c:/test ", "c:\\test", "test"},
|
2004-05-15 00:10:24 +02:00
|
|
|
{ "c:/test.", "c:\\test", "test"},
|
|
|
|
{ "c:/test .... .. ", "c:\\test", "test"},
|
|
|
|
{ "c:/test/ .... .. ", "c:\\test\\", NULL},
|
|
|
|
{ "c:/test/..", "c:\\", NULL},
|
|
|
|
{ "c:/test/.. ", "c:\\test\\", NULL},
|
2016-07-28 14:24:05 +02:00
|
|
|
{ "c:/TEST", "c:\\TEST", "TEST"},
|
2004-03-23 00:00:13 +01:00
|
|
|
{ "c:/test/file", "c:\\test\\file", "file"},
|
2005-06-24 13:55:28 +02:00
|
|
|
{ "c:/test./file", "c:\\test\\file", "file"},
|
|
|
|
{ "c:/test.. /file", "c:\\test.. \\file","file"},
|
2004-03-23 00:00:13 +01:00
|
|
|
{ "c:/test/././file", "c:\\test\\file", "file"},
|
|
|
|
{ "c:/test\\.\\.\\file", "c:\\test\\file", "file"},
|
|
|
|
{ "c:/test/\\.\\.\\file", "c:\\test\\file", "file"},
|
|
|
|
{ "c:/test\\\\.\\.\\file", "c:\\test\\file", "file"},
|
|
|
|
{ "c:/test\\test1\\..\\.\\file", "c:\\test\\file", "file"},
|
2008-11-05 19:58:21 +01:00
|
|
|
{ "c:///test\\.\\.\\file//", "c:\\test\\file\\", NULL,
|
|
|
|
"c:\\test\\file", "file"}, /* nt4 */
|
2004-03-23 00:00:13 +01:00
|
|
|
{ "c:///test\\..\\file\\..\\//", "c:\\", NULL},
|
2008-11-05 19:58:21 +01:00
|
|
|
{ "c:/test../file", "c:\\test.\\file", "file",
|
|
|
|
"c:\\test..\\file", "file"}, /* vista */
|
2016-07-28 14:24:05 +02:00
|
|
|
{ "c:\\test", "c:\\test", "test"},
|
2018-08-24 05:50:05 +02:00
|
|
|
{ "C:\\test", "C:\\test", "test"},
|
|
|
|
{ "c:/", "c:\\", NULL},
|
|
|
|
{ "c:.", "C:\\windows", "windows"},
|
|
|
|
{ "c:foo", "C:\\windows\\foo", "foo"},
|
|
|
|
{ "c:foo/bar", "C:\\windows\\foo\\bar", "bar"},
|
|
|
|
{ "c:./foo", "C:\\windows\\foo", "foo"},
|
|
|
|
{ "\\foo", "C:\\foo", "foo"},
|
|
|
|
{ "foo", "C:\\windows\\foo", "foo"},
|
|
|
|
{ ".", "C:\\windows", "windows"},
|
|
|
|
{ "..", "C:\\", NULL},
|
|
|
|
{ "...", "C:\\windows\\", NULL},
|
|
|
|
{ "./foo", "C:\\windows\\foo", "foo"},
|
|
|
|
{ "foo/..", "C:\\windows", "windows"},
|
|
|
|
{ "AUX", "\\\\.\\AUX", NULL},
|
|
|
|
{ "COM1", "\\\\.\\COM1", NULL},
|
|
|
|
{ "?<>*\"|:", "C:\\windows\\?<>*\"|:", "?<>*\"|:"},
|
|
|
|
|
|
|
|
{ "\\\\foo", "\\\\foo", NULL},
|
|
|
|
{ "//foo", "\\\\foo", NULL},
|
|
|
|
{ "\\/foo", "\\\\foo", NULL},
|
|
|
|
{ "//", "\\\\", NULL},
|
|
|
|
{ "//foo/", "\\\\foo\\", NULL},
|
|
|
|
|
|
|
|
{ "//.", "\\\\.\\", NULL},
|
|
|
|
{ "//./", "\\\\.\\", NULL},
|
|
|
|
{ "//.//", "\\\\.\\", NULL},
|
|
|
|
{ "//./foo", "\\\\.\\foo", "foo"},
|
|
|
|
{ "//./foo/", "\\\\.\\foo\\", NULL},
|
|
|
|
{ "//./foo/bar", "\\\\.\\foo\\bar", "bar"},
|
|
|
|
{ "//./foo/.", "\\\\.\\foo", "foo"},
|
|
|
|
{ "//./foo/..", "\\\\.\\", NULL},
|
|
|
|
|
|
|
|
{ "//?/", "\\\\?\\", NULL},
|
|
|
|
{ "//?//", "\\\\?\\", NULL},
|
|
|
|
{ "//?/foo", "\\\\?\\foo", "foo"},
|
|
|
|
{ "//?/foo/", "\\\\?\\foo\\", NULL},
|
|
|
|
{ "//?/foo/bar", "\\\\?\\foo\\bar", "bar"},
|
|
|
|
{ "//?/foo/.", "\\\\?\\foo", "foo"},
|
|
|
|
{ "//?/foo/..", "\\\\?\\", NULL},
|
|
|
|
|
|
|
|
/* RtlGetFullPathName_U() can't understand the global namespace prefix */
|
|
|
|
{ "\\??\\foo", "C:\\??\\foo", "foo"},
|
|
|
|
{ 0 }
|
2004-03-23 00:00:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
const struct test *test;
|
|
|
|
WCHAR pathbufW[2*MAX_PATH], rbufferW[MAX_PATH];
|
2018-08-24 05:50:05 +02:00
|
|
|
char rbufferA[MAX_PATH], rfileA[MAX_PATH], curdir[MAX_PATH];
|
2004-03-23 00:00:13 +01:00
|
|
|
ULONG ret;
|
|
|
|
WCHAR *file_part;
|
|
|
|
DWORD reslen;
|
2005-02-14 22:04:45 +01:00
|
|
|
UINT len;
|
2004-03-23 00:00:13 +01:00
|
|
|
|
2018-08-24 05:50:05 +02:00
|
|
|
GetCurrentDirectoryA(sizeof(curdir), curdir);
|
|
|
|
SetCurrentDirectoryA("C:\\windows\\");
|
2013-09-25 08:36:33 +02:00
|
|
|
|
2010-06-17 06:40:04 +02:00
|
|
|
file_part = (WCHAR *)0xdeadbeef;
|
|
|
|
lstrcpyW(rbufferW, deadbeefW);
|
|
|
|
ret = pRtlGetFullPathName_U(NULL, MAX_PATH, rbufferW, &file_part);
|
|
|
|
ok(!ret, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret);
|
|
|
|
ok(!lstrcmpW(rbufferW, deadbeefW),
|
|
|
|
"Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW));
|
|
|
|
ok(file_part == (WCHAR *)0xdeadbeef ||
|
|
|
|
file_part == NULL, /* Win7 */
|
|
|
|
"Expected file part pointer to be untouched, got %p\n", file_part);
|
|
|
|
|
|
|
|
file_part = (WCHAR *)0xdeadbeef;
|
|
|
|
lstrcpyW(rbufferW, deadbeefW);
|
|
|
|
ret = pRtlGetFullPathName_U(emptyW, MAX_PATH, rbufferW, &file_part);
|
|
|
|
ok(!ret, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret);
|
|
|
|
ok(!lstrcmpW(rbufferW, deadbeefW),
|
|
|
|
"Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW));
|
|
|
|
ok(file_part == (WCHAR *)0xdeadbeef ||
|
|
|
|
file_part == NULL, /* Win7 */
|
|
|
|
"Expected file part pointer to be untouched, got %p\n", file_part);
|
|
|
|
|
2004-03-23 00:00:13 +01:00
|
|
|
for (test = tests; test->path; test++)
|
|
|
|
{
|
|
|
|
len= strlen(test->rname) * sizeof(WCHAR);
|
|
|
|
pRtlMultiByteToUnicodeN(pathbufW , sizeof(pathbufW), NULL, test->path, strlen(test->path)+1 );
|
|
|
|
ret = pRtlGetFullPathName_U( pathbufW,MAX_PATH, rbufferW, &file_part);
|
2008-11-05 19:58:21 +01:00
|
|
|
ok( ret == len || (test->alt_rname && ret == strlen(test->alt_rname)*sizeof(WCHAR)),
|
|
|
|
"Wrong result %d/%d for \"%s\"\n", ret, len, test->path );
|
2006-01-27 16:18:05 +01:00
|
|
|
ok(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,(lstrlenW(rbufferW) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
|
2004-03-23 00:00:13 +01:00
|
|
|
"RtlUnicodeToMultiByteN failed\n");
|
2016-07-28 14:24:05 +02:00
|
|
|
ok(!lstrcmpA(rbufferA,test->rname) || (test->alt_rname && !lstrcmpA(rbufferA,test->alt_rname)),
|
2008-11-05 19:58:21 +01:00
|
|
|
"Got \"%s\" expected \"%s\"\n",rbufferA,test->rname);
|
2004-03-23 00:00:13 +01:00
|
|
|
if (file_part)
|
|
|
|
{
|
2006-01-27 16:18:05 +01:00
|
|
|
ok(pRtlUnicodeToMultiByteN(rfileA,MAX_PATH,&reslen,file_part,(lstrlenW(file_part) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
|
2004-03-23 00:00:13 +01:00
|
|
|
"RtlUnicodeToMultiByteN failed\n");
|
2016-07-28 14:24:05 +02:00
|
|
|
ok((test->rfile && !lstrcmpA(rfileA,test->rfile)) ||
|
|
|
|
(test->alt_rfile && !lstrcmpA(rfileA,test->alt_rfile)),
|
2008-11-05 19:58:21 +01:00
|
|
|
"Got \"%s\" expected \"%s\"\n",rfileA,test->rfile);
|
2004-03-23 00:00:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok( !test->rfile, "Got NULL expected \"%s\"\n", test->rfile );
|
|
|
|
}
|
|
|
|
}
|
2018-08-24 05:50:05 +02:00
|
|
|
|
|
|
|
SetCurrentDirectoryA(curdir);
|
2004-03-23 00:00:13 +01:00
|
|
|
}
|
2003-04-12 02:10:13 +02:00
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
static void test_RtlDosPathNameToNtPathName_U(void)
|
2017-10-23 08:48:21 +02:00
|
|
|
{
|
2018-08-24 05:50:07 +02:00
|
|
|
static const WCHAR broken_global_prefix[] = {'\\','?','?','\\','C',':','\\','?','?'};
|
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
char curdir[MAX_PATH];
|
2017-10-23 08:48:21 +02:00
|
|
|
WCHAR path[MAX_PATH];
|
|
|
|
UNICODE_STRING nameW;
|
2018-08-24 05:50:06 +02:00
|
|
|
WCHAR *file_part;
|
2017-10-23 08:48:21 +02:00
|
|
|
NTSTATUS status;
|
2018-08-24 05:50:06 +02:00
|
|
|
BOOL ret, expect;
|
|
|
|
int i;
|
2017-10-23 08:48:21 +02:00
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
static const struct
|
2017-10-23 08:48:21 +02:00
|
|
|
{
|
2018-08-24 05:50:06 +02:00
|
|
|
const char *dos;
|
|
|
|
const char *nt;
|
|
|
|
int file_offset; /* offset to file part */
|
|
|
|
NTSTATUS status;
|
|
|
|
NTSTATUS alt_status;
|
|
|
|
int broken;
|
2017-10-23 08:48:21 +02:00
|
|
|
}
|
2018-08-24 05:50:06 +02:00
|
|
|
tests[] =
|
|
|
|
{
|
|
|
|
{ "c:\\", "\\??\\c:\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "c:/", "\\??\\c:\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo", "\\??\\c:\\foo", 7, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo.", "\\??\\c:\\foo", 7, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo/", "\\??\\c:\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo//", "\\??\\c:\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "C:/foo", "\\??\\C:\\foo", 7, STATUS_SUCCESS },
|
|
|
|
{ "C:/foo/bar", "\\??\\C:\\foo\\bar", 11, STATUS_SUCCESS },
|
|
|
|
{ "C:/foo/bar", "\\??\\C:\\foo\\bar", 11, STATUS_SUCCESS },
|
|
|
|
{ "c:.", "\\??\\C:\\windows", 7, STATUS_SUCCESS },
|
|
|
|
{ "c:foo", "\\??\\C:\\windows\\foo", 15, STATUS_SUCCESS },
|
|
|
|
{ "c:foo/bar", "\\??\\C:\\windows\\foo\\bar", 19, STATUS_SUCCESS },
|
|
|
|
{ "c:./foo", "\\??\\C:\\windows\\foo", 15, STATUS_SUCCESS },
|
|
|
|
{ "c:/./foo", "\\??\\c:\\foo", 7, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo/.", "\\??\\c:\\foo", 7, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo/./bar", "\\??\\c:\\foo\\bar", 11, STATUS_SUCCESS },
|
|
|
|
{ "c:/foo/../bar", "\\??\\c:\\bar", 7, STATUS_SUCCESS },
|
|
|
|
{ "\\foo", "\\??\\C:\\foo", 7, STATUS_SUCCESS },
|
|
|
|
{ "foo", "\\??\\C:\\windows\\foo", 15, STATUS_SUCCESS },
|
|
|
|
{ ".", "\\??\\C:\\windows", 7, STATUS_SUCCESS },
|
|
|
|
{ "./", "\\??\\C:\\windows\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "..", "\\??\\C:\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "...", "\\??\\C:\\windows\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "./foo", "\\??\\C:\\windows\\foo", 15, STATUS_SUCCESS },
|
|
|
|
{ "foo/..", "\\??\\C:\\windows", 7, STATUS_SUCCESS },
|
|
|
|
{ "AUX" , "\\??\\AUX", -1, STATUS_SUCCESS },
|
|
|
|
{ "COM1" , "\\??\\COM1", -1, STATUS_SUCCESS },
|
|
|
|
{ "?<>*\"|:", "\\??\\C:\\windows\\?<>*\"|:", 15, STATUS_SUCCESS },
|
|
|
|
|
|
|
|
{ "", NULL, -1, STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND },
|
|
|
|
{ NULL, NULL, -1, STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND },
|
|
|
|
{ " ", NULL, -1, STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_PATH_NOT_FOUND },
|
|
|
|
|
|
|
|
{ "\\\\foo", "\\??\\UNC\\foo", -1, STATUS_SUCCESS },
|
|
|
|
{ "//foo", "\\??\\UNC\\foo", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\/foo", "\\??\\UNC\\foo", -1, STATUS_SUCCESS },
|
|
|
|
{ "//", "\\??\\UNC\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//foo/", "\\??\\UNC\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
|
|
|
|
{ "//.", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//./", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//.//", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//./foo", "\\??\\foo", 4, STATUS_SUCCESS },
|
|
|
|
{ "//./foo/", "\\??\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//./foo/bar", "\\??\\foo\\bar", 8, STATUS_SUCCESS },
|
|
|
|
{ "//./foo/.", "\\??\\foo", 4, STATUS_SUCCESS },
|
|
|
|
{ "//./foo/..", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
|
|
|
|
{ "//?", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//?/", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//?//", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//?/foo", "\\??\\foo", 4, STATUS_SUCCESS },
|
|
|
|
{ "//?/foo/", "\\??\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "//?/foo/bar", "\\??\\foo\\bar", 8, STATUS_SUCCESS },
|
|
|
|
{ "//?/foo/.", "\\??\\foo", 4, STATUS_SUCCESS },
|
|
|
|
{ "//?/foo/..", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
|
|
|
|
{ "\\\\?", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\", "\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
|
|
|
|
{ "\\\\?\\/", "\\??\\/", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo", "\\??\\foo", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo/", "\\??\\foo/", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo/bar", "\\??\\foo/bar", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo/.", "\\??\\foo/.", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo/..", "\\??\\foo/..", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\\\", "\\??\\\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\\\\\", "\\??\\\\\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo\\", "\\??\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo\\bar", "\\??\\foo\\bar", 8, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo\\.", "\\??\\foo\\.", 8, STATUS_SUCCESS },
|
|
|
|
{ "\\\\?\\foo\\..", "\\??\\foo\\..", 8, STATUS_SUCCESS },
|
2018-08-24 05:50:07 +02:00
|
|
|
|
|
|
|
{ "\\??", "\\??\\C:\\??", 7, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\", "\\??\\C:\\??\\", -1, STATUS_SUCCESS },
|
|
|
|
|
|
|
|
{ "\\??\\/", "\\??\\/", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo", "\\??\\foo", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo/", "\\??\\foo/", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo/bar", "\\??\\foo/bar", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo/.", "\\??\\foo/.", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo/..", "\\??\\foo/..", 4, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\\\", "\\??\\\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\\\\\", "\\??\\\\\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo\\", "\\??\\foo\\", -1, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo\\bar", "\\??\\foo\\bar", 8, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo\\.", "\\??\\foo\\.", 8, STATUS_SUCCESS },
|
|
|
|
{ "\\??\\foo\\..", "\\??\\foo\\..", 8, STATUS_SUCCESS },
|
2018-08-24 05:50:06 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
GetCurrentDirectoryA(sizeof(curdir), curdir);
|
|
|
|
SetCurrentDirectoryA("C:\\windows\\");
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests); ++i)
|
|
|
|
{
|
2018-08-28 13:23:14 +02:00
|
|
|
MultiByteToWideChar(CP_ACP, 0, tests[i].dos, -1, path, ARRAY_SIZE(path));
|
2018-08-24 05:50:06 +02:00
|
|
|
ret = pRtlDosPathNameToNtPathName_U(path, &nameW, &file_part, NULL);
|
|
|
|
|
|
|
|
if (pRtlDosPathNameToNtPathName_U_WithStatus)
|
|
|
|
{
|
2018-12-13 04:32:43 +01:00
|
|
|
RtlFreeUnicodeString(&nameW);
|
2018-08-24 05:50:06 +02:00
|
|
|
status = pRtlDosPathNameToNtPathName_U_WithStatus(path, &nameW, &file_part, NULL);
|
|
|
|
ok(status == tests[i].status || status == tests[i].alt_status,
|
|
|
|
"%s: Expected status %#x, got %#x.\n", tests[i].dos, tests[i].status, status);
|
|
|
|
}
|
2017-10-23 08:48:21 +02:00
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
expect = (tests[i].status == STATUS_SUCCESS);
|
|
|
|
ok(ret == expect, "%s: Expected %#x, got %#x.\n", tests[i].dos, expect, ret);
|
2017-10-23 08:48:21 +02:00
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
if (ret != TRUE) continue;
|
2017-10-23 08:48:21 +02:00
|
|
|
|
2018-08-24 05:50:07 +02:00
|
|
|
if (!strncmp(tests[i].dos, "\\??\\", 4) && tests[i].dos[4] &&
|
|
|
|
broken(!memcmp(nameW.Buffer, broken_global_prefix, sizeof(broken_global_prefix))))
|
|
|
|
{
|
|
|
|
/* Windows version prior to 2003 don't interpret the \??\ prefix */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-28 13:23:14 +02:00
|
|
|
MultiByteToWideChar(CP_ACP, 0, tests[i].nt, -1, path, ARRAY_SIZE(path));
|
2018-08-24 05:50:06 +02:00
|
|
|
ok(!lstrcmpW(nameW.Buffer, path), "%s: Expected %s, got %s.\n",
|
|
|
|
tests[i].dos, tests[i].nt, wine_dbgstr_w(nameW.Buffer));
|
2017-10-23 08:48:21 +02:00
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
if (tests[i].file_offset > 0)
|
|
|
|
ok(file_part == nameW.Buffer + tests[i].file_offset,
|
|
|
|
"%s: Expected file part %s, got %s.\n", tests[i].dos,
|
|
|
|
wine_dbgstr_w(nameW.Buffer + tests[i].file_offset), wine_dbgstr_w(file_part));
|
|
|
|
else
|
|
|
|
ok(file_part == NULL, "%s: Expected NULL file part, got %s.\n",
|
|
|
|
tests[i].dos, wine_dbgstr_w(file_part));
|
|
|
|
|
|
|
|
RtlFreeUnicodeString(&nameW);
|
|
|
|
}
|
2017-10-23 08:48:21 +02:00
|
|
|
|
2018-08-24 05:50:06 +02:00
|
|
|
SetCurrentDirectoryA(curdir);
|
2017-10-23 08:48:21 +02:00
|
|
|
}
|
|
|
|
|
2003-04-12 02:10:13 +02:00
|
|
|
START_TEST(path)
|
|
|
|
{
|
|
|
|
HMODULE mod = GetModuleHandleA("ntdll.dll");
|
2008-09-21 20:21:58 +02:00
|
|
|
if (!mod)
|
|
|
|
{
|
|
|
|
win_skip("Not running on NT, skipping tests\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-12 02:10:13 +02:00
|
|
|
pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
|
2004-03-23 00:00:13 +01:00
|
|
|
pRtlUnicodeToMultiByteN = (void *)GetProcAddress(mod,"RtlUnicodeToMultiByteN");
|
2003-04-12 02:10:13 +02:00
|
|
|
pRtlDetermineDosPathNameType_U = (void *)GetProcAddress(mod,"RtlDetermineDosPathNameType_U");
|
|
|
|
pRtlIsDosDeviceName_U = (void *)GetProcAddress(mod,"RtlIsDosDeviceName_U");
|
2003-04-17 01:15:29 +02:00
|
|
|
pRtlOemStringToUnicodeString = (void *)GetProcAddress(mod,"RtlOemStringToUnicodeString");
|
|
|
|
pRtlIsNameLegalDOS8Dot3 = (void *)GetProcAddress(mod,"RtlIsNameLegalDOS8Dot3");
|
2004-03-23 00:00:13 +01:00
|
|
|
pRtlGetFullPathName_U = (void *)GetProcAddress(mod,"RtlGetFullPathName_U");
|
2018-08-24 05:50:06 +02:00
|
|
|
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(mod, "RtlDosPathNameToNtPathName_U");
|
2017-10-23 08:48:21 +02:00
|
|
|
pRtlDosPathNameToNtPathName_U_WithStatus = (void *)GetProcAddress(mod, "RtlDosPathNameToNtPathName_U_WithStatus");
|
2013-09-25 08:36:33 +02:00
|
|
|
|
|
|
|
test_RtlDetermineDosPathNameType_U();
|
|
|
|
test_RtlIsDosDeviceName_U();
|
|
|
|
test_RtlIsNameLegalDOS8Dot3();
|
|
|
|
test_RtlGetFullPathName_U();
|
2018-08-24 05:50:06 +02:00
|
|
|
test_RtlDosPathNameToNtPathName_U();
|
2003-04-12 02:10:13 +02:00
|
|
|
}
|