- Fix critical bugs in exception handling: Unwinding was completely broken, using the wrong SEH protector to detect collided unwinding. The correct protector itself also had a broken check.

- Fix architectural bug in the entire TrapFrame<->Context conversion system and Ring Privilege Transitions (Inter-ring and intra-ring) which was lacking proper sanitation and validation of segments, flags and debug registers. Among other things, IOPL is now respected, CS is not KGDT_R0_CODE | RPL_MASK anymore, and the GPF code is now properly being called. This completely fixes exception handling being totally broken and crashing firefox installer, mirc, and other applications.
- Rewrite the page fault handler base code in assembly instead of relying on a broken C routine. Detect VDM, V8086, detecting expected/normal fault in ExpInterlockedPopEntrySList and faults in the system handler code. Rewrite MmAccessFault to be the main function that calls out to other sub-fault functions, and use the same prototype as NT.
- Fix the KGDT boot table to have proper granularity and big flags, and extend it to 256 entries.
- Create proper thread context in RtlInitializeContext and cleanup Rtl Thread routines.
- Remove all int3 and breakpoints from trap handlers, and replace them with a much better "UNHANDLED_PATH" macro which freezes the system, beeps, and displays a message with the line of code that's unhandled. This is to clearly tell the user that something is unhandled, instead of nesting infinite exceptions due to the int3.
- Fix a bug in INT_PROLOG.
- Sanitize EFLAGS and Code Segments in KeContextToTrapFrame and KeTrapFrameToContext.
- Implement KiUpdateDr7 and KiRecordDr7 as well as DR_MASK and other DR-validation macros and functions to protect against DR-vulnerabilites as well as to properly account for each active hardware breakpoint in a per-thread fashion by using the dispatcher header.
- Allow CR0_EM when running in a VDM.
- Fix FPU/NPX Register handling in KeContextToTrapFrame and KeTrapFrameToContext, and also speed it up by manual copying instead of a memory move.
- Properly give IOPL 3 to user-mode threads if they requested it.
- Detect GPF during GPF.
- Detect pagefault with a trap-frame spread over two or more pages and nested.
- Properly sanitize and set correct trap frame in KiInitailizeUserApc.
- Return STATUS_ACCESS_VIOLATION during page faults instead of STATUS_UNSUCESSFUL. 
- Fix assert in VdmSwapContext, as well as Code Selector check which was broken.
- Fix delayed object deletion (ObDeferDeleteObject) and the Ob Repear Routine and list.
- Update Kernel Fun.
- BUGBUG: Temporaily hack VMWare to detection to always detect VMWare.

svn path=/trunk/; revision=25238
This commit is contained in:
Alex Ionescu 2006-12-29 18:49:00 +00:00
parent 32b82baa21
commit c0a3750d26
28 changed files with 943 additions and 545 deletions

View file

@ -68,7 +68,7 @@ LONG CALLBACK VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_EXECUTION;
} }
static BOOL BOOL
DetectVMware(int *Version) DetectVMware(int *Version)
{ {
int magic, ver; int magic, ver;
@ -1010,7 +1010,7 @@ WinMain(HINSTANCE hInstance,
{ {
PVOID ExceptionHandler; PVOID ExceptionHandler;
int Version; //int Version;
WCHAR *lc; WCHAR *lc;
hAppInstance = hInstance; hAppInstance = hInstance;
@ -1024,9 +1024,9 @@ WinMain(HINSTANCE hInstance,
return 1; return 1;
} }
if(!DetectVMware(&Version)) //if(!DetectVMware(&Version))
{ {
return 1; //return 1;
} }
/* unregister the handler */ /* unregister the handler */

View file

@ -67,6 +67,7 @@ NtAcceptConnectPort@24
NtAccessCheck@32 NtAccessCheck@32
NtAccessCheckAndAuditAlarm@44 NtAccessCheckAndAuditAlarm@44
NtAddAtom@12 NtAddAtom@12
NtAddBootEntry@8
NtAdjustGroupsToken@24 NtAdjustGroupsToken@24
NtAdjustPrivilegesToken@24 NtAdjustPrivilegesToken@24
NtAlertResumeThread@8 NtAlertResumeThread@8

View file

@ -169,6 +169,7 @@ Author:
#define KPCR_STALL_SCALE_FACTOR 0x4C #define KPCR_STALL_SCALE_FACTOR 0x4C
#define KPCR_SET_MEMBER 0x48 #define KPCR_SET_MEMBER 0x48
#define KPCR_NUMBER 0x51 #define KPCR_NUMBER 0x51
#define KPCR_VDM_ALERT 0x54
#define KPCR_PRCB_DATA 0x120 #define KPCR_PRCB_DATA 0x120
#define KPCR_CURRENT_THREAD 0x124 #define KPCR_CURRENT_THREAD 0x124
#define KPCR_PRCB_NEXT_THREAD 0x128 #define KPCR_PRCB_NEXT_THREAD 0x128
@ -473,9 +474,13 @@ Author:
#endif #endif
// //
// DR7 Values // DR6 and 7 Masks
// //
#define DR6_LEGAL 0xE00F
#define DR7_LEGAL 0xFFFF0155
#define DR7_ACTIVE 0x55
#define DR7_RESERVED_MASK 0xDC00 #define DR7_RESERVED_MASK 0xDC00
#define DR7_OVERRIDE_MASK 0xF0000
// //
// Usermode callout frame definitions // Usermode callout frame definitions
@ -491,6 +496,10 @@ Author:
// //
#ifdef __ASM__ #ifdef __ASM__
#define STATUS_ACCESS_VIOLATION 0xC0000005 #define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_IN_PAGE_ERROR 0xC0000006
#define STATUS_GUARD_PAGE_VIOLATION 0x80000001
#define STATUS_STACK_OVERFLOW 0xC00000FD
#define KI_EXCEPTION_ACCESS_VIOLATION 0x10000004
#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C #define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258 #define STATUS_NO_CALLBACK_ACTIVE 0xC0000258
#define STATUS_CALLBACK_POP_STACK 0xC0000423 #define STATUS_CALLBACK_POP_STACK 0xC0000423

View file

@ -1893,9 +1893,9 @@ RtlCreateUserThread(
IN HANDLE ProcessHandle, IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOLEAN CreateSuspended, IN BOOLEAN CreateSuspended,
IN LONG StackZeroBits, IN ULONG StackZeroBits,
IN ULONG StackReserve, IN SIZE_T StackReserve,
IN ULONG StackCommit, IN SIZE_T StackCommit,
IN PTHREAD_START_ROUTINE StartAddress, IN PTHREAD_START_ROUTINE StartAddress,
IN PVOID Parameter, IN PVOID Parameter,
IN OUT PHANDLE ThreadHandle, IN OUT PHANDLE ThreadHandle,

View file

@ -134,7 +134,7 @@ _RtlpExecuteHandlerForException@20:
.globl _RtlpExecuteHandlerForUnwind@20 .globl _RtlpExecuteHandlerForUnwind@20
_RtlpExecuteHandlerForUnwind@20: _RtlpExecuteHandlerForUnwind@20:
/* Copy the routine in EDX */ /* Copy the routine in EDX */
mov edx, offset _RtlpExceptionProtector mov edx, offset _RtlpUnwindProtector
.endfunc .endfunc
.func RtlpExecuteHandler@20 .func RtlpExecuteHandler@20
@ -243,7 +243,7 @@ _RtlpUnwindProtector:
/* Put the exception record in ECX and check the Flags */ /* Put the exception record in ECX and check the Flags */
mov ecx, [esp+4] mov ecx, [esp+4]
test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWINDING + EXCEPTION_EXIT_UNWIND test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWINDING + EXCEPTION_EXIT_UNWIND
jnz .return jz .return
/* Save the frame in ECX and Context in EDX */ /* Save the frame in ECX and Context in EDX */
mov ecx, [esp+8] mov ecx, [esp+8]

View file

@ -10,30 +10,9 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include <rtl.h> #include <rtl.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
PEXCEPTION_REGISTRATION_RECORD
NTAPI
RtlpGetExceptionList(VOID);
VOID
NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
typedef struct _DISPATCHER_CONTEXT
{
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
/* PUBLIC FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS **********************************************************/
/* /*
@ -100,7 +79,6 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
sizeof(*RegistrationFrame)); sizeof(*RegistrationFrame));
/* Call the handler */ /* Call the handler */
DPRINT1("Calling handler: %p\n", RegistrationFrame->Handler);
Disposition = RtlpExecuteHandlerForException(ExceptionRecord, Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame, RegistrationFrame,
Context, Context,
@ -192,7 +170,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
IN PVOID ReturnValue) IN PVOID ReturnValue)
{ {
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame; PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame;
DISPATCHER_CONTEXT DispatcherContext; DISPATCHER_CONTEXT DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3; EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
EXCEPTION_DISPOSITION Disposition; EXCEPTION_DISPOSITION Disposition;
ULONG_PTR StackLow, StackHigh; ULONG_PTR StackLow, StackHigh;
@ -306,7 +284,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
&DispatcherContext, &DispatcherContext,
RegistrationFrame-> RegistrationFrame->
Handler); Handler);
switch (Disposition) switch(Disposition)
{ {
/* Continue searching */ /* Continue searching */
case ExceptionContinueSearch: case ExceptionContinueSearch:

View file

@ -16,6 +16,24 @@ extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
#define PAGED_CODE_RTL() #define PAGED_CODE_RTL()
#endif #endif
VOID
NTAPI
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
PEXCEPTION_REGISTRATION_RECORD
NTAPI
RtlpGetExceptionList(VOID);
VOID
NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
typedef struct _DISPATCHER_CONTEXT
{
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
/* These provide support for sharing code between User and Kernel RTL */ /* These provide support for sharing code between User and Kernel RTL */
PVOID PVOID
NTAPI NTAPI
@ -112,7 +130,7 @@ RtlpCaptureContext(OUT PCONTEXT ContextRecord);
NTSTATUS NTSTATUS
NTAPI NTAPI
DebugService(IN ULONG Service, DebugService(IN ULONG Service,
IN PCVOID Buffer, IN const void* Buffer,
IN ULONG Length, IN ULONG Length,
IN PVOID Argument1, IN PVOID Argument1,
IN PVOID Argument2); IN PVOID Argument2);

View file

@ -21,59 +21,53 @@
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlpCreateUserStack(HANDLE hProcess, RtlpCreateUserStack(IN HANDLE hProcess,
ULONG StackReserve, IN SIZE_T StackReserve OPTIONAL,
ULONG StackCommit, IN SIZE_T StackCommit OPTIONAL,
ULONG StackZeroBits, IN ULONG StackZeroBits OPTIONAL,
PINITIAL_TEB InitialTeb) OUT PINITIAL_TEB InitialTeb)
{ {
NTSTATUS Status; NTSTATUS Status;
SYSTEM_BASIC_INFORMATION SystemBasicInfo; SYSTEM_BASIC_INFORMATION SystemBasicInfo;
PIMAGE_NT_HEADERS Headers; PIMAGE_NT_HEADERS Headers;
ULONG_PTR Stack = 0; ULONG_PTR Stack = 0;
BOOLEAN UseGuard = FALSE; BOOLEAN UseGuard = FALSE;
ULONG Dummy, GuardPageSize;
DPRINT("RtlpCreateUserStack\n");
/* Get some memory information */ /* Get some memory information */
Status = NtQuerySystemInformation(SystemBasicInformation, Status = ZwQuerySystemInformation(SystemBasicInformation,
&SystemBasicInfo, &SystemBasicInfo,
sizeof(SYSTEM_BASIC_INFORMATION), sizeof(SYSTEM_BASIC_INFORMATION),
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1("Failure to query system info\n");
return Status;
}
/* Use the Image Settings if we are dealing with the current Process */ /* Use the Image Settings if we are dealing with the current Process */
if (hProcess == NtCurrentProcess()) if (hProcess == NtCurrentProcess())
{ {
/* Get the Image Headers */ /* Get the Image Headers */
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
DPRINT("Headers: %p\n", Headers);
/* If we didn't get the parameters, find them ourselves */ /* If we didn't get the parameters, find them ourselves */
StackReserve = (StackReserve) ? if (!StackReserve) StackReserve = Headers->OptionalHeader.
StackReserve : Headers->OptionalHeader.SizeOfStackReserve; SizeOfStackReserve;
StackCommit = (StackCommit) ? if (!StackCommit) StackCommit = Headers->OptionalHeader.
StackCommit : Headers->OptionalHeader.SizeOfStackCommit; SizeOfStackCommit;
} }
else else
{ {
/* Use the System Settings if needed */ /* Use the System Settings if needed */
StackReserve = (StackReserve) ? StackReserve : if (!StackReserve) StackReserve = SystemBasicInfo.AllocationGranularity;
SystemBasicInfo.AllocationGranularity; if (!StackCommit) StackCommit = SystemBasicInfo.PageSize;
StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
} }
/* Align everything to Page Size */ /* Align everything to Page Size */
StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity); StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize); StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
#if 1 // FIXME: Remove once Guard Page support is here
// FIXME: Remove once Guard Page support is here
#if 1
StackCommit = StackReserve; StackCommit = StackReserve;
#endif #endif
DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
/* Reserve memory for the stack */ /* Reserve memory for the stack */
Status = ZwAllocateVirtualMemory(hProcess, Status = ZwAllocateVirtualMemory(hProcess,
@ -82,11 +76,7 @@ RtlpCreateUserStack(HANDLE hProcess,
&StackReserve, &StackReserve,
MEM_RESERVE, MEM_RESERVE,
PAGE_READWRITE); PAGE_READWRITE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1("Failure to reserve stack\n");
return Status;
}
/* Now set up some basic Initial TEB Parameters */ /* Now set up some basic Initial TEB Parameters */
InitialTeb->PreviousStackBase = NULL; InitialTeb->PreviousStackBase = NULL;
@ -100,15 +90,12 @@ RtlpCreateUserStack(HANDLE hProcess,
/* Check if we will need a guard page */ /* Check if we will need a guard page */
if (StackReserve > StackCommit) if (StackReserve > StackCommit)
{ {
/* Remove a page to set as guard page */
Stack -= SystemBasicInfo.PageSize; Stack -= SystemBasicInfo.PageSize;
StackCommit += SystemBasicInfo.PageSize; StackCommit += SystemBasicInfo.PageSize;
UseGuard = TRUE; UseGuard = TRUE;
} }
DPRINT("AllocatedBase: %p, StackBase: %p, Stack: %lx, StackCommit: %lx\n",
InitialTeb->AllocatedStackBase, InitialTeb->StackBase, Stack,
StackCommit);
/* Allocate memory for the stack */ /* Allocate memory for the stack */
Status = ZwAllocateVirtualMemory(hProcess, Status = ZwAllocateVirtualMemory(hProcess,
(PVOID*)&Stack, (PVOID*)&Stack,
@ -116,56 +103,49 @@ RtlpCreateUserStack(HANDLE hProcess,
&StackCommit, &StackCommit,
MEM_COMMIT, MEM_COMMIT,
PAGE_READWRITE); PAGE_READWRITE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1("Failure to allocate stack\n");
return Status;
}
/* Now set the current Stack Limit */ /* Now set the current Stack Limit */
InitialTeb->StackLimit = (PVOID)Stack; InitialTeb->StackLimit = (PVOID)Stack;
DPRINT("StackLimit: %lx\n", Stack);
/* Create a guard page */ /* Create a guard page */
if (UseGuard) if (UseGuard)
{ {
ULONG GuardPageSize = SystemBasicInfo.PageSize;
ULONG Dummy;
/* Attempt maximum space possible */ /* Attempt maximum space possible */
GuardPageSize = SystemBasicInfo.PageSize;
Status = ZwProtectVirtualMemory(hProcess, Status = ZwProtectVirtualMemory(hProcess,
(PVOID*)&Stack, (PVOID*)&Stack,
&GuardPageSize, &GuardPageSize,
PAGE_GUARD | PAGE_READWRITE, PAGE_GUARD | PAGE_READWRITE,
&Dummy); &Dummy);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1("Failure to create guard page\n");
return Status;
}
/* Update the Stack Limit keeping in mind the Guard Page */ /* Update the Stack Limit keeping in mind the Guard Page */
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit -
GuardPageSize); GuardPageSize);
DPRINT1("StackLimit: %lx\n", Stack);
} }
/* We are done! */ /* We are done! */
return Status; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlpFreeUserStack(HANDLE hProcess, RtlpFreeUserStack(IN HANDLE Process,
PINITIAL_TEB InitialTeb) IN PINITIAL_TEB InitialTeb)
{ {
ULONG Dummy = 0; ULONG Dummy = 0;
NTSTATUS Status;
/* Free the Stack */ /* Free the Stack */
return ZwFreeVirtualMemory(hProcess, Status = ZwFreeVirtualMemory(Process,
&InitialTeb->AllocatedStackBase, &InitialTeb->AllocatedStackBase,
&Dummy, &Dummy,
MEM_RELEASE); MEM_RELEASE);
/* Clear the initial TEB */
RtlZeroMemory(InitialTeb, sizeof(INITIAL_TEB));
return Status;
} }
/* FUNCTIONS ***************************************************************/ /* FUNCTIONS ***************************************************************/
@ -175,16 +155,16 @@ RtlpFreeUserStack(HANDLE hProcess,
*/ */
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlCreateUserThread(HANDLE ProcessHandle, RtlCreateUserThread(IN HANDLE ProcessHandle,
PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
BOOLEAN CreateSuspended, IN BOOLEAN CreateSuspended,
LONG StackZeroBits, IN ULONG StackZeroBits OPTIONAL,
ULONG StackReserve, IN SIZE_T StackReserve OPTIONAL,
ULONG StackCommit, IN SIZE_T StackCommit OPTIONAL,
PTHREAD_START_ROUTINE StartAddress, IN PTHREAD_START_ROUTINE StartAddress,
PVOID Parameter, IN PVOID Parameter OPTIONAL,
PHANDLE ThreadHandle, OUT PHANDLE ThreadHandle OPTIONAL,
PCLIENT_ID ClientId) OUT PCLIENT_ID ClientId OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
HANDLE Handle; HANDLE Handle;
@ -193,23 +173,13 @@ RtlCreateUserThread(HANDLE ProcessHandle,
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
CONTEXT Context; CONTEXT Context;
DPRINT("RtlCreateUserThread: (hProcess: %p, Suspended: %d,"
"ZeroBits: %lx, StackReserve: %lx, StackCommit: %lx,"
"StartAddress: %p, Parameter: %p)\n", ProcessHandle,
CreateSuspended, StackZeroBits, StackReserve, StackCommit,
StartAddress, Parameter);
/* First, we'll create the Stack */ /* First, we'll create the Stack */
Status = RtlpCreateUserStack(ProcessHandle, Status = RtlpCreateUserStack(ProcessHandle,
StackReserve, StackReserve,
StackCommit, StackCommit,
StackZeroBits, StackZeroBits,
&InitialTeb); &InitialTeb);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1("Failure to create User Stack\n");
return Status;
}
/* Next, we'll set up the Initial Context */ /* Next, we'll set up the Initial Context */
RtlInitializeContext(ProcessHandle, RtlInitializeContext(ProcessHandle,
@ -234,14 +204,12 @@ RtlCreateUserThread(HANDLE ProcessHandle,
CreateSuspended); CreateSuspended);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failure to create Thread\n");
/* Free the stack */ /* Free the stack */
RtlpFreeUserStack(ProcessHandle, &InitialTeb); RtlpFreeUserStack(ProcessHandle, &InitialTeb);
} }
else else
{ {
DPRINT("Thread created: %p\n", Handle); /* Return thread data */
if (ThreadHandle) *ThreadHandle = Handle; if (ThreadHandle) *ThreadHandle = Handle;
if (ClientId) *ClientId = ThreadCid; if (ClientId) *ClientId = ThreadCid;
} }
@ -262,9 +230,6 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
IN PTHREAD_START_ROUTINE ThreadStartAddress, IN PTHREAD_START_ROUTINE ThreadStartAddress,
IN PINITIAL_TEB InitialTeb) IN PINITIAL_TEB InitialTeb)
{ {
DPRINT("RtlInitializeContext: (hProcess: %p, ThreadContext: %p, Teb: %p\n",
ProcessHandle, ThreadContext, InitialTeb);
/* /*
* Set the Initial Registers * Set the Initial Registers
* This is based on NT's default values -- crazy apps might expect this... * This is based on NT's default values -- crazy apps might expect this...
@ -279,14 +244,14 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
/* Set the Selectors */ /* Set the Selectors */
ThreadContext->SegGs = 0; ThreadContext->SegGs = 0;
ThreadContext->SegFs = KGDT_R3_TEB | RPL_MASK; ThreadContext->SegFs = KGDT_R3_TEB;
ThreadContext->SegEs = KGDT_R3_DATA | RPL_MASK; ThreadContext->SegEs = KGDT_R3_DATA;
ThreadContext->SegDs = KGDT_R3_DATA | RPL_MASK; ThreadContext->SegDs = KGDT_R3_DATA;
ThreadContext->SegCs = KGDT_R3_CODE | RPL_MASK; ThreadContext->SegSs = KGDT_R3_DATA;
ThreadContext->SegSs = KGDT_R3_DATA | RPL_MASK; ThreadContext->SegCs = KGDT_R3_CODE;
/* Enable Interrupts */ /* Enable Interrupts */
ThreadContext->EFlags = 0x200; /*X86_EFLAGS_IF */ ThreadContext->EFlags = EFLAGS_INTERRUPT_MASK;
/* Settings passed */ /* Settings passed */
ThreadContext->Eip = (ULONG)ThreadStartAddress; ThreadContext->Eip = (ULONG)ThreadStartAddress;
@ -343,11 +308,7 @@ RtlFreeUserThreadStack(HANDLE ProcessHandle,
&ThreadBasicInfo, &ThreadBasicInfo,
sizeof(THREAD_BASIC_INFORMATION), sizeof(THREAD_BASIC_INFORMATION),
NULL); NULL);
if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) return;
{
DPRINT1("Could not query info, or TEB is NULL\n");
return;
}
/* Get the deallocation stack */ /* Get the deallocation stack */
Status = NtReadVirtualMemory(ProcessHandle, Status = NtReadVirtualMemory(ProcessHandle,
@ -356,11 +317,7 @@ RtlFreeUserThreadStack(HANDLE ProcessHandle,
&StackLocation, &StackLocation,
sizeof(PVOID), sizeof(PVOID),
&Dummy); &Dummy);
if (!NT_SUCCESS(Status) || !StackLocation) if (!NT_SUCCESS(Status) || !StackLocation) return;
{
DPRINT1("Could not read Deallocation Base\n");
return;
}
/* Free it */ /* Free it */
NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE); NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE);

View file

@ -10,31 +10,32 @@
// //
// //
// Ob: // Ob:
// - Fix bug related to Deferred Loading (don't requeue active work item).
// - Add Directory Lock. // - Add Directory Lock.
// - Strengthen code with debug checks and assertions.
// - Fix FIXMEs/commented out code.
//
// Ex:
// - Fixup existing code that talks to Ke.
// - Implement Generic Callback mechanism.
// - Use pushlocks for handle implementation.
//
// Lpc:
// - Figure out why NTLPC-processes won't die anymore.
//
// Ke1:
// - Implement KiInitMachineDependent.
// - Implement Privileged Instruction Handler in Umode GPF.
// //
// Fstub: // Fstub:
// - Implement IoAssignDriveLetters using mount manager support. // - Implement IoAssignDriveLetters using mount manager support.
// //
// Ke: // Hal:
// - Figure out why the DPC stack doesn't really work. // - Use APC and DPC Interrupt Dispatchers.
// - Fix SEH/Page Fault + Exceptions!? Weird exception bugs! // - CMOS Initialization and CMOS Spinlock.
//
// Ke2:
// - New optimized table-based tick-hashed timer implementation. // - New optimized table-based tick-hashed timer implementation.
// - New Thread Scheduler based on 2003. // - New Thread Scheduler based on 2003.
// - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion.
//
// Hal:
// - New IRQL Implementation.
// - CMOS Initialization and CMOS Spinlock.
// - Report resource usage to kernel (HalReportResourceUsage).
//
// Lpc:
// - Activate new NTLPC and delete old implementation.
// - Figure out why LPC-processes won't die anymore.
//
// Ex:
// - Implement Generic Callback mechanism.
// - Use pushlocks for handle implementation.
// //
// Kd: // Kd:
// - Implement KD Kernel Debugging and WinDBG support. // - Implement KD Kernel Debugging and WinDBG support.
@ -45,3 +46,30 @@
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// REACTOS GUIDANCE PLAN
// ________________________________________________________________________________________________________
// / \
// | OB, PS, LPC, DBGK, IO => Almost entirely fixed interaction with Ke/Ex. | |
// | SE => Not looked at. Interaction with Ps/Io is minimal and currently hacked away. Preserve. |J|
// | EX => Needs re-visiting (in trunk). Do callbacks/push locks for interaction with Ps. |A|
// | KD/KDBG => Laptop has special version of ROS without these components. Commit in branch. |N|
// | INIT => Boot sequence still needs work in terms of interaction with Ke and CPU features. | |
// | || || || || || || || || || || || || |F|
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |E|
// | HAL => Needs APC/DPC/IRQL implementation fixed ASAP in terms of interaction with Ke. |B|
// | FSTUB => Needs IoAssignDriveLetters fixed ASAP but not critical to Ke/Ex. Interacts with Io. | |
// | || || || || || || || || || || || || |M|
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |A|
// | CM => TOTAL REWRITE. |R|
// | || || || || || || || || || || || || | |
// | || || || || || || || || || || || || |A|
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |P|
// | KE => Timer Rewrite + Thread Scheduler Rewrite. |R|
// | || || || || || || || || || || || || |I|
// | || || || || || || || || || || || || |L|
// | || || || || || || || || || || || || | |
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |M|
// | MM => TOTAL REWRITE. |A|
// | |Y|
// \________________________________________________________________________________________________________/
//

View file

@ -381,6 +381,9 @@
*/ */
.global @ExInterlockedPopEntrySList@8 .global @ExInterlockedPopEntrySList@8
.global @InterlockedPopEntrySList@4 .global @InterlockedPopEntrySList@4
.global _ExpInterlockedPopEntrySListResume@0
.global _ExpInterlockedPopEntrySListFault@0
.global _ExpInterlockedPopEntrySListEnd@0
@ExInterlockedPopEntrySList@8: @ExInterlockedPopEntrySList@8:
@InterlockedPopEntrySList@4: @InterlockedPopEntrySList@4:
@ -392,10 +395,10 @@
mov ebp, ecx mov ebp, ecx
/* Get sequence number and link pointer */ /* Get sequence number and link pointer */
_ExpInterlockedPopEntrySListResume@0:
mov edx, [ebp+4] mov edx, [ebp+4]
mov eax, [ebp] mov eax, [ebp]
1:
/* Check if the list is empty */ /* Check if the list is empty */
or eax, eax or eax, eax
jz 2f jz 2f
@ -404,9 +407,11 @@
lea ecx, [edx-1] lea ecx, [edx-1]
/* Get next pointer and do the exchange */ /* Get next pointer and do the exchange */
_ExpInterlockedPopEntrySListFault@0:
mov ebx, [eax] mov ebx, [eax]
_ExpInterlockedPopEntrySListEnd@0:
LOCK cmpxchg8b [ebp] LOCK cmpxchg8b [ebp]
jnz 1b jnz _ExpInterlockedPopEntrySListResume@0
/* Restore registers and return */ /* Restore registers and return */
2: 2:

View file

@ -65,6 +65,30 @@
#define RELEASE_SPINLOCK(x) #define RELEASE_SPINLOCK(x)
#endif #endif
//
// @name UNHANDLED_PATH
//
// This macro TODO
//
// @param None
//
// @remark None.
//
.macro UNHANDLED_PATH
/* Get EIP */
call $+5
pop eax
/* Print debug message */
push eax
push offset _UnhandledMsg
call _DbgPrint
add esp, 8
/* Loop indefinitely */
jmp $
.endm
// //
// @name IDT // @name IDT
// //
@ -182,7 +206,6 @@ _KiUnexpectedInterrupt&Number:
push offset V86DebugMsg push offset V86DebugMsg
call _DbgPrint call _DbgPrint
add esp, 8 add esp, 8
int 3
jmp $ jmp $
.endm .endm
@ -511,7 +534,7 @@ _KiUnexpectedInterrupt&Number:
/* Check if this was kernel mode */ /* Check if this was kernel mode */
1: 1:
cmp dword ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
jz 1f jz 1f
/* Set segments */ /* Set segments */
@ -947,7 +970,7 @@ PendingUserApc:
/* Assert the saved exception list */ /* Assert the saved exception list */
or edx, edx or edx, edx
jnz 1f jnz 1f
int 3 UNHANDLED_PATH
1: 1:
#endif #endif
@ -962,7 +985,7 @@ PendingUserApc:
/* Assert the saved previous mode */ /* Assert the saved previous mode */
cmp ecx, -1 cmp ecx, -1
jnz 1f jnz 1f
int 3 UNHANDLED_PATH
1: 1:
#endif #endif
@ -976,7 +999,7 @@ PendingUserApc:
mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE] mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
cmp ecx, -1 cmp ecx, -1
jz 1f jz 1f
int 3 UNHANDLED_PATH
1: 1:
#endif #endif
.endif .endif
@ -1111,7 +1134,7 @@ FastExit:
add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00 add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
6: 6:
int 3 UNHANDLED_PATH
jmp 5b jmp 5b
#endif #endif

View file

@ -41,12 +41,8 @@
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */ #define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */
#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */ #define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
#define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */
#define FRAME_EDITED 0xFFF8 #define FRAME_EDITED 0xFFF8
#define WE_DO_NOT_SPEAK_ABOUT_THE_V86_HACK 1
#ifndef __ASM__ #ifndef __ASM__
extern ULONG Ke386CacheAlignment; extern ULONG Ke386CacheAlignment;

View file

@ -130,6 +130,8 @@ extern PVOID KeUserApcDispatcher;
extern PVOID KeUserCallbackDispatcher; extern PVOID KeUserCallbackDispatcher;
extern PVOID KeUserExceptionDispatcher; extern PVOID KeUserExceptionDispatcher;
extern PVOID KeRaiseUserExceptionDispatcher; extern PVOID KeRaiseUserExceptionDispatcher;
extern UCHAR KiDebugRegisterTrapOffsets[9];
extern UCHAR KiDebugRegisterContextOffsets[9];
/* MACROS *************************************************************************/ /* MACROS *************************************************************************/

View file

@ -6,6 +6,86 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/ */
//
// Thread Dispatcher Header DebugActive Mask
//
#define DR_MASK(x) 1 << x
#define DR_ACTIVE_MASK 0x10
#define DR_REG_MASK 0x4F
//
// Sanitizes a selector
//
FORCEINLINE
ULONG
Ke386SanitizeSeg(IN ULONG Cs,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and force CPL 0 if so.
// Otherwise, force CPL 3.
//
return ((Mode == KernelMode) ?
(Cs & (0xFFFF & ~RPL_MASK)) :
(RPL_MASK | (Cs & 0xFFFF)));
}
//
// Sanitizes EFLAGS
//
FORCEINLINE
ULONG
Ke386SanitizeFlags(IN ULONG Eflags,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and sanitize EFLAGS if so.
// Otherwise, also force interrupt mask on.
//
return ((Mode == KernelMode) ?
(Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
(EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
}
//
// Gets a DR register from a CONTEXT structure
//
FORCEINLINE
PVOID
KiDrFromContext(IN ULONG Dr,
IN PCONTEXT Context)
{
return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
}
//
// Gets a DR register from a KTRAP_FRAME structure
//
FORCEINLINE
PVOID*
KiDrFromTrapFrame(IN ULONG Dr,
IN PKTRAP_FRAME TrapFrame)
{
return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
}
//
//
//
FORCEINLINE
PVOID
Ke386SanitizeDr(IN PVOID DrAddress,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and return the address directly if so.
// Otherwise, make sure it's not inside the kernel-mode address space.
// If it is, then clear the address.
//
return ((Mode == KernelMode) ? DrAddress :
(DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
}
// //
// Enters a Guarded Region // Enters a Guarded Region
// //

View file

@ -686,17 +686,10 @@ MmPageFault(
NTSTATUS NTSTATUS
NTAPI NTAPI
MmAccessFault( MmAccessFault(
KPROCESSOR_MODE Mode, IN BOOLEAN StoreInstruction,
ULONG_PTR Address, IN PVOID Address,
BOOLEAN FromMdl IN KPROCESSOR_MODE Mode,
); IN PVOID TrapInformation
NTSTATUS
NTAPI
MmNotPresentFault(
KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl
); );
/* anonmem.c *****************************************************************/ /* anonmem.c *****************************************************************/

View file

@ -188,9 +188,10 @@ ObQueryDeviceMapInformation(
// Object Lifetime Functions // Object Lifetime Functions
// //
VOID VOID
FASTCALL NTAPI
ObpDeleteObject( ObpDeleteObject(
IN PVOID Object IN PVOID Object,
IN BOOLEAN CalledFromWorkerThread
); );
LONG LONG

View file

@ -29,17 +29,17 @@ UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS];
/* The TSS to use for NMI Fault Traps (INT 0x2) */ /* The TSS to use for NMI Fault Traps (INT 0x2) */
UCHAR KiNMITSS[KTSS_IO_MAPS]; UCHAR KiNMITSS[KTSS_IO_MAPS];
/* The Boot GDT (FIXME: should have more entries */ /* The Boot GDT */
KGDTENTRY KiBootGdt[12] = KGDTENTRY KiBootGdt[256] =
{ {
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_NULL */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_NULL */
{0xffff, 0x0000, {{0x00, 0x9a, 0xcf, 0x00}}}, /* KGDT_R0_CODE */ {0xffff, 0x0000, {{0x00, 0x9b, 0xcf, 0x00}}}, /* KGDT_R0_CODE */
{0xffff, 0x0000, {{0x00, 0x92, 0xcf, 0x00}}}, /* KGDT_R0_DATA */ {0xffff, 0x0000, {{0x00, 0x93, 0xcf, 0x00}}}, /* KGDT_R0_DATA */
{0xffff, 0x0000, {{0x00, 0xfa, 0xcf, 0x00}}}, /* KGDT_R3_CODE */ {0xffff, 0x0000, {{0x00, 0xfb, 0xcf, 0x00}}}, /* KGDT_R3_CODE */
{0xffff, 0x0000, {{0x00, 0xf2, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/ {0xffff, 0x0000, {{0x00, 0xf3, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_TSS */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_TSS */
{0x0fff, 0x0000, {{0x00, 0x92, 0x00, 0xff}}}, /* KGDT_R0_PCR */ {0x0fff, 0x0000, {{0x00, 0x93, 0xc0, 0xff}}}, /* KGDT_R0_PCR */
{0x0fff, 0x0000, {{0x00, 0xf2, 0x00, 0x00}}}, /* KGDT_R3_TEB */ {0x0fff, 0x0000, {{0x00, 0xf3, 0x40, 0x00}}}, /* KGDT_R3_TEB */
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_UNUSED */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_UNUSED */
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_LDT */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_LDT */
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_DF_TSS */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_DF_TSS */

View file

@ -14,6 +14,36 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* GLOBALS *******************************************************************/
/* DR Registers in the CONTEXT structure */
UCHAR KiDebugRegisterContextOffsets[9] =
{
FIELD_OFFSET(CONTEXT, Dr0),
FIELD_OFFSET(CONTEXT, Dr1),
FIELD_OFFSET(CONTEXT, Dr2),
FIELD_OFFSET(CONTEXT, Dr3),
0,
0,
FIELD_OFFSET(CONTEXT, Dr6),
FIELD_OFFSET(CONTEXT, Dr7),
0,
};
/* DR Registers in the KTRAP_FRAME structure */
UCHAR KiDebugRegisterTrapOffsets[9] =
{
FIELD_OFFSET(KTRAP_FRAME, Dr0),
FIELD_OFFSET(KTRAP_FRAME, Dr1),
FIELD_OFFSET(KTRAP_FRAME, Dr2),
FIELD_OFFSET(KTRAP_FRAME, Dr3),
0,
0,
FIELD_OFFSET(KTRAP_FRAME, Dr6),
FIELD_OFFSET(KTRAP_FRAME, Dr7),
0,
};
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
_SEH_DEFINE_LOCALS(KiCopyInfo) _SEH_DEFINE_LOCALS(KiCopyInfo)
@ -53,6 +83,101 @@ KeInitExceptions(VOID)
} }
} }
ULONG
FASTCALL
KiUpdateDr7(IN ULONG Dr7)
{
ULONG DebugMask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
/* Check if debugging is enabled */
if (DebugMask & DR_ACTIVE_MASK)
{
/* Sanity checks */
ASSERT((DebugMask & DR_REG_MASK) != 0);
ASSERT((Dr7 & ~DR7_RESERVED_MASK) == DR7_OVERRIDE_MASK);
return 0;
}
/* Return DR7 itself */
return Dr7;
}
BOOLEAN
FASTCALL
KiRecordDr7(OUT PULONG Dr7Ptr,
OUT PULONG DrMask)
{
ULONG NewMask, Mask;
UCHAR Result;
/* Check if the caller gave us a mask */
if (!DrMask)
{
/* He didn't use the one from the thread */
Mask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
}
else
{
/* He did, read it */
Mask = *DrMask;
}
/* Sanity check */
ASSERT((*Dr7Ptr & DR7_RESERVED_MASK) == 0);
/* Check if DR7 is empty */
NewMask = Mask;
if (!(*Dr7Ptr))
{
/* Assume failure */
Result = FALSE;
/* Check the DR mask */
NewMask &= 0x7F;
if (NewMask & DR_REG_MASK)
{
/* Set the active mask */
NewMask |= DR_ACTIVE_MASK;
/* Set DR7 override */
*DrMask = DR7_OVERRIDE_MASK;
}
else
{
/* Sanity check */
ASSERT(NewMask == 0);
}
}
else
{
/* Check if we have a mask or not */
Result = NewMask ? TRUE: FALSE;
/* Update the mask to disable debugging */
NewMask &= ~DR_ACTIVE_MASK;
NewMask |= 0x80;
}
/* Check if caller wants the new mask */
if (DrMask)
{
/* Update it */
*DrMask = NewMask;
}
else
{
/* Check if the mask changed */
if (Mask != NewMask)
{
/* Update it */
KeGetCurrentThread()->DispatcherHeader.DebugActive = NewMask;
}
}
/* Return the result */
return Result;
}
ULONG ULONG
NTAPI NTAPI
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame) KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
@ -192,6 +317,8 @@ KeContextToTrapFrame(IN PCONTEXT Context,
ULONG i; ULONG i;
BOOLEAN V86Switch = FALSE; BOOLEAN V86Switch = FALSE;
KIRQL OldIrql = APC_LEVEL; KIRQL OldIrql = APC_LEVEL;
ULONG DrMask = 0;
PVOID SafeDr;
/* Do this at APC_LEVEL */ /* Do this at APC_LEVEL */
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
@ -207,8 +334,8 @@ KeContextToTrapFrame(IN PCONTEXT Context,
V86Switch = TRUE; V86Switch = TRUE;
} }
/* Copy EFLAGS. FIXME: Needs to be sanitized */ /* Copy EFLAGS and sanitize them*/
TrapFrame->EFlags = Context->EFlags; TrapFrame->EFlags = Ke386SanitizeFlags(Context->EFlags, PreviousMode);
/* Copy EBP and EIP */ /* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp; TrapFrame->Ebp = Context->Ebp;
@ -222,14 +349,14 @@ KeContextToTrapFrame(IN PCONTEXT Context,
} }
else else
{ {
/* We weren't in V86, so sanitize the CS (FIXME!) */ /* We weren't in V86, so sanitize the CS */
TrapFrame->SegCs = Context->SegCs; TrapFrame->SegCs = Ke386SanitizeSeg(Context->SegCs, PreviousMode);
/* Don't let it under 8, that's invalid */ /* Don't let it under 8, that's invalid */
if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8)) if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
{ {
/* Force it to User CS */ /* Force it to User CS */
TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK); TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
} }
} }
@ -261,7 +388,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Check if we were in V86 Mode */ /* Check if we were in V86 Mode */
if (TrapFrame->EFlags & EFLAGS_V86_MASK) if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{ {
/* Copy the V86 Segments directlry */ /* Copy the V86 Segments directly */
TrapFrame->V86Ds = Context->SegDs; TrapFrame->V86Ds = Context->SegDs;
TrapFrame->V86Es = Context->SegEs; TrapFrame->V86Es = Context->SegEs;
TrapFrame->V86Fs = Context->SegFs; TrapFrame->V86Fs = Context->SegFs;
@ -272,12 +399,12 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* For kernel mode, write the standard values */ /* For kernel mode, write the standard values */
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegFs = Context->SegFs; TrapFrame->SegFs = Ke386SanitizeSeg(Context->SegFs, PreviousMode);
TrapFrame->SegGs = 0; TrapFrame->SegGs = 0;
} }
else else
{ {
/* For user mode, return the values directlry */ /* For user mode, return the values directly */
TrapFrame->SegDs = Context->SegDs; TrapFrame->SegDs = Context->SegDs;
TrapFrame->SegEs = Context->SegEs; TrapFrame->SegEs = Context->SegEs;
TrapFrame->SegFs = Context->SegFs; TrapFrame->SegFs = Context->SegFs;
@ -320,7 +447,13 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Mask out any invalid flags */ /* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS); FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* FIXME: Check if this is a VDM app */ /* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
(CR0_EM | CR0_MP);
}
} }
} }
@ -373,16 +506,40 @@ KeContextToTrapFrame(IN PCONTEXT Context,
} }
else else
{ {
/* Just dump the Fn state in */ /* Copy the structure */
RtlCopyMemory(&FxSaveArea->U.FnArea, FxSaveArea->U.FnArea.ControlWord = Context->FloatSave.
&Context->FloatSave, ControlWord;
sizeof(FNSAVE_FORMAT)); FxSaveArea->U.FnArea.StatusWord = Context->FloatSave.
StatusWord;
FxSaveArea->U.FnArea.TagWord = Context->FloatSave.TagWord;
FxSaveArea->U.FnArea.ErrorOffset = Context->FloatSave.
ErrorOffset;
FxSaveArea->U.FnArea.ErrorSelector = Context->FloatSave.
ErrorSelector;
FxSaveArea->U.FnArea.DataOffset = Context->FloatSave.
DataOffset;
FxSaveArea->U.FnArea.DataSelector = Context->FloatSave.
DataSelector;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy registers */
FxSaveArea->U.FnArea.RegisterArea[i] =
Context->FloatSave.RegisterArea[i];
}
} }
/* Mask out any invalid flags */ /* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS); FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* FIXME: Check if this is a VDM app */ /* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
(CR0_EM | CR0_MP);
}
} }
else else
{ {
@ -394,23 +551,38 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Handle the Debug Registers */ /* Handle the Debug Registers */
if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{ {
/* FIXME: All these should be sanitized */ /* Loop DR registers */
TrapFrame->Dr0 = Context->Dr0; for (i = 0; i < 4; i++)
TrapFrame->Dr1 = Context->Dr1; {
TrapFrame->Dr2 = Context->Dr2; /* Sanitize the context DR Address */
TrapFrame->Dr3 = Context->Dr3; SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode);
TrapFrame->Dr6 = Context->Dr6;
TrapFrame->Dr7 = Context->Dr7;
/* Check if usermode */ /* Save it in the trap frame */
*KiDrFromTrapFrame(i, TrapFrame) = SafeDr;
/* Check if this DR address is active and add it in the DR mask */
if (SafeDr) DrMask |= DR_MASK(i);
}
/* Now save and sanitize DR6 */
TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL;
if (TrapFrame->Dr6) DrMask |= DR_MASK(6);
/* Save and sanitize DR7 */
TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL;
KiRecordDr7(&TrapFrame->Dr7, &DrMask);
/* If we're in user-mode */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
/* Set the Debug Flag */ /* FIXME: Save the mask */
KeGetCurrentThread()->DispatcherHeader.DebugActive = //KeGetCurrentThread()->DispatcherHeader.DebugActive = DrMask;
(Context->Dr7 & DR7_ACTIVE) ? TRUE: FALSE;
} }
} }
/* Check if thread has IOPL and force it enabled if so */
if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
/* Restore IRQL */ /* Restore IRQL */
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql); if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
} }
@ -429,6 +601,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
} FloatSaveBuffer; } FloatSaveBuffer;
FLOATING_SAVE_AREA *FloatSaveArea; FLOATING_SAVE_AREA *FloatSaveArea;
KIRQL OldIrql = APC_LEVEL; KIRQL OldIrql = APC_LEVEL;
ULONG i;
/* Do this at APC_LEVEL */ /* Do this at APC_LEVEL */
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
@ -550,10 +723,23 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
KiFlushNPXState(NULL); KiFlushNPXState(NULL);
} }
/* Copy into the Context */ /* Copy structure */
RtlCopyMemory(&Context->FloatSave, Context->FloatSave.ControlWord = FloatSaveArea->ControlWord;
FloatSaveArea, Context->FloatSave.StatusWord = FloatSaveArea->StatusWord;
sizeof(FNSAVE_FORMAT)); Context->FloatSave.TagWord = FloatSaveArea->TagWord;
Context->FloatSave.ErrorOffset = FloatSaveArea->ErrorOffset;
Context->FloatSave.ErrorSelector = FloatSaveArea->ErrorSelector;
Context->FloatSave.DataOffset = FloatSaveArea->DataOffset;
Context->FloatSave.DataSelector = FloatSaveArea->DataSelector;
Context->FloatSave.Cr0NpxState = FxSaveArea->Cr0NpxState;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy them */
Context->FloatSave.RegisterArea[i] =
FloatSaveArea->RegisterArea[i];
}
} }
else else
{ {
@ -566,24 +752,26 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS) CONTEXT_DEBUG_REGISTERS)
{ {
/* Copy the debug registers */ /* Make sure DR7 is valid */
Context->Dr0 = TrapFrame->Dr0; if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK)
Context->Dr1 = TrapFrame->Dr1;
Context->Dr2 = TrapFrame->Dr2;
Context->Dr3 = TrapFrame->Dr3;
Context->Dr6 = TrapFrame->Dr6;
/* For user-mode, only set DR7 if a debugger is active */
if (((TrapFrame->SegCs & MODE_MASK) ||
(TrapFrame->EFlags & EFLAGS_V86_MASK)) &&
(KeGetCurrentThread()->DispatcherHeader.DebugActive))
{ {
/* Copy it over */ /* Copy the debug registers */
Context->Dr7 = TrapFrame->Dr7; Context->Dr0 = TrapFrame->Dr0;
Context->Dr1 = TrapFrame->Dr1;
Context->Dr2 = TrapFrame->Dr2;
Context->Dr3 = TrapFrame->Dr3;
Context->Dr6 = TrapFrame->Dr6;
/* Update DR7 */
//Context->Dr7 = KiUpdateDr7(TrapFrame->Dr7);
} }
else else
{ {
/* Clear it */ /* Otherwise clear DR registers */
Context->Dr0 =
Context->Dr1 =
Context->Dr3 =
Context->Dr6 =
Context->Dr7 = 0; Context->Dr7 = 0;
} }
} }
@ -757,13 +945,13 @@ DispatchToUser:
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR)); KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
/* Force correct segments */ /* Force correct segments */
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, PreviousMode);
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK; TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, PreviousMode);
TrapFrame->SegGs = 0; TrapFrame->SegGs = 0;
/* Set EIP to the User-mode Dispathcer */ /* Set EIP to the User-mode Dispatcher */
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher; TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
_SEH_LEAVE; _SEH_LEAVE;
} }

View file

@ -87,13 +87,17 @@ _KiUnexpectedEntrySize:
_UnexpectedMsg: _UnexpectedMsg:
.asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n" .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
_UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
/* SOFTWARE INTERRUPT SERVICES ***********************************************/ /* SOFTWARE INTERRUPT SERVICES ***********************************************/
.text .text
_KiGetTickCount: _KiGetTickCount:
_KiCallbackReturn: _KiCallbackReturn:
_KiRaiseAssertion: _KiRaiseAssertion:
int 3 /* FIXME: TODO */
UNHANDLED_PATH
.func KiSystemService .func KiSystemService
Dr_kss: DR_TRAP_FIXUP Dr_kss: DR_TRAP_FIXUP
@ -144,6 +148,7 @@ SharedCode:
/* Check if we should flush the User Batch */ /* Check if we should flush the User Batch */
xor ebx, ebx xor ebx, ebx
ReadBatch:
or ebx, [ecx+TEB_GDI_BATCH_COUNT] or ebx, [ecx+TEB_GDI_BATCH_COUNT]
jz NotWin32K jz NotWin32K
@ -432,8 +437,8 @@ V86_Exit:
iret iret
AbiosExit: AbiosExit:
/* Not yet supported */ /* FIXME: TODO */
int 3 UNHANDLED_PATH
.func KiDebugService .func KiDebugService
Dr_kids: DR_TRAP_FIXUP Dr_kids: DR_TRAP_FIXUP
@ -672,6 +677,13 @@ _DispatchTwoParam:
/* HARDWARE TRAP HANDLERS ****************************************************/ /* HARDWARE TRAP HANDLERS ****************************************************/
.func KiFixupFrame
_KiFixupFrame:
/* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
UNHANDLED_PATH
.endfunc
.func KiTrap0 .func KiTrap0
Dr_kit0: DR_TRAP_FIXUP Dr_kit0: DR_TRAP_FIXUP
V86_kit0: V86_TRAP_FIXUP V86_kit0: V86_TRAP_FIXUP
@ -710,7 +722,8 @@ VdmCheck:
/* We don't support this yet! */ /* We don't support this yet! */
V86Int0: V86Int0:
int 3 /* FIXME: TODO */
UNHANDLED_PATH
.endfunc .endfunc
.func KiTrap1 .func KiTrap1
@ -754,7 +767,7 @@ V86Int1:
jz EnableInterrupts jz EnableInterrupts
/* We don't support VDM! */ /* We don't support VDM! */
int 3 UNHANDLED_PATH
.endfunc .endfunc
.globl _KiTrap2 .globl _KiTrap2
@ -813,7 +826,7 @@ V86Int3:
jz EnableInterrupts3 jz EnableInterrupts3
/* We don't support VDM! */ /* We don't support VDM! */
int 3 UNHANDLED_PATH
.endfunc .endfunc
.func KiTrap4 .func KiTrap4
@ -855,7 +868,7 @@ VdmCheck4:
/* We don't support this yet! */ /* We don't support this yet! */
V86Int4: V86Int4:
int 3 UNHANDLED_PATH
.endfunc .endfunc
.func KiTrap5 .func KiTrap5
@ -901,7 +914,7 @@ VdmCheck5:
/* We don't support this yet! */ /* We don't support this yet! */
V86Int5: V86Int5:
int 3 UNHANDLED_PATH
.endfunc .endfunc
.func KiTrap6 .func KiTrap6
@ -917,8 +930,7 @@ _KiTrap6:
V86_TRAP_PROLOG kit6 V86_TRAP_PROLOG kit6
/* Not yet supported (Invalid OPCODE from V86) */ /* Not yet supported (Invalid OPCODE from V86) */
int 3 UNHANDLED_PATH
jmp $
NotV86UD: NotV86UD:
/* Push error code */ /* Push error code */
@ -993,8 +1005,7 @@ LockCrash:
IsVdmOpcode: IsVdmOpcode:
/* Unhandled yet */ /* Unhandled yet */
int 3 UNHANDLED_PATH
jmp $
/* Return to caller */ /* Return to caller */
jmp _Kei386EoiHelper@0 jmp _Kei386EoiHelper@0
@ -1302,8 +1313,7 @@ V86Npx:
jz HandleUserNpx jz HandleUserNpx
/* V86 NPX not handled */ /* V86 NPX not handled */
int 3 UNHANDLED_PATH
jmp $
EmulationEnabled: EmulationEnabled:
/* Did this come from kernel-mode? */ /* Did this come from kernel-mode? */
@ -1456,7 +1466,7 @@ RaiseIrql:
jnz NoReflect jnz NoReflect
/* FIXME: TODO */ /* FIXME: TODO */
int 3 UNHANDLED_PATH
NoReflect: NoReflect:
@ -1485,9 +1495,21 @@ NotV86:
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jnz UserModeGpf jnz UserModeGpf
/* FIXME: Check for GPF during GPF */ /* Check if we have a VDM alert */
cmp dword ptr fs:[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Check for GPF during GPF */
mov eax, [ebp+KTRAP_FRAME_EIP]
cmp eax, offset CheckPrivilegedInstruction
jbe KmodeGpf
cmp eax, offset CheckPrivilegedInstruction2
/* FIXME: TODO */
UNHANDLED_PATH
/* Get the opcode and trap frame */ /* Get the opcode and trap frame */
KmodeGpf:
mov eax, [ebp+KTRAP_FRAME_EIP] mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax] mov eax, [eax]
mov edx, [ebp+KTRAP_FRAME_EBP] mov edx, [ebp+KTRAP_FRAME_EBP]
@ -1573,8 +1595,7 @@ TrapCopy:
MsrCheck: MsrCheck:
/* FIXME: Handle RDMSR/WRMSR */ /* FIXME: Handle RDMSR/WRMSR */
int 3 UNHANDLED_PATH
jmp $
NotIretGpf: NotIretGpf:
@ -1606,7 +1627,6 @@ SegPopGpf:
lea eax, [ebp+KTRAP_FRAME_ESP] lea eax, [ebp+KTRAP_FRAME_ESP]
cmp edx, eax cmp edx, eax
jz HandleSegPop jz HandleSegPop
int 3
/* Handle segment POP fault by setting it to 0 */ /* Handle segment POP fault by setting it to 0 */
HandleSegPop: HandleSegPop:
@ -1620,26 +1640,239 @@ ExitGpfTrap:
UserModeGpf: UserModeGpf:
/* FIXME: Unhandled */ /* If the previous mode was kernel, raise a fatal exception */
int 3 mov eax, 13
jmp $ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz _KiSystemFatalException
/* Get the process and check which CS this came from */
mov ebx, fs:[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckVdmGpf
/* Check if this is a VDM */
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jnz DispatchV86Gpf
/* Enable interrupts and check if we have an error code */
sti
cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
jnz SetException
jmp CheckPrivilegedInstruction
HandleSegPop2:
/* Update EIP (will be updated below again) */
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
HandleBop4:
/* Clear the segment, update EIP and ESP */
mov dword ptr [edx], 0
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
add dword ptr [ebp+KTRAP_FRAME_ESP], 4
jmp _Kei386EoiHelper@0
CheckVdmGpf:
/* Check if this is a VDM */
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz CheckPrivilegedInstruction
/* Check what kind of instruction this is */
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
/* FIXME: Check for BOP4 */
/* Check if this is POP FS */
mov edx, ebp
add edx, KTRAP_FRAME_FS
cmp ax, 0xA10F
jz HandleSegPop2
/* Check if this is POP GS */
add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
cmp ax, 0xA90F
jz HandleSegPop2
CheckPrivilegedInstruction:
/* FIXME */
UNHANDLED_PATH
CheckPrivilegedInstruction2:
/* FIXME */
UNHANDLED_PATH
SetException:
/* FIXME */
UNHANDLED_PATH
DispatchV86Gpf:
/* FIXME */
UNHANDLED_PATH
.endfunc .endfunc
.func KiTrap14 .func KiTrap14
Dr_kit14: DR_TRAP_FIXUP Dr_kit14: DR_TRAP_FIXUP
V86_kit14: V86_TRAP_FIXUP V86_kit14: V86_TRAP_FIXUP
_KiTrap14: _KiTrap14:
/* Enter trap */ /* Enter trap */
TRAP_PROLOG kit14 TRAP_PROLOG kit14
/* Call the C exception handler */ /* Check if we have a VDM alert */
push 14 cmp dword ptr fs:[KPCR_VDM_ALERT], 0
push ebp jnz VdmAlertGpf
call _KiPageFaultHandler
add esp, 8
/* Return to caller */ /* Get the current thread */
mov edi, fs:[KPCR_CURRENT_THREAD]
/* Get the stack address of the frame */
lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
sub eax, [edi+KTHREAD_INITIAL_STACK]
jz NoFixUp
/* This isn't the base frame, check if it's the second */
cmp eax, -KTRAP_FRAME_EFLAGS
jb NoFixUp
/* Check if we have a TEB */
mov eax, fs:[KPCR_TEB]
or eax, eax
jle NoFixUp
/* Fixup the frame */
call _KiFixupFrame
/* Save CR2 */
NoFixUp:
mov edi, cr2
/* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
je HandlePf
/* Enable interrupts and check if we got here with interrupts disabled */
sti
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
jz IllegalState
HandlePf:
/* Send trap frame and check if this is kernel-mode or usermode */
push ebp
mov eax, [ebp+KTRAP_FRAME_CS]
and eax, MODE_MASK
push eax
/* Send faulting address and check if this is read or write */
push edi
mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
and eax, 1
push eax
/* Call the access fault handler */
call _MmAccessFault@16
test eax, eax
jl AccessFail
/* Access fault handled, return to caller */
jmp _Kei386EoiHelper@0 jmp _Kei386EoiHelper@0
AccessFail:
/* First check if this is a fault in the S-LIST functions */
mov ecx, offset _ExpInterlockedPopEntrySListFault@0
cmp [ebp+KTRAP_FRAME_EIP], ecx
jz SlistFault
/* Check if this is a fault in the syscall handler */
mov ecx, offset CopyParams
cmp [ebp+KTRAP_FRAME_EIP], ecx
jz SysCallCopyFault
mov ecx, offset ReadBatch
cmp [ebp+KTRAP_FRAME_EIP], ecx
jnz CheckVdmPf
/* FIXME: TODO */
UNHANDLED_PATH
jmp _Kei386EoiHelper@0
SysCallCopyFault:
/* FIXME: TODO */
UNHANDLED_PATH
jmp _Kei386EoiHelper@0
/* Check if the fault occured in a V86 mode */
CheckVdmPf:
mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
and ecx, 1
shr ecx, 1
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz VdmPF
/* Check if the fault occured in a VDM */
mov esi, fs:[KPCR_CURRENT_THREAD]
mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
jz CheckStatus
/* Check if we this was in kernel-mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz CheckStatus
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckStatus
VdmPF:
/* FIXME: TODO */
UNHANDLED_PATH
/* Save EIP and check what kind of status failure we got */
CheckStatus:
mov esi, [ebp+KTRAP_FRAME_EIP]
cmp eax, STATUS_ACCESS_VIOLATION
je AccessViol
cmp eax, STATUS_GUARD_PAGE_VIOLATION
je SpecialCode
cmp eax, STATUS_STACK_OVERFLOW
je SpecialCode
/* Setup an in-page exception to dispatch */
mov edx, ecx
mov ebx, esi
mov esi, edi
mov ecx, 3
mov edi, eax
mov eax, STATUS_IN_PAGE_ERROR
call _CommonDispatchException
AccessViol:
/* Use more proper status code */
mov eax, KI_EXCEPTION_ACCESS_VIOLATION
SpecialCode:
/* Setup a normal page fault exception */
mov ebx, esi
mov edx, ecx
mov esi, edi
jmp _DispatchTwoParam
SlistFault:
/* FIXME: TODO */
UNHANDLED_PATH
IllegalState:
/* This is completely illegal, bugcheck the system */
push ebp
push esi
push ecx
push eax
push edi
push IRQL_NOT_LESS_OR_EQUAL
call _KeBugCheckWithTf@24
VdmAlertGpf:
/* FIXME: NOT SUPPORTED */
UNHANDLED_PATH
.endfunc .endfunc
.func KiTrap0F .func KiTrap0F
@ -1752,8 +1985,7 @@ _Ki16BitStackException:
add esp, [eax+KTHREAD_INITIAL_STACK] add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */ /* Switch to good stack segment */
/* TODO */ UNHANDLED_PATH
int 3
.endfunc .endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/ /* UNEXPECTED INTERRUPT HANDLERS **********************************************/
@ -1867,7 +2099,7 @@ CheckQuantum:
jz Return jz Return
/* FIXME: Schedule new thread */ /* FIXME: Schedule new thread */
int 3 UNHANDLED_PATH
Return: Return:
/* All done */ /* All done */
@ -1904,7 +2136,7 @@ _KiInterruptTemplateDispatch:
_KiChainedDispatch2ndLvl@0: _KiChainedDispatch2ndLvl@0:
/* Not yet supported */ /* Not yet supported */
int 3 UNHANDLED_PATH
.endfunc .endfunc
.func KiChainedDispatch@0 .func KiChainedDispatch@0

View file

@ -71,7 +71,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
_SEH_DECLARE_LOCALS(KiCopyInfo); _SEH_DECLARE_LOCALS(KiCopyInfo);
/* Don't deliver APCs in V86 mode */ /* Don't deliver APCs in V86 mode */
if (TrapFrame->EFlags & X86_EFLAGS_VM) return; if (TrapFrame->EFlags & EFLAGS_V86_MASK) return;
/* Save the full context */ /* Save the full context */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
@ -102,22 +102,19 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
TrapFrame->HardwareEsp = Stack; TrapFrame->HardwareEsp = Stack;
/* Setup Ring 3 state */ /* Setup Ring 3 state */
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, UserMode);
TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK; TrapFrame->HardwareSegSs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, UserMode);
TrapFrame->SegGs = 0; TrapFrame->SegGs = 0;
TrapFrame->ErrCode = 0;
/* Sanitize EFLAGS */ /* Sanitize EFLAGS */
TrapFrame->EFlags = Context.EFlags & EFLAGS_USER_SANITIZE; TrapFrame->EFlags = Ke386SanitizeFlags(Context.EFlags, UserMode);
TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
/* Check if user-mode has IO privileges */ /* Check if thread has IOPL and force it enabled if so */
if (KeGetCurrentThread()->Iopl) if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
{
/* Enable them*/
TrapFrame->EFlags |= (0x3000);
}
/* Setup the stack */ /* Setup the stack */
*(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine; *(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;

View file

@ -1,17 +0,0 @@
.globl @MmSafeReadPtr@4
.globl _MmSafeReadPtrStart
.globl _MmSafeReadPtrEnd
/*****************************************************************************/
/*
* PVOID FASTCALL MmSafeReadPtr(PVOID Source)
*/
@MmSafeReadPtr@4:
_MmSafeReadPtrStart:
/*
* If we incur a pagefault, eax will be set NULL
*/
movl (%ecx),%eax
_MmSafeReadPtrEnd:
ret

View file

@ -1,135 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/pfault.c
* PURPOSE: Paging file functions
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* EXTERNS *******************************************************************/
extern VOID MmSafeReadPtrStart(VOID);
extern VOID MmSafeReadPtrEnd(VOID);
extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
extern ULONG KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2);
extern BOOLEAN Ke386NoExecute;
/* FUNCTIONS *****************************************************************/
ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
{
ULONG_PTR cr2;
NTSTATUS Status;
KPROCESSOR_MODE Mode;
EXCEPTION_RECORD Er;
ASSERT(ExceptionNr == 14);
/* get the faulting address */
cr2 = __readcr2();
Tf->DbgArgPointer = cr2;
/* it's safe to enable interrupts after cr2 has been saved */
if (Tf->EFlags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
{
_enable();
}
if (cr2 >= (ULONG_PTR)MmSystemRangeStart)
{
/* check for an invalid page directory in kernel mode */
if (!(Tf->ErrCode & 0x5) && Mmi386MakeKernelPageTableGlobal((PVOID)cr2))
{
return 0;
}
/* check for non executable memory in kernel mode */
if (Ke386NoExecute && Tf->ErrCode & 0x10)
{
KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
}
}
Mode = Tf->ErrCode & 0x4 ? UserMode : KernelMode;
/* handle the fault */
if (Tf->ErrCode & 0x1)
{
Status = MmAccessFault(Mode, cr2, FALSE);
}
else
{
Status = MmNotPresentFault(Mode, cr2, FALSE);
}
/* handle the return for v86 mode */
if (Tf->EFlags & X86_EFLAGS_VM)
{
if (!NT_SUCCESS(Status))
{
/* FIXME: This should use ->VdmObjects */
if(!PsGetCurrentProcess()->Pcb.Unused)
{
*((PKV86M_TRAP_FRAME)Tf)->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
}
return 1;
}
return 0;
}
if (Mode == KernelMode)
{
if (!NT_SUCCESS(Status))
{
if (Tf->Eip >= (ULONG_PTR)MmSafeReadPtrStart &&
Tf->Eip < (ULONG_PTR)MmSafeReadPtrEnd)
{
Tf->Eip = (ULONG_PTR)MmSafeReadPtrEnd;
Tf->Eax = 0;
return 0;
}
}
}
else
{
if (KeGetCurrentThread()->ApcState.UserApcPending)
{
KIRQL oldIrql;
KeRaiseIrql(APC_LEVEL, &oldIrql);
KiDeliverApc(UserMode, NULL, NULL);
KeLowerIrql(oldIrql);
}
}
if (NT_SUCCESS(Status))
{
return 0;
}
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
Er.ExceptionFlags = 0;
Er.ExceptionRecord = NULL;
Er.ExceptionAddress = (PVOID)Tf->Eip;
Er.NumberParameters = 2;
Er.ExceptionInformation[0] = Tf->ErrCode & 0x1;
Er.ExceptionInformation[1] = (ULONG)cr2;
/* FIXME: Which exceptions are noncontinuable? */
Er.ExceptionFlags = 0;
KiDispatchException(&Er, 0, Tf, Mode, TRUE);
return 0;
}

View file

@ -433,7 +433,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
if (!MmIsPagePresent(NULL, Address)) if (!MmIsPagePresent(NULL, Address))
{ {
Status = MmNotPresentFault(Mode, (ULONG_PTR)Address, TRUE); Status = MmAccessFault(FALSE, Address, Mode, NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
@ -457,7 +457,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) && if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE))) (!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
{ {
Status = MmAccessFault(Mode, (ULONG_PTR)Address, TRUE); Status = MmAccessFault(TRUE, Address, Mode, NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
for (j = 0; j < i; j++) for (j = 0; j < i; j++)

View file

@ -75,9 +75,9 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress)
NTSTATUS NTSTATUS
NTAPI NTAPI
MmAccessFault(KPROCESSOR_MODE Mode, MmpAccessFault(KPROCESSOR_MODE Mode,
ULONG_PTR Address, ULONG_PTR Address,
BOOLEAN FromMdl) BOOLEAN FromMdl)
{ {
PMADDRESS_SPACE AddressSpace; PMADDRESS_SPACE AddressSpace;
MEMORY_AREA* MemoryArea; MEMORY_AREA* MemoryArea;
@ -109,7 +109,7 @@ MmAccessFault(KPROCESSOR_MODE Mode,
{ {
DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
DbgPrint("%s:%d\n",__FILE__,__LINE__); DbgPrint("%s:%d\n",__FILE__,__LINE__);
return(STATUS_UNSUCCESSFUL); return(STATUS_ACCESS_VIOLATION);
} }
AddressSpace = MmGetKernelAddressSpace(); AddressSpace = MmGetKernelAddressSpace();
} }
@ -131,13 +131,13 @@ MmAccessFault(KPROCESSOR_MODE Mode,
{ {
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
} }
return (STATUS_UNSUCCESSFUL); return (STATUS_ACCESS_VIOLATION);
} }
switch (MemoryArea->Type) switch (MemoryArea->Type)
{ {
case MEMORY_AREA_SYSTEM: case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_ACCESS_VIOLATION;
break; break;
case MEMORY_AREA_PAGED_POOL: case MEMORY_AREA_PAGED_POOL:
@ -152,15 +152,15 @@ MmAccessFault(KPROCESSOR_MODE Mode,
break; break;
case MEMORY_AREA_VIRTUAL_MEMORY: case MEMORY_AREA_VIRTUAL_MEMORY:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_ACCESS_VIOLATION;
break; break;
case MEMORY_AREA_SHARED_DATA: case MEMORY_AREA_SHARED_DATA:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_ACCESS_VIOLATION;
break; break;
default: default:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_ACCESS_VIOLATION;
break; break;
} }
} }
@ -174,32 +174,6 @@ MmAccessFault(KPROCESSOR_MODE Mode,
return(Status); return(Status);
} }
NTSTATUS
NTAPI
MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
{
NTSTATUS Status;
PFN_TYPE AllocatedPage;
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
MmLockAddressSpace(MmGetKernelAddressSpace());
}
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
&AllocatedPage,
1);
if (Locked)
{
MmLockPage(AllocatedPage);
}
return(Status);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
MmNotPresentFault(KPROCESSOR_MODE Mode, MmNotPresentFault(KPROCESSOR_MODE Mode,
@ -227,7 +201,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
DPRINT("No current process\n"); DPRINT("No current process\n");
if (Address < (ULONG_PTR)MmSystemRangeStart) if (Address < (ULONG_PTR)MmSystemRangeStart)
{ {
return(STATUS_UNSUCCESSFUL); return(STATUS_ACCESS_VIOLATION);
} }
} }
@ -242,7 +216,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
if (Mode != KernelMode) if (Mode != KernelMode)
{ {
CPRINT("Address: %x\n", Address); CPRINT("Address: %x\n", Address);
return(STATUS_UNSUCCESSFUL); return(STATUS_ACCESS_VIOLATION);
} }
AddressSpace = MmGetKernelAddressSpace(); AddressSpace = MmGetKernelAddressSpace();
} }
@ -268,7 +242,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
{ {
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
} }
return (STATUS_UNSUCCESSFUL); return (STATUS_ACCESS_VIOLATION);
} }
switch (MemoryArea->Type) switch (MemoryArea->Type)
@ -280,7 +254,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
} }
case MEMORY_AREA_SYSTEM: case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_ACCESS_VIOLATION;
break; break;
case MEMORY_AREA_SECTION_VIEW: case MEMORY_AREA_SECTION_VIEW:
@ -309,7 +283,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
break; break;
default: default:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_ACCESS_VIOLATION;
break; break;
} }
} }
@ -323,6 +297,67 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
return(Status); return(Status);
} }
extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
NTSTATUS
NTAPI
MmAccessFault(IN BOOLEAN StoreInstruction,
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation)
{
/* Cute little hack for ROS */
if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
{
/* Check for an invalid page directory in kernel mode */
if (Mmi386MakeKernelPageTableGlobal(Address))
{
/* All is well with the world */
return STATUS_SUCCESS;
}
}
/* Keep same old ReactOS Behaviour */
if (StoreInstruction)
{
/* Call access fault */
return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
}
else
{
/* Call not present */
return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
}
}
NTSTATUS
NTAPI
MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
{
NTSTATUS Status;
PFN_TYPE AllocatedPage;
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
MmLockAddressSpace(MmGetKernelAddressSpace());
}
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
&AllocatedPage,
1);
if (Locked)
{
MmLockPage(AllocatedPage);
}
return(Status);
}
/* Miscellanea functions: they may fit somewhere else */ /* Miscellanea functions: they may fit somewhere else */
/* /*

View file

@ -257,9 +257,7 @@
<directory name="mm"> <directory name="mm">
<if property="ARCH" value="i386"> <if property="ARCH" value="i386">
<directory name="i386"> <directory name="i386">
<file>memsafe.s</file>
<file>page.c</file> <file>page.c</file>
<file>pfault.c</file>
</directory> </directory>
</if> </if>
<file>anonmem.c</file> <file>anonmem.c</file>

View file

@ -134,8 +134,9 @@ ObpDeallocateObject(IN PVOID Object)
} }
VOID VOID
FASTCALL NTAPI
ObpDeleteObject(IN PVOID Object) ObpDeleteObject(IN PVOID Object,
IN BOOLEAN CalledFromWorkerThread)
{ {
POBJECT_HEADER Header; POBJECT_HEADER Header;
POBJECT_TYPE ObjectType; POBJECT_TYPE ObjectType;
@ -203,12 +204,15 @@ VOID
NTAPI NTAPI
ObpReapObject(IN PVOID Parameter) ObpReapObject(IN PVOID Parameter)
{ {
POBJECT_HEADER ReapObject; POBJECT_HEADER ReapObject = (PVOID)1;
PVOID NextObject; PVOID NextObject;
/* Start reaping */ /* Start reaping */
while ((ReapObject = InterlockedExchangePointer(&ObpReaperList, NULL))) do
{ {
/* Get the reap object */
ReapObject = InterlockedExchangePointer(&ObpReaperList, ReapObject);
/* Start deletion loop */ /* Start deletion loop */
do do
{ {
@ -216,12 +220,13 @@ ObpReapObject(IN PVOID Parameter)
NextObject = ReapObject->NextToFree; NextObject = ReapObject->NextToFree;
/* Delete the object */ /* Delete the object */
ObpDeleteObject(&ReapObject->Body); ObpDeleteObject(&ReapObject->Body, TRUE);
/* Move to the next one */ /* Move to the next one */
ReapObject = NextObject; ReapObject = NextObject;
} while (NextObject); } while ((NextObject) && (NextObject != (PVOID)1));
} } while ((ObpReaperList != (PVOID)1) ||
(InterlockedCompareExchange((PLONG)&ObpReaperList, 0, 1) != 1));
} }
/*++ /*++

View file

@ -50,21 +50,27 @@ ObReferenceObjectSafe(IN PVOID Object)
VOID VOID
NTAPI NTAPI
ObpDeferObjectDeletion(IN PVOID Object) ObpDeferObjectDeletion(IN POBJECT_HEADER Header)
{ {
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object); PVOID Entry, NewEntry;
/* Add us to the list */ /* Loop while trying to update the list */
do do
{ {
Header->NextToFree = ObpReaperList; /* Get the current entry */
} while (InterlockedCompareExchangePointer(&ObpReaperList, Entry = ObpReaperList;
Header,
Header->NextToFree) !=
Header->NextToFree);
/* Queue the work item */ /* Link our object to the list */
ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue); Header->NextToFree = Entry;
NewEntry = Header;
/* Update the list */
} while (InterlockedCompareExchangePointer(&ObpReaperList,
NewEntry,
Entry) != Entry);
/* Queue the work item if needed */
if (!Entry) ExQueueWorkItem(&ObpReaperWorkItem, CriticalWorkQueue);
} }
LONG LONG
@ -91,11 +97,7 @@ ObDereferenceObjectEx(IN PVOID Object,
/* Check whether the object can now be deleted. */ /* Check whether the object can now be deleted. */
NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count); NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count);
if (!Count) if (!Count) ObpDeferObjectDeletion(Header);
{
/* Add us to the deferred deletion list */
ObpDeferObjectDeletion(Object);
}
/* Return the current count */ /* Return the current count */
return NewCount; return NewCount;
@ -308,12 +310,12 @@ ObfDereferenceObject(IN PVOID Object)
if (KeGetCurrentIrql() == PASSIVE_LEVEL) if (KeGetCurrentIrql() == PASSIVE_LEVEL)
{ {
/* Remove the object */ /* Remove the object */
ObpDeleteObject(Object); ObpDeleteObject(Object, FALSE);
} }
else else
{ {
/* Add us to the deferred deletion list */ /* Add us to the deferred deletion list */
ObpDeferObjectDeletion(Object); ObpDeferObjectDeletion(Header);
} }
} }
@ -325,11 +327,13 @@ VOID
NTAPI NTAPI
ObDereferenceObjectDeferDelete(IN PVOID Object) ObDereferenceObjectDeferDelete(IN PVOID Object)
{ {
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
/* Check whether the object can now be deleted. */ /* Check whether the object can now be deleted. */
if (!(InterlockedDecrement(&OBJECT_TO_OBJECT_HEADER(Object)->PointerCount))) if (!InterlockedDecrement(&Header->PointerCount))
{ {
/* Add us to the deferred deletion list */ /* Add us to the deferred deletion list */
ObpDeferObjectDeletion(Object); ObpDeferObjectDeletion(Header);
} }
} }

View file

@ -50,7 +50,7 @@ VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
/* Make sure that we're at APC_LEVEL and that this is a valid frame */ /* Make sure that we're at APC_LEVEL and that this is a valid frame */
ASSERT_IRQL(APC_LEVEL); ASSERT_IRQL(APC_LEVEL);
ASSERT(TrapFrame->DbgArgMark = 0xBADB0D00); ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
/* Check if this is a V86 frame */ /* Check if this is a V86 frame */
if (TrapFrame->EFlags & EFLAGS_V86_MASK) if (TrapFrame->EFlags & EFLAGS_V86_MASK)
@ -61,9 +61,9 @@ VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
OutContext->SegEs = TrapFrame->V86Es; OutContext->SegEs = TrapFrame->V86Es;
OutContext->SegDs = TrapFrame->V86Ds; OutContext->SegDs = TrapFrame->V86Ds;
} }
else if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK)) else if (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK))
{ {
/* This was user mode, copy segment registers */ /* This was kernel mode, copy segment registers */
OutContext->SegGs = TrapFrame->SegGs; OutContext->SegGs = TrapFrame->SegGs;
OutContext->SegFs = TrapFrame->SegFs; OutContext->SegFs = TrapFrame->SegFs;
OutContext->SegEs = TrapFrame->SegEs; OutContext->SegEs = TrapFrame->SegEs;