mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
ntdll-NtSetLdtEntries: Update patchset and add actual implementation of NtSetLdtEntries.
This commit is contained in:
parent
0712486b63
commit
51b447a55f
@ -0,0 +1,170 @@
|
||||
From aadd7b2c0ca9bf60d64c3ed4e0722de3899b8c13 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Thu, 28 Apr 2016 18:14:36 +0800
|
||||
Subject: ntdll: Implement NtSetLdtEntries.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/thread.c | 79 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/nt.c | 28 +++++++++++++++-
|
||||
2 files changed, 106 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
|
||||
index e0de3f9..981e3c4 100644
|
||||
--- a/dlls/kernel32/tests/thread.c
|
||||
+++ b/dlls/kernel32/tests/thread.c
|
||||
@@ -102,6 +102,7 @@ static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID
|
||||
static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
|
||||
static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
|
||||
static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
|
||||
+static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG);
|
||||
|
||||
static HANDLE create_target_process(const char *arg)
|
||||
{
|
||||
@@ -1100,6 +1101,82 @@ static void test_SetThreadContext(void)
|
||||
CloseHandle( thread );
|
||||
}
|
||||
|
||||
+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(), 6 /*ThreadDescriptorTableEntry*/, &tdi, sizeof(tdi), &ret);
|
||||
+ ok(!ret, "NtQueryInformationThread failed: %08x\n", ret);
|
||||
+ ds_entry = tdi.Entry;
|
||||
+
|
||||
+ tdi.Selector = 0x000f;
|
||||
+ ret = pNtQueryInformationThread(GetCurrentThread(), 6 /*ThreadDescriptorTableEntry*/, &tdi, sizeof(tdi), &ret);
|
||||
+ ok(ret == STATUS_ACCESS_VIOLATION, "got %08x\n", ret);
|
||||
+
|
||||
+ tdi.Selector = 0x001f;
|
||||
+ ret = pNtQueryInformationThread(GetCurrentThread(), 6 /*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);
|
||||
+ todo_wine
|
||||
+ ok(ret, "GetThreadSelectorEntry failed\n");
|
||||
+ todo_wine
|
||||
+ 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);
|
||||
+ todo_wine
|
||||
+ ok(ret, "GetThreadSelectorEntry failed\n");
|
||||
+ todo_wine
|
||||
+ ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#endif /* __i386__ */
|
||||
|
||||
static HANDLE finish_event;
|
||||
@@ -1913,6 +1990,7 @@ static void init_funcs(void)
|
||||
X(NtQueryInformationThread);
|
||||
X(RtlGetThreadErrorMode);
|
||||
X(NtSetInformationThread);
|
||||
+ X(NtSetLdtEntries);
|
||||
}
|
||||
#undef X
|
||||
}
|
||||
@@ -1965,6 +2043,7 @@ START_TEST(thread)
|
||||
test_GetThreadExitCode();
|
||||
#ifdef __i386__
|
||||
test_SetThreadContext();
|
||||
+ test_NtSetLdtEntries();
|
||||
#endif
|
||||
test_QueueUserWorkItem();
|
||||
test_RegisterWaitForSingleObject();
|
||||
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
|
||||
index 3f5ae2c..fbea627 100644
|
||||
--- a/dlls/ntdll/nt.c
|
||||
+++ b/dlls/ntdll/nt.c
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "winternl.h"
|
||||
#include "ntdll_misc.h"
|
||||
#include "wine/server.h"
|
||||
+#include "wine/library.h"
|
||||
#include "ddk/wdm.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -2790,7 +2791,32 @@ NTSTATUS WINAPI NtSystemDebugControl(SYSDBG_COMMAND command, PVOID inbuffer, ULO
|
||||
NTSTATUS WINAPI NtSetLdtEntries(ULONG selector1, ULONG entry1_low, ULONG entry1_high,
|
||||
ULONG selector2, ULONG entry2_low, ULONG entry2_high)
|
||||
{
|
||||
- FIXME("(%u, %u, %u, %u, %u, %u): stub\n", selector1, entry1_low, entry1_high, selector2, entry2_low, entry2_high);
|
||||
+#ifdef __i386__
|
||||
+ union
|
||||
+ {
|
||||
+ LDT_ENTRY entry;
|
||||
+ ULONG dw[2];
|
||||
+ } sel;
|
||||
+
|
||||
+ TRACE("(%x,%x,%x,%x,%x,%x)\n", selector1, entry1_low, entry1_high, selector2, entry2_low, entry2_high);
|
||||
|
||||
+ if (selector1)
|
||||
+ {
|
||||
+ sel.dw[0] = entry1_low;
|
||||
+ sel.dw[1] = entry1_high;
|
||||
+ if (wine_ldt_set_entry(selector1, &sel.entry) < 0)
|
||||
+ return STATUS_ACCESS_DENIED;
|
||||
+ }
|
||||
+ if (selector2)
|
||||
+ {
|
||||
+ sel.dw[0] = entry2_low;
|
||||
+ sel.dw[1] = entry2_high;
|
||||
+ if (wine_ldt_set_entry(selector2, &sel.entry) < 0)
|
||||
+ return STATUS_ACCESS_DENIED;
|
||||
+ }
|
||||
+ return STATUS_SUCCESS;
|
||||
+#else
|
||||
+ FIXME("(%x,%x,%x,%x,%x,%x): stub\n", selector1, entry1_low, entry1_high, selector2, entry2_low, entry2_high);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
+#endif
|
||||
}
|
||||
--
|
||||
2.8.0
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 36cdcc900c03de3e2e27a16252242a7a5ec55513 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Thu, 28 Apr 2016 17:01:16 +0200
|
||||
Subject: libs/wine: Allow to modify reserved LDT entries.
|
||||
|
||||
Some implementation notes:
|
||||
|
||||
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 | 4 ----
|
||||
libs/wine/ldt.c | 4 +---
|
||||
2 files changed, 1 insertion(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
|
||||
index 981e3c4..6efc52a 100644
|
||||
--- a/dlls/kernel32/tests/thread.c
|
||||
+++ b/dlls/kernel32/tests/thread.c
|
||||
@@ -1163,16 +1163,12 @@ static void test_NtSetLdtEntries(void)
|
||||
{
|
||||
memset(&sel.entry, 0x9a, sizeof(sel.entry));
|
||||
ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
|
||||
- todo_wine
|
||||
ok(ret, "GetThreadSelectorEntry failed\n");
|
||||
- todo_wine
|
||||
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);
|
||||
- todo_wine
|
||||
ok(ret, "GetThreadSelectorEntry failed\n");
|
||||
- todo_wine
|
||||
ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
|
||||
}
|
||||
}
|
||||
diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c
|
||||
index 0946407..8ac779a 100644
|
||||
--- a/libs/wine/ldt.c
|
||||
+++ b/libs/wine/ldt.c
|
||||
@@ -169,8 +169,6 @@ static int internal_set_entry( unsigned short sel, const LDT_ENTRY *entry )
|
||||
{
|
||||
int ret = 0, index = sel >> 3;
|
||||
|
||||
- if (index < LDT_FIRST_ENTRY) return 0; /* cannot modify reserved entries */
|
||||
-
|
||||
#ifdef linux
|
||||
{
|
||||
struct modify_ldt_s ldt_info;
|
||||
@@ -222,7 +220,7 @@ static int internal_set_entry( unsigned short sel, const LDT_ENTRY *entry )
|
||||
wine_ldt_copy.limit[index] = wine_ldt_get_limit(entry);
|
||||
wine_ldt_copy.flags[index] = (entry->HighWord.Bits.Type |
|
||||
(entry->HighWord.Bits.Default_Big ? WINE_LDT_FLAGS_32BIT : 0) |
|
||||
- (wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED));
|
||||
+ WINE_LDT_FLAGS_ALLOCATED);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.8.0
|
||||
|
@ -0,0 +1,67 @@
|
||||
From 9a0e823dfa31ea24a3e697bf3a3914011947c3e4 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 28 Apr 2016 17:07:35 +0200
|
||||
Subject: ntdll: Export NtSetLdtEntries only on i386.
|
||||
|
||||
---
|
||||
dlls/ntdll/nt.c | 9 ++++-----
|
||||
dlls/ntdll/ntdll.spec | 4 ++--
|
||||
2 files changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
|
||||
index fbea627..8238932 100644
|
||||
--- a/dlls/ntdll/nt.c
|
||||
+++ b/dlls/ntdll/nt.c
|
||||
@@ -2784,6 +2784,8 @@ NTSTATUS WINAPI NtSystemDebugControl(SYSDBG_COMMAND command, PVOID inbuffer, ULO
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
+#ifdef __i386__
|
||||
+
|
||||
/******************************************************************************
|
||||
* NtSetLdtEntries (NTDLL.@)
|
||||
* ZwSetLdtEntries (NTDLL.@)
|
||||
@@ -2791,7 +2793,6 @@ NTSTATUS WINAPI NtSystemDebugControl(SYSDBG_COMMAND command, PVOID inbuffer, ULO
|
||||
NTSTATUS WINAPI NtSetLdtEntries(ULONG selector1, ULONG entry1_low, ULONG entry1_high,
|
||||
ULONG selector2, ULONG entry2_low, ULONG entry2_high)
|
||||
{
|
||||
-#ifdef __i386__
|
||||
union
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
@@ -2815,8 +2816,6 @@ NTSTATUS WINAPI NtSetLdtEntries(ULONG selector1, ULONG entry1_low, ULONG entry1_
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
-#else
|
||||
- FIXME("(%x,%x,%x,%x,%x,%x): stub\n", selector1, entry1_low, entry1_high, selector2, entry2_low, entry2_high);
|
||||
- return STATUS_NOT_IMPLEMENTED;
|
||||
-#endif
|
||||
}
|
||||
+
|
||||
+#endif /* __i386__ */
|
||||
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
|
||||
index 01c84c6..d4c4d52 100644
|
||||
--- a/dlls/ntdll/ntdll.spec
|
||||
+++ b/dlls/ntdll/ntdll.spec
|
||||
@@ -340,7 +340,7 @@
|
||||
@ stdcall NtSetInformationToken(long long ptr long)
|
||||
@ stdcall NtSetIntervalProfile(long long)
|
||||
@ stdcall NtSetIoCompletion(ptr long ptr long long)
|
||||
-@ stdcall NtSetLdtEntries(long long long long long long)
|
||||
+@ stdcall -i386 NtSetLdtEntries(long long long long long long)
|
||||
@ stub NtSetLowEventPair
|
||||
@ stub NtSetLowWaitHighEventPair
|
||||
@ stub NtSetLowWaitHighThread
|
||||
@@ -1261,7 +1261,7 @@
|
||||
@ stdcall ZwSetInformationToken(long long ptr long) NtSetInformationToken
|
||||
@ stdcall ZwSetIntervalProfile(long long) NtSetIntervalProfile
|
||||
@ stdcall ZwSetIoCompletion(ptr long ptr long long) NtSetIoCompletion
|
||||
-@ stdcall ZwSetLdtEntries(long long long long long long) NtSetLdtEntries
|
||||
+@ stdcall -i386 ZwSetLdtEntries(long long long long long long) NtSetLdtEntries
|
||||
@ stub ZwSetLowEventPair
|
||||
@ stub ZwSetLowWaitHighEventPair
|
||||
@ stub ZwSetLowWaitHighThread
|
||||
--
|
||||
2.8.0
|
||||
|
@ -4957,12 +4957,19 @@ fi
|
||||
# | * [#26268] Add stub for NtSetLdtEntries/ZwSetLdtEntries
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/nt.c, dlls/ntdll/ntdll.spec, include/ddk/wdm.h, include/winternl.h
|
||||
# | * dlls/kernel32/tests/thread.c, dlls/ntdll/nt.c, dlls/ntdll/ntdll.spec, include/ddk/wdm.h, include/winternl.h,
|
||||
# | libs/wine/ldt.c
|
||||
# |
|
||||
if test "$enable_ntdll_NtSetLdtEntries" -eq 1; then
|
||||
patch_apply ntdll-NtSetLdtEntries/0001-ntdll-add-NtSetLdtEntries-ZwSetLdtEntries-stub-try-2.patch
|
||||
patch_apply ntdll-NtSetLdtEntries/0002-ntdll-Implement-NtSetLdtEntries.patch
|
||||
patch_apply ntdll-NtSetLdtEntries/0003-libs-wine-Allow-to-modify-reserved-LDT-entries.patch
|
||||
patch_apply ntdll-NtSetLdtEntries/0004-ntdll-Export-NtSetLdtEntries-only-on-i386.patch
|
||||
(
|
||||
echo '+ { "Austin English", "ntdll: Add NtSetLdtEntries/ZwSetLdtEntries stub.", 2 },';
|
||||
echo '+ { "Dmitry Timoshkov", "ntdll: Implement NtSetLdtEntries.", 1 },';
|
||||
echo '+ { "Dmitry Timoshkov", "libs/wine: Allow to modify reserved LDT entries.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Export NtSetLdtEntries only on i386.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user