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

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>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Dmitry Timoshkov 2022-07-28 17:22:27 +03:00 committed by Alexandre Julliard
parent bfec2a6637
commit 9d9b564e4b

View file

@ -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 %u, expected %u\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();