diff --git a/dlls/kernel/selector.c b/dlls/kernel/selector.c index 7cd159c2040..86d150ca790 100644 --- a/dlls/kernel/selector.c +++ b/dlls/kernel/selector.c @@ -573,67 +573,21 @@ __ASM_GLOBAL_FUNC( UnMapSLFixArray, "ret $8" ); /*********************************************************************** * GetThreadSelectorEntry (KERNEL32.@) */ -BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent) +BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent ) { -#ifdef __i386__ - BOOL ret; + THREAD_DESCRIPTOR_INFORMATION tdi; + NTSTATUS status; - if (!(sel & 4)) /* GDT selector */ + tdi.Selector = sel; + status = NtQueryInformationThread( hthread, ThreadDescriptorTableEntry, + &tdi, sizeof(tdi), NULL); + if (status) { - sel &= ~3; /* ignore RPL */ - if (!sel) /* null selector */ - { - memset( ldtent, 0, sizeof(*ldtent) ); - return TRUE; - } - ldtent->BaseLow = 0; - ldtent->HighWord.Bits.BaseMid = 0; - ldtent->HighWord.Bits.BaseHi = 0; - ldtent->LimitLow = 0xffff; - ldtent->HighWord.Bits.LimitHi = 0xf; - ldtent->HighWord.Bits.Dpl = 3; - ldtent->HighWord.Bits.Sys = 0; - ldtent->HighWord.Bits.Pres = 1; - ldtent->HighWord.Bits.Granularity = 1; - ldtent->HighWord.Bits.Default_Big = 1; - ldtent->HighWord.Bits.Type = 0x12; - /* it has to be one of the system GDT selectors */ - if (sel == (wine_get_ds() & ~3)) return TRUE; - if (sel == (wine_get_ss() & ~3)) return TRUE; - if (sel == (wine_get_cs() & ~3)) - { - ldtent->HighWord.Bits.Type |= 8; /* code segment */ - return TRUE; - } - SetLastError( ERROR_NOACCESS ); + SetLastError( RtlNtStatusToDosError(status) ); return FALSE; } - - SERVER_START_REQ( get_selector_entry ) - { - req->handle = hthread; - req->entry = sel >> __AHSHIFT; - if ((ret = !wine_server_call_err( req ))) - { - if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED)) - { - SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */ - ret = FALSE; - } - else - { - wine_ldt_set_base( ldtent, (void *)reply->base ); - wine_ldt_set_limit( ldtent, reply->limit ); - wine_ldt_set_flags( ldtent, reply->flags ); - } - } - } - SERVER_END_REQ; - return ret; -#else - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; -#endif + *ldtent = tdi.Entry; + return TRUE; } diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 5d2509606b7..b2d0c551475 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -1073,11 +1073,71 @@ 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 = 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; + /* 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 status = STATUS_ACCESS_DENIED; + } + } + } + else + { + SERVER_START_REQ( get_selector_entry ) + { + req->handle = handle; + req->entry = tdi->Selector >> 3; + status = wine_server_call( req ); + if (!status) + { + if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED)) + status = STATUS_INVALID_LDT_OFFSET; + 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; + } +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + if (status == STATUS_SUCCESS && ret_len) *ret_len = sizeof(*tdi); + return status; + } case ThreadPriority: case ThreadBasePriority: case ThreadAffinityMask: case ThreadImpersonationToken: - case ThreadDescriptorTableEntry: case ThreadEnableAlignmentFaultFixup: case ThreadEventPair_Reusable: case ThreadQuerySetWin32StartAddress: diff --git a/include/winternl.h b/include/winternl.h index 71f03a09f25..2f85171dff7 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -728,6 +728,12 @@ typedef struct _THREAD_BASIC_INFORMATION LONG BasePriority; } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; +typedef struct _THREAD_DESCRIPTOR_INFORMATION +{ + DWORD Selector; + LDT_ENTRY Entry; +} THREAD_DESCRIPTOR_INFORMATION, *PTHREAD_DESCRIPTOR_INFORMATION; + typedef struct _KERNEL_USER_TIMES { LARGE_INTEGER CreateTime; LARGE_INTEGER ExitTime;