[PATCH 2/2] ntdll/tests: Add a bunch of tests for creating kernel objects with the names containing '\0'.

Dmitry Timoshkov dmitry at baikal.ru
Thu Jul 28 09:22:27 CDT 2022


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 at 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




More information about the wine-devel mailing list