NTSTATUS NTAPI MiSwapInPage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES Resources) { NTSTATUS Status; Status = MmRequestPageMemoryConsumer(Resources->Consumer, TRUE, &Resources->Page[Resources->Offset]); if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status); return Status; } Status = MmReadFromSwapPage(Resources->SwapEntry, Resources->Page[Resources->Offset]); if (!NT_SUCCESS(Status)) { DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); return Status; } MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset], Resources->SwapEntry); DPRINT1("MiSwapInPage(%x,%x)\n", Resources->Page[Resources->Offset], Resources->SwapEntry); return Status; }
/* Blocking function to acquire zeroed pages from the balancer. Upon entry: Required->Amount: Number of pages to acquire Required->Consumer: consumer to charge the page to Upon return: Required->Pages[0..Amount]: Allocated pages. The function fails unless all requested pages can be allocated. */ NTSTATUS NTAPI MiGetOnePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES Required) { ULONG i; NTSTATUS Status = STATUS_SUCCESS; for (i = 0; i < Required->Amount; i++) { DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line); Status = MmRequestPageMemoryConsumer(Required->Consumer, TRUE, &Required->Page[i]); if (!NT_SUCCESS(Status)) { while (i > 0) { MmReleasePageMemoryConsumer(Required->Consumer, Required->Page[i-1]); i--; } return Status; } } return Status; }
PMMPTE NTAPI MiGetPageTableForProcess(IN PEPROCESS Process, IN PVOID Address, IN BOOLEAN Create) { //ULONG PdeOffset; PMMPTE PointerPte; PMMPDE_HARDWARE PointerPde; MMPDE_HARDWARE TempPde; MMPTE TempPte; NTSTATUS Status; PFN_NUMBER Pfn; // // Check if this is a user-mode, non-kernel or non-current address // if ((Address < MmSystemRangeStart) && (Process) && (Process != PsGetCurrentProcess())) { // // FIXME-USER: No user-mode memory support // ASSERT(FALSE); } // // Get our templates // TempPde = MiArmTemplatePde; TempPte = MiArmTemplatePte; // // Get the PDE // PointerPde = MiGetPdeAddress(Address); if (PointerPde->u.Hard.Coarse.Valid) { // // Invalid PDE, is this a kernel address? // if (Address >= MmSystemRangeStart) { // // Does it exist in the kernel page directory? // //PdeOffset = MiGetPdeOffset(Address); //if (MmGlobalKernelPageDirectory[PdeOffset] == 0) { // // It doesn't. Is this a create operation? If not, fail // if (Create == FALSE) return NULL; kernelHack: DPRINT1("Must create a page for: %p PDE: %p\n", // Offset: %lx!\n", Address, PointerPde);//, PdeOffset); // // Allocate a non paged pool page for the PDE // Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn); if (!NT_SUCCESS(Status)) return NULL; // // Setup the PFN // TempPde.u.Hard.Coarse.PageFrameNumber = (Pfn << PAGE_SHIFT) >> CPT_SHIFT; // // Write the PDE // ASSERT(PointerPde->u.Hard.Coarse.Valid == 0); ASSERT(TempPde.u.Hard.Coarse.Valid == 1); *PointerPde = TempPde; // // Save it // //MmGlobalKernelPageDirectory[PdeOffset] = TempPde.u.Hard.AsUlong; //DPRINT1("KPD: %p PDEADDR: %p\n", &MmGlobalKernelPageDirectory[PdeOffset], MiGetPdeAddress(Address)); // // FIXFIX: Double check with Felix tomorrow // ///// // // Get the PTE for this 1MB region // PointerPte = MiGetPteAddress(MiGetPteAddress(Address)); DPRINT1("PointerPte: %p\n", PointerPte); // // Write the PFN of the PDE // TempPte.u.Hard.PageFrameNumber = Pfn; // // Write the PTE // ASSERT(PointerPte->u.Hard.Valid == 0); ASSERT(TempPte.u.Hard.Valid == 1); *PointerPte = TempPte; ///// } // // Now set the actual PDE // //PointerPde = (PMMPTE)&MmGlobalKernelPageDirectory[PdeOffset]; } else { // // Is this a create operation? If not, fail // if (Create == FALSE) return NULL;
NTSTATUS NTAPI MiReadFilePage(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_REQUIRED_RESOURCES RequiredResources) { PFILE_OBJECT FileObject = RequiredResources->Context; PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset]; PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset; NTSTATUS Status; PVOID PageBuf = NULL; KEVENT Event; IO_STATUS_BLOCK IOSB; UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)]; PMDL Mdl = (PMDL)MdlBase; KIRQL OldIrql; DPRINTC("Pulling page %I64x from %wZ to %Ix\n", FileOffset->QuadPart, &FileObject->FileName, *Page); Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page); if (!NT_SUCCESS(Status)) { DPRINT1("Status: %x\n", Status); return Status; } MmInitializeMdl(Mdl, NULL, PAGE_SIZE); MmBuildMdlFromPages(Mdl, Page); Mdl->MdlFlags |= MDL_PAGES_LOCKED; KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoPageRead(FileObject, Mdl, FileOffset, &Event, &IOSB); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = IOSB.Status; } if (Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) { MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl); } PageBuf = MiMapPageInHyperSpace(PsGetCurrentProcess(), *Page, &OldIrql); if (!PageBuf) { MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page); return STATUS_NO_MEMORY; } RtlZeroMemory((PCHAR)PageBuf+RequiredResources->Amount, PAGE_SIZE-RequiredResources->Amount); MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf, OldIrql); DPRINT("Read Status %x (Page %x)\n", Status, *Page); if (!NT_SUCCESS(Status)) { MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page); DPRINT("Status: %x\n", Status); return Status; } return STATUS_SUCCESS; }