relative optional parameter will now be handled by setting the RelativeName of the relative struct to NT converted and collapsed relative path and the ContainingDirectory to an open handle of current working directory. CurDir is currently not implemented.
-- v2: ntdll: Implement handling of relative parameter for RtlDosPathNameToRelativeNtPathName_U_WithStatus ntdll/tests: Add tests to verify relative pathname and container directory filling. Also additional entries to test more relative pathname cases
From: Rayhan Faizel rayhan.faizel@hotmail.com
--- dlls/ntdll/tests/path.c | 275 ++++++++++++++++++++++------------------ 1 file changed, 153 insertions(+), 122 deletions(-)
diff --git a/dlls/ntdll/tests/path.c b/dlls/ntdll/tests/path.c index 4732f6a6aa8..3f41b27a522 100644 --- a/dlls/ntdll/tests/path.c +++ b/dlls/ntdll/tests/path.c @@ -31,6 +31,7 @@ static BOOLEAN (WINAPI *pRtlIsNameLegalDOS8Dot3)(const UNICODE_STRING*,POEM_STRI static DWORD (WINAPI *pRtlGetFullPathName_U)(const WCHAR*,ULONG,WCHAR*,WCHAR**); static BOOLEAN (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR*, UNICODE_STRING*, WCHAR**, CURDIR*); static NTSTATUS (WINAPI *pRtlDosPathNameToNtPathName_U_WithStatus)(const WCHAR*, UNICODE_STRING*, WCHAR**, CURDIR*); +static NTSTATUS (WINAPI* pRtlDosPathNameToRelativeNtPathName_U_WithStatus)(const WCHAR *dos_path,UNICODE_STRING *ntpath, WCHAR **file_part, RTL_RELATIVE_NAME *relative); static NTSTATUS (WINAPI *pNtOpenFile)( HANDLE*, ACCESS_MASK, OBJECT_ATTRIBUTES*, IO_STATUS_BLOCK*, ULONG, ULONG );
static void test_RtlDetermineDosPathNameType_U(void) @@ -434,134 +435,140 @@ static void test_RtlDosPathNameToNtPathName_U(void) const WCHAR *dos; const WCHAR *nt; int file_offset; /* offset to file part */ + const WCHAR* relative; const WCHAR *alt_nt; BOOL may_fail; } tests[] = { - {L"c:\", L"\??\c:\", -1}, - {L"c:/", L"\??\c:\", -1}, - {L"c:/foo", L"\??\c:\foo", 7}, - {L"c:/foo.", L"\??\c:\foo", 7}, - {L"c:/foo ", L"\??\c:\foo", 7}, - {L"c:/foo . .", L"\??\c:\foo", 7}, - {L"c:/foo.a", L"\??\c:\foo.a", 7}, - {L"c:/foo a", L"\??\c:\foo a", 7}, - {L"c:/foo*", L"\??\c:\foo*", 7}, - {L"c:/foo*a", L"\??\c:\foo*a", 7}, - {L"c:/foo?", L"\??\c:\foo?", 7}, - {L"c:/foo?a", L"\??\c:\foo?a", 7}, - {L"c:/foo<", L"\??\c:\foo<", 7}, - {L"c:/foo<a", L"\??\c:\foo<a", 7}, - {L"c:/foo>", L"\??\c:\foo>", 7}, - {L"c:/foo>a", L"\??\c:\foo>a", 7}, - {L"c:/foo/", L"\??\c:\foo\", -1}, - {L"c:/foo//", L"\??\c:\foo\", -1}, - {L"C:/foo", L"\??\C:\foo", 7}, - {L"C:/foo/bar", L"\??\C:\foo\bar", 11}, - {L"C:/foo/bar", L"\??\C:\foo\bar", 11}, - {L"c:.", L"\??\C:\windows", 7}, - {L"c:foo", L"\??\C:\windows\foo", 15}, - {L"c:foo/bar", L"\??\C:\windows\foo\bar", 19}, - {L"c:./foo", L"\??\C:\windows\foo", 15}, - {L"c:/./foo", L"\??\c:\foo", 7}, - {L"c:/..", L"\??\c:\", -1}, - {L"c:/foo/.", L"\??\c:\foo", 7}, - {L"c:/foo/./bar", L"\??\c:\foo\bar", 11}, - {L"c:/foo/../bar", L"\??\c:\bar", 7}, - {L"\foo", L"\??\C:\foo", 7}, - {L"foo", L"\??\C:\windows\foo", 15}, - {L".", L"\??\C:\windows", 7}, - {L"./", L"\??\C:\windows\", -1}, - {L"..", L"\??\C:\", -1}, - {L"...", L"\??\C:\windows\", -1}, - {L"./foo", L"\??\C:\windows\foo", 15}, - {L"foo/..", L"\??\C:\windows", 7}, - {L"\windows\nul", L"\??\nul", -1}, - {L"C:NUL.", L"\??\NUL", -1}, - {L"C:NUL", L"\??\NUL", -1}, - {L"AUX" , L"\??\AUX", -1}, - {L"COM1" , L"\??\COM1", -1}, - {L"?<>*"|:", L"\??\C:\windows\?<>*"|:", 15}, - {L"?:", L"\??\?:\", -1}, - - {L"\\foo", L"\??\UNC\foo", -1}, - {L"//foo", L"\??\UNC\foo", -1}, - {L"\/foo", L"\??\UNC\foo", -1}, - {L"//", L"\??\UNC\", -1}, - {L"//foo/", L"\??\UNC\foo\", -1}, - - {L"//.", L"\??\", -1}, - {L"//./", L"\??\", -1}, - {L"//.//", L"\??\", -1}, - {L"//./foo", L"\??\foo", 4}, - {L"//./foo/", L"\??\foo\", -1}, - {L"//./foo/bar", L"\??\foo\bar", 8}, - {L"//./foo/.", L"\??\foo", 4}, - {L"//./foo/..", L"\??\", -1}, - {L"//./foo. . ", L"\??\foo", 4}, - - {L"//?", L"\??\", -1}, - {L"//?/", L"\??\", -1}, - {L"//?//", L"\??\", -1}, - {L"//?/foo", L"\??\foo", 4}, - {L"//?/foo/", L"\??\foo\", -1}, - {L"//?/foo/bar", L"\??\foo\bar", 8}, - {L"//?/foo/.", L"\??\foo", 4}, - {L"//?/foo/..", L"\??\", -1}, - {L"//?/foo. . ", L"\??\foo", 4}, - - {L"\\.", L"\??\", -1}, - {L"\\.\", L"\??\", -1}, - {L"\\.\/", L"\??\", -1}, - {L"\\.\foo", L"\??\foo", 4}, - {L"\\.\foo/", L"\??\foo\", -1}, - {L"\\.\foo/bar", L"\??\foo\bar", 8}, - {L"\\.\foo/.", L"\??\foo", 4}, - {L"\\.\foo/..", L"\??\", -1}, - {L"\\.\foo. . ", L"\??\foo", 4}, - {L"\\.\CON", L"\??\CON", 4, NULL, TRUE}, /* broken on win7 */ - {L"\\.\CONIN$", L"\??\CONIN$", 4}, - {L"\\.\CONOUT$", L"\??\CONOUT$", 4}, + {L"c:\", L"\??\c:\", -1, NULL}, + {L"c:/", L"\??\c:\", -1, NULL}, + {L"c:/foo", L"\??\c:\foo", 7, NULL}, + {L"c:/foo.", L"\??\c:\foo", 7, NULL}, + {L"c:/foo ", L"\??\c:\foo", 7, NULL}, + {L"c:/foo . .", L"\??\c:\foo", 7, NULL}, + {L"c:/foo.a", L"\??\c:\foo.a", 7, NULL}, + {L"c:/foo a", L"\??\c:\foo a", 7, NULL}, + {L"c:/foo*", L"\??\c:\foo*", 7, NULL}, + {L"c:/foo*a", L"\??\c:\foo*a", 7, NULL}, + {L"c:/foo?", L"\??\c:\foo?", 7, NULL}, + {L"c:/foo?a", L"\??\c:\foo?a", 7, NULL}, + {L"c:/foo<", L"\??\c:\foo<", 7, NULL}, + {L"c:/foo<a", L"\??\c:\foo<a", 7, NULL}, + {L"c:/foo>", L"\??\c:\foo>", 7, NULL}, + {L"c:/foo>a", L"\??\c:\foo>a", 7, NULL}, + {L"c:/foo/", L"\??\c:\foo\", -1, NULL}, + {L"c:/foo//", L"\??\c:\foo\", -1, NULL}, + {L"C:/foo", L"\??\C:\foo", 7, NULL}, + {L"C:/foo/bar", L"\??\C:\foo\bar", 11, NULL}, + {L"C:/foo/bar", L"\??\C:\foo\bar", 11, NULL}, + {L"c:.", L"\??\C:\windows", 7, NULL}, + {L"c:foo", L"\??\C:\windows\foo", 15, NULL}, + {L"c:foo/bar", L"\??\C:\windows\foo\bar", 19, NULL}, + {L"c:./foo", L"\??\C:\windows\foo", 15, NULL}, + {L"c:/./foo", L"\??\c:\foo", 7, NULL}, + {L"c:/..", L"\??\c:\", -1, NULL}, + {L"c:/foo/.", L"\??\c:\foo", 7, NULL}, + {L"c:/foo/./bar", L"\??\c:\foo\bar", 11, NULL}, + {L"c:/foo/../bar", L"\??\c:\bar", 7, NULL}, + {L"\foo", L"\??\C:\foo", 7, NULL}, + {L"foo", L"\??\C:\windows\foo", 15, L"foo"}, + {L".", L"\??\C:\windows", 7, NULL}, + {L"./", L"\??\C:\windows\", -1, L""}, + {L"..", L"\??\C:\", -1, NULL}, + {L"...", L"\??\C:\windows\", -1, L""}, + {L"./foo", L"\??\C:\windows\foo", 15, L"foo"}, + {L"./foo/bar", L"\??\C:\windows\foo\bar", 19, L"foo\bar"}, + + {L"foo/bar/baz", L"\??\C:\windows\foo\bar\baz", 23, L"foo\bar\baz"}, + {L"foo/bar/baz/..", L"\??\C:\windows\foo\bar", 19, L"foo\bar"}, + {L"foo/../..", L"\??\C:\", -1, NULL}, + + {L"\windows\nul", L"\??\nul", -1, NULL}, + {L"C:NUL.", L"\??\NUL", -1, NULL}, + {L"C:NUL", L"\??\NUL", -1, NULL}, + {L"AUX" , L"\??\AUX", -1, NULL}, + {L"COM1" , L"\??\COM1", -1, NULL}, + {L"?<>*"|:", L"\??\C:\windows\?<>*"|:", 15, L"?<>*"|:"}, + {L"?:", L"\??\?:\", -1, NULL}, + + {L"\\foo", L"\??\UNC\foo", -1, NULL}, + {L"//foo", L"\??\UNC\foo", -1, NULL}, + {L"\/foo", L"\??\UNC\foo", -1, NULL}, + {L"//", L"\??\UNC\", -1, NULL}, + {L"//foo/", L"\??\UNC\foo\", -1, NULL}, + + {L"//.", L"\??\", -1, NULL}, + {L"//./", L"\??\", -1, NULL}, + {L"//.//", L"\??\", -1, NULL}, + {L"//./foo", L"\??\foo", 4, NULL}, + {L"//./foo/", L"\??\foo\", -1, NULL}, + {L"//./foo/bar", L"\??\foo\bar", 8, NULL}, + {L"//./foo/.", L"\??\foo", 4, NULL}, + {L"//./foo/..", L"\??\", -1, NULL}, + {L"//./foo. . ", L"\??\foo", 4, NULL}, + + {L"//?", L"\??\", -1,NULL}, + {L"//?/", L"\??\", -1, NULL}, + {L"//?//", L"\??\", -1,NULL}, + {L"//?/foo", L"\??\foo", 4,NULL}, + {L"//?/foo/", L"\??\foo\", -1, NULL}, + {L"//?/foo/bar", L"\??\foo\bar", 8, NULL}, + {L"//?/foo/.", L"\??\foo", 4, NULL}, + {L"//?/foo/..", L"\??\", -1, NULL}, + {L"//?/foo. . ", L"\??\foo", 4, NULL}, + + {L"\\.", L"\??\", -1, NULL}, + {L"\\.\", L"\??\", -1, NULL}, + {L"\\.\/", L"\??\", -1, NULL}, + {L"\\.\foo", L"\??\foo", 4, NULL}, + {L"\\.\foo/", L"\??\foo\", -1, NULL}, + {L"\\.\foo/bar", L"\??\foo\bar", 8, NULL}, + {L"\\.\foo/.", L"\??\foo", 4, NULL}, + {L"\\.\foo/..", L"\??\", -1, NULL}, + {L"\\.\foo. . ", L"\??\foo", 4, NULL}, + {L"\\.\CON", L"\??\CON", 4, NULL,NULL, TRUE}, /* broken on win7 */ + {L"\\.\CONIN$", L"\??\CONIN$", 4, NULL}, + {L"\\.\CONOUT$", L"\??\CONOUT$", 4, NULL},
{L"\\?", L"\??\", -1}, - {L"\\?\", L"\??\", -1}, - - {L"\\?\/", L"\??\/", 4}, - {L"\\?\foo", L"\??\foo", 4}, - {L"\\?\foo/", L"\??\foo/", 4}, - {L"\\?\foo/bar", L"\??\foo/bar", 4}, - {L"\\?\foo/.", L"\??\foo/.", 4}, - {L"\\?\foo/..", L"\??\foo/..", 4}, - {L"\\?\\", L"\??\\", -1}, - {L"\\?\\\", L"\??\\\", -1}, - {L"\\?\foo\", L"\??\foo\", -1}, - {L"\\?\foo\bar",L"\??\foo\bar", 8}, - {L"\\?\foo\.", L"\??\foo\.", 8}, - {L"\\?\foo\..", L"\??\foo\..", 8}, - {L"\\?\foo. . ", L"\??\foo. . ", 4}, - - {L"\??", L"\??\C:\??", 7}, - {L"\??\", L"\??\C:\??\", -1}, - - {L"\??\/", L"\??\/", 4}, - {L"\??\foo", L"\??\foo", 4}, - {L"\??\foo/", L"\??\foo/", 4}, - {L"\??\foo/bar", L"\??\foo/bar", 4}, - {L"\??\foo/.", L"\??\foo/.", 4}, - {L"\??\foo/..", L"\??\foo/..", 4}, - {L"\??\\", L"\??\\", -1}, - {L"\??\\\", L"\??\\\", -1}, - {L"\??\foo\", L"\??\foo\", -1}, - {L"\??\foo\bar", L"\??\foo\bar", 8}, - {L"\??\foo\.", L"\??\foo\.", 8}, - {L"\??\foo\..", L"\??\foo\..", 8}, - {L"\??\foo. . ", L"\??\foo. . ", 4}, - - {L"CONIN$", L"\??\CONIN$", -1, L"\??\C:\windows\CONIN$" /* win7 */ }, - {L"CONOUT$", L"\??\CONOUT$", -1, L"\??\C:\windows\CONOUT$" /* win7 */ }, - {L"cOnOuT$", L"\??\cOnOuT$", -1, L"\??\C:\windows\cOnOuT$" /* win7 */ }, - {L"CONERR$", L"\??\C:\windows\CONERR$", 15}, + {L"\\?\", L"\??\", -1, NULL}, + + {L"\\?\/", L"\??\/", 4, NULL}, + {L"\\?\foo", L"\??\foo", 4, NULL}, + {L"\\?\foo/", L"\??\foo/", 4, NULL}, + {L"\\?\foo/bar", L"\??\foo/bar", 4, NULL}, + {L"\\?\foo/.", L"\??\foo/.", 4, NULL}, + {L"\\?\foo/..", L"\??\foo/..", 4, NULL}, + {L"\\?\\", L"\??\\", -1, NULL}, + {L"\\?\\\", L"\??\\\", -1, NULL}, + {L"\\?\foo\", L"\??\foo\", -1, NULL}, + {L"\\?\foo\bar",L"\??\foo\bar", 8, NULL}, + {L"\\?\foo\.", L"\??\foo\.", 8, NULL}, + {L"\\?\foo\..", L"\??\foo\..", 8, NULL}, + {L"\\?\foo. . ", L"\??\foo. . ", 4, NULL}, + + {L"\??", L"\??\C:\??", 7, NULL}, + {L"\??\", L"\??\C:\??\", -1, NULL}, + + {L"\??\/", L"\??\/", 4, NULL}, + {L"\??\foo", L"\??\foo", 4, NULL}, + {L"\??\foo/", L"\??\foo/", 4, NULL}, + {L"\??\foo/bar", L"\??\foo/bar", 4, NULL}, + {L"\??\foo/.", L"\??\foo/.", 4, NULL}, + {L"\??\foo/..", L"\??\foo/..", 4, NULL}, + {L"\??\\", L"\??\\", -1, NULL}, + {L"\??\\\", L"\??\\\", -1, NULL}, + {L"\??\foo\", L"\??\foo\", -1, NULL}, + {L"\??\foo\bar", L"\??\foo\bar", 8, NULL}, + {L"\??\foo\.", L"\??\foo\.", 8, NULL}, + {L"\??\foo\..", L"\??\foo\..", 8, NULL}, + {L"\??\foo. . ", L"\??\foo. . ", 4, NULL}, + + {L"CONIN$", L"\??\CONIN$", -1, NULL,L"\??\C:\windows\CONIN$" /* win7 */ }, + {L"CONOUT$", L"\??\CONOUT$", -1, NULL,L"\??\C:\windows\CONOUT$" /* win7 */ }, + {L"cOnOuT$", L"\??\cOnOuT$", -1, NULL,L"\??\C:\windows\cOnOuT$" /* win7 */ }, + {L"CONERR$", L"\??\C:\windows\CONERR$", 15, L"CONERR$"}, }; static const WCHAR *error_paths[] = { NULL, L"", L" ", L"C:\nonexistent\nul", L"C:\con\con" @@ -619,6 +626,30 @@ static void test_RtlDosPathNameToNtPathName_U(void) debugstr_w(tests[i].dos), debugstr_w(file_part)); }
+ + if (pRtlDosPathNameToRelativeNtPathName_U_WithStatus) + { + RTL_RELATIVE_NAME rtl; + + RtlFreeUnicodeString(&nameW); + status = pRtlDosPathNameToRelativeNtPathName_U_WithStatus(tests[i].dos, &nameW, &file_part, &rtl); + ok(status == STATUS_SUCCESS, "%s: Got status %#lx.\n", debugstr_w(tests[i].dos), status); + + + if (tests[i].relative) + { + ok(rtl.RelativeName.Buffer != NULL && !wcscmp(rtl.RelativeName.Buffer,tests[i].relative), + "%s: Expected %s, got %s.\n", debugstr_w(tests[i].dos), debugstr_w(tests[i].relative), debugstr_w(rtl.RelativeName.Buffer)); + ok(rtl.ContainerDirectory != 0, "%s: containing directory handle not created.\n",debugstr_w(tests[i].dos)); + } + else + { + ok(rtl.RelativeName.Buffer == NULL, + "%s: Expected NULL relative path, got %s\n", debugstr_w(tests[i].dos),debugstr_w(rtl.RelativeName.Buffer)); + ok(rtl.ContainerDirectory == 0, "%s: containing directory handle created.\n",debugstr_w(tests[i].dos)); + + } + } RtlFreeUnicodeString(&nameW); }
@@ -726,7 +757,6 @@ static void test_nt_names(void) } }
- START_TEST(path) { HMODULE mod = GetModuleHandleA("ntdll.dll"); @@ -741,6 +771,7 @@ START_TEST(path) pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(mod, "RtlDosPathNameToNtPathName_U"); pRtlDosPathNameToNtPathName_U_WithStatus = (void *)GetProcAddress(mod, "RtlDosPathNameToNtPathName_U_WithStatus"); pNtOpenFile = (void *)GetProcAddress(mod, "NtOpenFile"); + pRtlDosPathNameToRelativeNtPathName_U_WithStatus = (void*) GetProcAddress(mod,"RtlDosPathNameToRelativeNtPathName_U_WithStatus");
test_RtlDetermineDosPathNameType_U(); test_RtlIsDosDeviceName_U();
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=124724
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntdll: path.c:647: Test failed: L"CONIN$": Expected NULL relative path, got L"CONIN$" path.c:649: Test failed: L"CONIN$": containing directory handle created. path.c:647: Test failed: L"CONOUT$": Expected NULL relative path, got L"CONOUT$" path.c:649: Test failed: L"CONOUT$": containing directory handle created. path.c:647: Test failed: L"cOnOuT$": Expected NULL relative path, got L"cOnOuT$" path.c:649: Test failed: L"cOnOuT$": containing directory handle created.
=== w7u_adm (32 bit report) ===
ntdll: path.c:647: Test failed: L"CONIN$": Expected NULL relative path, got L"CONIN$" path.c:649: Test failed: L"CONIN$": containing directory handle created. path.c:647: Test failed: L"CONOUT$": Expected NULL relative path, got L"CONOUT$" path.c:649: Test failed: L"CONOUT$": containing directory handle created. path.c:647: Test failed: L"cOnOuT$": Expected NULL relative path, got L"cOnOuT$" path.c:649: Test failed: L"cOnOuT$": containing directory handle created.
=== w7u_el (32 bit report) ===
ntdll: path.c:647: Test failed: L"CONIN$": Expected NULL relative path, got L"CONIN$" path.c:649: Test failed: L"CONIN$": containing directory handle created. path.c:647: Test failed: L"CONOUT$": Expected NULL relative path, got L"CONOUT$" path.c:649: Test failed: L"CONOUT$": containing directory handle created. path.c:647: Test failed: L"cOnOuT$": Expected NULL relative path, got L"cOnOuT$" path.c:649: Test failed: L"cOnOuT$": containing directory handle created.
=== debian11 (32 bit report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit ar:MA report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit de report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit fr report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit he:IL report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit hi:IN report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit ja:JP report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit zh:CN report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (32 bit WoW report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
=== debian11 (64 bit WoW report) ===
ntdll: path.c:641: Test failed: L"foo": Expected L"foo", got (null). path.c:643: Test failed: L"foo": containing directory handle not created. path.c:641: Test failed: L"./": Expected L"", got (null). path.c:643: Test failed: L"./": containing directory handle not created. path.c:641: Test failed: L"...": Expected L"", got (null). path.c:643: Test failed: L"...": containing directory handle not created. path.c:641: Test failed: L"./foo": Expected L"foo", got (null). path.c:643: Test failed: L"./foo": containing directory handle not created. path.c:641: Test failed: L"./foo/bar": Expected L"foo\bar", got (null). path.c:643: Test failed: L"./foo/bar": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz": Expected L"foo\bar\baz", got (null). path.c:643: Test failed: L"foo/bar/baz": containing directory handle not created. path.c:641: Test failed: L"foo/bar/baz/..": Expected L"foo\bar", got (null). path.c:643: Test failed: L"foo/bar/baz/..": containing directory handle not created. path.c:641: Test failed: L"?<>*"|:": Expected L"?<>*"|:", got (null). path.c:643: Test failed: L"?<>*"|:": containing directory handle not created. path.c:641: Test failed: L"CONERR$": Expected L"CONERR$", got (null). path.c:643: Test failed: L"CONERR$": containing directory handle not created.
From: Rayhan Faizel rayhan.faizel@hotmail.com
--- dlls/ntdll/path.c | 229 +++++++++++++++++++++++++++++----------------- 1 file changed, 147 insertions(+), 82 deletions(-)
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index 37ad4bbcea2..6a5bbda4280 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -290,7 +290,6 @@ NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(const WCHAR *dos_path, U *file_part = ntpath->Buffer + ntpath->Length / sizeof(WCHAR) - wcslen(*file_part);
/* FIXME: cd filling */ - out: if (ptr != local) RtlFreeHeap(GetProcessHeap(), 0, ptr); return nts; @@ -309,6 +308,82 @@ BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR dos_path, return RtlDosPathNameToNtPathName_U_WithStatus(dos_path, ntpath, file_part, cd) == STATUS_SUCCESS; }
+ + +/****************************************************************** + * collapse_path + * + * Helper for RtlGetFullPathName_U. + * Get rid of . and .. components in the path. + */ +static inline void collapse_path( WCHAR *path, UINT mark ) +{ + WCHAR *p, *next; + + /* convert every / into a \ */ + for (p = path; *p; p++) if (*p == '/') *p = '\'; + + /* collapse duplicate backslashes */ + next = path + max( 1, mark ); + for (p = next; *p; p++) if (*p != '\' || next[-1] != '\') *next++ = *p; + *next = 0; + + p = path + mark; + while (*p) + { + if (*p == '.') + { + switch(p[1]) + { + case '\': /* .\ component */ + next = p + 2; + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + case 0: /* final . */ + if (p > path + mark) p--; + *p = 0; + continue; + case '.': + if (p[2] == '\') /* ..\ component */ + { + next = p + 3; + if (p > path + mark) + { + p--; + while (p > path + mark && p[-1] != '\') p--; + } + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + } + else if (!p[2]) /* final .. */ + { + if (p > path + mark) + { + p--; + while (p > path + mark && p[-1] != '\') p--; + if (p > path + mark) p--; + } + *p = 0; + continue; + } + break; + } + } + /* skip to the next component */ + while (*p && *p != '\') p++; + if (*p == '\') + { + /* remove last dot in previous dir name */ + if (p > path + mark && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) ); + else p++; + } + } + + /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ + while (p > path + mark && (p[-1] == ' ' || p[-1] == '.')) p--; + *p = 0; +} + /************************************************************************** * RtlDosPathNameToRelativeNtPathName_U_WithStatus [NTDLL.@] * @@ -317,17 +392,83 @@ BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR dos_path, NTSTATUS WINAPI RtlDosPathNameToRelativeNtPathName_U_WithStatus(const WCHAR *dos_path, UNICODE_STRING *ntpath, WCHAR **file_part, RTL_RELATIVE_NAME *relative) { + + NTSTATUS ret; TRACE("(%s,%p,%p,%p)\n", debugstr_w(dos_path), ntpath, file_part, relative);
+ + ret = RtlDosPathNameToNtPathName_U_WithStatus(dos_path, ntpath, file_part, NULL); + if (relative) { - FIXME("Unsupported parameter\n"); - memset(relative, 0, sizeof(*relative)); - } + DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U(dos_path); + DWORD dosdev = RtlIsDosDeviceName_U(dos_path); + + relative->RelativeName.Buffer = NULL; + relative->ContainerDirectory = 0; + relative->CurDirRef = NULL; + + if (type == RELATIVE_PATH && !dosdev) + { + HANDLE handle;
- /* FIXME: fill parameter relative */ + IO_STATUS_BLOCK io; + OBJECT_ATTRIBUTES attr; + NTSTATUS ret_rel, nts; + UNICODE_STRING *cur_dir, cur_dir_nt; + int dos_path_len = wcslen(dos_path); + + WCHAR *converted_path = RtlAllocateHeap(GetProcessHeap(), 0, (dos_path_len+1) * sizeof(WCHAR));; + wcscpy(converted_path, dos_path); + collapse_path(converted_path, 0); + + // RTL_Relative_name is filled for ./ and ... on real Windows for whatever reason, so we will make exceptions for these + if (wcscmp(dos_path,L"./") && wcscmp(dos_path,L".\") && wcscmp(dos_path,L"...") && wcslen(converted_path) == 0) + { + /* Collapsed path is empty so don't bother */ + memset(relative,0,sizeof(*relative)); + goto out; + } + + RtlInitUnicodeString(&(relative->RelativeName),converted_path);
- return RtlDosPathNameToNtPathName_U_WithStatus(dos_path, ntpath, file_part, NULL); + if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */ + cur_dir = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir.DosPath; + else + cur_dir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath; + + /* FIXME: Better way besides invoking this function twice? Maybe a more direct way of getting current dir in nt path form? */ + ret_rel = RtlDosPathNameToNtPathName_U_WithStatus(cur_dir->Buffer, &cur_dir_nt, NULL, NULL); + if (ret_rel == STATUS_SUCCESS) + { + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &cur_dir_nt; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + /* Give open directory handle */ + nts = NtOpenFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + + if (nts == STATUS_SUCCESS) + relative->ContainerDirectory = handle; + RtlFreeUnicodeString(&cur_dir_nt); + } + + + /* FIXME: No idea what this does. Some reference count or something? */ + relative->CurDirRef = NULL; + } + else + { + memset(relative,0,sizeof(*relative)); + } + } + out: + return ret; }
/************************************************************************** @@ -416,82 +557,6 @@ ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext, return len; }
- -/****************************************************************** - * collapse_path - * - * Helper for RtlGetFullPathName_U. - * Get rid of . and .. components in the path. - */ -static inline void collapse_path( WCHAR *path, UINT mark ) -{ - WCHAR *p, *next; - - /* convert every / into a \ */ - for (p = path; *p; p++) if (*p == '/') *p = '\'; - - /* collapse duplicate backslashes */ - next = path + max( 1, mark ); - for (p = next; *p; p++) if (*p != '\' || next[-1] != '\') *next++ = *p; - *next = 0; - - p = path + mark; - while (*p) - { - if (*p == '.') - { - switch(p[1]) - { - case '\': /* .\ component */ - next = p + 2; - memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); - continue; - case 0: /* final . */ - if (p > path + mark) p--; - *p = 0; - continue; - case '.': - if (p[2] == '\') /* ..\ component */ - { - next = p + 3; - if (p > path + mark) - { - p--; - while (p > path + mark && p[-1] != '\') p--; - } - memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); - continue; - } - else if (!p[2]) /* final .. */ - { - if (p > path + mark) - { - p--; - while (p > path + mark && p[-1] != '\') p--; - if (p > path + mark) p--; - } - *p = 0; - continue; - } - break; - } - } - /* skip to the next component */ - while (*p && *p != '\') p++; - if (*p == '\') - { - /* remove last dot in previous dir name */ - if (p > path + mark && p[-1] == '.') memmove( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) ); - else p++; - } - } - - /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ - while (p > path + mark && (p[-1] == ' ' || p[-1] == '.')) p--; - *p = 0; -} - - /****************************************************************** * skip_unc_prefix *
Hmm, I probably should have done the commits in reverse, because the bot seems to have completely ignored the commit after the tests hence the errors in the Debian VM.
I will also need to account for the Windows 7 alternate paths as well.
actually the test bot fails on your first commit (we require to have no test failures after each commit, not at the end of the serie)
so the preferred is to mark the tests with todo_wine in the first commit (actually showing what isn't working), and remove them in second commit (when you actually committed something)
the different results you get for win7 should be marked with a 'broken(...)' in the ok's condition