00109                    :
00110 
00111     This routine stands on its head to produce a copy of 
the specified
00112     process's address space in 
the process to initialize.  This
00113     
is done by examining each 
virtual address descriptor's inherit
00114     attributes.  If 
the pages described by 
the VAD should be inherited,
00115     each PTE 
is examined and copied into 
the new address space.
00116 
00117     For 
private pages, fork prototype PTEs are constructed and 
the pages
00118     become shared, copy-on-write, between 
the two processes.
00119 
00120 
00121 Arguments:
00122 
00123     ProcessToClone - Supplies 
the process whose address space should be
00124                      cloned.
00125 
00126     ProcessToInitialize - Supplies 
the process whose address space 
is to
00127                           be created.
00128 
00129     RootPhysicalPage - Supplies 
the physical page number of 
the top level
00130                        page (parent on 64-bit systems) directory
00131                        of 
the process to initialize.
00132 
00133     HyperPhysicalPage - Supplies 
the physical page number of 
the page table
00134                         page which maps hyperspace 
for the process to
00135                         initialize.  This 
is only needed 
for 32-bit systems.
00136 
00137 Return Value:
00138 
00139     None.
00140 
00141 Environment:
00142 
00143     Kernel mode, APCs disabled.
00144 
00145 --*/
00146 
00147 {
00148     PFN_NUMBER PpePhysicalPage;
00149     PFN_NUMBER PdePhysicalPage;
00150     
PEPROCESS CurrentProcess;
00151     
PMMPTE PdeBase;
00152     
PMMCLONE_HEADER CloneHeader;
00153     
PMMCLONE_BLOCK CloneProtos;
00154     
PMMCLONE_DESCRIPTOR CloneDescriptor;
00155     
PMMVAD NewVad;
00156     
PMMVAD Vad;
00157     
PMMVAD NextVad;
00158     
PMMVAD *VadList;
00159     
PMMVAD FirstNewVad;
00160     
PMMCLONE_DESCRIPTOR *CloneList;
00161     
PMMCLONE_DESCRIPTOR FirstNewClone;
00162     
PMMCLONE_DESCRIPTOR Clone;
00163     
PMMCLONE_DESCRIPTOR NextClone;
00164     
PMMCLONE_DESCRIPTOR NewClone;
00165     ULONG Attached;
00166     ULONG CloneFailed;
00167     ULONG VadInsertFailed;
00168     
WSLE_NUMBER WorkingSetIndex;
00169     PVOID VirtualAddress;
00170     
NTSTATUS status;
00171     
PMMPFN Pfn2;
00172     
PMMPFN PfnPdPage;
00173     
MMPTE TempPte;
00174     
MMPTE PteContents;
00175 
#if defined (_X86PAE_)
00176 
    PMDL MdlPageDirectory;
00177     PPFN_NUMBER MdlPageFrames;
00178     PFN_NUMBER PageDirectoryFrames[PD_PER_SYSTEM];
00179     PFN_NUMBER MdlHackPageDirectory[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) + PD_PER_SYSTEM];
00180 
#endif
00181 
    PFN_NUMBER MdlPage;
00182     PFN_NUMBER MdlDirPage;
00183     
PMMPTE PointerPte;
00184     
PMMPTE PointerPde;
00185     
PMMPTE PointerPpe;
00186     
PMMPTE LastPte;
00187     
PMMPTE PointerNewPte;
00188     
PMMPTE NewPteMappedAddress;
00189     
PMMPTE PointerNewPde;
00190     PLIST_ENTRY NextEntry;
00191     
PMI_PHYSICAL_VIEW PhysicalView;
00192     PFN_NUMBER PageFrameIndex;
00193     PFN_NUMBER PageDirFrameIndex;
00194     
PMMCLONE_BLOCK ForkProtoPte;
00195     
PMMCLONE_BLOCK CloneProto;
00196     
PMMCLONE_BLOCK LockedForkPte;
00197     
PMMPTE ContainingPte;
00198     ULONG NumberOfForkPtes;
00199     PFN_NUMBER NumberOfPrivatePages;
00200     PFN_NUMBER PageTablePage;
00201     SIZE_T TotalPagedPoolCharge;
00202     SIZE_T TotalNonPagedPoolCharge;
00203     
PMMPFN PfnForkPtePage;
00204     PVOID UsedPageTableEntries;
00205     ULONG ReleasedWorkingSetMutex;
00206     ULONG FirstTime;
00207     ULONG Waited;
00208     ULONG i;
00209     ULONG PpePdeOffset;
00210 
#if defined (_WIN64)
00211 
    PVOID UsedPageDirectoryEntries;
00212     
PMMPTE PointerNewPpe;
00213     
PMMPTE PpeBase;
00214     
PMMPFN PfnPpPage;
00215 
#else
00216 
    PMMWSL HyperBase;
00217 
#endif
00218 
00219     PageTablePage = 2;
00220     NumberOfForkPtes = 0;
00221     Attached = 
FALSE;
00222     PageFrameIndex = (PFN_NUMBER)-1;
00223     PageDirFrameIndex = (PFN_NUMBER)-1;
00224 
00225 
#if DBG
00226 
    if (MmDebug & 
MM_DBG_FORK) {
00227         
DbgPrint(
"beginning clone operation process to clone = %lx\n",
00228             ProcessToClone);
00229     }
00230 
#endif //DBG
00231 
00232     
PAGED_CODE();
00233 
00234     
if (ProcessToClone != 
PsGetCurrentProcess()) {
00235         Attached = 
TRUE;
00236         
KeAttachProcess (&ProcessToClone->Pcb);
00237     }
00238 
00239 
#if defined (_X86PAE_)
00240 
    MiRetrievePageDirectoryFrames (RootPhysicalPage, PageDirectoryFrames);
00241 
#endif
00242 
00243     CurrentProcess = ProcessToClone;
00244 
00245     
00246     
00247     
00248     
00249     
00250     
00251 
00252     
LOCK_ADDRESS_SPACE (CurrentProcess);
00253 
00254     
00255     
00256     
00257     
00258 
00259     
if (CurrentProcess->
Vm.
u.Flags.WriteWatch == 1) {
00260         status = STATUS_INVALID_PAGE_PROTECTION;
00261         
goto ErrorReturn1;
00262     }
00263 
00264     
00265     
00266     
00267     
00268     
00269 
00270     NextEntry = CurrentProcess->
PhysicalVadList.Flink;
00271     
while (NextEntry != &CurrentProcess->
PhysicalVadList) {
00272 
00273         PhysicalView = CONTAINING_RECORD(NextEntry,
00274                                          
MI_PHYSICAL_VIEW,
00275                                          ListEntry);
00276 
00277         
if (PhysicalView->
Vad->
u.VadFlags.UserPhysicalPages == 1) {
00278             status = STATUS_INVALID_PAGE_PROTECTION;
00279             
goto ErrorReturn1;
00280         }
00281 
00282         NextEntry = NextEntry->Flink;
00283     }
00284 
00285     
00286     
00287     
00288 
00289     
if (CurrentProcess->
AddressSpaceDeleted != 0) {
00290         status = STATUS_PROCESS_IS_TERMINATING;
00291         
goto ErrorReturn1;
00292     }
00293 
00294     
00295     
00296     
00297     
00298     
00299 
00300     NumberOfPrivatePages = CurrentProcess->
NumberOfPrivatePages;
00301 
00302     CloneProtos = 
ExAllocatePoolWithTag (PagedPool, 
sizeof(
MMCLONE_BLOCK) *
00303                                                 NumberOfPrivatePages,
00304                                                 'lCmM');
00305     
if (CloneProtos == 
NULL) {
00306         status = STATUS_INSUFFICIENT_RESOURCES;
00307         
goto ErrorReturn1;
00308     }
00309 
00310     CloneHeader = 
ExAllocatePoolWithTag (NonPagedPool,
00311                                          
sizeof(
MMCLONE_HEADER),
00312                                          '  mM');
00313     
if (CloneHeader == 
NULL) {
00314         status = STATUS_INSUFFICIENT_RESOURCES;
00315         
goto ErrorReturn2;
00316     }
00317 
00318     CloneDescriptor = 
ExAllocatePoolWithTag (NonPagedPool,
00319                                              
sizeof(
MMCLONE_DESCRIPTOR),
00320                                              '  mM');
00321     
if (CloneDescriptor == 
NULL) {
00322         status = STATUS_INSUFFICIENT_RESOURCES;
00323         
goto ErrorReturn3;
00324     }
00325 
00326     Vad = 
MiGetFirstVad (CurrentProcess);
00327     VadList = &FirstNewVad;
00328 
00329     
while (Vad != (
PMMVAD)
NULL) {
00330 
00331         
00332         
00333         
00334 
00335         
if ((Vad->
u.VadFlags.UserPhysicalPages == 0) &&
00336 
00337             ((Vad->
u.VadFlags.PrivateMemory == 1) ||
00338             (Vad->
u2.VadFlags2.Inherit == 
MM_VIEW_SHARE))) {
00339 
00340             NewVad = 
ExAllocatePoolWithTag (NonPagedPool, 
sizeof(
MMVAD), ' daV');
00341 
00342             
if (NewVad == 
NULL) {
00343 
00344                 
00345                 
00346                 
00347                 
00348 
00349                 *VadList = (
PMMVAD)
NULL;
00350                 status = STATUS_INSUFFICIENT_RESOURCES;
00351                 
goto ErrorReturn4;
00352             }
00353             *VadList = NewVad;
00354             VadList = &NewVad->
Parent;
00355         }
00356         Vad = 
MiGetNextVad (Vad);
00357     }
00358 
00359     
00360     
00361     
00362 
00363     *VadList = (
PMMVAD)
NULL;
00364 
00365     
00366     
00367     
00368     
00369     
00370 
00371     
try {
00372         
PsChargePoolQuota (CurrentProcess, PagedPool, 
sizeof(
MMCLONE_BLOCK) *
00373                                                 NumberOfPrivatePages);
00374         PageTablePage = 1;
00375         
PsChargePoolQuota (CurrentProcess, NonPagedPool, 
sizeof(
MMCLONE_HEADER));
00376         PageTablePage = 0;
00377 
00378     } except (EXCEPTION_EXECUTE_HANDLER) {
00379 
00380         
00381         
00382         
00383 
00384         status = GetExceptionCode();
00385         
goto ErrorReturn4;
00386     }
00387 
00388     
LOCK_WS (CurrentProcess);
00389 
00390     
ASSERT (CurrentProcess->
ForkInProgress == NULL);
00391 
00392     
00393     
00394     
00395     
00396     
00397 
00398     CurrentProcess->
ForkInProgress = 
PsGetCurrentThread();
00399 
00400 
#if defined (_WIN64)
00401 
00402     
00403     
00404     
00405     
00406     
00407     
00408 
00409     
MiUpPfnReferenceCount (RootPhysicalPage, 3);
00410 
00411     
00412     
00413     
00414     
00415     
00416 
00417     PpeBase = (
PMMPTE)
MiMapSinglePage (NULL,
00418                                        RootPhysicalPage,
00419                                        MmCached,
00420                                        HighPagePriority);
00421 
00422     
if (PpeBase == 
NULL) {
00423         
MiDownPfnReferenceCount (RootPhysicalPage, 3);
00424         CurrentProcess->
ForkInProgress = 
NULL;
00425         
UNLOCK_WS (CurrentProcess);
00426         status = STATUS_INSUFFICIENT_RESOURCES;
00427         
goto ErrorReturn4;
00428     }
00429 
00430     PfnPpPage = 
MI_PFN_ELEMENT (RootPhysicalPage);
00431 
00432 
#else
00433 
00434 
#if !defined (_X86PAE_)
00435 
    MiUpPfnReferenceCount (RootPhysicalPage, 1);
00436 
#endif
00437 
00438 
#endif
00439 
00440     
00441     
00442     
00443     
00444     
00445     
00446 
00447 
#if !defined (_X86PAE_)
00448 
00449     MdlDirPage = RootPhysicalPage;
00450 
00451     PdePhysicalPage = RootPhysicalPage;
00452 
00453     PdeBase = (
PMMPTE)
MiMapSinglePage (NULL,
00454                                        MdlDirPage,
00455                                        MmCached,
00456                                        HighPagePriority);
00457 
00458     
if (PdeBase == 
NULL) {
00459 
#if defined (_WIN64)
00460 
        MiDownPfnReferenceCount (RootPhysicalPage, 3);
00461         
MiUnmapSinglePage (PpeBase);
00462 
#else
00463 
        MiDownPfnReferenceCount (RootPhysicalPage, 1);
00464 
#endif
00465 
        CurrentProcess->
ForkInProgress = 
NULL;
00466         
UNLOCK_WS (CurrentProcess);
00467         status = STATUS_INSUFFICIENT_RESOURCES;
00468         
goto ErrorReturn4;
00469     }
00470 
00471 
#else
00472 
00473     
00474     
00475     
00476     
00477 
00478     MdlPageDirectory = (
PMDL)&MdlHackPageDirectory[0];
00479 
00480     
MmInitializeMdl(MdlPageDirectory, (PVOID)PDE_BASE, PD_PER_SYSTEM * PAGE_SIZE);
00481     MdlPageDirectory->
MdlFlags |= 
MDL_PAGES_LOCKED;
00482 
00483     MdlPageFrames = (PPFN_NUMBER)(MdlPageDirectory + 1);
00484 
00485     
for (i = 0; i < PD_PER_SYSTEM; i += 1) {
00486         *(MdlPageFrames + i) = PageDirectoryFrames[i];
00487         
MiUpPfnReferenceCount (PageDirectoryFrames[i], 1);
00488     }
00489 
00490     PdePhysicalPage = RootPhysicalPage;
00491 
00492     PdeBase = (
PMMPTE)
MmMapLockedPagesSpecifyCache (MdlPageDirectory,
00493                                                     KernelMode,
00494                                                     MmCached,
00495                                                     NULL,
00496                                                     FALSE,
00497                                                     HighPagePriority);
00498 
00499     
if (PdeBase == 
NULL) {
00500         
for (i = 0; i < PD_PER_SYSTEM; i += 1) {
00501             
MiDownPfnReferenceCount (PageDirectoryFrames[i], 1);
00502         }
00503         CurrentProcess->
ForkInProgress = 
NULL;
00504         
UNLOCK_WS (CurrentProcess);
00505         status = STATUS_INSUFFICIENT_RESOURCES;
00506         
goto ErrorReturn4;
00507     }
00508 
00509 
#endif
00510 
00511     PfnPdPage = 
MI_PFN_ELEMENT (RootPhysicalPage);
00512 
00513 
#if !defined (_WIN64)
00514 
00515     
00516     
00517     
00518 
00519     
MiUpPfnReferenceCount (HyperPhysicalPage, 2);
00520 
00521     HyperBase = (
PMMWSL)
MiMapSinglePage (NULL,
00522                                          HyperPhysicalPage,
00523                                          MmCached,
00524                                          HighPagePriority);
00525 
00526     
if (HyperBase == 
NULL) {
00527         
MiDownPfnReferenceCount (HyperPhysicalPage, 2);
00528 
#if !defined (_X86PAE_)
00529 
        MiDownPfnReferenceCount (RootPhysicalPage, 1);
00530         
MiUnmapSinglePage (PdeBase);
00531 
#else
00532 
        for (i = 0; i < PD_PER_SYSTEM; i += 1) {
00533             
MiDownPfnReferenceCount (PageDirectoryFrames[i], 1);
00534         }
00535         
MmUnmapLockedPages (PdeBase, MdlPageDirectory);
00536 
#endif
00537 
        CurrentProcess->
ForkInProgress = 
NULL;
00538         
UNLOCK_WS (CurrentProcess);
00539         status = STATUS_INSUFFICIENT_RESOURCES;
00540         
goto ErrorReturn4;
00541     }
00542 
#endif
00543 
00544     
00545     
00546     
00547     
00548     
00549 
00550 
#if defined (_WIN64)
00551 
    MdlPage = RootPhysicalPage;
00552 
#else
00553 
    MdlPage = HyperPhysicalPage;
00554 
#endif
00555 
00556     NewPteMappedAddress = (
PMMPTE)
MiMapSinglePage (NULL,
00557                                                    MdlPage,
00558                                                    MmCached,
00559                                                    HighPagePriority);
00560 
00561     
if (NewPteMappedAddress == 
NULL) {
00562 
00563 
#if defined (_WIN64)
00564 
00565         
MiDownPfnReferenceCount (RootPhysicalPage, 3);
00566         
MiUnmapSinglePage (PpeBase);
00567         
MiUnmapSinglePage (PdeBase);
00568 
00569 
#else
00570 
        MiDownPfnReferenceCount (HyperPhysicalPage, 2);
00571         
MiUnmapSinglePage (HyperBase);
00572 
#if !defined (_X86PAE_)
00573 
        MiDownPfnReferenceCount (RootPhysicalPage, 1);
00574         
MiUnmapSinglePage (PdeBase);
00575 
#else
00576 
        for (i = 0; i < PD_PER_SYSTEM; i += 1) {
00577             
MiDownPfnReferenceCount (PageDirectoryFrames[i], 1);
00578         }
00579         
MmUnmapLockedPages (PdeBase, MdlPageDirectory);
00580 
#endif
00581 
00582 
#endif
00583 
00584         CurrentProcess->
ForkInProgress = 
NULL;
00585         
UNLOCK_WS (CurrentProcess);
00586         status = STATUS_INSUFFICIENT_RESOURCES;
00587         
goto ErrorReturn4;
00588     }
00589 
00590     PointerNewPte = NewPteMappedAddress;
00591 
00592     
00593     
00594     
00595     
00596 
00597     ForkProtoPte = CloneProtos;
00598 
00599     LockedForkPte = ForkProtoPte;
00600     
MiLockPagedAddress (LockedForkPte, FALSE);
00601 
00602     CloneHeader->
NumberOfPtes = (ULONG)NumberOfPrivatePages;
00603     CloneHeader->
NumberOfProcessReferences = 1;
00604     CloneHeader->
ClonePtes = CloneProtos;
00605 
00606 
00607 
00608     CloneDescriptor->
StartingVpn = (ULONG_PTR)CloneProtos;
00609     CloneDescriptor->
EndingVpn = (ULONG_PTR)((ULONG_PTR)CloneProtos +
00610                             NumberOfPrivatePages *
00611                               
sizeof(
MMCLONE_BLOCK));
00612     CloneDescriptor->
NumberOfReferences = 0;
00613     CloneDescriptor->
NumberOfPtes = (ULONG)NumberOfPrivatePages;
00614     CloneDescriptor->
CloneHeader = CloneHeader;
00615     CloneDescriptor->
PagedPoolQuotaCharge = 
sizeof(
MMCLONE_BLOCK) *
00616                                 NumberOfPrivatePages;
00617 
00618     
00619     
00620     
00621     
00622 
00623     
MiInsertClone (CloneDescriptor);
00624 
00625     
00626     
00627     
00628     
00629 
00630     Vad = 
MiGetFirstVad (CurrentProcess);
00631     NewVad = FirstNewVad;
00632 
00633     
while (Vad != (
PMMVAD)
NULL) {
00634 
00635         
00636         
00637         
00638         
00639 
00640         
if ((Vad->
u.VadFlags.UserPhysicalPages == 0) &&
00641 
00642             ((Vad->
u.VadFlags.PrivateMemory == 1) ||
00643             (Vad->
u2.VadFlags2.Inherit == 
MM_VIEW_SHARE))) {
00644 
00645             
00646             
00647             
00648             
00649 
00650             
00651             
00652             
00653             
00654             
00655 
00656             NextVad = NewVad->
Parent;
00657 
00658 
00659             
if (Vad->
u.VadFlags.PrivateMemory == 1) {
00660                 *(
PMMVAD_SHORT)NewVad = *(
PMMVAD_SHORT)Vad;
00661                 NewVad->
u.VadFlags.NoChange = 0;
00662             } 
else {
00663                 *NewVad = *Vad;
00664             }
00665 
00666             
if (NewVad->
u.VadFlags.NoChange) {
00667                 
if ((NewVad->
u2.VadFlags2.OneSecured) ||
00668                     (NewVad->
u2.VadFlags2.MultipleSecured)) {
00669 
00670                     
00671                     
00672                     
00673                     
00674 
00675                     NewVad->
u2.VadFlags2.OneSecured = 0;
00676                     NewVad->
u2.VadFlags2.MultipleSecured = 0;
00677                     NewVad->
u2.VadFlags2.StoredInVad = 0;
00678                     NewVad->
u3.List.Flink = 
NULL;
00679                     NewVad->
u3.List.Blink = 
NULL;
00680                 }
00681                 
if (NewVad->
u2.VadFlags2.SecNoChange == 0) {
00682                     NewVad->
u.VadFlags.NoChange = 0;
00683                 }
00684             }
00685             NewVad->
Parent = NextVad;
00686 
00687             
00688             
00689             
00690             
00691 
00692             
if ((Vad->
u.VadFlags.PrivateMemory == 0) &&
00693                 (Vad->
ControlArea != (
PCONTROL_AREA)
NULL)) {
00694 
00695                 
00696                 
00697                 
00698                 
00699 
00700                 
MiUpControlAreaRefs (Vad->
ControlArea);
00701             }
00702 
00703             
00704             
00705             
00706             
00707 
00708             PointerPde = 
MiGetPdeAddress (MI_VPN_TO_VA (Vad->
StartingVpn));
00709             PointerPte = (
volatile PMMPTE) 
MiGetPteAddress (
00710                                           MI_VPN_TO_VA (Vad->
StartingVpn));
00711             LastPte = 
MiGetPteAddress (MI_VPN_TO_VA (Vad->
EndingVpn));
00712             FirstTime = 
TRUE;
00713 
00714             
while ((
PMMPTE)PointerPte <= LastPte) {
00715 
00716                 
00717                 
00718                 
00719                 
00720                 
00721 
00722                 
if ((FirstTime) || 
MiIsPteOnPdeBoundary (PointerPte)) {
00723 
00724                     PointerPpe = 
MiGetPdeAddress (PointerPte);
00725                     PointerPde = 
MiGetPteAddress (PointerPte);
00726 
00727                     
do {
00728 
00729                         
while (!
MiDoesPpeExistAndMakeValid (PointerPpe,
00730                                                             CurrentProcess,
00731                                                             FALSE,
00732                                                             &Waited)) {
00733     
00734                             
00735                             
00736                             
00737     
00738                             PointerPpe += 1;
00739                             PointerPde = 
MiGetVirtualAddressMappedByPte (PointerPpe);
00740                             PointerPte = 
MiGetVirtualAddressMappedByPte (PointerPde);
00741     
00742                             
if ((
PMMPTE)PointerPte > LastPte) {
00743     
00744                                 
00745                                 
00746                                 
00747     
00748                                 
goto AllDone;
00749                             }
00750                         }
00751     
00752                         Waited = 0;
00753     
00754                         
while (!
MiDoesPdeExistAndMakeValid (PointerPde,
00755                                                             CurrentProcess,
00756                                                             FALSE,
00757                                                             &Waited)) {
00758     
00759                             
00760                             
00761                             
00762     
00763                             PointerPde += 1;
00764                             PointerPte = 
MiGetVirtualAddressMappedByPte (PointerPde);
00765     
00766                             
if ((
PMMPTE)PointerPte > LastPte) {
00767     
00768                                 
00769                                 
00770                                 
00771     
00772                                 
goto AllDone;
00773                             }
00774 
#if defined (_WIN64)
00775 
                            if (
MiIsPteOnPdeBoundary (PointerPde)) {
00776                                 PointerPpe = 
MiGetPteAddress (PointerPde);
00777                                 Waited = 1;
00778                                 
break;
00779                             }
00780 
#endif
00781 
                        }
00782     
00783                     } 
while (Waited != 0);
00784 
00785                     FirstTime = 
FALSE;
00786 
00787 
#if defined (_WIN64)
00788 
                    
00789                     
00790                     
00791                     
00792 
00793                     PointerNewPpe = &PpeBase[
MiGetPdeOffset(PointerPte)];
00794 
00795                     
if (PointerNewPpe->
u.Long == 0) {
00796 
00797                         
00798                         
00799                         
00800                         
00801                         
00802 
00803                         ReleasedWorkingSetMutex =
00804                                 
MiDoneWithThisPageGetAnother (&PageDirFrameIndex,
00805                                                               PointerPpe,
00806                                                               CurrentProcess);
00807 
00808                         MI_ZERO_USED_PAGETABLE_ENTRIES (
MI_PFN_ELEMENT(PageDirFrameIndex));
00809 
00810                         
if (ReleasedWorkingSetMutex) {
00811 
00812                             
do {
00813 
00814                                 
MiDoesPpeExistAndMakeValid (PointerPpe,
00815                                                             CurrentProcess,
00816                                                             FALSE,
00817                                                             &Waited);
00818     
00819                                 Waited = 0;
00820     
00821                                 
MiDoesPdeExistAndMakeValid (PointerPde,
00822                                                             CurrentProcess,
00823                                                             FALSE,
00824                                                             &Waited);
00825                             } 
while (Waited != 0);
00826                         }
00827 
00828                         
00829                         
00830                         
00831                         
00832                         
00833                         
00834                         
00835                         
00836                         
00837                         
00838 
00839                         
MiBuildForkPageTable (PageDirFrameIndex,
00840                                               PointerPpe,
00841                                               PointerNewPpe,
00842                                               RootPhysicalPage,
00843                                               PfnPpPage);
00844 
00845                         
00846                         
00847                         
00848                         
00849                         
00850                         
00851                         
00852 
00853                         
MiDownPfnReferenceCount (MdlDirPage, 1);
00854 
00855                         MdlDirPage = PageDirFrameIndex;
00856 
00857                         
ASSERT (PdeBase != NULL);
00858 
00859                         PdeBase = (
PMMPTE)
MiMapSinglePage (PdeBase,
00860                                                            MdlDirPage,
00861                                                            MmCached,
00862                                                            HighPagePriority);
00863 
00864                         
MiUpPfnReferenceCount (MdlDirPage, 1);
00865 
00866                         PointerNewPde = PdeBase;
00867                     }
00868                     
else {
00869                         
ASSERT (PointerNewPpe->
u.Hard.Valid == 1 ||
00870                                 PointerNewPpe->
u.Soft.Transition == 1);
00871 
00872                         
if (PointerNewPpe->
u.Hard.Valid == 1) {
00873                             PageDirFrameIndex = 
MI_GET_PAGE_FRAME_FROM_PTE (PointerNewPpe);
00874                         }
00875                         
else {
00876                             PageDirFrameIndex = 
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerNewPpe);
00877                         }
00878                     }
00879 
00880                     
00881                     
00882                     
00883                     
00884                     
00885 
00886                     PointerNewPde = (
PMMPTE)((ULONG_PTR)
PAGE_ALIGN(PointerNewPde) |
00887                                             
BYTE_OFFSET (PointerPde));
00888 
00889                     PdePhysicalPage = PageDirFrameIndex;
00890                 
00891                     PfnPdPage = 
MI_PFN_ELEMENT (PdePhysicalPage);
00892 
00893                     UsedPageDirectoryEntries = (PVOID)PfnPdPage;
00894 
#endif
00895 
00896                     
00897                     
00898                     
00899                     
00900 
00901                     PpePdeOffset = 
MiGetPpePdeOffset(
MiGetVirtualAddressMappedByPte(PointerPte));
00902                     PointerNewPde = &PdeBase[PpePdeOffset];
00903 
00904                     
if (PointerNewPde->
u.Long == 0) {
00905 
00906                         
00907                         
00908                         
00909                         
00910                         
00911 
00912                         ReleasedWorkingSetMutex =
00913                                 
MiDoneWithThisPageGetAnother (&PageFrameIndex,
00914                                                               PointerPde,
00915                                                               CurrentProcess);
00916 
00917                         
if (ReleasedWorkingSetMutex) {
00918 
00919                             
do {
00920 
00921                                 
MiDoesPpeExistAndMakeValid (PointerPpe,
00922                                                             CurrentProcess,
00923                                                             FALSE,
00924                                                             &Waited);
00925     
00926                                 Waited = 0;
00927     
00928                                 
MiDoesPdeExistAndMakeValid (PointerPde,
00929                                                             CurrentProcess,
00930                                                             FALSE,
00931                                                             &Waited);
00932                             } 
while (Waited != 0);
00933                         }
00934 
00935                         
00936                         
00937                         
00938                         
00939                         
00940                         
00941                         
00942                         
00943                         
00944                         
00945 
00946 
#if defined (_X86PAE_)
00947 
                        PdePhysicalPage = PageDirectoryFrames[MiGetPdPteOffset(
MiGetVirtualAddressMappedByPte(PointerPte))];
00948                         PfnPdPage = 
MI_PFN_ELEMENT (PdePhysicalPage);
00949 
#endif
00950 
00951                         
MiBuildForkPageTable (PageFrameIndex,
00952                                               PointerPde,
00953                                               PointerNewPde,
00954                                               PdePhysicalPage,
00955                                               PfnPdPage);
00956 
00957 
#if defined (_WIN64)
00958 
                        MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageDirectoryEntries);
00959 
#endif
00960 
00961                         
00962                         
00963                         
00964                         
00965                         
00966                         
00967                         
00968 
00969                         
ASSERT (NewPteMappedAddress != NULL);
00970 
00971                         
MiDownPfnReferenceCount (MdlPage, 1);
00972 
00973                         MdlPage = PageFrameIndex;
00974 
00975                         PointerNewPte = (
PMMPTE)
MiMapSinglePage (NewPteMappedAddress,
00976                                                                  MdlPage,
00977                                                                  MmCached,
00978                                                                  HighPagePriority);
00979                     
00980                         
ASSERT (PointerNewPte != NULL);
00981 
00982                         
MiUpPfnReferenceCount (MdlPage, 1);
00983                     }
00984 
00985                     
00986                     
00987                     
00988                     
00989                     
00990 
00991                     PointerNewPte = (
PMMPTE)((ULONG_PTR)
PAGE_ALIGN(PointerNewPte) |
00992                                             
BYTE_OFFSET (PointerPte));
00993 
00994 
#ifdef _WIN64
00995 
                    UsedPageTableEntries = (PVOID)
MI_PFN_ELEMENT((PFN_NUMBER)PointerNewPde->
u.Hard.PageFrameNumber);
00996 
#else
00997 
#if !defined (_X86PAE_)
00998 
                    UsedPageTableEntries = (PVOID)&HyperBase->
UsedPageTableEntries
00999                                                 [
MiGetPteOffset( PointerPte )];
01000 
#else
01001 
                    UsedPageTableEntries = (PVOID)&HyperBase->
UsedPageTableEntries
01002                                                 [
MiGetPpePdeOffset(
MiGetVirtualAddressMappedByPte(PointerPte))];
01003 
#endif
01004 
#endif
01005 
01006                 }
01007 
01008                 
01009                 
01010                 
01011 
01012                 
if (
PAGE_ALIGN (ForkProtoPte) != 
PAGE_ALIGN (LockedForkPte)) {
01013                     
MiUnlockPagedAddress (LockedForkPte, FALSE);
01014                     LockedForkPte = ForkProtoPte;
01015                     
MiLockPagedAddress (LockedForkPte, FALSE);
01016                 }
01017 
01018                 
MiMakeSystemAddressValid (PointerPte, CurrentProcess);
01019 
01020                 PteContents = *PointerPte;
01021 
01022                 
01023                 
01024                 
01025 
01026                 
if (PteContents.
u.Long == 0) {
01027                     NOTHING;
01028 
01029                 } 
else if (PteContents.
u.Hard.Valid == 1) {
01030 
01031                     
01032                     
01033                     
01034 
01035                     Pfn2 = 
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
01036                     VirtualAddress = 
MiGetVirtualAddressMappedByPte (PointerPte);
01037                     WorkingSetIndex = 
MiLocateWsle (VirtualAddress,
01038                                                     MmWorkingSetList,
01039                                                     Pfn2->
u1.WsIndex);
01040 
01041                     
ASSERT (WorkingSetIndex != WSLE_NULL_INDEX);
01042 
01043                     
if (Pfn2->
u3.e1.PrototypePte == 1) {
01044 
01045                         
01046                         
01047                         
01048 
01049                         
01050                         
01051                         
01052                         
01053                         
01054                         
01055                         
01056                         
01057                         
01058                         
01059 
01060                         
if (
MmWsle[WorkingSetIndex].
u1.e1.SameProtectAsProto
01061                                                                         == 0) {
01062 
01063                             
01064                             
01065                             
01066                             
01067 
01068                             TempPte.
u.Long = 0;
01069                             TempPte.
u.Soft.Protection =
01070                                 
MI_GET_PROTECTION_FROM_WSLE(&MmWsle[WorkingSetIndex]);
01071                             TempPte.
u.Soft.PageFileHigh = 
MI_PTE_LOOKUP_NEEDED;
01072 
01073                         } 
else {
01074 
01075                             
01076                             
01077                             
01078 
01079                             TempPte.
u.Long = 
MiProtoAddressForPte (
01080                                                             Pfn2->
PteAddress);
01081  
01082  
01083                         }
01084 
01085                         TempPte.
u.Proto.Prototype = 1;
01086                         
MI_WRITE_INVALID_PTE (PointerNewPte, TempPte);
01087 
01088                         
01089                         
01090                         
01091                         
01092 
01093                         
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries);
01094 
01095                         
01096                         
01097                         
01098                         
01099                         
01100 
01101                         
if (
MiLocateCloneAddress ((PVOID)Pfn2->
PteAddress) !=
01102                                     (
PMMCLONE_DESCRIPTOR)
NULL) {
01103 
01104                             
01105                             
01106                             
01107                             
01108 
01109                             CloneProto = (
PMMCLONE_BLOCK)Pfn2->
PteAddress;
01110 
01111                             
MiUpCloneProtoRefCount (CloneProto,
01112                                                     CurrentProcess);
01113 
01114                             
if (
PAGE_ALIGN (ForkProtoPte) !=
01115                                                     
PAGE_ALIGN (LockedForkPte)) {
01116                                 
MiUnlockPagedAddress (LockedForkPte, FALSE);
01117                                 LockedForkPte = ForkProtoPte;
01118                                 
MiLockPagedAddress (LockedForkPte, FALSE);
01119                             }
01120 
01121                             
MiMakeSystemAddressValid (PointerPte,
01122                                                       CurrentProcess);
01123                         }
01124 
01125                     } 
else {
01126 
01127                         
01128                         
01129                         
01130                         
01131                         
01132                         
01133 
01134                         
MI_MAKE_VALID_PTE_WRITE_COPY (PointerPte);
01135 
01136                         ForkProtoPte->ProtoPte = *PointerPte;
01137                         ForkProtoPte->CloneRefCount = 2;
01138 
01139                         
01140                         
01141                         
01142                         
01143 
01144                         Pfn2->
PteAddress = &ForkProtoPte->ProtoPte;
01145                         Pfn2->
u3.e1.PrototypePte = 1;
01146 
01147                         ContainingPte = 
MiGetPteAddress(&ForkProtoPte->ProtoPte);
01148                         
if (ContainingPte->
u.Hard.Valid == 0) {
01149 
#if !defined (_WIN64)
01150 
                            if (!
NT_SUCCESS(MiCheckPdeForPagedPool (&ForkProtoPte->ProtoPte))) {
01151 
#endif
01152 
                                KeBugCheckEx (MEMORY_MANAGEMENT,
01153                                               0x61940, 
01154                                               (ULONG_PTR)&ForkProtoPte->ProtoPte,
01155                                               (ULONG_PTR)ContainingPte->
u.Long,
01156                                               (ULONG_PTR)
MiGetVirtualAddressMappedByPte(&ForkProtoPte->ProtoPte));
01157 
#if !defined (_WIN64)
01158 
                            }
01159 
#endif
01160 
                        }
01161                         Pfn2->
PteFrame = 
MI_GET_PAGE_FRAME_FROM_PTE (ContainingPte);
01162 
01163 
01164                         
01165                         
01166                         
01167                         
01168                         
01169 
01170                         PfnForkPtePage = 
MI_PFN_ELEMENT (
01171                                             ContainingPte->
u.Hard.PageFrameNumber );
01172 
01173                         
MiUpForkPageShareCount (PfnForkPtePage);
01174 
01175                         
01176                         
01177                         
01178                         
01179 
01180                         
MI_MAKE_PROTECT_WRITE_COPY (Pfn2->
OriginalPte);
01181 
01182                         
01183                         
01184                         
01185                         
01186                         
01187 
01188                         
MmWsle[WorkingSetIndex].
u1.e1.Protection =
01189                             
MI_GET_PROTECTION_FROM_SOFT_PTE(&Pfn2->
OriginalPte);
01190 
01191                         
MmWsle[WorkingSetIndex].
u1.e1.SameProtectAsProto = 1;
01192 
01193                         TempPte.
u.Long = 
MiProtoAddressForPte (Pfn2->
PteAddress);
01194                         TempPte.
u.Proto.Prototype = 1;
01195                         
MI_WRITE_INVALID_PTE (PointerNewPte, TempPte);
01196 
01197                         
01198                         
01199                         
01200                         
01201 
01202                         
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries);
01203 
01204                         
01205                         
01206                         
01207 
01208                         CurrentProcess->
NumberOfPrivatePages -= 1;
01209 
01210                         ForkProtoPte += 1;
01211                         NumberOfForkPtes += 1;
01212 
01213                     }
01214 
01215                 } 
else if (PteContents.
u.Soft.Prototype == 1) {
01216 
01217                     
01218                     
01219                     
01220                     
01221                     
01222 
01223                     
MI_WRITE_INVALID_PTE (PointerNewPte, PteContents);
01224 
01225                     
01226                     
01227                     
01228                     
01229 
01230                     
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries);
01231 
01232                     
01233                     
01234                     
01235                     
01236                     
01237 
01238                     CloneProto = (
PMMCLONE_BLOCK)(
MiPteToProto(PointerPte));
01239 
01240                     
if (
MiLocateCloneAddress ((PVOID)CloneProto) !=
01241                                 (
PMMCLONE_DESCRIPTOR)
NULL) {
01242 
01243                         
01244                         
01245                         
01246                         
01247 
01248                         
MiUpCloneProtoRefCount (CloneProto,
01249                                                 CurrentProcess);
01250 
01251                         
if (
PAGE_ALIGN (ForkProtoPte) !=
01252                                                 
PAGE_ALIGN (LockedForkPte)) {
01253                             
MiUnlockPagedAddress (LockedForkPte, FALSE);
01254                             LockedForkPte = ForkProtoPte;
01255                             
MiLockPagedAddress (LockedForkPte, FALSE);
01256                         }
01257 
01258                         
MiMakeSystemAddressValid (PointerPte,
01259                                                     CurrentProcess);
01260                     }
01261 
01262                 } 
else if (PteContents.
u.Soft.Transition == 1) {
01263 
01264                     
01265                     
01266                     
01267 
01268                     
if (
MiHandleForkTransitionPte (PointerPte,
01269                                                    PointerNewPte,
01270                                                    ForkProtoPte)) {
01271                         
01272                         
01273                         
01274 
01275                         
continue;
01276                     }
01277 
01278                     
01279                     
01280                     
01281                     
01282 
01283                     
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries);
01284 
01285                     
01286                     
01287                     
01288 
01289                     CurrentProcess->
NumberOfPrivatePages -= 1;
01290 
01291                     ForkProtoPte += 1;
01292                     NumberOfForkPtes += 1;
01293 
01294                 } 
else {
01295 
01296                     
01297                     
01298                     
01299 
01300                     
if (
IS_PTE_NOT_DEMAND_ZERO (PteContents)) {
01301 
01302                         
if (PteContents.
u.Soft.Protection == 
MM_DECOMMIT) {
01303 
01304                             
01305                             
01306                             
01307                             
01308                             
01309 
01310                             
MI_WRITE_INVALID_PTE (PointerNewPte, PteContents);
01311                         } 
else {
01312 
01313                             
01314                             
01315                             
01316                             
01317                             
01318                             
01319 
01320                             ForkProtoPte->ProtoPte = PteContents;
01321 
01322                             
01323                             
01324                             
01325 
01326                             
MI_MAKE_PROTECT_WRITE_COPY (ForkProtoPte->ProtoPte);
01327 
01328                             ForkProtoPte->CloneRefCount = 2;
01329 
01330                             TempPte.
u.Long =
01331                                  
MiProtoAddressForPte (&ForkProtoPte->ProtoPte);
01332 
01333                             TempPte.
u.Proto.Prototype = 1;
01334 
01335                             
MI_WRITE_INVALID_PTE (PointerPte, TempPte);
01336                             
MI_WRITE_INVALID_PTE (PointerNewPte, TempPte);
01337 
01338                             
01339                             
01340                             
01341 
01342                             CurrentProcess->
NumberOfPrivatePages -= 1;
01343 
01344                             ForkProtoPte += 1;
01345                             NumberOfForkPtes += 1;
01346                         }
01347                     } 
else {
01348 
01349                         
01350                         
01351                         
01352                         
01353 
01354                         
MI_WRITE_INVALID_PTE (PointerNewPte, PteContents);
01355                     }
01356 
01357                     
01358                     
01359                     
01360                     
01361 
01362                     
MI_INCREMENT_USED_PTES_BY_HANDLE (UsedPageTableEntries);
01363                 }
01364 
01365                 PointerPte += 1;
01366                 PointerNewPte += 1;
01367 
01368             }  
01369 AllDone:
01370             NewVad = NewVad->
Parent;
01371         }
01372         Vad = 
MiGetNextVad (Vad);
01373 
01374     } 
01375 
01376     
01377     
01378     
01379 
01380     
MiUnlockPagedAddress (LockedForkPte, FALSE);
01381 
01382     
01383     
01384     
01385 
01386 
#if defined (_WIN64)
01387 
    MiUnmapSinglePage (PpeBase);
01388 
#endif
01389 
01390 
#if !defined (_X86PAE_)
01391 
    MiUnmapSinglePage (PdeBase);
01392 
#else
01393 
    MmUnmapLockedPages (PdeBase, MdlPageDirectory);
01394 
#endif
01395 
01396 
#if !defined (_WIN64)
01397 
    MiUnmapSinglePage (HyperBase);
01398 
#endif
01399 
01400     
MiUnmapSinglePage (NewPteMappedAddress);
01401 
01402 
#if defined (_WIN64)
01403 
    MiDownPfnReferenceCount (RootPhysicalPage, 1);
01404 
#endif
01405 
01406 
#if defined (_X86PAE_)
01407 
    for (i = 0; i < PD_PER_SYSTEM; i += 1) {
01408         
MiDownPfnReferenceCount (PageDirectoryFrames[i], 1);
01409     }
01410 
#else
01411 
    MiDownPfnReferenceCount (MdlDirPage, 1);
01412 
#endif
01413 
01414 
#if !defined (_WIN64)
01415 
    MiDownPfnReferenceCount (HyperPhysicalPage, 1);
01416 
#endif
01417 
01418     
MiDownPfnReferenceCount (MdlPage, 1);
01419 
01420     
01421     
01422     
01423 
01424     
ASSERT ((SPFN_NUMBER)CurrentProcess->
NumberOfPrivatePages >= 0);
01425 
01426     ProcessToInitialize->NumberOfPrivatePages =
01427                                           CurrentProcess->
NumberOfPrivatePages;
01428 
01429     
ASSERT (NumberOfForkPtes <= CloneDescriptor->NumberOfPtes);
01430 
01431     
if (NumberOfForkPtes != 0) {
01432 
01433         
01434         
01435         
01436         
01437 
01438         CloneHeader->
NumberOfPtes = NumberOfForkPtes;
01439         CloneDescriptor->
NumberOfReferences = NumberOfForkPtes;
01440         CloneDescriptor->
NumberOfPtes = NumberOfForkPtes;
01441 
01442     } 
else {
01443 
01444         
01445         
01446         
01447         
01448         
01449         
01450 
01451         
MiRemoveClone (CloneDescriptor);
01452 
01453         
UNLOCK_WS (CurrentProcess);
01454 
01455         
ExFreePool (CloneDescriptor->
CloneHeader->
ClonePtes);
01456 
01457         
ExFreePool (CloneDescriptor->
CloneHeader);
01458 
01459         
01460         
01461         
01462         
01463 
01464         
PsReturnPoolQuota (CurrentProcess,
01465                            PagedPool,
01466                            CloneDescriptor->
PagedPoolQuotaCharge);
01467 
01468         
PsReturnPoolQuota (CurrentProcess, NonPagedPool, 
sizeof(
MMCLONE_HEADER));
01469 
01470         
ExFreePool (CloneDescriptor);
01471 
01472         
LOCK_WS (CurrentProcess);
01473     }
01474 
01475     
MiDownShareCountFlushEntireTb (PageFrameIndex);
01476 
01477 
#if defined (_WIN64)
01478 
    MiDownShareCountFlushEntireTb (PageDirFrameIndex);
01479 
#endif
01480 
01481     PageFrameIndex = (PFN_NUMBER)-1;
01482     PageDirFrameIndex = (PFN_NUMBER)-1;
01483 
01484     
01485     
01486     
01487 
01488     Clone = 
MiGetFirstClone ();
01489     CloneList = &FirstNewClone;
01490     CloneFailed = 
FALSE;
01491 
01492     
while (Clone != (
PMMCLONE_DESCRIPTOR)
NULL) {
01493 
01494         
01495         
01496         
01497 
01498         
MiUpCloneProcessRefCount (Clone);
01499 
01500         
do {
01501             NewClone = 
ExAllocatePoolWithTag (NonPagedPool,
01502                                               
sizeof( 
MMCLONE_DESCRIPTOR),
01503                                               '  mM');
01504 
01505             
if (NewClone != 
NULL) {
01506                 
break;
01507             }
01508 
01509             
01510             
01511             
01512             
01513             
01514             
01515             
01516             
01517             
01518 
01519             CloneFailed = 
TRUE;
01520             status = STATUS_INSUFFICIENT_RESOURCES;
01521 
01522             
KeDelayExecutionThread (KernelMode,
01523                                     FALSE,
01524                                     (PLARGE_INTEGER)&MmShortTime);
01525             
continue;
01526         } 
while (
TRUE);
01527 
01528         *NewClone = *Clone;
01529 
01530         *CloneList = NewClone;
01531         CloneList = &NewClone->
Parent;
01532         Clone = 
MiGetNextClone (Clone);
01533     }
01534 
01535     *CloneList = (
PMMCLONE_DESCRIPTOR)
NULL;
01536 
01537     
01538     
01539     
01540     
01541     
01542 
01543     
UNLOCK_WS (CurrentProcess);
01544 
01545     CurrentProcess->
ForkInProgress = 
NULL;
01546 
01547     
UNLOCK_ADDRESS_SPACE (CurrentProcess);
01548 
01549     
01550     
01551     
01552     
01553     
01554     
01555 
01556 
01557     
01558     
01559     
01560     
01561 
01562     
if (Attached) {
01563         
KeDetachProcess ();
01564         Attached = 
FALSE;
01565     }
01566 
01567     
if (
PsGetCurrentProcess() != ProcessToInitialize) {
01568         Attached = 
TRUE;
01569         
KeAttachProcess (&ProcessToInitialize->Pcb);
01570     }
01571 
01572     CurrentProcess = ProcessToInitialize;
01573 
01574     
01575     
01576     
01577     
01578 
01579     Vad = FirstNewVad;
01580     VadInsertFailed = 
FALSE;
01581 
01582     
LOCK_WS (CurrentProcess);
01583 
01584     
while (Vad != (
PMMVAD)
NULL) {
01585 
01586         NextVad = Vad->
Parent;
01587 
01588         
try {
01589 
01590             
if (VadInsertFailed) {
01591                 Vad->
u.VadFlags.CommitCharge = 
MM_MAX_COMMIT;
01592             }
01593 
01594             
MiInsertVad (Vad);
01595 
01596         } except (EXCEPTION_EXECUTE_HANDLER) {
01597 
01598             
01599             
01600             
01601             
01602             
01603             
01604 
01605             VadInsertFailed = 
TRUE;
01606             status = GetExceptionCode();
01607 
01608             
01609             
01610             
01611 
01612             
continue;
01613         }
01614 
01615         
01616         
01617         
01618 
01619         CurrentProcess->
VirtualSize += 
PAGE_SIZE +
01620                             ((Vad->
EndingVpn - Vad->
StartingVpn) >> 
PAGE_SHIFT);
01621 
01622         Vad = NextVad;
01623     }
01624 
01625     
UNLOCK_WS (CurrentProcess);
01626     
01627 
01628     
01629     
01630     
01631 
01632     CurrentProcess->
PeakVirtualSize = CurrentProcess->
VirtualSize;
01633 
01634     Clone = FirstNewClone;
01635     TotalPagedPoolCharge = 0;
01636     TotalNonPagedPoolCharge = 0;
01637 
01638     
while (Clone != (
PMMCLONE_DESCRIPTOR)
NULL) {
01639 
01640         NextClone = Clone->
Parent;
01641         
MiInsertClone (Clone);
01642 
01643         
01644         
01645         
01646         
01647 
01648         TotalPagedPoolCharge += Clone->
PagedPoolQuotaCharge;
01649         TotalNonPagedPoolCharge += 
sizeof(
MMCLONE_HEADER);
01650 
01651         Clone = NextClone;
01652     }
01653 
01654     
if (CloneFailed || VadInsertFailed) {
01655 
01656         CurrentProcess->
ForkWasSuccessful = 
MM_FORK_FAILED;
01657 
01658         
if (Attached) {
01659             
KeDetachProcess ();
01660         }
01661         KdPrint((
"MMFORK: vad insert failed\n"));
01662 
01663         
return status;
01664     }
01665 
01666     
try {
01667 
01668         PageTablePage = 1;
01669         
PsChargePoolQuota (CurrentProcess, PagedPool, TotalPagedPoolCharge);
01670         PageTablePage = 0;
01671         
PsChargePoolQuota (CurrentProcess, NonPagedPool, TotalNonPagedPoolCharge);
01672 
01673     } except (EXCEPTION_EXECUTE_HANDLER) {
01674 
01675         
if (PageTablePage == 0) {
01676             
PsReturnPoolQuota (CurrentProcess, PagedPool, TotalPagedPoolCharge);
01677         }
01678         KdPrint((
"MMFORK: pool quota failed\n"));
01679 
01680         CurrentProcess->
ForkWasSuccessful = 
MM_FORK_FAILED;
01681 
01682         
if (Attached) {
01683             
KeDetachProcess ();
01684         }
01685         
return GetExceptionCode();
01686     }
01687 
01688     
ASSERT (ProcessToClone->ForkWasSuccessful == MM_FORK_SUCCEEDED);
01689     
ASSERT (CurrentProcess->
ForkWasSuccessful == MM_FORK_SUCCEEDED);
01690 
01691     
if (Attached) {
01692         
KeDetachProcess ();
01693     }
01694 
01695 
#if DBG
01696 
    if (MmDebug & 
MM_DBG_FORK) {
01697         
DbgPrint(
"ending clone operation process to clone = %lx\n",
01698             ProcessToClone);
01699     }
01700 
#endif //DBG
01701 
01702     
return STATUS_SUCCESS;
01703 
01704     
01705     
01706     
01707 
01708 ErrorReturn4:
01709         
if (PageTablePage == 2) {
01710             NOTHING;
01711         }
01712         
else if (PageTablePage == 1) {
01713             
PsReturnPoolQuota (CurrentProcess, PagedPool, 
sizeof(
MMCLONE_BLOCK) *
01714                                 NumberOfPrivatePages);
01715         }
01716         
else {
01717             
ASSERT (PageTablePage == 0);
01718             
PsReturnPoolQuota (CurrentProcess, PagedPool, 
sizeof(
MMCLONE_BLOCK) *
01719                                 NumberOfPrivatePages);
01720             
PsReturnPoolQuota (CurrentProcess, NonPagedPool, 
sizeof(
MMCLONE_HEADER));
01721         }
01722 
01723         NewVad = FirstNewVad;
01724         
while (NewVad != 
NULL) {
01725             Vad = NewVad->
Parent;
01726             
ExFreePool (NewVad);
01727             NewVad = Vad;
01728         }
01729 
01730         
ExFreePool (CloneDescriptor);
01731 ErrorReturn3:
01732         
ExFreePool (CloneHeader);
01733 ErrorReturn2:
01734         
ExFreePool (CloneProtos);
01735 ErrorReturn1:
01736         
UNLOCK_ADDRESS_SPACE (CurrentProcess);
01737         
ASSERT (CurrentProcess->
ForkWasSuccessful == MM_FORK_SUCCEEDED);
01738         
if (Attached) {
01739             
KeDetachProcess ();
01740         }
01741         
return status;
01742 }