- Implement the ThreadDescriptorTableEntry case for NtQueryInformationThread. This is required for the GetThreadSelectorEntry routine used by user mode debuggers.

- #if out some x86-only LDT code from PS and move it to psldt.c.

svn path=/trunk/; revision=43827
This commit is contained in:
Stefan Ginsberg 2009-10-29 10:04:15 +00:00
parent 7590cdb16d
commit bec72fa6a7
10 changed files with 217 additions and 37 deletions

View file

@ -651,28 +651,32 @@ SetThreadPriorityBoost(IN HANDLE hThread,
/*
* @implemented
*/
BOOL WINAPI
BOOL
WINAPI
GetThreadSelectorEntry(IN HANDLE hThread,
IN DWORD dwSelector,
OUT LPLDT_ENTRY lpSelectorEntry)
IN DWORD dwSelector,
OUT LPLDT_ENTRY lpSelectorEntry)
{
DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
NTSTATUS Status;
DESCRIPTOR_TABLE_ENTRY DescriptionTableEntry;
NTSTATUS Status;
DescriptionTableEntry.Selector = dwSelector;
Status = NtQueryInformationThread(hThread,
ThreadDescriptorTableEntry,
&DescriptionTableEntry,
sizeof(DESCRIPTOR_TABLE_ENTRY),
NULL);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
/* Set the selector and do the query */
DescriptionTableEntry.Selector = dwSelector;
Status = NtQueryInformationThread(hThread,
ThreadDescriptorTableEntry,
&DescriptionTableEntry,
sizeof(DESCRIPTOR_TABLE_ENTRY),
NULL);
if (!NT_SUCCESS(Status))
{
/* Fail */
SetLastErrorByStatus(Status);
return FALSE;
}
*lpSelectorEntry = DescriptionTableEntry.Descriptor;
return TRUE;
/* Success, return the selector */
*lpSelectorEntry = DescriptionTableEntry.Descriptor;
return TRUE;
}
/*

View file

@ -66,6 +66,11 @@ Author:
#define KGDT_DF_TSS 0x50
#define KGDT_NMI_TSS 0x58
//
// Define the number of GDTs that can be queried by user mode
//
#define KGDT_NUMBER 10
//
// CR4
//

View file

@ -88,6 +88,14 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
KTRAP_FRAME TrapFrame);
#endif
NTSTATUS
NTAPI
Ke386GetGdtEntryThread(
IN PKTHREAD Thread,
IN ULONG Offset,
IN PKGDTENTRY Descriptor
);
#endif
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H */

View file

@ -300,8 +300,9 @@ PspDestroyQuotaBlock(
IN PEPROCESS Process
);
#if defined(_X86_)
//
// VDM Support
// VDM and LDT Support
//
NTSTATUS
NTAPI
@ -315,6 +316,16 @@ PspDeleteVdmObjects(
IN PEPROCESS Process
);
NTSTATUS
NTAPI
PspQueryDescriptorThread(
IN PETHREAD Thread,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
#endif
//
// Job Routines
//

View file

@ -5,6 +5,7 @@
* PURPOSE: LDT managment
*
* PROGRAMMERS: David Welch (welch@cwcom.net)
* Stefan Ginsberg (stefan.ginsberg@reactos.org)
*/
/* INCLUDES *****************************************************************/
@ -20,6 +21,55 @@ static KSPIN_LOCK GdtLock;
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
Ke386GetGdtEntryThread(IN PKTHREAD Thread,
IN ULONG Offset,
IN PKGDTENTRY Descriptor)
{
/* Make sure the offset is inside the allowed range */
if (!((Offset) < (KGDT_NUMBER * sizeof(KGDTENTRY))))
{
/* It isn't, fail */
return STATUS_ACCESS_VIOLATION;
}
/* Check if this is the LDT selector */
if (Offset == KGDT_LDT)
{
/* Get it from the thread's process */
RtlCopyMemory(Descriptor,
&Thread->Process->LdtDescriptor,
sizeof(KGDTENTRY));
}
else
{
/* Get the descriptor entry from the GDT */
RtlCopyMemory(Descriptor,
(PCHAR)((PKIPCR)KeGetPcr()->GDT) + Offset,
sizeof(KGDTENTRY));
/* Check if this is the TEB selector */
if (Offset == KGDT_R3_TEB)
{
/*
* Make sure we set the correct base for this thread. This is per
* process and is set in the GDT on context switch, so it might not
* be correct for the thread specified.
*/
Descriptor->BaseLow =
(USHORT)((ULONG_PTR)(Thread->Teb) & 0xFFFF);
Descriptor->HighWord.Bytes.BaseMid =
(UCHAR)((ULONG_PTR)(Thread->Teb) >> 16);
Descriptor->HighWord.Bytes.BaseHi =
(UCHAR)((ULONG_PTR)(Thread->Teb) >> 24);
}
}
/* Success */
return STATUS_SUCCESS;
}
VOID
KeSetBaseGdtSelector(ULONG Entry,
PVOID Base)

View file

@ -444,6 +444,7 @@
<if property="ARCH" value="i386">
<directory name="i386">
<file>psctx.c</file>
<file>psldt.c</file>
</directory>
</if>
<if property="ARCH" value="arm">

View file

@ -0,0 +1,105 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ps/i386/psldt.c
* PURPOSE: LDT support for x86
* PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
PspDeleteLdt(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PspDeleteVdmObjects(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PspQueryDescriptorThread(IN PETHREAD Thread,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
DESCRIPTOR_TABLE_ENTRY DescriptorEntry;
LDT_ENTRY Descriptor;
NTSTATUS Status;
PAGED_CODE();
/* Verify the size */
if (ThreadInformationLength != sizeof(DESCRIPTOR_TABLE_ENTRY))
{
/* Fail */
return STATUS_INFO_LENGTH_MISMATCH;
}
/* Enter SEH for the copy */
_SEH2_TRY
{
/* Get the descriptor */
RtlCopyMemory(&DescriptorEntry,
ThreadInformation,
sizeof(DESCRIPTOR_TABLE_ENTRY));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
/* Check if this is a GDT selector */
if (!(DescriptorEntry.Selector & 0x4))
{
/* Get the GDT entry */
Status = Ke386GetGdtEntryThread(&Thread->Tcb,
DescriptorEntry.Selector & 0xFFFFFFF8,
(PKGDTENTRY)&Descriptor);
if (!NT_SUCCESS(Status)) return Status;
/* Enter SEH for the copy */
_SEH2_TRY
{
/* Copy the GDT entry to caller */
RtlCopyMemory(&((PDESCRIPTOR_TABLE_ENTRY)ThreadInformation)->
Descriptor,
&Descriptor,
sizeof(LDT_ENTRY));
if (ReturnLength) *ReturnLength = sizeof(LDT_ENTRY);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
/* Success */
Status = STATUS_SUCCESS;
}
else
{
/* This is only supported for VDM, which we don't implement */
ASSERT(Thread->ThreadsProcess->LdtInformation == NULL);
Status = STATUS_NO_LDT;
}
/* Return status to caller */
return Status;
}

View file

@ -270,9 +270,11 @@ PspDeleteProcess(IN PVOID ObjectBody)
Process->SectionObject = NULL;
}
/* Clean LDT and VDM_OBJECTS */
#if defined(_X86_)
/* Clean Ldt and Vdm objects */
PspDeleteLdt(Process);
PspDeleteVdmObjects(Process);
#endif
/* Delete the Object Table */
if (Process->ObjectTable)

View file

@ -70,22 +70,6 @@ KPRIORITY PspPriorityTable[PROCESS_PRIORITY_CLASS_ABOVE_NORMAL + 1] =
/* PRIVATE FUNCTIONS *********************************************************/
NTSTATUS
NTAPI
PspDeleteLdt(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PspDeleteVdmObjects(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
PETHREAD
NTAPI
PsGetNextProcessThread(IN PEPROCESS Process,

View file

@ -1819,9 +1819,19 @@ NtQueryInformationThread(IN HANDLE ThreadHandle,
KeLowerIrql(OldIrql);
break;
/* LDT and GDT information */
case ThreadDescriptorTableEntry:
DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
#if defined(_X86_)
/* Call the worker routine */
Status = PspQueryDescriptorThread(Thread,
ThreadInformation,
ThreadInformationLength,
ReturnLength);
#else
/* Only implemented on x86 */
Status = STATUS_NOT_IMPLEMENTED;
#endif
break;
case ThreadPriorityBoost: