mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 01:42:30 +00:00
- 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:
parent
32b82baa21
commit
c0a3750d26
|
@ -68,7 +68,7 @@ LONG CALLBACK VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
|
|||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
BOOL
|
||||
DetectVMware(int *Version)
|
||||
{
|
||||
int magic, ver;
|
||||
|
@ -1010,7 +1010,7 @@ WinMain(HINSTANCE hInstance,
|
|||
{
|
||||
|
||||
PVOID ExceptionHandler;
|
||||
int Version;
|
||||
//int Version;
|
||||
WCHAR *lc;
|
||||
|
||||
hAppInstance = hInstance;
|
||||
|
@ -1024,9 +1024,9 @@ WinMain(HINSTANCE hInstance,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!DetectVMware(&Version))
|
||||
//if(!DetectVMware(&Version))
|
||||
{
|
||||
return 1;
|
||||
//return 1;
|
||||
}
|
||||
|
||||
/* unregister the handler */
|
||||
|
|
|
@ -67,6 +67,7 @@ NtAcceptConnectPort@24
|
|||
NtAccessCheck@32
|
||||
NtAccessCheckAndAuditAlarm@44
|
||||
NtAddAtom@12
|
||||
NtAddBootEntry@8
|
||||
NtAdjustGroupsToken@24
|
||||
NtAdjustPrivilegesToken@24
|
||||
NtAlertResumeThread@8
|
||||
|
|
|
@ -169,6 +169,7 @@ Author:
|
|||
#define KPCR_STALL_SCALE_FACTOR 0x4C
|
||||
#define KPCR_SET_MEMBER 0x48
|
||||
#define KPCR_NUMBER 0x51
|
||||
#define KPCR_VDM_ALERT 0x54
|
||||
#define KPCR_PRCB_DATA 0x120
|
||||
#define KPCR_CURRENT_THREAD 0x124
|
||||
#define KPCR_PRCB_NEXT_THREAD 0x128
|
||||
|
@ -473,9 +474,13 @@ Author:
|
|||
#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_OVERRIDE_MASK 0xF0000
|
||||
|
||||
//
|
||||
// Usermode callout frame definitions
|
||||
|
@ -491,6 +496,10 @@ Author:
|
|||
//
|
||||
#ifdef __ASM__
|
||||
#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_NO_CALLBACK_ACTIVE 0xC0000258
|
||||
#define STATUS_CALLBACK_POP_STACK 0xC0000423
|
||||
|
|
|
@ -1893,9 +1893,9 @@ RtlCreateUserThread(
|
|||
IN HANDLE ProcessHandle,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN BOOLEAN CreateSuspended,
|
||||
IN LONG StackZeroBits,
|
||||
IN ULONG StackReserve,
|
||||
IN ULONG StackCommit,
|
||||
IN ULONG StackZeroBits,
|
||||
IN SIZE_T StackReserve,
|
||||
IN SIZE_T StackCommit,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
IN PVOID Parameter,
|
||||
IN OUT PHANDLE ThreadHandle,
|
||||
|
|
|
@ -134,7 +134,7 @@ _RtlpExecuteHandlerForException@20:
|
|||
.globl _RtlpExecuteHandlerForUnwind@20
|
||||
_RtlpExecuteHandlerForUnwind@20:
|
||||
/* Copy the routine in EDX */
|
||||
mov edx, offset _RtlpExceptionProtector
|
||||
mov edx, offset _RtlpUnwindProtector
|
||||
.endfunc
|
||||
|
||||
.func RtlpExecuteHandler@20
|
||||
|
@ -243,7 +243,7 @@ _RtlpUnwindProtector:
|
|||
/* Put the exception record in ECX and check the Flags */
|
||||
mov ecx, [esp+4]
|
||||
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 */
|
||||
mov ecx, [esp+8]
|
||||
|
|
|
@ -10,30 +10,9 @@
|
|||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <rtl.h>
|
||||
|
||||
#define NDEBUG
|
||||
#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 **********************************************************/
|
||||
|
||||
/*
|
||||
|
@ -100,7 +79,6 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
sizeof(*RegistrationFrame));
|
||||
|
||||
/* Call the handler */
|
||||
DPRINT1("Calling handler: %p\n", RegistrationFrame->Handler);
|
||||
Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
|
||||
RegistrationFrame,
|
||||
Context,
|
||||
|
@ -192,7 +170,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
|
|||
IN PVOID ReturnValue)
|
||||
{
|
||||
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame;
|
||||
DISPATCHER_CONTEXT DispatcherContext;
|
||||
DISPATCHER_CONTEXT DispatcherContext;
|
||||
EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
|
||||
EXCEPTION_DISPOSITION Disposition;
|
||||
ULONG_PTR StackLow, StackHigh;
|
||||
|
@ -306,7 +284,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
|
|||
&DispatcherContext,
|
||||
RegistrationFrame->
|
||||
Handler);
|
||||
switch (Disposition)
|
||||
switch(Disposition)
|
||||
{
|
||||
/* Continue searching */
|
||||
case ExceptionContinueSearch:
|
||||
|
|
|
@ -16,6 +16,24 @@ extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
|
|||
#define PAGED_CODE_RTL()
|
||||
#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 */
|
||||
PVOID
|
||||
NTAPI
|
||||
|
@ -112,7 +130,7 @@ RtlpCaptureContext(OUT PCONTEXT ContextRecord);
|
|||
NTSTATUS
|
||||
NTAPI
|
||||
DebugService(IN ULONG Service,
|
||||
IN PCVOID Buffer,
|
||||
IN const void* Buffer,
|
||||
IN ULONG Length,
|
||||
IN PVOID Argument1,
|
||||
IN PVOID Argument2);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* PROJECT: ReactOS system libraries
|
||||
* PURPOSE: Rtl user thread functions
|
||||
* FILE: lib/rtl/thread.c
|
||||
* PROGRAMERS:
|
||||
* PROGRAMERS:
|
||||
* Alex Ionescu (alex@relsoft.net)
|
||||
* Eric Kohl
|
||||
* KJK::Hyperion
|
||||
|
@ -21,60 +21,54 @@
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlpCreateUserStack(HANDLE hProcess,
|
||||
ULONG StackReserve,
|
||||
ULONG StackCommit,
|
||||
ULONG StackZeroBits,
|
||||
PINITIAL_TEB InitialTeb)
|
||||
RtlpCreateUserStack(IN HANDLE hProcess,
|
||||
IN SIZE_T StackReserve OPTIONAL,
|
||||
IN SIZE_T StackCommit OPTIONAL,
|
||||
IN ULONG StackZeroBits OPTIONAL,
|
||||
OUT PINITIAL_TEB InitialTeb)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
|
||||
PIMAGE_NT_HEADERS Headers;
|
||||
ULONG_PTR Stack = 0;
|
||||
BOOLEAN UseGuard = FALSE;
|
||||
|
||||
DPRINT("RtlpCreateUserStack\n");
|
||||
|
||||
ULONG Dummy, GuardPageSize;
|
||||
|
||||
/* Get some memory information */
|
||||
Status = NtQuerySystemInformation(SystemBasicInformation,
|
||||
Status = ZwQuerySystemInformation(SystemBasicInformation,
|
||||
&SystemBasicInfo,
|
||||
sizeof(SYSTEM_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to query system info\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Use the Image Settings if we are dealing with the current Process */
|
||||
if (hProcess == NtCurrentProcess())
|
||||
{
|
||||
/* Get the Image Headers */
|
||||
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
|
||||
DPRINT("Headers: %p\n", Headers);
|
||||
|
||||
|
||||
/* If we didn't get the parameters, find them ourselves */
|
||||
StackReserve = (StackReserve) ?
|
||||
StackReserve : Headers->OptionalHeader.SizeOfStackReserve;
|
||||
StackCommit = (StackCommit) ?
|
||||
StackCommit : Headers->OptionalHeader.SizeOfStackCommit;
|
||||
if (!StackReserve) StackReserve = Headers->OptionalHeader.
|
||||
SizeOfStackReserve;
|
||||
if (!StackCommit) StackCommit = Headers->OptionalHeader.
|
||||
SizeOfStackCommit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the System Settings if needed */
|
||||
StackReserve = (StackReserve) ? StackReserve :
|
||||
SystemBasicInfo.AllocationGranularity;
|
||||
StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
|
||||
if (!StackReserve) StackReserve = SystemBasicInfo.AllocationGranularity;
|
||||
if (!StackCommit) StackCommit = SystemBasicInfo.PageSize;
|
||||
}
|
||||
|
||||
|
||||
/* Align everything to Page Size */
|
||||
StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
|
||||
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;
|
||||
#endif
|
||||
DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
|
||||
|
||||
|
||||
/* Reserve memory for the stack */
|
||||
Status = ZwAllocateVirtualMemory(hProcess,
|
||||
(PVOID*)&Stack,
|
||||
|
@ -82,33 +76,26 @@ RtlpCreateUserStack(HANDLE hProcess,
|
|||
&StackReserve,
|
||||
MEM_RESERVE,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to reserve stack\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Now set up some basic Initial TEB Parameters */
|
||||
InitialTeb->PreviousStackBase = NULL;
|
||||
InitialTeb->PreviousStackLimit = NULL;
|
||||
InitialTeb->AllocatedStackBase = (PVOID)Stack;
|
||||
InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
|
||||
|
||||
|
||||
/* Update the Stack Position */
|
||||
Stack += StackReserve - StackCommit;
|
||||
|
||||
|
||||
/* Check if we will need a guard page */
|
||||
if (StackReserve > StackCommit)
|
||||
{
|
||||
/* Remove a page to set as guard page */
|
||||
Stack -= SystemBasicInfo.PageSize;
|
||||
StackCommit += SystemBasicInfo.PageSize;
|
||||
UseGuard = TRUE;
|
||||
}
|
||||
|
||||
DPRINT("AllocatedBase: %p, StackBase: %p, Stack: %lx, StackCommit: %lx\n",
|
||||
InitialTeb->AllocatedStackBase, InitialTeb->StackBase, Stack,
|
||||
StackCommit);
|
||||
|
||||
|
||||
/* Allocate memory for the stack */
|
||||
Status = ZwAllocateVirtualMemory(hProcess,
|
||||
(PVOID*)&Stack,
|
||||
|
@ -116,75 +103,68 @@ RtlpCreateUserStack(HANDLE hProcess,
|
|||
&StackCommit,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to allocate stack\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Now set the current Stack Limit */
|
||||
InitialTeb->StackLimit = (PVOID)Stack;
|
||||
DPRINT("StackLimit: %lx\n", Stack);
|
||||
|
||||
|
||||
/* Create a guard page */
|
||||
if (UseGuard)
|
||||
{
|
||||
ULONG GuardPageSize = SystemBasicInfo.PageSize;
|
||||
ULONG Dummy;
|
||||
|
||||
/* Attempt maximum space possible */
|
||||
/* Attempt maximum space possible */
|
||||
GuardPageSize = SystemBasicInfo.PageSize;
|
||||
Status = ZwProtectVirtualMemory(hProcess,
|
||||
(PVOID*)&Stack,
|
||||
&GuardPageSize,
|
||||
PAGE_GUARD | PAGE_READWRITE,
|
||||
&Dummy);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to create guard page\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Update the Stack Limit keeping in mind the Guard Page */
|
||||
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit -
|
||||
GuardPageSize);
|
||||
DPRINT1("StackLimit: %lx\n", Stack);
|
||||
}
|
||||
|
||||
|
||||
/* We are done! */
|
||||
return Status;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlpFreeUserStack(HANDLE hProcess,
|
||||
PINITIAL_TEB InitialTeb)
|
||||
RtlpFreeUserStack(IN HANDLE Process,
|
||||
IN PINITIAL_TEB InitialTeb)
|
||||
{
|
||||
ULONG Dummy = 0;
|
||||
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Free the Stack */
|
||||
return ZwFreeVirtualMemory(hProcess,
|
||||
&InitialTeb->AllocatedStackBase,
|
||||
&Dummy,
|
||||
MEM_RELEASE);
|
||||
Status = ZwFreeVirtualMemory(Process,
|
||||
&InitialTeb->AllocatedStackBase,
|
||||
&Dummy,
|
||||
MEM_RELEASE);
|
||||
|
||||
/* Clear the initial TEB */
|
||||
RtlZeroMemory(InitialTeb, sizeof(INITIAL_TEB));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlCreateUserThread(HANDLE ProcessHandle,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
BOOLEAN CreateSuspended,
|
||||
LONG StackZeroBits,
|
||||
ULONG StackReserve,
|
||||
ULONG StackCommit,
|
||||
PTHREAD_START_ROUTINE StartAddress,
|
||||
PVOID Parameter,
|
||||
PHANDLE ThreadHandle,
|
||||
PCLIENT_ID ClientId)
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlCreateUserThread(IN HANDLE ProcessHandle,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
||||
IN BOOLEAN CreateSuspended,
|
||||
IN ULONG StackZeroBits OPTIONAL,
|
||||
IN SIZE_T StackReserve OPTIONAL,
|
||||
IN SIZE_T StackCommit OPTIONAL,
|
||||
IN PTHREAD_START_ROUTINE StartAddress,
|
||||
IN PVOID Parameter OPTIONAL,
|
||||
OUT PHANDLE ThreadHandle OPTIONAL,
|
||||
OUT PCLIENT_ID ClientId OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE Handle;
|
||||
|
@ -192,37 +172,27 @@ RtlCreateUserThread(HANDLE ProcessHandle,
|
|||
INITIAL_TEB InitialTeb;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
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 */
|
||||
Status = RtlpCreateUserStack(ProcessHandle,
|
||||
StackReserve,
|
||||
StackCommit,
|
||||
StackZeroBits,
|
||||
&InitialTeb);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to create User Stack\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Next, we'll set up the Initial Context */
|
||||
RtlInitializeContext(ProcessHandle,
|
||||
&Context,
|
||||
Parameter,
|
||||
StartAddress,
|
||||
InitialTeb.StackBase);
|
||||
|
||||
|
||||
/* We are now ready to create the Kernel Thread Object */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
SecurityDescriptor);
|
||||
Status = ZwCreateThread(&Handle,
|
||||
THREAD_ALL_ACCESS,
|
||||
|
@ -234,18 +204,16 @@ RtlCreateUserThread(HANDLE ProcessHandle,
|
|||
CreateSuspended);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failure to create Thread\n");
|
||||
|
||||
/* Free the stack */
|
||||
RtlpFreeUserStack(ProcessHandle, &InitialTeb);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Thread created: %p\n", Handle);
|
||||
/* Return thread data */
|
||||
if (ThreadHandle) *ThreadHandle = Handle;
|
||||
if (ClientId) *ClientId = ThreadCid;
|
||||
}
|
||||
|
||||
|
||||
/* Return success or the previous failure */
|
||||
return Status;
|
||||
}
|
||||
|
@ -262,10 +230,7 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
|
|||
IN PTHREAD_START_ROUTINE ThreadStartAddress,
|
||||
IN PINITIAL_TEB InitialTeb)
|
||||
{
|
||||
DPRINT("RtlInitializeContext: (hProcess: %p, ThreadContext: %p, Teb: %p\n",
|
||||
ProcessHandle, ThreadContext, InitialTeb);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Set the Initial Registers
|
||||
* This is based on NT's default values -- crazy apps might expect this...
|
||||
*/
|
||||
|
@ -276,27 +241,27 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
|
|||
ThreadContext->Edx = 3;
|
||||
ThreadContext->Esi = 4;
|
||||
ThreadContext->Edi = 5;
|
||||
|
||||
|
||||
/* Set the Selectors */
|
||||
ThreadContext->SegGs = 0;
|
||||
ThreadContext->SegFs = KGDT_R3_TEB | RPL_MASK;
|
||||
ThreadContext->SegEs = KGDT_R3_DATA | RPL_MASK;
|
||||
ThreadContext->SegDs = KGDT_R3_DATA | RPL_MASK;
|
||||
ThreadContext->SegCs = KGDT_R3_CODE | RPL_MASK;
|
||||
ThreadContext->SegSs = KGDT_R3_DATA | RPL_MASK;
|
||||
|
||||
ThreadContext->SegFs = KGDT_R3_TEB;
|
||||
ThreadContext->SegEs = KGDT_R3_DATA;
|
||||
ThreadContext->SegDs = KGDT_R3_DATA;
|
||||
ThreadContext->SegSs = KGDT_R3_DATA;
|
||||
ThreadContext->SegCs = KGDT_R3_CODE;
|
||||
|
||||
/* Enable Interrupts */
|
||||
ThreadContext->EFlags = 0x200; /*X86_EFLAGS_IF */
|
||||
|
||||
ThreadContext->EFlags = EFLAGS_INTERRUPT_MASK;
|
||||
|
||||
/* Settings passed */
|
||||
ThreadContext->Eip = (ULONG)ThreadStartAddress;
|
||||
ThreadContext->Esp = (ULONG)InitialTeb;
|
||||
|
||||
|
||||
/* Only the basic Context is initialized */
|
||||
ThreadContext->ContextFlags = CONTEXT_CONTROL |
|
||||
CONTEXT_INTEGER |
|
||||
ThreadContext->ContextFlags = CONTEXT_CONTROL |
|
||||
CONTEXT_INTEGER |
|
||||
CONTEXT_SEGMENTS;
|
||||
|
||||
|
||||
/* Set up ESP to the right value */
|
||||
ThreadContext->Esp -= sizeof(PVOID);
|
||||
ZwWriteVirtualMemory(ProcessHandle,
|
||||
|
@ -304,7 +269,7 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
|
|||
(PVOID)&ThreadStartParam,
|
||||
sizeof(PVOID),
|
||||
NULL);
|
||||
|
||||
|
||||
/* Push it down one more notch for RETEIP */
|
||||
ThreadContext->Esp -= sizeof(PVOID);
|
||||
}
|
||||
|
@ -312,13 +277,13 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
|
|||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlExitUserThread(NTSTATUS Status)
|
||||
{
|
||||
/* Call the Loader and tell him to notify the DLLs */
|
||||
LdrShutdownThread();
|
||||
|
||||
|
||||
/* Shut us down */
|
||||
NtCurrentTeb()->FreeStackOnTermination = TRUE;
|
||||
NtTerminateThread(NtCurrentThread(), Status);
|
||||
|
@ -327,8 +292,8 @@ RtlExitUserThread(NTSTATUS Status)
|
|||
/*
|
||||
@implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlFreeUserThreadStack(HANDLE ProcessHandle,
|
||||
HANDLE ThreadHandle)
|
||||
{
|
||||
|
@ -336,19 +301,15 @@ RtlFreeUserThreadStack(HANDLE ProcessHandle,
|
|||
THREAD_BASIC_INFORMATION ThreadBasicInfo;
|
||||
ULONG Dummy, Size = 0;
|
||||
PVOID StackLocation;
|
||||
|
||||
|
||||
/* Query the Basic Info */
|
||||
Status = NtQueryInformationThread(ThreadHandle,
|
||||
ThreadBasicInformation,
|
||||
&ThreadBasicInfo,
|
||||
sizeof(THREAD_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress)
|
||||
{
|
||||
DPRINT1("Could not query info, or TEB is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) return;
|
||||
|
||||
/* Get the deallocation stack */
|
||||
Status = NtReadVirtualMemory(ProcessHandle,
|
||||
&((PTEB)ThreadBasicInfo.TebBaseAddress)->
|
||||
|
@ -356,12 +317,8 @@ RtlFreeUserThreadStack(HANDLE ProcessHandle,
|
|||
&StackLocation,
|
||||
sizeof(PVOID),
|
||||
&Dummy);
|
||||
if (!NT_SUCCESS(Status) || !StackLocation)
|
||||
{
|
||||
DPRINT1("Could not read Deallocation Base\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status) || !StackLocation) return;
|
||||
|
||||
/* Free it */
|
||||
NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE);
|
||||
}
|
||||
|
|
|
@ -10,31 +10,32 @@
|
|||
//
|
||||
//
|
||||
// Ob:
|
||||
// - Fix bug related to Deferred Loading (don't requeue active work item).
|
||||
// - 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:
|
||||
// - Implement IoAssignDriveLetters using mount manager support.
|
||||
//
|
||||
// Ke:
|
||||
// - Figure out why the DPC stack doesn't really work.
|
||||
// - Fix SEH/Page Fault + Exceptions!? Weird exception bugs!
|
||||
// Hal:
|
||||
// - Use APC and DPC Interrupt Dispatchers.
|
||||
// - CMOS Initialization and CMOS Spinlock.
|
||||
//
|
||||
// Ke2:
|
||||
// - New optimized table-based tick-hashed timer implementation.
|
||||
// - 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:
|
||||
// - 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|
|
||||
// \________________________________________________________________________________________________________/
|
||||
//
|
||||
|
|
|
@ -381,6 +381,9 @@
|
|||
*/
|
||||
.global @ExInterlockedPopEntrySList@8
|
||||
.global @InterlockedPopEntrySList@4
|
||||
.global _ExpInterlockedPopEntrySListResume@0
|
||||
.global _ExpInterlockedPopEntrySListFault@0
|
||||
.global _ExpInterlockedPopEntrySListEnd@0
|
||||
@ExInterlockedPopEntrySList@8:
|
||||
@InterlockedPopEntrySList@4:
|
||||
|
||||
|
@ -392,10 +395,10 @@
|
|||
mov ebp, ecx
|
||||
|
||||
/* Get sequence number and link pointer */
|
||||
_ExpInterlockedPopEntrySListResume@0:
|
||||
mov edx, [ebp+4]
|
||||
mov eax, [ebp]
|
||||
|
||||
1:
|
||||
/* Check if the list is empty */
|
||||
or eax, eax
|
||||
jz 2f
|
||||
|
@ -404,9 +407,11 @@
|
|||
lea ecx, [edx-1]
|
||||
|
||||
/* Get next pointer and do the exchange */
|
||||
_ExpInterlockedPopEntrySListFault@0:
|
||||
mov ebx, [eax]
|
||||
_ExpInterlockedPopEntrySListEnd@0:
|
||||
LOCK cmpxchg8b [ebp]
|
||||
jnz 1b
|
||||
jnz _ExpInterlockedPopEntrySListResume@0
|
||||
|
||||
/* Restore registers and return */
|
||||
2:
|
||||
|
|
|
@ -65,6 +65,30 @@
|
|||
#define RELEASE_SPINLOCK(x)
|
||||
#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
|
||||
//
|
||||
|
@ -182,7 +206,6 @@ _KiUnexpectedInterrupt&Number:
|
|||
push offset V86DebugMsg
|
||||
call _DbgPrint
|
||||
add esp, 8
|
||||
int 3
|
||||
jmp $
|
||||
.endm
|
||||
|
||||
|
@ -511,7 +534,7 @@ _KiUnexpectedInterrupt&Number:
|
|||
|
||||
/* Check if this was kernel mode */
|
||||
1:
|
||||
cmp dword ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
|
||||
cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
|
||||
jz 1f
|
||||
|
||||
/* Set segments */
|
||||
|
@ -947,7 +970,7 @@ PendingUserApc:
|
|||
/* Assert the saved exception list */
|
||||
or edx, edx
|
||||
jnz 1f
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
1:
|
||||
#endif
|
||||
|
||||
|
@ -962,7 +985,7 @@ PendingUserApc:
|
|||
/* Assert the saved previous mode */
|
||||
cmp ecx, -1
|
||||
jnz 1f
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
1:
|
||||
#endif
|
||||
|
||||
|
@ -976,7 +999,7 @@ PendingUserApc:
|
|||
mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
|
||||
cmp ecx, -1
|
||||
jz 1f
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
1:
|
||||
#endif
|
||||
.endif
|
||||
|
@ -1111,7 +1134,7 @@ FastExit:
|
|||
add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
|
||||
|
||||
6:
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
jmp 5b
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,12 +41,8 @@
|
|||
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 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 WE_DO_NOT_SPEAK_ABOUT_THE_V86_HACK 1
|
||||
|
||||
#ifndef __ASM__
|
||||
|
||||
extern ULONG Ke386CacheAlignment;
|
||||
|
|
|
@ -130,6 +130,8 @@ extern PVOID KeUserApcDispatcher;
|
|||
extern PVOID KeUserCallbackDispatcher;
|
||||
extern PVOID KeUserExceptionDispatcher;
|
||||
extern PVOID KeRaiseUserExceptionDispatcher;
|
||||
extern UCHAR KiDebugRegisterTrapOffsets[9];
|
||||
extern UCHAR KiDebugRegisterContextOffsets[9];
|
||||
|
||||
/* MACROS *************************************************************************/
|
||||
|
||||
|
|
|
@ -6,6 +6,86 @@
|
|||
* 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
|
||||
//
|
||||
|
|
|
@ -686,17 +686,10 @@ MmPageFault(
|
|||
NTSTATUS
|
||||
NTAPI
|
||||
MmAccessFault(
|
||||
KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmNotPresentFault(
|
||||
KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl
|
||||
IN BOOLEAN StoreInstruction,
|
||||
IN PVOID Address,
|
||||
IN KPROCESSOR_MODE Mode,
|
||||
IN PVOID TrapInformation
|
||||
);
|
||||
|
||||
/* anonmem.c *****************************************************************/
|
||||
|
|
|
@ -188,9 +188,10 @@ ObQueryDeviceMapInformation(
|
|||
// Object Lifetime Functions
|
||||
//
|
||||
VOID
|
||||
FASTCALL
|
||||
NTAPI
|
||||
ObpDeleteObject(
|
||||
IN PVOID Object
|
||||
IN PVOID Object,
|
||||
IN BOOLEAN CalledFromWorkerThread
|
||||
);
|
||||
|
||||
LONG
|
||||
|
|
|
@ -29,17 +29,17 @@ UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS];
|
|||
/* The TSS to use for NMI Fault Traps (INT 0x2) */
|
||||
UCHAR KiNMITSS[KTSS_IO_MAPS];
|
||||
|
||||
/* The Boot GDT (FIXME: should have more entries */
|
||||
KGDTENTRY KiBootGdt[12] =
|
||||
/* The Boot GDT */
|
||||
KGDTENTRY KiBootGdt[256] =
|
||||
{
|
||||
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_NULL */
|
||||
{0xffff, 0x0000, {{0x00, 0x9a, 0xcf, 0x00}}}, /* KGDT_R0_CODE */
|
||||
{0xffff, 0x0000, {{0x00, 0x92, 0xcf, 0x00}}}, /* KGDT_R0_DATA */
|
||||
{0xffff, 0x0000, {{0x00, 0xfa, 0xcf, 0x00}}}, /* KGDT_R3_CODE */
|
||||
{0xffff, 0x0000, {{0x00, 0xf2, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/
|
||||
{0xffff, 0x0000, {{0x00, 0x9b, 0xcf, 0x00}}}, /* KGDT_R0_CODE */
|
||||
{0xffff, 0x0000, {{0x00, 0x93, 0xcf, 0x00}}}, /* KGDT_R0_DATA */
|
||||
{0xffff, 0x0000, {{0x00, 0xfb, 0xcf, 0x00}}}, /* KGDT_R3_CODE */
|
||||
{0xffff, 0x0000, {{0x00, 0xf3, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/
|
||||
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_TSS */
|
||||
{0x0fff, 0x0000, {{0x00, 0x92, 0x00, 0xff}}}, /* KGDT_R0_PCR */
|
||||
{0x0fff, 0x0000, {{0x00, 0xf2, 0x00, 0x00}}}, /* KGDT_R3_TEB */
|
||||
{0x0fff, 0x0000, {{0x00, 0x93, 0xc0, 0xff}}}, /* KGDT_R0_PCR */
|
||||
{0x0fff, 0x0000, {{0x00, 0xf3, 0x40, 0x00}}}, /* KGDT_R3_TEB */
|
||||
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_UNUSED */
|
||||
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_LDT */
|
||||
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_DF_TSS */
|
||||
|
|
|
@ -14,6 +14,36 @@
|
|||
#define NDEBUG
|
||||
#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 *****************************************************************/
|
||||
|
||||
_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
|
||||
NTAPI
|
||||
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
|
||||
|
@ -192,6 +317,8 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
|||
ULONG i;
|
||||
BOOLEAN V86Switch = FALSE;
|
||||
KIRQL OldIrql = APC_LEVEL;
|
||||
ULONG DrMask = 0;
|
||||
PVOID SafeDr;
|
||||
|
||||
/* Do this at APC_LEVEL */
|
||||
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||
|
@ -207,8 +334,8 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
|||
V86Switch = TRUE;
|
||||
}
|
||||
|
||||
/* Copy EFLAGS. FIXME: Needs to be sanitized */
|
||||
TrapFrame->EFlags = Context->EFlags;
|
||||
/* Copy EFLAGS and sanitize them*/
|
||||
TrapFrame->EFlags = Ke386SanitizeFlags(Context->EFlags, PreviousMode);
|
||||
|
||||
/* Copy EBP and EIP */
|
||||
TrapFrame->Ebp = Context->Ebp;
|
||||
|
@ -222,14 +349,14 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* We weren't in V86, so sanitize the CS (FIXME!) */
|
||||
TrapFrame->SegCs = Context->SegCs;
|
||||
/* We weren't in V86, so sanitize the CS */
|
||||
TrapFrame->SegCs = Ke386SanitizeSeg(Context->SegCs, PreviousMode);
|
||||
|
||||
/* Don't let it under 8, that's invalid */
|
||||
if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
|
||||
{
|
||||
/* 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 */
|
||||
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
|
||||
{
|
||||
/* Copy the V86 Segments directlry */
|
||||
/* Copy the V86 Segments directly */
|
||||
TrapFrame->V86Ds = Context->SegDs;
|
||||
TrapFrame->V86Es = Context->SegEs;
|
||||
TrapFrame->V86Fs = Context->SegFs;
|
||||
|
@ -272,12 +399,12 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
|||
/* For kernel mode, write the standard values */
|
||||
TrapFrame->SegDs = 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For user mode, return the values directlry */
|
||||
/* For user mode, return the values directly */
|
||||
TrapFrame->SegDs = Context->SegDs;
|
||||
TrapFrame->SegEs = Context->SegEs;
|
||||
TrapFrame->SegFs = Context->SegFs;
|
||||
|
@ -320,7 +447,13 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
|||
/* Mask out any invalid flags */
|
||||
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
|
||||
{
|
||||
/* Just dump the Fn state in */
|
||||
RtlCopyMemory(&FxSaveArea->U.FnArea,
|
||||
&Context->FloatSave,
|
||||
sizeof(FNSAVE_FORMAT));
|
||||
/* Copy the structure */
|
||||
FxSaveArea->U.FnArea.ControlWord = Context->FloatSave.
|
||||
ControlWord;
|
||||
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 */
|
||||
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
|
||||
{
|
||||
|
@ -394,23 +551,38 @@ KeContextToTrapFrame(IN PCONTEXT Context,
|
|||
/* Handle the Debug Registers */
|
||||
if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
||||
{
|
||||
/* FIXME: All these should be sanitized */
|
||||
TrapFrame->Dr0 = Context->Dr0;
|
||||
TrapFrame->Dr1 = Context->Dr1;
|
||||
TrapFrame->Dr2 = Context->Dr2;
|
||||
TrapFrame->Dr3 = Context->Dr3;
|
||||
TrapFrame->Dr6 = Context->Dr6;
|
||||
TrapFrame->Dr7 = Context->Dr7;
|
||||
/* Loop DR registers */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
/* Sanitize the context DR Address */
|
||||
SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Set the Debug Flag */
|
||||
KeGetCurrentThread()->DispatcherHeader.DebugActive =
|
||||
(Context->Dr7 & DR7_ACTIVE) ? TRUE: FALSE;
|
||||
/* FIXME: Save the mask */
|
||||
//KeGetCurrentThread()->DispatcherHeader.DebugActive = DrMask;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if thread has IOPL and force it enabled if so */
|
||||
if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
|
||||
|
||||
/* Restore IRQL */
|
||||
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
@ -429,6 +601,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
|||
} FloatSaveBuffer;
|
||||
FLOATING_SAVE_AREA *FloatSaveArea;
|
||||
KIRQL OldIrql = APC_LEVEL;
|
||||
ULONG i;
|
||||
|
||||
/* Do this at APC_LEVEL */
|
||||
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||
|
@ -550,10 +723,23 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
|||
KiFlushNPXState(NULL);
|
||||
}
|
||||
|
||||
/* Copy into the Context */
|
||||
RtlCopyMemory(&Context->FloatSave,
|
||||
FloatSaveArea,
|
||||
sizeof(FNSAVE_FORMAT));
|
||||
/* Copy structure */
|
||||
Context->FloatSave.ControlWord = FloatSaveArea->ControlWord;
|
||||
Context->FloatSave.StatusWord = FloatSaveArea->StatusWord;
|
||||
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
|
||||
{
|
||||
|
@ -566,24 +752,26 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
|||
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
|
||||
CONTEXT_DEBUG_REGISTERS)
|
||||
{
|
||||
/* Copy the debug registers */
|
||||
Context->Dr0 = TrapFrame->Dr0;
|
||||
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))
|
||||
/* Make sure DR7 is valid */
|
||||
if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK)
|
||||
{
|
||||
/* Copy it over */
|
||||
Context->Dr7 = TrapFrame->Dr7;
|
||||
/* Copy the debug registers */
|
||||
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
|
||||
{
|
||||
/* Clear it */
|
||||
/* Otherwise clear DR registers */
|
||||
Context->Dr0 =
|
||||
Context->Dr1 =
|
||||
Context->Dr3 =
|
||||
Context->Dr6 =
|
||||
Context->Dr7 = 0;
|
||||
}
|
||||
}
|
||||
|
@ -757,13 +945,13 @@ DispatchToUser:
|
|||
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
|
||||
|
||||
/* Force correct segments */
|
||||
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
|
||||
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
|
||||
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
|
||||
TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
|
||||
TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, PreviousMode);
|
||||
TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
|
||||
TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
|
||||
TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, PreviousMode);
|
||||
TrapFrame->SegGs = 0;
|
||||
|
||||
/* Set EIP to the User-mode Dispathcer */
|
||||
/* Set EIP to the User-mode Dispatcher */
|
||||
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
|
||||
_SEH_LEAVE;
|
||||
}
|
||||
|
|
|
@ -87,13 +87,17 @@ _KiUnexpectedEntrySize:
|
|||
_UnexpectedMsg:
|
||||
.asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
|
||||
|
||||
_UnhandledMsg:
|
||||
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
|
||||
|
||||
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
|
||||
.text
|
||||
|
||||
_KiGetTickCount:
|
||||
_KiCallbackReturn:
|
||||
_KiRaiseAssertion:
|
||||
int 3
|
||||
/* FIXME: TODO */
|
||||
UNHANDLED_PATH
|
||||
|
||||
.func KiSystemService
|
||||
Dr_kss: DR_TRAP_FIXUP
|
||||
|
@ -144,6 +148,7 @@ SharedCode:
|
|||
|
||||
/* Check if we should flush the User Batch */
|
||||
xor ebx, ebx
|
||||
ReadBatch:
|
||||
or ebx, [ecx+TEB_GDI_BATCH_COUNT]
|
||||
jz NotWin32K
|
||||
|
||||
|
@ -432,8 +437,8 @@ V86_Exit:
|
|||
iret
|
||||
|
||||
AbiosExit:
|
||||
/* Not yet supported */
|
||||
int 3
|
||||
/* FIXME: TODO */
|
||||
UNHANDLED_PATH
|
||||
|
||||
.func KiDebugService
|
||||
Dr_kids: DR_TRAP_FIXUP
|
||||
|
@ -672,6 +677,13 @@ _DispatchTwoParam:
|
|||
|
||||
/* HARDWARE TRAP HANDLERS ****************************************************/
|
||||
|
||||
.func KiFixupFrame
|
||||
_KiFixupFrame:
|
||||
|
||||
/* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.func KiTrap0
|
||||
Dr_kit0: DR_TRAP_FIXUP
|
||||
V86_kit0: V86_TRAP_FIXUP
|
||||
|
@ -710,7 +722,8 @@ VdmCheck:
|
|||
|
||||
/* We don't support this yet! */
|
||||
V86Int0:
|
||||
int 3
|
||||
/* FIXME: TODO */
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.func KiTrap1
|
||||
|
@ -754,7 +767,7 @@ V86Int1:
|
|||
jz EnableInterrupts
|
||||
|
||||
/* We don't support VDM! */
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.globl _KiTrap2
|
||||
|
@ -813,7 +826,7 @@ V86Int3:
|
|||
jz EnableInterrupts3
|
||||
|
||||
/* We don't support VDM! */
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.func KiTrap4
|
||||
|
@ -855,7 +868,7 @@ VdmCheck4:
|
|||
|
||||
/* We don't support this yet! */
|
||||
V86Int4:
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.func KiTrap5
|
||||
|
@ -901,7 +914,7 @@ VdmCheck5:
|
|||
|
||||
/* We don't support this yet! */
|
||||
V86Int5:
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.func KiTrap6
|
||||
|
@ -917,8 +930,7 @@ _KiTrap6:
|
|||
V86_TRAP_PROLOG kit6
|
||||
|
||||
/* Not yet supported (Invalid OPCODE from V86) */
|
||||
int 3
|
||||
jmp $
|
||||
UNHANDLED_PATH
|
||||
|
||||
NotV86UD:
|
||||
/* Push error code */
|
||||
|
@ -993,8 +1005,7 @@ LockCrash:
|
|||
IsVdmOpcode:
|
||||
|
||||
/* Unhandled yet */
|
||||
int 3
|
||||
jmp $
|
||||
UNHANDLED_PATH
|
||||
|
||||
/* Return to caller */
|
||||
jmp _Kei386EoiHelper@0
|
||||
|
@ -1302,8 +1313,7 @@ V86Npx:
|
|||
jz HandleUserNpx
|
||||
|
||||
/* V86 NPX not handled */
|
||||
int 3
|
||||
jmp $
|
||||
UNHANDLED_PATH
|
||||
|
||||
EmulationEnabled:
|
||||
/* Did this come from kernel-mode? */
|
||||
|
@ -1456,7 +1466,7 @@ RaiseIrql:
|
|||
jnz NoReflect
|
||||
|
||||
/* FIXME: TODO */
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
|
||||
NoReflect:
|
||||
|
||||
|
@ -1485,9 +1495,21 @@ NotV86:
|
|||
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
|
||||
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 */
|
||||
KmodeGpf:
|
||||
mov eax, [ebp+KTRAP_FRAME_EIP]
|
||||
mov eax, [eax]
|
||||
mov edx, [ebp+KTRAP_FRAME_EBP]
|
||||
|
@ -1573,8 +1595,7 @@ TrapCopy:
|
|||
MsrCheck:
|
||||
|
||||
/* FIXME: Handle RDMSR/WRMSR */
|
||||
int 3
|
||||
jmp $
|
||||
UNHANDLED_PATH
|
||||
|
||||
NotIretGpf:
|
||||
|
||||
|
@ -1606,7 +1627,6 @@ SegPopGpf:
|
|||
lea eax, [ebp+KTRAP_FRAME_ESP]
|
||||
cmp edx, eax
|
||||
jz HandleSegPop
|
||||
int 3
|
||||
|
||||
/* Handle segment POP fault by setting it to 0 */
|
||||
HandleSegPop:
|
||||
|
@ -1620,26 +1640,239 @@ ExitGpfTrap:
|
|||
|
||||
UserModeGpf:
|
||||
|
||||
/* FIXME: Unhandled */
|
||||
int 3
|
||||
jmp $
|
||||
/* If the previous mode was kernel, raise a fatal exception */
|
||||
mov eax, 13
|
||||
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
|
||||
|
||||
.func KiTrap14
|
||||
Dr_kit14: DR_TRAP_FIXUP
|
||||
V86_kit14: V86_TRAP_FIXUP
|
||||
_KiTrap14:
|
||||
|
||||
/* Enter trap */
|
||||
TRAP_PROLOG kit14
|
||||
|
||||
/* Call the C exception handler */
|
||||
push 14
|
||||
push ebp
|
||||
call _KiPageFaultHandler
|
||||
add esp, 8
|
||||
/* Check if we have a VDM alert */
|
||||
cmp dword ptr fs:[KPCR_VDM_ALERT], 0
|
||||
jnz VdmAlertGpf
|
||||
|
||||
/* 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
|
||||
|
||||
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
|
||||
|
||||
.func KiTrap0F
|
||||
|
@ -1752,8 +1985,7 @@ _Ki16BitStackException:
|
|||
add esp, [eax+KTHREAD_INITIAL_STACK]
|
||||
|
||||
/* Switch to good stack segment */
|
||||
/* TODO */
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
|
||||
|
@ -1867,7 +2099,7 @@ CheckQuantum:
|
|||
jz Return
|
||||
|
||||
/* FIXME: Schedule new thread */
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
|
||||
Return:
|
||||
/* All done */
|
||||
|
@ -1904,7 +2136,7 @@ _KiInterruptTemplateDispatch:
|
|||
_KiChainedDispatch2ndLvl@0:
|
||||
|
||||
/* Not yet supported */
|
||||
int 3
|
||||
UNHANDLED_PATH
|
||||
.endfunc
|
||||
|
||||
.func KiChainedDispatch@0
|
||||
|
|
|
@ -71,7 +71,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
|
|||
_SEH_DECLARE_LOCALS(KiCopyInfo);
|
||||
|
||||
/* 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 */
|
||||
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
|
@ -102,22 +102,19 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
|
|||
TrapFrame->HardwareEsp = Stack;
|
||||
|
||||
/* Setup Ring 3 state */
|
||||
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
|
||||
TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
|
||||
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
|
||||
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
|
||||
TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, UserMode);
|
||||
TrapFrame->HardwareSegSs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
|
||||
TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
|
||||
TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
|
||||
TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, UserMode);
|
||||
TrapFrame->SegGs = 0;
|
||||
TrapFrame->ErrCode = 0;
|
||||
|
||||
/* Sanitize EFLAGS */
|
||||
TrapFrame->EFlags = Context.EFlags & EFLAGS_USER_SANITIZE;
|
||||
TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
|
||||
TrapFrame->EFlags = Ke386SanitizeFlags(Context.EFlags, UserMode);
|
||||
|
||||
/* Check if user-mode has IO privileges */
|
||||
if (KeGetCurrentThread()->Iopl)
|
||||
{
|
||||
/* Enable them*/
|
||||
TrapFrame->EFlags |= (0x3000);
|
||||
}
|
||||
/* Check if thread has IOPL and force it enabled if so */
|
||||
if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
|
||||
|
||||
/* Setup the stack */
|
||||
*(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -433,7 +433,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
|
|||
|
||||
if (!MmIsPagePresent(NULL, Address))
|
||||
{
|
||||
Status = MmNotPresentFault(Mode, (ULONG_PTR)Address, TRUE);
|
||||
Status = MmAccessFault(FALSE, Address, Mode, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
|
@ -457,7 +457,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
|
|||
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
|
||||
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
|
||||
{
|
||||
Status = MmAccessFault(Mode, (ULONG_PTR)Address, TRUE);
|
||||
Status = MmAccessFault(TRUE, Address, Mode, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
|
|
|
@ -75,9 +75,9 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress)
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmAccessFault(KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl)
|
||||
MmpAccessFault(KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl)
|
||||
{
|
||||
PMADDRESS_SPACE AddressSpace;
|
||||
MEMORY_AREA* MemoryArea;
|
||||
|
@ -109,7 +109,7 @@ MmAccessFault(KPROCESSOR_MODE Mode,
|
|||
{
|
||||
DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
|
||||
DbgPrint("%s:%d\n",__FILE__,__LINE__);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
return(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
|
@ -131,13 +131,13 @@ MmAccessFault(KPROCESSOR_MODE Mode,
|
|||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
return (STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
switch (MemoryArea->Type)
|
||||
{
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_PAGED_POOL:
|
||||
|
@ -152,15 +152,15 @@ MmAccessFault(KPROCESSOR_MODE Mode,
|
|||
break;
|
||||
|
||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -174,32 +174,6 @@ MmAccessFault(KPROCESSOR_MODE Mode,
|
|||
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
|
||||
NTAPI
|
||||
MmNotPresentFault(KPROCESSOR_MODE Mode,
|
||||
|
@ -227,7 +201,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
DPRINT("No current process\n");
|
||||
if (Address < (ULONG_PTR)MmSystemRangeStart)
|
||||
{
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
return(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +216,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
if (Mode != KernelMode)
|
||||
{
|
||||
CPRINT("Address: %x\n", Address);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
return(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
|
@ -268,7 +242,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
{
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
}
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
return (STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
switch (MemoryArea->Type)
|
||||
|
@ -280,7 +254,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
}
|
||||
|
||||
case MEMORY_AREA_SYSTEM:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
break;
|
||||
|
||||
case MEMORY_AREA_SECTION_VIEW:
|
||||
|
@ -309,7 +283,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
Status = STATUS_ACCESS_VIOLATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -323,6 +297,67 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -257,9 +257,7 @@
|
|||
<directory name="mm">
|
||||
<if property="ARCH" value="i386">
|
||||
<directory name="i386">
|
||||
<file>memsafe.s</file>
|
||||
<file>page.c</file>
|
||||
<file>pfault.c</file>
|
||||
</directory>
|
||||
</if>
|
||||
<file>anonmem.c</file>
|
||||
|
|
|
@ -134,8 +134,9 @@ ObpDeallocateObject(IN PVOID Object)
|
|||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ObpDeleteObject(IN PVOID Object)
|
||||
NTAPI
|
||||
ObpDeleteObject(IN PVOID Object,
|
||||
IN BOOLEAN CalledFromWorkerThread)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
POBJECT_TYPE ObjectType;
|
||||
|
@ -203,12 +204,15 @@ VOID
|
|||
NTAPI
|
||||
ObpReapObject(IN PVOID Parameter)
|
||||
{
|
||||
POBJECT_HEADER ReapObject;
|
||||
POBJECT_HEADER ReapObject = (PVOID)1;
|
||||
PVOID NextObject;
|
||||
|
||||
/* Start reaping */
|
||||
while ((ReapObject = InterlockedExchangePointer(&ObpReaperList, NULL)))
|
||||
do
|
||||
{
|
||||
/* Get the reap object */
|
||||
ReapObject = InterlockedExchangePointer(&ObpReaperList, ReapObject);
|
||||
|
||||
/* Start deletion loop */
|
||||
do
|
||||
{
|
||||
|
@ -216,12 +220,13 @@ ObpReapObject(IN PVOID Parameter)
|
|||
NextObject = ReapObject->NextToFree;
|
||||
|
||||
/* Delete the object */
|
||||
ObpDeleteObject(&ReapObject->Body);
|
||||
ObpDeleteObject(&ReapObject->Body, TRUE);
|
||||
|
||||
/* Move to the next one */
|
||||
ReapObject = NextObject;
|
||||
} while (NextObject);
|
||||
}
|
||||
} while ((NextObject) && (NextObject != (PVOID)1));
|
||||
} while ((ObpReaperList != (PVOID)1) ||
|
||||
(InterlockedCompareExchange((PLONG)&ObpReaperList, 0, 1) != 1));
|
||||
}
|
||||
|
||||
/*++
|
||||
|
|
|
@ -50,21 +50,27 @@ ObReferenceObjectSafe(IN PVOID Object)
|
|||
|
||||
VOID
|
||||
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
|
||||
{
|
||||
Header->NextToFree = ObpReaperList;
|
||||
} while (InterlockedCompareExchangePointer(&ObpReaperList,
|
||||
Header,
|
||||
Header->NextToFree) !=
|
||||
Header->NextToFree);
|
||||
/* Get the current entry */
|
||||
Entry = ObpReaperList;
|
||||
|
||||
/* Queue the work item */
|
||||
ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue);
|
||||
/* Link our object to the list */
|
||||
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
|
||||
|
@ -91,11 +97,7 @@ ObDereferenceObjectEx(IN PVOID Object,
|
|||
|
||||
/* Check whether the object can now be deleted. */
|
||||
NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count);
|
||||
if (!Count)
|
||||
{
|
||||
/* Add us to the deferred deletion list */
|
||||
ObpDeferObjectDeletion(Object);
|
||||
}
|
||||
if (!Count) ObpDeferObjectDeletion(Header);
|
||||
|
||||
/* Return the current count */
|
||||
return NewCount;
|
||||
|
@ -308,12 +310,12 @@ ObfDereferenceObject(IN PVOID Object)
|
|||
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
|
||||
{
|
||||
/* Remove the object */
|
||||
ObpDeleteObject(Object);
|
||||
ObpDeleteObject(Object, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add us to the deferred deletion list */
|
||||
ObpDeferObjectDeletion(Object);
|
||||
ObpDeferObjectDeletion(Header);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,11 +327,13 @@ VOID
|
|||
NTAPI
|
||||
ObDereferenceObjectDeferDelete(IN PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
|
||||
/* 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 */
|
||||
ObpDeferObjectDeletion(Object);
|
||||
ObpDeferObjectDeletion(Header);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
|
|||
|
||||
/* Make sure that we're at APC_LEVEL and that this is a valid frame */
|
||||
ASSERT_IRQL(APC_LEVEL);
|
||||
ASSERT(TrapFrame->DbgArgMark = 0xBADB0D00);
|
||||
ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
|
||||
|
||||
/* Check if this is a V86 frame */
|
||||
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
|
||||
|
@ -61,9 +61,9 @@ VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
|
|||
OutContext->SegEs = TrapFrame->V86Es;
|
||||
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->SegFs = TrapFrame->SegFs;
|
||||
OutContext->SegEs = TrapFrame->SegEs;
|
||||
|
|
Loading…
Reference in a new issue