ntdll: Move support for getting LDT entries to the platform-specific files.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
73dad192b4
commit
6169cacd0d
|
@ -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__ */
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue