00042                    :
00043 
00044     This function locks a region of pages within 
the working set list
00045     of a subject process.
00046 
00047     The caller of 
this function must have PROCESS_VM_OPERATION access
00048     to 
the target process.  The caller must also have 
SeLockMemoryPrivilege.
00049 
00050 Arguments:
00051 
00052    ProcessHandle - Supplies an open handle to a process object.
00053 
00054    BaseAddress - The base address of 
the region of pages
00055         to be locked. This value 
is rounded down to 
the
00056         next host page address boundary.
00057 
00058    RegionSize - 
A pointer to a variable that will receive
00059         
the actual size in bytes of 
the locked region of
00060         pages. The initial value of 
this argument 
is
00061         rounded up to 
the next host page size boundary.
00062 
00063    MapType - 
A set of flags that describe 
the type of locking to
00064             perform.  One of MAP_PROCESS or MAP_SYSTEM.
00065 
00066 Return Value:
00067 
00068     Returns 
the status
00069 
00070     STATUS_PRIVILEGE_NOT_HELD - The caller did not have sufficient
00071         privilege to perform 
the requested operation.
00072 
00073     TBS
00074 
00075 
00076 --*/
00077 
00078 {
00079     PVOID Va;
00080     PVOID EndingAddress;
00081     
PMMPTE PointerPte;
00082     
PMMPTE PointerPte1;
00083     
PMMPFN Pfn1;
00084     
PMMPTE PointerPde;
00085     
PMMPTE PointerPpe;
00086     ULONG_PTR CapturedRegionSize;
00087     PVOID CapturedBase;
00088     
PEPROCESS TargetProcess;
00089     
NTSTATUS Status;
00090     BOOLEAN WasLocked;
00091     
KPROCESSOR_MODE PreviousMode;
00092     ULONG Entry;
00093     ULONG SwapEntry;
00094     SIZE_T NumberOfAlreadyLocked;
00095     SIZE_T NumberToLock;
00096     ULONG WorkingSetIndex;
00097     
PMMVAD Vad;
00098     PVOID LastVa;
00099     
MMLOCK_CONFLICT Conflict;
00100     ULONG Waited;
00101     LOGICAL Attached;
00102 
#if defined(_MIALT4K_)
00103 
    BOOLEAN IsWow64Process = 
FALSE;
00104 
#endif
00105 
00106     
PAGED_CODE();
00107 
00108     WasLocked = 
FALSE;
00109     LastVa = 
NULL;
00110 
00111     
00112     
00113     
00114 
00115     
if ((MapType & ~(MAP_PROCESS | MAP_SYSTEM)) != 0) {
00116         
return STATUS_INVALID_PARAMETER;
00117     }
00118 
00119     
if ((MapType & (MAP_PROCESS | MAP_SYSTEM)) == 0) {
00120         
return STATUS_INVALID_PARAMETER;
00121     }
00122 
00123     PreviousMode = KeGetPreviousMode();
00124 
00125     
try {
00126 
00127         
if (PreviousMode != 
KernelMode) {
00128 
00129             
ProbeForWritePointer ((PULONG)BaseAddress);
00130             
ProbeForWriteUlong_ptr (RegionSize);
00131         }
00132 
00133         
00134         
00135         
00136 
00137         CapturedBase = *BaseAddress;
00138 
00139         
00140         
00141         
00142 
00143         CapturedRegionSize = *RegionSize;
00144 
00145     } except (
ExSystemExceptionFilter()) {
00146 
00147         
00148         
00149         
00150         
00151         
00152 
00153         
return GetExceptionCode();
00154     }
00155 
00156     
00157     
00158     
00159     
00160 
00161     
if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {
00162 
00163         
00164         
00165         
00166 
00167         
return STATUS_INVALID_PARAMETER;
00168     }
00169 
00170     
if ((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)CapturedBase <
00171                                                         CapturedRegionSize) {
00172 
00173         
00174         
00175         
00176 
00177         
return STATUS_INVALID_PARAMETER;
00178 
00179     }
00180 
00181     
if (CapturedRegionSize == 0) {
00182         
return STATUS_INVALID_PARAMETER;
00183     }
00184 
00185     
00186     
00187     
00188 
00189     
Status = 
ObReferenceObjectByHandle ( ProcessHandle,
00190                                          PROCESS_VM_OPERATION,
00191                                          PsProcessType,
00192                                          PreviousMode,
00193                                          (PVOID *)&TargetProcess,
00194                                          NULL );
00195 
00196     
if (!
NT_SUCCESS(Status)) {
00197         
return Status;
00198     }
00199 
00200     
if ((MapType & MAP_SYSTEM) != 0) {
00201 
00202         
00203         
00204         
00205         
00206 
00207         
if (!
SeSinglePrivilegeCheck(
00208                            SeLockMemoryPrivilege,
00209                            PreviousMode
00210                            )) {
00211 
00212             
ObDereferenceObject( TargetProcess );
00213             
return( STATUS_PRIVILEGE_NOT_HELD );
00214         }
00215     }
00216 
00217     
00218     
00219     
00220 
00221     
if (ProcessHandle != NtCurrentProcess()) {
00222         
KeAttachProcess (&TargetProcess->
Pcb);
00223         Attached = 
TRUE;
00224     }
00225     
else {
00226         Attached = 
FALSE;
00227     }
00228 
00229     
00230     
00231     
00232     
00233     
00234     
00235     
00236 
00237 
#if defined(_MIALT4K_)
00238 
00239     
00240     
00241     
00242 
00243     EndingAddress = 
PAGE_4K_ALIGN((PCHAR)CapturedBase + CapturedRegionSize - 1);
00244 
#else
00245 
    EndingAddress = 
PAGE_ALIGN((PCHAR)CapturedBase + CapturedRegionSize - 1);
00246 
#endif
00247 
00248     Va = 
PAGE_ALIGN (CapturedBase);
00249     NumberOfAlreadyLocked = 0;
00250     NumberToLock = ((ULONG_PTR)EndingAddress - (ULONG_PTR)Va) >> 
PAGE_SHIFT;
00251 
00252     
LOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
00253 
00254     
00255     
00256     
00257 
00258     
if (TargetProcess->
AddressSpaceDeleted != 0) {
00259         
Status = STATUS_PROCESS_IS_TERMINATING;
00260         
goto ErrorReturn;
00261     }
00262 
00263     
if (NumberToLock + 
MM_FLUID_WORKING_SET >
00264                                     TargetProcess->
Vm.
MinimumWorkingSetSize) {
00265         
Status = STATUS_WORKING_SET_QUOTA;
00266         
goto ErrorReturn;
00267     }
00268 
00269     
while (Va <= EndingAddress) {
00270 
00271         
if (Va > LastVa) {
00272 
00273             
00274             
00275             
00276 
00277             Vad = 
MiLocateAddress (Va);
00278             
if (Vad == 
NULL) {
00279                 
Status = STATUS_ACCESS_VIOLATION;
00280                 
goto ErrorReturn;
00281             }
00282 
00283             
if ((Vad->
u.VadFlags.PhysicalMapping == 1) ||
00284                 (Vad->
u.VadFlags.UserPhysicalPages == 1)) {
00285                 
Status = STATUS_INCOMPATIBLE_FILE_MAP;
00286                 
goto ErrorReturn;
00287             }
00288             LastVa = 
MI_VPN_TO_VA (Vad->
EndingVpn);
00289         }
00290 
00291         
if (
MmIsAddressValid (Va)) {
00292 
00293             
00294             
00295             
00296             
00297 
00298             PointerPte1 = 
MiGetPteAddress (Va);
00299             Pfn1 = 
MI_PFN_ELEMENT (PointerPte1->
u.Hard.PageFrameNumber);
00300 
00301             WorkingSetIndex = 
MiLocateWsle (Va,
00302                                             MmWorkingSetList,
00303                                             Pfn1->
u1.WsIndex);
00304 
00305             
ASSERT (WorkingSetIndex != WSLE_NULL_INDEX);
00306 
00307             
if (WorkingSetIndex < 
MmWorkingSetList->
FirstDynamic) {
00308 
00309                 
00310                 
00311                 
00312 
00313                 NumberOfAlreadyLocked += 1;
00314 
00315                 
00316                 
00317                 
00318 
00319                 
if ((MapType & MAP_PROCESS) &&
00320                         (
MmWsle[WorkingSetIndex].
u1.e1.LockedInWs == 1)) {
00321                     WasLocked = 
TRUE;
00322                 }
00323 
00324                 
if ((MapType & MAP_SYSTEM) &&
00325                         (
MmWsle[WorkingSetIndex].
u1.e1.LockedInMemory == 1)) {
00326                     WasLocked = 
TRUE;
00327                 }
00328             }
00329         }
00330         Va = (PVOID)((PCHAR)Va + 
PAGE_SIZE);
00331     }
00332 
00333     
UNLOCK_WS_UNSAFE (TargetProcess);
00334 
00335     
00336     
00337     
00338     
00339 
00340     
if (TargetProcess->
Vm.
MinimumWorkingSetSize <
00341           ((
MmWorkingSetList->
FirstDynamic + NumberToLock +
00342                       
MM_FLUID_WORKING_SET) - NumberOfAlreadyLocked)) {
00343 
00344         
Status = STATUS_WORKING_SET_QUOTA;
00345         
UNLOCK_ADDRESS_SPACE (TargetProcess);
00346         
goto ErrorReturn1;
00347     }
00348 
00349     Va = 
PAGE_ALIGN (CapturedBase);
00350 
00351 
#if defined(_MIALT4K_)
00352 
00353     
if (TargetProcess->
Wow64Process != 
NULL) {
00354 
00355         IsWow64Process = 
TRUE;
00356         Va = 
PAGE_4K_ALIGN (CapturedBase);
00357 
00358     }
00359 
00360 
#endif
00361 
00362     
00363     
00364     
00365     
00366 
00367     
MiInsertConflictInList (&Conflict);
00368 
00369     
try {
00370 
00371         
while (Va <= EndingAddress) {
00372             *(
volatile ULONG *)Va;
00373             Va = (PVOID)((PCHAR)Va + 
PAGE_SIZE);
00374         }
00375 
00376     } except (EXCEPTION_EXECUTE_HANDLER) {
00377         
Status = GetExceptionCode();
00378         
MiRemoveConflictFromList (&Conflict);
00379         
UNLOCK_ADDRESS_SPACE (TargetProcess);
00380         
goto ErrorReturn1;
00381     }
00382 
00383     
MiRemoveConflictFromList (&Conflict);
00384 
00385     
00386     
00387     
00388     
00389 
00390     PointerPte = 
MiGetPteAddress (CapturedBase);
00391     Va = 
PAGE_ALIGN (CapturedBase);
00392 
00393 
#if defined(_MIALT4K_)
00394 
00395     
if (IsWow64Process) {
00396 
00397         Va = 
PAGE_4K_ALIGN (CapturedBase);
00398 
00399     }
00400 
00401 
#endif
00402 
00403     
00404     
00405     
00406 
00407     
LOCK_WS_UNSAFE (TargetProcess);
00408 
00409     
while (Va <= EndingAddress) {
00410 
00411         
00412         
00413         
00414 
00415         PointerPde = 
MiGetPdeAddress (Va);
00416         PointerPpe = 
MiGetPteAddress (PointerPde);
00417 
00418         
do {
00419 
00420             (
VOID)
MiDoesPpeExistAndMakeValid (PointerPpe,
00421                                               TargetProcess,
00422                                               FALSE,
00423                                               &Waited);
00424 
00425             Waited = 0;
00426 
00427             (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde,
00428                                               TargetProcess,
00429                                               FALSE,
00430                                               &Waited);
00431 
00432         } 
while (Waited != 0);
00433 
00434         
00435         
00436         
00437 
00438         
while (PointerPte->
u.Hard.Valid == 0) {
00439 
00440             
00441             
00442             
00443 
00444             
UNLOCK_WS_UNSAFE (TargetProcess);
00445 
00446             
00447             
00448             
00449 
00450             *(
volatile ULONG *)Va;
00451 
00452             
00453             
00454             
00455 
00456             
LOCK_WS_UNSAFE (TargetProcess);
00457 
00458             
00459             
00460             
00461             
00462             
00463             
00464 
00465             
do {
00466 
00467                 (
VOID)
MiDoesPpeExistAndMakeValid (PointerPpe,
00468                                                   TargetProcess,
00469                                                   FALSE,
00470                                                   &Waited);
00471 
00472                 Waited = 0;
00473 
00474                 (
VOID)
MiDoesPdeExistAndMakeValid (PointerPde,
00475                                                   TargetProcess,
00476                                                   FALSE,
00477                                                   &Waited);
00478             } 
while (Waited != 0);
00479         }
00480 
00481         
00482         
00483         
00484         
00485 
00486         PointerPte1 = 
MiGetPteAddress (Va);
00487         Pfn1 = 
MI_PFN_ELEMENT (PointerPte1->
u.Hard.PageFrameNumber);
00488 
00489         Entry = 
MiLocateWsle (Va, MmWorkingSetList, Pfn1->
u1.WsIndex);
00490 
00491         
if (Entry >= 
MmWorkingSetList->
FirstDynamic) {
00492 
00493             SwapEntry = 
MmWorkingSetList->
FirstDynamic;
00494 
00495             
if (Entry != 
MmWorkingSetList->
FirstDynamic) {
00496 
00497                 
00498                 
00499                 
00500 
00501                 
MiSwapWslEntries (Entry, SwapEntry, &TargetProcess->
Vm);
00502             }
00503 
00504             
MmWorkingSetList->
FirstDynamic += 1;
00505         } 
else {
00506             SwapEntry = Entry;
00507         }
00508 
00509         
00510         
00511         
00512 
00513         
if (MapType & MAP_PROCESS) {
00514             
MmWsle[SwapEntry].
u1.e1.LockedInWs = 1;
00515         }
00516 
00517         
if (MapType & MAP_SYSTEM) {
00518             
MmWsle[SwapEntry].
u1.e1.LockedInMemory = 1;
00519         }
00520 
00521         
00522         
00523         
00524 
00525         PointerPte += 1;
00526         Va = (PVOID)((PCHAR)Va + 
PAGE_SIZE);
00527     }
00528 
00529 
#if !(defined(_MIALT4K_))
00530 
00531     
UNLOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
00532 
00533 
#else
00534 
00535     
UNLOCK_WS_UNSAFE (TargetProcess);
00536 
00537     
if (IsWow64Process) {
00538 
00539         
MiLockFor4kPage(CapturedBase, CapturedRegionSize, TargetProcess);
00540 
00541     }
00542 
00543     
UNLOCK_ADDRESS_SPACE (TargetProcess);
00544 
00545 
#endif
00546 
00547     
if (Attached == 
TRUE) {
00548         
KeDetachProcess();
00549     }
00550     
ObDereferenceObject (TargetProcess);
00551 
00552     
00553     
00554     
00555 
00556     
00557     
00558     
00559     
00560 
00561     
try {
00562 
00563 
#if defined(_MIALT4K_)
00564 
00565         
if (IsWow64Process) { 
00566 
00567             *RegionSize = ((PCHAR)EndingAddress -
00568                         (PCHAR)
PAGE_4K_ALIGN(CapturedBase)) + 
PAGE_4K;
00569 
00570             *BaseAddress = 
PAGE_4K_ALIGN(CapturedBase);
00571 
00572 
00573         } 
else {    
00574 
00575 
#endif
00576 
        *RegionSize = ((PCHAR)EndingAddress - (PCHAR)
PAGE_ALIGN(CapturedBase)) +
00577                                                                     
PAGE_SIZE;
00578         *BaseAddress = 
PAGE_ALIGN(CapturedBase);
00579 
00580 
#if defined(_MIALT4K_)
00581 
        }
00582 
#endif
00583 
00584     } except (EXCEPTION_EXECUTE_HANDLER) {
00585         
return GetExceptionCode();
00586     }
00587 
00588     
if (WasLocked) {
00589         
return STATUS_WAS_LOCKED;
00590     }
00591 
00592     
return STATUS_SUCCESS;
00593 
00594 ErrorReturn:
00595         
UNLOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
00596 ErrorReturn1:
00597         
if (Attached == 
TRUE) {
00598             
KeDetachProcess();
00599         }
00600         
ObDereferenceObject (TargetProcess);
00601         
return Status;
00602 }