#001 NTSTATUS
#002 NTAPI
#003 MmNotPresentFault(KPROCESSOR_MODE Mode,
#004 ULONG_PTR Address,
#005 BOOLEAN FromMdl)
#006 {
#007 PMM_AVL_TABLE AddressSpace;
#008 MEMORY_AREA* MemoryArea;
#009 NTSTATUS Status;
#010 BOOLEAN Locked = FromMdl;
#011 PFN_TYPE Pfn;
#012
#013 DPRINT("MmNotPresentFault(Mode %d,Address %x)/n",Mode,Address);
#014
判断访问内存的级别。
#015 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
#016 {
#017 DPRINT1("Page fault at high IRQL was %d,address %x/n",KeGetCurrentIrql(),Address);
#018 return(STATUS_UNSUCCESSFUL);
#019 }
#020
判断是否在内核内存,还是在进程内存空间上。
#021 /*
#022 * Find the memory area for the faulting address
#023 */
#024 if (Address >= (ULONG_PTR)MmSystemRangeStart)
#025 {
#026 /*
#027 * Check permissions
#028 */
#029 if (Mode != KernelMode)
#030 {
#031 DPRINT1("Address: %x/n",Address);
#032 return(STATUS_ACCESS_VIOLATION);
#033 }
#034 AddressSpace = MmGetKernelAddressSpace();
#035 }
#036 else
#037 {
#038 AddressSpace = &PsGetCurrentProcess()->VadRoot;
#039 }
#040
#041 if (!FromMdl)
#042 {
#043 MmLockAddressSpace(AddressSpace);
#044 }
#045
#046 /*
#047 * Call the memory area specific fault handler
#048 */
#049 do
#050 {
#051 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,(PVOID)Address);
#052 if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
#053 {
#054 if (!FromMdl)
#055 {
#056 MmUnlockAddressSpace(AddressSpace);
#057 }
#058 return (STATUS_ACCESS_VIOLATION);
#059 }
#060
#061 switch (MemoryArea->Type)
#062 {
#063 case MEMORY_AREA_PAGED_POOL:
#064 {
#065 Status = MmCommitPagedPoolAddress((PVOID)Address,Locked);
#066 break;
#067 }
#068
#069 case MEMORY_AREA_SYSTEM:
#070 Status = STATUS_ACCESS_VIOLATION;
#071 break;
#072
#073 case MEMORY_AREA_SECTION_VIEW:
#074 Status = MmNotPresentFaultSectionView(AddressSpace,
#075 MemoryArea,
#076 (PVOID)Address,
#077 Locked);
#078 break;
#079
#080 case MEMORY_AREA_VIRTUAL_MEMORY:
#081 case MEMORY_AREA_PEB_OR_TEB:
#082 Status = MmNotPresentFaultVirtualMemory(AddressSpace,
#083 MemoryArea,
#084 (PVOID)Address,
#085 Locked);
#086 break;
#087
#088 case MEMORY_AREA_SHARED_DATA:
#089 Pfn = MmSharedDataPagePhysicalAddress.LowPart >> PAGE_SHIFT;
#090 Status =
#091 MmCreateVirtualMapping(PsGetCurrentProcess(),
#092 (PVOID)PAGE_ROUND_DOWN(Address),
#093 PAGE_READONLY,
#094 &Pfn,
#095 1);
#096 break;
#097
#098 default:
#099 Status = STATUS_ACCESS_VIOLATION;
#100 break;
#101 }
#102 }
#103 while (Status == STATUS_MM_RESTART_OPERATION);
#104
#105 DPRINT("Completed page fault handling/n");
#106 if (!FromMdl)
#107 {
#108 MmUnlockAddressSpace(AddressSpace);
#109 }
#110 return(Status);
#111 }
通过上面的函数,就可以实现读取内存不存在的缺页中断处理。