mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +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;
|
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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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|
|
||||||
|
// \________________________________________________________________________________________________________/
|
||||||
|
//
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 *************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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 *****************************************************************/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
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++)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue