You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-12-15 08:03:15 -08:00
Rebase against 0abb419016e3a38e36ba0bdfe9c0497a29a86fcf.
This commit is contained in:
@@ -1,143 +0,0 @@
|
||||
From fdc7661206f824bcf796ee6b59a222fd28c5437b Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Thu, 28 Apr 2016 18:14:36 +0800
|
||||
Subject: [PATCH] ntdll/tests: Add some tests for NtSetLdtEntries.
|
||||
|
||||
1. Some copy protections call NtSetLdtEntries(0x000f) and then with 'retf'
|
||||
instruction jump to that selector expecting that it works (the tests show that
|
||||
NtSetLdtEntries(0x000f,0x001f) should succeed). In order to make this work a
|
||||
limitation to set only selectors > LDT_FIRST_ENTRY (512) in wine_ldt_set_entry()
|
||||
was removed.
|
||||
|
||||
2. wine_ldt_set_entry() was made to always mark modified selector entries as
|
||||
WINE_LDT_FLAGS_ALLOCATED, otherwise get_selector_entry() server call returns
|
||||
entries without that flag set and NtQueryInformationThread(ThreadDescriptorTableEntry)
|
||||
fails.
|
||||
---
|
||||
dlls/kernel32/tests/thread.c | 75 +++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/signal_i386.c | 2 +-
|
||||
2 files changed, 76 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
|
||||
index c0303b471e8..64b62fefd0d 100644
|
||||
--- a/dlls/kernel32/tests/thread.c
|
||||
+++ b/dlls/kernel32/tests/thread.c
|
||||
@@ -103,6 +103,7 @@ static HRESULT (WINAPI *pSetThreadDescription)(HANDLE,const WCHAR *);
|
||||
static HRESULT (WINAPI *pGetThreadDescription)(HANDLE,WCHAR **);
|
||||
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG,PVECTORED_EXCEPTION_HANDLER);
|
||||
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
|
||||
+static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG);
|
||||
|
||||
static HANDLE create_target_process(const char *arg)
|
||||
{
|
||||
@@ -1319,6 +1320,78 @@ static void test_GetThreadSelectorEntry(void)
|
||||
ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
|
||||
}
|
||||
|
||||
+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 */
|
||||
+ {
|
||||
+ win_skip("NtSetLdtEntries is not implemented on this platform\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ret = pNtSetLdtEntries(0, 0, 0, 0, 0, 0);
|
||||
+ ok(!ret, "NtSetLdtEntries failed: %08x\n", ret);
|
||||
+
|
||||
+ ctx.ContextFlags = CONTEXT_SEGMENTS;
|
||||
+ ret = GetThreadContext(GetCurrentThread(), &ctx);
|
||||
+ ok(ret, "GetThreadContext failed\n");
|
||||
+
|
||||
+ tdi.Selector = ctx.SegDs;
|
||||
+ ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
|
||||
+ ok(!ret, "NtQueryInformationThread failed: %08x\n", ret);
|
||||
+ ds_entry = tdi.Entry;
|
||||
+
|
||||
+ tdi.Selector = 0x000f;
|
||||
+ ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
|
||||
+ ok(ret == STATUS_ACCESS_VIOLATION, "got %08x\n", ret);
|
||||
+
|
||||
+ tdi.Selector = 0x001f;
|
||||
+ ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
|
||||
+ ok(ret == STATUS_ACCESS_VIOLATION, "NtQueryInformationThread returned %08x\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: %08x\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");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#endif /* __i386__ */
|
||||
|
||||
static HANDLE finish_event;
|
||||
@@ -2644,6 +2717,7 @@ static void init_funcs(void)
|
||||
X(NtSetInformationThread);
|
||||
X(RtlAddVectoredExceptionHandler);
|
||||
X(RtlRemoveVectoredExceptionHandler);
|
||||
+ X(NtSetLdtEntries);
|
||||
}
|
||||
#undef X
|
||||
}
|
||||
@@ -2700,6 +2774,7 @@ START_TEST(thread)
|
||||
test_SetThreadContext();
|
||||
test_GetThreadSelectorEntry();
|
||||
test_GetThreadContext();
|
||||
+ test_NtSetLdtEntries();
|
||||
#endif
|
||||
test_QueueUserWorkItem();
|
||||
test_RegisterWaitForSingleObject();
|
||||
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
|
||||
index 59069f92b43..505e0b652b5 100644
|
||||
--- a/dlls/ntdll/unix/signal_i386.c
|
||||
+++ b/dlls/ntdll/unix/signal_i386.c
|
||||
@@ -2300,7 +2300,7 @@ NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_
|
||||
if (base || bits.limit || bits.type)
|
||||
info->Entry = ldt_make_entry( base, bits );
|
||||
else
|
||||
- status = STATUS_UNSUCCESSFUL;
|
||||
+ status = STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
if (status == STATUS_SUCCESS && ret_len)
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@@ -1 +1 @@
|
||||
915a1e6fc76943913a77b71446c72dc13eadc1a0
|
||||
0abb419016e3a38e36ba0bdfe9c0497a29a86fcf
|
||||
|
||||
Reference in New Issue
Block a user