#define NDEBUG
#include <debug.h>
-VOID KiFastCallEntry(VOID);
-VOID KiFastCallEntryWithSingleStep(VOID);
+VOID __cdecl KiFastCallEntry(VOID);
+VOID __cdecl KiFastCallEntryWithSingleStep(VOID);
+
+extern PVOID KeUserPopEntrySListFault;
+extern PVOID KeUserPopEntrySListResume;
+extern PVOID FrRestore;
+VOID FASTCALL Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea);
/* GLOBALS ********************************************************************/
};
PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
-#if DBG && !defined(_WINKD_)
+#if DBG && defined(_M_IX86) && !defined(_WINKD_)
PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
#endif
-#if TRAP_DEBUG
+#if DBG
BOOLEAN StopChecking = FALSE;
#endif
{
/* We can use the sysexit handler */
KiFastCallExitHandler(TrapFrame);
+ UNREACHABLE;
}
}
IN ULONG Parameter3)
{
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Enable interrupts if the trap came from user-mode */
if (KiUserTrap(TrapFrame)) _enable();
ULONG Cr0, Mask, Error, ErrorOffset, DataOffset;
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Check for kernel trap */
if (!KiUserTrap(TrapFrame))
SaveArea->Cr0NpxState |= CR0_TS;
/* Only valid if it happened during a restore */
- //if ((PVOID)TrapFrame->Eip == FrRestore)
+ if ((PVOID)TrapFrame->Eip == FrRestore)
{
/* It did, so just skip the instruction */
- //TrapFrame->Eip += 3; /* sizeof(FRSTOR) */
- //KiEoiHelper(TrapFrame);
+ TrapFrame->Eip += 3; /* Size of FRSTOR instruction */
+ KiEoiHelper(TrapFrame);
}
}
- /* User or kernel trap -- get ready to issue an exception */
- //if (Thread->NpxState == NPX_STATE_NOT_LOADED)
+ /* User or kernel trap -- check if we need to unload the current state */
+ if (Thread->NpxState == NPX_STATE_LOADED)
{
/* Update CR0 */
Cr0 = __readcr0();
}
/* Get legal exceptions that software should handle */
- /* We do this by first masking off from the Mask the bits we need, */
- /* This is done so we can keep the FSW_STACK_FAULT bit in Error. */
Mask &= (FSW_INVALID_OPERATION |
FSW_DENORMAL |
FSW_ZERO_DIVIDE |
/* Check for invalid operation */
if (Error & FSW_INVALID_OPERATION)
{
- /* NOTE: Stack fault is handled differently than any other case. */
- /* 1. It's only raised for invalid operation. */
- /* 2. It's only raised if invalid operation is not masked. */
+ /*
+ * Now check if this is actually a Stack Fault. This is needed because
+ * on x86 the Invalid Operation error is set for Stack Check faults as well.
+ */
if (Error & FSW_STACK_FAULT)
{
/* Issue stack check fault */
DataOffset,
TrapFrame);
}
-
- /* Issue fault */
- KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
- ErrorOffset,
- 0,
- TrapFrame);
+ else
+ {
+ /* This is an invalid operation fault after all, so raise that instead */
+ KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
+ ErrorOffset,
+ 0,
+ TrapFrame);
+ }
}
/* Check for divide by zero */
KiEnterTrap(TrapFrame);
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Enable interrupts */
_enable();
KiEnterTrap(TrapFrame);
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Check if this was a single step after sysenter */
if (TrapFrame->Eip == (ULONG)KiFastCallEntry)
TrapFrame);
}
-DECLSPEC_NORETURN
VOID
__cdecl
-KiTrap02(VOID)
+KiTrap02Handler(VOID)
{
PKTSS Tss, NmiTss;
PKTHREAD Thread;
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
- // normally already be set.
- //
- // For sanity's sake, make sure interrupts are disabled for sure.
- // NMIs will already be since the CPU does it for us.
- //
+ /*
+ * 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
+ * normally already be set.
+ *
+ * For sanity's sake, make sure interrupts are disabled for sure.
+ * NMIs will already be since the CPU does it for us.
+ */
_disable();
- //
- // Get the current TSS, thread, and process
- //
- Tss = PCR->TSS;
- Thread = ((PKIPCR)PCR)->PrcbData.CurrentThread;
+ /* Get the current TSS, thread, and process */
+ Tss = KeGetPcr()->TSS;
+ Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
Process = Thread->ApcState.Process;
- //
- // Save data usually not in the TSS
- //
+ /* Save data usually not present 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
- //
+ /* Now get the base address of the NMI TSS */
TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
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
- //
- // Note that in reality, we are already on the NMI tss -- we just need to
- // update the PCR to reflect this
- //
- PCR->TSS = NmiTss;
+ /*
+ * Switch to it and activate it, masking off the nested flag.
+ *
+ * Note that in reality, we are already on the NMI TSS -- we just
+ * need to update the PCR to reflect this.
+ */
+ KeGetPcr()->TSS = NmiTss;
__writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
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
- //
- // The CPU does a hardware "Context switch" / task switch of sorts and so it
- // takes care of saving our context in the normal TSS.
- //
- // We just have to go get the values...
- //
+ /*
+ * Now build the trap frame based on the original TSS.
+ *
+ * The CPU does a hardware "Context switch" / task switch of sorts
+ * and so it takes care of saving our context in the normal TSS.
+ *
+ * We just have to go get the values...
+ */
RtlZeroMemory(&TrapFrame, sizeof(KTRAP_FRAME));
TrapFrame.HardwareSegSs = Tss->Ss0;
TrapFrame.HardwareEsp = Tss->Esp0;
TrapFrame.Esi = Tss->Esi;
TrapFrame.Edi = Tss->Edi;
TrapFrame.SegFs = Tss->Fs;
- TrapFrame.ExceptionList = PCR->NtTib.ExceptionList;
- TrapFrame.PreviousPreviousMode = -1;
+ TrapFrame.ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ TrapFrame.PreviousPreviousMode = (ULONG)-1;
TrapFrame.Eax = Tss->Eax;
TrapFrame.Ecx = Tss->Ecx;
TrapFrame.Edx = Tss->Edx;
TrapFrame.DbgEip = Tss->Eip;
TrapFrame.DbgEbp = Tss->Ebp;
- //
- // Store the trap frame in the KPRCB
- //
+ /* Store the trap frame in the KPRCB */
KiSaveProcessorState(&TrapFrame, NULL);
- //
- // Call any registered NMI handlers and see if they handled it or not
- //
+ /* Call any registered NMI handlers and see if they handled it or not */
if (!KiHandleNmi())
{
- //
- // They did not, so call the platform HAL routine to bugcheck the system
- //
- // Make sure the HAL believes it's running at HIGH IRQL... we can't use
- // the normal APIs here as playing with the IRQL could change the system
- // state
- //
- OldIrql = PCR->Irql;
- PCR->Irql = HIGH_LEVEL;
+ /*
+ * They did not, so call the platform HAL routine to bugcheck the system
+ *
+ * Make sure the HAL believes it's running at HIGH IRQL... we can't use
+ * the normal APIs here as playing with the IRQL could change the system
+ * state.
+ */
+ OldIrql = KeGetPcr()->Irql;
+ KeGetPcr()->Irql = HIGH_LEVEL;
HalHandleNMI(NULL);
- PCR->Irql = OldIrql;
+ KeGetPcr()->Irql = OldIrql;
}
- //
- // Although the CPU disabled NMIs, we just did a BIOS Call, which could've
- // totally changed things.
- //
- // We have to make sure we're still in our original NMI -- a nested NMI
- // will point back to the NMI TSS, and in that case we're hosed.
- //
- if (PCR->TSS->Backlink != KGDT_NMI_TSS)
+ /*
+ * Although the CPU disabled NMIs, we just did a BIOS call, which could've
+ * totally changed things.
+ *
+ * We have to make sure we're still in our original NMI -- a nested NMI
+ * will point back to the NMI TSS, and in that case we're hosed.
+ */
+ if (KeGetPcr()->TSS->Backlink == KGDT_NMI_TSS)
{
- //
- // 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 */
+ KiSystemFatalException(EXCEPTION_NMI, NULL);
}
- //
- // Unhandled: crash the system
- //
- KiSystemFatalException(EXCEPTION_NMI, NULL);
+ /* Restore original TSS */
+ KeGetPcr()->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 */
}
DECLSPEC_NORETURN
KiEnterTrap(TrapFrame);
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Enable interrupts */
_enable();
KiEnterTrap(TrapFrame);
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Check for kernel-mode fault */
if (!KiUserTrap(TrapFrame)) KiSystemFatalException(EXCEPTION_BOUND_CHECK, TrapFrame);
}
/* Go to APC level */
- OldIrql = KfRaiseIrql(APC_LEVEL);
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
_enable();
/* Check for BOP */
}
/* Bring IRQL back */
- KfLowerIrql(OldIrql);
+ KeLowerIrql(OldIrql);
_disable();
/* Do a quick V86 exit if possible */
KiEnterTrap(TrapFrame);
/* Try to handle NPX delay load */
- while (TRUE)
+ for (;;)
{
/* Get the current thread */
Thread = KeGetCurrentThread();
NpxSaveArea = KiGetThreadNpxArea(NpxThread);
/* Save FPU state */
- DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea);
- //Ke386SaveFpuState(NpxSaveArea);
+ Ke386SaveFpuState(NpxSaveArea);
/* Update NPX state */
NpxThread->NpxState = NPX_STATE_NOT_LOADED;
}
/* Load FPU state */
- //Ke386LoadFpuState(SaveArea);
+ Ke386LoadFpuState(SaveArea);
/* Update NPX state */
Thread->NpxState = NPX_STATE_LOADED;
{
/*
* If it's incorrectly set, then maybe the state is actually still valid
- * but we could've lock track of that due to a BIOS call.
+ * but we could have lost track of that due to a BIOS call.
* Make sure MP is still set, which should verify the theory.
*/
if (Cr0 & CR0_MP)
DECLSPEC_NORETURN
VOID
-FASTCALL
-KiTrap08Handler(IN PKTRAP_FRAME TrapFrame)
+__cdecl
+KiTrap08Handler(VOID)
{
- /* FIXME: Not handled */
- KiSystemFatalException(EXCEPTION_DOUBLE_FAULT, TrapFrame);
+ PKTSS Tss, DfTss;
+ PKTHREAD Thread;
+ PKPROCESS Process;
+ PKGDTENTRY TssGdt;
+
+ /* For sanity's sake, make sure interrupts are disabled */
+ _disable();
+
+ /* Get the current TSS, thread, and process */
+ Tss = KeGetPcr()->TSS;
+ Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
+ Process = Thread->ApcState.Process;
+
+ /* Save data usually not present 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 double-fault TSS */
+ TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_DF_TSS / sizeof(KGDTENTRY)];
+ DfTss = (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.
+ *
+ * Note that in reality, we are already on the double-fault TSS
+ * -- we just need to update the PCR to reflect this.
+ */
+ KeGetPcr()->TSS = DfTss;
+ __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
+ TssGdt->HighWord.Bits.Dpl = 0;
+ TssGdt->HighWord.Bits.Pres = 1;
+ // TssGdt->HighWord.Bits.Type &= ~0x2; /* I386_ACTIVE_TSS --> I386_TSS */
+ TssGdt->HighWord.Bits.Type = I386_TSS; // Busy bit cleared in the TSS selector.
+
+ /* Bugcheck the system */
+ KeBugCheckWithTf(UNEXPECTED_KERNEL_MODE_TRAP,
+ EXCEPTION_DOUBLE_FAULT,
+ (ULONG_PTR)Tss,
+ 0,
+ 0,
+ NULL);
}
DECLSPEC_NORETURN
KiEnterTrap(TrapFrame);
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Kill the system */
KiSystemFatalException(EXCEPTION_INVALID_TSS, TrapFrame);
}
/* Go to APC level */
- OldIrql = KfRaiseIrql(APC_LEVEL);
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
_enable();
/* Handle the V86 opcode */
}
/* Bring IRQL back */
- KfLowerIrql(OldIrql);
+ KeLowerIrql(OldIrql);
_disable();
/* Do a quick V86 exit if possible */
KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
{
PKTHREAD Thread;
+ BOOLEAN StoreInstruction;
ULONG_PTR Cr2;
NTSTATUS Status;
/* Save CR2 */
Cr2 = __readcr2();
- /* Enable interupts */
+ /* Enable interrupts */
_enable();
+ /* Interpret the error code */
+ StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
+
/* Check if we came in with interrupts disabled */
if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
{
/* This is completely illegal, bugcheck the system */
KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
Cr2,
- -1,
- TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ (ULONG_PTR)-1,
+ TrapFrame->ErrCode,
TrapFrame->Eip,
TrapFrame);
}
- /* Check for S-LIST fault in kernel mode */
- if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault)
+ /* Check for S-List fault
+
+ Explanation: An S-List fault can occur due to a race condition between 2
+ threads simultaneously trying to pop an element from the S-List. After
+ thread 1 has read the pointer to the top element on the S-List it is
+ preempted and thread 2 calls InterlockedPopEntrySlist on the same S-List,
+ removing the top element and freeing it's memory. After that thread 1
+ resumes and tries to read the address of the Next pointer from the top
+ element, which it assumes will be the next top element.
+ But since that memory has been freed, we get a page fault. To handle this
+ race condition, we let thread 1 repeat the operation.
+ We do NOT invoke the page fault handler in this case, since we do not
+ want to trigger any side effects, like paging or a guard page fault.
+
+ Sequence of operations:
+
+ Thread 1 : mov eax, [ebp] <= eax now points to the first element
+ Thread 1 : mov edx, [ebp + 4] <= edx is loaded with Depth and Sequence
+ *** preempted ***
+ Thread 2 : calls InterlockedPopEntrySlist, changing the top element
+ Thread 2 : frees the memory of the element that was popped
+ *** preempted ***
+ Thread 1 : checks if eax is NULL
+ Thread 1 : InterlockedPopEntrySListFault: mov ebx, [eax] <= faults
+
+ To be sure that we are dealing with exactly the case described above, we
+ check whether the ListHeader has changed. If Thread 2 only popped one
+ entry, the Next field in the S-List-header has changed.
+ If after thread 1 has faulted, thread 2 allocates a new element, by
+ chance getting the same address as the previously freed element and
+ pushes it on the list again, we will see the same top element, but the
+ Sequence member of the S-List header has changed. Therefore we check
+ both fields to make sure we catch any concurrent modification of the
+ S-List-header.
+ */
+ if ((TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) ||
+ (TrapFrame->Eip == (ULONG_PTR)KeUserPopEntrySListFault))
{
- PSLIST_HEADER SListHeader;
+ ULARGE_INTEGER SListHeader;
+ PVOID ResumeAddress;
/* Sanity check that the assembly is correct:
This must be mov ebx, [eax]
(((UCHAR*)TrapFrame->Eip)[4] == 0x4D) &&
(((UCHAR*)TrapFrame->Eip)[5] == 0x00));
- /* Get the pointer to the SLIST_HEADER */
- SListHeader = (PSLIST_HEADER)TrapFrame->Ebp;
+ /* Check if this is a user fault */
+ if (TrapFrame->Eip == (ULONG_PTR)KeUserPopEntrySListFault)
+ {
+ /* EBP points to the S-List-header. Copy it inside SEH, to protect
+ against a bogus pointer from user mode */
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)TrapFrame->Ebp,
+ sizeof(ULARGE_INTEGER),
+ TYPE_ALIGNMENT(SLIST_HEADER));
+ SListHeader = *(PULARGE_INTEGER)TrapFrame->Ebp;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* The S-List pointer is not valid! */
+ goto NotSListFault;
+ }
+ _SEH2_END;
+ ResumeAddress = KeUserPopEntrySListResume;
+ }
+ else
+ {
+ SListHeader = *(PULARGE_INTEGER)TrapFrame->Ebp;
+ ResumeAddress = ExpInterlockedPopEntrySListResume;
+ }
- /* Check if the Next member of the SLIST_HEADER was changed */
- if (SListHeader->Next.Next != (PSLIST_ENTRY)TrapFrame->Eax)
+ /* Check if either the Next pointer or the Sequence member in the
+ S-List-header has changed. If any of these has changed, we restart
+ the operation. Otherwise we only have a bogus pointer and let the
+ page fault handler deal with it. */
+ if ((SListHeader.LowPart != TrapFrame->Eax) ||
+ (SListHeader.HighPart != TrapFrame->Edx))
{
+ DPRINT1("*** Got an S-List-Fault ***\n");
+ KeGetCurrentThread()->SListFaultCount++;
+
/* Restart the operation */
- TrapFrame->Eip = (ULONG_PTR)ExpInterlockedPopEntrySListResume;
+ TrapFrame->Eip = (ULONG_PTR)ResumeAddress;
/* 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
- }
}
+NotSListFault:
/* Call the access fault handler */
- Status = MmAccessFault(TrapFrame->ErrCode & 1,
+ Status = MmAccessFault(TrapFrame->ErrCode,
(PVOID)Cr2,
KiUserTrap(TrapFrame),
TrapFrame);
- if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame);
+ if (NT_SUCCESS(Status))
+ {
+#ifdef _WINKD_
+ /* Check whether the kernel debugger has owed breakpoints to be inserted */
+ KdSetOwedBreakpoints();
+#endif
+ /* We succeeded, return */
+ KiEoiHelper(TrapFrame);
+ }
/* Check for syscall fault */
#if 0
UNIMPLEMENTED_FATAL();
}
#endif
+
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ if (KiVdmTrap(TrapFrame))
+ {
+ DPRINT1("VDM PAGE FAULT at %lx:%lx for address %lx\n",
+ TrapFrame->SegCs, TrapFrame->Eip, Cr2);
+ if (VdmDispatchPageFault(TrapFrame))
+ {
+ /* Return and end VDM execution */
+ DPRINT1("VDM page fault with status 0x%lx resolved\n", Status);
+ KiEoiHelper(TrapFrame);
+ }
+ DPRINT1("VDM page fault with status 0x%lx NOT resolved\n", Status);
+ }
/* Either kernel or user trap (non VDM) so dispatch exception */
if (Status == STATUS_ACCESS_VIOLATION)
/* This status code is repurposed so we can recognize it later */
KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION,
TrapFrame->Eip,
- TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ StoreInstruction,
Cr2,
TrapFrame);
}
/* These faults only have two parameters */
KiDispatchException2Args(Status,
TrapFrame->Eip,
- TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ StoreInstruction,
Cr2,
TrapFrame);
}
0,
TrapFrame->Eip,
3,
- TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ StoreInstruction,
Cr2,
Status,
TrapFrame);
SaveArea = KiGetThreadNpxArea(Thread);
/* Check for VDM trap */
- ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+ ASSERT(KiVdmTrap(TrapFrame) == FALSE);
/* Check for user trap */
if (!KiUserTrap(TrapFrame))
FASTCALL
KiGetTickCountHandler(IN PKTRAP_FRAME TrapFrame)
{
- UNIMPLEMENTED_DBGBREAK();
+ /* Save trap frame */
+ KiEnterTrap(TrapFrame);
+
+ /*
+ * Just fail the request
+ */
+ DbgPrint("INT 0x2A attempted, returning 0 tick count\n");
+ TrapFrame->Eax = 0;
+
+ /* Exit the trap */
+ KiEoiHelper(TrapFrame);
}
VOID
Thread = KeGetCurrentThread();
Thread->TrapFrame = TrapFrame;
Thread->PreviousMode = KiUserTrap(TrapFrame);
- NT_ASSERT(Thread->PreviousMode != KernelMode);
+ ASSERT(Thread->PreviousMode != KernelMode);
/* Pass the register parameters to NtCallbackReturn.
Result pointer is in ecx, result length in edx, status in eax */
{
PKTHREAD Thread;
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
- ULONG Id, Offset, StackBytes, Result;
+ ULONG Id, Offset, StackBytes;
+ NTSTATUS Status;
PVOID Handler;
ULONG SystemCallNumber = TrapFrame->Eax;
if (!(Offset & SERVICE_TABLE_TEST))
{
/* Fail the call */
- Result = STATUS_INVALID_SYSTEM_SERVICE;
+ Status = STATUS_INVALID_SYSTEM_SERVICE;
goto ExitCall;
}
/* Convert us to a GUI thread -- must wrap in ASM to get new EBP */
- Result = KiConvertToGuiThread();
+ Status = KiConvertToGuiThread();
/* Reload trap frame and descriptor table pointer from new stack */
TrapFrame = *(volatile PVOID*)&Thread->TrapFrame;
DescriptorTable = (PVOID)(*(volatile ULONG_PTR*)&Thread->ServiceTable + Offset);
- if (!NT_SUCCESS(Result))
+ if (!NT_SUCCESS(Status))
{
/* Set the last error and fail */
- //SetLastWin32Error(RtlNtStatusToDosError(Result));
goto ExitCall;
}
if (Id >= DescriptorTable->Limit)
{
/* Fail the call */
- Result = STATUS_INVALID_SYSTEM_SERVICE;
+ Status = STATUS_INVALID_SYSTEM_SERVICE;
goto ExitCall;
}
}
/* Get the handler and make the system call */
Handler = (PVOID)DescriptorTable->Base[Id];
- Result = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
+ Status = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
/* Call post-service debug hook */
- Result = KiDbgPostServiceHook(SystemCallNumber, Result);
+ Status = KiDbgPostServiceHook(SystemCallNumber, Status);
/* Make sure we're exiting correctly */
KiExitSystemCallDebugChecks(Id, TrapFrame);
Thread->TrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
/* Exit from system call */
- KiServiceExit(TrapFrame, Result);
+ KiServiceExit(TrapFrame, Status);
+}
+
+VOID
+FASTCALL
+KiCheckForSListAddress(IN PKTRAP_FRAME TrapFrame)
+{
+ UNIMPLEMENTED;
}
/*
Kei386EoiHelper(VOID)
{
/* We should never see this call happening */
- ERROR_FATAL("Mismatched NT/HAL version");
+ KeBugCheck(MISMATCHED_HAL);
}
/* EOF */