00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
#include "mi.h"
00027 
00028 extern ULONG 
MMVADKEY;
00029 
00030 
#if defined(_MIALT4K_)
00031 
00032 
VOID
00033 MiCheckPoint(ULONG Number);
00034 
00035 
VOID
00036 MiCheckPointBreak(VOID);
00037 
00038 
00039 ULONG MmCheckPointNumber = 100;
00040 PVOID MmAddressBreak = (PVOID)0x7ecd0000;
00041 LOGICAL _MiMakeRtlBoot = 
FALSE;
00042 
00043 ULONG
00044 MiFindProtectionForNativePte( 
00045     PVOID VirtualAddress
00046     );
00047 
00048 
VOID
00049 MiFillZeroFor4kPage (
00050     IN PVOID BaseAddress,
00051     IN 
PEPROCESS Process
00052     );
00053 
00054 MiCheckPointBreakVirtualAddress (
00055     PVOID VirtualAddress
00056 );
00057 
00058 
VOID
00059 MiResetAccessBitForNativePtes(
00060     IN PVOID StartVirtual,
00061     IN PVOID EndVirtual,
00062     IN 
PEPROCESS Process
00063     );
00064 
00065 
NTSTATUS
00066 
MiMapViewOfDataSection (
00067     IN 
PCONTROL_AREA ControlArea,
00068     IN 
PEPROCESS Process,
00069     IN PVOID *CapturedBase,
00070     IN PLARGE_INTEGER SectionOffset,
00071     IN PSIZE_T CapturedViewSize,
00072     IN 
PSECTION Section,
00073     IN SECTION_INHERIT InheritDisposition,
00074     IN ULONG ProtectionMask,
00075     IN SIZE_T CommitSize,
00076     IN ULONG_PTR ZeroBits,
00077     IN ULONG AllocationType,
00078     OUT PBOOLEAN ReleasedWsMutex
00079     );
00080 
00081 BOOLEAN
00082 MiIsSplitPage(
00083     IN PVOID Virtual
00084     );
00085 
00086 
VOID
00087 MiCopyOnWriteFor4kPage(
00088     PVOID VirtualAddress,
00089     
PEPROCESS Process
00090     
00091     );
00092 
00093 
VOID
00094 MiCheckDemandZeroCopyOnWriteFor4kPage(
00095     PVOID VirtualAddress,
00096     
PEPROCESS Process
00097     );
00098 
00099 
VOID
00100 MiCheckVirtualAddressFor4kPage(
00101     PVOID VirtualAddress,
00102     
PEPROCESS Process
00103     );
00104 
00105 
MmX86Fault (
00106     IN BOOLEAN StoreInstruction,
00107     IN PVOID VirtualAddress, 
00108     IN KPROCESSOR_MODE PreviousMode,
00109     IN PVOID TrapInformation
00110     )
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 {
00152     
PMMPTE PointerAltPte;
00153     
MMPTE AltPteContents;
00154     
MMPTE PteContents;
00155     
PMMPTE PointerPte;
00156     
PMMPTE PointerPde;
00157     
PMMPTE PointerPpe;
00158     
PMMPTE PointerProtoPte = (
PMMPTE)
NULL;
00159     ULONG ProtectCode;
00160     
MMPTE TempPte;
00161     ULONG NewPteProtection = 0;
00162     ULONG AteProtection;
00163     LOGICAL ExecutionFault = 
FALSE;
00164     LOGICAL FillZero = 
FALSE;
00165     LOGICAL SetNewProtection = 
FALSE;
00166     LOGICAL PageIsSplit = 
FALSE;
00167     
PEPROCESS CurrentProcess;
00168     
PWOW64_PROCESS Wow64Process;
00169     KIRQL PreviousIrql;
00170     KIRQL OldIrql;
00171     
NTSTATUS status;
00172     
PMMINPAGE_SUPPORT ReadBlock;
00173     ULONG Waited;
00174     ULONG OriginalProtection;
00175     ULONGLONG ProtectionMaskOriginal;
00176     
PMMPTE ProtoPte;
00177     
PMMPFN Pfn1;
00178     ULONG i;
00179 
00180     
00181     
00182     
00183 
00184     MiCheckPointBreakVirtualAddress (VirtualAddress);
00185 
00186     PreviousIrql = KeGetCurrentIrql ();
00187     
00188     
ASSERT (PreviousIrql <= APC_LEVEL);
00189 
00190     CurrentProcess = 
PsGetCurrentProcess ();
00191 
00192     Wow64Process = CurrentProcess->
Wow64Process;
00193 
00194     
ASSERT (VirtualAddress < (PVOID)_MAX_WOW64_ADDRESS);
00195 
00196     
if (StoreInstruction == 2) { 
00197         ExecutionFault = 
TRUE;
00198         StoreInstruction = 
FALSE;
00199     }
00200 
00201     
00202     
00203     
00204 
00205     
LOCK_ALTERNATE_TABLE (Wow64Process);
00206 
00207     
00208     
00209     
00210 
00211     
if (
MI_CHECK_BIT(Wow64Process->AltPermBitmap, 
00212                      
MI_VA_TO_VPN(VirtualAddress)) == 0) { 
00213 
00214         MiCheckVirtualAddressFor4kPage(VirtualAddress, CurrentProcess);
00215 
00216     }
00217 
00218     
00219     
00220     
00221 
00222     PointerPte = 
MiGetPteAddress(VirtualAddress);
00223     PointerAltPte = 
MiGetAltPteAddress(VirtualAddress);
00224 
00225     
00226     
00227     
00228 
00229     AltPteContents = *PointerAltPte;
00230 
00231     
00232     
00233     
00234 
00235     
if (AltPteContents.
u.Long == 0) {
00236 
00237         MiCheckPoint(10);
00238 
00239         
00240         
00241         
00242 
00243         
LOCK_WS (CurrentProcess);
00244 
00245         ProtoPte = 
MiCheckVirtualAddress (VirtualAddress, &OriginalProtection);
00246 
00247         
if (OriginalProtection == 
MM_UNKNOWN_PROTECTION) {
00248 
00249             
if (!
MI_IS_PHYSICAL_ADDRESS(ProtoPte)) {
00250                 PointerPde = 
MiGetPteAddress (ProtoPte);
00251                 
LOCK_PFN (OldIrql);
00252                 
if (PointerPde->
u.Hard.Valid == 0) {
00253                     
MiMakeSystemAddressValidPfn (ProtoPte);
00254                 }
00255                 Pfn1 = 
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
00256                 Pfn1->
u3.e2.ReferenceCount += 1;
00257                 
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
00258                 
UNLOCK_PFN (OldIrql);
00259             }
00260 
00261             OriginalProtection = 
00262                 
MiMakeProtectionMask(
MiGetPageProtection(ProtoPte, CurrentProcess));
00263 
00264             
00265             
00266             
00267 
00268             
if (!
MI_IS_PHYSICAL_ADDRESS(ProtoPte)) {
00269                 
LOCK_PFN (OldIrql);
00270                 
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
00271                 Pfn1->
u3.e2.ReferenceCount -= 1;
00272                 
UNLOCK_PFN (OldIrql);
00273             }
00274         }
00275         
00276         
UNLOCK_WS (CurrentProcess);
00277 
00278         
if (OriginalProtection != 
MM_NOACCESS) {
00279 
00280             ProtectionMaskOriginal = 
MiMakeProtectionAteMask (OriginalProtection);
00281             ProtectionMaskOriginal |= 
MM_ATE_COMMIT;
00282 
00283             AltPteContents.
u.Long = ProtectionMaskOriginal;
00284             AltPteContents.
u.Alt.Protection = OriginalProtection;
00285 
00286             
00287             
00288             
00289 
00290             PointerAltPte->u.Long = AltPteContents.
u.Long;
00291         }
00292     } 
00293 
00294     
if (AltPteContents.
u.Alt.NoAccess != 0) {
00295 
00296         
00297         
00298         
00299 
00300         status = STATUS_ACCESS_VIOLATION;
00301         
00302         
goto return_status;
00303 
00304     }
00305     
00306     
if (AltPteContents.
u.Alt.PteIndirect != 0) {
00307 
00308         MiCheckPoint(3);
00309 
00310         
00311         
00312         
00313 
00314         PointerPde = 
MiGetPdeAddress(VirtualAddress);
00315         PointerPpe = 
MiGetPpeAddress(VirtualAddress);
00316 
00317         
00318         
00319         
00320         
00321 
00322         
LOCK_WS (CurrentProcess);
00323 
00324         (
VOID)
MiMakePpeExistAndMakeValid (PointerPpe,
00325                                           CurrentProcess,
00326                                           FALSE);
00327     
00328         (
VOID)
MiMakePdeExistAndMakeValid (PointerPde,
00329                                           CurrentProcess,
00330                                           FALSE);
00331 
00332         
UNLOCK_WS (CurrentProcess);
00333 
00334         PointerPte = (
PMMPTE)(AltPteContents.
u.Alt.PteOffset + PTE_UBASE);
00335 
00336         VirtualAddress = 
MiGetVirtualAddressMappedByPte(PointerPte);
00337 
00338         
goto Check_Pte;
00339 
00340     }
00341         
00342     
if ((_MiMakeRtlBoot == 
TRUE) && (AltPteContents.
u.Alt.Commit == 0)) {
00343       
00344         
00345         
00346         
00347         
00348         
00349         
00350 
00351         MiCheckPoint(0);
00352 
00353         PointerAltPte->u.Alt.Commit = 1;
00354 
00355         AltPteContents = *PointerAltPte;
00356 
00357     }
00358 
00359     
if (AltPteContents.
u.Alt.Commit == 0) {
00360         
00361         
00362         
00363         
00364 
00365         status = STATUS_ACCESS_VIOLATION;
00366 
00367         
goto return_status;
00368 
00369     }
00370 
00371     
00372     
00373     
00374 
00375     PageIsSplit = MiIsSplitPage(VirtualAddress);
00376 
00377     
00378     
00379     
00380 
00381     NewPteProtection = MiFindProtectionForNativePte (VirtualAddress);
00382 
00383 Check_Pte:
00384 
00385     
00386     
00387     
00388 
00389     
LOCK_WS (CurrentProcess);
00390 
00391     
00392     
00393     
00394 
00395     PointerPde = 
MiGetPdeAddress(VirtualAddress);
00396     PointerPpe = 
MiGetPpeAddress(VirtualAddress);
00397 
00398     
if (
MiDoesPpeExistAndMakeValid (PointerPpe,
00399                                     CurrentProcess,
00400                                     FALSE,
00401                                     &Waited) == 
FALSE) {
00402         PteContents.
u.Long = 0;
00403     
00404     } 
else if (
MiDoesPdeExistAndMakeValid (PointerPde,
00405                                            CurrentProcess,
00406                                            FALSE,
00407                                            &Waited) == 
FALSE) {
00408 
00409         PteContents.
u.Long = 0;
00410 
00411     } 
else {
00412 
00413         
00414         
00415         
00416 
00417         PteContents = *PointerPte;
00418 
00419     }
00420 
00421     
00422     
00423     
00424     
00425 
00426     
if (PteContents.
u.Hard.Valid != 0) { 
00427 
00428         TempPte = PteContents;
00429 
00430         
00431         
00432         
00433 
00434         TempPte.
u.Long |= NewPteProtection;
00435 
00436         
if (PteContents.u.Hard.Accessed == 0) {
00437 
00438             TempPte.
u.Hard.Accessed = 1;
00439 
00440             
if (PageIsSplit == 
TRUE) {
00441 
00442                 TempPte.
u.Hard.Cache = 
MM_PTE_CACHE_RESERVED;
00443 
00444             } 
00445         }
00446 
00447         
00448         
00449         
00450 
00451         
if ((TempPte.
u.Hard.CopyOnWrite != 0) && (PteContents.u.Hard.Write != 0)) { 
00452 
00453             TempPte.
u.Hard.CopyOnWrite = 0;
00454             
00455         }
00456 
00457         
MI_WRITE_VALID_PTE_NEW_PROTECTION(PointerPte, TempPte); 
00458     }
00459 
00460     
UNLOCK_WS (CurrentProcess);
00461     
00462     
00463     
00464     
00465     
00466 
00467     
ASSERT (AltPteContents.
u.Long != 0);
00468     
ASSERT (AltPteContents.
u.Alt.Commit != 0);
00469         
00470     
if (AltPteContents.
u.Alt.Accessed == 0) {
00471 
00472         
00473         
00474         
00475         
00476         
00477         
00478         
00479         
00480         
00481 
00482         
if (AltPteContents.
u.Alt.FillZero != 0) {
00483 
00484             
00485             
00486             
00487 
00488             FillZero = 
TRUE;
00489             
00490         } 
00491 
00492         
if ((AltPteContents.
u.Alt.Protection & 
MM_GUARD_PAGE) != 0) {
00493         
00494             MiCheckPoint(5);
00495 
00496             
00497             
00498             
00499         
00500             
if (PteContents.
u.Hard.Valid == 0) {
00501 
00502                 
UNLOCK_ALTERNATE_TABLE (Wow64Process);
00503 
00504                 
00505                 
00506                 
00507 
00508                 status = 
MmAccessFault (StoreInstruction,
00509                                         VirtualAddress,
00510                                         PreviousMode,
00511                                         TrapInformation);
00512 
00513                 
LOCK_ALTERNATE_TABLE (Wow64Process);
00514 
00515                 
if (status == STATUS_PAGE_FAULT_GUARD_PAGE) {
00516                     
00517                     PointerAltPte = 
MiGetAltPteAddress(
PAGE_ALIGN(VirtualAddress));
00518                 
00519                     
for (i = 0; i < 
SPLITS_PER_PAGE; i += 1) {
00520                     
00521                         AltPteContents.
u.Long = PointerAltPte->u.Long;
00522 
00523                         
if ((AltPteContents.
u.Alt.Protection & 
MM_GUARD_PAGE) != 0) {
00524 
00525                             AltPteContents.
u.Alt.Protection &= ~
MM_GUARD_PAGE;
00526                             AltPteContents.
u.Alt.Accessed = 1;
00527                             PointerAltPte->u.Long = AltPteContents.
u.Long;
00528 
00529                         }
00530 
00531                         PointerAltPte += 1;
00532 
00533                     } 
00534                     
00535                     
goto return_status;
00536                 }
00537 
00538             }
00539 
00540             AltPteContents.
u.Alt.Protection &= ~
MM_GUARD_PAGE;
00541             AltPteContents.
u.Alt.Accessed = 1;
00542 
00543             PointerAltPte->u.Long = AltPteContents.
u.Long;
00544 
00545             status =  STATUS_GUARD_PAGE_VIOLATION;           
00546 
00547             
goto return_status;
00548 
00549         } 
else if (FillZero == 
FALSE) {
00550 
00551             
00552             
00553             
00554 
00555             status = STATUS_ACCESS_VIOLATION;
00556             
00557             
goto return_status;
00558 
00559         }
00560     }
00561 
00562     
if (ExecutionFault == 
TRUE) {
00563         
00564         
00565         
00566         
00567         
00568 
00569     } 
else if (StoreInstruction == 
TRUE) {
00570         
00571         
00572         
00573         
00574 
00575         
if (AltPteContents.
u.Alt.CopyOnWrite != 0) {
00576 
00577 
#if 0
00578 
            MiCheckDemandZeroCopyOnWriteFor4kPage(VirtualAddress, CurrentProcess);
00579 
#endif
00580 
            
00581             
00582             
00583 
00584             status = 
MmAccessFault (StoreInstruction,
00585                                     VirtualAddress,
00586                                     PreviousMode,
00587                                     TrapInformation);
00588 
00589 
#if 0
00590 
            if (PteContents.
u.Hard.Valid != 0) {
00591                 
DbgPrint(
"copyonwrite original page = %p, %p\n", VirtualAddress, PteContents.
u.Long);
00592             }
00593 
#endif
00594 
00595             
if (!
NT_SUCCESS(status)) {
00596 
00597                 MiCheckPointBreak();
00598                 
goto return_status;
00599                 
00600             }
00601 
00602             
if (status == STATUS_PAGE_FAULT_COPY_ON_WRITE) {
00603                 MiCopyOnWriteFor4kPage(VirtualAddress, CurrentProcess);
00604             } 
else {
00605                 MiCheckPointBreak();
00606             }
00607             
00608             
00609             
00610             
00611 
00612             status = STATUS_SUCCESS;
00613 
00614             
goto return_status;
00615         }
00616             
00617         
if (AltPteContents.
u.Hard.Write == 0) {
00618 
00619             status = STATUS_ACCESS_VIOLATION;
00620             
00621             
goto return_status;
00622         }
00623 
00624     }
00625 
00626     
00627     
00628     
00629 
00630     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
00631     
00632     status = 
MmAccessFault (StoreInstruction,
00633                             VirtualAddress,
00634                             PreviousMode,
00635                             TrapInformation);
00636 
00637     
if ((status == STATUS_PAGE_FAULT_GUARD_PAGE) ||
00638         (status == STATUS_GUARD_PAGE_VIOLATION)) {
00639 
00640         
LOCK_ALTERNATE_TABLE (Wow64Process);
00641 
00642         AltPteContents = *PointerAltPte;
00643 
00644         
if ((AltPteContents.
u.Alt.Protection & 
MM_GUARD_PAGE) != 0) {
00645         
00646             AltPteContents = *PointerAltPte;
00647             AltPteContents.
u.Alt.Protection &= ~
MM_GUARD_PAGE;
00648             AltPteContents.
u.Alt.Accessed = 1;
00649         
00650             PointerAltPte->u.Long = AltPteContents.
u.Long;
00651 
00652         }
00653 
00654         
UNLOCK_ALTERNATE_TABLE (Wow64Process);
00655 
00656         
if (status == STATUS_GUARD_PAGE_VIOLATION) {
00657 
00658             status = STATUS_SUCCESS;
00659 
00660         }
00661 
00662     }
00663 
00664     
KiFlushSingleTb(TRUE, VirtualAddress);
00665 
00666     
if (FillZero == 
TRUE) {
00667 
00668         MiFillZeroFor4kPage (VirtualAddress, CurrentProcess);
00669 
00670     }
00671 
00672     
if (!
NT_SUCCESS(status)) {
00673 
00674         MiCheckPointBreak();
00675 
00676     } 
00677 
00678     
return status;
00679 
00680  return_status:
00681 
00682     
KiFlushSingleTb(TRUE, VirtualAddress);
00683 
00684     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
00685 
00686     
if (FillZero == 
TRUE) {
00687 
00688         MiFillZeroFor4kPage (VirtualAddress, CurrentProcess);
00689 
00690     }
00691 
00692     
if (!
NT_SUCCESS(status)) {
00693 
00694         MiCheckPointBreak();
00695 
00696     } 
00697 
00698     
return status;
00699 }
00700 
00701 ULONG
00702 MiFindProtectionForNativePte( 
00703     PVOID VirtualAddress
00704     )
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 {
00727     
PMMPTE PointerAltPte;
00728     ULONG i;
00729     ULONG ProtectionCode = 0;
00730 
00731     PointerAltPte = 
MiGetAltPteAddress(
PAGE_ALIGN(VirtualAddress));
00732     
00733     
for (i = 0; i < 
SPLITS_PER_PAGE; i++) {
00734 
00735         ProtectionCode |= (PointerAltPte->
u.Long & 
ALT_PROTECTION_MASK);
00736 
00737         
if (PointerAltPte->
u.Alt.CopyOnWrite != 0) {
00738             ProtectionCode |= 
MM_PTE_COPY_ON_WRITE_MASK;
00739         }
00740 
00741         PointerAltPte += 1;
00742     }
00743 
00744     
return ProtectionCode;
00745 
00746 }
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 ULONGLONG 
MmProtectToAteMask[32] = {
00755                        
MM_PTE_NOACCESS | 
MM_ATE_NOACCESS,
00756                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK,
00757                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK,
00758                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK,
00759                        
MM_PTE_EXECUTE_READWRITE | 
MM_PTE_ACCESS_MASK,
00760                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK | 
MM_ATE_COPY_ON_WRITE,
00761                        
MM_PTE_EXECUTE_READWRITE | 
MM_PTE_ACCESS_MASK,
00762                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK | 
MM_ATE_COPY_ON_WRITE,
00763                        
MM_PTE_NOACCESS | 
MM_ATE_NOACCESS,
00764                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK,
00765                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK,
00766                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK,
00767                        
MM_PTE_EXECUTE_READWRITE | 
MM_PTE_ACCESS_MASK,
00768                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK | 
MM_ATE_COPY_ON_WRITE,
00769                        
MM_PTE_EXECUTE_READWRITE | 
MM_PTE_ACCESS_MASK,
00770                        
MM_PTE_EXECUTE_READ | 
MM_PTE_ACCESS_MASK | 
MM_ATE_COPY_ON_WRITE,
00771                        
MM_PTE_NOACCESS | 
MM_ATE_NOACCESS,
00772                        
MM_PTE_EXECUTE_READ,
00773                        
MM_PTE_EXECUTE_READ,
00774                        
MM_PTE_EXECUTE_READ,
00775                        
MM_PTE_EXECUTE_READWRITE,
00776                        
MM_PTE_EXECUTE_READ | 
MM_ATE_COPY_ON_WRITE,
00777                        
MM_PTE_EXECUTE_READWRITE,
00778                        
MM_PTE_EXECUTE_READ | 
MM_ATE_COPY_ON_WRITE,
00779                        
MM_PTE_NOACCESS | 
MM_ATE_NOACCESS,
00780                        
MM_PTE_EXECUTE_READ,
00781                        
MM_PTE_EXECUTE_READ,
00782                        
MM_PTE_EXECUTE_READ,
00783                        
MM_PTE_EXECUTE_READWRITE,
00784                        
MM_PTE_EXECUTE_READ | 
MM_ATE_COPY_ON_WRITE,
00785                        
MM_PTE_EXECUTE_READWRITE,
00786                        
MM_PTE_EXECUTE_READ | 
MM_ATE_COPY_ON_WRITE
00787                     };
00788 
00789 
#define MiMakeProtectionAteMask(NewProtect) MmProtectToAteMask[NewProtect]
00790 
00791 
VOID
00792 
MiProtectFor4kPage(
00793     IN PVOID Base,
00794     IN SIZE_T Size,
00795     IN ULONG NewProtect,
00796     IN ULONG Flags,
00797     IN 
PEPROCESS Process
00798     )
00799 
00800 
00801 
00802 
00803 
00804 
00805 
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 
00814 
00815 
00816 
00817 
00818 
00819 
00820 
00821 
00822 
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 {
00834     PVOID Starting4KAddress;
00835     PVOID Ending4KAddress;
00836     PVOID VirtualAddress;
00837     ULONG NewProtectNotCopy;
00838     ULONGLONG ProtectionMask;
00839     ULONGLONG ProtectionMaskNotCopy;
00840     ULONGLONG HardwareProtectionMask;
00841     
PMMPTE StartAltPte, EndAltPte;
00842     
PMMPTE StartAltPte0, EndAltPte0;
00843     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
00844     PVOID 
Virtual[
MM_MAXIMUM_FLUSH_COUNT];
00845     ULONG FlushCount;
00846     
MMPTE AltPteContents;
00847     
MMPTE TempAltPte;
00848 
00849 
00850     Starting4KAddress = Base;
00851     Ending4KAddress = (PCHAR)Base + 
Size - 1;
00852 
00853     
00854     
00855     
00856     
ASSERT( ((ULONG_PTR) Starting4KAddress) < _MAX_WOW64_ADDRESS);
00857     
ASSERT( ((ULONG_PTR) Ending4KAddress) < _MAX_WOW64_ADDRESS);
00858 
00859     
00860     
00861     
00862     
if ((((UINT_PTR) Starting4KAddress) >= 
_MAX_WOW64_ADDRESS)
00863              || (((UINT_PTR) Ending4KAddress) >= 
_MAX_WOW64_ADDRESS)) {
00864         
return;
00865     }
00866 
00867     
00868     
00869     
00870 
00871     
if ((NewProtect & 
MM_COPY_ON_WRITE_MASK) == 
MM_COPY_ON_WRITE_MASK) {
00872         NewProtectNotCopy = NewProtect & ~
MM_PROTECTION_COPY_MASK;
00873     } 
else {
00874         NewProtectNotCopy = NewProtect;
00875     }    
00876 
00877     ProtectionMask = 
MiMakeProtectionAteMask (NewProtect);
00878     ProtectionMaskNotCopy = 
MiMakeProtectionAteMask (NewProtectNotCopy);
00879 
00880     
if (Flags & 
ALT_COMMIT) {
00881 
00882         ProtectionMask |= 
MM_ATE_COMMIT;
00883         ProtectionMaskNotCopy |= 
MM_ATE_COMMIT; 
00884 
00885     }
00886 
00887     
00888     
00889     
00890 
00891     StartAltPte = 
MiGetAltPteAddress (Starting4KAddress);
00892     EndAltPte = 
MiGetAltPteAddress (Ending4KAddress);
00893 
00894     StartAltPte0 = 
MiGetAltPteAddress(
PAGE_ALIGN(Starting4KAddress) );
00895     EndAltPte0 = 
MiGetAltPteAddress((ULONG_PTR)
PAGE_ALIGN(Ending4KAddress)+PAGE_SIZE-1);
00896 
00897     
00898     
00899     
00900 
00901     
LOCK_ALTERNATE_TABLE (Wow64Process);
00902 
00903     
if (!(Flags & 
ALT_ALLOCATE) && 
00904         (
MI_CHECK_BIT(Wow64Process->AltPermBitmap, 
MI_VA_TO_VPN(Starting4KAddress)) == 0)) {
00905 
00906         
UNLOCK_ALTERNATE_TABLE (Wow64Process);
00907         
return;
00908 
00909     }
00910 
00911     
00912     
00913     
00914 
00915     VirtualAddress = Starting4KAddress;
00916 
00917     
while (StartAltPte <= EndAltPte) {
00918 
00919         AltPteContents.
u.Long = StartAltPte->
u.Long;
00920 
00921         
if (!(Flags & 
ALT_ALLOCATE) && (AltPteContents.
u.Alt.Private != 0)) {
00922 
00923 
00924             
00925             
00926             
00927                 
00928             TempAltPte.
u.Long = ProtectionMaskNotCopy;
00929             TempAltPte.
u.Alt.Protection = NewProtectNotCopy;
00930 
00931             
00932             
00933             
00934 
00935             TempAltPte.
u.Alt.Private = 1;
00936 
00937         } 
else {             
00938                 
00939             TempAltPte.
u.Long = ProtectionMask;
00940             TempAltPte.
u.Alt.Protection = NewProtect;
00941 
00942         } 
00943 
00944         
if (Flags & 
ALT_CHANGE) {
00945 
00946             
00947             
00948             
00949 
00950             TempAltPte.
u.Alt.Commit = AltPteContents.
u.Alt.Commit;
00951             
00952         }
00953 
00954         
if (!(Flags & 
ALT_ALLOCATE) && (AltPteContents.
u.Alt.FillZero != 0)) {
00955 
00956             TempAltPte.
u.Alt.Accessed = 0;
00957             TempAltPte.
u.Alt.FillZero = 1;
00958 
00959         }
00960             
00961         
00962         
00963         
00964 
00965         StartAltPte->
u.Long = TempAltPte.
u.Long;
00966 
00967         StartAltPte++;
00968         VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + 
PAGE_4K);
00969 
00970     }
00971 
00972     
if (Flags & 
ALT_ALLOCATE) {
00973 
00974         
00975         
00976         
00977 
00978         
while (EndAltPte <= EndAltPte0) {
00979 
00980             
if (EndAltPte->
u.Long == 0) {
00981 
00982                 TempAltPte.
u.Long = EndAltPte->
u.Long;
00983                 TempAltPte.
u.Alt.NoAccess = 1;
00984 
00985                 
00986                 
00987                 
00988 
00989                 EndAltPte->
u.Long = TempAltPte.
u.Long;
00990 
00991             }
00992 
00993             EndAltPte++;
00994         }
00995 
00996         
00997         
00998         
00999 
01000         
MiMarkSplitPages(Base, 
01001                          (PVOID)((ULONG_PTR)Base + Size - 1), 
01002                          Wow64Process->AltPermBitmap,
01003                          TRUE);
01004     }
01005 
01006     
01007     
01008     
01009     
01010     
01011     
01012     
01013     
01014 
01015 
01016 
01017     
01018     
01019     
01020 
01021     VirtualAddress = 
PAGE_ALIGN(Starting4KAddress);
01022 
01023     FlushCount = 0;
01024     
while (VirtualAddress <= Ending4KAddress) {
01025         
if (FlushCount != 
MM_MAXIMUM_FLUSH_COUNT) {
01026             
Virtual[FlushCount] = VirtualAddress;
01027             FlushCount += 1;
01028         } 
01029         VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + 
PAGE_SIZE);
01030     }
01031     
01032     
if (FlushCount != 0) {
01033         
01034         
if (FlushCount <= 
MM_MAXIMUM_FLUSH_COUNT) {
01035 
01036             
KeFlushMultipleTb(FlushCount,
01037                               &Virtual[0],
01038                               TRUE,
01039                               TRUE,
01040                               NULL,
01041                               
ZeroPte.
u.Flush);                          
01042         } 
else {
01043 
01044             
KeFlushEntireTb(TRUE, TRUE);
01045 
01046         }
01047     }
01048 
01049     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01050 }
01051 
01052 
VOID
01053 
MiProtectMapFileFor4kPage(
01054     IN PVOID Base,
01055     IN SIZE_T Size,
01056     IN ULONG NewProtect,
01057     IN 
PMMPTE PointerPte,
01058     IN 
PEPROCESS Process
01059     )
01060 
01061 
01062 
01063 
01064 
01065 
01066 
01067 
01068 
01069 
01070 
01071 
01072 
01073 
01074 
01075 
01076 
01077 
01078 
01079 
01080 
01081 
01082 
01083 
01084 
01085 
01086 
01087 
01088 
01089 
01090 
01091 {
01092     PVOID Starting4KAddress;
01093     PVOID Ending4KAddress;
01094     ULONGLONG ProtectionMask;
01095     ULONGLONG HardwareProtectionMask;
01096     
PMMPTE StartAltPte, EndAltPte;
01097     
PMMPTE StartAltPte0, EndAltPte0;
01098     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01099     
MMPTE TempAltPte;
01100 
01101     Starting4KAddress = Base;
01102     Ending4KAddress = (PCHAR)Base + 
Size - 1;
01103 
01104     
01105     
01106     
01107     
ASSERT( ((ULONG_PTR) Starting4KAddress) < _MAX_WOW64_ADDRESS);
01108     
ASSERT( ((ULONG_PTR) Ending4KAddress) < _MAX_WOW64_ADDRESS);
01109 
01110     
01111     
01112     
01113     
if ((((UINT_PTR) Starting4KAddress) >= 
_MAX_WOW64_ADDRESS)
01114              || (((UINT_PTR) Ending4KAddress) >= 
_MAX_WOW64_ADDRESS)) {
01115         
return;
01116     }
01117 
01118     
01119     
01120     
01121 
01122     ProtectionMask = 
MiMakeProtectionAteMask (NewProtect);
01123 
01124     
01125     
01126     
01127 
01128     StartAltPte = 
MiGetAltPteAddress (Starting4KAddress);
01129     EndAltPte = 
MiGetAltPteAddress (Ending4KAddress);
01130     EndAltPte0 = 
MiGetAltPteAddress((ULONG_PTR)
PAGE_ALIGN(Ending4KAddress)+PAGE_SIZE-1);
01131 
01132     
LOCK_ALTERNATE_TABLE (Wow64Process);
01133 
01134     
ExAcquireFastMutexUnsafe (&MmSectionCommitMutex);
01135 
01136     
01137     
01138     
01139 
01140     
while (StartAltPte <= EndAltPte) {
01141 
01142         TempAltPte.
u.Long = ProtectionMask;
01143         TempAltPte.
u.Alt.Protection = NewProtect;
01144 
01145         
if (PointerPte->u.Long != 0) {
01146 
01147             TempAltPte.
u.Alt.Commit = 1;
01148 
01149         } 
else {
01150 
01151             TempAltPte.
u.Alt.Commit = 0;
01152 
01153         }
01154 
01155         
01156         
01157         
01158 
01159         StartAltPte->
u.Long = TempAltPte.
u.Long;
01160 
01161         StartAltPte++;
01162 
01163         
if (((ULONG_PTR)StartAltPte & ((
SPLITS_PER_PAGE * 
sizeof(
MMPTE))-1)) == 0) {
01164 
01165             PointerPte++;
01166 
01167         }
01168     }
01169 
01170     
ExReleaseFastMutexUnsafe (&MmSectionCommitMutex);
01171 
01172     
01173     
01174     
01175 
01176     
while (EndAltPte <= EndAltPte0) {
01177 
01178         
if (EndAltPte->
u.Long == 0) {
01179 
01180             TempAltPte.
u.Long = EndAltPte->
u.Long;
01181             TempAltPte.
u.Alt.NoAccess = 1;
01182 
01183             
01184             
01185             
01186 
01187             EndAltPte->
u.Long = TempAltPte.
u.Long;
01188 
01189         }
01190 
01191         EndAltPte++;
01192     }
01193     
01194     
MiMarkSplitPages(Base, 
01195                      (PVOID)((ULONG_PTR)Base + Size - 1), 
01196                      Wow64Process->AltPermBitmap,
01197                      TRUE);
01198 
01199     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01200 }
01201 
01202 
VOID
01203 
MiProtectImageFileFor4kPage(
01204     IN PVOID Base,
01205     IN SIZE_T Size,
01206     IN 
PMMPTE PointerPte,
01207     IN 
PEPROCESS Process
01208     )
01209 {
01210     PVOID Starting4KAddress;
01211     PVOID Ending4KAddress;
01212     ULONGLONG ProtectionMask;
01213     ULONGLONG HardwareProtectionMask;
01214     
PMMPTE StartAltPte;
01215     
PMMPTE EndAltPte;
01216     
PMMPTE EndAltPte0;
01217     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01218     
MMPTE TempAltPte;
01219     
MMPTE TempPte;
01220     ULONG NewProtect;
01221     KIRQL OldIrql;
01222     ULONG i;
01223 
01224     Starting4KAddress = Base;
01225     Ending4KAddress = (PCHAR)Base + 
Size - 1;
01226 
01227     
01228     
01229     
01230     
ASSERT( ((ULONG_PTR) Starting4KAddress) < _MAX_WOW64_ADDRESS);
01231     
ASSERT( ((ULONG_PTR) Ending4KAddress) < _MAX_WOW64_ADDRESS);
01232 
01233     
01234     
01235     
01236     
if ((((UINT_PTR) Starting4KAddress) >= 
_MAX_WOW64_ADDRESS)
01237              || (((UINT_PTR) Ending4KAddress) >= 
_MAX_WOW64_ADDRESS)) {
01238         
return;
01239     }
01240 
01241     
01242     
01243     
01244 
01245     StartAltPte = 
MiGetAltPteAddress (Starting4KAddress);
01246     EndAltPte = 
MiGetAltPteAddress (Ending4KAddress);
01247     EndAltPte0 = 
MiGetAltPteAddress((ULONG_PTR)
PAGE_ALIGN(Ending4KAddress)+PAGE_SIZE-1);
01248 
01249     
LOCK_ALTERNATE_TABLE (Wow64Process);
01250 
01251     
01252     
01253     
01254 
01255     
while (StartAltPte <= EndAltPte) {
01256 
01257         
01258         
01259         
01260 
01261         
LOCK_WS_UNSAFE (Process);
01262 
01263         
LOCK_PFN (OldIrql);
01264         
MiMakeSystemAddressValidPfnWs (PointerPte, Process);
01265         TempPte = *PointerPte;
01266         
UNLOCK_PFN (OldIrql);
01267 
01268         NewProtect = 
01269             
MiMakeProtectionMask(
MiGetPageProtection(&TempPte, Process));
01270 
01271         
UNLOCK_WS_UNSAFE (Process);
01272 
01273         
01274         
01275         
01276 
01277         
if ((!
IS_PTE_NOT_DEMAND_ZERO(TempPte)) && 
01278             (TempPte.
u.Soft.Protection & 
MM_COPY_ON_WRITE_MASK)) {
01279             NewProtect = NewProtect & ~
MM_PROTECTION_COPY_MASK;
01280         }
01281 
01282         ProtectionMask = 
MiMakeProtectionAteMask (NewProtect);
01283         ProtectionMask |= 
MM_ATE_COMMIT;
01284 
01285         TempAltPte.
u.Long = ProtectionMask;
01286         TempAltPte.
u.Alt.Protection = NewProtect;
01287 
01288         
if ((NewProtect & 
MM_PROTECTION_COPY_MASK) == 0) {
01289 
01290             
01291             
01292             
01293 
01294             TempAltPte.
u.Alt.Private = 1;
01295 
01296         }
01297 
01298         
01299         
01300         
01301 
01302         
for (i = 0; i < 
SPLITS_PER_PAGE; i += 1) { 
01303 
01304             StartAltPte->
u.Long = TempAltPte.
u.Long;
01305             StartAltPte++;
01306 
01307         }
01308 
01309         PointerPte++;
01310     }
01311 
01312     
01313     
01314     
01315 
01316     
while (EndAltPte <= EndAltPte0) {
01317 
01318         
if (EndAltPte->
u.Long == 0) {
01319 
01320             TempAltPte.
u.Long = EndAltPte->
u.Long;
01321             TempAltPte.
u.Alt.NoAccess = 1;
01322 
01323             
01324             
01325             
01326 
01327             EndAltPte->
u.Long = TempAltPte.
u.Long;
01328 
01329         }
01330 
01331         EndAltPte++;
01332     }
01333     
01334     
MiMarkSplitPages(Base, 
01335                      (PVOID)((ULONG_PTR)Base + Size - 1), 
01336                      Wow64Process->AltPermBitmap,
01337                      TRUE);
01338 
01339     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01340 }
01341 
01342 
VOID
01343 
MiReleaseFor4kPage(
01344     IN PVOID StartVirtual,
01345     IN PVOID EndVirtual,
01346     IN 
PEPROCESS Process
01347     )
01348 
01349 
01350 
01351 
01352 
01353 
01354 
01355 
01356 
01357 
01358 
01359 
01360 
01361 
01362 
01363 
01364 
01365 
01366 
01367 
01368 
01369 
01370 
01371 
01372 
01373 
01374 {
01375     
PMMPTE StartAltPte;
01376     
PMMPTE EndAltPte;
01377     
MMPTE TempAltPte;
01378     ULONG_PTR VirtualAddress;
01379     ULONG i;
01380     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01381     PVOID 
Virtual[
MM_MAXIMUM_FLUSH_COUNT];
01382     ULONG FlushCount = 0;
01383 
01384     
ASSERT(StartVirtual <= EndVirtual);
01385 
01386     StartAltPte = 
MiGetAltPteAddress (StartVirtual);
01387     EndAltPte = 
MiGetAltPteAddress (EndVirtual);
01388 
01389     
LOCK_ALTERNATE_TABLE (Wow64Process);
01390 
01391     VirtualAddress = (ULONG_PTR)StartVirtual;
01392 
01393     
while (StartAltPte <= EndAltPte) {
01394 
01395         StartAltPte->
u.Long = 0;
01396         StartAltPte->
u.Alt.NoAccess = 1;
01397         StartAltPte->
u.Alt.FillZero = 1;
01398         StartAltPte++;
01399 
01400     }
01401 
01402     StartVirtual = 
PAGE_ALIGN(StartVirtual);
01403 
01404     VirtualAddress = (ULONG_PTR)StartVirtual;
01405 
01406     
while (VirtualAddress <= (ULONG_PTR)EndVirtual) {
01407 
01408         StartAltPte = 
MiGetAltPteAddress(VirtualAddress);
01409         TempAltPte = *StartAltPte;
01410 
01411         i = 0;
01412 
01413         
while (TempAltPte.
u.Long == StartAltPte->u.Long) {
01414             i += 1;
01415             StartAltPte++;
01416         }
01417 
01418         
if (i == 
SPLITS_PER_PAGE) {
01419 
01420             StartAltPte = 
MiGetAltPteAddress(VirtualAddress);
01421             
01422             
for (i = 0; i < 
SPLITS_PER_PAGE; i += 1) {
01423                 StartAltPte->u.Long = 0;
01424                 StartAltPte++;
01425             }
01426             
01427         }
01428         
01429         VirtualAddress  += 
PAGE_SIZE;
01430         
01431         
if (FlushCount != 
MM_MAXIMUM_FLUSH_COUNT) {
01432             
Virtual[FlushCount] = (PVOID)VirtualAddress;
01433             FlushCount += 1;
01434         } 
01435     }
01436 
01437     MiResetAccessBitForNativePtes(StartVirtual, EndVirtual, Process);
01438 
01439     
if (FlushCount != 0) {
01440         
01441         
if (FlushCount <= 
MM_MAXIMUM_FLUSH_COUNT) {
01442 
01443             
KeFlushMultipleTb(FlushCount,
01444                               &Virtual[0],
01445                               TRUE,
01446                               TRUE,
01447                               NULL,
01448                               
ZeroPte.
u.Flush);                          
01449         } 
else {
01450 
01451             
KeFlushEntireTb(TRUE, TRUE);
01452 
01453         }
01454     }
01455 
01456     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01457 }
01458 
01459 
VOID
01460 
MiDecommitFor4kPage(
01461     IN PVOID StartVirtual,
01462     IN PVOID EndVirtual,
01463     IN 
PEPROCESS Process
01464     )
01465 
01466 
01467 
01468 
01469 
01470 
01471 
01472 
01473 
01474 
01475 
01476 
01477 
01478 
01479 
01480 
01481 
01482 
01483 
01484 
01485 
01486 
01487 
01488 
01489 
01490 
01491 {
01492     
PMMPTE StartAltPte;
01493     
PMMPTE EndAltPte;
01494     
MMPTE TempAltPte;
01495     ULONG_PTR VirtualAddress;
01496     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01497     PVOID 
Virtual[
MM_MAXIMUM_FLUSH_COUNT];
01498     ULONG FlushCount = 0;
01499 
01500     
ASSERT(StartVirtual <= EndVirtual);
01501 
01502     StartAltPte = 
MiGetAltPteAddress (StartVirtual);
01503     EndAltPte = 
MiGetAltPteAddress (EndVirtual);
01504 
01505     
LOCK_ALTERNATE_TABLE (Wow64Process);
01506 
01507     
while (StartAltPte <= EndAltPte) {
01508 
01509         TempAltPte.
u.Long = StartAltPte->
u.Long;
01510         TempAltPte.
u.Alt.Commit = 0;
01511         TempAltPte.
u.Alt.FillZero = 1;
01512 
01513         
01514         
01515         
01516 
01517         StartAltPte->
u.Long = TempAltPte.
u.Long;
01518 
01519         StartAltPte++;
01520     }
01521 
01522     
01523     
01524     
01525 
01526     VirtualAddress = (ULONG_PTR)StartVirtual;
01527 
01528     
while ((PVOID)VirtualAddress <= EndVirtual) {
01529 
01530         
if (FlushCount != 
MM_MAXIMUM_FLUSH_COUNT) {
01531             
Virtual[FlushCount] = (PVOID)VirtualAddress;
01532             FlushCount += 1;
01533         } 
01534         VirtualAddress += 
PAGE_SIZE;
01535 
01536     }
01537 
01538     MiResetAccessBitForNativePtes(StartVirtual, EndVirtual, Process);
01539 
01540     
if (FlushCount != 0) {
01541         
01542         
if (FlushCount <= 
MM_MAXIMUM_FLUSH_COUNT) {
01543 
01544             
KeFlushMultipleTb(FlushCount,
01545                               &Virtual[0],
01546                               TRUE,
01547                               TRUE,
01548                               NULL,
01549                               
ZeroPte.
u.Flush);                          
01550         } 
else {
01551 
01552             
KeFlushEntireTb(TRUE, TRUE);
01553 
01554         }
01555     }
01556 
01557     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01558 }
01559 
01560 
01561 
VOID
01562 
MiDeleteFor4kPage(
01563     IN PVOID StartVirtual,
01564     IN PVOID EndVirtual,
01565     IN 
PEPROCESS Process
01566     )
01567 
01568 
01569 
01570 
01571 
01572 
01573 
01574 
01575 
01576 
01577 
01578 
01579 
01580 
01581 
01582 
01583 
01584 
01585 
01586 
01587 
01588 
01589 
01590 
01591 
01592 
01593 {
01594     
PMMPTE StartAltPte;
01595     
PMMPTE EndAltPte;
01596     ULONG_PTR VirtualAddress;
01597     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01598     PVOID 
Virtual[
MM_MAXIMUM_FLUSH_COUNT];
01599     ULONG FlushCount = 0;
01600 
01601     
ASSERT(StartVirtual <= EndVirtual);
01602 
01603     StartAltPte = 
MiGetAltPteAddress (StartVirtual);
01604     EndAltPte = 
MiGetAltPteAddress (EndVirtual);
01605 
01606     
LOCK_ALTERNATE_TABLE (Wow64Process);
01607 
01608     VirtualAddress = (ULONG_PTR)StartVirtual;
01609 
01610     
while (StartAltPte <= EndAltPte) {
01611 
01612         StartAltPte->
u.Long= 0;
01613         StartAltPte++;
01614     }
01615 
01616 
01617     
01618     
01619     
01620 
01621     VirtualAddress = (ULONG_PTR)StartVirtual;
01622 
01623     
while ((PVOID)VirtualAddress <= EndVirtual) {
01624 
01625         
if (FlushCount != 
MM_MAXIMUM_FLUSH_COUNT) {
01626             
Virtual[FlushCount] = (PVOID)VirtualAddress;
01627             FlushCount += 1;
01628         } 
01629         VirtualAddress += 
PAGE_SIZE;
01630 
01631     }
01632 
01633     
MiMarkSplitPages(StartVirtual, 
01634                      EndVirtual, 
01635                      Wow64Process->AltPermBitmap,
01636                      TRUE);
01637 
01638     MiResetAccessBitForNativePtes(StartVirtual, EndVirtual, Process);
01639 
01640     
if (FlushCount != 0) {
01641         
01642         
if (FlushCount <= 
MM_MAXIMUM_FLUSH_COUNT) {
01643 
01644             
KeFlushMultipleTb(FlushCount,
01645                               &Virtual[0],
01646                               TRUE,
01647                               TRUE,
01648                               NULL,
01649                               
ZeroPte.
u.Flush);                          
01650         } 
else {
01651 
01652             
KeFlushEntireTb(TRUE, TRUE);
01653 
01654         }
01655     }
01656 
01657     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01658 }
01659 
01660 BOOLEAN
01661 MiIsSplitPage(
01662     IN PVOID Virtual
01663     )
01664 {
01665     
PMMPTE AltPte;
01666     
MMPTE PteContents;
01667     BOOLEAN IsSplit;
01668     ULONG i;
01669 
01670     
Virtual = 
PAGE_ALIGN(Virtual);
01671     AltPte = 
MiGetAltPteAddress(Virtual);
01672     PteContents = *AltPte;
01673 
01674     
for (i = 0; i < 
SPLITS_PER_PAGE; i++) {
01675 
01676         
if ((AltPte->u.Long != 0) && 
01677             ((AltPte->u.Alt.Commit == 0) || 
01678              (AltPte->u.Alt.Accessed == 0) ||
01679              (AltPte->u.Alt.CopyOnWrite != 0) || 
01680              (AltPte->u.Alt.FillZero != 0))) {
01681 
01682             
01683             
01684             
01685             
01686 
01687             
return TRUE;
01688 
01689         } 
else if (PteContents.
u.Long != AltPte->u.Long) {
01690 
01691             
01692             
01693             
01694             
01695 
01696             
return TRUE;
01697 
01698         }
01699 
01700         AltPte++;
01701 
01702     }
01703 
01704     
return FALSE;
01705 }
01706 
01707 
01708 
VOID
01709 
MiMarkSplitPages(
01710     IN PVOID StartVirtual,
01711     IN PVOID EndVirtual,
01712     IN PULONG Bitmap,
01713     IN BOOLEAN SetBit
01714     )
01715 
01716 
01717 
01718 
01719 
01720 
01721 
01722 
01723 
01724 
01725 
01726 
01727 
01728 
01729 
01730 
01731 
01732 
01733 
01734 
01735 
01736 
01737 
01738 
01739 
01740 
01741 
01742 {
01743     ULONG i;
01744     
01745     
ASSERT(StartVirtual <= EndVirtual);
01746     
ASSERT((ULONG_PTR)StartVirtual < _MAX_WOW64_ADDRESS);
01747     
ASSERT((ULONG_PTR)EndVirtual < _MAX_WOW64_ADDRESS);
01748 
01749     StartVirtual = 
PAGE_ALIGN(StartVirtual);
01750 
01751     
while (StartVirtual <= EndVirtual) {
01752         
01753         
if (SetBit == 
TRUE) {
01754 
01755             
01756             
01757             
01758 
01759             
MI_SET_BIT(Bitmap, 
MI_VA_TO_VPN(StartVirtual));
01760 
01761         } 
else {
01762 
01763             
01764             
01765             
01766 
01767             
MI_CLEAR_BIT(Bitmap, 
MI_VA_TO_VPN(StartVirtual)); 
01768                 
01769         }
01770             
01771         StartVirtual = (PVOID)((ULONG_PTR)StartVirtual + 
PAGE_SIZE);
01772     }
01773 }
01774 
01775 
VOID
01776 MiResetAccessBitForNativePtes(
01777     IN PVOID StartVirtual,
01778     IN PVOID EndVirtual,
01779     IN 
PEPROCESS Process
01780     )
01781 
01782 
01783 
01784 
01785 
01786 
01787 
01788 
01789 
01790 
01791 
01792 
01793 
01794 
01795 
01796 
01797 
01798 
01799 
01800 
01801 
01802 
01803 
01804 {
01805     
PMMPTE PointerPte;
01806     
PMMPTE PointerPde;
01807     
PMMPTE PointerPpe;
01808     BOOLEAN FirstTime;
01809     ULONG Waited;
01810     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01811 
01812     PointerPte = 
MiGetPteAddress (StartVirtual);
01813 
01814     
LOCK_WS_UNSAFE (Process);
01815 
01816     FirstTime = 
TRUE;
01817 
01818     
while (StartVirtual <= EndVirtual) {
01819 
01820         
if ((FirstTime == 
TRUE) || 
MiIsPteOnPdeBoundary (PointerPte)) {
01821 
01822             PointerPde = 
MiGetPteAddress (PointerPte);
01823             PointerPpe = 
MiGetPdeAddress (PointerPte);
01824 
01825             
if (
MiDoesPpeExistAndMakeValid (PointerPpe, 
01826                                             Process, 
01827                                             FALSE,
01828                                              &Waited) == 
FALSE) {
01829 
01830                 
01831                 
01832                 
01833                 
01834 
01835                 PointerPpe += 1;
01836                 PointerPde = 
MiGetVirtualAddressMappedByPte (PointerPpe);
01837                 PointerPte = 
MiGetVirtualAddressMappedByPte (PointerPde);
01838                 StartVirtual = 
MiGetVirtualAddressMappedByPte (PointerPte);
01839                 
continue;
01840             }
01841 
01842             
if (
MiDoesPdeExistAndMakeValid (PointerPde, 
01843                                             Process,
01844                                             FALSE,
01845                                             &Waited) == 
FALSE) {
01846 
01847 
01848                 
01849                 
01850                 
01851                 
01852 
01853                 PointerPde++;
01854                 PointerPte = 
MiGetVirtualAddressMappedByPte(PointerPde);
01855                 StartVirtual = 
MiGetVirtualAddressMappedByPte(PointerPte);
01856                 
continue;
01857             }
01858                     
01859             FirstTime = 
FALSE;
01860 
01861         }
01862             
01863         
if ((
MI_CHECK_BIT(Wow64Process->AltPermBitmap, 
MI_VA_TO_VPN(StartVirtual))) &&
01864             ((PointerPte->
u.Hard.Valid != 0) && (PointerPte->
u.Hard.Accessed != 0))) {
01865 
01866             PointerPte->
u.Hard.Accessed = 0;
01867 
01868         }
01869 
01870         PointerPte += 1;
01871         StartVirtual = (PVOID)((ULONG_PTR)StartVirtual + 
PAGE_SIZE); 
01872         
01873     }
01874 
01875     
UNLOCK_WS_UNSAFE (Process);
01876 }
01877 
01878 
VOID
01879 
MiQueryRegionFor4kPage(
01880     IN PVOID BaseAddress,
01881     IN PVOID EndAddress,
01882     IN OUT PSIZE_T RegionSize,
01883     IN OUT PULONG RegionState,
01884     IN OUT PULONG RegionProtect,
01885     IN 
PEPROCESS Process
01886     )
01887 
01888 
01889 
01890 
01891 
01892 
01893 
01894 
01895 
01896 
01897 
01898 
01899 
01900 
01901 
01902 
01903 
01904 
01905 
01906 
01907 
01908 
01909 
01910 
01911 
01912 
01913 
01914 
01915 
01916 
01917 
01918 
01919 
01920 
01921 
01922 {
01923    
PMMPTE AltPte;
01924    
MMPTE AltContents;
01925    PVOID Va;
01926    
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
01927 
01928    AltPte = 
MiGetAltPteAddress(BaseAddress);
01929 
01930    
LOCK_ALTERNATE_TABLE (Wow64Process);
01931 
01932    
if (
MI_CHECK_BIT(Wow64Process->AltPermBitmap, 
01933                      
MI_VA_TO_VPN(BaseAddress)) == 0) {
01934 
01935        
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01936        
return;
01937        
01938    }
01939 
01940 
01941    AltContents.
u.Long = AltPte->
u.Long;
01942 
01943    
if (AltContents.
u.Long == 0) {
01944 
01945        
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01946 
01947        
return;
01948 
01949    }
01950 
01951    
if (AltContents.
u.Alt.Commit != 0) {
01952 
01953        *RegionState = MEM_COMMIT;
01954 
01955        *RegionProtect = 
01956            
MI_CONVERT_FROM_PTE_PROTECTION(AltContents.
u.Alt.Protection);
01957 
01958    } 
else {
01959 
01960        *RegionState = MEM_RESERVE;
01961        
01962        *RegionProtect = 0;
01963 
01964    }
01965 
01966    Va = BaseAddress;
01967 
01968    
while ((ULONG_PTR)Va < (ULONG_PTR)EndAddress) {
01969 
01970        Va = (PVOID)((ULONG_PTR)Va + 
PAGE_4K);
01971        AltPte++;
01972 
01973        
if ((AltPte->
u.Alt.Protection != AltContents.
u.Alt.Protection) ||
01974            (AltPte->
u.Alt.Commit != AltContents.
u.Alt.Commit)) {
01975 
01976             
01977             
01978             
01979             
01980 
01981             
break;
01982        }
01983        
01984    } 
01985 
01986    
UNLOCK_ALTERNATE_TABLE (Wow64Process);
01987 
01988    *RegionSize = (SIZE_T)((ULONG_PTR)Va - (ULONG_PTR)BaseAddress);
01989 }
01990 
01991 ULONG
01992 
MiQueryProtectionFor4kPage (
01993     IN PVOID BaseAddress,
01994     IN 
PEPROCESS Process
01995     )
01996 
01997 
01998 
01999 
02000 
02001 
02002 
02003 
02004 
02005 
02006 
02007 
02008 
02009 
02010 
02011 
02012 
02013 
02014 
02015 
02016 
02017 
02018 {
02019 
02020     ULONG Protection;
02021     
PMMPTE PointerAltPte;
02022     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
02023 
02024     PointerAltPte = 
MiGetAltPteAddress(BaseAddress);
02025 
02026     
LOCK_ALTERNATE_TABLE (Process->Wow64Process);
02027     
02028    
if (
MI_CHECK_BIT(Wow64Process->AltPermBitmap, 
02029                      
MI_VA_TO_VPN(BaseAddress)) == 0) {
02030 
02031        
UNLOCK_ALTERNATE_TABLE (Wow64Process);
02032        
return 0;
02033        
02034    }
02035 
02036     Protection = (ULONG)PointerAltPte->
u.Alt.Protection;
02037 
02038     
UNLOCK_ALTERNATE_TABLE (Process->Wow64Process);
02039     
02040     
return Protection;
02041     
02042 }
02043 
02044 
VOID
02045 MiCheckPointBreak(VOID)
02046 {
02047 }
02048 
02049 
VOID
02050 MiCheckPoint(
02051     ULONG Number
02052     )
02053 {
02054     
if (Number == MmCheckPointNumber) {
02055         
02056         MiCheckPointBreak();
02057 
02058     }
02059 }
02060 
02061 
02062 MiCheckPointBreakVirtualAddress (
02063     PVOID VirtualAddress
02064 )
02065 {
02066     ULONG Value;
02067 
02068     
if (
PAGE_4K_ALIGN(VirtualAddress) == MmAddressBreak) {
02069 
02070         MiCheckPointBreak();
02071 
02072     }
02073 }
02074 
02075 
02076 
NTSTATUS
02077 
MiInitializeAlternateTable(
02078     
PEPROCESS Process
02079     )
02080 
02081 
02082 
02083 
02084 
02085 
02086 
02087 
02088 
02089 
02090 
02091 
02092 
02093 
02094 
02095 
02096 
02097 
02098 
02099 
02100 
02101 
02102 {
02103     PULONG AltTablePointer; 
02104     
PWOW64_PROCESS Wow64Process = Process->
Wow64Process;
02105 
02106     AltTablePointer = (PULONG)
ExAllocatePoolWithTag (NonPagedPool,
02107                                                     (_MAX_WOW64_ADDRESS >> PTI_SHIFT)/8,
02108                                                     'AlmM');
02109 
02110     
if (AltTablePointer == (PULONG) 
NULL) {
02111         
return  STATUS_NO_MEMORY;
02112     }
02113 
02114     Wow64Process->AltPermBitmap = AltTablePointer;
02115 
02116     RtlZeroMemory(AltTablePointer, (_MAX_WOW64_ADDRESS >> PTI_SHIFT)/8);
02117 
02118     
ExInitializeFastMutex(&Wow64Process->AlternateTableLock);
02119 
02120     
return STATUS_SUCCESS;
02121 }
02122 
02123 
02124 
VOID
02125 
MiDeleteAlternateTable(
02126     
PEPROCESS Process
02127     )
02128 
02129 
02130 
02131 
02132 
02133 
02134 
02135 
02136 
02137 
02138 
02139 
02140 
02141 
02142 
02143 
02144 
02145 
02146 
02147 
02148 
02149 {
02150 
02151     
PMMPTE PointerPte;
02152     
PMMPTE PointerPde;
02153     
PMMPTE PointerPpe;
02154     ULONG_PTR Va;
02155     ULONG_PTR TempVa;
02156     ULONG i;
02157     ULONG Waited;
02158     
MMPTE_FLUSH_LIST PteFlushList;
02159     
PWOW64_PROCESS Wow64Process = Process->
Wow64Process;
02160     KIRQL OldIrql;
02161 
02162     
ASSERT (Wow64Process->AltPermBitmap != NULL);
02163     
02164     
02165     
02166     
02167     
02168     
02169 
02170     PointerPpe = 
MiGetPpeAddress (ALT4KB_PERMISSION_TABLE_START);
02171     PointerPde = 
MiGetPdeAddress (ALT4KB_PERMISSION_TABLE_START);
02172     PointerPte = 
MiGetPteAddress (ALT4KB_PERMISSION_TABLE_START);
02173 
02174     Va = 
ALT4KB_PERMISSION_TABLE_START;
02175 
02176     
LOCK_PFN(OldIrql);
02177 
02178     
while (Va < 
ALT4KB_PERMISSION_TABLE_END) {
02179 
02180         
while (
MiDoesPdeExistAndMakeValid (PointerPde,
02181                                            Process,
02182                                            TRUE,
02183                                            &Waited) == 
FALSE) {
02184 
02185             
02186             
02187             
02188 
02189             PointerPde += 1;
02190             PointerPte = 
MiGetVirtualAddressMappedByPte (PointerPde);
02191             Va = (ULONG_PTR)
MiGetVirtualAddressMappedByPte (PointerPte);
02192 
02193             
if (Va > 
ALT4KB_PERMISSION_TABLE_START) {
02194                 
02195                 
goto delete_end;
02196 
02197             }
02198 
02199         }
02200     
02201         
02202         
02203         
02204 
02205         TempVa = Va;
02206         
for (i = 0; i < 
PTE_PER_PAGE; i++) {
02207 
02208             
if (PointerPte->
u.Long != 0) {
02209 
02210                 
if (
IS_PTE_NOT_DEMAND_ZERO (*PointerPte)) {
02211 
02212                     
MiDeletePte (PointerPte,
02213                                  (PVOID)TempVa,
02214                                  TRUE,
02215                                  Process,
02216                                  NULL,
02217                                  &PteFlushList);
02218                 } 
else {
02219 
02220                     *PointerPte = 
ZeroPte;
02221                 }
02222                                     
02223             }
02224             
02225             TempVa = 
PAGE_4K;
02226             PointerPte += 1;
02227         }
02228 
02229         
02230         
02231         
02232 
02233         TempVa = (ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPde);
02234         
MiDeletePte (PointerPde,
02235                      (PVOID)TempVa,
02236                      TRUE,
02237                      Process,
02238                      NULL,
02239                      &PteFlushList);
02240        
02241         
02242         
MiFlushPteList (&PteFlushList, FALSE, ZeroPte);
02243 
02244         PointerPde += 1;
02245         PointerPte = 
MiGetVirtualAddressMappedByPte (PointerPde);
02246         Va = (ULONG_PTR)
MiGetVirtualAddressMappedByPte (PointerPte);
02247         
02248     }
02249 
02250  delete_end:
02251 
02252     
MiFlushPteList (&PteFlushList, FALSE, ZeroPte);
02253 
02254     
UNLOCK_PFN(OldIrql);
02255     
02256     
ExFreePool (Wow64Process->AltPermBitmap);
02257 
02258     Wow64Process->AltPermBitmap = 
NULL;
02259 }
02260 
02261 
VOID
02262 MiFillZeroFor4kPage (
02263     IN PVOID VirtualAddress,
02264     IN 
PEPROCESS Process
02265     )
02266 
02267 
02268 
02269 
02270 
02271 
02272 
02273 
02274 
02275 
02276 
02277 
02278 
02279 
02280 
02281 
02282 
02283 
02284 
02285 
02286 
02287 
02288 {
02289     SIZE_T RegionSize = 
PAGE_4K;
02290     PVOID BaseAddress;
02291     ULONG OldProtect;
02292     
NTSTATUS Status;
02293     
PMMPTE PointerAltPte;
02294     
PMMPTE PointerPde;
02295     
PMMPTE PointerPpe;
02296     
PMMPTE PointerPte;
02297     
MMPTE TempAltContents;
02298     
MMPTE PteContents;
02299     ULONG Waited;
02300     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
02301 
02302     PointerAltPte = 
MiGetAltPteAddress (VirtualAddress);
02303 
02304     
LOCK_ALTERNATE_TABLE (Wow64Process);
02305 
02306     
if (PointerAltPte->
u.Alt.FillZero == 0) {
02307 
02308         
02309         
02310         
02311 
02312         
UNLOCK_ALTERNATE_TABLE (Wow64Process);
02313 
02314         
return;
02315 
02316     }
02317 
02318     
02319     
02320     
02321 
02322     PointerPte = 
MiGetPteAddress(VirtualAddress);
02323     PointerPde = 
MiGetPdeAddress(VirtualAddress);
02324     PointerPpe = 
MiGetPpeAddress(VirtualAddress);
02325 
02326     
02327     
02328     
02329     
02330 
02331     
LOCK_WS (Process);
02332 
02333     
if (
MiDoesPpeExistAndMakeValid (PointerPpe,
02334                                     Process,
02335                                     FALSE,
02336                                     &Waited) == 
FALSE) {
02337         PteContents.
u.Long = 0;
02338     
02339     } 
else if (
MiDoesPdeExistAndMakeValid (PointerPde,
02340                                            Process,
02341                                            FALSE,
02342                                            &Waited) == 
FALSE) {
02343 
02344         PteContents.
u.Long = 0;
02345 
02346     } 
else {
02347 
02348         
02349         
02350         
02351 
02352         PteContents = *PointerPte;
02353 
02354     }
02355 
02356     TempAltContents.
u.Long = PointerAltPte->
u.Long;
02357 
02358     
if (PteContents.
u.Hard.Valid != 0) { 
02359 
02360         BaseAddress = KSEG_ADDRESS(PteContents.
u.Hard.PageFrameNumber);
02361 
02362         BaseAddress = 
02363             (PVOID)((ULONG_PTR)BaseAddress + 
02364                     ((ULONG_PTR)
PAGE_4K_ALIGN(VirtualAddress) & (
PAGE_SIZE-1)));
02365 
02366         RtlZeroMemory(BaseAddress, PAGE_4K);
02367 
02368         
UNLOCK_WS (Process);
02369 
02370         TempAltContents.
u.Alt.FillZero = 0;
02371         TempAltContents.
u.Alt.Accessed = 1;
02372 
02373     } 
else {
02374 
02375         
UNLOCK_WS (Process);
02376 
02377         TempAltContents.
u.Alt.Accessed = 0;
02378 
02379     }
02380 
02381     PointerAltPte->
u.Long = TempAltContents.
u.Long;
02382 
02383     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
02384 }
02385 
02386 
#define USE_MAPVIEW 1
02387 
02388 
#if !USE_MAPVIEW
02389 
NTSTATUS
02390 MiCreateAliasOfDataSection(
02391     IN 
PCONTROL_AREA ControlArea,
02392     IN 
PEPROCESS Process,
02393     IN PVOID *CapturedBase,
02394     IN PLARGE_INTEGER SectionOffset,
02395     IN PSIZE_T CapturedViewSize,
02396     IN ULONG ProtectionMask,
02397     OUT 
PMMVAD *Vad
02398     )
02399 
02400 
02401 
02402 
02403 
02404 
02405 
02406 
02407 
02408 
02409 
02410 
02411 
02412 
02413 
02414 
02415 
02416 
02417 
02418 
02419 
02420 
02421 
02422 
02423 
02424 
02425 
02426 
02427 
02428 
02429 
02430 {
02431     ULONG_PTR Alignment;
02432     KIRQL OldIrql;
02433     
PSUBSECTION Subsection;
02434     ULONG PteOffset;
02435     PVOID NewStartingAddress;
02436     PVOID NewEndingAddress;
02437     
PMMVAD NewVad;
02438     
PMMPTE TheFirstPrototypePte;
02439 
02440     
02441     
02442     
02443 
02444     Subsection = (
PSUBSECTION)(ControlArea + 1);
02445 
02446     Alignment = 
X64K;
02447 
02448     SectionOffset->LowPart = SectionOffset->LowPart & ~((ULONG)Alignment - 1);
02449     PteOffset = (ULONG)(SectionOffset->QuadPart >> 
PAGE_SHIFT);
02450 
02451     
02452     
02453     
02454     
02455 
02456     
if (PteOffset >= ControlArea->Segment->TotalNumberOfPtes) {
02457         
LOCK_PFN (OldIrql);
02458         ControlArea->NumberOfMappedViews -= 1;
02459         ControlArea->NumberOfUserReferences -= 1;
02460         
UNLOCK_PFN (OldIrql);
02461         
return STATUS_INVALID_VIEW_SIZE;
02462     }
02463 
02464     
while (PteOffset >= Subsection->
PtesInSubsection) {
02465         PteOffset -= Subsection->
PtesInSubsection;
02466         Subsection = Subsection->
NextSubsection;
02467         
ASSERT (Subsection != NULL);
02468     }
02469 
02470     TheFirstPrototypePte = &Subsection->
SubsectionBase[PteOffset];
02471 
02472     
LOCK_WS_UNSAFE (Process);
02473 
02474     
try {
02475 
02476         
02477         
02478         
02479 
02480         NewStartingAddress = 
MiFindEmptyAddressRange (*CapturedViewSize,
02481                                                       X64K,
02482                                                       (ULONG)0);
02483     } except (EXCEPTION_EXECUTE_HANDLER) {
02484 
02485         
LOCK_PFN (OldIrql);
02486         ControlArea->NumberOfMappedViews -= 1;
02487         ControlArea->NumberOfUserReferences -= 1;
02488         
UNLOCK_PFN (OldIrql);
02489 
02490         
UNLOCK_WS_UNSAFE(Process);
02491 
02492         
return GetExceptionCode();
02493     }
02494 
02495     NewEndingAddress = (PVOID)(((ULONG_PTR)NewStartingAddress +
02496                                 *CapturedViewSize - 1
L) | (
PAGE_SIZE - 1
L));
02497 
02498     
02499     
02500     
02501     
02502 
02503     
try  {
02504 
02505         NewVad = 
ExAllocatePoolWithTag (NonPagedPool,
02506                                         
sizeof(
MMVAD),
02507                                         MMVADKEY);
02508         
if (NewVad == 
NULL) {
02509             
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
02510         }
02511         RtlZeroMemory (NewVad, 
sizeof(
MMVAD));
02512 
02513         NewVad->
StartingVpn = 
MI_VA_TO_VPN (NewStartingAddress);
02514         NewVad->
EndingVpn = 
MI_VA_TO_VPN (NewEndingAddress);
02515         NewVad->
FirstPrototypePte = TheFirstPrototypePte;
02516 
02517         
02518         
02519         
02520 
02521         NewVad->
ControlArea = ControlArea;
02522 
02523         NewVad->
u2.VadFlags2.Inherit = 1;
02524         NewVad->
u.VadFlags.Protection = ProtectionMask;
02525         NewVad->
u2.VadFlags2.CopyOnWrite = 0;
02526 
02527         
02528         
02529         
02530         
02531 
02532         NewVad->
u2.VadFlags2.FileOffset = (ULONG)(SectionOffset->QuadPart >> 16);
02533 
02534         
02535         
02536         
02537         
02538         
02539         
02540         
02541 
02542         PteOffset += (ULONG)(NewVad->
EndingVpn - NewVad->
StartingVpn);
02543 
02544         
if (PteOffset < Subsection->
PtesInSubsection ) {
02545             NewVad->
LastContiguousPte = &Subsection->
SubsectionBase[PteOffset];
02546 
02547         } 
else {
02548             NewVad->
LastContiguousPte = &Subsection->
SubsectionBase[
02549                                         (Subsection->
PtesInSubsection - 1) +
02550                                         Subsection->
UnusedPtes];
02551         }
02552 
02553         
ASSERT (NewVad->
FirstPrototypePte <= NewVad->
LastContiguousPte);
02554         
MiInsertVad (NewVad);
02555 
02556     } except (EXCEPTION_EXECUTE_HANDLER) {
02557 
02558         
LOCK_PFN (OldIrql);
02559         ControlArea->NumberOfMappedViews -= 1;
02560         ControlArea->NumberOfUserReferences -= 1;
02561         
UNLOCK_PFN (OldIrql);
02562 
02563         
if (NewVad != (
PMMVAD)
NULL) {
02564 
02565             
02566             
02567             
02568             
02569             
02570 
02571             
ExFreePool (NewVad);
02572 
02573             
UNLOCK_WS_UNSAFE (Process);
02574 
02575             
return GetExceptionCode();
02576         }
02577         
02578         
UNLOCK_WS_UNSAFE (Process);
02579 
02580         
return STATUS_INSUFFICIENT_RESOURCES;
02581     }
02582 
02583     
UNLOCK_WS_UNSAFE (Process);
02584 
02585     
02586     
02587     
02588 
02589     *CapturedViewSize = (PCHAR)NewEndingAddress - (PCHAR)NewStartingAddress + 1
L;
02590 
02591     Process->VirtualSize += *CapturedViewSize;
02592 
02593     
if (Process->VirtualSize > Process->PeakVirtualSize) {
02594         Process->PeakVirtualSize = Process->VirtualSize;
02595     }
02596 
02597     *CapturedBase = NewStartingAddress;
02598 
02599     *Vad = NewVad;
02600 
02601     
return STATUS_SUCCESS;
02602 }
02603 
#endif
02604 
02605 
NTSTATUS
02606 MiSetCopyPagesFor4kPage(
02607     IN 
PEPROCESS Process,
02608     IN OUT 
PMMVAD *Vad,
02609     IN OUT PVOID *StartingAddress,
02610     IN OUT PVOID *EndingAddress,
02611     IN ULONG NewProtection
02612     )
02613 
02614 
02615 
02616 
02617 
02618 
02619 
02620 
02621 
02622 
02623 
02624 
02625 
02626 
02627 
02628 
02629 
02630 
02631 
02632 
02633 
02634 
02635 
02636 
02637 
02638 
02639 
02640 
02641 
02642 
02643 
02644 
02645 
02646 
02647 
02648 {
02649     LARGE_INTEGER SectionOffset;
02650     SIZE_T CapturedViewSize;
02651     PVOID CapturedBase;
02652     PVOID Va;
02653     PVOID VaEnd;
02654     PVOID Alias;
02655     
PMMVAD NewVad;
02656     
PMMPTE PointerPte;
02657     
PMMPTE AltPte;
02658 
#if USE_MAPVIEW
02659 
    BOOLEAN ReleasedWsMutex;
02660     
SECTION Section;
02661     
PCONTROL_AREA ControlArea;
02662 
#endif
02663 
    NTSTATUS status;
02664 
02665     SectionOffset.QuadPart = (ULONG_PTR)*StartingAddress - 
02666         (ULONG_PTR)((*Vad)->StartingVpn << 
PAGE_SHIFT);
02667 
02668     CapturedBase = (PVOID)
NULL;
02669     CapturedViewSize = (ULONG_PTR)*EndingAddress - (ULONG_PTR)*StartingAddress + 1;
02670 
02671 
#if USE_MAPVIEW
02672 
02673     ControlArea = (*Vad)->ControlArea;
02674 
02675     RtlZeroMemory((PVOID)&Section, 
sizeof(Section));
02676 
02677     ReleasedWsMutex = 
FALSE;
02678 
02679     
UNLOCK_WS_UNSAFE (Process);
02680 
02681     status = 
MiMapViewOfDataSection (ControlArea,
02682                                      Process,
02683                                      &CapturedBase,
02684                                      &SectionOffset,
02685                                      &CapturedViewSize,
02686                                      &Section,
02687                                      ViewShare,
02688                                      (ULONG)(*Vad)->u.VadFlags.Protection,
02689                                      0,
02690                                      0,
02691                                      0,
02692                                      &ReleasedWsMutex);
02693         
02694     
if (!ReleasedWsMutex) {
02695         
UNLOCK_WS_UNSAFE (Process);
02696     }
02697 
02698     
if (status != STATUS_SUCCESS) {
02699 
02700         
return status;
02701     }    
02702 
02703     NewVad = 
MiLocateAddress(CapturedBase);
02704 
02705     
ASSERT(NewVad != (
PMMVAD)NULL);
02706 
02707 
#else
02708 
02709     
UNLOCK_WS_UNSAFE (Process);
02710 
02711     status = MiCreateAliasOfDataSection((*Vad)->ControlArea,
02712                                         Process,
02713                                         &CapturedBase,
02714                                         &SectionOffset,
02715                                         &CapturedViewSize,
02716                                         (ULONG)(*Vad)->u.VadFlags.Protection,
02717                                         &NewVad);
02718     
if (status != STATUS_SUCCESS) {
02719 
02720         
LOCK_WS_UNSAFE (Process);
02721         
return status;
02722     }    
02723 
02724 
02725 
#endif
02726 
02727     
LOCK_ALTERNATE_TABLE (Process->Wow64Process);
02728 
02729     Va = *StartingAddress;
02730     VaEnd = *EndingAddress;
02731     Alias = CapturedBase;
02732 
02733     
while (Va <= VaEnd) {
02734 
02735         AltPte = 
MiGetAltPteAddress (Va);
02736         PointerPte = 
MiGetPteAddress (Alias);
02737         
if (AltPte->
u.Alt.CopyOnWrite == 1) {
02738             AltPte->
u.Alt.PteOffset = (ULONG_PTR)PointerPte - PTE_UBASE;
02739             AltPte->
u.Alt.PteIndirect = 1;
02740         }
02741 
02742         Va = (PVOID)((ULONG_PTR)Va + 
PAGE_4K);
02743         Alias = (PVOID)((ULONG_PTR)Alias + 
PAGE_4K);
02744     }
02745         
02746     
MiMarkSplitPages(*StartingAddress, 
02747                      *EndingAddress,
02748                      Process->Wow64Process->AltPermBitmap,
02749                      TRUE);
02750 
02751     
UNLOCK_ALTERNATE_TABLE (Process->Wow64Process);
02752 
02753     
LOCK_WS_UNSAFE (Process);
02754 
02755     Process->Wow64Process->AltFlags |= 
MI_ALTFLG_FLUSH2G;
02756 
02757     *Vad = NewVad;
02758     *StartingAddress = CapturedBase;
02759     *EndingAddress = (PVOID)((ULONG_PTR)CapturedBase + CapturedViewSize - 1
L);
02760 
02761     
return STATUS_SUCCESS;
02762 }    
02763 
02764 
VOID
02765 
MiLockFor4kPage(
02766     PVOID CapturedBase,
02767     SIZE_T CapturedRegionSize,
02768     
PEPROCESS Process
02769     )
02770 
02771 
02772 
02773 
02774 
02775 
02776 
02777 
02778 
02779 
02780 
02781 
02782 
02783 
02784 
02785 
02786 
02787 
02788 
02789 
02790 
02791 
02792 
02793 
02794 {
02795     
PWOW64_PROCESS Wow64Process = Process->
Wow64Process;
02796     PVOID EndingAddress;
02797     
PMMPTE StartAltPte;
02798     
PMMPTE EndAltPte;
02799 
02800     EndingAddress = (PVOID)((ULONG_PTR)CapturedBase + CapturedRegionSize - 1);
02801 
02802     StartAltPte = 
MiGetAltPteAddress(CapturedBase);
02803     EndAltPte = 
MiGetAltPteAddress(EndingAddress);
02804 
02805     
LOCK_ALTERNATE_TABLE (Wow64Process);
02806     
02807     
while (StartAltPte <= EndAltPte) {
02808 
02809         StartAltPte->
u.Alt.Lock = 1;
02810         StartAltPte++;
02811 
02812     }
02813 
02814     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
02815 
02816 }
02817 
02818 
NTSTATUS
02819 
MiUnlockFor4kPage(
02820     PVOID CapturedBase,
02821     SIZE_T CapturedRegionSize,
02822     
PEPROCESS Process
02823     )
02824 
02825 
02826 
02827 
02828 
02829 
02830 
02831 
02832 
02833 
02834 
02835 
02836 
02837 
02838 
02839 
02840 
02841 
02842 
02843 
02844 
02845 
02846 
02847 
02848 {
02849     
PMMPTE StartAltPte;
02850     
PMMPTE EndAltPte;
02851     
PWOW64_PROCESS Wow64Process = Process->
Wow64Process;
02852     PVOID EndingAddress;
02853     
NTSTATUS Status = STATUS_SUCCESS;
02854 
02855     EndingAddress = (PVOID)((ULONG_PTR)CapturedBase + CapturedRegionSize - 1);
02856 
02857     StartAltPte = 
MiGetAltPteAddress(CapturedBase);
02858     EndAltPte = 
MiGetAltPteAddress(EndingAddress);
02859 
02860     
02861     
02862     
02863 
02864     
UNLOCK_WS_UNSAFE (Process);
02865 
02866     
LOCK_ALTERNATE_TABLE (Wow64Process);
02867     
02868     
while (StartAltPte <= EndAltPte) {
02869 
02870         
if (StartAltPte->
u.Alt.Lock == 0) {
02871 
02872             
Status = STATUS_NOT_LOCKED;
02873             
goto StatusReturn;
02874 
02875         }
02876 
02877         StartAltPte++;
02878     }
02879 
02880     StartAltPte = 
MiGetAltPteAddress(CapturedBase);
02881 
02882     
while (StartAltPte <= EndAltPte) {
02883 
02884         StartAltPte->
u.Alt.Lock = 0;
02885 
02886         StartAltPte++;
02887     }
02888 
02889 StatusReturn:
02890 
02891     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
02892 
02893     
LOCK_WS_UNSAFE (Process);
02894 
02895     
return (
Status);
02896 }
02897 
02898 BOOLEAN
02899 
MiShouldBeUnlockedFor4kPage(
02900     PVOID VirtualAddress,
02901     
PEPROCESS Process
02902     )
02903 
02904 
02905 
02906 
02907 
02908 
02909 
02910 
02911 
02912 
02913 
02914 
02915 
02916 
02917 
02918 
02919 
02920 
02921 
02922 
02923 
02924 
02925 
02926 {
02927     
PMMPTE PointerAltPte;
02928     
PMMPTE StartAltPte;
02929     
PMMPTE EndAltPte;
02930     
PWOW64_PROCESS Wow64Process = Process->
Wow64Process;
02931     PVOID VirtualAligned;
02932     PVOID EndingAddress;
02933     BOOLEAN PageUnlocked = 
TRUE;
02934 
02935     VirtualAligned = 
PAGE_ALIGN(VirtualAddress);
02936     EndingAddress = (PVOID)((ULONG_PTR)VirtualAligned + 
PAGE_SIZE - 1);
02937 
02938     StartAltPte = 
MiGetAltPteAddress(VirtualAligned);
02939     EndAltPte = 
MiGetAltPteAddress(EndingAddress);
02940 
02941     
02942     
02943     
02944 
02945     
UNLOCK_WS_UNSAFE (Process);
02946 
02947     
LOCK_ALTERNATE_TABLE (Wow64Process);
02948 
02949     
while (StartAltPte <= EndAltPte) {
02950 
02951         
if (StartAltPte->
u.Alt.Lock != 0) {
02952             PageUnlocked = 
FALSE;
02953         }
02954 
02955         StartAltPte++;
02956     }
02957 
02958     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
02959 
02960     
LOCK_WS_UNSAFE (Process);
02961 
02962     
return (PageUnlocked);
02963 }
02964 
02965 
VOID
02966 MiCopyOnWriteFor4kPage(
02967     PVOID VirtualAddress,
02968     
PEPROCESS Process
02969     )
02970 
02971 
02972 
02973 
02974 
02975 
02976 
02977 
02978 
02979 
02980 
02981 
02982 
02983 
02984 
02985 
02986 
02987 
02988 
02989 
02990 
02991 
02992 
02993 {
02994     
PMMPTE PointerAltPte;
02995     
MMPTE TempAltPte;
02996     ULONG i;
02997     
02998     PointerAltPte = 
MiGetAltPteAddress(
PAGE_ALIGN(VirtualAddress));
02999     
03000     
for (i = 0; i < 
SPLITS_PER_PAGE; i++) {
03001      
03002         TempAltPte.
u.Long = PointerAltPte->
u.Long;
03003 
03004         
if ((TempAltPte.
u.Alt.Commit != 0) && 
03005             (TempAltPte.
u.Alt.CopyOnWrite != 0)) {
03006 
03007             TempAltPte.
u.Alt.CopyOnWrite = 0;
03008             TempAltPte.
u.Alt.Private = 1;
03009             TempAltPte.
u.Hard.Write = 1;
03010 
03011             TempAltPte.
u.Alt.Protection = 
03012                     
MI_MAKE_PROTECT_NOT_WRITE_COPY(PointerAltPte->
u.Alt.Protection);
03013 
03014         } 
else {
03015 
03016             
03017             
03018             
03019 
03020             TempAltPte.
u.Alt.Private = 1;
03021 
03022             MiCheckPointBreak();
03023 
03024         }
03025         
03026         
03027         
03028         
03029 
03030         PointerAltPte->
u.Long = TempAltPte.
u.Long;
03031         PointerAltPte++;
03032     }
03033 }
03034 
03035 
VOID
03036 MiCheckDemandZeroCopyOnWriteFor4kPage(
03037     PVOID VirtualAddress,
03038     
PEPROCESS Process
03039     )
03040 
03041 
03042 
03043 
03044 
03045 
03046 
03047 
03048 
03049 
03050 
03051 
03052 
03053 
03054 
03055 
03056 
03057 
03058 
03059 
03060 
03061 
03062 
03063 {
03064     
PMMPTE PointerPpe;
03065     
PMMPTE PointerPde;
03066     
PMMPTE PointerPte;
03067     
MMPTE PteContents;
03068     
PMMPTE ProtoPte;
03069     
PMMPFN Pfn1;
03070     KIRQL OldIrql;
03071     ULONG OriginalProtection;
03072     ULONGLONG ProtectionMaskOriginal;
03073     ULONG Waited;
03074 
03075     
03076     
03077     
03078 
03079     
LOCK_WS (Process);
03080 
03081     ProtoPte = 
MiCheckVirtualAddress (VirtualAddress, &OriginalProtection);
03082 
03083     
if (OriginalProtection == 
MM_UNKNOWN_PROTECTION) {
03084 
03085         
if (!
MI_IS_PHYSICAL_ADDRESS(ProtoPte)) {
03086             PointerPde = 
MiGetPteAddress (ProtoPte);
03087             
LOCK_PFN (OldIrql);
03088             
if (PointerPde->
u.Hard.Valid == 0) {
03089                 
MiMakeSystemAddressValidPfn (ProtoPte);
03090             }
03091             Pfn1 = 
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
03092             Pfn1->
u3.e2.ReferenceCount += 1;
03093             
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
03094             
UNLOCK_PFN (OldIrql);
03095         }
03096 
03097         
if (!
IS_PTE_NOT_DEMAND_ZERO(*ProtoPte)) {
03098 
03099             PointerPde = 
MiGetPdeAddress(VirtualAddress);
03100             PointerPpe = 
MiGetPpeAddress(VirtualAddress);
03101             PointerPte = 
MiGetPteAddress(VirtualAddress);
03102 
03103             
if (
MiDoesPpeExistAndMakeValid (PointerPpe,
03104                                             Process,
03105                                             FALSE,
03106                                             &Waited) == 
FALSE) {
03107                 PteContents.
u.Long = 0;
03108     
03109             } 
else if (
MiDoesPdeExistAndMakeValid (PointerPde,
03110                                                    Process,
03111                                                    FALSE,
03112                                                    &Waited) == 
FALSE) {
03113 
03114                 PteContents.
u.Long = 0;
03115 
03116             } 
else {
03117 
03118                 
03119                 
03120                 
03121 
03122                 PteContents = *PointerPte;
03123 
03124             }
03125 
03126             
if (PteContents.
u.Hard.Valid != 0) {
03127 
03128                 PteContents.
u.Hard.CopyOnWrite = 0;
03129                 PteContents.
u.Hard.Write = 1;
03130                 PointerPte->
u.Long = PteContents.
u.Long;
03131 
03132             }
03133         }
03134 
03135         
03136         
03137         
03138 
03139         
if (!
MI_IS_PHYSICAL_ADDRESS(ProtoPte)) {
03140             
LOCK_PFN (OldIrql);
03141             
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
03142             Pfn1->
u3.e2.ReferenceCount -= 1;
03143             
UNLOCK_PFN (OldIrql);
03144         }
03145     }
03146         
03147     
UNLOCK_WS (Process);
03148 }
03149 
03150 ULONG
03151 
MiMakeProtectForNativePage(
03152     IN PVOID VirtualAddress,
03153     IN ULONG NewProtect,
03154     IN 
PEPROCESS Process
03155     )
03156 
03157 
03158 
03159 
03160 
03161 
03162 
03163 
03164 
03165 
03166 
03167 
03168 
03169 
03170 
03171 
03172 
03173 
03174 
03175 
03176 
03177 
03178 
03179 
03180 {
03181     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
03182 
03183 
#if 0
03184 
    LOCK_ALTERNATE_TABLE (Wow64Process);
03185 
#endif 
03186 
    
03187     
if (
MI_CHECK_BIT(Wow64Process->AltPermBitmap, 
03188                      
MI_VA_TO_VPN(VirtualAddress)) != 0) {
03189 
03190         
if (NewProtect & PAGE_NOACCESS) {
03191             NewProtect &= ~PAGE_NOACCESS;
03192             NewProtect |= PAGE_EXECUTE_READWRITE;
03193         }
03194 
03195         
if (NewProtect & PAGE_READONLY) {
03196             NewProtect &= ~PAGE_READONLY;
03197             NewProtect |= PAGE_EXECUTE_READWRITE;
03198         }
03199 
03200         
if (NewProtect & PAGE_EXECUTE) {
03201             NewProtect &= ~PAGE_EXECUTE;
03202             NewProtect |= PAGE_EXECUTE_READWRITE;
03203         }
03204 
03205         
if (NewProtect & PAGE_EXECUTE_READ) {
03206             NewProtect &= ~PAGE_EXECUTE_READ;
03207             NewProtect |= PAGE_EXECUTE_READWRITE;
03208         }
03209 
03210 
#if 0            
03211 
        
03212         
03213         
03214 
03215         
if (NewProtect & PAGE_GUARD) {
03216             NewProtect &= ~PAGE_GUARD;
03217         }
03218 
#endif
03219 
    }
03220 
03221 
#if 0
03222 
    UNLOCK_ALTERNATE_TABLE (Wow64Process);
03223 
#endif
03224 
03225     
return NewProtect;
03226 }
03227 
03228 
VOID
03229 MiCheckVirtualAddressFor4kPage(
03230     PVOID VirtualAddress,
03231     
PEPROCESS Process
03232     )
03233 {
03234     
PMMPTE ProtoPte;
03235     
PMMPTE PointerAltPte;
03236     
PMMPTE PointerPde;
03237     
MMPTE AltPteContents;
03238     
MMPTE TempPte;
03239     ULONG OriginalProtection;
03240     ULONGLONG ProtectionMaskOriginal;
03241     
PWOW64_PROCESS Wow64Process;
03242     KIRQL OldIrql;
03243     
PMMPFN Pfn1;
03244     ULONG i;
03245 
03246     Wow64Process = Process->
Wow64Process;
03247 
03248     
LOCK_WS (Process);
03249 
03250     ProtoPte = 
MiCheckVirtualAddress (VirtualAddress, &OriginalProtection);
03251 
03252     
if (OriginalProtection == 
MM_UNKNOWN_PROTECTION) {
03253 
03254         
if (!
MI_IS_PHYSICAL_ADDRESS(ProtoPte)) {
03255             PointerPde = 
MiGetPteAddress (ProtoPte);
03256             
LOCK_PFN (OldIrql);
03257             
if (PointerPde->
u.Hard.Valid == 0) {
03258                 
MiMakeSystemAddressValidPfn (ProtoPte);
03259             }
03260             Pfn1 = 
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
03261             Pfn1->
u3.e2.ReferenceCount += 1;
03262             
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
03263             
UNLOCK_PFN (OldIrql);
03264         }
03265 
03266         OriginalProtection = 
03267             
MiMakeProtectionMask(
MiGetPageProtection(ProtoPte, Process));
03268 
03269         
03270         
03271         
03272 
03273         
if (!
MI_IS_PHYSICAL_ADDRESS(ProtoPte)) {
03274             
LOCK_PFN (OldIrql);
03275             
ASSERT (Pfn1->
u3.e2.ReferenceCount > 1);
03276             Pfn1->
u3.e2.ReferenceCount -= 1;
03277             
UNLOCK_PFN (OldIrql);
03278         }
03279 
03280     }
03281         
03282     
UNLOCK_WS (Process);
03283 
03284     ProtectionMaskOriginal = 
MiMakeProtectionAteMask (OriginalProtection);
03285     ProtectionMaskOriginal |= 
MM_ATE_COMMIT;
03286 
03287     PointerAltPte = 
MiGetAltPteAddress(
PAGE_ALIGN(VirtualAddress));
03288 
03289     AltPteContents.
u.Long = ProtectionMaskOriginal;
03290     AltPteContents.
u.Alt.Protection = OriginalProtection;
03291         
03292     
for (i = 0; i < 
SPLITS_PER_PAGE; i += 1) {
03293 
03294         
03295         
03296         
03297 
03298         PointerAltPte->
u.Long = AltPteContents.
u.Long;
03299         PointerAltPte += 1;
03300     }
03301 
03302     
03303     
03304     
03305 
03306     
MiMarkSplitPages(
03307         VirtualAddress,
03308         VirtualAddress,
03309         Wow64Process->AltPermBitmap,
03310         TRUE);
03311 }
03312 
03313 MiIsEntireRangeCommittedFor4kPage(
03314     IN PVOID StartVirtual,
03315     IN PVOID EndVirtual,
03316     IN 
PEPROCESS Process
03317     )
03318 {
03319     
PWOW64_PROCESS Wow64Process = Process->Wow64Process;
03320 
03321     
LOCK_ALTERNATE_TABLE (Wow64Process);
03322 
03323     
UNLOCK_ALTERNATE_TABLE (Wow64Process);
03324 }
03325 
03326 
#endif
03327 
03328