Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

umapview.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 umapview.c 00008 00009 Abstract: 00010 00011 This module contains the routines which implement the 00012 NtUnmapViewOfSection service. 00013 00014 Author: 00015 00016 Lou Perazzoli (loup) 22-May-1989 00017 00018 Revision History: 00019 00020 Landy Wang (landyw) 08-April-1998 : Modifications for 3-level 64-bit NT. 00021 00022 --*/ 00023 00024 #include "mi.h" 00025 00026 #ifdef ALLOC_PRAGMA 00027 #pragma alloc_text(PAGE,NtUnmapViewOfSection) 00028 #pragma alloc_text(PAGE,MmUnmapViewOfSection) 00029 #endif 00030 00031 00032 NTSTATUS 00033 NtUnmapViewOfSection( 00034 IN HANDLE ProcessHandle, 00035 IN PVOID BaseAddress 00036 ) 00037 00038 /*++ 00039 00040 Routine Description: 00041 00042 This function unmaps a previously created view to a section. 00043 00044 Arguments: 00045 00046 ProcessHandle - Supplies an open handle to a process object. 00047 00048 BaseAddress - Supplies the base address of the view. 00049 00050 Return Value: 00051 00052 Returns the status 00053 00054 TBS 00055 00056 00057 --*/ 00058 00059 { 00060 PEPROCESS Process; 00061 KPROCESSOR_MODE PreviousMode; 00062 NTSTATUS Status; 00063 00064 PAGED_CODE(); 00065 00066 PreviousMode = KeGetPreviousMode(); 00067 00068 if ((PreviousMode == UserMode) && (BaseAddress > MM_HIGHEST_USER_ADDRESS)) { 00069 return STATUS_NOT_MAPPED_VIEW; 00070 } 00071 00072 Status = ObReferenceObjectByHandle ( ProcessHandle, 00073 PROCESS_VM_OPERATION, 00074 PsProcessType, 00075 PreviousMode, 00076 (PVOID *)&Process, 00077 NULL ); 00078 00079 if (!NT_SUCCESS(Status)) { 00080 return Status; 00081 } 00082 00083 Status = MmUnmapViewOfSection ( Process, BaseAddress ); 00084 ObDereferenceObject (Process); 00085 00086 return Status; 00087 } 00088 00089 NTSTATUS 00090 MmUnmapViewOfSection( 00091 IN PEPROCESS Process, 00092 IN PVOID BaseAddress 00093 ) 00094 00095 /*++ 00096 00097 Routine Description: 00098 00099 This function unmaps a previously created view to a section. 00100 00101 Arguments: 00102 00103 Process - Supplies a referenced pointer to a process object. 00104 00105 BaseAddress - Supplies the base address of the view. 00106 00107 Return Value: 00108 00109 Returns the status 00110 00111 TBS 00112 00113 00114 --*/ 00115 00116 { 00117 PMMVAD Vad; 00118 PMMVAD PreviousVad; 00119 PMMVAD NextVad; 00120 SIZE_T RegionSize; 00121 PVOID UnMapImageBase; 00122 NTSTATUS status; 00123 BOOLEAN Attached = FALSE; 00124 00125 PAGED_CODE(); 00126 00127 UnMapImageBase = NULL; 00128 00129 // 00130 // If the specified process is not the current process, attach 00131 // to the specified process. 00132 // 00133 00134 if (PsGetCurrentProcess() != Process) { 00135 KeAttachProcess (&Process->Pcb); 00136 Attached = TRUE; 00137 } 00138 00139 // 00140 // Get the address creation mutex to block multiple threads from 00141 // creating or deleting address space at the same time and 00142 // get the working set mutex so virtual address descriptors can 00143 // be inserted and walked. 00144 // Raise IRQL to block APCs. 00145 // 00146 // Get the working set mutex, no page faults allowed for now until 00147 // working set mutex released. 00148 // 00149 00150 00151 LOCK_WS_AND_ADDRESS_SPACE (Process); 00152 00153 // 00154 // Make sure the address space was not deleted, if so, return an error. 00155 // 00156 00157 if (Process->AddressSpaceDeleted != 0) { 00158 status = STATUS_PROCESS_IS_TERMINATING; 00159 goto ErrorReturn; 00160 } 00161 00162 // 00163 // Find the associated vad. 00164 // 00165 00166 Vad = MiLocateAddress (BaseAddress); 00167 00168 if ((Vad == (PMMVAD)NULL) || (Vad->u.VadFlags.PrivateMemory)) { 00169 00170 // 00171 // No Virtual Address Descriptor located for Base Address. 00172 // 00173 00174 status = STATUS_NOT_MAPPED_VIEW; 00175 goto ErrorReturn; 00176 } 00177 00178 if (Vad->u.VadFlags.NoChange == 1) { 00179 00180 // 00181 // An attempt is being made to delete a secured VAD, check 00182 // the whole VAD to see if this deletion is allowed. 00183 // 00184 00185 status = MiCheckSecuredVad ((PMMVAD)Vad, 00186 MI_VPN_TO_VA (Vad->StartingVpn), 00187 ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT) + 00188 (PAGE_SIZE - 1), 00189 MM_SECURE_DELETE_CHECK); 00190 00191 if (!NT_SUCCESS (status)) { 00192 goto ErrorReturn; 00193 } 00194 } 00195 00196 // 00197 // If this Vad is for an image section, then 00198 // get the base address of the section 00199 // 00200 00201 if ((Vad->u.VadFlags.ImageMap == 1) && (Process == PsGetCurrentProcess())) { 00202 UnMapImageBase = MI_VPN_TO_VA (Vad->StartingVpn); 00203 } 00204 00205 RegionSize = PAGE_SIZE + ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT); 00206 00207 PreviousVad = MiGetPreviousVad (Vad); 00208 NextVad = MiGetNextVad (Vad); 00209 00210 00211 MiRemoveVad (Vad); 00212 00213 // 00214 // Return commitment for page table pages if possible. 00215 // 00216 00217 MiReturnPageTablePageCommitment (MI_VPN_TO_VA (Vad->StartingVpn), 00218 MI_VPN_TO_VA_ENDING (Vad->EndingVpn), 00219 Process, 00220 PreviousVad, 00221 NextVad); 00222 00223 MiRemoveMappedView (Process, Vad); 00224 00225 #if defined(_MIALT4K_) 00226 00227 if (Process->Wow64Process != NULL) { 00228 00229 UNLOCK_WS_UNSAFE (Process); 00230 00231 MiDeleteFor4kPage(MI_VPN_TO_VA (Vad->StartingVpn), 00232 MI_VPN_TO_VA_ENDING (Vad->EndingVpn), 00233 Process); 00234 00235 LOCK_WS_UNSAFE (Process); 00236 00237 } 00238 00239 #endif 00240 00241 ExFreePool (Vad); 00242 00243 // 00244 // Update the current virtual size in the process header. 00245 // 00246 00247 Process->VirtualSize -= RegionSize; 00248 status = STATUS_SUCCESS; 00249 00250 ErrorReturn: 00251 00252 UNLOCK_WS_AND_ADDRESS_SPACE (Process); 00253 00254 if ( UnMapImageBase ) { 00255 DbgkUnMapViewOfSection(UnMapImageBase); 00256 } 00257 if (Attached == TRUE) { 00258 KeDetachProcess(); 00259 } 00260 00261 return status; 00262 } 00263 00264 VOID 00265 MiRemoveMappedView ( 00266 IN PEPROCESS CurrentProcess, 00267 IN PMMVAD Vad 00268 ) 00269 00270 /*++ 00271 00272 Routine Description: 00273 00274 This function removes the mapping from the current process's 00275 address space. The physical VAD may be a normal mapping (backed by 00276 a control area) or it may have no control area (it was mapped by a driver). 00277 00278 Arguments: 00279 00280 Process - Supplies a referenced pointer to the current process object. 00281 00282 Vad - Supplies the VAD which maps the view. 00283 00284 Return Value: 00285 00286 None. 00287 00288 Environment: 00289 00290 APC level, working set mutex and address creation mutex held. 00291 00292 NOTE: THE WORKING SET MUTEXES MAY BE RELEASED THEN REACQUIRED!!!! 00293 00294 SINCE MiCheckControlArea releases unsafe, the WS mutex must be 00295 acquired UNSAFE. 00296 00297 --*/ 00298 00299 { 00300 KIRQL OldIrql; 00301 BOOLEAN DereferenceSegment; 00302 PCONTROL_AREA ControlArea; 00303 PMMPTE PointerPte; 00304 PMMPTE PointerPde; 00305 PMMPTE LastPte; 00306 PFN_NUMBER PdePage; 00307 PKEVENT PurgeEvent; 00308 PVOID TempVa; 00309 BOOLEAN DeleteOnClose; 00310 MMPTE_FLUSH_LIST PteFlushList; 00311 PVOID UsedPageTableHandle; 00312 PLIST_ENTRY NextEntry; 00313 PMI_PHYSICAL_VIEW PhysicalView; 00314 PVOID PhysicalPool; 00315 #if defined (_WIN64) 00316 PMMPTE PointerPpe; 00317 PVOID UsedPageDirectoryHandle; 00318 #endif 00319 00320 DereferenceSegment = FALSE; 00321 PurgeEvent = NULL; 00322 DeleteOnClose = FALSE; 00323 PhysicalPool = NULL; 00324 00325 ControlArea = Vad->ControlArea; 00326 00327 if (Vad->u.VadFlags.PhysicalMapping == 1) { 00328 00329 if (Vad->u4.Banked) { 00330 ExFreePool (Vad->u4.Banked); 00331 } 00332 00333 #ifdef LARGE_PAGES 00334 if (Vad->u.VadFlags.LargePages == 1) { 00335 00336 // 00337 // Delete the subsection allocated to hold the large pages. 00338 // 00339 00340 ExFreePool (Vad->FirstPrototypePte); 00341 Vad->FirstPrototypePte = NULL; 00342 KeFlushEntireTb (TRUE, FALSE); 00343 LOCK_PFN (OldIrql); 00344 } else { 00345 00346 #endif //LARGE_PAGES 00347 00348 // 00349 // This is a physical memory view. The pages map physical memory 00350 // and are not accounted for in the working set list or in the PFN 00351 // database. 00352 // 00353 00354 LOCK_AWE (CurrentProcess, OldIrql); 00355 00356 NextEntry = CurrentProcess->PhysicalVadList.Flink; 00357 while (NextEntry != &CurrentProcess->PhysicalVadList) { 00358 00359 PhysicalView = CONTAINING_RECORD(NextEntry, 00360 MI_PHYSICAL_VIEW, 00361 ListEntry); 00362 00363 if (Vad == PhysicalView->Vad) { 00364 RemoveEntryList (NextEntry); 00365 PhysicalPool = (PVOID)PhysicalView; 00366 break; 00367 } 00368 NextEntry = NextEntry->Flink; 00369 } 00370 00371 UNLOCK_AWE (CurrentProcess, OldIrql); 00372 00373 // 00374 // Set count so only flush entire TB operations are performed. 00375 // 00376 00377 PteFlushList.Count = MM_MAXIMUM_FLUSH_COUNT; 00378 00379 LOCK_PFN (OldIrql); 00380 00381 // 00382 // Remove the PTES from the address space. 00383 // 00384 00385 PointerPde = MiGetPdeAddress (MI_VPN_TO_VA (Vad->StartingVpn)); 00386 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (PointerPde); 00387 PointerPte = MiGetPteAddress (MI_VPN_TO_VA (Vad->StartingVpn)); 00388 LastPte = MiGetPteAddress (MI_VPN_TO_VA (Vad->EndingVpn)); 00389 00390 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MI_VPN_TO_VA (Vad->StartingVpn)); 00391 00392 while (PointerPte <= LastPte) { 00393 00394 if (MiIsPteOnPdeBoundary (PointerPte)) { 00395 00396 PointerPde = MiGetPteAddress (PointerPte); 00397 PdePage = MI_GET_PAGE_FRAME_FROM_PTE (PointerPde); 00398 00399 UsedPageTableHandle = MI_GET_USED_PTES_HANDLE (MiGetVirtualAddressMappedByPte (PointerPte)); 00400 } 00401 00402 MI_WRITE_INVALID_PTE (PointerPte, ZeroPte); 00403 MiDecrementShareAndValidCount (PdePage); 00404 00405 // 00406 // Decrement the count of non-zero page table entries for this 00407 // page table. 00408 // 00409 00410 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageTableHandle); 00411 00412 // 00413 // If all the entries have been eliminated from the previous 00414 // page table page, delete the page table page itself. And if 00415 // this results in an empty page directory page, then delete 00416 // that too. 00417 // 00418 00419 if (MI_GET_USED_PTES_FROM_HANDLE(UsedPageTableHandle) == 0) { 00420 00421 TempVa = MiGetVirtualAddressMappedByPte(PointerPde); 00422 00423 PteFlushList.Count = MM_MAXIMUM_FLUSH_COUNT; 00424 00425 MiDeletePte (PointerPde, 00426 TempVa, 00427 FALSE, 00428 CurrentProcess, 00429 (PMMPTE)NULL, 00430 &PteFlushList); 00431 00432 // 00433 // Add back in the private page MiDeletePte subtracted. 00434 // 00435 00436 CurrentProcess->NumberOfPrivatePages += 1; 00437 00438 #if defined (_WIN64) 00439 UsedPageDirectoryHandle = MI_GET_USED_PTES_HANDLE (PointerPte); 00440 00441 MI_DECREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryHandle); 00442 00443 if (MI_GET_USED_PTES_FROM_HANDLE(UsedPageDirectoryHandle) == 0) { 00444 00445 PointerPpe = MiGetPdeAddress(PointerPte); 00446 TempVa = MiGetVirtualAddressMappedByPte(PointerPpe); 00447 00448 PteFlushList.Count = MM_MAXIMUM_FLUSH_COUNT; 00449 00450 MiDeletePte (PointerPpe, 00451 TempVa, 00452 FALSE, 00453 CurrentProcess, 00454 (PMMPTE)NULL, 00455 &PteFlushList); 00456 00457 // 00458 // Add back in the private page MiDeletePte subtracted. 00459 // 00460 00461 CurrentProcess->NumberOfPrivatePages += 1; 00462 } 00463 #endif 00464 } 00465 PointerPte += 1; 00466 } 00467 KeFlushEntireTb (TRUE, FALSE); 00468 00469 #ifdef LARGE_PAGES 00470 } 00471 #endif //LARGE_PAGES 00472 } else { 00473 00474 if (Vad->u2.VadFlags2.ExtendableFile) { 00475 PMMEXTEND_INFO exinfo = NULL; 00476 ExAcquireFastMutexUnsafe (&MmSectionBasedMutex); 00477 ASSERT (Vad->ControlArea->Segment->ExtendInfo == Vad->u4.ExtendedInfo); 00478 Vad->u4.ExtendedInfo->ReferenceCount -= 1; 00479 if (Vad->u4.ExtendedInfo->ReferenceCount == 0) { 00480 exinfo = Vad->u4.ExtendedInfo; 00481 Vad->ControlArea->Segment->ExtendInfo = NULL; 00482 } 00483 ExReleaseFastMutexUnsafe (&MmSectionBasedMutex); 00484 if (exinfo) { 00485 ExFreePool (exinfo); 00486 } 00487 } 00488 00489 LOCK_PFN (OldIrql); 00490 MiDeleteVirtualAddresses (MI_VPN_TO_VA (Vad->StartingVpn), 00491 MI_VPN_TO_VA_ENDING (Vad->EndingVpn), 00492 FALSE, 00493 Vad); 00494 } 00495 00496 // 00497 // Only physical VADs mapped by drivers don't have control areas. 00498 // If this view has a control area, the view count must be decremented now. 00499 // 00500 00501 if (ControlArea) { 00502 00503 // 00504 // Decrement the count of the number of views for the 00505 // Segment object. This requires the PFN mutex to be held (it is 00506 // already). 00507 // 00508 00509 ControlArea->NumberOfMappedViews -= 1; 00510 ControlArea->NumberOfUserReferences -= 1; 00511 00512 // 00513 // Check to see if the control area (segment) should be deleted. 00514 // This routine releases the PFN lock. 00515 // 00516 00517 MiCheckControlArea (ControlArea, CurrentProcess, OldIrql); 00518 } 00519 else { 00520 00521 UNLOCK_PFN (OldIrql); 00522 00523 // 00524 // Even though it says short VAD in VadFlags, it better be a long VAD. 00525 // 00526 00527 ASSERT (Vad->u.VadFlags.PhysicalMapping == 1); 00528 ASSERT (Vad->u4.Banked == NULL); 00529 ASSERT (Vad->ControlArea == NULL); 00530 ASSERT (Vad->FirstPrototypePte == NULL); 00531 } 00532 00533 if (PhysicalPool != NULL) { 00534 ExFreePool (PhysicalPool); 00535 } 00536 00537 return; 00538 } 00539 00540 VOID 00541 MiPurgeImageSection ( 00542 IN PCONTROL_AREA ControlArea, 00543 IN PEPROCESS Process OPTIONAL 00544 ) 00545 00546 /*++ 00547 00548 Routine Description: 00549 00550 This function locates subsections within an image section that 00551 contain global memory and resets the global memory back to 00552 the initial subsection contents. 00553 00554 Note, that for this routine to be called the section is not 00555 referenced nor is it mapped in any process. 00556 00557 Arguments: 00558 00559 ControlArea - Supplies a pointer to the control area for the section. 00560 00561 Process - Supplies a pointer to the process IFF the working set mutex 00562 is held, else NULL is supplied. Note that IFF the working set 00563 mutex is held, it must always be acquired unsafe. 00564 00565 Return Value: 00566 00567 None. 00568 00569 Environment: 00570 00571 PFN LOCK held. 00572 00573 --*/ 00574 00575 { 00576 PMMPTE PointerPte; 00577 PMMPTE LastPte; 00578 PMMPFN Pfn1; 00579 MMPTE PteContents; 00580 MMPTE NewContents; 00581 MMPTE NewContentsDemandZero; 00582 KIRQL OldIrql = APC_LEVEL; 00583 ULONG i; 00584 ULONG SizeOfRawData; 00585 ULONG OffsetIntoSubsection; 00586 PSUBSECTION Subsection; 00587 #if DBG 00588 ULONG DelayCount = 0; 00589 #endif //DBG 00590 00591 ASSERT (ControlArea->u.Flags.Image != 0); 00592 00593 i = ControlArea->NumberOfSubsections; 00594 00595 if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) { 00596 Subsection = (PSUBSECTION)(ControlArea + 1); 00597 } 00598 else { 00599 Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); 00600 } 00601 00602 // 00603 // Loop through all the subsections 00604 00605 while (i > 0) { 00606 00607 if (Subsection->u.SubsectionFlags.GlobalMemory == 1) { 00608 00609 NewContents.u.Long = 0; 00610 NewContentsDemandZero.u.Long = 0; 00611 SizeOfRawData = 0; 00612 OffsetIntoSubsection = 0; 00613 00614 // 00615 // Purge this section. 00616 // 00617 00618 if (Subsection->StartingSector != 0) { 00619 00620 // 00621 // This is not a demand zero section. 00622 // 00623 00624 NewContents.u.Long = MiGetSubsectionAddressForPte(Subsection); 00625 NewContents.u.Soft.Prototype = 1; 00626 00627 SizeOfRawData = (Subsection->NumberOfFullSectors << MMSECTOR_SHIFT) | 00628 Subsection->u.SubsectionFlags.SectorEndOffset; 00629 } 00630 00631 NewContents.u.Soft.Protection = 00632 Subsection->u.SubsectionFlags.Protection; 00633 NewContentsDemandZero.u.Soft.Protection = 00634 NewContents.u.Soft.Protection; 00635 00636 PointerPte = Subsection->SubsectionBase; 00637 LastPte = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; 00638 ControlArea = Subsection->ControlArea; 00639 00640 // 00641 // The WS lock may be released and reacquired and our callers 00642 // always acquire it unsafe. 00643 // 00644 00645 MiMakeSystemAddressValidPfnWs (PointerPte, Process); 00646 00647 while (PointerPte < LastPte) { 00648 00649 if (MiIsPteOnPdeBoundary(PointerPte)) { 00650 00651 // 00652 // We are on a page boundary, make sure this PTE is resident. 00653 // 00654 00655 MiMakeSystemAddressValidPfnWs (PointerPte, Process); 00656 } 00657 00658 PteContents = *PointerPte; 00659 if (PteContents.u.Long == 0) { 00660 00661 // 00662 // No more valid PTEs to deal with. 00663 // 00664 00665 break; 00666 } 00667 00668 ASSERT (PteContents.u.Hard.Valid == 0); 00669 00670 if ((PteContents.u.Soft.Prototype == 0) && 00671 (PteContents.u.Soft.Transition == 1)) { 00672 00673 // 00674 // The prototype PTE is in transition format. 00675 // 00676 00677 Pfn1 = MI_PFN_ELEMENT (PteContents.u.Trans.PageFrameNumber); 00678 00679 // 00680 // If the prototype PTE is no longer pointing to 00681 // the original image page (not in protopte format), 00682 // or has been modified, remove it from memory. 00683 // 00684 00685 if ((Pfn1->u3.e1.Modified == 1) || 00686 (Pfn1->OriginalPte.u.Soft.Prototype == 0)) { 00687 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 00688 00689 // 00690 // This is a transition PTE which has been 00691 // modified or is no longer in protopte format. 00692 // 00693 00694 if (Pfn1->u3.e2.ReferenceCount != 0) { 00695 00696 // 00697 // There must be an I/O in progress on this 00698 // page. Wait for the I/O operation to complete. 00699 // 00700 00701 UNLOCK_PFN (OldIrql); 00702 00703 KeDelayExecutionThread (KernelMode, FALSE, &MmShortTime); 00704 00705 // 00706 // Redo the loop. 00707 // 00708 #if DBG 00709 if ((DelayCount % 1024) == 0) { 00710 DbgPrint("MMFLUSHSEC: waiting for i/o to complete PFN %lx\n", 00711 Pfn1); 00712 } 00713 DelayCount += 1; 00714 #endif //DBG 00715 00716 LOCK_PFN (OldIrql); 00717 00718 MiMakeSystemAddressValidPfnWs (PointerPte, Process); 00719 continue; 00720 } 00721 00722 ASSERT (!((Pfn1->OriginalPte.u.Soft.Prototype == 0) && 00723 (Pfn1->OriginalPte.u.Soft.Transition == 1))); 00724 00725 MI_WRITE_INVALID_PTE (PointerPte, Pfn1->OriginalPte); 00726 ASSERT (Pfn1->OriginalPte.u.Hard.Valid == 0); 00727 00728 // 00729 // Only reduce the number of PFN references if 00730 // the original PTE is still in prototype PTE 00731 // format. 00732 // 00733 00734 if (Pfn1->OriginalPte.u.Soft.Prototype == 1) { 00735 ControlArea->NumberOfPfnReferences -= 1; 00736 ASSERT ((LONG)ControlArea->NumberOfPfnReferences >= 0); 00737 } 00738 MiUnlinkPageFromList (Pfn1); 00739 00740 MI_SET_PFN_DELETED (Pfn1); 00741 00742 MiDecrementShareCount (Pfn1->PteFrame); 00743 00744 // 00745 // If the reference count for the page is zero, insert 00746 // it into the free page list, otherwise leave it alone 00747 // and when the reference count is decremented to zero 00748 // the page will go to the free list. 00749 // 00750 00751 if (Pfn1->u3.e2.ReferenceCount == 0) { 00752 MiReleasePageFileSpace (Pfn1->OriginalPte); 00753 MiInsertPageInList (MmPageLocationList[FreePageList], 00754 MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents)); 00755 } 00756 00757 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 00758 } 00759 } else { 00760 00761 // 00762 // Prototype PTE is not in transition format. 00763 // 00764 00765 if (PteContents.u.Soft.Prototype == 0) { 00766 00767 // 00768 // This refers to a page in the paging file, 00769 // as it no longer references the image, 00770 // restore the PTE contents to what they were 00771 // at the initial image creation. 00772 // 00773 00774 if (PteContents.u.Long != NoAccessPte.u.Long) { 00775 MiReleasePageFileSpace (PteContents); 00776 MI_WRITE_INVALID_PTE (PointerPte, NewContents); 00777 } 00778 } 00779 } 00780 PointerPte += 1; 00781 OffsetIntoSubsection += PAGE_SIZE; 00782 00783 if (OffsetIntoSubsection >= SizeOfRawData) { 00784 00785 // 00786 // There are trailing demand zero pages in this 00787 // subsection, set the PTE contents to be demand 00788 // zero for the remainder of the PTEs in this 00789 // subsection. 00790 // 00791 00792 NewContents = NewContentsDemandZero; 00793 } 00794 00795 #if DBG 00796 DelayCount = 0; 00797 #endif //DBG 00798 00799 } //end while 00800 } 00801 00802 i -=1; 00803 Subsection += 1; 00804 } 00805 00806 return; 00807 }

Generated on Sat May 15 19:42:11 2004 for test by doxygen 1.3.7