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(a)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();
--
2.37.1