-- v3: ntdll/tests: Add some tests for NtSetLdtEntries.
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/ntdll/tests/wow64.c | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+)
diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index 544290c3273..6555d2742dc 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -42,6 +42,7 @@ static NTSTATUS (WINAPI *pRtlWow64GetSharedInfoProcess)(HANDLE,BOOLEAN*,WOW64INF static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE,WOW64_CONTEXT*); static NTSTATUS (WINAPI *pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*); static NTSTATUS (WINAPI *pNtMapViewOfSectionEx)(HANDLE,HANDLE,PVOID*,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG); +static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG); #ifdef _WIN64 static NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*); static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*); @@ -117,6 +118,7 @@ static void init(void)
#define GET_PROC(func) p##func = (void *)GetProcAddress( ntdll, #func ) GET_PROC( NtMapViewOfSectionEx ); + GET_PROC( NtSetLdtEntries ); GET_PROC( NtQuerySystemInformation ); GET_PROC( NtQuerySystemInformationEx ); GET_PROC( RtlGetNativeSystemInformation ); @@ -3181,6 +3183,78 @@ static void test_arm64ec(void) #endif }
+static void test_NtSetLdtEntries(void) +{ + THREAD_DESCRIPTOR_INFORMATION tdi; + LDT_ENTRY ds_entry; + CONTEXT ctx; + DWORD ret; + union + { + LDT_ENTRY entry; + DWORD dw[2]; + } sel; + + if (!pNtSetLdtEntries) + { + win_skip("NtSetLdtEntries is not available on this platform\n"); + return; + } + + if (pNtSetLdtEntries(0, 0, 0, 0, 0, 0) == STATUS_NOT_IMPLEMENTED) /* WoW64 */ + { + skip("NtSetLdtEntries is not implemented on this platform\n"); + return; + } + + ret = pNtSetLdtEntries(0, 0, 0, 0, 0, 0); + ok(!ret, "NtSetLdtEntries failed: %08lx\n", ret); + + ctx.ContextFlags = CONTEXT_SEGMENTS; + ret = GetThreadContext(GetCurrentThread(), &ctx); + ok(ret, "GetThreadContext failed\n"); + + tdi.Selector = ctx.SegDs; + ret = NtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret); + ok(!ret, "NtQueryInformationThread failed: %08lx\n", ret); + ds_entry = tdi.Entry; + + tdi.Selector = 0x000f; + ret = NtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret); + ok(ret == STATUS_UNSUCCESSFUL, "got %08lx\n", ret); + + tdi.Selector = 0x001f; + ret = NtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret); + ok(ret == STATUS_UNSUCCESSFUL, "NtQueryInformationThread returned %08lx\n", ret); + + ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry); + ok(!ret, "GetThreadSelectorEntry should fail\n"); + + ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry); + ok(!ret, "GetThreadSelectorEntry should fail\n"); + + memset(&sel.entry, 0x9a, sizeof(sel.entry)); + ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &sel.entry); + ok(ret, "GetThreadSelectorEntry failed\n"); + ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n"); + + ret = pNtSetLdtEntries(0x000f, sel.dw[0], sel.dw[1], 0x001f, sel.dw[0], sel.dw[1]); + ok(!ret || broken(ret == STATUS_INVALID_LDT_DESCRIPTOR) /*XP*/, "NtSetLdtEntries failed: %08lx\n", ret); + + if (!ret) + { + memset(&sel.entry, 0x9a, sizeof(sel.entry)); + ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry); + ok(ret, "GetThreadSelectorEntry failed\n"); + ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n"); + + memset(&sel.entry, 0x9a, sizeof(sel.entry)); + ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry); + ok(ret, "GetThreadSelectorEntry failed\n"); + ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n"); + } +} + START_TEST(wow64) { init(); @@ -3202,4 +3276,5 @@ START_TEST(wow64) test_cpu_area(); test_exception_dispatcher(); test_arm64ec(); + test_NtSetLdtEntries(); }
v3: Move tests to dlls/ntdll/tests/wow64.c.
The tests for invalid selectors are part of the test to make sure that the modified LDT entries didn't exist before initializing them.
I'm not sure how useful that is, but if you need it you should add it in the existing checks, there's no need to duplicate them.