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 }