ntdll/kernel32: Moved GetThreadSelectorEntry to ntdll.
- implemented NtQueryInformationThread's ThreadDescriptorTableEntry information class - used it to implement the kernel32's equivalent (GetThreadSelectorEntry)
This commit is contained in:
parent
1d6e2590e0
commit
2d3504c309
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue