ntdll: Move support for getting LDT entries to the platform-specific files.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-04-01 12:33:29 +02:00
parent 73dad192b4
commit 6169cacd0d
8 changed files with 151 additions and 74 deletions

View File

@ -1195,6 +1195,19 @@ static void test_GetThreadSelectorEntry(void)
ok(ret, "GetThreadSelectorEntry(SegCs) error %u\n", GetLastError());
ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry);
ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs & ~3, &entry);
ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
ret = GetThreadSelectorEntry(GetCurrentThread(), 0, &entry);
ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
ret = GetThreadSelectorEntry(GetCurrentThread(), 3, &entry);
ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
SetLastError( 0xdeadbeef );
ret = GetThreadSelectorEntry(GetCurrentThread(), 0xdeadbeef, &entry);
ok(!ret, "GetThreadSelectorEntry(invalid) succeeded\n");
ok( GetLastError() == ERROR_GEN_FAILURE, "wrong error %u\n", GetLastError() );
ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs + 0x100, &entry);
ok(!ret, "GetThreadSelectorEntry(invalid) succeeded\n");
ok( GetLastError() == ERROR_GEN_FAILURE, "wrong error %u\n", GetLastError() );
memset(&entry, 0x11, sizeof(entry));
ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegFs, &entry);
@ -1213,6 +1226,40 @@ static void test_GetThreadSelectorEntry(void)
ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity);
memset(&entry, 0x11, sizeof(entry));
ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegCs, &entry);
ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
ok(base == 0, "got base %p\n", base);
ok(limit == ~0u >> 12, "got limit %#x\n", limit);
ok(entry.HighWord.Bits.Type == 0x1a, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
memset(&entry, 0x11, sizeof(entry));
ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry);
ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
ok(base == 0, "got base %p\n", base);
ok(limit == ~0u >> 12, "got limit %#x\n", limit);
ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
}
#endif /* __i386__ */

View File

@ -58,6 +58,7 @@ extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN;
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN;
extern NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN;
extern LONG WINAPI call_unhandled_exception_filter( PEXCEPTION_POINTERS eptr ) DECLSPEC_HIDDEN;
#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)

View File

@ -1277,6 +1277,14 @@ void signal_exit_process( int status )
call_thread_exit_func( status, exit, NtCurrentTeb() );
}
/**********************************************************************
* get_thread_ldt_entry
*/
NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len )
{
return STATUS_NOT_IMPLEMENTED;
}
/**********************************************************************
* DbgBreakPoint (NTDLL.@)
*/

View File

@ -2105,6 +2105,14 @@ void signal_exit_process( int status )
call_thread_exit_func( status, exit, NtCurrentTeb() );
}
/**********************************************************************
* get_thread_ldt_entry
*/
NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len )
{
return STATUS_NOT_IMPLEMENTED;
}
/**********************************************************************
* DbgBreakPoint (NTDLL.@)
*/

View File

@ -522,6 +522,14 @@ extern DWORD EXC_CallHandler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_R
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher,
PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler );
/***********************************************************************
* is_gdt_sel
*/
static inline int is_gdt_sel( WORD sel )
{
return !(sel & 4);
}
/***********************************************************************
* dispatch_signal
*/
@ -2242,7 +2250,7 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
/***********************************************************************
* locking for LDT routines
* LDT support
*/
static RTL_CRITICAL_SECTION ldt_section;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
@ -2254,6 +2262,8 @@ static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
static RTL_CRITICAL_SECTION ldt_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static sigset_t ldt_sigset;
static const LDT_ENTRY null_entry;
static void ldt_lock(void)
{
sigset_t sigset;
@ -2274,6 +2284,63 @@ static void ldt_unlock(void)
else RtlLeaveCriticalSection( &ldt_section );
}
static LDT_ENTRY ldt_make_entry( void *base, unsigned int limit, unsigned char flags )
{
LDT_ENTRY entry;
wine_ldt_set_base( &entry, base );
wine_ldt_set_limit( &entry, limit );
wine_ldt_set_flags( &entry, flags );
return entry;
}
/**********************************************************************
* get_thread_ldt_entry
*/
NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len )
{
THREAD_DESCRIPTOR_INFORMATION *info = data;
NTSTATUS status = STATUS_SUCCESS;
if (len < sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH;
if (info->Selector >> 16) return STATUS_UNSUCCESSFUL;
if (is_gdt_sel( info->Selector ))
{
if (!(info->Selector & ~3))
info->Entry = null_entry;
else if ((info->Selector | 3) == wine_get_cs())
info->Entry = ldt_make_entry( 0, ~0u, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
else if ((info->Selector | 3) == wine_get_ds())
info->Entry = ldt_make_entry( 0, ~0u, WINE_LDT_FLAGS_DATA | WINE_LDT_FLAGS_32BIT );
else if ((info->Selector | 3) == wine_get_fs())
info->Entry = ldt_make_entry( NtCurrentTeb(), 0xfff, WINE_LDT_FLAGS_DATA | WINE_LDT_FLAGS_32BIT );
else
return STATUS_UNSUCCESSFUL;
}
else
{
SERVER_START_REQ( get_selector_entry )
{
req->handle = wine_server_obj_handle( handle );
req->entry = info->Selector >> 3;
status = wine_server_call( req );
if (!status)
{
if (reply->flags)
info->Entry = ldt_make_entry( (void *)reply->base, reply->limit, reply->flags );
else
status = STATUS_UNSUCCESSFUL;
}
}
SERVER_END_REQ;
}
if (status == STATUS_SUCCESS && ret_len)
/* yes, that's a bit strange, but it's the way it is */
*ret_len = sizeof(info->Entry);
return status;
}
/**********************************************************************
* signal_alloc_thread

View File

@ -1255,6 +1255,14 @@ void signal_exit_process( int status )
exit( status );
}
/**********************************************************************
* get_thread_ldt_entry
*/
NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len )
{
return STATUS_NOT_IMPLEMENTED;
}
/**********************************************************************
* DbgBreakPoint (NTDLL.@)
*/

View File

@ -4278,6 +4278,14 @@ void signal_exit_process( int status )
call_thread_exit_func( status, exit );
}
/**********************************************************************
* get_thread_ldt_entry
*/
NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len )
{
return STATUS_NOT_IMPLEMENTED;
}
/**********************************************************************
* DbgBreakPoint (NTDLL.@)
*/

View File

@ -980,80 +980,10 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
}
}
return status;
case ThreadDescriptorTableEntry:
{
#ifdef __i386__
THREAD_DESCRIPTOR_INFORMATION* tdi = data;
if (length < sizeof(*tdi))
status = STATUS_INFO_LENGTH_MISMATCH;
else if (!(tdi->Selector & 4)) /* GDT selector */
{
unsigned sel = LOWORD(tdi->Selector) & ~3; /* ignore RPL */
status = STATUS_SUCCESS;
if (!sel) /* null selector */
memset( &tdi->Entry, 0, sizeof(tdi->Entry) );
else
{
tdi->Entry.BaseLow = 0;
tdi->Entry.HighWord.Bits.BaseMid = 0;
tdi->Entry.HighWord.Bits.BaseHi = 0;
tdi->Entry.LimitLow = 0xffff;
tdi->Entry.HighWord.Bits.LimitHi = 0xf;
tdi->Entry.HighWord.Bits.Dpl = 3;
tdi->Entry.HighWord.Bits.Sys = 0;
tdi->Entry.HighWord.Bits.Pres = 1;
tdi->Entry.HighWord.Bits.Granularity = 1;
tdi->Entry.HighWord.Bits.Default_Big = 1;
tdi->Entry.HighWord.Bits.Type = 0x12;
tdi->Entry.HighWord.Bits.Reserved_0 = 0;
/* it has to be one of the system GDT selectors */
if (sel != (wine_get_ds() & ~3) && sel != (wine_get_ss() & ~3))
{
if (sel == (wine_get_cs() & ~3))
tdi->Entry.HighWord.Bits.Type |= 8; /* code segment */
else if (sel == (wine_get_fs() & ~3))
{
ULONG_PTR fs_base = (ULONG_PTR)NtCurrentTeb();
tdi->Entry.BaseLow = fs_base & 0xffff;
tdi->Entry.HighWord.Bits.BaseMid = (fs_base >> 16) & 0xff;
tdi->Entry.HighWord.Bits.BaseHi = (fs_base >> 24) & 0xff;
tdi->Entry.LimitLow = 0x0fff;
tdi->Entry.HighWord.Bits.LimitHi = 0;
tdi->Entry.HighWord.Bits.Granularity = 0;
}
else status = STATUS_ACCESS_DENIED;
}
}
}
else
{
SERVER_START_REQ( get_selector_entry )
{
req->handle = wine_server_obj_handle( handle );
req->entry = LOWORD(tdi->Selector) >> 3;
status = wine_server_call( req );
if (!status)
{
if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
status = STATUS_ACCESS_VIOLATION;
else
{
wine_ldt_set_base ( &tdi->Entry, (void *)reply->base );
wine_ldt_set_limit( &tdi->Entry, reply->limit );
wine_ldt_set_flags( &tdi->Entry, reply->flags );
}
}
}
SERVER_END_REQ;
}
if (status == STATUS_SUCCESS && ret_len)
/* yes, that's a bit strange, but it's the way it is */
*ret_len = sizeof(LDT_ENTRY);
#else
status = STATUS_NOT_IMPLEMENTED;
#endif
return status;
}
return get_thread_ldt_entry( handle, data, length, ret_len );
case ThreadAmILastThread:
{
SERVER_START_REQ(get_thread_info)