pfault.c

来自「一个类似windows」· C语言 代码 · 共 136 行

C
136
字号
/* $Id: pfault.c 21252 2006-03-08 20:03:59Z audit $
 *
 * 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;
   
   ASSERT(ExceptionNr == 14);
   
   /* Store the exception number in an unused field in the trap frame. */
   Tf->DbgArgMark = 14;

   /* get the faulting address */
   cr2 = Ke386GetCr2();
   Tf->DbgArgPointer = cr2;

   /* it's safe to enable interrupts after cr2 has been saved */
   if (Tf->EFlags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
   {
      Ke386EnableInterrupts();
   }

   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(!KeGetCurrentProcess()->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;
   }

   /*
    * Handle user exceptions differently
    */
   if (Mode == KernelMode)
   {
      return(KiKernelTrapHandler(Tf, 14, (PVOID)cr2));
   }
   else
   {
      return(KiUserTrapHandler(Tf, 14, (PVOID)cr2));
   }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?