00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "mi.h"
00023
00024 extern ULONG
MMVADKEY;
00025
00026
#ifdef VLM_SUPPORT
00027
00028
#define ROUND_TO_PAGES64(Size) ((ULONGLONG)(Size) + (PAGE_SIZE - 1) & ~((LONGLONG)PAGE_SIZE - 1))
00029
00030
#define MM_VALID_PTE_SIZE (256)
00031
00032
#define MM_LARGEST_VLM_RANGE \
00033
((ULONGLONG)MM_HIGHEST_USER_ADDRESS64 - (ULONGLONG)MM_LOWEST_USER_ADDRESS64)
00034
00035
#define DELETE_TYPE_PRIVATE 0
00036
#define DELETE_TYPE_SHARED 1
00037
00038
MMPTE
00039
MiCaptureSystemPte (
00040 IN
PMMPTE PointerProtoPte,
00041 IN
PEPROCESS Process
00042 );
00043
00044 LOGICAL
00045 MiCommitPages64 (
00046 IN
PMMPTE StartPte,
00047 IN
PMMPTE LastPte,
00048 IN ULONG ProtectionMask,
00049 IN
PEPROCESS Process,
00050 OUT PSIZE_T ValidPtes
00051 );
00052
00053 ULONG
00054 MiDecommitOrDeletePages64 (
00055 IN
PMMPTE StartingPte,
00056 IN
PMMPTE EndingPte,
00057 IN
PEPROCESS Process,
00058 IN ULONG Type,
00059 IN LOGICAL FlushTb
00060 );
00061
00062
VOID
00063 MiFlushPteList64 (
00064 IN PMMPTE_FLUSH_LIST64 PteFlushList,
00065 IN ULONG AllProcessors,
00066 IN
MMPTE FillPte
00067 );
00068
00069
VOID
00070 MiReturnAvailablePages (
00071 IN PFN_NUMBER Amount
00072 );
00073
00074 LOGICAL
00075 MiCheckPdeForDeletion (
00076 IN
PMMPTE PointerPde,
00077 IN LOGICAL FlushTb
00078 );
00079
00080
VOID
00081 MiProcessValidPteList64 (
00082 IN
PMMPTE *ValidPteList,
00083 IN ULONG Count,
00084 IN LOGICAL FlushTb
00085 );
00086
00087 ULONG
00088 MiDoesPdeExist64 (
00089 IN
PMMPTE PointerPde
00090 );
00091
00092 LOGICAL
00093 MiMakePdeExistAndMakeValid64 (
00094 IN
PMMPTE PointerPde,
00095 IN
PEPROCESS TargetProcess,
00096 IN LOGICAL PfnLockHeld,
00097 IN LOGICAL MakePageTablePage
00098 );
00099
00100 HARDWARE_PTE
00101
MiFlushTbAndCapture(
00102 IN
PMMPTE PtePointer,
00103 IN HARDWARE_PTE TempPte,
00104 IN
PMMPFN Pfn1
00105 );
00106
00107
NTSTATUS
00108 MiMapViewOfVlmDataSection (
00109 IN
PCONTROL_AREA ControlArea,
00110 IN
PEPROCESS Process,
00111 IN PVOID64 *CapturedBase,
00112 IN PULONGLONG SectionOffset,
00113 IN PULONGLONG CapturedViewSize,
00114 IN PSECTION Section,
00115 IN ULONG ProtectionMask,
00116 IN ULONG AllocationType,
00117 IN PULONG ReleasedWsMutex
00118 );
00119
00120 ULONG
00121 MiIsEntireRangeCommitted64 (
00122 IN PVOID64 StartingAddress,
00123 IN PVOID64 EndingAddress,
00124 IN
PMMVAD Vad,
00125 IN
PEPROCESS Process
00126 );
00127
00128
VOID
00129 MiMakeValidPageNoAccess64 (
00130 IN
PMMPTE PointePte
00131 );
00132
00133
VOID
00134 MiMakeNoAccessPageValid64 (
00135 IN
PMMPTE PointerPte,
00136 IN ULONG Protect
00137 );
00138
00139 ULONG
00140
MiSetProtectionOnTransitionPte (
00141 IN
PMMPTE PointerPte,
00142 IN ULONG ProtectionMask
00143 );
00144
00145 ULONG
00146 MiQueryAddressState64 (
00147 IN PVOID64 Va,
00148 IN
PMMVAD Vad,
00149 IN
PEPROCESS TargetProcess,
00150 OUT PULONG ReturnedProtect
00151 );
00152
00153
#define MI_NONPAGABLE_MEMORY_AVAILABLE(_SizeInPages) \
00154
(MmResidentAvailablePages > ((SPFN_NUMBER)_SizeInPages + (SPFN_NUMBER)MmTotalFreeSystemPtes[NonPagedPoolExpansion] + ((SPFN_NUMBER)MiSpecialPagesNonPagedMaximum - (SPFN_NUMBER)MiSpecialPagesNonPaged) + (SPFN_NUMBER)MM_VLM_FLUID_PAGES))
00155
00156
#define MI_GET_USED_PDE64_HANDLE(PDE64) \
00157
(&(((PMI_PROCESS_VLM_INFO) (((PMMPTE)PDE_BASE64)->u.Long))->UsedPageTableEntries[PDE64 - MiGetPdeAddress64 (MM_LOWEST_USER_ADDRESS64)]))
00158
00159 ULONG MmSharedCommitVlm;
00160
00161 KSPIN_LOCK MiVlmStatisticsLock;
00162
00163 ULONG MiVlmCommitChargeInPages;
00164 ULONG MiVlmCommitChargeInPagesPeak;
00165
00166
00167
NTSTATUS
00168
NtAllocateVirtualMemory64 (
00169 IN HANDLE ProcessHandle,
00170 IN OUT PVOID64 *BaseAddress,
00171 IN ULONG ZeroBits,
00172 IN OUT PULONGLONG RegionSize,
00173 IN ULONG AllocationType,
00174 IN ULONG Protect
00175 )
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 {
00259
PMMVAD Vad;
00260
PMMVAD FoundVad;
00261
PEPROCESS Process;
00262
KPROCESSOR_MODE PreviousMode;
00263 PVOID64 StartingAddress;
00264 PVOID64 EndingAddress;
00265
NTSTATUS Status;
00266 PVOID64 CapturedBase;
00267 ULONGLONG CapturedRegionSize;
00268
PMMPTE CommitLimitPte;
00269 ULONG ProtectionMask;
00270
PMMPTE LastPte;
00271
PMMPTE PointerPde;
00272
PMMPTE StartingPte;
00273
PMMPTE PointerPte;
00274
MMPTE TempPte;
00275 ULONG OldProtect;
00276 SSIZE_T QuotaCharge;
00277 SIZE_T QuotaFree;
00278 ULONG CopyOnWriteCharge;
00279 BOOLEAN PageFileChargeSucceeded;
00280 LOGICAL Attached;
00281 KIRQL OldIrql;
00282 ULONG_PTR NewPages;
00283 LOGICAL ChargedExactQuota;
00284 LOGICAL CommitSucceeded;
00285 LOGICAL LargeVad;
00286 LOGICAL GotResidentAvail;
00287 PMI_PROCESS_VLM_INFO VlmInfo;
00288 ULONG CommitCharge;
00289
00290 Attached =
FALSE;
00291
00292
if (MI_VLM_ENABLED() ==
FALSE) {
00293
return STATUS_NOT_IMPLEMENTED;
00294 }
00295
00296
00297
00298
00299
00300
if ((AllocationType & ~(MEM_COMMIT | MEM_RESERVE |
00301 MEM_RESET)) != 0) {
00302
return STATUS_INVALID_PARAMETER_5;
00303 }
00304
00305
00306
00307
00308
00309
if ((AllocationType & (MEM_COMMIT | MEM_RESERVE | MEM_RESET)) == 0) {
00310
return STATUS_INVALID_PARAMETER_5;
00311 }
00312
00313
if ((AllocationType & MEM_RESET) && (AllocationType != MEM_RESET)) {
00314
00315
00316
00317
00318
00319
return STATUS_INVALID_PARAMETER_5;
00320 }
00321
00322
00323
00324
00325
00326
try {
00327 ProtectionMask =
MiMakeProtectionMask (Protect);
00328 } except (EXCEPTION_EXECUTE_HANDLER) {
00329
return GetExceptionCode();
00330 }
00331
00332
if ((ProtectionMask ==
MM_NOACCESS) &&
00333 (AllocationType & MEM_COMMIT)) {
00334
00335
return STATUS_INVALID_PAGE_PROTECTION;
00336 }
00337
00338 PreviousMode = KeGetPreviousMode();
00339
00340
00341
00342
00343
00344
00345
try {
00346
00347
if (PreviousMode !=
KernelMode) {
00348
00349
ProbeForWrite (BaseAddress,
sizeof(PVOID64),
sizeof(PVOID64));
00350
ProbeForWrite (RegionSize,
sizeof(ULONGLONG),
sizeof(ULONGLONG));
00351 }
00352
00353
00354
00355
00356
00357 CapturedBase = *BaseAddress;
00358
00359
00360
00361
00362
00363 CapturedRegionSize = *RegionSize;
00364
00365 } except (
ExSystemExceptionFilter()) {
00366
00367
00368
00369
00370
00371
00372
00373
return GetExceptionCode();
00374 }
00375
00376
#if 0
00377
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
00378
if ( MmWatchProcess ) {
00379 ;
00380 }
else {
00381
DbgPrint(
"allocvm process handle %lx base address %p zero bits %lx\n",
00382 ProcessHandle, CapturedBase, ZeroBits);
00383
DbgPrint(
" region size %p alloc type %lx protect %lx\n",
00384 CapturedRegionSize, AllocationType, Protect);
00385 }
00386 }
00387
#endif
00388
00389
00390
00391
00392
00393
00394
if ((CapturedBase !=
NULL ) &&
00395 ((CapturedBase > (PVOID64)MM_HIGHEST_USER_ADDRESS64) ||
00396 (CapturedBase < (PVOID64)MM_LOWEST_USER_ADDRESS64))) {
00397
00398
00399
00400
00401
00402
return STATUS_INVALID_PARAMETER_2;
00403 }
00404
00405
if (CapturedBase !=
NULL) {
00406
00407
if ((ULONGLONG)CapturedBase + CapturedRegionSize < (ULONGLONG)CapturedBase) {
00408
00409
00410
00411
00412
00413
return STATUS_INVALID_PARAMETER_4;
00414 }
00415
00416
00417
if ((ULONGLONG)CapturedBase + CapturedRegionSize > (ULONGLONG)MM_HIGHEST_USER_ADDRESS64 -
X64K) {
00418
00419
00420
00421
00422
00423
return STATUS_INVALID_PARAMETER_4;
00424 }
00425 }
00426
else if (CapturedRegionSize > (ULONGLONG)MM_LARGEST_VLM_RANGE -
X64K) {
00427
00428
00429
00430
00431
00432
return STATUS_INVALID_PARAMETER_4;
00433 }
00434
00435
if (CapturedRegionSize == 0) {
00436
00437
00438
00439
00440
00441
return STATUS_INVALID_PARAMETER_4;
00442 }
00443
00444
00445
00446
00447
00448
if ( ProcessHandle == NtCurrentProcess() ) {
00449 Process =
PsGetCurrentProcess();
00450 }
else {
00451
Status =
ObReferenceObjectByHandle ( ProcessHandle,
00452 PROCESS_VM_OPERATION,
00453 PsProcessType,
00454 PreviousMode,
00455 (PVOID *)&Process,
00456 NULL );
00457
00458
if (!
NT_SUCCESS(Status)) {
00459
return Status;
00460 }
00461 }
00462
00463
00464
00465
00466
00467
00468
if (
PsGetCurrentProcess() != Process) {
00469
KeAttachProcess (&Process->
Pcb);
00470 Attached =
TRUE;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
LOCK_WS_AND_ADDRESS_SPACE (Process);
00482
00483
00484
00485
00486
00487
if (Process->
AddressSpaceDeleted != 0) {
00488
Status = STATUS_PROCESS_IS_TERMINATING;
00489
goto ErrorReturn;
00490 }
00491
00492
00493
00494
00495
00496
if ((Process->
CloneRoot !=
NULL) &&
00497 (Process->
ForkWasSuccessful != MM_NO_FORK_ALLOWED)) {
00498
Status = STATUS_INVALID_VLM_OPERATION;
00499
goto ErrorReturn;
00500 }
00501 Process->
ForkWasSuccessful = MM_NO_FORK_ALLOWED;
00502
00503
if ((CapturedBase ==
NULL) || (AllocationType & MEM_RESERVE)) {
00504
00505
00506
00507
00508
00509
if ((Protect & PAGE_WRITECOPY) ||
00510 (Protect & PAGE_EXECUTE_WRITECOPY)) {
00511
Status = STATUS_INVALID_PAGE_PROTECTION;
00512
goto ErrorReturn;
00513 }
00514
00515
00516
00517
00518
00519
if (CapturedBase ==
NULL) {
00520
00521
00522
00523
00524
00525
00526 CapturedRegionSize =
ROUND_TO_PAGES64 (CapturedRegionSize);
00527
00528
00529
00530
00531
00532
00533
try {
00534
00535
00536 StartingAddress = MiFindEmptyAddressRangeInTree64 (
00537 CapturedRegionSize,
00538 X64K,
00539 (
PMMADDRESS_NODE)(Process->
CloneRoot));
00540
00541 } except (EXCEPTION_EXECUTE_HANDLER) {
00542
Status = GetExceptionCode();
00543
goto ErrorReturn;
00544 }
00545
00546
00547
00548
00549
00550 EndingAddress = (PVOID64)(((ULONGLONG)StartingAddress +
00551 CapturedRegionSize - 1
L) | (
PAGE_SIZE - 1
L));
00552
00553 }
else {
00554
00555
00556
00557
00558
00559
00560
00561 EndingAddress = (PVOID64)(((ULONGLONG)CapturedBase +
00562 CapturedRegionSize - 1
L) | (
PAGE_SIZE - 1
L));
00563
00564
00565
00566
00567
00568 StartingAddress = MI_64K_ALIGN64(CapturedBase);
00569
00570
00571
00572
00573
00574
if (MiCheckForConflictingVad64 (StartingAddress, EndingAddress) !=
00575 (
PMMVAD)
NULL) {
00576
00577
Status = STATUS_CONFLICTING_ADDRESSES;
00578
goto ErrorReturn;
00579 }
00580 }
00581
00582
if (AllocationType & MEM_COMMIT) {
00583 StartingPte =
MiGetPteAddress64 (StartingAddress);
00584
ASSERT (
MiGetPdeAddress64(StartingAddress) == MiGetPteAddress (StartingPte));
00585 LastPte =
MiGetPteAddress64 (EndingAddress);
00586 QuotaCharge = 1 + LastPte - StartingPte;
00587 }
00588
else {
00589 QuotaCharge = 0;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
try {
00604
00605
if ((AllocationType & MEM_COMMIT) && (QuotaCharge + QuotaCharge /
PTE_PER_PAGE + 2 >=
MM_MAX_COMMIT)) {
00606 LargeVad =
TRUE;
00607 Vad = (
PMMVAD)
ExAllocatePoolWithTag (NonPagedPool,
00608
sizeof(
MMVAD),
00609 MMVADKEY);
00610 }
00611
else {
00612 LargeVad =
FALSE;
00613 Vad = (
PMMVAD)
ExAllocatePoolWithTag (NonPagedPool,
00614
sizeof(
MMVAD_SHORT),
00615 'SdaV');
00616 }
00617
00618
00619
00620
00621
00622
00623
if (Vad == (
PMMVAD)0) {
00624
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
00625 }
00626
00627 Vad->
StartingVpn = MI_VA_TO_VPN64 (StartingAddress);
00628 Vad->
EndingVpn = MI_VA_TO_VPN64 (EndingAddress);
00629
00630 Vad->
u.LongFlags = 0;
00631
if (AllocationType & MEM_COMMIT) {
00632 Vad->
u.VadFlags.MemCommit = 1;
00633
00634
if (LargeVad ==
TRUE) {
00635 Vad->
u.VadFlags.ImageMap = 1;
00636 Vad->
u.VadFlags.CommitCharge = 0;
00637 Vad->
u3.List.Flink = (PLIST_ENTRY)QuotaCharge;
00638 }
00639
else {
00640 Vad->
u.VadFlags.CommitCharge = QuotaCharge;
00641 }
00642 }
00643
00644 Vad->
u.VadFlags.Protection = ProtectionMask;
00645 Vad->
u.VadFlags.PrivateMemory = 1;
00646
00647 MiInsertVad64 ((PVOID)Vad);
00648
00649 } except (EXCEPTION_EXECUTE_HANDLER) {
00650
00651
if (Vad != (
PMMVAD)
NULL) {
00652
00653
00654
00655
00656
00657
00658
00659
ExFreePool (Vad);
00660
Status = GetExceptionCode();
00661 }
else {
00662
Status = STATUS_INSUFFICIENT_RESOURCES;
00663 }
00664
00665
goto ErrorReturn;
00666 }
00667
00668
if (AllocationType & MEM_COMMIT) {
00669
00670
00671
00672
00673
00674
00675
00676 QuotaFree = 1;
00677
Status = STATUS_SUCCESS;
00678
00679
LOCK_PFN (OldIrql);
00680
00681
if (
MI_NONPAGABLE_MEMORY_AVAILABLE (QuotaCharge)) {
00682
MmResidentAvailablePages -= (PFN_NUMBER)QuotaCharge;
00683
MM_BUMP_COUNTER(22, QuotaCharge);
00684 QuotaFree = 0;
00685 }
00686
UNLOCK_PFN (OldIrql);
00687
if (QuotaFree == 1) {
00688 MiRemoveVad64 ((
PMMVAD)Vad);
00689
ExFreePool (Vad);
00690
Status = STATUS_COMMITMENT_LIMIT;
00691
goto ErrorReturn;
00692 }
00693
00694 CommitSucceeded = MiCommitPages64 (StartingPte,
00695 LastPte,
00696 ProtectionMask,
00697 Process,
00698 &QuotaFree);
00699
00700
if (CommitSucceeded ==
FALSE) {
00701
00702
00703
00704
00705
00706
LOCK_PFN (OldIrql);
00707
MmResidentAvailablePages += (PFN_NUMBER) QuotaCharge;
00708
MM_BUMP_COUNTER(22, -QuotaCharge);
00709
UNLOCK_PFN (OldIrql);
00710 MiRemoveVad64 ((
PMMVAD)Vad);
00711
ExFreePool (Vad);
00712
Status = STATUS_INSUFFICIENT_RESOURCES;
00713
goto ErrorReturn;
00714 }
00715
00716
if (QuotaFree != 0) {
00717
LOCK_PFN (OldIrql);
00718
MmResidentAvailablePages += (PFN_NUMBER) QuotaFree;
00719
MM_BUMP_COUNTER(23, QuotaFree);
00720
UNLOCK_PFN (OldIrql);
00721 }
00722
00723 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
00724 VlmInfo->CommitCharge += (QuotaCharge - QuotaFree);
00725
if (VlmInfo->CommitCharge > VlmInfo->CommitChargePeak) {
00726 VlmInfo->CommitChargePeak = VlmInfo->CommitCharge;
00727 }
00728 }
00729
else {
00730
00731
00732
00733
00734
00735
00736
00737
00738 CommitSucceeded = MiMakePdeExistAndMakeValid64 (
00739 MiGetPdeAddress64 (StartingAddress),
00740 Process,
00741 FALSE,
00742 FALSE);
00743
00744
if (CommitSucceeded ==
FALSE) {
00745 MiRemoveVad64 ((
PMMVAD)Vad);
00746
ExFreePool (Vad);
00747
Status = STATUS_INSUFFICIENT_RESOURCES;
00748
goto ErrorReturn;
00749 }
00750 QuotaCharge = 0;
00751 }
00752
00753
00754
00755
00756
00757
UNLOCK_WS (Process);
00758
00759
00760
00761
00762
00763
00764 CapturedRegionSize = (ULONGLONG)EndingAddress - (ULONGLONG)StartingAddress + 1;
00765
00766 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
00767 VlmInfo->VirtualSize += CapturedRegionSize;
00768
if (VlmInfo->VirtualSize > VlmInfo->VirtualSizePeak) {
00769 VlmInfo->VirtualSizePeak = VlmInfo->VirtualSize;
00770 }
00771
00772 ExAcquireFastLock (&MiVlmStatisticsLock, &OldIrql);
00773
00774
if (AllocationType & MEM_COMMIT) {
00775 MiVlmCommitChargeInPages += (QuotaCharge - QuotaFree);
00776
if (MiVlmCommitChargeInPages > MiVlmCommitChargeInPagesPeak) {
00777 MiVlmCommitChargeInPagesPeak = MiVlmCommitChargeInPages;
00778 }
00779 }
00780
00781 ExReleaseFastLock (&MiVlmStatisticsLock, OldIrql);
00782
00783
00784
00785
00786
00787
00788
UNLOCK_ADDRESS_SPACE(Process);
00789
if (Attached) {
00790
KeDetachProcess();
00791 }
00792
00793
if ( ProcessHandle != NtCurrentProcess() ) {
00794
ObDereferenceObject (Process);
00795 }
00796
00797
00798
00799
00800
00801
try {
00802
00803 *RegionSize = CapturedRegionSize;
00804 *BaseAddress = StartingAddress;
00805
00806 } except (EXCEPTION_EXECUTE_HANDLER) {
00807
00808
00809
00810
00811
00812
00813 NOTHING;
00814 }
00815
00816
#if 0
00817
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
00818
if ( MmWatchProcess ) {
00819
if ( MmWatchProcess ==
PsGetCurrentProcess() ) {
00820
DbgPrint(
"\n+++ ALLOC Type %lx Base %p Size %p\n",
00821 AllocationType,StartingAddress, CapturedRegionSize);
00822 MmFooBar();
00823 }
00824 }
else {
00825
DbgPrint(
"return allocvm status %lx baseaddr %p size %p\n",
00826 Status, StartingAddress, CapturedRegionSize);
00827 }
00828 }
00829
#endif
00830
00831
return STATUS_SUCCESS;
00832
00833 }
else {
00834
00835
00836
00837
00838
00839
00840
if (AllocationType == MEM_RESET) {
00841
00842
00843
00844
00845
00846
00847
Status = STATUS_SUCCESS;
00848
goto ErrorReturn;
00849
00850 }
else {
00851 EndingAddress = (PVOID64)(((ULONGLONG)CapturedBase +
00852 CapturedRegionSize - 1) | (
PAGE_SIZE - 1));
00853 StartingAddress = (PVOID64)PAGE_ALIGN64(CapturedBase);
00854 }
00855
00856 CapturedRegionSize = (ULONGLONG)EndingAddress - (ULONGLONG)StartingAddress + 1;
00857
00858 FoundVad = MiCheckForConflictingVad64 (StartingAddress, EndingAddress);
00859
00860
if (FoundVad == (
PMMVAD)
NULL) {
00861
00862
00863
00864
00865
00866
00867
Status = STATUS_CONFLICTING_ADDRESSES;
00868
goto ErrorReturn;
00869 }
00870
00871
00872
00873
00874
00875
00876
if ((MI_VA_TO_VPN64 (StartingAddress) < FoundVad->
StartingVpn) ||
00877 (MI_VA_TO_VPN64 (EndingAddress) > FoundVad->
EndingVpn)) {
00878
00879
00880
00881
00882
00883
00884
Status = STATUS_CONFLICTING_ADDRESSES;
00885
goto ErrorReturn;
00886 }
00887
00888
00889
if (FoundVad->
u.VadFlags.PrivateMemory == 1) {
00890
00891
00892
00893
00894
00895
if ((Protect & PAGE_WRITECOPY) ||
00896 (Protect & PAGE_EXECUTE_WRITECOPY)) {
00897
Status = STATUS_INVALID_PAGE_PROTECTION;
00898
goto ErrorReturn;
00899 }
00900
00901
00902
00903
00904
00905
#if 0
00906
if (AllocationType &
MEM_CHECK_COMMIT_STATE) {
00907
if ( !
MiIsEntireRangeDecommitted(StartingAddress,
00908 EndingAddress,
00909 FoundVad,
00910 Process)) {
00911
00912
00913
00914
00915
00916
00917
Status = STATUS_ALREADY_COMMITTED;
00918
goto ErrorReturn;
00919 }
00920 }
00921
#endif //0
00922
00923
00924
00925
00926
00927
00928
00929 StartingPte =
MiGetPteAddress64 (StartingAddress);
00930
ASSERT (
MiGetPdeAddress64(StartingAddress) == MiGetPteAddress (StartingPte));
00931 LastPte =
MiGetPteAddress64 (EndingAddress);
00932
00933
00934
00935
00936
00937 QuotaCharge = 1 + LastPte - StartingPte;
00938
00939
00940
00941
00942
00943
00944 QuotaFree = 1;
00945
Status = STATUS_SUCCESS;
00946
00947
LOCK_PFN (OldIrql);
00948
if (
MI_NONPAGABLE_MEMORY_AVAILABLE (QuotaCharge)) {
00949
MmResidentAvailablePages -= (PFN_NUMBER) QuotaCharge;
00950
MM_BUMP_COUNTER(24, QuotaCharge);
00951 QuotaFree = 0;
00952 }
00953
UNLOCK_PFN (OldIrql);
00954
if (QuotaFree == 1) {
00955
Status = STATUS_COMMITMENT_LIMIT;
00956
goto ErrorReturn;
00957 }
00958
00959
if (Process->
CommitChargeLimit) {
00960
if (Process->
CommitCharge + QuotaCharge > Process->
CommitChargeLimit) {
00961
Status = STATUS_COMMITMENT_LIMIT;
00962
LOCK_PFN (OldIrql);
00963
MmResidentAvailablePages += (PFN_NUMBER) QuotaCharge;
00964
MM_BUMP_COUNTER(24, -QuotaCharge);
00965
UNLOCK_PFN (OldIrql);
00966
if (Process->
Job) {
00967
PsReportProcessMemoryLimitViolation ();
00968 }
00969
goto ErrorReturn;
00970 }
00971 }
00972
if (Process->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
00973
if (
PsChangeJobMemoryUsage(QuotaCharge) ==
FALSE) {
00974
Status = STATUS_COMMITMENT_LIMIT;
00975
LOCK_PFN (OldIrql);
00976
MmResidentAvailablePages += (PFN_NUMBER) QuotaCharge;
00977
MM_BUMP_COUNTER(24, -QuotaCharge);
00978
UNLOCK_PFN (OldIrql);
00979
goto ErrorReturn;
00980 }
00981 }
00982
00983
try {
00984
MiChargeCommitment (QuotaCharge, Process);
00985 } except (EXCEPTION_EXECUTE_HANDLER) {
00986
00987
Status = GetExceptionCode();
00988
LOCK_PFN (OldIrql);
00989
MmResidentAvailablePages += (PFN_NUMBER) QuotaCharge;
00990
MM_BUMP_COUNTER(24, -QuotaCharge);
00991
UNLOCK_PFN (OldIrql);
00992
if (Process->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
00993
00994
00995
00996
00997
00998
00999
01000 Process->
CommitCharge += QuotaCharge;
01001
PsChangeJobMemoryUsage (-(SSIZE_T)QuotaCharge);
01002 Process->
CommitCharge -= QuotaCharge;
01003 }
01004
goto ErrorReturn;
01005 }
01006
01007
MM_TRACK_COMMIT (MM_DBG_COMMIT_ALLOCVM1_VLM, QuotaCharge);
01008
01009 CommitSucceeded = MiCommitPages64 (StartingPte,
01010 LastPte,
01011 ProtectionMask,
01012 Process,
01013 &QuotaFree);
01014
01015
if (CommitSucceeded ==
FALSE) {
01016
Status = STATUS_INSUFFICIENT_RESOURCES;
01017
LOCK_PFN (OldIrql);
01018
MmResidentAvailablePages += (PFN_NUMBER) QuotaCharge;
01019
MM_BUMP_COUNTER(24, -QuotaCharge);
01020
UNLOCK_PFN (OldIrql);
01021
MiReturnCommitment (QuotaCharge);
01022
if (Process->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
01023
01024
01025
01026
01027
01028
01029
01030 Process->
CommitCharge += QuotaCharge;
01031
PsChangeJobMemoryUsage (-(SSIZE_T)QuotaCharge);
01032 Process->
CommitCharge -= QuotaCharge;
01033 }
01034
goto ErrorReturn;
01035 }
01036
01037 NewPages = QuotaCharge - QuotaFree;
01038
01039
01040
01041
01042
01043
if (FoundVad->
u.VadFlags.ImageMap == 1) {
01044
ASSERT (FoundVad->
u.VadFlags.CommitCharge == 0);
01045 CommitCharge = (ULONG)FoundVad->
u3.List.Flink;
01046 }
01047
else {
01048 CommitCharge = FoundVad->
u.VadFlags.CommitCharge;
01049 }
01050
01051
ASSERT (CommitCharge + NewPages >= CommitCharge);
01052 CommitCharge += NewPages;
01053
01054
if (QuotaFree) {
01055
MiReturnCommitment (QuotaFree);
01056
MM_TRACK_COMMIT (MM_DBG_COMMIT_ALLOCVM1_VLM, -QuotaFree);
01057
if (Process->
JobStatus &
PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
01058
01059
01060
01061
01062
01063
01064
01065 Process->
CommitCharge += QuotaFree;
01066
PsChangeJobMemoryUsage (-(SSIZE_T)QuotaFree);
01067 Process->
CommitCharge -= QuotaFree;
01068 }
01069 }
01070
01071
if (FoundVad->
u.VadFlags.ImageMap == 1) {
01072
ASSERT (FoundVad->
u.VadFlags.CommitCharge == 0);
01073 FoundVad->
u3.List.Flink = (PLIST_ENTRY)CommitCharge;
01074 }
01075
else {
01076 FoundVad->
u.VadFlags.CommitCharge = CommitCharge;
01077 }
01078
01079 Process->
CommitCharge += NewPages;
01080
if (Process->
CommitCharge > Process->
CommitChargePeak) {
01081 Process->
CommitChargePeak = Process->
CommitCharge;
01082 }
01083
01084 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
01085 VlmInfo->CommitCharge += NewPages;
01086
if (VlmInfo->CommitCharge > VlmInfo->CommitChargePeak) {
01087 VlmInfo->CommitChargePeak = VlmInfo->CommitCharge;
01088 }
01089
01090 ExAcquireFastLock (&MiVlmStatisticsLock, &OldIrql);
01091
01092 MiVlmCommitChargeInPages += NewPages;
01093
if (MiVlmCommitChargeInPages > MiVlmCommitChargeInPagesPeak) {
01094 MiVlmCommitChargeInPagesPeak = MiVlmCommitChargeInPages;
01095 }
01096
01097 ExReleaseFastLock (&MiVlmStatisticsLock, OldIrql);
01098
01099 }
else {
01100
01101
01102
01103
01104
01105
if (Protect & PAGE_NOCACHE) {
01106
Status = STATUS_INVALID_PAGE_PROTECTION;
01107
goto ErrorReturn;
01108 }
01109
01110
ASSERT (FoundVad->
u.VadFlags.NoChange == 0);
01111
01112
ASSERT (FoundVad->
ControlArea->
FilePointer == NULL);
01113
01114 StartingPte =
MiGetProtoPteAddress (FoundVad,
01115 MI_VA_TO_VPN64 (StartingAddress));
01116 PointerPte = StartingPte;
01117 LastPte =
MiGetProtoPteAddress (FoundVad,
01118 MI_VA_TO_VPN64 (EndingAddress));
01119
01120
UNLOCK_WS (Process);
01121
01122 ExAcquireFastMutex (&MmSectionCommitMutex);
01123
01124 PointerPte = StartingPte;
01125
01126
01127
01128
01129
01130
01131
01132 QuotaCharge = 1 + LastPte - StartingPte;
01133
01134
01135
01136
01137
01138
01139 QuotaFree = 0;
01140
01141
Status = STATUS_INVALID_VLM_OPERATION;
01142 ChargedExactQuota =
FALSE;
01143
01144
for (; ; ) {
01145 GotResidentAvail =
FALSE;
01146
LOCK_PFN (OldIrql);
01147
if (
MI_NONPAGABLE_MEMORY_AVAILABLE (QuotaCharge)) {
01148
MmResidentAvailablePages -= (PFN_NUMBER) QuotaCharge;
01149
MM_BUMP_COUNTER(36, QuotaCharge);
01150
Status = STATUS_SUCCESS;
01151 GotResidentAvail =
TRUE;
01152 }
01153
UNLOCK_PFN (OldIrql);
01154
01155
if (
Status == STATUS_SUCCESS) {
01156
01157
try {
01158
MiChargeCommitment (QuotaCharge, NULL);
01159 } except (EXCEPTION_EXECUTE_HANDLER) {
01160
Status = GetExceptionCode();
01161 }
01162
if (
Status == STATUS_SUCCESS) {
01163
LOCK_PFN (OldIrql);
01164 MmSharedCommitVlm += QuotaCharge;
01165
UNLOCK_PFN (OldIrql);
01166
break;
01167 }
01168 }
01169
01170
01171
01172
01173
01174
01175
01176
if (GotResidentAvail ==
TRUE) {
01177
LOCK_PFN (OldIrql);
01178
MmResidentAvailablePages += (PFN_NUMBER) QuotaCharge;
01179
MM_BUMP_COUNTER(36, -QuotaCharge);
01180
UNLOCK_PFN (OldIrql);
01181 }
01182
01183
if (
Status != STATUS_INVALID_VLM_OPERATION) {
01184
01185
01186
01187
01188
01189
01190 ExReleaseFastMutex (&MmSectionCommitMutex);
01191
goto ErrorReturn1;
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
while (PointerPte <= LastPte) {
01201
01202
01203
01204
01205
01206
01207
01208
01209
if (PointerPte->
u.Long != 0) {
01210 QuotaFree += 1;
01211 }
01212 PointerPte += 1;
01213 }
01214
01215
if (QuotaFree) {
01216 PointerPte = StartingPte;
01217 QuotaCharge -= QuotaFree;
01218
Status = STATUS_COMMITMENT_LIMIT;
01219 ChargedExactQuota =
TRUE;
01220 }
01221
else {
01222 ExReleaseFastMutex (&MmSectionCommitMutex);
01223
goto ErrorReturn1;
01224 }
01225 }
01226
01227
01228
01229
01230
01231 QuotaFree = 0;
01232 TempPte = FoundVad->
ControlArea->
Segment->
SegmentPteTemplate;
01233
01234 FoundVad->
ControlArea->
Segment->
NumberOfCommittedPages +=
01235 QuotaCharge;
01236
01237
while (PointerPte <= LastPte) {
01238
01239
if (PointerPte->
u.Long != 0) {
01240
01241
01242
01243
01244
01245 QuotaFree += 1;
01246 }
else {
01247 *PointerPte = TempPte;
01248 }
01249 PointerPte += 1;
01250 }
01251
01252
if (ChargedExactQuota ==
TRUE) {
01253 QuotaFree = 0;
01254 }
01255
else {
01256
LOCK_PFN (OldIrql);
01257 MmSharedCommitVlm -= QuotaFree;
01258
UNLOCK_PFN (OldIrql);
01259 FoundVad->
ControlArea->
Segment->
NumberOfCommittedPages -=
01260 QuotaFree;
01261 }
01262
01263 ExReleaseFastMutex (&MmSectionCommitMutex);
01264
ASSERT ((LONG)QuotaFree >= 0);
01265
01266
01267
01268
01269
01270
LOCK_WS (Process);
01271
01272
#if 0 //fixfix charge and update protection.
01273
MiSetProtectionOnSection (Process,
01274 FoundVad,
01275 StartingAddress,
01276 EndingAddress,
01277 Protect,
01278 &OldProtect,
01279 TRUE);
01280
01281
#endif //0
01282
}
01283
01284
UNLOCK_WS (Process);
01285
01286
if (QuotaFree != 0) {
01287
LOCK_PFN (OldIrql);
01288
MmResidentAvailablePages += (PFN_NUMBER) QuotaFree;
01289
MM_BUMP_COUNTER(25, QuotaFree);
01290
UNLOCK_PFN (OldIrql);
01291 }
01292
01293
01294
01295
01296
01297
01298
01299
UNLOCK_ADDRESS_SPACE(Process);
01300
01301
if (Attached) {
01302
KeDetachProcess();
01303 }
01304
if ( ProcessHandle != NtCurrentProcess() ) {
01305
ObDereferenceObject (Process);
01306 }
01307
01308
01309
01310
01311
01312
01313
try {
01314
01315 *RegionSize = CapturedRegionSize;
01316 *BaseAddress = StartingAddress;
01317
01318 } except (EXCEPTION_EXECUTE_HANDLER) {
01319
return GetExceptionCode();
01320 }
01321
01322
#if 0
01323
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
01324
if ( MmWatchProcess ) {
01325
if ( MmWatchProcess ==
PsGetCurrentProcess() ) {
01326
DbgPrint(
"\n+++ ALLOC Type %lx Base %p Size %p\n",
01327 AllocationType,StartingAddress, CapturedRegionSize);
01328 MmFooBar();
01329 }
01330 }
else {
01331
DbgPrint(
"return allocvm status %lx baseaddr %p size %p\n",
01332 Status, CapturedRegionSize, StartingAddress);
01333 }
01334 }
01335
#endif
01336
01337
return STATUS_SUCCESS;
01338 }
01339
01340 ErrorReturn:
01341
UNLOCK_WS (Process);
01342
01343 ErrorReturn1:
01344
01345
UNLOCK_ADDRESS_SPACE (Process);
01346
if (Attached) {
01347
KeDetachProcess();
01348 }
01349
if (ProcessHandle != NtCurrentProcess()) {
01350
ObDereferenceObject (Process);
01351 }
01352
return Status;
01353 }
01354
01355
NTSTATUS
01356
NtFreeVirtualMemory64(
01357 IN HANDLE ProcessHandle,
01358 IN OUT PVOID64 *BaseAddress,
01359 IN OUT PULONGLONG RegionSize,
01360 IN ULONG FreeType
01361 )
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 {
01407
PMMVAD_SHORT Vad;
01408
PMMVAD_SHORT NewVad;
01409
PMMVAD PreviousVad;
01410
PMMVAD NextVad;
01411
PEPROCESS Process;
01412
KPROCESSOR_MODE PreviousMode;
01413 PVOID64 StartingAddress;
01414 PVOID64 EndingAddress;
01415
NTSTATUS Status;
01416 LOGICAL Attached;
01417 ULONGLONG CapturedRegionSize;
01418 PVOID64 CapturedBase;
01419
PMMPTE StartingPte;
01420
PMMPTE EndingPte;
01421 SIZE_T OldQuota;
01422 SIZE_T QuotaCharge;
01423 SIZE_T CommitReduction;
01424 ULONG OldEnd;
01425 KIRQL OldIrql;
01426 PMI_PROCESS_VLM_INFO VlmInfo;
01427
01428
PAGED_CODE();
01429
01430 Attached =
FALSE;
01431
01432
if (MI_VLM_ENABLED() ==
FALSE) {
01433
return STATUS_NOT_IMPLEMENTED;
01434 }
01435
01436
01437
01438
01439
01440
if ((FreeType & ~(MEM_DECOMMIT | MEM_RELEASE)) != 0) {
01441
return STATUS_INVALID_PARAMETER_4;
01442 }
01443
01444
01445
01446
01447
01448
if (((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == 0) ||
01449 ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) ==
01450 (MEM_DECOMMIT | MEM_RELEASE))) {
01451
return STATUS_INVALID_PARAMETER_4;
01452 }
01453
01454 PreviousMode = KeGetPreviousMode();
01455
01456
01457
01458
01459
01460
01461
try {
01462
01463
if (PreviousMode !=
KernelMode) {
01464
01465
ProbeForWrite (BaseAddress,
sizeof(PVOID64),
sizeof(PVOID64));
01466
ProbeForWrite (RegionSize,
sizeof(ULONGLONG),
sizeof(ULONGLONG));
01467 }
01468
01469
01470
01471
01472
01473 CapturedBase = *BaseAddress;
01474
01475
01476
01477
01478
01479 CapturedRegionSize = *RegionSize;
01480
01481 } except (
ExSystemExceptionFilter()) {
01482
01483
01484
01485
01486
01487
01488
01489
return GetExceptionCode();
01490 }
01491
01492
#if 0
01493
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
01494
if ( !MmWatchProcess ) {
01495
DbgPrint(
"freevm processhandle %lx base %p size %p type %lx\n",
01496 ProcessHandle, CapturedBase, CapturedRegionSize, FreeType);
01497 }
01498 }
01499
#endif
01500
01501
if ((CapturedRegionSize != 0) && (FreeType & MEM_RELEASE)) {
01502
return STATUS_FREE_VM_NOT_AT_BASE;
01503 }
01504
01505
01506
01507
01508
01509
01510
if (CapturedBase > (PVOID64)MM_HIGHEST_USER_ADDRESS64) {
01511
01512
01513
01514
01515
01516
return STATUS_INVALID_PARAMETER_2;
01517 }
01518
01519
if ((ULONGLONG)MM_HIGHEST_USER_ADDRESS64 - (ULONGLONG)CapturedBase <
01520 CapturedRegionSize) {
01521
01522
01523
01524
01525
01526
return STATUS_INVALID_PARAMETER_3;
01527
01528 }
01529
01530 EndingAddress = (PVOID64)(((ULONGLONG)CapturedBase + CapturedRegionSize - 1) |
01531 (
PAGE_SIZE - 1));
01532
01533 StartingAddress = (PVOID64)PAGE_ALIGN64(CapturedBase);
01534
01535
if ( ProcessHandle == NtCurrentProcess() ) {
01536 Process =
PsGetCurrentProcess();
01537 }
else {
01538
01539
01540
01541
01542
01543
Status =
ObReferenceObjectByHandle ( ProcessHandle,
01544 PROCESS_VM_OPERATION,
01545 PsProcessType,
01546 PreviousMode,
01547 (PVOID *)&Process,
01548 NULL );
01549
if (!
NT_SUCCESS(Status)) {
01550
return Status;
01551 }
01552 }
01553
01554
01555
01556
01557
01558
01559
if (
PsGetCurrentProcess() != Process) {
01560
KeAttachProcess (&Process->
Pcb);
01561 Attached =
TRUE;
01562 }
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
LOCK_WS_AND_ADDRESS_SPACE (Process);
01574
01575
01576
01577
01578
01579
if (Process->
AddressSpaceDeleted != 0) {
01580
Status = STATUS_PROCESS_IS_TERMINATING;
01581
goto ErrorReturn;
01582 }
01583
01584
if (Process->
ForkWasSuccessful != MM_NO_FORK_ALLOWED) {
01585
Status = STATUS_MEMORY_NOT_ALLOCATED;
01586
goto ErrorReturn;
01587 }
01588
01589 Vad = (
PMMVAD_SHORT)MiLocateAddress64 (MI_VA_TO_VPN64 (StartingAddress));
01590
01591
if (Vad ==
NULL) {
01592
01593
01594
01595
01596
01597
Status = STATUS_MEMORY_NOT_ALLOCATED;
01598
goto ErrorReturn;
01599 }
01600
01601
01602
01603
01604
01605
if (Vad->
EndingVpn < MI_VA_TO_VPN64 (EndingAddress)) {
01606
01607
01608
01609
01610
01611
01612
Status = STATUS_UNABLE_TO_FREE_VM;
01613
goto ErrorReturn;
01614 }
01615
01616
01617
01618
01619
01620
01621
if ((Vad->
u.VadFlags.PrivateMemory == 0) ||
01622 (Vad->
u.VadFlags.PhysicalMapping == 1)) {
01623
Status = STATUS_UNABLE_TO_DELETE_SECTION;
01624
goto ErrorReturn;
01625 }
01626
01627
ASSERT (Vad->
u.VadFlags.NoChange == 0);
01628
01629
if (FreeType & MEM_RELEASE) {
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
ASSERT (CapturedRegionSize == 0);
01643
01644
01645
01646
01647
01648
01649
if (MI_VA_TO_VPN64 (CapturedBase) != Vad->
StartingVpn) {
01650
Status = STATUS_FREE_VM_NOT_AT_BASE;
01651
goto ErrorReturn;
01652 }
01653
01654
01655
01656
01657
01658 StartingAddress = MI_VPN_TO_VA64 (Vad->
StartingVpn);
01659 StartingPte =
MiGetPteAddress64 (StartingAddress);
01660 EndingAddress = MI_VPN_TO_VA64 (Vad->
EndingVpn);
01661 EndingPte =
MiGetPteAddress64 (EndingAddress);
01662 CapturedRegionSize = ((EndingPte - StartingPte + 1) <<
PAGE_SHIFT);
01663 MiRemoveVad64 ((
PMMVAD)Vad);
01664
ExFreePool (Vad);
01665
01666
01667
01668
01669
01670 CommitReduction = MiDecommitOrDeletePages64 (StartingPte,
01671 EndingPte,
01672 Process,
01673 DELETE_TYPE_PRIVATE,
01674 TRUE);
01675
UNLOCK_WS (Process);
01676
01677
01678
01679
01680
01681 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
01682 VlmInfo->VirtualSize -= CapturedRegionSize;
01683 VlmInfo->CommitCharge -= CommitReduction;
01684
01685 ExAcquireFastLock (&MiVlmStatisticsLock, &OldIrql);
01686 MiVlmCommitChargeInPages -= CommitReduction;
01687 ExReleaseFastLock (&MiVlmStatisticsLock, OldIrql);
01688
01689
UNLOCK_ADDRESS_SPACE (Process);
01690
01691
if (Attached) {
01692
KeDetachProcess();
01693 }
01694
01695
if ( ProcessHandle != NtCurrentProcess() ) {
01696
ObDereferenceObject (Process);
01697 }
01698
01699
01700
01701
01702
01703
try {
01704
01705 *RegionSize = CapturedRegionSize;
01706 *BaseAddress = StartingAddress;
01707
01708 } except (EXCEPTION_EXECUTE_HANDLER) {
01709
01710
01711
01712
01713
01714 }
01715
01716
#if 0
01717
if (MmDebug &
MM_DBG_SHOW_NT_CALLS) {
01718
if ( MmWatchProcess ) {
01719
if ( MmWatchProcess ==
PsGetCurrentProcess() ) {
01720
DbgPrint(
"\n--- FREE Type 0x%lx Base %p Size %p\n",
01721 FreeType, StartingAddress, CapturedRegionSize);
01722 MmFooBar();
01723 }
01724 }
01725 }
01726
#endif
01727
01728
return STATUS_SUCCESS;
01729 }
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
if (CapturedRegionSize == 0) {
01744
01745
if (MI_VA_TO_VPN64 (CapturedBase) != Vad->
StartingVpn) {
01746
Status = STATUS_FREE_VM_NOT_AT_BASE;
01747
goto ErrorReturn;
01748 }
01749 EndingAddress = MI_VPN_TO_VA_ENDING64 (Vad->
EndingVpn);
01750 }
01751
01752
01753
01754
01755
01756 StartingPte =
MiGetPteAddress64 (StartingAddress);
01757 EndingPte =
MiGetPteAddress64 (EndingAddress);
01758
01759 CapturedRegionSize = 1 + (ULONGLONG)EndingAddress - (ULONGLONG)StartingAddress;
01760
01761 CommitReduction = MiDecommitOrDeletePages64 (StartingPte,
01762 EndingPte,
01763 Process,
01764 DELETE_TYPE_PRIVATE,
01765 TRUE);
01766
01767 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
01768 VlmInfo->CommitCharge -= CommitReduction;
01769
01770 ExAcquireFastLock (&MiVlmStatisticsLock, &OldIrql);
01771 MiVlmCommitChargeInPages -= CommitReduction;
01772 ExReleaseFastLock (&MiVlmStatisticsLock, OldIrql);
01773
01774
UNLOCK_WS (Process);
01775
UNLOCK_ADDRESS_SPACE (Process);
01776
01777
if (Attached) {
01778
KeDetachProcess();
01779 }
01780
if (ProcessHandle != NtCurrentProcess()) {
01781
ObDereferenceObject (Process);
01782 }
01783
01784
01785
01786
01787
01788
01789
try {
01790
01791 *RegionSize = CapturedRegionSize;
01792 *BaseAddress = StartingAddress;
01793
01794 } except (EXCEPTION_EXECUTE_HANDLER) {
01795 NOTHING;
01796 }
01797
01798
return STATUS_SUCCESS;
01799
01800 ErrorReturn:
01801
01802
UNLOCK_WS (Process);
01803
UNLOCK_ADDRESS_SPACE (Process);
01804
01805
if (Attached) {
01806
KeDetachProcess();
01807 }
01808
01809
if (ProcessHandle != NtCurrentProcess()) {
01810
ObDereferenceObject (Process);
01811 }
01812
01813
return Status;
01814 }
01815
01816
01817 PVOID64
01818 MiFindEmptyAddressRangeInTree64 (
01819 IN ULONGLONG SizeOfRange64,
01820 IN ULONG_PTR Alignment,
01821 IN
PMMADDRESS_NODE Root
01822 )
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 {
01849
PMMADDRESS_NODE Node;
01850
PMMADDRESS_NODE NextNode;
01851 ULONG_PTR AlignmentVpn;
01852 ULONG SizeOfRange;
01853 PVOID64
Start;
01854
01855 AlignmentVpn = Alignment >>
PAGE_SHIFT;
01856
01857
01858
01859
01860
01861 SizeOfRange = (ULONG)((SizeOfRange64 + (
PAGE_SIZE - 1)) >>
PAGE_SHIFT);
01862
ASSERT (SizeOfRange != 0);
01863
01864 Node = Root;
01865
01866
if (Node == (
PMMADDRESS_NODE)
NULL) {
01867
return (PVOID64)MM_LOWEST_USER_ADDRESS64;
01868 }
01869
while (Node->
LeftChild != (
PMMADDRESS_NODE)
NULL) {
01870 Node = Node->
LeftChild;
01871 }
01872
01873
01874
01875
01876
01877
01878
if (Node->
StartingVpn > MI_VA_TO_VPN64 (MM_LOWEST_USER_ADDRESS64)) {
01879
if ( SizeOfRange <
01880 (Node->
StartingVpn - MI_VA_TO_VPN64 (MM_LOWEST_USER_ADDRESS64))) {
01881
01882
return (PVOID64)MM_LOWEST_USER_ADDRESS64;
01883 }
01884 }
01885
01886
for (;;) {
01887
01888 NextNode =
MiGetNextNode (Node);
01889
01890
if (NextNode != (
PMMADDRESS_NODE)
NULL) {
01891
01892
if (SizeOfRange <=
01893 ((ULONG_PTR)NextNode->
StartingVpn -
01894
MI_ROUND_TO_SIZE(1 + Node->
EndingVpn,
01895 AlignmentVpn))) {
01896
01897
01898
01899
01900
01901
01902
if ((ULONG_PTR)NextNode->
StartingVpn >
01903
MI_ROUND_TO_SIZE(1 + Node->
EndingVpn,
01904 AlignmentVpn)) {
01905
01906
return (PVOID64)
MI_ROUND_TO_SIZE(
01907 (ULONGLONG)(MI_VPN_TO_VA_ENDING64(Node->
EndingVpn)),
01908 (ULONGLONG)Alignment);
01909 }
01910 }
01911
01912 }
else {
01913
01914
01915
01916
01917
01918
01919
if ((((ULONG_PTR)Node->
EndingVpn +
MI_VA_TO_VPN(X64K)) <
01920 MI_VA_TO_VPN64 (MM_HIGHEST_VAD_ADDRESS64))
01921 &&
01922 (SizeOfRange64 <=
01923 ((ULONGLONG)
MM_HIGHEST_VAD_ADDRESS64 -
X64K -
01924
MI_ROUND_TO_SIZE(
01925 (ULONGLONG)(MI_VPN_TO_VA64(Node->
EndingVpn)),
01926 (ULONGLONG)Alignment)))) {
01927
01928
Start = MI_VPN_TO_VA_ENDING64 (Node->
EndingVpn);
01929
ASSERT (MI_VA_TO_VPN64 (Start) == Node->
EndingVpn);
01930
01931
Start = (PVOID64)
MI_ROUND_TO_SIZE((ULONGLONG)Start,
01932 (ULONGLONG)Alignment);
01933
ASSERT (MI_VA_TO_VPN64 (Start) > Node->
EndingVpn);
01934
return Start;
01935 }
else {
01936
ExRaiseStatus (STATUS_NO_MEMORY);
01937 }
01938 }
01939 Node = NextNode;
01940 }
01941 }
01942
01943 LOGICAL
01944 MiCommitPages64 (
01945 IN
PMMPTE StartPte,
01946 IN
PMMPTE LastPte,
01947 IN ULONG ProtectionMask,
01948 IN
PEPROCESS Process,
01949 OUT PSIZE_T PtesCommitted
01950 )
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983 {
01984
PMMPTE PointerPte;
01985
PMMPTE PointerPde;
01986
MMPTE TempPte;
01987 PFN_NUMBER PageFrameIndex;
01988
PMMPFN Pfn1;
01989 ULONG PageColor;
01990 KIRQL OldIrql;
01991 ULONG BarrierStamp;
01992 LOGICAL TopPdeBuilt;
01993 LOGICAL PdeBuilt;
01994
PUSHORT UsedPde64Handle;
01995
01996 *PtesCommitted = 0;
01997 PointerPde =
MiGetPteAddress (StartPte);
01998
01999
02000
02001
02002
02003 TopPdeBuilt = MiMakePdeExistAndMakeValid64 (PointerPde, Process, FALSE, TRUE);
02004
if (TopPdeBuilt ==
FALSE) {
02005
return FALSE;
02006 }
02007
02008 UsedPde64Handle = MI_GET_USED_PDE64_HANDLE (PointerPde);
02009
02010 PointerPte = StartPte;
02011
while (PointerPte <= LastPte) {
02012
02013
if (
MiIsPteOnPdeBoundary(PointerPte)) {
02014
02015
02016
02017
02018
02019
02020 PointerPde =
MiGetPteAddress (PointerPte);
02021 UsedPde64Handle = MI_GET_USED_PDE64_HANDLE (PointerPde);
02022
02023
02024
02025
02026
02027
02028 PdeBuilt = MiMakePdeExistAndMakeValid64 (PointerPde, Process, FALSE, TRUE);
02029
ASSERT (PdeBuilt == TRUE);
02030 }
02031
02032
if (PointerPte->
u.Long == 0) {
02033
02034 PageColor =
MI_PAGE_COLOR_PTE_PROCESS (PointerPte,
02035 &Process->NextPageColor);
02036 PointerPte->
u.Soft.Protection = ProtectionMask;
02037
LOCK_PFN (OldIrql);
02038
02039
02040
02041
02042
02043
02044
MiEnsureAvailablePageOrWait (Process, NULL);
02045
02046 PageFrameIndex =
MiRemoveZeroPage (PageColor);
02047
02048 BarrierStamp =
MI_PFN_ELEMENT(PageFrameIndex)->PteFrame;
02049
02050
MiInitializePfn (PageFrameIndex, PointerPte, 1);
02051
UNLOCK_PFN (OldIrql);
02052
02053
MI_MAKE_VALID_PTE (TempPte,
02054 PageFrameIndex,
02055 ProtectionMask,
02056 NULL);
02057
02058
if (TempPte.
u.Hard.Write) {
02059
MI_SET_PTE_DIRTY (TempPte);
02060 }
02061
02062
MI_BARRIER_SYNCHRONIZE (BarrierStamp);
02063
02064 *PointerPte = TempPte;
02065 (*UsedPde64Handle) += 1;
02066
02067 }
else {
02068
ASSERT (PointerPte->
u.Hard.Valid == 1);
02069 (*PtesCommitted) += 1;
02070
02071 Pfn1 =
MI_PFN_ELEMENT (PointerPte->
u.Hard.PageFrameNumber);
02072
02073
if (Pfn1->
OriginalPte.
u.Soft.Protection != ProtectionMask) {
02074
02075
02076
02077
02078
02079 Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
02080
MI_MAKE_VALID_PTE (TempPte,
02081 PointerPte->
u.Hard.PageFrameNumber,
02082 ProtectionMask,
02083 NULL);
02084
if (TempPte.
u.Hard.Write) {
02085
MI_SET_PTE_DIRTY (TempPte);
02086 }
02087
02088
02089
02090
02091
02092
02093
MiFlushTbAndCapture (PointerPte,
02094 TempPte.
u.Flush,
02095 Pfn1);
02096 }
02097 }
02098 PointerPte += 1;
02099 }
02100
return TRUE;
02101 }
02102
02103 LOGICAL
02104 MiMakePdeExistAndMakeValid64 (
02105 IN
PMMPTE PointerPde,
02106 IN
PEPROCESS TargetProcess,
02107 IN LOGICAL PfnLockHeld,
02108 IN LOGICAL MakePageTablePage
02109 )
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
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
02152
02153 {
02154
PMMPTE PointerPte;
02155 KIRQL OldIrql;
02156
MMPTE TempPte;
02157 ULONG PageColor;
02158 PFN_NUMBER PageFrameIndex;
02159 ULONG BarrierStamp;
02160 PMI_PROCESS_VLM_INFO VlmInfo;
02161
PMMPTE PdeBase;
02162
02163 VlmInfo =
NULL;
02164
02165
02166
02167
02168
02169 PointerPte =
MiGetPteAddress (PointerPde);
02170
02171 redo:
02172
02173
if (PointerPte->
u.Long == 0) {
02174
02175
02176
02177
02178
02179
if (VlmInfo ==
NULL) {
02180
02181
if (PfnLockHeld) {
02182
UNLOCK_PFN (OldIrql);
02183 }
02184
02185
UNLOCK_WS (TargetProcess);
02186
02187 VlmInfo = (PMI_PROCESS_VLM_INFO)
ExAllocatePoolWithTag (
02188 NonPagedPool,
02189
sizeof (MI_PROCESS_VLM_INFO),
02190 'lVmM');
02191
02192
if (VlmInfo) {
02193 RtlZeroMemory (VlmInfo,
02194
sizeof (MI_PROCESS_VLM_INFO));
02195 }
02196
02197
LOCK_WS (TargetProcess);
02198
02199
if (PfnLockHeld) {
02200
LOCK_PFN (OldIrql);
02201 }
02202
02203
if (VlmInfo ==
NULL) {
02204
return FALSE;
02205 }
02206
02207
02208
02209
02210
02211
02212
02213
goto redo;
02214 }
02215
02216 PageColor =
MI_PAGE_COLOR_PTE_PROCESS (PointerPte,
02217 &TargetProcess->NextPageColor);
02218
if (!PfnLockHeld) {
02219
LOCK_PFN (OldIrql);
02220 }
02221
02222
if (
MiEnsureAvailablePageOrWait (TargetProcess, NULL) ==
TRUE) {
02223
02224
02225
02226
02227
02228
goto redo;
02229 }
02230
02231 PageFrameIndex =
MiRemoveZeroPage (PageColor);
02232 BarrierStamp =
MI_PFN_ELEMENT(PageFrameIndex)->PteFrame;
02233
MiInitializePfn (PageFrameIndex, PointerPte, 1);
02234
02235
if (!PfnLockHeld) {
02236
UNLOCK_PFN (OldIrql);
02237 }
02238
02239
MI_MAKE_VALID_PTE (TempPte,
02240 PageFrameIndex,
02241 MM_READWRITE,
02242 NULL);
02243
02244
MI_SET_PTE_DIRTY (TempPte);
02245
02246
MI_BARRIER_SYNCHRONIZE (BarrierStamp);
02247
02248 *PointerPte = TempPte;
02249
02250
02251
02252
02253
02254 PdeBase =
MiGetVirtualAddressMappedByPte (PointerPte);
02255
02256
02257
02258
02259
02260
ASSERT (PdeBase == (
PMMPTE)PDE_BASE64);
02261
02262 PdeBase->
u.Long = (ULONG)VlmInfo;
02263 }
02264
else {
02265
if (VlmInfo) {
02266
ExFreePool (VlmInfo);
02267 }
02268 }
02269
02270
ASSERT (PointerPte->
u.Hard.Valid == 1);
02271
02272
if (MakePageTablePage ==
FALSE) {
02273
return TRUE;
02274 }
02275
02276 redo2:
02277
02278
if (PointerPde->u.Hard.Valid == 1) {
02279
02280
02281
02282
02283
02284
return TRUE;
02285 }
02286
02287
02288
02289
02290
02291 PageColor =
MI_PAGE_COLOR_PTE_PROCESS (PointerPde,
02292 &TargetProcess->NextPageColor);
02293
if (!PfnLockHeld) {
02294
LOCK_PFN (OldIrql);
02295 }
02296
02297
if (
MiEnsureAvailablePageOrWait (TargetProcess, NULL) ==
TRUE) {
02298
02299
02300
02301
02302
02303
02304
if (!PfnLockHeld) {
02305
UNLOCK_PFN (OldIrql);
02306 }
02307
goto redo2;
02308 }
02309
02310 PageFrameIndex =
MiRemoveZeroPage (PageColor);
02311 BarrierStamp =
MI_PFN_ELEMENT(PageFrameIndex)->PteFrame;
02312
MiInitializePfn (PageFrameIndex, PointerPde, 1);
02313
02314
if (!PfnLockHeld) {
02315
UNLOCK_PFN (OldIrql);
02316 }
02317
02318
MI_MAKE_VALID_PTE (TempPte,
02319 PageFrameIndex,
02320 MM_READWRITE,
02321 NULL);
02322
02323
MI_SET_PTE_DIRTY (TempPte);
02324
02325
MI_BARRIER_SYNCHRONIZE (BarrierStamp);
02326
02327 *PointerPde = TempPte;
02328
02329
return TRUE;
02330 }
02331
02332 ULONG
02333 MiDoesPdeExist64 (
02334 IN
PMMPTE PointerPde
02335 )
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371 {
02372
PMMPTE PointerPte;
02373 PMI_PROCESS_VLM_INFO VlmInfo;
02374
02375 PointerPte =
MiGetPteAddress(PointerPde);
02376
if (PointerPte->
u.Long == 0) {
02377
02378
02379
02380
02381
02382
return FALSE;
02383 }
02384
02385
if (PointerPde->u.Long == 0) {
02386
02387
02388
02389
02390
02391
return FALSE;
02392 }
02393
02394
ASSERT (PointerPde->u.Hard.Valid == 1);
02395
02396 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
02397
ASSERT (VlmInfo != NULL);
02398
02399
return TRUE;
02400 }
02401
02402 ULONG
02403 MiDecommitOrDeletePages64 (
02404 IN
PMMPTE StartingPte,
02405 IN
PMMPTE EndingPte,
02406 IN
PEPROCESS Process,
02407 IN ULONG Type,
02408 IN LOGICAL FlushTb
02409 )
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441 {
02442
PMMPTE PointerPde;
02443
PMMPTE PointerPte;
02444 ULONG PdeOffset;
02445 PFN_NUMBER CommitReduction;
02446
PMMPTE CommitLimitPte;
02447 KIRQL OldIrql;
02448
PMMPTE ValidPteList[
MM_VALID_PTE_SIZE];
02449 ULONG count;
02450 ULONG WorkingSetIndex;
02451
PMMPFN Pfn1;
02452
PMMPFN Pfn2;
02453 PVOID SwapVa;
02454 ULONG Entry;
02455
MMPTE PteContents;
02456
MMPTE NewPte;
02457 ULONG PfnLockHeld;
02458
PMMPTE LowestPde;
02459 PMI_PROCESS_VLM_INFO VlmInfo;
02460
02461 count = 0;
02462 PfnLockHeld =
FALSE;
02463 CommitReduction = 0;
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473 PointerPte = StartingPte;
02474 PointerPde =
MiGetPteAddress (StartingPte);
02475
02476 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
02477 LowestPde =
MiGetPdeAddress64 (MM_LOWEST_USER_ADDRESS64);
02478
02479
02480
02481
02482
02483
02484
02485
if (!MiDoesPdeExist64 (PointerPde)) {
02486 PointerPte = (
PMMPTE)
PAGE_ALIGN (PointerPte);
02487 PointerPte +=
PTE_PER_PAGE;
02488 }
02489
02490
while (PointerPte <= EndingPte) {
02491
02492
if (
MiIsPteOnPdeBoundary(PointerPte)) {
02493
02494
if (count != 0) {
02495 MiProcessValidPteList64 (&ValidPteList[0], count, FlushTb);
02496 count = 0;
02497 }
02498
02499
if (PfnLockHeld) {
02500
UNLOCK_PFN (OldIrql);
02501 }
02502
02503 MiCheckPdeForDeletion (PointerPde, FlushTb);
02504 PointerPde =
MiGetPteAddress (PointerPte);
02505
02506
if (!MiDoesPdeExist64 (PointerPde)) {
02507 PointerPte +=
PTE_PER_PAGE;
02508
continue;
02509 }
02510
if (PfnLockHeld) {
02511
LOCK_PFN (OldIrql);
02512 }
02513 }
02514
02515
02516
02517
02518
02519
02520
02521 PteContents = *PointerPte;
02522
02523
if (PteContents.
u.Long != 0) {
02524
02525 VlmInfo->UsedPageTableEntries[PointerPde - LowestPde] -= 1;
02526
02527
if (PteContents.
u.Hard.Valid == 1) {
02528
if (Type == DELETE_TYPE_PRIVATE) {
02529 CommitReduction += 1;
02530 }
02531
02532
02533
02534
02535
02536
if (count ==
MM_VALID_PTE_SIZE) {
02537 MiProcessValidPteList64 (&ValidPteList[0], count, FlushTb);
02538 count = 0;
02539 }
02540 ValidPteList[count] = PointerPte;
02541 count += 1;
02542 }
else if (PteContents.
u.Soft.Prototype == 1) {
02543 NOTHING;
02544
02545 }
else if (PteContents.
u.Soft.Transition == 1) {
02546
02547
02548
02549
02550
02551
02552
02553
if (!PfnLockHeld) {
02554
LOCK_PFN (OldIrql);
02555 PfnLockHeld =
TRUE;
02556
continue;
02557 }
02558 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
02559
02560
MI_SET_PFN_DELETED (Pfn1);
02561
02562
MiDecrementShareCount (Pfn1->
PteFrame);
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
if (Pfn1->
u3.e2.ReferenceCount == 0) {
02573
MiUnlinkPageFromList (Pfn1);
02574
MiReleasePageFileSpace (Pfn1->
OriginalPte);
02575
MiInsertPageInList (MmPageLocationList[FreePageList],
02576
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&PteContents));
02577 }
02578 }
else {
02579
ASSERT (PteContents.
u.Soft.PageFileHigh == 0);
02580 }
02581 }
02582
02583
if (PfnLockHeld) {
02584
UNLOCK_PFN (OldIrql);
02585 PfnLockHeld =
FALSE;
02586 }
02587 PointerPte += 1;
02588 }
02589
if (count != 0) {
02590 MiProcessValidPteList64 (&ValidPteList[0], count, FlushTb);
02591 }
02592
02593 MiCheckPdeForDeletion (PointerPde, FlushTb);
02594
02595 MiReturnAvailablePages (CommitReduction);
02596
02597
return CommitReduction;
02598 }
02599
VOID
02600 MiProcessValidPteList64 (
02601 IN
PMMPTE *ValidPteList,
02602 IN ULONG Count,
02603 IN LOGICAL FlushTb
02604 )
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631 {
02632 ULONG i = 0;
02633 MMPTE_FLUSH_LIST64 PteFlushList;
02634
MMPTE PteContents;
02635
PMMPFN Pfn1;
02636 KIRQL OldIrql;
02637
PMMPTE PointerPde;
02638
02639 PteFlushList.Count =
Count;
02640
02641
LOCK_PFN (OldIrql);
02642
02643
do {
02644 PteContents = *ValidPteList[i];
02645
ASSERT (PteContents.
u.Hard.Valid == 1);
02646 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
02647
02648
if (Pfn1->
u3.e1.PrototypePte == 1) {
02649
02650
02651
02652
02653
02654
02655
MI_CAPTURE_DIRTY_BIT_TO_PFN (&PteContents, Pfn1);
02656
02657
02658
02659
02660
02661
02662 PointerPde =
MiGetPteAddress (ValidPteList[i]);
02663
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE(PointerPde));
02664
02665
02666
02667
02668
02669
MiDecrementShareCount (
MI_GET_PAGE_FRAME_FROM_PTE(&PteContents));
02670
02671 }
else {
02672
02673
02674
02675
02676
02677
02678
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
02679
02680
MI_SET_PFN_DELETED (Pfn1);
02681
02682
02683
02684
02685
02686
02687
MiDecrementShareCountOnly (
MI_GET_PAGE_FRAME_FROM_PTE(&PteContents));
02688 }
02689
02690
if (
Count <
MM_MAXIMUM_FLUSH_COUNT) {
02691 PteFlushList.FlushPte[i] = ValidPteList[i];
02692 PteFlushList.FlushVpn[i] =
02693
MiGetVirtualPageNumberMappedByPte64 (ValidPteList[i]) >>
PAGE_SHIFT;
02694 }
02695 *ValidPteList[i] =
ZeroPte;
02696 i += 1;
02697 }
while (i !=
Count);
02698
02699
if (FlushTb) {
02700 MiFlushPteList64 (&PteFlushList, FALSE, ZeroPte);
02701 }
02702
02703
UNLOCK_PFN (OldIrql);
02704
return;
02705 }
02706
02707
VOID
02708 MiReturnAvailablePages (
02709 IN PFN_NUMBER Amount
02710 )
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733 {
02734 KIRQL OldIrql;
02735
02736
LOCK_PFN (OldIrql);
02737
MmResidentAvailablePages += Amount;
02738
MM_BUMP_COUNTER(26, Amount);
02739
UNLOCK_PFN (OldIrql);
02740
return;
02741 }
02742
02743
02744 LOGICAL
02745 MiCheckPdeForDeletion (
02746 IN
PMMPTE PointerPde,
02747 IN LOGICAL FlushTb
02748 )
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775 {
02776 LOGICAL
Status;
02777 KIRQL OldIrql;
02778 PFN_NUMBER PageFrameIndex;
02779
PMMPFN Pfn1;
02780
PMMPTE PointerPte;
02781 PMI_PROCESS_VLM_INFO VlmInfo;
02782
PMMPTE LowestPde;
02783
02784 PointerPte =
MiGetPteAddress (PointerPde);
02785
if (PointerPte->
u.Hard.Valid == 0) {
02786
02787
02788
02789
02790
02791
return TRUE;
02792 }
02793
02794
if (PointerPde->u.Hard.Valid == 0) {
02795
02796
02797
02798
02799
02800
return TRUE;
02801 }
02802 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE(PointerPde);
02803 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02804
Status =
FALSE;
02805
LOCK_PFN (OldIrql);
02806
02807 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
02808 LowestPde =
MiGetPdeAddress64 (MM_LOWEST_USER_ADDRESS64);
02809
02810 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
02811
02812
if (VlmInfo->UsedPageTableEntries[PointerPde - LowestPde] == 0) {
02813
ASSERT (Pfn1->
u2.ShareCount == 1);
02814
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
02815
MI_SET_PFN_DELETED (Pfn1);
02816
MiDecrementShareCountOnly (PageFrameIndex);
02817
if (FlushTb ==
TRUE) {
02818
KeFlushSingleTb (PointerPte,
02819 TRUE,
02820 FALSE,
02821 (PHARDWARE_PTE)PointerPde,
02822
ZeroPte.
u.Flush);
02823 }
02824
else {
02825 *PointerPde =
ZeroPte;
02826 }
02827
Status =
TRUE;
02828 }
02829
#if DBG
02830
else {
02831 ULONG i;
02832 ULONG count;
02833 PULONG p;
02834
02835 count = 0;
02836 p = (PULONG)PointerPte;
02837
02838
for (i = 0; i <
PAGE_SIZE; i +=
sizeof(p)) {
02839 p += 1;
02840 count += 1;
02841 }
02842
ASSERT (count != 0);
02843 }
02844
#endif
02845
02846
UNLOCK_PFN (OldIrql);
02847
return Status;
02848 }
02849
02850
VOID
02851 MiDeleteVlmAddressSpace (
02852 IN
PEPROCESS Process
02853 )
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878 {
02879
PMMVAD Vad;
02880
PMMPTE PointerPde;
02881
PMMPTE PointerPte1;
02882
PMMPTE PointerPte2;
02883
PMMPFN Pfn1;
02884
MMPTE PteContents;
02885 KIRQL OldIrql;
02886
PCONTROL_AREA ControlArea;
02887 ULONG Type;
02888 PMI_PROCESS_VLM_INFO VlmInfo;
02889 SIZE_T CommitReduction;
02890 ULONGLONG RegionSize;
02891
02892 Vad = (
PMMVAD)Process->CloneRoot;
02893
02894
if (Vad != (
PMMVAD)
NULL) {
02895 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
02896
02897
do {
02898
02899 MiRemoveVad64 (Vad);
02900
02901 Type = DELETE_TYPE_PRIVATE;
02902
if (Vad->
u.VadFlags.PrivateMemory == 0) {
02903 Type = DELETE_TYPE_SHARED;
02904 }
02905 CommitReduction = MiDecommitOrDeletePages64 (
02906 MiGetPteAddress64 (MI_VPN_TO_VA64 (Vad->
StartingVpn)),
02907
MiGetPteAddress64 (MI_VPN_TO_VA_ENDING64 (Vad->
EndingVpn)),
02908 Process,
02909 Type,
02910 FALSE);
02911
02912
02913 RegionSize = (((ULONGLONG)(Vad->
EndingVpn - Vad->
StartingVpn + 1)) <<
PAGE_SHIFT);
02914 VlmInfo->VirtualSize -= RegionSize;
02915
02916 ExAcquireFastLock (&MiVlmStatisticsLock, &OldIrql);
02917
if (Type != DELETE_TYPE_SHARED) {
02918 MiVlmCommitChargeInPages -= CommitReduction;
02919 }
02920 ExReleaseFastLock (&MiVlmStatisticsLock, OldIrql);
02921
02922
if (Type == DELETE_TYPE_SHARED) {
02923
02924
02925
02926
02927
02928
02929 ControlArea = Vad->
ControlArea;
02930
02931
LOCK_PFN (OldIrql);
02932 ControlArea->
NumberOfMappedViews -= 1;
02933 ControlArea->
NumberOfUserReferences -= 1;
02934
02935
02936
02937
02938
02939
02940
MiCheckControlArea (ControlArea, Process, OldIrql);
02941 }
02942
else {
02943 VlmInfo->CommitCharge -= CommitReduction;
02944 }
02945
02946
ExFreePool (Vad);
02947 Vad = (
PMMVAD)Process->CloneRoot;
02948
02949 }
while (Vad != (
PMMVAD)
NULL);
02950 }
02951
02952
02953
02954
02955
02956 PointerPde =
MiGetPdeAddress64 (MM_LOWEST_USER_ADDRESS64);
02957 PointerPte1 =
MiGetPteAddress (PointerPde);
02958 PointerPde =
MiGetPdeAddress64 (MM_HIGHEST_USER_ADDRESS64);
02959 PointerPte2 =
MiGetPteAddress (PointerPde);
02960
02961
02962
02963
02964
02965
if (PointerPte1->
u.Hard.Valid) {
02966
ASSERT (MiGetPteAddress (PDE_BASE64) == PointerPte1);
02967
ASSERT ((
PMMPTE)PDE_BASE64 != PointerPde);
02968 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
02969
02970
#if DBG
02971
ASSERT (VlmInfo->CommitCharge == 0);
02972
ASSERT (VlmInfo->VirtualSize == 0);
02973
02974 {
02975 ULONG i;
02976
PUSHORT UsedPageTableEntries;
02977
02978 UsedPageTableEntries = VlmInfo->UsedPageTableEntries;
02979
02980
for (i = 0; i < MM_USER_PAGE_TABLE_PAGES64; i += 1) {
02981
ASSERT ((*UsedPageTableEntries) == 0);
02982 UsedPageTableEntries += 1;
02983 }
02984 }
02985
#endif
02986
02987
ExFreePool (VlmInfo);
02988 }
02989
02990
do {
02991
02992 PteContents = *PointerPte1;
02993
if (PteContents.
u.Hard.Valid) {
02994
02995 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
02996
02997
02998
02999
03000
03001
03002
LOCK_PFN (OldIrql);
03003
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
03004
03005
MI_SET_PFN_DELETED (Pfn1);
03006
03007
03008
03009
03010
03011
03012
MiDecrementShareCountOnly(
MI_GET_PAGE_FRAME_FROM_PTE(&PteContents));
03013
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
03014
UNLOCK_PFN (OldIrql);
03015 }
03016 PointerPte1 += 1;
03017
03018 }
while (PointerPte1 <= PointerPte2);
03019
03020
return;
03021 }
03022
03023
VOID
03024 MiFlushPteList64 (
03025 IN PMMPTE_FLUSH_LIST64 PteFlushList,
03026 IN ULONG AllProcessors,
03027 IN
MMPTE FillPte
03028 )
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055 {
03056 ULONG count;
03057 ULONG i = 0;
03058
03059
ASSERT (ARGUMENT_PRESENT (PteFlushList));
03060
MM_PFN_LOCK_ASSERT ();
03061
03062 count = PteFlushList->Count;
03063
03064
if (count != 0) {
03065
if (count != 1) {
03066
if (count <
MM_MAXIMUM_FLUSH_COUNT) {
03067
KeFlushMultipleTb64 (count,
03068 &PteFlushList->FlushVpn[0],
03069 TRUE,
03070 (BOOLEAN)AllProcessors,
03071 &((PHARDWARE_PTE)PteFlushList->FlushPte[0]),
03072 FillPte.u.Flush);
03073 }
else {
03074
03075
03076
03077
03078
03079
if (AllProcessors ==
TRUE) {
03080
MiLockSystemSpaceAtDpcLevel();
03081
KeFlushEntireTb (TRUE, TRUE);
03082
MmFlushCounter = (
MmFlushCounter + 1) &
MM_FLUSH_COUNTER_MASK;
03083
MiUnlockSystemSpaceFromDpcLevel();
03084 }
else {
03085
KeFlushEntireTb (TRUE, FALSE);
03086 }
03087 }
03088 }
else {
03089
KeFlushSingleTb64 (PteFlushList->FlushVpn[0],
03090 TRUE,
03091 (BOOLEAN)AllProcessors,
03092 (PHARDWARE_PTE)PteFlushList->FlushPte[0],
03093 FillPte.u.Flush);
03094 }
03095 PteFlushList->Count = 0;
03096 }
03097
return;
03098 }
03099
03100 BOOLEAN
03101 MmIsAddressValid64 (
03102 IN PVOID64 VirtualAddress
03103 )
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130 {
03131
PMMPTE PointerPte;
03132
PMMPTE PointerPde;
03133
03134 PointerPde =
MiGetPdeAddress64 (VirtualAddress);
03135
03136
03137
03138
03139
03140 PointerPte =
MiGetPteAddress (PointerPde);
03141
if (PointerPte->
u.Hard.Valid == 0) {
03142
return FALSE;
03143 }
03144
03145
if (PointerPde->
u.Hard.Valid == 0) {
03146
return FALSE;
03147 }
03148
03149 PointerPte =
MiGetPteAddress64 (VirtualAddress);
03150
if (PointerPte->
u.Hard.Valid == 0) {
03151
return FALSE;
03152 }
03153
return TRUE;
03154 }
03155
03156
NTSTATUS
03157
NtMapViewOfVlmSection (
03158 IN HANDLE SectionHandle,
03159 IN HANDLE ProcessHandle,
03160 IN OUT PVOID64 *BaseAddress,
03161 IN OUT PULONGLONG SectionOffset OPTIONAL,
03162 IN OUT PULONGLONG ViewSize,
03163 IN ULONG AllocationType,
03164 IN ULONG Protect
03165 )
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237 {
03238
PSECTION Section;
03239
PEPROCESS Process;
03240
KPROCESSOR_MODE PreviousMode;
03241
NTSTATUS Status;
03242 PVOID64 CapturedBase;
03243 ULONGLONG CapturedViewSize;
03244 ULONGLONG TempViewSize;
03245 ULONGLONG CapturedOffset;
03246 ACCESS_MASK DesiredSectionAccess;
03247 ULONG ProtectMaskForAccess;
03248
PCONTROL_AREA ControlArea;
03249 LOGICAL Attached;
03250 ULONG ReleasedWsMutex;
03251
03252
PAGED_CODE();
03253
03254 Attached =
FALSE;
03255
03256
if (MI_VLM_ENABLED() ==
FALSE) {
03257
return STATUS_NOT_IMPLEMENTED;
03258 }
03259
03260
03261
03262
03263
03264
if (AllocationType != 0) {
03265
return STATUS_INVALID_PARAMETER_6;
03266 }
03267
03268
03269
03270
03271
03272
try {
03273 ProtectMaskForAccess =
MiMakeProtectionMask (Protect) & 0x7;
03274 } except (EXCEPTION_EXECUTE_HANDLER) {
03275
return GetExceptionCode();
03276 }
03277
03278 DesiredSectionAccess =
MmMakeSectionAccess[ProtectMaskForAccess];
03279
03280 PreviousMode = KeGetPreviousMode();
03281
03282
03283
03284
03285
03286
03287 CapturedOffset = 0;
03288
try {
03289
if (PreviousMode !=
KernelMode) {
03290
ProbeForWrite (BaseAddress,
sizeof(PVOID64),
sizeof(PVOID64));
03291
ProbeForWrite (ViewSize,
sizeof(ULONGLONG),
sizeof(ULONGLONG));
03292
if (ARGUMENT_PRESENT (SectionOffset)) {
03293
if (PreviousMode !=
KernelMode) {
03294
ProbeForWrite (SectionOffset,
03295
sizeof(ULONGLONG),
03296
sizeof(ULONGLONG));
03297 }
03298 }
03299 }
03300
03301
if (ARGUMENT_PRESENT (SectionOffset)) {
03302 CapturedOffset = *SectionOffset;
03303 }
03304
03305
03306
03307
03308
03309 CapturedBase = *BaseAddress;
03310
03311
03312
03313
03314
03315 CapturedViewSize = *ViewSize;
03316
03317 } except (
ExSystemExceptionFilter()) {
03318
03319
03320
03321
03322
03323
03324
03325
return GetExceptionCode();
03326 }
03327
03328
if ((ARGUMENT_PRESENT (SectionOffset)) &&
03329 ((CapturedOffset & (
X64K - 1)) != 0)) {
03330
return STATUS_MAPPED_ALIGNMENT;
03331 }
03332
03333
if (((ULONGLONG)CapturedBase & (
X64K - 1)) != 0) {
03334
return STATUS_MAPPED_ALIGNMENT;
03335 }
03336
03337
03338
03339
03340
03341
03342
if ((CapturedBase !=
NULL ) &&
03343 ((CapturedBase > (PVOID64)MM_HIGHEST_USER_ADDRESS64) ||
03344 (CapturedBase < (PVOID64)MM_LOWEST_USER_ADDRESS64))) {
03345
03346
03347
03348
03349
03350
return STATUS_INVALID_PARAMETER_3;
03351 }
03352
03353
if (CapturedBase !=
NULL) {
03354
03355
if ((ULONGLONG)CapturedBase + CapturedViewSize < (ULONGLONG)CapturedBase) {
03356
03357
03358
03359
03360
03361
return STATUS_INVALID_PARAMETER_5;
03362 }
03363
03364
03365
if ((ULONGLONG)CapturedBase + CapturedViewSize > (ULONGLONG)MM_HIGHEST_USER_ADDRESS64 -
X64K) {
03366
03367
03368
03369
03370
03371
return STATUS_INVALID_PARAMETER_5;
03372 }
03373 }
03374
else if (CapturedViewSize > (ULONGLONG)MM_LARGEST_VLM_RANGE -
X64K) {
03375
03376
03377
03378
03379
03380
return STATUS_INVALID_PARAMETER_5;
03381 }
03382
03383
03384
Status =
ObReferenceObjectByHandle ( ProcessHandle,
03385 PROCESS_VM_OPERATION,
03386 PsProcessType,
03387 PreviousMode,
03388 (PVOID *)&Process,
03389 NULL );
03390
if (!
NT_SUCCESS(Status)) {
03391
return Status;
03392 }
03393
03394
03395
03396
03397
03398
03399
03400
Status =
ObReferenceObjectByHandle ( SectionHandle,
03401 DesiredSectionAccess,
03402 MmSectionObjectType,
03403 PreviousMode,
03404 (PVOID *)&Section,
03405 NULL );
03406
03407
if (!
NT_SUCCESS(Status)) {
03408
goto ErrorReturn1;
03409 }
03410
03411
if (Section->Segment->ControlArea->u.Flags.Vlm == 0) {
03412
03413
03414
03415
03416
03417
Status = STATUS_INVALID_VLM_OPERATION;
03418
goto ErrorReturn;
03419 }
03420
03421
03422
03423
03424
03425
if ((CapturedOffset + CapturedViewSize) >
03426 (ULONGLONG)Section->SizeOfSection.QuadPart) {
03427
Status = STATUS_INVALID_VIEW_SIZE;
03428
goto ErrorReturn;
03429 }
03430
03431
if (CapturedViewSize == 0) {
03432
03433
03434
03435
03436
03437 TempViewSize = Section->SizeOfSection.QuadPart -
03438 CapturedOffset;
03439
03440 CapturedViewSize = TempViewSize;
03441
03442
if ((TempViewSize == 0) ||
03443 (((ULONGLONG)
MM_HIGHEST_VAD_ADDRESS64 - (ULONGLONG)CapturedBase) <
03444 CapturedViewSize)) {
03445
03446
03447
03448
03449
03450
Status = STATUS_INVALID_VIEW_SIZE;
03451
goto ErrorReturn;
03452 }
03453
03454 }
else {
03455
03456
03457
03458
03459
03460
03461
if ((CapturedViewSize + CapturedOffset) >
03462 (ULONGLONG)Section->SizeOfSection.QuadPart) {
03463
03464
Status = STATUS_INVALID_VIEW_SIZE;
03465
goto ErrorReturn;
03466 }
03467 }
03468
03469 ControlArea = Section->
Segment->
ControlArea;
03470
03471
if (
PsGetCurrentProcess() != Process) {
03472
KeAttachProcess (&Process->
Pcb);
03473 Attached =
TRUE;
03474 }
03475
03476
03477
03478
03479
03480
03481
LOCK_ADDRESS_SPACE (Process);
03482
03483
03484
03485
03486
03487
if (Process->
AddressSpaceDeleted != 0) {
03488
UNLOCK_ADDRESS_SPACE (Process);
03489
Status = STATUS_PROCESS_IS_TERMINATING;
03490
goto ErrorReturn;
03491 }
03492
03493
03494
03495
03496
03497
if ((Process->
CloneRoot !=
NULL) &&
03498 (Process->
ForkWasSuccessful != MM_NO_FORK_ALLOWED)) {
03499
UNLOCK_ADDRESS_SPACE (Process);
03500
Status = STATUS_INVALID_VLM_OPERATION;
03501
goto ErrorReturn;
03502 }
03503 Process->
ForkWasSuccessful = MM_NO_FORK_ALLOWED;
03504
03505 ReleasedWsMutex =
FALSE;
03506
03507
Status = MiMapViewOfVlmDataSection (ControlArea,
03508 Process,
03509 &CapturedBase,
03510 &CapturedOffset,
03511 &CapturedViewSize,
03512 Section,
03513 ProtectMaskForAccess,
03514 AllocationType,
03515 &ReleasedWsMutex);
03516
03517
if (!ReleasedWsMutex) {
03518
UNLOCK_WS (Process);
03519 }
03520
UNLOCK_ADDRESS_SPACE (Process);
03521
03522
if (Attached ==
TRUE) {
03523
KeDetachProcess();
03524 Attached =
FALSE;
03525 }
03526
03527
if (!
NT_SUCCESS(Status) ) {
03528
goto ErrorReturn;
03529 }
03530
03531
03532
03533
03534
03535
03536
try {
03537
03538 *ViewSize = CapturedViewSize;
03539 *BaseAddress = CapturedBase;
03540
03541
if (ARGUMENT_PRESENT(SectionOffset)) {
03542 *SectionOffset = CapturedOffset;
03543 }
03544
03545 } except (EXCEPTION_EXECUTE_HANDLER) {
03546 NOTHING;
03547 }
03548
03549 ErrorReturn:
03550
if (Attached ==
TRUE) {
03551
KeDetachProcess();
03552 Attached =
FALSE;
03553 }
03554
03555
ObDereferenceObject (Section);
03556 ErrorReturn1:
03557
ObDereferenceObject (Process);
03558
return Status;
03559 }
03560
03561
NTSTATUS
03562 MiMapViewOfVlmDataSection (
03563 IN
PCONTROL_AREA ControlArea,
03564 IN
PEPROCESS Process,
03565 IN PVOID64 *CapturedBase,
03566 IN PULONGLONG SectionOffset,
03567 IN PULONGLONG CapturedViewSize,
03568 IN PSECTION Section,
03569 IN ULONG ProtectionMask,
03570 IN ULONG AllocationType,
03571 IN PULONG ReleasedWsMutex
03572 )
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605 {
03606
PMMVAD Vad;
03607
volatile PVOID64 Va;
03608 PVOID64 StartingAddress;
03609 PVOID64 EndingAddress;
03610 KIRQL OldIrql;
03611
PSUBSECTION Subsection;
03612 ULONG PteOffset;
03613
PMMPTE PointerPte;
03614
PMMPTE LastPte;
03615
MMPTE TempPte;
03616 ULONG QuotaCharge;
03617
PMMPTE TheFirstPrototypePte;
03618
PMMPTE Pde;
03619
PMMPTE LastPde;
03620 LOGICAL PdeBuilt;
03621
NTSTATUS ReturnStatus;
03622 PMI_PROCESS_VLM_INFO VlmInfo;
03623
03624
03625
03626
03627
03628
03629
03630
if ((Process->CloneRoot !=
NULL) &&
03631 (Process->ForkWasSuccessful != MM_NO_FORK_ALLOWED)) {
03632 *ReleasedWsMutex =
TRUE;
03633
return STATUS_INVALID_VLM_OPERATION;
03634 }
03635
03636 QuotaCharge = 0;
03637
03638 Process->ForkWasSuccessful = MM_NO_FORK_ALLOWED;
03639
03640
MiCheckPurgeAndUpMapCount (ControlArea);
03641
03642
03643
03644
03645
03646
ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0);
03647
03648 Subsection = (
PSUBSECTION)(ControlArea + 1);
03649
03650 *SectionOffset = (ULONGLONG)MI_ALIGN_TO_SIZE64 (*SectionOffset, X64K);
03651 PteOffset = (ULONG)(*SectionOffset >>
PAGE_SHIFT);
03652
03653
03654
03655
03656
03657
03658
while (PteOffset >= Subsection->
PtesInSubsection) {
03659 PteOffset -= Subsection->
PtesInSubsection;
03660 Subsection = Subsection->
NextSubsection;
03661
ASSERT (Subsection != NULL);
03662 }
03663
03664 TheFirstPrototypePte = &Subsection->
SubsectionBase[PteOffset];
03665
03666
03667
03668
LOCK_WS (Process);
03669
03670
if (*CapturedBase ==
NULL) {
03671
03672
03673
03674
03675
03676
try {
03677
03678
03679
03680
03681
03682 StartingAddress = MiFindEmptyAddressRangeInTree64 (
03683 *CapturedViewSize,
03684 X64K,
03685 (
PMMADDRESS_NODE)(Process->CloneRoot));
03686
03687 } except (EXCEPTION_EXECUTE_HANDLER) {
03688
03689
LOCK_PFN (OldIrql);
03690 ControlArea->NumberOfMappedViews -= 1;
03691 ControlArea->NumberOfUserReferences -= 1;
03692
UNLOCK_PFN (OldIrql);
03693
return GetExceptionCode();
03694 }
03695
03696 EndingAddress = (PVOID64)(((ULONGLONG)StartingAddress +
03697 *CapturedViewSize - 1
L) | (
PAGE_SIZE - 1
L));
03698
03699 }
else {
03700
03701 StartingAddress = MI_ALIGN_TO_SIZE64 (*CapturedBase, X64K);
03702
03703
03704
03705
03706
03707
03708 EndingAddress = (PVOID64)(((ULONGLONG)StartingAddress +
03709 *CapturedViewSize - 1
L) | (
PAGE_SIZE - 1
L));
03710
03711 Vad = MiCheckForConflictingVad64 (StartingAddress, EndingAddress);
03712
if (Vad != (
PMMVAD)
NULL) {
03713
LOCK_PFN (OldIrql);
03714 ControlArea->NumberOfMappedViews -= 1;
03715 ControlArea->NumberOfUserReferences -= 1;
03716
UNLOCK_PFN (OldIrql);
03717
return STATUS_CONFLICTING_ADDRESSES;
03718 }
03719 }
03720
03721
03722
03723
03724
03725
03726
try {
03727
03728 Vad =
ExAllocatePoolWithTag (NonPagedPool,
03729
sizeof(
MMVAD),
03730 MMVADKEY);
03731
if (Vad ==
NULL) {
03732
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
03733 }
03734 RtlZeroMemory (Vad,
sizeof(
MMVAD));
03735
03736 Vad->
StartingVpn = MI_VA_TO_VPN64 (StartingAddress);
03737 Vad->
EndingVpn = MI_VA_TO_VPN64 (EndingAddress);
03738 Vad->
FirstPrototypePte = TheFirstPrototypePte;
03739
03740
03741
03742
03743
03744 Vad->
ControlArea = ControlArea;
03745
03746 Vad->
u2.VadFlags2.Inherit = 0;
03747 Vad->
u.VadFlags.Protection = ProtectionMask;
03748 Vad->
u2.VadFlags2.CopyOnWrite = 0;
03749
03750 Vad->
u2.VadFlags2.FileOffset = (ULONG)(*SectionOffset >> 16);
03751
03752 PteOffset += (ULONG) (Vad->
EndingVpn - Vad->
StartingVpn);
03753
03754
if (PteOffset < Subsection->
PtesInSubsection ) {
03755 Vad->
LastContiguousPte = &Subsection->
SubsectionBase[PteOffset];
03756
03757 }
else {
03758 Vad->
LastContiguousPte = &Subsection->
SubsectionBase[
03759 (Subsection->
PtesInSubsection - 1) +
03760 Subsection->
UnusedPtes];
03761 }
03762
03763
ASSERT (Vad->
FirstPrototypePte <= Vad->
LastContiguousPte);
03764 MiInsertVad64 (Vad);
03765
03766 } except (EXCEPTION_EXECUTE_HANDLER) {
03767
03768
LOCK_PFN (OldIrql);
03769 ControlArea->NumberOfMappedViews -= 1;
03770 ControlArea->NumberOfUserReferences -= 1;
03771
UNLOCK_PFN (OldIrql);
03772
03773
if (Vad != (
PMMVAD)
NULL) {
03774
03775
03776
03777
03778
03779
03780
03781
ExFreePool (Vad);
03782
return GetExceptionCode();
03783 }
03784
return STATUS_INSUFFICIENT_RESOURCES;
03785 }
03786
03787
03788
03789
03790
03791
03792
03793 Pde =
MiGetPdeAddress64 (StartingAddress);
03794 PdeBuilt = MiMakePdeExistAndMakeValid64 (Pde, Process, FALSE, FALSE);
03795
03796
if (PdeBuilt ==
FALSE) {
03797
ASSERT (Pde == MiGetPdeAddress64 (StartingAddress));
03798
LOCK_PFN (OldIrql);
03799 ControlArea->NumberOfMappedViews -= 1;
03800 ControlArea->NumberOfUserReferences -= 1;
03801
UNLOCK_PFN (OldIrql);
03802 MiRemoveVad64 (Vad);
03803
ExFreePool (Vad);
03804
return STATUS_INSUFFICIENT_RESOURCES;
03805 }
03806
03807 *ReleasedWsMutex =
TRUE;
03808
UNLOCK_WS (Process);
03809
03810
03811
03812
03813
03814 *CapturedViewSize = (
char * POINTER_64)EndingAddress - (
char * POINTER_64)StartingAddress + 1
L;
03815
03816 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
03817 VlmInfo->VirtualSize += *CapturedViewSize;
03818
if (VlmInfo->VirtualSize > VlmInfo->VirtualSizePeak) {
03819 VlmInfo->VirtualSizePeak = VlmInfo->VirtualSize;
03820 }
03821
03822 *CapturedBase = StartingAddress;
03823
03824
return STATUS_SUCCESS;
03825 }
03826
03827
NTSTATUS
03828
NtUnmapViewOfVlmSection(
03829 IN HANDLE ProcessHandle,
03830 IN OUT PVOID64 *BaseAddress
03831 )
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854 {
03855
PEPROCESS Process;
03856
KPROCESSOR_MODE PreviousMode;
03857
PMMVAD Vad;
03858 ULONGLONG RegionSize;
03859 PVOID64 UnMapImageBase;
03860 PVOID64 CapturedBase;
03861
NTSTATUS status;
03862
PMMPTE StartingPte;
03863
PMMPTE EndingPte;
03864
PCONTROL_AREA ControlArea;
03865 KIRQL OldIrql;
03866 ULONG CommitReduction;
03867 PMI_PROCESS_VLM_INFO VlmInfo;
03868
03869
if (MI_VLM_ENABLED() ==
FALSE) {
03870
return STATUS_NOT_IMPLEMENTED;
03871 }
03872
03873 PreviousMode = KeGetPreviousMode();
03874
03875 status =
ObReferenceObjectByHandle ( ProcessHandle,
03876 PROCESS_VM_OPERATION,
03877 PsProcessType,
03878 PreviousMode,
03879 (PVOID *)&Process,
03880 NULL );
03881
if (!
NT_SUCCESS(status)) {
03882
return status;
03883 }
03884
03885 UnMapImageBase =
NULL;
03886
03887
03888
03889
03890
03891
03892
KeAttachProcess (&Process->
Pcb);
03893
03894
03895
03896
03897
03898 PreviousMode = KeGetPreviousMode();
03899
03900
if (PreviousMode !=
KernelMode) {
03901
try {
03902
ProbeForRead (BaseAddress,
sizeof(PVOID64),
sizeof(PVOID64));
03903
03904
03905
03906
03907
03908 CapturedBase = *BaseAddress;
03909 } except (
ExSystemExceptionFilter()) {
03910
03911
03912
03913
03914
03915
03916
03917
KeDetachProcess();
03918
ObDereferenceObject (Process);
03919
return GetExceptionCode();
03920 }
03921 }
03922
else {
03923 CapturedBase = *BaseAddress;
03924 }
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
LOCK_WS_AND_ADDRESS_SPACE (Process);
03937
03938
03939
03940
03941
03942
if (Process->
AddressSpaceDeleted != 0) {
03943 status = STATUS_PROCESS_IS_TERMINATING;
03944
goto ErrorReturn;
03945 }
03946
03947
if (Process->
ForkWasSuccessful != MM_NO_FORK_ALLOWED) {
03948 status = STATUS_NOT_MAPPED_VIEW;
03949
goto ErrorReturn;
03950 }
03951
03952
03953
03954
03955
03956 Vad = (
PMMVAD)MiLocateAddress64 (MI_VA_TO_VPN64 (CapturedBase));
03957
03958
if ((Vad == (
PMMVAD)
NULL) || (Vad->
u.VadFlags.PrivateMemory)) {
03959
03960
03961
03962
03963
03964 status = STATUS_NOT_MAPPED_VIEW;
03965
goto ErrorReturn;
03966 }
03967
03968
ASSERT (Vad->
u.VadFlags.NoChange == 0);
03969
03970 RegionSize =
PAGE_SIZE + (((ULONGLONG)(Vad->
EndingVpn - Vad->
StartingVpn)) <<
PAGE_SHIFT);
03971
03972 MiRemoveVad64 (Vad);
03973
03974
#if 0
03975
03976
03977
03978
03979
MiReturnPageTablePageCommitment (MI_VPN_TO_VA (Vad->
StartingVpn),
03980
MI_VPN_TO_VA_ENDING (Vad->
EndingVpn),
03981 Process,
03982 PreviousVad,
03983 NextVad);
03984
#endif //0
03985
03986 StartingPte =
MiGetPteAddress64 (MI_VPN_TO_VA64 (Vad->
StartingVpn));
03987 EndingPte =
MiGetPteAddress64 (MI_VPN_TO_VA64 (Vad->
EndingVpn));
03988
03989 CommitReduction = MiDecommitOrDeletePages64 (StartingPte,
03990 EndingPte,
03991 Process,
03992 DELETE_TYPE_SHARED,
03993 TRUE);
03994
03995
03996
03997
03998
03999
04000
04001 ControlArea = Vad->
ControlArea;
04002
LOCK_PFN (OldIrql);
04003 ControlArea->
NumberOfMappedViews -= 1;
04004 ControlArea->
NumberOfUserReferences -= 1;
04005
04006
04007
04008
04009
04010
04011
MiCheckControlArea (ControlArea, Process, OldIrql);
04012
04013
ExFreePool (Vad);
04014
04015
04016
04017
04018
04019 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
04020 VlmInfo->VirtualSize -= RegionSize;
04021
04022 status = STATUS_SUCCESS;
04023
04024 ErrorReturn:
04025
04026
UNLOCK_WS (Process);
04027
UNLOCK_ADDRESS_SPACE (Process);
04028
04029
KeDetachProcess();
04030
ObDereferenceObject (Process);
04031
04032
return status;
04033 }
04034
04035
04036
NTSTATUS
04037
NtProtectVirtualMemory64(
04038 IN HANDLE ProcessHandle,
04039 IN OUT PVOID64 *BaseAddress,
04040 IN OUT PULONGLONG RegionSize,
04041 IN ULONG NewProtect,
04042 OUT PULONG OldProtect
04043 )
04044
04045 {
04046
PEPROCESS Process;
04047
KPROCESSOR_MODE PreviousMode;
04048
NTSTATUS Status;
04049 LOGICAL Attached;
04050 PVOID64 CapturedBase;
04051 ULONGLONG CapturedRegionSize;
04052 ULONG ProtectionMask;
04053
PMMVAD FoundVad;
04054 PVOID64 StartingAddress;
04055 PVOID64 EndingAddress;
04056
PMMPTE PointerPte;
04057
PMMPTE LastPte;
04058
PMMPTE PointerPde;
04059
PMMPTE PointerProtoPte;
04060
PMMPTE LastProtoPte;
04061
PMMPFN Pfn1;
04062 ULONG CapturedOldProtect;
04063
MMPTE TempPte;
04064
MMPTE PteContents;
04065 PVOID64 Va;
04066 ULONG DoAgain;
04067 PMI_PROCESS_VLM_INFO VlmInfo;
04068
PMMPTE LowestPde;
04069
04070
PAGED_CODE();
04071
04072 Attached =
FALSE;
04073
04074
04075
04076
04077
04078
if ((NewProtect & PAGE_GUARD) ||
04079 (NewProtect & PAGE_NOCACHE)) {
04080
return STATUS_INVALID_PAGE_PROTECTION;
04081 }
04082
04083
try {
04084 ProtectionMask =
MiMakeProtectionMask (NewProtect);
04085 } except (EXCEPTION_EXECUTE_HANDLER) {
04086
return GetExceptionCode();
04087 }
04088
04089 PreviousMode = KeGetPreviousMode();
04090
04091
if (PreviousMode !=
KernelMode) {
04092
04093
04094
04095
04096
04097
try {
04098
04099
ProbeForWrite (BaseAddress,
sizeof(PVOID64),
sizeof(PVOID64));
04100
ProbeForWrite (RegionSize,
sizeof(ULONGLONG),
sizeof(ULONGLONG));
04101
ProbeForWriteUlong (OldProtect);
04102
04103
04104
04105
04106
04107 CapturedBase = *BaseAddress;
04108 CapturedRegionSize = *RegionSize;
04109
04110 } except (EXCEPTION_EXECUTE_HANDLER) {
04111
04112
04113
04114
04115
04116
04117
04118
return GetExceptionCode();
04119 }
04120
04121 }
else {
04122
04123
04124
04125
04126
04127 CapturedRegionSize = *RegionSize;
04128 CapturedBase = *BaseAddress;
04129 }
04130
04131
04132
04133
04134
04135
04136
if (CapturedBase > (PVOID64)MM_HIGHEST_USER_ADDRESS64) {
04137
04138
04139
04140
04141
04142
return STATUS_INVALID_PARAMETER_2;
04143 }
04144
04145
if ((ULONGLONG)MM_HIGHEST_USER_ADDRESS64 - (ULONGLONG)CapturedBase <
04146 CapturedRegionSize) {
04147
04148
04149
04150
04151
04152
return STATUS_INVALID_PARAMETER_3;
04153 }
04154
04155
if (CapturedRegionSize == 0) {
04156
return STATUS_INVALID_PARAMETER_3;
04157 }
04158
04159
Status =
ObReferenceObjectByHandle ( ProcessHandle,
04160 PROCESS_VM_OPERATION,
04161 PsProcessType,
04162 PreviousMode,
04163 (PVOID *)&Process,
04164 NULL );
04165
04166
if (!
NT_SUCCESS(Status)) {
04167
return Status;
04168 }
04169
04170
04171
04172
04173
04174
04175
if (
PsGetCurrentProcess() != Process) {
04176
KeAttachProcess (&Process->
Pcb);
04177 Attached =
TRUE;
04178 }
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
LOCK_WS_AND_ADDRESS_SPACE (Process);
04190
04191
04192
04193
04194
04195
if (Process->
AddressSpaceDeleted != 0) {
04196
Status = STATUS_PROCESS_IS_TERMINATING;
04197
goto ErrorFound;
04198 }
04199
04200 EndingAddress = (PVOID64)(((ULONGLONG)CapturedBase + CapturedRegionSize - 1) |
04201 (
PAGE_SIZE - 1));
04202 StartingAddress = (PVOID64)PAGE_ALIGN64(CapturedBase);
04203
04204 FoundVad = MiCheckForConflictingVad64 (StartingAddress, EndingAddress);
04205
04206
if (FoundVad ==
NULL) {
04207
04208
04209
04210
04211
04212
04213
Status = STATUS_CONFLICTING_ADDRESSES;
04214
goto ErrorFound;
04215 }
04216
04217
04218
04219
04220
04221
04222
if ((MI_VA_TO_VPN64 (StartingAddress) < FoundVad->
StartingVpn) ||
04223 (MI_VA_TO_VPN64 (EndingAddress) > FoundVad->
EndingVpn)) {
04224
04225
04226
04227
04228
04229
04230
Status = STATUS_CONFLICTING_ADDRESSES;
04231
goto ErrorFound;
04232 }
04233
04234
ASSERT (FoundVad->
u.VadFlags.PhysicalMapping == 0);
04235
ASSERT (FoundVad->
u.VadFlags.NoChange == 0);
04236
04237
if (FoundVad->
u.VadFlags.PrivateMemory == 0) {
04238
04239
04240
04241
04242
04243
04244
04245
if ((NewProtect & PAGE_NOCACHE) ||
04246 (ProtectionMask &
MM_COPY_ON_WRITE_MASK)) {
04247
04248
04249
04250
04251
04252
Status = STATUS_INVALID_PARAMETER_4;
04253
goto ErrorFound;
04254 }
04255
04256
04257
04258
04259
04260
04261
04262
04263
if ((FoundVad->
ControlArea->
u.Flags.File == 0) ||
04264 (FoundVad->
ControlArea->
u.Flags.Image == 1)) {
04265
04266 PointerProtoPte =
MiGetProtoPteAddress (FoundVad,
04267 MI_VA_TO_VPN64 (StartingAddress));
04268 LastProtoPte =
MiGetProtoPteAddress (FoundVad,
04269 MI_VA_TO_VPN64 (EndingAddress));
04270
04271
04272
04273
04274
04275
04276
04277
UNLOCK_WS (Process);
04278 ExAcquireFastMutex (&MmSectionCommitMutex);
04279
04280
while (PointerProtoPte <= LastProtoPte) {
04281
04282
04283
04284
04285
04286
04287
if (PointerProtoPte->
u.Long == 0) {
04288
04289
04290
04291
04292
04293 ExReleaseFastMutex (&MmSectionCommitMutex);
04294
Status = STATUS_NOT_COMMITTED;
04295
goto ErrorFoundNoWs;
04296 }
04297 PointerProtoPte += 1;
04298 }
04299
04300
04301
04302
04303
04304
04305 ExReleaseFastMutex (&MmSectionCommitMutex);
04306
04307
04308
04309
04310
04311
04312
LOCK_WS (Process);
04313 }
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323 PointerPde =
MiGetPdeAddress64 (StartingAddress);
04324 PointerPte =
MiGetPteAddress64 (StartingAddress);
04325 LastPte =
MiGetPteAddress64 (EndingAddress);
04326
04327
MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE);
04328
04329
04330
04331
04332
04333
if (PointerPte->
u.Long != 0) {
04334
04335 CapturedOldProtect = PAGE_READWRITE;
04336
if (PointerPte->
u.Hard.Valid == 1) {
04337
if (PointerPte->
u.Hard.Write == 0) {
04338 CapturedOldProtect = PAGE_READONLY;
04339 }
04340 }
else {
04341
ASSERT (PointerPte->
u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
04342
ASSERT (PointerPte->
u.Soft.Prototype == 1);
04343 CapturedOldProtect =
04344
MI_CONVERT_FROM_PTE_PROTECTION (PointerPte->
u.Soft.Protection);
04345 }
04346
04347 }
else {
04348
04349
04350
04351
04352
04353 CapturedOldProtect =
04354
MI_CONVERT_FROM_PTE_PROTECTION(FoundVad->
u.VadFlags.Protection);
04355 }
04356
04357 LowestPde =
MiGetPdeAddress64 (MM_LOWEST_USER_ADDRESS64);
04358 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
04359
04360
04361
04362
04363
04364
04365
while (PointerPte <= LastPte) {
04366
04367
if (
MiIsPteOnPdeBoundary(PointerPte)) {
04368
04369 PointerPde =
MiGetPteAddress (PointerPte);
04370
04371
MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE);
04372 }
04373
04374 PteContents = *PointerPte;
04375
04376
if (PteContents.
u.Hard.Valid == 1) {
04377
04378
if (ProtectionMask !=
MM_NOACCESS) {
04379
04380
04381
04382
04383
04384
04385 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
04386
04387
ASSERT (Pfn1->
u3.e1.PrototypePte == 1);
04388
04389
04390
04391
04392
04393
04394
04395
MI_MAKE_VALID_PTE (TempPte,
04396 PointerPte->u.Hard.PageFrameNumber,
04397 ProtectionMask,
04398 NULL);
04399
if (TempPte.
u.Hard.Write) {
04400
MI_SET_PTE_DIRTY (TempPte);
04401 }
04402
04403
04404
04405
04406
04407
04408
MiFlushTbAndCapture (PointerPte,
04409 TempPte.
u.Flush,
04410 Pfn1);
04411 }
else {
04412
04413
04414
04415
04416
04417 MiMakeValidPageNoAccess64 (PointerPte);
04418 }
04419
04420 }
else {
04421
04422
if (PointerPte->u.Long ==
ZeroPte.
u.Long) {
04423 *PointerPte =
PrototypePte;
04424 PointerPte->
u.Soft.Protection = ProtectionMask;
04425
04426 VlmInfo->UsedPageTableEntries[PointerPde - LowestPde] += 1;
04427
04428 }
else {
04429
ASSERT (PointerPte->u.Soft.Prototype == 1);
04430
ASSERT (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED);
04431 PointerPte->u.Soft.Protection = ProtectionMask;
04432 }
04433 }
04434 PointerPte += 1;
04435 }
04436
04437 }
else {
04438
04439
04440
04441
04442
04443
04444
if ((NewProtect & PAGE_WRITECOPY) ||
04445 (NewProtect & PAGE_EXECUTE_WRITECOPY)) {
04446
04447
04448
04449
04450
04451
Status = STATUS_INVALID_PARAMETER_4;
04452
goto ErrorFound;
04453 }
04454
04455
04456
04457
04458
04459
04460
if ( !MiIsEntireRangeCommitted64 (StartingAddress,
04461 EndingAddress,
04462 FoundVad,
04463 Process)) {
04464
04465
04466
04467
04468
04469
04470
Status = STATUS_NOT_COMMITTED;
04471
goto ErrorFound;
04472 }
04473
04474
04475
04476
04477
04478 PointerPde =
MiGetPdeAddress64 (StartingAddress);
04479 PointerPte =
MiGetPteAddress64 (StartingAddress);
04480 LastPte =
MiGetPteAddress64 (EndingAddress);
04481
04482
MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE);
04483
04484
04485
04486
04487
04488
if (PointerPte->
u.Long != 0) {
04489
04490 CapturedOldProtect =
MiGetPageProtection (PointerPte, Process);
04491
04492 }
else {
04493
04494
04495
04496
04497
04498 CapturedOldProtect =
04499
MI_CONVERT_FROM_PTE_PROTECTION(FoundVad->
u.VadFlags.Protection);
04500 }
04501
04502
04503
04504
04505
04506
04507
while (PointerPte <= LastPte) {
04508
04509
if (
MiIsPteOnPdeBoundary(PointerPte)) {
04510
04511 PointerPde =
MiGetPteAddress (PointerPte);
04512
04513
MiMakePdeExistAndMakeValid(PointerPde, Process, FALSE);
04514 }
04515
04516 PteContents = *PointerPte;
04517
04518
if (PteContents.
u.Hard.Valid == 1) {
04519
04520
if (ProtectionMask !=
MM_NOACCESS) {
04521
04522
04523
04524
04525
04526
04527 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
04528
04529 Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
04530
MI_MAKE_VALID_PTE (TempPte,
04531 PointerPte->u.Hard.PageFrameNumber,
04532 ProtectionMask,
04533 NULL);
04534
if (TempPte.
u.Hard.Write) {
04535
MI_SET_PTE_DIRTY (TempPte);
04536 }
04537
04538
04539
04540
04541
04542
04543
MiFlushTbAndCapture (PointerPte,
04544 TempPte.
u.Flush,
04545 Pfn1);
04546 }
else {
04547
04548
04549
04550
04551
04552 MiMakeValidPageNoAccess64 (PointerPte);
04553 }
04554 }
else {
04555
04556
04557
04558
04559
04560
if (PteContents.
u.Soft.Transition == 1) {
04561
04562
04563
04564
04565
04566
04567
04568
04569
if (ProtectionMask !=
MM_NOACCESS) {
04570 MiMakeNoAccessPageValid64 (PointerPte, ProtectionMask);
04571 }
04572
04573 }
else {
04574
04575
04576
04577
04578
04579 PointerPte->u.Soft.Protection = ProtectionMask;
04580
ASSERT (PointerPte->u.Long != 0);
04581 }
04582 }
04583 PointerPte += 1;
04584 }
04585 }
04586
04587
04588
04589
04590
04591 CapturedRegionSize = (
char * POINTER_64)EndingAddress - (
char * POINTER_64)StartingAddress + 1
L;
04592
04593
Status = STATUS_SUCCESS;
04594
04595 ErrorFound:
04596
04597
UNLOCK_WS (Process);
04598 ErrorFoundNoWs:
04599
04600
UNLOCK_ADDRESS_SPACE (Process);
04601
04602
if (Attached) {
04603
KeDetachProcess();
04604 }
04605
04606
ObDereferenceObject (Process);
04607
04608
04609
04610
04611
04612
04613
try {
04614
04615
04616
04617
04618
04619
04620
04621
04622
if (PreviousMode !=
KernelMode) {
04623
04624
ProbeForWrite (BaseAddress,
sizeof(PVOID64),
sizeof(PVOID64));
04625
ProbeForWrite (RegionSize,
sizeof(ULONGLONG),
sizeof(ULONGLONG));
04626
ProbeForWriteUlong (OldProtect);
04627 }
04628
04629 *RegionSize = CapturedRegionSize;
04630 *BaseAddress = StartingAddress;
04631 *OldProtect = CapturedOldProtect;
04632
04633 } except (EXCEPTION_EXECUTE_HANDLER) {
04634 NOTHING;
04635 }
04636
04637
return Status;
04638 }
04639
04640 ULONG
04641 MiIsEntireRangeCommitted64 (
04642 IN PVOID64 StartingAddress,
04643 IN PVOID64 EndingAddress,
04644 IN
PMMVAD Vad,
04645 IN
PEPROCESS Process
04646 )
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678 {
04679
PMMPTE PointerPte;
04680
PMMPTE LastPte;
04681
PMMPTE PointerPde;
04682 LOGICAL FirstTime;
04683 PVOID64 Va;
04684
04685
PAGED_CODE();
04686
04687 FirstTime =
TRUE;
04688
04689 PointerPde =
MiGetPdeAddress64 (StartingAddress);
04690 PointerPte =
MiGetPteAddress64 (StartingAddress);
04691 LastPte =
MiGetPteAddress64 (EndingAddress);
04692
04693
ASSERT (Vad->u.VadFlags.PrivateMemory == 1);
04694
04695 Va = StartingAddress;
04696
04697
while (PointerPte <= LastPte) {
04698
04699
if (
MiIsPteOnPdeBoundary(PointerPte) || FirstTime) {
04700
04701
04702
04703
04704
04705
04706 FirstTime =
FALSE;
04707 PointerPde =
MiGetPteAddress (PointerPte);
04708
04709
if (PointerPde->
u.Long == 0) {
04710
04711
04712
04713
04714
04715
04716
ASSERT (Vad->u.VadFlags.PrivateMemory == 1);
04717
return FALSE;
04718 }
04719
#if 0
04720
while (!
MiDoesPdeExistAndMakeValid(PointerPde, Process, FALSE)) {
04721
04722
04723
04724
04725
04726
04727 PointerPde += 1;
04728
04729 PointerPte =
MiGetVirtualAddressMappedByPte (PointerPde);
04730 Va =
MiGetVirtualAddressMappedByPte (PointerPte);
04731
04732
if (PointerPte > LastPte) {
04733
04734
04735
04736
04737
04738
if (Vad->u.VadFlags.MemCommit == 0) {
04739
04740
04741
04742
04743
04744
04745
return FALSE;
04746 }
else {
04747
return TRUE;
04748 }
04749 }
04750
04751
04752
04753
04754
04755
if (Vad->u.VadFlags.MemCommit == 0) {
04756
04757
04758
04759
04760
04761
04762
return FALSE;
04763 }
04764 }
04765
#endif //0
04766
}
04767
04768
04769
04770
04771
04772
if (PointerPte->
u.Long == 0) {
04773
04774
04775
04776
04777
04778
#if 0
04779
if (Vad->u.VadFlags.MemCommit == 0) {
04780
#endif
04781
04782
04783
04784
04785
04786
04787
return FALSE;
04788
#if 0
04789
}
04790
#endif
04791
}
else {
04792
04793
04794
04795
04796
04797
if (
MiIsPteDecommittedPage (PointerPte)) {
04798
04799
04800
04801
04802
04803
return FALSE;
04804 }
04805 }
04806 PointerPte += 1;
04807 Va = (PVOID64)((ULONGLONG)Va +
PAGE_SIZE);
04808 }
04809
return TRUE;
04810 }
04811
04812
04813
VOID
04814 MiMakeValidPageNoAccess64 (
04815 IN
PMMPTE PointerPte
04816 )
04817 {
04818
PMMPFN Pfn1;
04819
PMMPTE PointerPde;
04820
MMPTE PteContents;
04821 KIRQL OldIrql;
04822
MMPTE TempPte;
04823 ULONG_PTR Vpn;
04824
04825 Vpn = (ULONG_PTR)((ULONGLONG)
MiGetVirtualAddressMappedByPte64(PointerPte) >>
04826
PAGE_SHIFT);
04827
04828 TempPte =
PrototypePte;
04829 TempPte.
u.Soft.Protection =
MM_NOACCESS;
04830
04831 PointerPde =
MiGetPteAddress (PointerPte);
04832
LOCK_PFN (OldIrql);
04833
04834 PteContents = *PointerPte;
04835 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
04836
04837
if (Pfn1->
u3.e1.PrototypePte == 1) {
04838
04839
04840
04841
04842
04843
MI_CAPTURE_DIRTY_BIT_TO_PFN (&PteContents, Pfn1);
04844
04845
04846
04847
04848
04849
04850
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE(PointerPde));
04851
04852
04853
04854
04855
04856
MiDecrementShareCount (
MI_GET_PAGE_FRAME_FROM_PTE(&PteContents));
04857
04858 }
else {
04859
04860
04861
04862
04863
04864
04865
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
04866 Pfn1->
u3.e2.ReferenceCount += 1;
04867
MiDecrementShareCount (
MI_GET_PAGE_FRAME_FROM_PTE(&PteContents));
04868 TempPte = PteContents;
04869
MI_MAKE_VALID_PTE_TRANSITION (TempPte, MM_NOACCESS);
04870 }
04871
04872
KeFlushSingleTb64 (Vpn,
04873 TRUE,
04874 FALSE,
04875 (PHARDWARE_PTE)PointerPte,
04876 TempPte.
u.Flush);
04877
UNLOCK_PFN (OldIrql);
04878
return;
04879 }
04880
04881
VOID
04882 MiMakeNoAccessPageValid64 (
04883 IN
PMMPTE PointerPte,
04884 IN ULONG Protect
04885 )
04886
04887 {
04888
MMPTE PteContents;
04889
MMPTE TempPte;
04890 KIRQL OldIrql;
04891
PMMPFN Pfn1;
04892 PFN_NUMBER PageFrameIndex;
04893
04894
LOCK_PFN (OldIrql);
04895 PteContents = *PointerPte;
04896 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE(&PteContents);
04897 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
04898
MI_MAKE_VALID_PTE (TempPte,
04899 PageFrameIndex,
04900 Protect,
04901 NULL);
04902
if (TempPte.
u.Hard.Write) {
04903
MI_SET_PTE_DIRTY (TempPte);
04904 }
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
ASSERT (Pfn1->
u3.e2.ReferenceCount != 0);
04921 Pfn1->
u2.ShareCount += 1;
04922 *PointerPte = TempPte;
04923
UNLOCK_PFN (OldIrql);
04924
return;
04925 }
04926
04927
NTSTATUS
04928 MiGetVlmInfo (
04929 IN PMEMORY_VLM_COUNTERS VlmUserInfo
04930 )
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952 {
04953
PMMPTE PointerPte;
04954
PEPROCESS TargetProcess;
04955 PMI_PROCESS_VLM_INFO VlmInfo;
04956
04957 RtlZeroMemory (VlmUserInfo,
sizeof (*VlmUserInfo));
04958
04959 VlmUserInfo->SystemCommitCharge = MiVlmCommitChargeInPages;
04960 VlmUserInfo->SystemPeakCommitCharge = MiVlmCommitChargeInPagesPeak;
04961 VlmUserInfo->SystemSharedCommitCharge = MmSharedCommitVlm;
04962 VlmUserInfo->VirtualSizeAvailable =
04963 MM_HIGHEST_USER_ADDRESS64 - MM_LOWEST_USER_ADDRESS64 + 1;
04964
04965
04966 TargetProcess =
PsGetCurrentProcess();
04967
04968
LOCK_WS (TargetProcess);
04969
04970
if (TargetProcess->
AddressSpaceDeleted != 0) {
04971
UNLOCK_WS (TargetProcess);
04972
return STATUS_PROCESS_IS_TERMINATING;
04973 }
04974
04975 PointerPte =
MiGetPteAddress (PDE_BASE64);
04976
04977
if (PointerPte->
u.Long != 0) {
04978
04979
ASSERT (PointerPte->
u.Hard.Valid == 1);
04980
04981 VlmInfo = (PMI_PROCESS_VLM_INFO) (((
PMMPTE)
PDE_BASE64)->u.Long);
04982
04983 VlmUserInfo->VirtualSize = VlmInfo->VirtualSize;
04984 VlmUserInfo->PeakVirtualSize = VlmInfo->VirtualSizePeak;
04985
04986 VlmUserInfo->VirtualSizeAvailable -= VlmInfo->VirtualSize;
04987
04988 VlmUserInfo->CommitCharge = VlmInfo->CommitCharge;
04989 VlmUserInfo->PeakCommitCharge = VlmInfo->CommitChargePeak;
04990 }
04991
04992
UNLOCK_WS (TargetProcess);
04993
04994
return STATUS_SUCCESS;
04995 }
04996
04997
NTSTATUS
04998
NtQueryVirtualMemory64(
04999 IN HANDLE ProcessHandle,
05000 IN PVOID64 *pBaseAddress,
05001 IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
05002 OUT PVOID MemoryInformation,
05003 IN ULONG MemoryInformationLength,
05004 OUT PULONG ReturnLength OPTIONAL
05005 )
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088
05089
05090
05091
05092
05093
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118
05119
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139 {
05140
KPROCESSOR_MODE PreviousMode;
05141
PEPROCESS TargetProcess;
05142
NTSTATUS Status;
05143
PMMVAD Vad;
05144 PVOID64 Va;
05145 BOOLEAN Found =
FALSE;
05146 ULONGLONG TheRegionSize;
05147 ULONG NewProtect;
05148 ULONG NewState;
05149 ULONG_PTR BaseVpn;
05150 PVOID64 BaseAddress;
05151
05152 MEMORY_BASIC_INFORMATION_VLM Info;
05153
05154
if (MI_VLM_ENABLED() ==
FALSE) {
05155
return STATUS_NOT_IMPLEMENTED;
05156 }
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
switch (MemoryInformationClass) {
05167
case MemoryBasicInformation:
05168
if (MemoryInformationLength <
sizeof(MEMORY_BASIC_INFORMATION_VLM)) {
05169
return STATUS_INFO_LENGTH_MISMATCH;
05170 }
05171
break;
05172
05173
default:
05174
return STATUS_INVALID_INFO_CLASS;
05175 }
05176
05177 PreviousMode = KeGetPreviousMode();
05178
05179
if (PreviousMode !=
KernelMode) {
05180
05181
05182
05183
05184
05185
try {
05186
ProbeForRead(pBaseAddress,
sizeof(PVOID64),
sizeof(ULONG));
05187 BaseAddress = *pBaseAddress;
05188
05189
ProbeForWrite(MemoryInformation,
05190 MemoryInformationLength,
05191
sizeof(ULONGLONG));
05192
05193
if (ARGUMENT_PRESENT(ReturnLength)) {
05194
ProbeForWriteUlong(ReturnLength);
05195 }
05196
05197 } except (EXCEPTION_EXECUTE_HANDLER) {
05198
05199
05200
05201
05202
05203
05204
05205
return GetExceptionCode();
05206 }
05207 }
else {
05208 BaseAddress = *pBaseAddress;
05209 }
05210
05211
if (BaseAddress == (PVOID64)
NULL) {
05212 BaseAddress = (PVOID64)MM_LOWEST_USER_ADDRESS64;
05213 }
05214
05215
if ((BaseAddress > (PVOID64)MM_HIGHEST_USER_ADDRESS64) ||
05216 (BaseAddress < (PVOID64)MM_LOWEST_USER_ADDRESS64)) {
05217
return STATUS_INVALID_PARAMETER;
05218 }
05219
05220
if ( ProcessHandle == NtCurrentProcess() ) {
05221 TargetProcess =
PsGetCurrentProcess();
05222 }
else {
05223
Status =
ObReferenceObjectByHandle ( ProcessHandle,
05224 PROCESS_QUERY_INFORMATION,
05225 PsProcessType,
05226 PreviousMode,
05227 (PVOID *)&TargetProcess,
05228 NULL );
05229
05230
if (!
NT_SUCCESS(Status)) {
05231
return Status;
05232 }
05233 }
05234
05235
05236
05237
05238
05239
05240
KeAttachProcess (&TargetProcess->
Pcb);
05241
05242
05243
05244
05245
05246
LOCK_WS_AND_ADDRESS_SPACE (TargetProcess);
05247
05248
05249
05250
05251
05252
if (TargetProcess->
AddressSpaceDeleted != 0) {
05253
UNLOCK_WS (TargetProcess);
05254
UNLOCK_ADDRESS_SPACE (TargetProcess);
05255
KeDetachProcess();
05256
if ( ProcessHandle != NtCurrentProcess() ) {
05257
ObDereferenceObject (TargetProcess);
05258 }
05259
return STATUS_PROCESS_IS_TERMINATING;
05260 }
05261
05262
if (TargetProcess->
ForkWasSuccessful != MM_NO_FORK_ALLOWED) {
05263 Vad =
NULL;
05264 }
else {
05265 Vad = TargetProcess->
CloneRoot;
05266 }
05267
05268
05269
05270
05271
05272
05273 BaseVpn = MI_VA_TO_VPN64 (BaseAddress);
05274
05275
for (;;) {
05276
05277
if (Vad == (
PMMVAD)
NULL) {
05278
break;
05279 }
05280
05281
if ((BaseVpn >= Vad->
StartingVpn) &&
05282 (BaseVpn <= Vad->
EndingVpn)) {
05283 Found =
TRUE;
05284
break;
05285 }
05286
05287
if (BaseVpn < Vad->
StartingVpn) {
05288
if (Vad->
LeftChild == (
PMMVAD)
NULL) {
05289
break;
05290 }
05291 Vad = Vad->
LeftChild;
05292
05293 }
else {
05294
if (BaseVpn < Vad->
EndingVpn) {
05295
break;
05296 }
05297
if (Vad->
RightChild == (
PMMVAD)
NULL) {
05298
break;
05299 }
05300 Vad = Vad->
RightChild;
05301 }
05302 }
05303
05304
if (!Found) {
05305
05306
05307
05308
05309
05310
05311
05312
if (Vad ==
NULL) {
05313 TheRegionSize = MM_LARGEST_VLM_RANGE + 1;
05314 }
else {
05315
if (Vad->
StartingVpn < BaseVpn) {
05316
05317
05318
05319
05320
05321
05322 Vad =
MiGetNextVad (Vad);
05323
if (Vad ==
NULL) {
05324 TheRegionSize = (ULONGLONG)
MM_HIGHEST_VAD_ADDRESS64 -
05325 (ULONGLONG)PAGE_ALIGN64(BaseAddress);
05326 }
else {
05327 TheRegionSize = (ULONGLONG)MI_VPN_TO_VA64 (Vad->
StartingVpn) -
05328 (ULONGLONG)PAGE_ALIGN64(BaseAddress);
05329 }
05330 }
else {
05331 TheRegionSize = (ULONGLONG)MI_VPN_TO_VA64 (Vad->
StartingVpn) -
05332 (ULONGLONG)PAGE_ALIGN64(BaseAddress);
05333 }
05334 }
05335
05336
UNLOCK_WS (TargetProcess);
05337
UNLOCK_ADDRESS_SPACE (TargetProcess);
05338
KeDetachProcess();
05339
05340
if (ProcessHandle != NtCurrentProcess()) {
05341
ObDereferenceObject (TargetProcess);
05342 }
05343
05344
05345
05346
05347
05348
05349
if (MemoryInformationClass == MemoryBasicInformation) {
05350
try {
05351
05352 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->AllocationBase =
05353 (PVOID64)MM_LOWEST_USER_ADDRESS64;
05354 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->AllocationProtect =
05355 0;
05356 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->BaseAddressAsUlongLong =
05357 (ULONGLONG)PAGE_ALIGN64(BaseAddress);
05358 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->RegionSize =
05359 TheRegionSize;
05360 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->State = MEM_FREE;
05361 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->Protect = PAGE_NOACCESS;
05362 ((PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation)->Type = 0;
05363
05364
if (ARGUMENT_PRESENT(ReturnLength)) {
05365 *ReturnLength =
sizeof(MEMORY_BASIC_INFORMATION_VLM);
05366 }
05367
05368 } except (EXCEPTION_EXECUTE_HANDLER) {
05369
05370
05371
05372
05373 }
05374
05375
return STATUS_SUCCESS;
05376 }
05377
return STATUS_INVALID_ADDRESS;
05378 }
05379
05380
05381
05382
05383
05384 Va = PAGE_ALIGN64(BaseAddress);
05385 Info.BaseAddress = Va;
05386
05387
05388
05389
05390
05391
05392
if (Vad->
u.VadFlags.PrivateMemory) {
05393 Info.Type = MEM_PRIVATE;
05394 }
else {
05395 Info.Type = MEM_MAPPED;
05396 }
05397
05398 Info.State = MiQueryAddressState64 (Va, Vad, TargetProcess, &Info.Protect);
05399
05400 Va = (PVOID64)((ULONGLONG)Va +
PAGE_SIZE);
05401
05402
while (MI_VA_TO_VPN64 (Va) <= Vad->
EndingVpn) {
05403
05404 NewState = MiQueryAddressState64 (Va,
05405 Vad,
05406 TargetProcess,
05407 &NewProtect);
05408
05409
if ((NewState != Info.State) || (NewProtect != Info.Protect)) {
05410
05411
05412
05413
05414
05415
05416
break;
05417 }
05418 Va = (PVOID64)((ULONGLONG)Va +
PAGE_SIZE);
05419 }
05420
05421 Info.RegionSize = ((ULONGLONG)Va - (ULONGLONG)Info.BaseAddress);
05422 Info.AllocationBase = MI_VPN_TO_VA64 (Vad->
StartingVpn);
05423 Info.AllocationProtect =
MI_CONVERT_FROM_PTE_PROTECTION (
05424 Vad->
u.VadFlags.Protection);
05425
05426
05427
05428
05429
05430
05431
UNLOCK_WS (TargetProcess);
05432
UNLOCK_ADDRESS_SPACE (TargetProcess);
05433
KeDetachProcess();
05434
05435
if ( ProcessHandle != NtCurrentProcess() ) {
05436
ObDereferenceObject (TargetProcess);
05437 }
05438
05439
05440
if ( MemoryInformationClass == MemoryBasicInformation ) {
05441
try {
05442
05443 *(PMEMORY_BASIC_INFORMATION_VLM)MemoryInformation = Info;
05444
05445
if (ARGUMENT_PRESENT(ReturnLength)) {
05446 *ReturnLength =
sizeof(MEMORY_BASIC_INFORMATION_VLM);
05447 }
05448
05449 } except (EXCEPTION_EXECUTE_HANDLER) {
05450 NOTHING;
05451 }
05452
return STATUS_SUCCESS;
05453 }
05454
return Status;
05455 }
05456
05457
05458
05459 ULONG
05460 MiQueryAddressState64 (
05461 IN PVOID64 Va,
05462 IN
PMMVAD Vad,
05463 IN
PEPROCESS TargetProcess,
05464 OUT PULONG ReturnedProtect
05465 )
05466
05467
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477
05478
05479
05480
05481
05482
05483
05484 {
05485
PMMPTE PointerPte;
05486
PMMPTE PointerPde;
05487
MMPTE CapturedProtoPte;
05488
PMMPTE ProtoPte;
05489 LOGICAL PteIsZero;
05490 ULONG State;
05491 ULONG Protect;
05492 ULONG VadProtect;
05493
05494 VadProtect =
MI_CONVERT_FROM_PTE_PROTECTION (Vad->u.VadFlags.Protection);
05495
#ifdef LARGE_PAGES
05496
if (Vad->u.VadFlags.LargePages) {
05497 *ReturnedProtect = VadProtect;
05498
return MEM_COMMIT;
05499 }
05500
#endif //LARGE_PAGES
05501
05502 PointerPde =
MiGetPdeAddress64 (Va);
05503 PointerPte =
MiGetPteAddress64 (Va);
05504
05505
ASSERT ((Vad->StartingVpn <= MI_VA_TO_VPN64 (Va)) &&
05506 (Vad->EndingVpn >= MI_VA_TO_VPN64 (Va)));
05507
05508 PteIsZero =
TRUE;
05509
05510
05511
05512
05513
05514
if (
MmIsAddressValid (PointerPde) &&
MmIsAddressValid(PointerPte)) {
05515
05516
05517
05518
05519
05520
if (PointerPte->
u.Long != 0) {
05521
05522 PteIsZero =
FALSE;
05523
05524
05525
05526
05527
05528
05529
if (
MiIsPteDecommittedPage (PointerPte)) {
05530 Protect = 0;
05531 State = MEM_RESERVE;
05532 }
else {
05533
05534 State = MEM_COMMIT;
05535
05536 Protect = PAGE_READWRITE;
05537
if (PointerPte->
u.Hard.Valid == 1) {
05538
if (PointerPte->
u.Hard.Write == 0) {
05539 Protect = PAGE_READONLY;
05540 }
05541 }
else if (PointerPte->
u.Soft.Prototype) {
05542 Protect = VadProtect;
05543
05544
if (PointerPte->
u.Soft.PageFileHigh ==
MI_PTE_LOOKUP_NEEDED) {
05545 Protect =
MI_CONVERT_FROM_PTE_PROTECTION (PointerPte->
u.Soft.Protection);
05546 }
05547
05548 ProtoPte =
MiGetProtoPteAddress(Vad,
05549 MI_VA_TO_VPN64 (Va));
05550 CapturedProtoPte.
u.Long = 0;
05551
if (ProtoPte) {
05552 CapturedProtoPte =
MiCaptureSystemPte (ProtoPte,
05553 TargetProcess);
05554 }
05555
if (CapturedProtoPte.
u.Long == 0) {
05556 State = MEM_RESERVE;
05557 Protect = 0;
05558 }
05559
05560 }
else {
05561 Protect =
MI_CONVERT_FROM_PTE_PROTECTION (PointerPte->
u.Soft.Protection);
05562 }
05563 }
05564 }
05565 }
05566
05567
if (PteIsZero ==
TRUE) {
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580 State = MEM_RESERVE;
05581 Protect = 0;
05582
05583
if ((Vad->u.VadFlags.PrivateMemory == 0) &&
05584 (Vad->ControlArea != (
PCONTROL_AREA)
NULL)) {
05585
05586
05587
05588
05589
05590
05591 ProtoPte =
MiGetProtoPteAddress(Vad, MI_VA_TO_VPN64 (Va));
05592
05593 CapturedProtoPte.
u.Long = 0;
05594
if (ProtoPte) {
05595 CapturedProtoPte =
MiCaptureSystemPte (ProtoPte,
05596 TargetProcess);
05597 }
05598
05599
if (CapturedProtoPte.
u.Long != 0) {
05600 State = MEM_COMMIT;
05601 Protect = VadProtect;
05602 }
05603
05604 }
else {
05605
05606
05607
05608
05609
05610
if (Vad->u.VadFlags.MemCommit) {
05611 State = MEM_COMMIT;
05612 Protect = VadProtect;
05613 }
05614 }
05615 }
05616
05617 *ReturnedProtect = Protect;
05618
return State;
05619 }
05620
05621
05622
#else
05623
05624
NTSTATUS
05625 NtAllocateVirtualMemory64 (
05626 IN HANDLE ProcessHandle,
05627 IN OUT PVOID64 *BaseAddress,
05628 IN ULONG ZeroBits,
05629 IN OUT PULONGLONG RegionSize,
05630 IN ULONG AllocationType,
05631 IN ULONG Protect
05632 )
05633 {
05634
return STATUS_NOT_IMPLEMENTED;
05635 }
05636
05637
NTSTATUS
05638 NtFreeVirtualMemory64(
05639 IN HANDLE ProcessHandle,
05640 IN OUT PVOID64 *BaseAddress,
05641 IN OUT PULONGLONG RegionSize,
05642 IN ULONG FreeType
05643 )
05644 {
05645
return STATUS_NOT_IMPLEMENTED;
05646 }
05647
05648
NTSTATUS
05649 NtMapViewOfVlmSection (
05650 IN HANDLE SectionHandle,
05651 IN HANDLE ProcessHandle,
05652 IN OUT PVOID64 *BaseAddress,
05653 IN OUT PULONGLONG SectionOffset OPTIONAL,
05654 IN OUT PULONGLONG ViewSize,
05655 IN ULONG AllocationType,
05656 IN ULONG Protect
05657 )
05658 {
05659
return STATUS_NOT_IMPLEMENTED;
05660 }
05661
05662
NTSTATUS
05663 NtUnmapViewOfVlmSection(
05664 IN HANDLE ProcessHandle,
05665 IN OUT PVOID64 *BaseAddress
05666 )
05667 {
05668
return STATUS_NOT_IMPLEMENTED;
05669 }
05670
05671
NTSTATUS
05672 NtQueryVirtualMemory64(
05673 IN HANDLE ProcessHandle,
05674 IN PVOID64 *pBaseAddress,
05675 IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
05676 OUT PVOID MemoryInformation,
05677 IN ULONG MemoryInformationLength,
05678 OUT PULONG ReturnLength OPTIONAL
05679 )
05680 {
05681
return STATUS_NOT_IMPLEMENTED;
05682 }
05683
05684
NTSTATUS
05685 NtProtectVirtualMemory64(
05686 IN HANDLE ProcessHandle,
05687 IN OUT PVOID64 *BaseAddress,
05688 IN OUT PULONGLONG RegionSize,
05689 IN ULONG NewProtect,
05690 OUT PULONG OldProtect
05691 )
05692
05693 {
05694
return STATUS_NOT_IMPLEMENTED;
05695 }
05696
05697
#endif //VLM_SUPPORT