As the tests show after creating a kernel object with name "wine_test\0" it's possible to only open it as "wine_test\0", an attempt opening it as "wine_test" fails with STATUS_OBJECT_NAME_NOT_FOUND, and vice versa. Also the tests show that "wine\0test" is a valid kernel object name.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/ntdll/tests/om.c | 350 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 349 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c index 7fe0fb59f89..f98a8843d62 100644 --- a/dlls/ntdll/tests/om.c +++ b/dlls/ntdll/tests/om.c @@ -1580,7 +1580,8 @@ static void _test_object_name( unsigned line, HANDLE handle, const WCHAR *expect ok_(__FILE__,line)( status == STATUS_SUCCESS, "NtQueryObject failed %lx\n", status ); ok_(__FILE__,line)( len >= sizeof(OBJECT_NAME_INFORMATION) + str->Length, "unexpected len %lu\n", len ); todo_wine_if (todo) - ok_(__FILE__,line)(compare_unicode_string( str, expected_name ), "wrong name %s\n", debugstr_w( str->Buffer )); + ok_(__FILE__,line)(compare_unicode_string( str, expected_name ), "got %s, expected %s\n", + debugstr_w(str->Buffer), debugstr_w(expected_name)); }
static void test_query_object(void) @@ -2722,6 +2723,352 @@ static void test_query_directory(void) pNtClose( dir ); }
+#define test_object_name_with_null(a,b) _test_object_name_with_null(__LINE__,a,b) +static void _test_object_name_with_null(unsigned line, HANDLE handle, UNICODE_STRING *expect) +{ + char buffer[1024]; + UNICODE_STRING *str = (UNICODE_STRING *)buffer; + ULONG len = 0; + NTSTATUS status; + + memset(buffer, 0, sizeof(buffer)); + status = pNtQueryObject(handle, ObjectNameInformation, buffer, sizeof(buffer), &len); + ok_(__FILE__,line)(status == STATUS_SUCCESS, "got %08lx\n", status); + ok_(__FILE__,line)(len >= sizeof(OBJECT_NAME_INFORMATION) + str->Length, "got %lu\n", len); + ok_(__FILE__,line)(str->Length == expect->Length, "got %lu, expected %lu\n", str->Length, expect->Length); + ok_(__FILE__,line)(!wcsnicmp(str->Buffer, expect->Buffer, str->Length/sizeof(WCHAR)), "got %s, expected %s\n", + debugstr_w(str->Buffer), debugstr_w(expect->Buffer)); +} + +static void test_null_in_object_name(void) +{ + WCHAR name[256], name3[256], *p, *name_exp, *name3_exp; + HANDLE handle, handle2; + NTSTATUS status; + OBJECT_ATTRIBUTES attr, attr2, attr3; + UNICODE_STRING nameU, name2U, name3U, name2U_exp, name3U_exp; + LARGE_INTEGER size; +#ifndef _WIN64 + BOOL is_wow64 = FALSE; +#endif + + trace("running as %d bit\n", (int)sizeof(void *) * 8); + + swprintf(name, ARRAY_SIZE(name), L"\Sessions\%u\BaseNamedObjects\wine_test", NtCurrentTeb()->Peb->SessionId); + swprintf(name3, ARRAY_SIZE(name3), L"\Sessions\%u\BaseNamedObjects\wine_test", NtCurrentTeb()->Peb->SessionId); + p = wcsrchr(name3, '\'); + p[5] = 0; /* => \wine\0test */ + + RtlInitUnicodeString(&nameU, name); + InitializeObjectAttributes(&attr, &nameU, 0, 0, NULL); + + name2U = nameU; + name2U.Length += sizeof(WCHAR); /* add terminating \0 to string length */ + InitializeObjectAttributes(&attr2, &name2U, 0, 0, NULL); + + name3U = nameU; + name3U.Buffer = name3; + InitializeObjectAttributes(&attr3, &name3U, 0, 0, NULL); + + status = pNtCreateEvent(&handle, GENERIC_ALL, &attr, NotificationEvent, FALSE); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenEvent(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + status = pNtOpenEvent(&handle2, GENERIC_ALL, &attr2); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateEvent(&handle, GENERIC_ALL, &attr2, NotificationEvent, FALSE); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenEvent(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + status = pNtOpenEvent(&handle2, GENERIC_ALL, &attr); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateEvent(&handle, GENERIC_ALL, &attr3, NotificationEvent, FALSE); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenEvent(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + status = pNtCreateDebugObject(&handle, GENERIC_ALL, &attr, 0); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + pNtClose(handle); + status = pNtCreateDebugObject(&handle, GENERIC_ALL, &attr2, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + pNtClose(handle); + status = pNtCreateDebugObject(&handle, GENERIC_ALL, &attr3, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + pNtClose(handle); + + status = pNtCreateMutant(&handle, GENERIC_ALL, &attr, 0); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenMutant(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + status = pNtOpenMutant(&handle2, GENERIC_ALL, &attr2); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateMutant(&handle, GENERIC_ALL, &attr2, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenMutant(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + status = pNtOpenMutant(&handle2, GENERIC_ALL, &attr); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateMutant(&handle, GENERIC_ALL, &attr3, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenMutant(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + status = pNtCreateSemaphore(&handle, GENERIC_ALL, &attr, 1, 2); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenSemaphore(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + status = pNtOpenSemaphore(&handle2, GENERIC_ALL, &attr2); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateSemaphore(&handle, GENERIC_ALL, &attr2, 1, 2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenSemaphore(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + status = pNtOpenSemaphore(&handle2, GENERIC_ALL, &attr); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateSemaphore(&handle, GENERIC_ALL, &attr3, 1, 2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenSemaphore(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + status = pNtCreateKeyedEvent(&handle, GENERIC_ALL, &attr, 0); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenKeyedEvent(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + status = pNtOpenKeyedEvent(&handle2, GENERIC_ALL, &attr2); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateKeyedEvent(&handle, GENERIC_ALL, &attr2, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenKeyedEvent(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + status = pNtOpenKeyedEvent(&handle2, GENERIC_ALL, &attr); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtClose(handle); + status = pNtCreateKeyedEvent(&handle, GENERIC_ALL, &attr3, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenKeyedEvent(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + status = pNtCreateIoCompletion(&handle, GENERIC_ALL, &attr, 0); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenIoCompletion(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateIoCompletion(&handle, GENERIC_ALL, &attr2, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenIoCompletion(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateIoCompletion(&handle, GENERIC_ALL, &attr3, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenIoCompletion(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + status = pNtCreateJobObject(&handle, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenJobObject(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateJobObject(&handle, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenJobObject(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateJobObject(&handle, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenJobObject(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + status = pNtCreateTimer(&handle, GENERIC_ALL, &attr, NotificationTimer); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenTimer(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateTimer(&handle, GENERIC_ALL, &attr2, NotificationTimer); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenTimer(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateTimer(&handle, GENERIC_ALL, &attr3, NotificationTimer); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenTimer(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + size.QuadPart = 4096; + status = pNtCreateSection(&handle, GENERIC_ALL, &attr, &size, PAGE_READWRITE, SEC_COMMIT, 0); + ok(!status, "got %08lx\n", status); + test_object_name(handle, name, FALSE); + status = pNtOpenSection(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name, FALSE); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateSection(&handle, GENERIC_ALL, &attr2, &size, PAGE_READWRITE, SEC_COMMIT, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U); + status = pNtOpenSection(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name2U); + pNtClose(handle2); + pNtClose(handle); + status = pNtCreateSection(&handle, GENERIC_ALL, &attr3, &size, PAGE_READWRITE, SEC_COMMIT, 0); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U); + status = pNtOpenSection(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle2, &name3U); + pNtClose(handle2); + pNtClose(handle); + + wcscpy(name, L"\Registry\Machine\Software\wine_test"); + wcscpy(name3, L"\Registry\Machine\Software\wine_test"); + p = wcsrchr(name3, '\'); + p[5] = 0; /* => \wine\0test */ + + RtlInitUnicodeString(&nameU, name); + name2U = nameU; + name3U = nameU; + name3U.Buffer = name3; +#ifdef _WIN64 + name_exp = name; + name3_exp = name3; + name2U_exp = name2U; +#else + if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64) + { + name_exp = (WCHAR *)L"\Registry\Machine\Software\WOW6432Node\wine_test"; + name3_exp =(WCHAR *) L"\Registry\Machine\Software\WOW6432Node\wine\0test"; + } + else + { + name_exp = name; + name3_exp = name3; + } + RtlInitUnicodeString(&name2U_exp, name_exp); +#endif + name3U_exp = name2U_exp; + name3U_exp.Buffer = name3_exp; + name2U.Length += sizeof(WCHAR); /* add terminating \0 to string length */ + name2U_exp.Length += sizeof(WCHAR); /* add terminating \0 to string length */ + + status = pNtCreateKey(&handle, GENERIC_ALL, &attr, 0, NULL, 0, NULL); + ok(!status || status == STATUS_ACCESS_DENIED || broken(status == STATUS_OBJECT_PATH_NOT_FOUND) /* win8 */, "got %08lx\n", status); + if (!status) + { + test_object_name(handle, name_exp, FALSE); + status = pNtOpenKey(&handle2, GENERIC_ALL, &attr); + ok(!status, "got %08lx\n", status); + test_object_name(handle2, name_exp, FALSE); + pNtClose(handle2); + status = pNtOpenKey(&handle2, GENERIC_ALL, &attr2); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtDeleteKey(handle); + pNtClose(handle); + status = pNtCreateKey(&handle, GENERIC_ALL, &attr2, 0, NULL, 0, NULL); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U_exp); + status = pNtOpenKey(&handle2, GENERIC_ALL, &attr2); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name2U_exp); + pNtClose(handle2); + status = pNtOpenKey(&handle2, GENERIC_ALL, &attr); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %08lx\n", status); + pNtDeleteKey(handle); + pNtClose(handle); + status = pNtCreateKey(&handle, GENERIC_ALL, &attr3, 0, NULL, 0, NULL); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U_exp); + status = pNtOpenKey(&handle2, GENERIC_ALL, &attr3); + ok(!status, "got %08lx\n", status); + test_object_name_with_null(handle, &name3U_exp); + pNtClose(handle2); + pNtDeleteKey(handle); + pNtClose(handle); + } + else + skip("Limited access to \Registry\Machine\Software key, skipping the tests\n"); +} + START_TEST(om) { HMODULE hntdll = GetModuleHandleA("ntdll.dll"); @@ -2767,6 +3114,7 @@ START_TEST(om) pNtDuplicateObject = (void *)GetProcAddress(hntdll, "NtDuplicateObject"); pNtCompareObjects = (void *)GetProcAddress(hntdll, "NtCompareObjects");
+ test_null_in_object_name(); test_case_sensitive(); test_namespace_pipe(); test_name_collisions();