Author: ion Date: Fri Dec 29 21:49:00 2006 New Revision: 25238
URL: http://svn.reactos.org/svn/reactos?rev=25238&view=rev Log: - 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.
Removed: trunk/reactos/ntoskrnl/mm/i386/memsafe.s trunk/reactos/ntoskrnl/mm/i386/pfault.c Modified: trunk/reactos/base/setup/vmwinst/vmwinst.c trunk/reactos/dll/ntdll/def/ntdll.def trunk/reactos/include/ndk/asm.h trunk/reactos/include/ndk/rtlfuncs.h trunk/reactos/lib/rtl/i386/except_asm.s trunk/reactos/lib/rtl/i386/exception.c trunk/reactos/lib/rtl/rtlp.h trunk/reactos/lib/rtl/thread.c trunk/reactos/ntoskrnl/KrnlFun.c trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S trunk/reactos/ntoskrnl/include/internal/i386/ke.h trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/include/internal/ke_x.h trunk/reactos/ntoskrnl/include/internal/mm.h trunk/reactos/ntoskrnl/include/internal/ob.h trunk/reactos/ntoskrnl/ke/i386/cpu.c trunk/reactos/ntoskrnl/ke/i386/exp.c trunk/reactos/ntoskrnl/ke/i386/trap.s trunk/reactos/ntoskrnl/ke/i386/usercall.c trunk/reactos/ntoskrnl/mm/mdl.c trunk/reactos/ntoskrnl/mm/mm.c trunk/reactos/ntoskrnl/ntoskrnl.rbuild trunk/reactos/ntoskrnl/ob/oblife.c trunk/reactos/ntoskrnl/ob/obref.c trunk/reactos/ntoskrnl/vdm/vdmexec.c
Modified: trunk/reactos/base/setup/vmwinst/vmwinst.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/vmwinst/vmwinst.... ============================================================================== --- trunk/reactos/base/setup/vmwinst/vmwinst.c (original) +++ trunk/reactos/base/setup/vmwinst/vmwinst.c Fri Dec 29 21:49:00 2006 @@ -68,7 +68,7 @@ return EXCEPTION_CONTINUE_EXECUTION; }
-static BOOL +BOOL DetectVMware(int *Version) { int magic, ver; @@ -1010,7 +1010,7 @@ {
PVOID ExceptionHandler; - int Version; + //int Version; WCHAR *lc;
hAppInstance = hInstance; @@ -1024,9 +1024,9 @@ return 1; }
- if(!DetectVMware(&Version)) - { - return 1; + //if(!DetectVMware(&Version)) + { + //return 1; }
/* unregister the handler */
Modified: trunk/reactos/dll/ntdll/def/ntdll.def URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/def/ntdll.def?rev... ============================================================================== --- trunk/reactos/dll/ntdll/def/ntdll.def (original) +++ trunk/reactos/dll/ntdll/def/ntdll.def Fri Dec 29 21:49:00 2006 @@ -67,6 +67,7 @@ NtAccessCheck@32 NtAccessCheckAndAuditAlarm@44 NtAddAtom@12 +NtAddBootEntry@8 NtAdjustGroupsToken@24 NtAdjustPrivilegesToken@24 NtAlertResumeThread@8
Modified: trunk/reactos/include/ndk/asm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/asm.h?rev=25238... ============================================================================== --- trunk/reactos/include/ndk/asm.h (original) +++ trunk/reactos/include/ndk/asm.h Fri Dec 29 21:49:00 2006 @@ -169,6 +169,7 @@ #define KPCR_STALL_SCALE_FACTOR 0x4C #define KPCR_SET_MEMBER 0x48 #define KPCR_NUMBER 0x51 +#define KPCR_VDM_ALERT 0x54 #define KPCR_PRCB_DATA 0x120 #define KPCR_CURRENT_THREAD 0x124 #define KPCR_PRCB_NEXT_THREAD 0x128 @@ -473,9 +474,13 @@ #endif
// -// DR7 Values -// +// DR6 and 7 Masks +// +#define DR6_LEGAL 0xE00F +#define DR7_LEGAL 0xFFFF0155 +#define DR7_ACTIVE 0x55 #define DR7_RESERVED_MASK 0xDC00 +#define DR7_OVERRIDE_MASK 0xF0000
// // Usermode callout frame definitions @@ -491,6 +496,10 @@ // #ifdef __ASM__ #define STATUS_ACCESS_VIOLATION 0xC0000005 +#define STATUS_IN_PAGE_ERROR 0xC0000006 +#define STATUS_GUARD_PAGE_VIOLATION 0x80000001 +#define STATUS_STACK_OVERFLOW 0xC00000FD +#define KI_EXCEPTION_ACCESS_VIOLATION 0x10000004 #define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C #define STATUS_NO_CALLBACK_ACTIVE 0xC0000258 #define STATUS_CALLBACK_POP_STACK 0xC0000423
Modified: trunk/reactos/include/ndk/rtlfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtlfuncs.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/rtlfuncs.h (original) +++ trunk/reactos/include/ndk/rtlfuncs.h Fri Dec 29 21:49:00 2006 @@ -1893,9 +1893,9 @@ IN HANDLE ProcessHandle, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN CreateSuspended, - IN LONG StackZeroBits, - IN ULONG StackReserve, - IN ULONG StackCommit, + IN ULONG StackZeroBits, + IN SIZE_T StackReserve, + IN SIZE_T StackCommit, IN PTHREAD_START_ROUTINE StartAddress, IN PVOID Parameter, IN OUT PHANDLE ThreadHandle,
Modified: trunk/reactos/lib/rtl/i386/except_asm.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/i386/except_asm.s?r... ============================================================================== --- trunk/reactos/lib/rtl/i386/except_asm.s (original) +++ trunk/reactos/lib/rtl/i386/except_asm.s Fri Dec 29 21:49:00 2006 @@ -134,7 +134,7 @@ .globl _RtlpExecuteHandlerForUnwind@20 _RtlpExecuteHandlerForUnwind@20: /* Copy the routine in EDX */ - mov edx, offset _RtlpExceptionProtector + mov edx, offset _RtlpUnwindProtector .endfunc
.func RtlpExecuteHandler@20 @@ -243,7 +243,7 @@ /* Put the exception record in ECX and check the Flags */ mov ecx, [esp+4] test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWINDING + EXCEPTION_EXIT_UNWIND - jnz .return + jz .return
/* Save the frame in ECX and Context in EDX */ mov ecx, [esp+8]
Modified: trunk/reactos/lib/rtl/i386/exception.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/i386/exception.c?re... ============================================================================== --- trunk/reactos/lib/rtl/i386/exception.c (original) +++ trunk/reactos/lib/rtl/i386/exception.c Fri Dec 29 21:49:00 2006 @@ -10,29 +10,8 @@ /* INCLUDES *****************************************************************/
#include <rtl.h> - #define NDEBUG #include <debug.h> - -/* PRIVATE FUNCTIONS *********************************************************/ - -VOID -NTAPI -RtlpGetStackLimits(PULONG_PTR StackBase, - PULONG_PTR StackLimit); - -PEXCEPTION_REGISTRATION_RECORD -NTAPI -RtlpGetExceptionList(VOID); - -VOID -NTAPI -RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList); - -typedef struct _DISPATCHER_CONTEXT -{ - PEXCEPTION_REGISTRATION_RECORD RegistrationPointer; -} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
/* PUBLIC FUNCTIONS **********************************************************/
@@ -100,7 +79,6 @@ sizeof(*RegistrationFrame));
/* Call the handler */ - DPRINT1("Calling handler: %p\n", RegistrationFrame->Handler); Disposition = RtlpExecuteHandlerForException(ExceptionRecord, RegistrationFrame, Context, @@ -192,7 +170,7 @@ IN PVOID ReturnValue) { PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame; - DISPATCHER_CONTEXT DispatcherContext; + DISPATCHER_CONTEXT DispatcherContext; EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3; EXCEPTION_DISPOSITION Disposition; ULONG_PTR StackLow, StackHigh; @@ -306,7 +284,7 @@ &DispatcherContext, RegistrationFrame-> Handler); - switch (Disposition) + switch(Disposition) { /* Continue searching */ case ExceptionContinueSearch:
Modified: trunk/reactos/lib/rtl/rtlp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/rtlp.h?rev=25238&am... ============================================================================== --- trunk/reactos/lib/rtl/rtlp.h (original) +++ trunk/reactos/lib/rtl/rtlp.h Fri Dec 29 21:49:00 2006 @@ -15,6 +15,24 @@ #else #define PAGED_CODE_RTL() #endif + +VOID +NTAPI +RtlpGetStackLimits(PULONG_PTR StackBase, + PULONG_PTR StackLimit); + +PEXCEPTION_REGISTRATION_RECORD +NTAPI +RtlpGetExceptionList(VOID); + +VOID +NTAPI +RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList); + +typedef struct _DISPATCHER_CONTEXT +{ + PEXCEPTION_REGISTRATION_RECORD RegistrationPointer; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
/* These provide support for sharing code between User and Kernel RTL */ PVOID @@ -112,7 +130,7 @@ NTSTATUS NTAPI DebugService(IN ULONG Service, - IN PCVOID Buffer, + IN const void* Buffer, IN ULONG Length, IN PVOID Argument1, IN PVOID Argument2);
Modified: trunk/reactos/lib/rtl/thread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/thread.c?rev=25238&... ============================================================================== --- trunk/reactos/lib/rtl/thread.c (original) +++ trunk/reactos/lib/rtl/thread.c Fri Dec 29 21:49:00 2006 @@ -3,7 +3,7 @@ * PROJECT: ReactOS system libraries * PURPOSE: Rtl user thread functions * FILE: lib/rtl/thread.c - * PROGRAMERS: + * PROGRAMERS: * Alex Ionescu (alex@relsoft.net) * Eric Kohl * KJK::Hyperion @@ -21,60 +21,54 @@
NTSTATUS NTAPI -RtlpCreateUserStack(HANDLE hProcess, - ULONG StackReserve, - ULONG StackCommit, - ULONG StackZeroBits, - PINITIAL_TEB InitialTeb) +RtlpCreateUserStack(IN HANDLE hProcess, + IN SIZE_T StackReserve OPTIONAL, + IN SIZE_T StackCommit OPTIONAL, + IN ULONG StackZeroBits OPTIONAL, + OUT PINITIAL_TEB InitialTeb) { NTSTATUS Status; SYSTEM_BASIC_INFORMATION SystemBasicInfo; PIMAGE_NT_HEADERS Headers; ULONG_PTR Stack = 0; BOOLEAN UseGuard = FALSE; - - DPRINT("RtlpCreateUserStack\n"); - + ULONG Dummy, GuardPageSize; + /* Get some memory information */ - Status = NtQuerySystemInformation(SystemBasicInformation, + Status = ZwQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SYSTEM_BASIC_INFORMATION), NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failure to query system info\n"); - return Status; - } - + if (!NT_SUCCESS(Status)) return Status; + /* Use the Image Settings if we are dealing with the current Process */ if (hProcess == NtCurrentProcess()) { /* Get the Image Headers */ Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); - DPRINT("Headers: %p\n", Headers); - + /* If we didn't get the parameters, find them ourselves */ - StackReserve = (StackReserve) ? - StackReserve : Headers->OptionalHeader.SizeOfStackReserve; - StackCommit = (StackCommit) ? - StackCommit : Headers->OptionalHeader.SizeOfStackCommit; + if (!StackReserve) StackReserve = Headers->OptionalHeader. + SizeOfStackReserve; + if (!StackCommit) StackCommit = Headers->OptionalHeader. + SizeOfStackCommit; } else { /* Use the System Settings if needed */ - StackReserve = (StackReserve) ? StackReserve : - SystemBasicInfo.AllocationGranularity; - StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize; - } - + if (!StackReserve) StackReserve = SystemBasicInfo.AllocationGranularity; + if (!StackCommit) StackCommit = SystemBasicInfo.PageSize; + } + /* Align everything to Page Size */ StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity); StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize); - #if 1 // FIXME: Remove once Guard Page support is here + + // FIXME: Remove once Guard Page support is here + #if 1 StackCommit = StackReserve; #endif - DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit); - + /* Reserve memory for the stack */ Status = ZwAllocateVirtualMemory(hProcess, (PVOID*)&Stack, @@ -82,33 +76,26 @@ &StackReserve, MEM_RESERVE, PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failure to reserve stack\n"); - return Status; - } - + if (!NT_SUCCESS(Status)) return Status; + /* Now set up some basic Initial TEB Parameters */ InitialTeb->PreviousStackBase = NULL; InitialTeb->PreviousStackLimit = NULL; InitialTeb->AllocatedStackBase = (PVOID)Stack; InitialTeb->StackBase = (PVOID)(Stack + StackReserve); - + /* Update the Stack Position */ Stack += StackReserve - StackCommit; - + /* Check if we will need a guard page */ if (StackReserve > StackCommit) { + /* Remove a page to set as guard page */ Stack -= SystemBasicInfo.PageSize; StackCommit += SystemBasicInfo.PageSize; UseGuard = TRUE; } - - DPRINT("AllocatedBase: %p, StackBase: %p, Stack: %lx, StackCommit: %lx\n", - InitialTeb->AllocatedStackBase, InitialTeb->StackBase, Stack, - StackCommit); - + /* Allocate memory for the stack */ Status = ZwAllocateVirtualMemory(hProcess, (PVOID*)&Stack, @@ -116,75 +103,68 @@ &StackCommit, MEM_COMMIT, PAGE_READWRITE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failure to allocate stack\n"); - return Status; - } - + if (!NT_SUCCESS(Status)) return Status; + /* Now set the current Stack Limit */ InitialTeb->StackLimit = (PVOID)Stack; - DPRINT("StackLimit: %lx\n", Stack); - + /* Create a guard page */ if (UseGuard) { - ULONG GuardPageSize = SystemBasicInfo.PageSize; - ULONG Dummy; - - /* Attempt maximum space possible */ + /* Attempt maximum space possible */ + GuardPageSize = SystemBasicInfo.PageSize; Status = ZwProtectVirtualMemory(hProcess, (PVOID*)&Stack, &GuardPageSize, PAGE_GUARD | PAGE_READWRITE, &Dummy); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failure to create guard page\n"); - return Status; - } - + if (!NT_SUCCESS(Status)) return Status; + /* Update the Stack Limit keeping in mind the Guard Page */ InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit - GuardPageSize); - DPRINT1("StackLimit: %lx\n", Stack); - } - + } + /* We are done! */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +RtlpFreeUserStack(IN HANDLE Process, + IN PINITIAL_TEB InitialTeb) +{ + ULONG Dummy = 0; + NTSTATUS Status; + + /* Free the Stack */ + Status = ZwFreeVirtualMemory(Process, + &InitialTeb->AllocatedStackBase, + &Dummy, + MEM_RELEASE); + + /* Clear the initial TEB */ + RtlZeroMemory(InitialTeb, sizeof(INITIAL_TEB)); return Status; }
-NTSTATUS -NTAPI -RtlpFreeUserStack(HANDLE hProcess, - PINITIAL_TEB InitialTeb) -{ - ULONG Dummy = 0; - - /* Free the Stack */ - return ZwFreeVirtualMemory(hProcess, - &InitialTeb->AllocatedStackBase, - &Dummy, - MEM_RELEASE); -} - /* FUNCTIONS ***************************************************************/
/* @implemented */ -NTSTATUS -NTAPI -RtlCreateUserThread(HANDLE ProcessHandle, - PSECURITY_DESCRIPTOR SecurityDescriptor, - BOOLEAN CreateSuspended, - LONG StackZeroBits, - ULONG StackReserve, - ULONG StackCommit, - PTHREAD_START_ROUTINE StartAddress, - PVOID Parameter, - PHANDLE ThreadHandle, - PCLIENT_ID ClientId) +NTSTATUS +NTAPI +RtlCreateUserThread(IN HANDLE ProcessHandle, + IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, + IN BOOLEAN CreateSuspended, + IN ULONG StackZeroBits OPTIONAL, + IN SIZE_T StackReserve OPTIONAL, + IN SIZE_T StackCommit OPTIONAL, + IN PTHREAD_START_ROUTINE StartAddress, + IN PVOID Parameter OPTIONAL, + OUT PHANDLE ThreadHandle OPTIONAL, + OUT PCLIENT_ID ClientId OPTIONAL) { NTSTATUS Status; HANDLE Handle; @@ -192,37 +172,27 @@ INITIAL_TEB InitialTeb; OBJECT_ATTRIBUTES ObjectAttributes; CONTEXT Context; - - DPRINT("RtlCreateUserThread: (hProcess: %p, Suspended: %d," - "ZeroBits: %lx, StackReserve: %lx, StackCommit: %lx," - "StartAddress: %p, Parameter: %p)\n", ProcessHandle, - CreateSuspended, StackZeroBits, StackReserve, StackCommit, - StartAddress, Parameter); - + /* First, we'll create the Stack */ Status = RtlpCreateUserStack(ProcessHandle, StackReserve, StackCommit, StackZeroBits, &InitialTeb); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failure to create User Stack\n"); - return Status; - } - + if (!NT_SUCCESS(Status)) return Status; + /* Next, we'll set up the Initial Context */ RtlInitializeContext(ProcessHandle, &Context, Parameter, StartAddress, InitialTeb.StackBase); - + /* We are now ready to create the Kernel Thread Object */ - InitializeObjectAttributes(&ObjectAttributes, - NULL, - 0, - NULL, + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, SecurityDescriptor); Status = ZwCreateThread(&Handle, THREAD_ALL_ACCESS, @@ -234,18 +204,16 @@ CreateSuspended); if (!NT_SUCCESS(Status)) { - DPRINT1("Failure to create Thread\n"); - /* Free the stack */ RtlpFreeUserStack(ProcessHandle, &InitialTeb); } else { - DPRINT("Thread created: %p\n", Handle); + /* Return thread data */ if (ThreadHandle) *ThreadHandle = Handle; if (ClientId) *ClientId = ThreadCid; } - + /* Return success or the previous failure */ return Status; } @@ -262,10 +230,7 @@ IN PTHREAD_START_ROUTINE ThreadStartAddress, IN PINITIAL_TEB InitialTeb) { - DPRINT("RtlInitializeContext: (hProcess: %p, ThreadContext: %p, Teb: %p\n", - ProcessHandle, ThreadContext, InitialTeb); - - /* + /* * Set the Initial Registers * This is based on NT's default values -- crazy apps might expect this... */ @@ -276,27 +241,27 @@ ThreadContext->Edx = 3; ThreadContext->Esi = 4; ThreadContext->Edi = 5; - + /* Set the Selectors */ ThreadContext->SegGs = 0; - ThreadContext->SegFs = KGDT_R3_TEB | RPL_MASK; - ThreadContext->SegEs = KGDT_R3_DATA | RPL_MASK; - ThreadContext->SegDs = KGDT_R3_DATA | RPL_MASK; - ThreadContext->SegCs = KGDT_R3_CODE | RPL_MASK; - ThreadContext->SegSs = KGDT_R3_DATA | RPL_MASK; - + ThreadContext->SegFs = KGDT_R3_TEB; + ThreadContext->SegEs = KGDT_R3_DATA; + ThreadContext->SegDs = KGDT_R3_DATA; + ThreadContext->SegSs = KGDT_R3_DATA; + ThreadContext->SegCs = KGDT_R3_CODE; + /* Enable Interrupts */ - ThreadContext->EFlags = 0x200; /*X86_EFLAGS_IF */ - + ThreadContext->EFlags = EFLAGS_INTERRUPT_MASK; + /* Settings passed */ ThreadContext->Eip = (ULONG)ThreadStartAddress; ThreadContext->Esp = (ULONG)InitialTeb; - + /* Only the basic Context is initialized */ - ThreadContext->ContextFlags = CONTEXT_CONTROL | - CONTEXT_INTEGER | + ThreadContext->ContextFlags = CONTEXT_CONTROL | + CONTEXT_INTEGER | CONTEXT_SEGMENTS; - + /* Set up ESP to the right value */ ThreadContext->Esp -= sizeof(PVOID); ZwWriteVirtualMemory(ProcessHandle, @@ -304,7 +269,7 @@ (PVOID)&ThreadStartParam, sizeof(PVOID), NULL); - + /* Push it down one more notch for RETEIP */ ThreadContext->Esp -= sizeof(PVOID); } @@ -312,13 +277,13 @@ /* * @implemented */ -VOID -NTAPI +VOID +NTAPI RtlExitUserThread(NTSTATUS Status) { /* Call the Loader and tell him to notify the DLLs */ LdrShutdownThread(); - + /* Shut us down */ NtCurrentTeb()->FreeStackOnTermination = TRUE; NtTerminateThread(NtCurrentThread(), Status); @@ -327,8 +292,8 @@ /* @implemented */ -VOID -NTAPI +VOID +NTAPI RtlFreeUserThreadStack(HANDLE ProcessHandle, HANDLE ThreadHandle) { @@ -336,19 +301,15 @@ THREAD_BASIC_INFORMATION ThreadBasicInfo; ULONG Dummy, Size = 0; PVOID StackLocation; - + /* Query the Basic Info */ Status = NtQueryInformationThread(ThreadHandle, ThreadBasicInformation, &ThreadBasicInfo, sizeof(THREAD_BASIC_INFORMATION), NULL); - if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) - { - DPRINT1("Could not query info, or TEB is NULL\n"); - return; - } - + if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) return; + /* Get the deallocation stack */ Status = NtReadVirtualMemory(ProcessHandle, &((PTEB)ThreadBasicInfo.TebBaseAddress)-> @@ -356,12 +317,8 @@ &StackLocation, sizeof(PVOID), &Dummy); - if (!NT_SUCCESS(Status) || !StackLocation) - { - DPRINT1("Could not read Deallocation Base\n"); - return; - } - + if (!NT_SUCCESS(Status) || !StackLocation) return; + /* Free it */ NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE); }
Modified: trunk/reactos/ntoskrnl/KrnlFun.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=2523... ============================================================================== --- trunk/reactos/ntoskrnl/KrnlFun.c (original) +++ trunk/reactos/ntoskrnl/KrnlFun.c Fri Dec 29 21:49:00 2006 @@ -10,31 +10,32 @@ // // // Ob: -// - Fix bug related to Deferred Loading (don't requeue active work item). // - Add Directory Lock. +// - Strengthen code with debug checks and assertions. +// - Fix FIXMEs/commented out code. +// +// Ex: +// - Fixup existing code that talks to Ke. +// - Implement Generic Callback mechanism. +// - Use pushlocks for handle implementation. +// +// Lpc: +// - Figure out why NTLPC-processes won't die anymore. +// +// Ke1: +// - Implement KiInitMachineDependent. +// - Implement Privileged Instruction Handler in Umode GPF. // // Fstub: // - Implement IoAssignDriveLetters using mount manager support. // -// Ke: -// - Figure out why the DPC stack doesn't really work. -// - Fix SEH/Page Fault + Exceptions!? Weird exception bugs! +// Hal: +// - Use APC and DPC Interrupt Dispatchers. +// - CMOS Initialization and CMOS Spinlock. +// +// Ke2: // - New optimized table-based tick-hashed timer implementation. // - New Thread Scheduler based on 2003. -// - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion. -// -// Hal: -// - New IRQL Implementation. -// - CMOS Initialization and CMOS Spinlock. -// - Report resource usage to kernel (HalReportResourceUsage). -// -// Lpc: -// - Activate new NTLPC and delete old implementation. -// - Figure out why LPC-processes won't die anymore. -// -// Ex: -// - Implement Generic Callback mechanism. -// - Use pushlocks for handle implementation. // // Kd: // - Implement KD Kernel Debugging and WinDBG support. @@ -45,3 +46,30 @@ // ///////////////////////////////////////////////////////////////////////////////
+// REACTOS GUIDANCE PLAN +// ________________________________________________________________________________________________________ +// / \ +// | OB, PS, LPC, DBGK, IO => Almost entirely fixed interaction with Ke/Ex. | | +// | SE => Not looked at. Interaction with Ps/Io is minimal and currently hacked away. Preserve. |J| +// | EX => Needs re-visiting (in trunk). Do callbacks/push locks for interaction with Ps. |A| +// | KD/KDBG => Laptop has special version of ROS without these components. Commit in branch. |N| +// | INIT => Boot sequence still needs work in terms of interaction with Ke and CPU features. | | +// | || || || || || || || || || || || || |F| +// | / / / / / / / / / / / / |E| +// | HAL => Needs APC/DPC/IRQL implementation fixed ASAP in terms of interaction with Ke. |B| +// | FSTUB => Needs IoAssignDriveLetters fixed ASAP but not critical to Ke/Ex. Interacts with Io. | | +// | || || || || || || || || || || || || |M| +// | / / / / / / / / / / / / |A| +// | CM => TOTAL REWRITE. |R| +// | || || || || || || || || || || || || | | +// | || || || || || || || || || || || || |A| +// | / / / / / / / / / / / / |P| +// | KE => Timer Rewrite + Thread Scheduler Rewrite. |R| +// | || || || || || || || || || || || || |I| +// | || || || || || || || || || || || || |L| +// | || || || || || || || || || || || || | | +// | / / / / / / / / / / / / |M| +// | MM => TOTAL REWRITE. |A| +// | |Y| +// ________________________________________________________________________________________________________/ +//
Modified: trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/i386/fastinterl... ============================================================================== --- trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S (original) +++ trunk/reactos/ntoskrnl/ex/i386/fastinterlck_asm.S Fri Dec 29 21:49:00 2006 @@ -381,6 +381,9 @@ */ .global @ExInterlockedPopEntrySList@8 .global @InterlockedPopEntrySList@4 +.global _ExpInterlockedPopEntrySListResume@0 +.global _ExpInterlockedPopEntrySListFault@0 +.global _ExpInterlockedPopEntrySListEnd@0 @ExInterlockedPopEntrySList@8: @InterlockedPopEntrySList@4:
@@ -392,10 +395,10 @@ mov ebp, ecx
/* Get sequence number and link pointer */ +_ExpInterlockedPopEntrySListResume@0: mov edx, [ebp+4] mov eax, [ebp]
-1: /* Check if the list is empty */ or eax, eax jz 2f @@ -404,9 +407,11 @@ lea ecx, [edx-1]
/* Get next pointer and do the exchange */ +_ExpInterlockedPopEntrySListFault@0: mov ebx, [eax] +_ExpInterlockedPopEntrySListEnd@0: LOCK cmpxchg8b [ebp] - jnz 1b + jnz _ExpInterlockedPopEntrySListResume@0
/* Restore registers and return */ 2:
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S Fri Dec 29 21:49:00 2006 @@ -66,6 +66,30 @@ #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 // // This macro creates an IDT entry for the given handler @@ -182,7 +206,6 @@ push offset V86DebugMsg call _DbgPrint add esp, 8 - int 3 jmp $ .endm
@@ -511,7 +534,7 @@
/* Check if this was kernel mode */ 1: - cmp dword ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE + cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE jz 1f
/* Set segments */ @@ -947,7 +970,7 @@ /* Assert the saved exception list */ or edx, edx jnz 1f - int 3 + UNHANDLED_PATH 1: #endif
@@ -962,7 +985,7 @@ /* Assert the saved previous mode */ cmp ecx, -1 jnz 1f - int 3 + UNHANDLED_PATH 1: #endif
@@ -976,7 +999,7 @@ mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE] cmp ecx, -1 jz 1f - int 3 + UNHANDLED_PATH 1: #endif .endif @@ -1111,7 +1134,7 @@ add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
6: - int 3 + UNHANDLED_PATH jmp 5b #endif
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h Fri Dec 29 21:49:00 2006 @@ -41,11 +41,7 @@ #define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */ #define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
-#define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */ - #define FRAME_EDITED 0xFFF8 - -#define WE_DO_NOT_SPEAK_ABOUT_THE_V86_HACK 1
#ifndef __ASM__
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h Fri Dec 29 21:49:00 2006 @@ -130,6 +130,8 @@ extern PVOID KeUserCallbackDispatcher; extern PVOID KeUserExceptionDispatcher; extern PVOID KeRaiseUserExceptionDispatcher; +extern UCHAR KiDebugRegisterTrapOffsets[9]; +extern UCHAR KiDebugRegisterContextOffsets[9];
/* MACROS *************************************************************************/
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke_x.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke_x.h Fri Dec 29 21:49:00 2006 @@ -5,6 +5,86 @@ * PURPOSE: Internal Inlined Functions for the Kernel * 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
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/m... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/mm.h (original) +++ trunk/reactos/ntoskrnl/include/internal/mm.h Fri Dec 29 21:49:00 2006 @@ -686,17 +686,10 @@ NTSTATUS NTAPI MmAccessFault( - KPROCESSOR_MODE Mode, - ULONG_PTR Address, - BOOLEAN FromMdl -); - -NTSTATUS -NTAPI -MmNotPresentFault( - KPROCESSOR_MODE Mode, - ULONG_PTR Address, - BOOLEAN FromMdl + IN BOOLEAN StoreInstruction, + IN PVOID Address, + IN KPROCESSOR_MODE Mode, + IN PVOID TrapInformation );
/* anonmem.c *****************************************************************/
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ob.h Fri Dec 29 21:49:00 2006 @@ -188,9 +188,10 @@ // Object Lifetime Functions // VOID -FASTCALL +NTAPI ObpDeleteObject( - IN PVOID Object + IN PVOID Object, + IN BOOLEAN CalledFromWorkerThread );
LONG
Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/cpu.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/cpu.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/cpu.c Fri Dec 29 21:49:00 2006 @@ -29,17 +29,17 @@ /* The TSS to use for NMI Fault Traps (INT 0x2) */ UCHAR KiNMITSS[KTSS_IO_MAPS];
-/* The Boot GDT (FIXME: should have more entries */ -KGDTENTRY KiBootGdt[12] = +/* The Boot GDT */ +KGDTENTRY KiBootGdt[256] = { {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_NULL */ - {0xffff, 0x0000, {{0x00, 0x9a, 0xcf, 0x00}}}, /* KGDT_R0_CODE */ - {0xffff, 0x0000, {{0x00, 0x92, 0xcf, 0x00}}}, /* KGDT_R0_DATA */ - {0xffff, 0x0000, {{0x00, 0xfa, 0xcf, 0x00}}}, /* KGDT_R3_CODE */ - {0xffff, 0x0000, {{0x00, 0xf2, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/ + {0xffff, 0x0000, {{0x00, 0x9b, 0xcf, 0x00}}}, /* KGDT_R0_CODE */ + {0xffff, 0x0000, {{0x00, 0x93, 0xcf, 0x00}}}, /* KGDT_R0_DATA */ + {0xffff, 0x0000, {{0x00, 0xfb, 0xcf, 0x00}}}, /* KGDT_R3_CODE */ + {0xffff, 0x0000, {{0x00, 0xf3, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_TSS */ - {0x0fff, 0x0000, {{0x00, 0x92, 0x00, 0xff}}}, /* KGDT_R0_PCR */ - {0x0fff, 0x0000, {{0x00, 0xf2, 0x00, 0x00}}}, /* KGDT_R3_TEB */ + {0x0fff, 0x0000, {{0x00, 0x93, 0xc0, 0xff}}}, /* KGDT_R0_PCR */ + {0x0fff, 0x0000, {{0x00, 0xf3, 0x40, 0x00}}}, /* KGDT_R3_TEB */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_UNUSED */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_LDT */ {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_DF_TSS */
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/exp.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/exp.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/exp.c Fri Dec 29 21:49:00 2006 @@ -14,6 +14,36 @@ #define NDEBUG #include <debug.h>
+/* GLOBALS *******************************************************************/ + +/* DR Registers in the CONTEXT structure */ +UCHAR KiDebugRegisterContextOffsets[9] = +{ + FIELD_OFFSET(CONTEXT, Dr0), + FIELD_OFFSET(CONTEXT, Dr1), + FIELD_OFFSET(CONTEXT, Dr2), + FIELD_OFFSET(CONTEXT, Dr3), + 0, + 0, + FIELD_OFFSET(CONTEXT, Dr6), + FIELD_OFFSET(CONTEXT, Dr7), + 0, +}; + +/* DR Registers in the KTRAP_FRAME structure */ +UCHAR KiDebugRegisterTrapOffsets[9] = +{ + FIELD_OFFSET(KTRAP_FRAME, Dr0), + FIELD_OFFSET(KTRAP_FRAME, Dr1), + FIELD_OFFSET(KTRAP_FRAME, Dr2), + FIELD_OFFSET(KTRAP_FRAME, Dr3), + 0, + 0, + FIELD_OFFSET(KTRAP_FRAME, Dr6), + FIELD_OFFSET(KTRAP_FRAME, Dr7), + 0, +}; + /* FUNCTIONS *****************************************************************/
_SEH_DEFINE_LOCALS(KiCopyInfo) @@ -51,6 +81,101 @@ KiIdt[i].Selector = KiIdt[i].ExtendedOffset; KiIdt[i].ExtendedOffset = FlippedSelector; } +} + +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 @@ -192,6 +317,8 @@ ULONG i; BOOLEAN V86Switch = FALSE; KIRQL OldIrql = APC_LEVEL; + ULONG DrMask = 0; + PVOID SafeDr;
/* Do this at APC_LEVEL */ if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); @@ -207,8 +334,8 @@ V86Switch = TRUE; }
- /* Copy EFLAGS. FIXME: Needs to be sanitized */ - TrapFrame->EFlags = Context->EFlags; + /* Copy EFLAGS and sanitize them*/ + TrapFrame->EFlags = Ke386SanitizeFlags(Context->EFlags, PreviousMode);
/* Copy EBP and EIP */ TrapFrame->Ebp = Context->Ebp; @@ -222,14 +349,14 @@ } else { - /* We weren't in V86, so sanitize the CS (FIXME!) */ - TrapFrame->SegCs = Context->SegCs; + /* We weren't in V86, so sanitize the CS */ + TrapFrame->SegCs = Ke386SanitizeSeg(Context->SegCs, PreviousMode);
/* Don't let it under 8, that's invalid */ if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8)) { /* Force it to User CS */ - TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK); + TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; } }
@@ -261,7 +388,7 @@ /* Check if we were in V86 Mode */ if (TrapFrame->EFlags & EFLAGS_V86_MASK) { - /* Copy the V86 Segments directlry */ + /* Copy the V86 Segments directly */ TrapFrame->V86Ds = Context->SegDs; TrapFrame->V86Es = Context->SegEs; TrapFrame->V86Fs = Context->SegFs; @@ -272,12 +399,12 @@ /* For kernel mode, write the standard values */ TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; - TrapFrame->SegFs = Context->SegFs; + TrapFrame->SegFs = Ke386SanitizeSeg(Context->SegFs, PreviousMode); TrapFrame->SegGs = 0; } else { - /* For user mode, return the values directlry */ + /* For user mode, return the values directly */ TrapFrame->SegDs = Context->SegDs; TrapFrame->SegEs = Context->SegEs; TrapFrame->SegFs = Context->SegFs; @@ -320,7 +447,13 @@ /* Mask out any invalid flags */ FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
- /* FIXME: Check if this is a VDM app */ + /* Check if this is a VDM app */ + if (PsGetCurrentProcess()->VdmObjects) + { + /* Allow the EM flag */ + FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState & + (CR0_EM | CR0_MP); + } } }
@@ -373,16 +506,40 @@ } else { - /* Just dump the Fn state in */ - RtlCopyMemory(&FxSaveArea->U.FnArea, - &Context->FloatSave, - sizeof(FNSAVE_FORMAT)); + /* Copy the structure */ + FxSaveArea->U.FnArea.ControlWord = Context->FloatSave. + ControlWord; + FxSaveArea->U.FnArea.StatusWord = Context->FloatSave. + StatusWord; + FxSaveArea->U.FnArea.TagWord = Context->FloatSave.TagWord; + FxSaveArea->U.FnArea.ErrorOffset = Context->FloatSave. + ErrorOffset; + FxSaveArea->U.FnArea.ErrorSelector = Context->FloatSave. + ErrorSelector; + FxSaveArea->U.FnArea.DataOffset = Context->FloatSave. + DataOffset; + FxSaveArea->U.FnArea.DataSelector = Context->FloatSave. + DataSelector; + + /* Loop registers */ + for (i = 0; i < SIZE_OF_80387_REGISTERS; i++) + { + /* Copy registers */ + FxSaveArea->U.FnArea.RegisterArea[i] = + Context->FloatSave.RegisterArea[i]; + } }
/* Mask out any invalid flags */ FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
- /* FIXME: Check if this is a VDM app */ + /* Check if this is a VDM app */ + if (PsGetCurrentProcess()->VdmObjects) + { + /* Allow the EM flag */ + FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState & + (CR0_EM | CR0_MP); + } } else { @@ -394,22 +551,37 @@ /* Handle the Debug Registers */ if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) { - /* FIXME: All these should be sanitized */ - TrapFrame->Dr0 = Context->Dr0; - TrapFrame->Dr1 = Context->Dr1; - TrapFrame->Dr2 = Context->Dr2; - TrapFrame->Dr3 = Context->Dr3; - TrapFrame->Dr6 = Context->Dr6; - TrapFrame->Dr7 = Context->Dr7; - - /* Check if usermode */ + /* Loop DR registers */ + for (i = 0; i < 4; i++) + { + /* Sanitize the context DR Address */ + SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode); + + /* Save it in the trap frame */ + *KiDrFromTrapFrame(i, TrapFrame) = SafeDr; + + /* Check if this DR address is active and add it in the DR mask */ + if (SafeDr) DrMask |= DR_MASK(i); + } + + /* Now save and sanitize DR6 */ + TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL; + if (TrapFrame->Dr6) DrMask |= DR_MASK(6); + + /* Save and sanitize DR7 */ + TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL; + KiRecordDr7(&TrapFrame->Dr7, &DrMask); + + /* If we're in user-mode */ if (PreviousMode != KernelMode) { - /* Set the Debug Flag */ - KeGetCurrentThread()->DispatcherHeader.DebugActive = - (Context->Dr7 & DR7_ACTIVE) ? TRUE: FALSE; - } - } + /* FIXME: Save the mask */ + //KeGetCurrentThread()->DispatcherHeader.DebugActive = DrMask; + } + } + + /* Check if thread has IOPL and force it enabled if so */ + if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
/* Restore IRQL */ if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql); @@ -429,6 +601,7 @@ } FloatSaveBuffer; FLOATING_SAVE_AREA *FloatSaveArea; KIRQL OldIrql = APC_LEVEL; + ULONG i;
/* Do this at APC_LEVEL */ if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); @@ -550,10 +723,23 @@ KiFlushNPXState(NULL); }
- /* Copy into the Context */ - RtlCopyMemory(&Context->FloatSave, - FloatSaveArea, - sizeof(FNSAVE_FORMAT)); + /* Copy structure */ + Context->FloatSave.ControlWord = FloatSaveArea->ControlWord; + Context->FloatSave.StatusWord = FloatSaveArea->StatusWord; + Context->FloatSave.TagWord = FloatSaveArea->TagWord; + Context->FloatSave.ErrorOffset = FloatSaveArea->ErrorOffset; + Context->FloatSave.ErrorSelector = FloatSaveArea->ErrorSelector; + Context->FloatSave.DataOffset = FloatSaveArea->DataOffset; + Context->FloatSave.DataSelector = FloatSaveArea->DataSelector; + Context->FloatSave.Cr0NpxState = FxSaveArea->Cr0NpxState; + + /* Loop registers */ + for (i = 0; i < SIZE_OF_80387_REGISTERS; i++) + { + /* Copy them */ + Context->FloatSave.RegisterArea[i] = + FloatSaveArea->RegisterArea[i]; + } } else { @@ -566,24 +752,26 @@ if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) { - /* Copy the debug registers */ - Context->Dr0 = TrapFrame->Dr0; - Context->Dr1 = TrapFrame->Dr1; - Context->Dr2 = TrapFrame->Dr2; - Context->Dr3 = TrapFrame->Dr3; - Context->Dr6 = TrapFrame->Dr6; - - /* For user-mode, only set DR7 if a debugger is active */ - if (((TrapFrame->SegCs & MODE_MASK) || - (TrapFrame->EFlags & EFLAGS_V86_MASK)) && - (KeGetCurrentThread()->DispatcherHeader.DebugActive)) - { - /* Copy it over */ - Context->Dr7 = TrapFrame->Dr7; + /* Make sure DR7 is valid */ + if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK) + { + /* Copy the debug registers */ + Context->Dr0 = TrapFrame->Dr0; + Context->Dr1 = TrapFrame->Dr1; + Context->Dr2 = TrapFrame->Dr2; + Context->Dr3 = TrapFrame->Dr3; + Context->Dr6 = TrapFrame->Dr6; + + /* Update DR7 */ + //Context->Dr7 = KiUpdateDr7(TrapFrame->Dr7); } else { - /* Clear it */ + /* Otherwise clear DR registers */ + Context->Dr0 = + Context->Dr1 = + Context->Dr3 = + Context->Dr6 = Context->Dr7 = 0; } } @@ -757,13 +945,13 @@ KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
/* Force correct segments */ - TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; - TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; - TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; - TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK; + TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, PreviousMode); + TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode); + TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode); + TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, PreviousMode); TrapFrame->SegGs = 0;
- /* Set EIP to the User-mode Dispathcer */ + /* Set EIP to the User-mode Dispatcher */ TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher; _SEH_LEAVE; }
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/trap.s (original) +++ trunk/reactos/ntoskrnl/ke/i386/trap.s Fri Dec 29 21:49:00 2006 @@ -87,13 +87,17 @@ _UnexpectedMsg: .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
+_UnhandledMsg: + .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n" + /* SOFTWARE INTERRUPT SERVICES ***********************************************/ .text
_KiGetTickCount: _KiCallbackReturn: _KiRaiseAssertion: - int 3 + /* FIXME: TODO */ + UNHANDLED_PATH
.func KiSystemService Dr_kss: DR_TRAP_FIXUP @@ -144,6 +148,7 @@
/* Check if we should flush the User Batch */ xor ebx, ebx +ReadBatch: or ebx, [ecx+TEB_GDI_BATCH_COUNT] jz NotWin32K
@@ -432,8 +437,8 @@ iret
AbiosExit: - /* Not yet supported */ - int 3 + /* FIXME: TODO */ + UNHANDLED_PATH
.func KiDebugService Dr_kids: DR_TRAP_FIXUP @@ -672,6 +677,13 @@
/* HARDWARE TRAP HANDLERS ****************************************************/
+.func KiFixupFrame +_KiFixupFrame: + + /* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */ + UNHANDLED_PATH +.endfunc + .func KiTrap0 Dr_kit0: DR_TRAP_FIXUP V86_kit0: V86_TRAP_FIXUP @@ -710,7 +722,8 @@
/* We don't support this yet! */ V86Int0: - int 3 + /* FIXME: TODO */ + UNHANDLED_PATH .endfunc
.func KiTrap1 @@ -754,7 +767,7 @@ jz EnableInterrupts
/* We don't support VDM! */ - int 3 + UNHANDLED_PATH .endfunc
.globl _KiTrap2 @@ -813,7 +826,7 @@ jz EnableInterrupts3
/* We don't support VDM! */ - int 3 + UNHANDLED_PATH .endfunc
.func KiTrap4 @@ -855,7 +868,7 @@
/* We don't support this yet! */ V86Int4: - int 3 + UNHANDLED_PATH .endfunc
.func KiTrap5 @@ -901,7 +914,7 @@
/* We don't support this yet! */ V86Int5: - int 3 + UNHANDLED_PATH .endfunc
.func KiTrap6 @@ -917,8 +930,7 @@ V86_TRAP_PROLOG kit6
/* Not yet supported (Invalid OPCODE from V86) */ - int 3 - jmp $ + UNHANDLED_PATH
NotV86UD: /* Push error code */ @@ -993,8 +1005,7 @@ IsVdmOpcode:
/* Unhandled yet */ - int 3 - jmp $ + UNHANDLED_PATH
/* Return to caller */ jmp _Kei386EoiHelper@0 @@ -1302,8 +1313,7 @@ jz HandleUserNpx
/* V86 NPX not handled */ - int 3 - jmp $ + UNHANDLED_PATH
EmulationEnabled: /* Did this come from kernel-mode? */ @@ -1456,7 +1466,7 @@ jnz NoReflect
/* FIXME: TODO */ - int 3 + UNHANDLED_PATH
NoReflect:
@@ -1485,9 +1495,21 @@ test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK jnz UserModeGpf
- /* FIXME: Check for GPF during GPF */ + /* Check if we have a VDM alert */ + cmp dword ptr fs:[KPCR_VDM_ALERT], 0 + jnz VdmAlertGpf + + /* Check for GPF during GPF */ + mov eax, [ebp+KTRAP_FRAME_EIP] + cmp eax, offset CheckPrivilegedInstruction + jbe KmodeGpf + cmp eax, offset CheckPrivilegedInstruction2 + + /* FIXME: TODO */ + UNHANDLED_PATH
/* Get the opcode and trap frame */ +KmodeGpf: mov eax, [ebp+KTRAP_FRAME_EIP] mov eax, [eax] mov edx, [ebp+KTRAP_FRAME_EBP] @@ -1573,8 +1595,7 @@ MsrCheck:
/* FIXME: Handle RDMSR/WRMSR */ - int 3 - jmp $ + UNHANDLED_PATH
NotIretGpf:
@@ -1606,7 +1627,6 @@ lea eax, [ebp+KTRAP_FRAME_ESP] cmp edx, eax jz HandleSegPop - int 3
/* Handle segment POP fault by setting it to 0 */ HandleSegPop: @@ -1620,26 +1640,239 @@
UserModeGpf:
- /* FIXME: Unhandled */ - int 3 - jmp $ + /* If the previous mode was kernel, raise a fatal exception */ + mov eax, 13 + test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK + jz _KiSystemFatalException + + /* Get the process and check which CS this came from */ + mov ebx, fs:[KPCR_CURRENT_THREAD] + mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS] + cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK + jz CheckVdmGpf + + /* Check if this is a VDM */ + cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 + jnz DispatchV86Gpf + + /* Enable interrupts and check if we have an error code */ + sti + cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0 + jnz SetException + jmp CheckPrivilegedInstruction + +HandleSegPop2: + /* Update EIP (will be updated below again) */ + add dword ptr [ebp+KTRAP_FRAME_EIP], 1 + +HandleBop4: + /* Clear the segment, update EIP and ESP */ + mov dword ptr [edx], 0 + add dword ptr [ebp+KTRAP_FRAME_EIP], 1 + add dword ptr [ebp+KTRAP_FRAME_ESP], 4 + jmp _Kei386EoiHelper@0 + +CheckVdmGpf: + /* Check if this is a VDM */ + cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 + jz CheckPrivilegedInstruction + + /* Check what kind of instruction this is */ + mov eax, [ebp+KTRAP_FRAME_EIP] + mov eax, [eax] + + /* FIXME: Check for BOP4 */ + + /* Check if this is POP FS */ + mov edx, ebp + add edx, KTRAP_FRAME_FS + cmp ax, 0xA10F + jz HandleSegPop2 + + /* Check if this is POP GS */ + add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS + cmp ax, 0xA90F + jz HandleSegPop2 + +CheckPrivilegedInstruction: + /* FIXME */ + UNHANDLED_PATH + +CheckPrivilegedInstruction2: + /* FIXME */ + UNHANDLED_PATH + +SetException: + /* FIXME */ + UNHANDLED_PATH + +DispatchV86Gpf: + /* FIXME */ + UNHANDLED_PATH .endfunc
.func KiTrap14 Dr_kit14: DR_TRAP_FIXUP V86_kit14: V86_TRAP_FIXUP _KiTrap14: + /* Enter trap */ TRAP_PROLOG kit14
- /* Call the C exception handler */ - push 14 + /* Check if we have a VDM alert */ + cmp dword ptr fs:[KPCR_VDM_ALERT], 0 + jnz VdmAlertGpf + + /* 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 - call _KiPageFaultHandler - add esp, 8 - - /* Return to caller */ + mov eax, [ebp+KTRAP_FRAME_CS] + and eax, MODE_MASK + push eax + + /* Send faulting address and check if this is read or write */ + push edi + mov eax, [ebp+KTRAP_FRAME_ERROR_CODE] + and eax, 1 + push eax + + /* Call the access fault handler */ + call _MmAccessFault@16 + test eax, eax + jl AccessFail + + /* Access fault handled, return to caller */ jmp _Kei386EoiHelper@0 + +AccessFail: + /* First check if this is a fault in the S-LIST functions */ + mov ecx, offset _ExpInterlockedPopEntrySListFault@0 + cmp [ebp+KTRAP_FRAME_EIP], ecx + jz SlistFault + + /* Check if this is a fault in the syscall handler */ + mov ecx, offset CopyParams + cmp [ebp+KTRAP_FRAME_EIP], ecx + jz SysCallCopyFault + mov ecx, offset ReadBatch + cmp [ebp+KTRAP_FRAME_EIP], ecx + jnz CheckVdmPf + + /* FIXME: TODO */ + UNHANDLED_PATH + jmp _Kei386EoiHelper@0 + +SysCallCopyFault: + /* FIXME: TODO */ + UNHANDLED_PATH + jmp _Kei386EoiHelper@0 + + /* Check if the fault occured in a V86 mode */ +CheckVdmPf: + mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE] + and ecx, 1 + shr ecx, 1 + test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + jnz VdmPF + + /* Check if the fault occured in a VDM */ + mov esi, fs:[KPCR_CURRENT_THREAD] + mov esi, [esi+KTHREAD_APCSTATE_PROCESS] + cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0 + jz CheckStatus + + /* Check if we this was in kernel-mode */ + test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK + jz CheckStatus + cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK + jz CheckStatus + +VdmPF: + /* FIXME: TODO */ + UNHANDLED_PATH + + /* Save EIP and check what kind of status failure we got */ +CheckStatus: + mov esi, [ebp+KTRAP_FRAME_EIP] + cmp eax, STATUS_ACCESS_VIOLATION + je AccessViol + cmp eax, STATUS_GUARD_PAGE_VIOLATION + je SpecialCode + cmp eax, STATUS_STACK_OVERFLOW + je SpecialCode + + /* Setup an in-page exception to dispatch */ + mov edx, ecx + mov ebx, esi + mov esi, edi + mov ecx, 3 + mov edi, eax + mov eax, STATUS_IN_PAGE_ERROR + call _CommonDispatchException + +AccessViol: + /* Use more proper status code */ + mov eax, KI_EXCEPTION_ACCESS_VIOLATION + +SpecialCode: + /* Setup a normal page fault exception */ + mov ebx, esi + mov edx, ecx + mov esi, edi + jmp _DispatchTwoParam + +SlistFault: + /* FIXME: TODO */ + UNHANDLED_PATH + +IllegalState: + + /* This is completely illegal, bugcheck the system */ + push ebp + push esi + push ecx + push eax + push edi + push IRQL_NOT_LESS_OR_EQUAL + call _KeBugCheckWithTf@24 + +VdmAlertGpf: + + /* FIXME: NOT SUPPORTED */ + UNHANDLED_PATH .endfunc
.func KiTrap0F @@ -1752,8 +1985,7 @@ add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */ - /* TODO */ - int 3 + UNHANDLED_PATH .endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/ @@ -1867,7 +2099,7 @@ jz Return
/* FIXME: Schedule new thread */ - int 3 + UNHANDLED_PATH
Return: /* All done */ @@ -1904,7 +2136,7 @@ _KiChainedDispatch2ndLvl@0:
/* Not yet supported */ - int 3 + UNHANDLED_PATH .endfunc
.func KiChainedDispatch@0
Modified: trunk/reactos/ntoskrnl/ke/i386/usercall.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/usercall.c... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/usercall.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/usercall.c Fri Dec 29 21:49:00 2006 @@ -71,7 +71,7 @@ _SEH_DECLARE_LOCALS(KiCopyInfo);
/* Don't deliver APCs in V86 mode */ - if (TrapFrame->EFlags & X86_EFLAGS_VM) return; + if (TrapFrame->EFlags & EFLAGS_V86_MASK) return;
/* Save the full context */ Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; @@ -102,22 +102,19 @@ TrapFrame->HardwareEsp = Stack;
/* Setup Ring 3 state */ - TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; - TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK; - TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; - TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; + TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, UserMode); + TrapFrame->HardwareSegSs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode); + TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode); + TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode); + TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, UserMode); TrapFrame->SegGs = 0; + TrapFrame->ErrCode = 0;
/* Sanitize EFLAGS */ - TrapFrame->EFlags = Context.EFlags & EFLAGS_USER_SANITIZE; - TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK; - - /* Check if user-mode has IO privileges */ - if (KeGetCurrentThread()->Iopl) - { - /* Enable them*/ - TrapFrame->EFlags |= (0x3000); - } + TrapFrame->EFlags = Ke386SanitizeFlags(Context.EFlags, UserMode); + + /* Check if thread has IOPL and force it enabled if so */ + if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
/* Setup the stack */ *(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;
Removed: trunk/reactos/ntoskrnl/mm/i386/memsafe.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/memsafe.s?... ============================================================================== --- trunk/reactos/ntoskrnl/mm/i386/memsafe.s (original) +++ trunk/reactos/ntoskrnl/mm/i386/memsafe.s (removed) @@ -1,17 +1,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
Removed: trunk/reactos/ntoskrnl/mm/i386/pfault.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/pfault.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/mm/i386/pfault.c (original) +++ trunk/reactos/ntoskrnl/mm/i386/pfault.c (removed) @@ -1,135 +1,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; -} -
Modified: trunk/reactos/ntoskrnl/mm/mdl.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mdl.c?rev=25238... ============================================================================== --- trunk/reactos/ntoskrnl/mm/mdl.c (original) +++ trunk/reactos/ntoskrnl/mm/mdl.c Fri Dec 29 21:49:00 2006 @@ -433,7 +433,7 @@
if (!MmIsPagePresent(NULL, Address)) { - Status = MmNotPresentFault(Mode, (ULONG_PTR)Address, TRUE); + Status = MmAccessFault(FALSE, Address, Mode, NULL); if (!NT_SUCCESS(Status)) { for (j = 0; j < i; j++) @@ -457,7 +457,7 @@ if ((Operation == IoWriteAccess || Operation == IoModifyAccess) && (!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE))) { - Status = MmAccessFault(Mode, (ULONG_PTR)Address, TRUE); + Status = MmAccessFault(TRUE, Address, Mode, NULL); if (!NT_SUCCESS(Status)) { for (j = 0; j < i; j++)
Modified: trunk/reactos/ntoskrnl/mm/mm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mm.c?rev=25238&... ============================================================================== --- trunk/reactos/ntoskrnl/mm/mm.c (original) +++ trunk/reactos/ntoskrnl/mm/mm.c Fri Dec 29 21:49:00 2006 @@ -75,9 +75,9 @@
NTSTATUS NTAPI -MmAccessFault(KPROCESSOR_MODE Mode, - ULONG_PTR Address, - BOOLEAN FromMdl) +MmpAccessFault(KPROCESSOR_MODE Mode, + ULONG_PTR Address, + BOOLEAN FromMdl) { PMADDRESS_SPACE AddressSpace; MEMORY_AREA* MemoryArea; @@ -109,7 +109,7 @@ { DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); DbgPrint("%s:%d\n",__FILE__,__LINE__); - return(STATUS_UNSUCCESSFUL); + return(STATUS_ACCESS_VIOLATION); } AddressSpace = MmGetKernelAddressSpace(); } @@ -131,13 +131,13 @@ { MmUnlockAddressSpace(AddressSpace); } - return (STATUS_UNSUCCESSFUL); + return (STATUS_ACCESS_VIOLATION); }
switch (MemoryArea->Type) { case MEMORY_AREA_SYSTEM: - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_ACCESS_VIOLATION; break;
case MEMORY_AREA_PAGED_POOL: @@ -152,15 +152,15 @@ break;
case MEMORY_AREA_VIRTUAL_MEMORY: - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_ACCESS_VIOLATION; break;
case MEMORY_AREA_SHARED_DATA: - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_ACCESS_VIOLATION; break;
default: - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_ACCESS_VIOLATION; break; } } @@ -170,32 +170,6 @@ if (!FromMdl) { MmUnlockAddressSpace(AddressSpace); - } - 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); } @@ -227,7 +201,7 @@ DPRINT("No current process\n"); if (Address < (ULONG_PTR)MmSystemRangeStart) { - return(STATUS_UNSUCCESSFUL); + return(STATUS_ACCESS_VIOLATION); } }
@@ -242,7 +216,7 @@ if (Mode != KernelMode) { CPRINT("Address: %x\n", Address); - return(STATUS_UNSUCCESSFUL); + return(STATUS_ACCESS_VIOLATION); } AddressSpace = MmGetKernelAddressSpace(); } @@ -268,7 +242,7 @@ { MmUnlockAddressSpace(AddressSpace); } - return (STATUS_UNSUCCESSFUL); + return (STATUS_ACCESS_VIOLATION); }
switch (MemoryArea->Type) @@ -280,7 +254,7 @@ }
case MEMORY_AREA_SYSTEM: - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_ACCESS_VIOLATION; break;
case MEMORY_AREA_SECTION_VIEW: @@ -309,7 +283,7 @@ break;
default: - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_ACCESS_VIOLATION; break; } } @@ -322,6 +296,67 @@ } 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 */
Modified: trunk/reactos/ntoskrnl/ntoskrnl.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl.rbuild?re... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl.rbuild (original) +++ trunk/reactos/ntoskrnl/ntoskrnl.rbuild Fri Dec 29 21:49:00 2006 @@ -257,9 +257,7 @@ <directory name="mm"> <if property="ARCH" value="i386"> <directory name="i386"> - <file>memsafe.s</file> <file>page.c</file> - <file>pfault.c</file> </directory> </if> <file>anonmem.c</file>
Modified: trunk/reactos/ntoskrnl/ob/oblife.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/oblife.c?rev=25... ============================================================================== --- trunk/reactos/ntoskrnl/ob/oblife.c (original) +++ trunk/reactos/ntoskrnl/ob/oblife.c Fri Dec 29 21:49:00 2006 @@ -134,8 +134,9 @@ }
VOID -FASTCALL -ObpDeleteObject(IN PVOID Object) +NTAPI +ObpDeleteObject(IN PVOID Object, + IN BOOLEAN CalledFromWorkerThread) { POBJECT_HEADER Header; POBJECT_TYPE ObjectType; @@ -203,12 +204,15 @@ NTAPI ObpReapObject(IN PVOID Parameter) { - POBJECT_HEADER ReapObject; + POBJECT_HEADER ReapObject = (PVOID)1; PVOID NextObject;
/* Start reaping */ - while ((ReapObject = InterlockedExchangePointer(&ObpReaperList, NULL))) - { + do + { + /* Get the reap object */ + ReapObject = InterlockedExchangePointer(&ObpReaperList, ReapObject); + /* Start deletion loop */ do { @@ -216,12 +220,13 @@ NextObject = ReapObject->NextToFree;
/* Delete the object */ - ObpDeleteObject(&ReapObject->Body); + ObpDeleteObject(&ReapObject->Body, TRUE);
/* Move to the next one */ ReapObject = NextObject; - } while (NextObject); - } + } while ((NextObject) && (NextObject != (PVOID)1)); + } while ((ObpReaperList != (PVOID)1) || + (InterlockedCompareExchange((PLONG)&ObpReaperList, 0, 1) != 1)); }
/*++
Modified: trunk/reactos/ntoskrnl/ob/obref.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obref.c?rev=252... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obref.c (original) +++ trunk/reactos/ntoskrnl/ob/obref.c Fri Dec 29 21:49:00 2006 @@ -50,21 +50,27 @@
VOID NTAPI -ObpDeferObjectDeletion(IN PVOID Object) -{ - POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object); - - /* Add us to the list */ +ObpDeferObjectDeletion(IN POBJECT_HEADER Header) +{ + PVOID Entry, NewEntry; + + /* Loop while trying to update the list */ do { - Header->NextToFree = ObpReaperList; + /* Get the current entry */ + Entry = ObpReaperList; + + /* Link our object to the list */ + Header->NextToFree = Entry; + NewEntry = Header; + + /* Update the list */ } while (InterlockedCompareExchangePointer(&ObpReaperList, - Header, - Header->NextToFree) != - Header->NextToFree); - - /* Queue the work item */ - ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue); + NewEntry, + Entry) != Entry); + + /* Queue the work item if needed */ + if (!Entry) ExQueueWorkItem(&ObpReaperWorkItem, CriticalWorkQueue); }
LONG @@ -91,11 +97,7 @@
/* Check whether the object can now be deleted. */ NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count); - if (!Count) - { - /* Add us to the deferred deletion list */ - ObpDeferObjectDeletion(Object); - } + if (!Count) ObpDeferObjectDeletion(Header);
/* Return the current count */ return NewCount; @@ -308,12 +310,12 @@ if (KeGetCurrentIrql() == PASSIVE_LEVEL) { /* Remove the object */ - ObpDeleteObject(Object); + ObpDeleteObject(Object, FALSE); } else { /* Add us to the deferred deletion list */ - ObpDeferObjectDeletion(Object); + ObpDeferObjectDeletion(Header); } }
@@ -325,11 +327,13 @@ NTAPI ObDereferenceObjectDeferDelete(IN PVOID Object) { + POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object); + /* Check whether the object can now be deleted. */ - if (!(InterlockedDecrement(&OBJECT_TO_OBJECT_HEADER(Object)->PointerCount))) + if (!InterlockedDecrement(&Header->PointerCount)) { /* Add us to the deferred deletion list */ - ObpDeferObjectDeletion(Object); + ObpDeferObjectDeletion(Header); } }
Modified: trunk/reactos/ntoskrnl/vdm/vdmexec.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/vdm/vdmexec.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/vdm/vdmexec.c (original) +++ trunk/reactos/ntoskrnl/vdm/vdmexec.c Fri Dec 29 21:49:00 2006 @@ -50,7 +50,7 @@
/* Make sure that we're at APC_LEVEL and that this is a valid frame */ ASSERT_IRQL(APC_LEVEL); - ASSERT(TrapFrame->DbgArgMark = 0xBADB0D00); + ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
/* Check if this is a V86 frame */ if (TrapFrame->EFlags & EFLAGS_V86_MASK) @@ -61,9 +61,9 @@ OutContext->SegEs = TrapFrame->V86Es; OutContext->SegDs = TrapFrame->V86Ds; } - else if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK)) - { - /* This was user mode, copy segment registers */ + else if (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK)) + { + /* This was kernel mode, copy segment registers */ OutContext->SegGs = TrapFrame->SegGs; OutContext->SegFs = TrapFrame->SegFs; OutContext->SegEs = TrapFrame->SegEs;