diff --git a/reactos/dll/win32/kernel32/thread/thread.c b/reactos/dll/win32/kernel32/thread/thread.c
index 6936d4054b3..3fb6a6da7e7 100644
--- a/reactos/dll/win32/kernel32/thread/thread.c
+++ b/reactos/dll/win32/kernel32/thread/thread.c
@@ -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;
}
/*
diff --git a/reactos/include/ndk/i386/ketypes.h b/reactos/include/ndk/i386/ketypes.h
index e94658771ef..4ce98184a46 100644
--- a/reactos/include/ndk/i386/ketypes.h
+++ b/reactos/include/ndk/i386/ketypes.h
@@ -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
//
diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h
index 4c997d0673b..c40b259dcd5 100644
--- a/reactos/ntoskrnl/include/internal/i386/ke.h
+++ b/reactos/ntoskrnl/include/internal/i386/ke.h
@@ -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 */
diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h
index 405cc41c0c6..50f32626f47 100644
--- a/reactos/ntoskrnl/include/internal/ps.h
+++ b/reactos/ntoskrnl/include/internal/ps.h
@@ -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
//
diff --git a/reactos/ntoskrnl/ke/i386/ldt.c b/reactos/ntoskrnl/ke/i386/ldt.c
index 7ac9e428962..4a08fd1c6fa 100644
--- a/reactos/ntoskrnl/ke/i386/ldt.c
+++ b/reactos/ntoskrnl/ke/i386/ldt.c
@@ -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)
diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild
index 5ff09a5e51f..d34f964a860 100644
--- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild
+++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild
@@ -444,6 +444,7 @@
psctx.c
+ psldt.c
diff --git a/reactos/ntoskrnl/ps/i386/psldt.c b/reactos/ntoskrnl/ps/i386/psldt.c
new file mode 100644
index 00000000000..19fccfe8ab2
--- /dev/null
+++ b/reactos/ntoskrnl/ps/i386/psldt.c
@@ -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
+#define NDEBUG
+#include
+
+/* 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;
+}
diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c
index 92237434fa6..31de3a1d738 100644
--- a/reactos/ntoskrnl/ps/kill.c
+++ b/reactos/ntoskrnl/ps/kill.c
@@ -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)
diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c
index 31c01628822..2cc0c4f6ae2 100644
--- a/reactos/ntoskrnl/ps/process.c
+++ b/reactos/ntoskrnl/ps/process.c
@@ -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,
diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c
index f9d70a93590..b4c2abaefea 100644
--- a/reactos/ntoskrnl/ps/query.c
+++ b/reactos/ntoskrnl/ps/query.c
@@ -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: