#define NDEBUG
#include <debug.h>
+VOID KiFastCallEntry(VOID);
+VOID KiFastCallEntryWithSingleStep(VOID);
+
/* GLOBALS ********************************************************************/
UCHAR KiTrapPrefixTable[] =
/* TRAP EXIT CODE *************************************************************/
-BOOLEAN
FORCEINLINE
+BOOLEAN
KiVdmTrap(IN PKTRAP_FRAME TrapFrame)
{
/* Either the V8086 flag is on, or this is user-mode with a VDM */
((KiUserTrap(TrapFrame)) && (PsGetCurrentProcess()->VdmObjects)));
}
-BOOLEAN
FORCEINLINE
+BOOLEAN
KiV86Trap(IN PKTRAP_FRAME TrapFrame)
{
/* Check if the V8086 flag is on */
return ((TrapFrame->EFlags & EFLAGS_V86_MASK) != 0);
}
-BOOLEAN
FORCEINLINE
+BOOLEAN
KiIsFrameEdited(IN PKTRAP_FRAME TrapFrame)
{
/* An edited frame changes esp. It is marked by clearing the bits
return ((TrapFrame->SegCs & FRAME_EDITED) == 0);
}
-VOID
FORCEINLINE
+VOID
KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode)
{
/* Disable interrupts until we return */
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
{
/* Check if the frame was from user mode or v86 mode */
- if ((TrapFrame->SegCs & MODE_MASK) ||
+ if (KiUserTrap(TrapFrame) ||
(TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* Handle debug registers */
if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
/* Check for user mode exit */
- if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame);
+ if (KiUserTrap(TrapFrame)) KiTrapReturn(TrapFrame);
/* Check for edited frame */
if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame);
+ /* Check if we have single stepping enabled */
+ if (TrapFrame->EFlags & EFLAGS_TF) KiTrapReturnNoSegments(TrapFrame);
+
/* Exit the trap to kernel mode */
- KiTrapReturnNoSegments(TrapFrame);
+ KiTrapReturnNoSegmentsRet8(TrapFrame);
}
DECLSPEC_NORETURN
{
ASSERT((TrapFrame->EFlags & EFLAGS_V86_MASK) == 0);
ASSERT(!KiIsFrameEdited(TrapFrame));
-
+
/* Copy the status into EAX */
TrapFrame->Eax = Status;
-
+
/* Common trap exit code */
KiCommonExit(TrapFrame, FALSE);
-
+
/* Restore previous mode */
KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode;
/* Check for user mode exit */
- if (TrapFrame->SegCs & MODE_MASK)
+ if (KiUserTrap(TrapFrame))
{
/* Check if we were single stepping */
if (TrapFrame->EFlags & EFLAGS_TF)
{
/* Common trap exit code */
KiCommonExit(TrapFrame, FALSE);
-
+
/* Restore previous mode */
KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode;
-
+
/* Check if this was a V8086 trap */
if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
/* Check for user mode exit */
- if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame);
+ if (KiUserTrap(TrapFrame)) KiTrapReturn(TrapFrame);
/* Check for edited frame */
if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame);
+ /* Check if we have single stepping enabled */
+ if (TrapFrame->EFlags & EFLAGS_TF) KiTrapReturnNoSegments(TrapFrame);
+
/* Exit the trap to kernel mode */
- KiTrapReturnNoSegments(TrapFrame);
+ KiTrapReturnNoSegmentsRet8(TrapFrame);
}
IN PFX_SAVE_AREA SaveArea)
{
ULONG Cr0, Mask, Error, ErrorOffset, DataOffset;
-
+
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
{
/* Kernel might've tripped a delayed error */
SaveArea->Cr0NpxState |= CR0_TS;
-
+
/* Only valid if it happened during a restore */
//if ((PVOID)TrapFrame->Eip == FrRestore)
{
/* Clear the TS bit and re-enable interrupts */
SaveArea->Cr0NpxState &= ~CR0_TS;
_enable();
-
+
/* Check if we should get the FN or FX error */
if (KeI386FxsrPresent)
{
/* Get it from FX */
Mask = SaveArea->U.FxArea.ControlWord;
Error = SaveArea->U.FxArea.StatusWord;
-
+
/* Get the FPU exception address too */
ErrorOffset = SaveArea->U.FxArea.ErrorOffset;
DataOffset = SaveArea->U.FxArea.DataOffset;
/* Get it from FN */
Mask = SaveArea->U.FnArea.ControlWord;
Error = SaveArea->U.FnArea.StatusWord;
-
+
/* Get the FPU exception address too */
ErrorOffset = SaveArea->U.FnArea.ErrorOffset;
DataOffset = SaveArea->U.FnArea.DataOffset;
0,
TrapFrame);
}
-
+
/* Check for divide by zero */
if (Error & FSW_ZERO_DIVIDE)
{
0,
TrapFrame);
}
-
+
/* Check for denormal */
if (Error & FSW_DENORMAL)
{
0,
TrapFrame);
}
-
+
/* Check for overflow */
if (Error & FSW_OVERFLOW)
{
0,
TrapFrame);
}
-
+
/* Check for underflow */
if (Error & FSW_UNDERFLOW)
{
0,
TrapFrame);
}
-
+
/* Unknown FPU fault */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 1, Error, 0, 0, TrapFrame);
}
{
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
/* Enable interrupts */
_enable();
-
+
/* Dispatch the exception */
KiDispatchException0Args(STATUS_INTEGER_DIVIDE_BY_ZERO,
TrapFrame->Eip,
{
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ /* Check if this was a single step after sysenter */
+ if (TrapFrame->Eip == (ULONG)KiFastCallEntry)
+ {
+ /* Disable single stepping */
+ TrapFrame->EFlags &= ~EFLAGS_TF;
+
+ /* Re-enter at the alternative sysenter entry point */
+ TrapFrame->Eip = (ULONG)KiFastCallEntryWithSingleStep;
+
+ /* End this trap */
+ KiEoiHelper(TrapFrame);
+ }
+
/* Enable interrupts if the trap came from user-mode */
if (KiUserTrap(TrapFrame)) _enable();
-
+
/* Mask out trap flag and dispatch the exception */
TrapFrame->EFlags &= ~EFLAGS_TF;
KiDispatchException0Args(STATUS_SINGLE_STEP,
PKGDTENTRY TssGdt;
KTRAP_FRAME TrapFrame;
KIRQL OldIrql;
-
+
//
// In some sort of strange recursion case, we might end up here with the IF
// flag incorrectly on the interrupt frame -- during a normal NMI this would
Tss = PCR->TSS;
Thread = ((PKIPCR)PCR)->PrcbData.CurrentThread;
Process = Thread->ApcState.Process;
-
+
//
// Save data usually not in the TSS
//
Tss->CR3 = Process->DirectoryTableBase[0];
Tss->IoMapBase = Process->IopmOffset;
Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
-
+
//
// Now get the base address of the NMI TSS
//
NmiTss = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
TssGdt->HighWord.Bytes.BaseMid << 16 |
TssGdt->HighWord.Bytes.BaseHi << 24);
-
+
//
// Switch to it and activate it, masking off the nested flag
//
TssGdt->HighWord.Bits.Dpl = 0;
TssGdt->HighWord.Bits.Pres = 1;
TssGdt->HighWord.Bits.Type = I386_TSS;
-
+
//
// Now build the trap frame based on the original TSS
//
TrapFrame.SegGs = Tss->Gs;
TrapFrame.DbgEip = Tss->Eip;
TrapFrame.DbgEbp = Tss->Ebp;
-
+
//
// Store the trap frame in the KPRCB
//
KiSaveProcessorState(&TrapFrame, NULL);
-
+
//
// Call any registered NMI handlers and see if they handled it or not
//
// Restore original TSS
//
PCR->TSS = Tss;
-
+
//
// Set it back to busy
//
TssGdt->HighWord.Bits.Dpl = 0;
TssGdt->HighWord.Bits.Pres = 1;
TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
-
+
//
// Restore nested flag
//
__writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
-
+
//
// Handled, return from interrupt
//
KiIret();
}
-
+
//
// Unhandled: crash the system
//
{
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Continue with the common handler */
KiDebugHandler(TrapFrame, BREAKPOINT_BREAK, 0, 0);
}
{
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
/* Enable interrupts */
_enable();
-
+
/* Dispatch the exception */
KiDispatchException0Args(STATUS_INTEGER_OVERFLOW,
TrapFrame->Eip - 1,
{
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
-
+
/* Check for kernel-mode fault */
if (!KiUserTrap(TrapFrame)) KiSystemFatalException(EXCEPTION_BOUND_CHECK, TrapFrame);
/* Enable interrupts */
_enable();
-
+
/* Dispatch the exception */
KiDispatchException0Args(STATUS_ARRAY_BOUNDS_EXCEEDED,
TrapFrame->Eip,
PUCHAR Instruction;
ULONG i;
KIRQL OldIrql;
-
+
/* Check for V86 GPF */
if (__builtin_expect(KiV86Trap(TrapFrame), 1))
{
/* Enter V86 trap */
KiEnterV86Trap(TrapFrame);
-
+
/* Must be a VDM process */
if (__builtin_expect(!PsGetCurrentProcess()->VdmObjects, 0))
{
/* Enable interrupts */
_enable();
-
+
/* Setup illegal instruction fault */
KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
TrapFrame->Eip,
TrapFrame);
}
-
+
/* Go to APC level */
OldIrql = KfRaiseIrql(APC_LEVEL);
_enable();
-
+
/* Check for BOP */
if (!VdmDispatchBop(TrapFrame))
{
/* Should only happen in VDM mode */
UNIMPLEMENTED_FATAL();
}
-
+
/* Bring IRQL back */
KfLowerIrql(OldIrql);
_disable();
-
+
/* Do a quick V86 exit if possible */
KiExitV86Trap(TrapFrame);
}
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Enable interrupts */
Instruction = (PUCHAR)TrapFrame->Eip;
_enable();
-
+
/* Check for user trap */
if (KiUserTrap(TrapFrame))
{
/* FIXME: Use SEH */
-
+
/* Scan next 4 opcodes */
for (i = 0; i < 4; i++)
{
TrapFrame);
}
}
-
+
/* FIXME: SEH ends here */
}
-
+
/* Kernel-mode or user-mode fault (but not LOCK) */
KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
TrapFrame->Eip,
TrapFrame);
-
+
}
DECLSPEC_NORETURN
PKTHREAD Thread, NpxThread;
PFX_SAVE_AREA SaveArea, NpxSaveArea;
ULONG Cr0;
-
+
/* Save trap frame */
KiEnterTrap(TrapFrame);
/* Not implemented */
UNIMPLEMENTED_FATAL();
}
-
+
/* Save CR0 and check NPX state */
Cr0 = __readcr0();
if (Thread->NpxState != NPX_STATE_LOADED)
/* Update CR0 */
Cr0 &= ~(CR0_MP | CR0_EM | CR0_TS);
__writecr0(Cr0);
-
+
/* Get the NPX thread */
NpxThread = KeGetCurrentPrcb()->NpxThread;
if (NpxThread)
{
/* Get the NPX frame */
NpxSaveArea = KiGetThreadNpxArea(NpxThread);
-
+
/* Save FPU state */
DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea);
//Ke386SaveFpuState(NpxSaveArea);
/* Update NPX state */
NpxThread->NpxState = NPX_STATE_NOT_LOADED;
}
-
+
/* Load FPU state */
//Ke386LoadFpuState(SaveArea);
-
+
/* Update NPX state */
Thread->NpxState = NPX_STATE_LOADED;
KeGetCurrentPrcb()->NpxThread = Thread;
-
+
/* Enable interrupts */
_enable();
-
+
/* Check if CR0 needs to be reloaded due to context switch */
if (!SaveArea->Cr0NpxState) KiEoiHelper(TrapFrame);
-
+
/* Otherwise, we need to reload CR0, disable interrupts */
_disable();
-
+
/* Reload CR0 */
Cr0 = __readcr0();
Cr0 |= SaveArea->Cr0NpxState;
__writecr0(Cr0);
-
+
/* Now restore interrupts and check for TS */
_enable();
if (Cr0 & CR0_TS) KiEoiHelper(TrapFrame);
-
+
/* We're still here -- clear TS and try again */
__writecr0(__readcr0() &~ CR0_TS);
_disable();
break;
}
}
-
+
/* TS should not be set */
if (Cr0 & CR0_TS)
{
__writecr0(__readcr0() &~ CR0_TS);
KiEoiHelper(TrapFrame);
}
-
+
/* Otherwise, something strange is going on */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 2, Cr0, 0, 0, TrapFrame);
}
-
+
/* It's not a delayed load, so process this trap as an NPX fault */
KiNpxHandler(TrapFrame, Thread, SaveArea);
}
PUCHAR Instructions;
UCHAR Instruction = 0;
KIRQL OldIrql;
-
+
/* Check for V86 GPF */
if (__builtin_expect(KiV86Trap(TrapFrame), 1))
{
/* Enter V86 trap */
KiEnterV86Trap(TrapFrame);
-
+
/* Must be a VDM process */
if (__builtin_expect(!PsGetCurrentProcess()->VdmObjects, 0))
{
/* Enable interrupts */
_enable();
-
+
/* Setup illegal instruction fault */
KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
TrapFrame->Eip,
TrapFrame);
}
-
+
/* Go to APC level */
OldIrql = KfRaiseIrql(APC_LEVEL);
_enable();
-
+
/* Handle the V86 opcode */
if (__builtin_expect(Ki386HandleOpcodeV86(TrapFrame) == 0xFF, 0))
{
/* Should only happen in VDM mode */
UNIMPLEMENTED_FATAL();
}
-
+
/* Bring IRQL back */
KfLowerIrql(OldIrql);
_disable();
-
+
/* Do a quick V86 exit if possible */
KiExitV86Trap(TrapFrame);
}
-
+
/* Save trap frame */
KiEnterTrap(TrapFrame);
{
/* Should not be VDM */
ASSERT(KiVdmTrap(TrapFrame) == FALSE);
-
+
/* Enable interrupts and check error code */
_enable();
if (!TrapFrame->ErrCode)
{
/* FIXME: Use SEH */
Instructions = (PUCHAR)TrapFrame->Eip;
-
+
/* Scan next 15 bytes */
for (i = 0; i < 15; i++)
{
break;
}
}
-
+
/* Is this NOT any prefix instruction? */
if (j == sizeof(KiTrapPrefixTable))
{
break;
}
}
-
+
/* If all we found was prefixes, then this instruction is too long */
if (i == 15)
{
TrapFrame->Eip,
TrapFrame);
}
-
+
/* Check for privileged instructions */
- DPRINT("Instruction (%d) at fault: %lx %lx %lx %lx\n",
+ DPRINT("Instruction (%lu) at fault: %lx %lx %lx %lx\n",
i,
Instructions[i],
Instructions[i + 1],
}
}
}
-
+
/* So now... was the instruction privileged or not? */
if (Privileged)
{
TrapFrame);
}
}
-
+
/* If we got here, send an access violation */
KiDispatchException2Args(STATUS_ACCESS_VIOLATION,
TrapFrame->Eip,
* when the user is purposedly trying to create one from kernel-mode, so
* we should probably table this for now since it's not a "real" issue.
*/
-
+
/*
* NOTE2: Another scenario is the IRET during a V8086 restore (BIOS Call)
* which will cause a GPF since the trap frame is a total mess (on purpose)
UNIMPLEMENTED_FATAL();
}
}
-
+
/* So since we're not dealing with the above case, check for RDMSR/WRMSR */
if ((Instructions[0] == 0xF) && // 2-byte opcode
((Instructions[1] == 0x32) || // RDMSR
/* Whatever it is, we can't handle it */
KiSystemFatalException(EXCEPTION_GP_FAULT, TrapFrame);
}
-
+
/* Return to where we came from */
KiTrapReturn(TrapFrame);
}
/* Continue execution */
KiEoiHelper(TrapFrame);
}
+ else
+ {
+#if 0
+ /* Do what windows does and issue an invalid access violation */
+ KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION,
+ TrapFrame->Eip,
+ TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ Cr2,
+ TrapFrame);
+#endif
+ }
}
/* Call the access fault handler */
Status = MmAccessFault(TrapFrame->ErrCode & 1,
(PVOID)Cr2,
- TrapFrame->SegCs & MODE_MASK,
+ KiUserTrap(TrapFrame),
TrapFrame);
if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame);
-
+
/* Check for syscall fault */
#if 0
if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) ||
#endif
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
-
+
/* Either kernel or user trap (non VDM) so dispatch exception */
if (Status == STATUS_ACCESS_VIOLATION)
{
Cr2,
TrapFrame);
}
-
+
/* Only other choice is an in-page error, with 3 parameters */
KiDispatchExceptionFromTrapFrame(STATUS_IN_PAGE_ERROR,
TrapFrame->Eip,
{
PKTHREAD Thread;
PFX_SAVE_AREA SaveArea;
-
+
/* Save trap frame */
KiEnterTrap(TrapFrame);
/* It isn't, enable interrupts and set delayed error */
_enable();
SaveArea->Cr0NpxState |= CR0_TS;
-
+
/* End trap */
KiEoiHelper(TrapFrame);
}
-
+
/* Otherwise, proceed with NPX fault handling */
KiNpxHandler(TrapFrame, Thread, SaveArea);
}
PKTHREAD Thread;
PFX_SAVE_AREA SaveArea;
ULONG Cr0, MxCsrMask, Error;
-
+
/* Save trap frame */
KiEnterTrap(TrapFrame);
/* Kernel should not fault on XMMI */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 2, TrapFrame);
}
-
+
/* Update CR0 */
Cr0 = __readcr0();
Cr0 &= ~(CR0_MP | CR0_EM | CR0_TS);
__writecr0(Cr0);
-
+
/* Save FPU state */
Ke386SaveFpuState(SaveArea);
-
+
/* Mark CR0 state dirty */
Cr0 |= NPX_STATE_NOT_LOADED;
Cr0 |= SaveArea->Cr0NpxState;
__writecr0(Cr0);
-
+
/* Update NPX state */
Thread->NpxState = NPX_STATE_NOT_LOADED;
KeGetCurrentPrcb()->NpxThread = NULL;
-
+
/* Clear the TS bit and re-enable interrupts */
SaveArea->Cr0NpxState &= ~CR0_TS;
_enable();
/* Now look at MxCsr to get the mask of errors we should care about */
MxCsrMask = ~((USHORT)SaveArea->U.FxArea.MXCsr >> 7);
-
+
/* Get legal exceptions that software should handle */
Error = (USHORT)SaveArea->U.FxArea.MXCsr & (FSW_INVALID_OPERATION |
FSW_DENORMAL |
0,
TrapFrame);
}
-
+
/* Unknown XMMI fault */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 1, TrapFrame);
}
/* SOFTWARE SERVICES **********************************************************/
+VOID
+FASTCALL
+KiRaiseSecurityCheckFailureHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Save trap frame */
+ KiEnterTrap(TrapFrame);
+
+ /* Decrement EIP to point to the INT29 instruction (2 bytes, not 1 like INT3) */
+ TrapFrame->Eip -= 2;
+
+ /* Check if this is a user trap */
+ if (KiUserTrap(TrapFrame))
+ {
+ /* Dispatch exception to user mode */
+ KiDispatchException1Args(STATUS_STACK_BUFFER_OVERRUN,
+ TrapFrame->Eip,
+ TrapFrame->Ecx,
+ TrapFrame);
+ }
+ else
+ {
+ EXCEPTION_RECORD ExceptionRecord;
+
+ /* Bugcheck the system */
+ ExceptionRecord.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
+ ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ ExceptionRecord.ExceptionRecord = NULL;
+ ExceptionRecord.ExceptionAddress = (PVOID)TrapFrame->Eip;
+ ExceptionRecord.NumberParameters = 1;
+ ExceptionRecord.ExceptionInformation[0] = TrapFrame->Ecx;
+
+ KeBugCheckWithTf(KERNEL_SECURITY_CHECK_FAILURE,
+ TrapFrame->Ecx,
+ (ULONG_PTR)TrapFrame,
+ (ULONG_PTR)&ExceptionRecord,
+ 0,
+ TrapFrame);
+ }
+}
+
VOID
FASTCALL
KiGetTickCountHandler(IN PKTRAP_FRAME TrapFrame)
FASTCALL
KiCallbackReturnHandler(IN PKTRAP_FRAME TrapFrame)
{
- UNIMPLEMENTED_DBGBREAK();
+ NTSTATUS Status;
+
+ /* Pass the register parameters to NtCallbackReturn.
+ Result pointer is in ecx, result length in edx, status in eax */
+ Status = NtCallbackReturn((PVOID)TrapFrame->Ecx,
+ TrapFrame->Edx,
+ TrapFrame->Eax);
+
+ /* If we got here, something went wrong. Return an error to the caller */
+ KiServiceExit(TrapFrame, Status);
}
DECLSPEC_NORETURN
{
/* Save trap frame */
KiEnterTrap(TrapFrame);
-
+
/* Increment EIP to skip the INT3 instruction */
TrapFrame->Eip++;
-
+
/* Continue with the common handler */
KiDebugHandler(TrapFrame, TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
}
DECLSPEC_NORETURN
VOID
-FORCEINLINE
-KiSystemCall(IN PKTRAP_FRAME TrapFrame,
- IN PVOID Arguments)
+FASTCALL
+KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
+ IN PVOID Arguments)
{
PKTHREAD Thread;
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
ULONG Id, Offset, StackBytes, Result;
PVOID Handler;
ULONG SystemCallNumber = TrapFrame->Eax;
-
+
/* Get the current thread */
Thread = KeGetCurrentThread();
TrapFrame->Dr7 = 0;
/* Check if the frame was from user mode */
- if (TrapFrame->SegCs & MODE_MASK)
+ if (KiUserTrap(TrapFrame))
{
/* Check for active debugging */
if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
/* Decode the system call number */
Offset = (SystemCallNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
Id = SystemCallNumber & SERVICE_NUMBER_MASK;
-
+
/* Get descriptor table */
DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
goto ExitCall;
}
}
-
+
/* Check if this is a GUI call */
if (__builtin_expect(Offset & SERVICE_TABLE_TEST, 0))
{
/* Get the batch count and flush if necessary */
if (NtCurrentTeb()->GdiBatchCount) KeGdiFlushUserBatch();
}
-
+
/* Increase system call count */
KeGetCurrentPrcb()->KeSystemCalls++;
-
+
/* FIXME: Increase individual counts on debug systems */
//KiIncreaseSystemCallCount(DescriptorTable, Id);
-
+
/* Get stack bytes */
StackBytes = DescriptorTable->Number[Id];
-
+
/* Probe caller stack */
if (__builtin_expect((Arguments < (PVOID)MmUserProbeAddress) && !(KiUserTrap(TrapFrame)), 0))
{
/* Access violation */
UNIMPLEMENTED_FATAL();
}
-
+
/* Call pre-service debug hook */
KiDbgPreServiceHook(SystemCallNumber, Arguments);
/* Get the handler and make the system call */
Handler = (PVOID)DescriptorTable->Base[Id];
Result = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
-
+
/* Call post-service debug hook */
Result = KiDbgPostServiceHook(SystemCallNumber, Result);
/* Make sure we're exiting correctly */
KiExitSystemCallDebugChecks(Id, TrapFrame);
-
+
/* Restore the old trap frame */
ExitCall:
Thread->TrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
KiServiceExit(TrapFrame, Result);
}
-DECLSPEC_NORETURN
-VOID
-FASTCALL
-KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
- IN PVOID Arguments)
-{
- /* Call the shared handler (inline) */
- KiSystemCall(TrapFrame, Arguments);
-}
-
-DECLSPEC_NORETURN
-VOID
-FASTCALL
-KiFastCallEntryHandler(IN PKTRAP_FRAME TrapFrame,
- IN PVOID Arguments)
-{
- /* Set up a fake INT Stack and enable interrupts */
- TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
- TrapFrame->HardwareEsp = (ULONG_PTR)Arguments;
- TrapFrame->EFlags = __readeflags() | EFLAGS_INTERRUPT_MASK;
- TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
- TrapFrame->Eip = SharedUserData->SystemCallReturn;
- TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
- __writeeflags(0x2);
-
- /* Arguments are actually 2 frames down (because of the double indirection) */
- Arguments = (PVOID)(TrapFrame->HardwareEsp + 8);
-
- /* Call the shared handler (inline) */
- KiSystemCall(TrapFrame, Arguments);
-}
-
/*
* @implemented
*/