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
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 typedef struct _SESSIONWIDE_DRIVER_ADDRESS {
00043 LIST_ENTRY
Link;
00044 ULONG
ReferenceCount;
00045 PVOID
Address;
00046 ULONG_PTR
Size;
00047 ULONG_PTR
WritablePages;
00048 UNICODE_STRING
FullDllName;
00049 }
SESSIONWIDE_DRIVER_ADDRESS, *
PSESSIONWIDE_DRIVER_ADDRESS;
00050
00051 LIST_ENTRY
MmSessionWideAddressList;
00052
00053
00054
00055
00056
00057 extern KSPIN_LOCK
PsLoadedModuleSpinLock;
00058
00059 extern LIST_ENTRY
PsLoadedModuleList;
00060
00061
00062
00063
00064
00065 ULONG
00066
MiSetProtectionOnTransitionPte (
00067 IN
PMMPTE PointerPte,
00068 IN ULONG ProtectionMask
00069 );
00070
00071
NTSTATUS
00072
MiSessionInsertImage(
00073 IN PVOID BaseAddress
00074 );
00075
00076
NTSTATUS
00077
MiSessionRemoveImage(
00078 IN PVOID BaseAddress
00079 );
00080
00081
NTSTATUS
00082
MiSessionWideInsertImageAddress (
00083 IN PVOID BaseAddress,
00084 IN ULONG_PTR Size,
00085 IN ULONG WritablePages,
00086 IN PUNICODE_STRING ImageName,
00087 IN BOOLEAN AtPreferredAddress
00088 );
00089
00090
NTSTATUS
00091
MiSessionWideDereferenceImage(
00092 IN PVOID BaseAddress
00093 );
00094
00095 PLDR_DATA_TABLE_ENTRY
00096
MiLookupPsLoadedModule (
00097 IN PVOID Address
00098 );
00099
00100
#ifdef ALLOC_PRAGMA
00101
#pragma alloc_text(INIT, MiSessionWideInitializeAddresses)
00102
00103
#pragma alloc_text(PAGEHYDRA, MiSessionWideInsertImageAddress)
00104
#pragma alloc_text(PAGEHYDRA, MiSessionWideReserveImageAddress)
00105
#pragma alloc_text(PAGEHYDRA, MiSessionWideDereferenceImage)
00106
#pragma alloc_text(PAGEHYDRA, MiSessionWideGetImageSize)
00107
#pragma alloc_text(PAGEHYDRA, MiRemoveImageSessionWide)
00108
#pragma alloc_text(PAGEHYDRA, MiLookupPsLoadedModule)
00109
#pragma alloc_text(PAGEHYDRA, MiShareSessionImage)
00110
00111
#pragma alloc_text(PAGEHYDRA, MiSessionInsertImage)
00112
#pragma alloc_text(PAGEHYDRA, MiSessionRemoveImage)
00113
#pragma alloc_text(PAGEHYDRA, MiSessionLookupImage)
00114
#pragma alloc_text(PAGEHYDRA, MiSessionUnloadAllImages)
00115
#endif
00116
00117
00118
NTSTATUS
00119 MiShareSessionImage (
00120 IN PSECTION Section,
00121 IN OUT PSIZE_T ViewSize
00122 )
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 {
00149 KIRQL WsIrql;
00150 KIRQL OldIrql;
00151
PSUBSECTION Subsection;
00152
PCONTROL_AREA ControlArea;
00153 ULONG NumberOfPtes;
00154
PMMPTE StartPte;
00155
PMMPTE EndPte;
00156 PVOID AllocationStart;
00157 SIZE_T AllocationSize;
00158
NTSTATUS Status;
00159 BOOLEAN FirstMapped;
00160 PVOID MappedBase;
00161 SIZE_T CommittedPages;
00162
PIMAGE_ENTRY_IN_SESSION DriverImage;
00163
00164
PAGED_CODE();
00165
00166
SYSLOAD_LOCK_OWNED_BY_ME ();
00167
00168
if (*ViewSize == 0) {
00169
return STATUS_SUCCESS;
00170 }
00171
00172
ASSERT (
MmIsAddressValid (
MmSessionSpace) ==
TRUE);
00173
00174 MappedBase = Section->Segment->BasedAddress;
00175
00176
ASSERT (((ULONG_PTR)MappedBase %
PAGE_SIZE) == 0);
00177
ASSERT ((*ViewSize %
PAGE_SIZE) == 0);
00178
00179
MmLockPagableSectionByHandle (
ExPageLockHandle);
00180
00181
LOCK_SESSION_SPACE_WS (WsIrql);
00182
00183
00184
00185
00186
00187
00188
00189 ControlArea = Section->
Segment->
ControlArea;
00190
00191
ASSERT (ControlArea->
u.Flags.GlobalOnlyPerSession == 0);
00192
00193 Subsection = (
PSUBSECTION)(ControlArea + 1);
00194
00195
if (
MiCheckPurgeAndUpMapCount (ControlArea) ==
FALSE) {
00196
UNLOCK_SESSION_SPACE_WS(WsIrql);
00197
MmUnlockPagableImageSection(
ExPageLockHandle);
00198
return STATUS_INSUFFICIENT_RESOURCES;
00199 }
00200
00201
if (*ViewSize == 0) {
00202
00203 *ViewSize = Section->SizeOfSection.LowPart;
00204
00205 }
00206
else if (*ViewSize > Section->SizeOfSection.LowPart) {
00207
00208
00209
00210
00211
00212
UNLOCK_SESSION_SPACE_WS(WsIrql);
00213
LOCK_PFN (OldIrql);
00214 ControlArea->
NumberOfMappedViews -= 1;
00215 ControlArea->
NumberOfUserReferences -= 1;
00216
00217
00218
00219
00220
00221
00222
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00223
00224
MmUnlockPagableImageSection(
ExPageLockHandle);
00225
return STATUS_INVALID_VIEW_SIZE;
00226 }
00227
00228 AllocationStart = MappedBase;
00229
00230 AllocationSize = *ViewSize;
00231
00232
00233
00234
00235
00236 StartPte =
MiGetPteAddress (AllocationStart);
00237
00238 EndPte =
MiGetPteAddress ((PCHAR)AllocationStart + AllocationSize);
00239
00240 NumberOfPtes =
BYTES_TO_PAGES (AllocationSize);
00241
00242
Status =
MiSessionWideGetImageSize (MappedBase,
00243
NULL,
00244 &CommittedPages);
00245
00246
if (!
NT_SUCCESS(
Status)) {
00247 CommittedPages = NumberOfPtes;
00248 }
00249
00250
Status = STATUS_SUCCESS;
00251
00252
if (
MiChargeCommitment (CommittedPages,
NULL) ==
FALSE) {
00253
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_COMMIT);
00254
Status = STATUS_NO_MEMORY;
00255 }
00256
00257
if (!
NT_SUCCESS(
Status)) {
00258
00259
00260
00261
00262
00263
00264
00265
UNLOCK_SESSION_SPACE_WS(WsIrql);
00266
00267
LOCK_PFN (OldIrql);
00268 ControlArea->
NumberOfMappedViews -= 1;
00269 ControlArea->
NumberOfUserReferences -= 1;
00270
00271
00272
00273
00274
00275
00276
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00277
00278
MmUnlockPagableImageSection(
ExPageLockHandle);
00279
return STATUS_NO_MEMORY;
00280 }
00281
00282
MmSessionSpace->
CommittedPages += CommittedPages;
00283
00284
00285
00286
00287
00288
00289
Status =
MiSessionCommitPageTables (AllocationStart,
00290 (PVOID)((PCHAR)AllocationStart + AllocationSize));
00291
00292
if (!
NT_SUCCESS(
Status)) {
00293
00294
MmSessionSpace->
CommittedPages -= CommittedPages;
00295
UNLOCK_SESSION_SPACE_WS (WsIrql);
00296
00297
LOCK_PFN (OldIrql);
00298 ControlArea->
NumberOfMappedViews -= 1;
00299 ControlArea->
NumberOfUserReferences -= 1;
00300
00301
00302
00303
00304
00305
00306
MiCheckControlArea (ControlArea,
NULL, OldIrql);
00307
00308
MmUnlockPagableImageSection (
ExPageLockHandle);
00309
MiReturnCommitment (CommittedPages);
00310
00311
return STATUS_NO_MEMORY;
00312 }
00313
00314
MM_TRACK_COMMIT (
MM_DBG_COMMIT_SESSION_SHARED_IMAGE, CommittedPages);
00315
00316
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_SYSMAPPED_PAGES_COMMITTED, CommittedPages);
00317
00318
MM_BUMP_SESS_COUNTER (
MM_DBG_SESSION_SYSMAPPED_PAGES_ALLOC, NumberOfPtes);
00319
00320
#if DBG
00321
while (StartPte < EndPte) {
00322
ASSERT (StartPte->
u.Long == 0);
00323 StartPte += 1;
00324 }
00325 StartPte =
MiGetPteAddress (AllocationStart);
00326
#endif
00327
00328
00329
00330
00331
00332
if (Section->u.Flags.Image) {
00333
00334 FirstMapped =
FALSE;
00335
00336
LOCK_PFN (OldIrql);
00337
if (ControlArea->
u.Flags.ImageMappedInSystemSpace == 0) {
00338 FirstMapped =
TRUE;
00339 ControlArea->
u.Flags.ImageMappedInSystemSpace = 1;
00340 }
00341
UNLOCK_PFN (OldIrql);
00342
00343
00344
00345
00346
00347
00348
if (FirstMapped ==
TRUE) {
00349
MiSetImageProtect (Section->Segment,
MM_EXECUTE_READ);
00350 }
00351 }
00352
00353
00354
00355
00356
00357
MiAddMappedPtes (StartPte,
00358 NumberOfPtes,
00359 ControlArea);
00360
00361
UNLOCK_SESSION_SPACE_WS(WsIrql);
00362
00363
00364
00365
00366
00367
00368 DriverImage =
MiSessionLookupImage (AllocationStart);
00369
ASSERT (DriverImage);
00370
00371 DriverImage->
LastAddress = (PVOID)((PCHAR)AllocationStart + AllocationSize - 1);
00372 DriverImage->
PrototypePtes = Section->Segment->PrototypePte;
00373
00374
MmUnlockPagableImageSection(
ExPageLockHandle);
00375
00376
return STATUS_SUCCESS;
00377 }
00378
00379
00380
NTSTATUS
00381 MiSessionInsertImage(
00382 IN PVOID BaseAddress
00383 )
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 {
00407 PLIST_ENTRY NextEntry;
00408
PIMAGE_ENTRY_IN_SESSION Image;
00409 KIRQL OldIrql;
00410
00411
PAGED_CODE();
00412
00413
SYSLOAD_LOCK_OWNED_BY_ME ();
00414
00415
00416
00417
00418
00419
LOCK_SESSION_SPACE_WS (OldIrql);
00420
00421 NextEntry =
MmSessionSpace->
ImageList.Flink;
00422
00423
while (NextEntry != &
MmSessionSpace->
ImageList) {
00424 Image = CONTAINING_RECORD (NextEntry,
IMAGE_ENTRY_IN_SESSION, Link);
00425
00426
if (Image->
Address == BaseAddress) {
00427 Image->
ImageCountInThisSession += 1;
00428
UNLOCK_SESSION_SPACE_WS (OldIrql);
00429
return STATUS_ALREADY_COMMITTED;
00430 }
00431 NextEntry = NextEntry->Flink;
00432 }
00433
00434
00435
00436
00437
00438 Image =
ExAllocatePoolWithTag (
NonPagedPool,
00439
sizeof(
IMAGE_ENTRY_IN_SESSION),
00440 'iHmM');
00441
00442
if (Image ==
NULL) {
00443
UNLOCK_SESSION_SPACE_WS (OldIrql);
00444
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_NONPAGED_POOL);
00445
return STATUS_NO_MEMORY;
00446 }
00447
00448 RtlZeroMemory (Image,
sizeof(
IMAGE_ENTRY_IN_SESSION));
00449
00450 Image->
Address = BaseAddress;
00451 Image->
ImageCountInThisSession = 1;
00452
00453 InsertTailList (&
MmSessionSpace->
ImageList, &Image->
Link);
00454
00455
UNLOCK_SESSION_SPACE_WS (OldIrql);
00456
return STATUS_SUCCESS;
00457 }
00458
00459
00460
NTSTATUS
00461 MiSessionRemoveImage(
00462 PVOID BaseAddr
00463 )
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 {
00487 PLIST_ENTRY NextEntry;
00488
PIMAGE_ENTRY_IN_SESSION Image;
00489 KIRQL OldIrql;
00490
00491
PAGED_CODE();
00492
00493
SYSLOAD_LOCK_OWNED_BY_ME ();
00494
00495
LOCK_SESSION_SPACE_WS (OldIrql);
00496 NextEntry =
MmSessionSpace->
ImageList.Flink;
00497
00498
while (NextEntry != &
MmSessionSpace->
ImageList) {
00499
00500 Image = CONTAINING_RECORD(NextEntry,
IMAGE_ENTRY_IN_SESSION, Link);
00501
00502
if (Image->
Address == BaseAddr) {
00503 RemoveEntryList (NextEntry);
00504
UNLOCK_SESSION_SPACE_WS (OldIrql);
00505
ExFreePool (Image);
00506
return STATUS_SUCCESS;
00507 }
00508
00509 NextEntry = NextEntry->Flink;
00510 }
00511
00512
UNLOCK_SESSION_SPACE_WS (OldIrql);
00513
return STATUS_NOT_FOUND;
00514 }
00515
00516
00517
PIMAGE_ENTRY_IN_SESSION
00518 MiSessionLookupImage (
00519 IN PVOID BaseAddress
00520 )
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 {
00544 PLIST_ENTRY NextEntry;
00545
PIMAGE_ENTRY_IN_SESSION Image;
00546 KIRQL OldIrql;
00547
00548
SYSLOAD_LOCK_OWNED_BY_ME ();
00549
00550
LOCK_SESSION_SPACE_WS (OldIrql);
00551
00552 NextEntry =
MmSessionSpace->
ImageList.Flink;
00553
00554
while (NextEntry != &
MmSessionSpace->
ImageList) {
00555
00556 Image = CONTAINING_RECORD(NextEntry,
IMAGE_ENTRY_IN_SESSION, Link);
00557
00558
if (Image->
Address == BaseAddress) {
00559
UNLOCK_SESSION_SPACE_WS (OldIrql);
00560
return Image;
00561 }
00562
00563 NextEntry = NextEntry->Flink;
00564 }
00565
00566
UNLOCK_SESSION_SPACE_WS (OldIrql);
00567
return NULL;
00568 }
00569
00570
00571
VOID
00572 MiSessionUnloadAllImages (
00573 VOID
00574 )
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 {
00611
NTSTATUS Status;
00612 PLIST_ENTRY NextEntry;
00613
PIMAGE_ENTRY_IN_SESSION Module;
00614 PLDR_DATA_TABLE_ENTRY ImageHandle;
00615
00616
ASSERT (
MmSessionSpace->
ReferenceCount == 1);
00617
00618
00619
00620
00621
00622
00623 NextEntry =
MmSessionSpace->
ImageList.Flink;
00624
00625
while (NextEntry != &
MmSessionSpace->
ImageList) {
00626
00627 Module = CONTAINING_RECORD(NextEntry,
IMAGE_ENTRY_IN_SESSION, Link);
00628
00629
00630
00631
00632
00633
00634 ImageHandle =
MiLookupPsLoadedModule (Module->
Address);
00635
00636
ASSERT (ImageHandle);
00637
00638
Status =
MmUnloadSystemImage (ImageHandle);
00639
00640
00641
00642
00643
00644
ASSERT (
MmSessionSpace->
ReferenceCount == 1);
00645
00646 NextEntry =
MmSessionSpace->
ImageList.Flink;
00647 }
00648 }
00649
00650
00651
VOID
00652 MiSessionWideInitializeAddresses (
00653 VOID
00654 )
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 {
00678 InitializeListHead (&
MmSessionWideAddressList);
00679 }
00680
00681
00682
NTSTATUS
00683 MiSessionWideInsertImageAddress (
00684 IN PVOID BaseAddress,
00685 IN ULONG_PTR NumberOfBytes,
00686 IN ULONG WritablePages,
00687 IN PUNICODE_STRING ImageName,
00688 IN BOOLEAN AtPreferredAddress
00689 )
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 {
00723 PVOID LastAddress;
00724 PLIST_ENTRY NextEntry;
00725
PSESSIONWIDE_DRIVER_ADDRESS Vaddr;
00726
PSESSIONWIDE_DRIVER_ADDRESS New;
00727 PWCHAR
NewName;
00728
00729
SYSLOAD_LOCK_OWNED_BY_ME ();
00730
00731 New =
ExAllocatePoolWithTag (
NonPagedPool,
00732
sizeof(
SESSIONWIDE_DRIVER_ADDRESS),
00733 'vHmM');
00734
00735
if (New ==
NULL) {
00736
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_NONPAGED_POOL);
00737
return STATUS_NO_MEMORY;
00738 }
00739
00740 RtlZeroMemory (New,
sizeof(
SESSIONWIDE_DRIVER_ADDRESS));
00741
00742 New->
ReferenceCount = 1;
00743 New->
Address = BaseAddress;
00744 New->
Size = NumberOfBytes;
00745
if (AtPreferredAddress ==
TRUE) {
00746 New->
WritablePages = WritablePages;
00747 }
00748
else {
00749 New->
WritablePages = (
MI_ROUND_TO_SIZE (NumberOfBytes,
PAGE_SIZE)) >>
PAGE_SHIFT;
00750 }
00751
00752
if (ImageName) {
00753
00754
NewName = (PWCHAR)
ExAllocatePoolWithTag (
PagedPool,
00755 ImageName->Length +
sizeof(UNICODE_NULL),
00756 'nHmM');
00757
00758
if (
NewName ==
NULL) {
00759
ExFreePool (New);
00760
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_PAGED_POOL);
00761
return STATUS_NO_MEMORY;
00762 }
00763
00764 RtlMoveMemory (
NewName, ImageName->Buffer, ImageName->Length);
00765
NewName [ImageName->Length /
sizeof(WCHAR)] = UNICODE_NULL;
00766
00767 New->
FullDllName.Buffer =
NewName;
00768 New->
FullDllName.Length = ImageName->Length;
00769 New->
FullDllName.MaximumLength = ImageName->Length;
00770 }
00771
else {
00772
RtlInitUnicodeString (&New->
FullDllName,
NULL);
00773 }
00774
00775
00776
00777
00778
00779 LastAddress =
NULL;
00780 NextEntry =
MmSessionWideAddressList.Flink;
00781
00782
while (NextEntry != &
MmSessionWideAddressList) {
00783
00784 Vaddr = CONTAINING_RECORD (NextEntry,
00785
SESSIONWIDE_DRIVER_ADDRESS,
00786 Link);
00787
00788
if (LastAddress < Vaddr->
Address && Vaddr->
Address > New->
Address) {
00789
break;
00790 }
00791
00792 LastAddress = Vaddr->
Address;
00793 NextEntry = NextEntry->Flink;
00794 }
00795
00796 InsertTailList (NextEntry, &New->
Link);
00797
00798
return STATUS_SUCCESS;
00799 }
00800
00801
NTSTATUS
00802 MiSessionWideDereferenceImage(
00803 IN PVOID BaseAddress
00804 )
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 {
00828 PLIST_ENTRY NextEntry;
00829
PSESSIONWIDE_DRIVER_ADDRESS SessionWideImageEntry;
00830
00831
SYSLOAD_LOCK_OWNED_BY_ME ();
00832
00833
ASSERT (BaseAddress);
00834
00835 NextEntry =
MmSessionWideAddressList.Flink;
00836
00837
while (NextEntry != &
MmSessionWideAddressList) {
00838
00839 SessionWideImageEntry = CONTAINING_RECORD (NextEntry,
00840
SESSIONWIDE_DRIVER_ADDRESS,
00841 Link);
00842
00843
if (BaseAddress == SessionWideImageEntry->
Address) {
00844
00845 SessionWideImageEntry->
ReferenceCount -= 1;
00846
00847
00848
00849
00850
00851
if (SessionWideImageEntry->
ReferenceCount == 0) {
00852 RemoveEntryList (NextEntry);
00853
ExFreePool (SessionWideImageEntry);
00854 }
00855
return STATUS_SUCCESS;
00856 }
00857
00858 NextEntry = NextEntry->Flink;
00859 }
00860
00861
return STATUS_NOT_FOUND;
00862 }
00863
00864
00865
NTSTATUS
00866 MiSessionWideGetImageSize(
00867 IN PVOID BaseAddress,
00868 OUT PSIZE_T NumberOfBytes OPTIONAL,
00869 OUT PSIZE_T CommitPages OPTIONAL
00870 )
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 {
00902 PLIST_ENTRY NextEntry;
00903
PSESSIONWIDE_DRIVER_ADDRESS SessionWideEntry;
00904
00905
SYSLOAD_LOCK_OWNED_BY_ME ();
00906
00907 NextEntry =
MmSessionWideAddressList.Flink;
00908
00909
while (NextEntry != &
MmSessionWideAddressList) {
00910
00911 SessionWideEntry = CONTAINING_RECORD (NextEntry,
00912
SESSIONWIDE_DRIVER_ADDRESS,
00913 Link);
00914
00915
if (BaseAddress == SessionWideEntry->
Address) {
00916
00917
if (ARGUMENT_PRESENT (NumberOfBytes)) {
00918 *NumberOfBytes = SessionWideEntry->
Size;
00919 }
00920
00921
if (ARGUMENT_PRESENT (CommitPages)) {
00922 *CommitPages = SessionWideEntry->
WritablePages;
00923 }
00924
00925
return STATUS_SUCCESS;
00926 }
00927
00928 NextEntry = NextEntry->Flink;
00929 }
00930
00931
return STATUS_NOT_FOUND;
00932 }
00933
00934
00935
NTSTATUS
00936 MiSessionWideReserveImageAddress (
00937 IN PUNICODE_STRING ImageName,
00938 IN PSECTION Section,
00939 IN ULONG_PTR Alignment,
00940 OUT PVOID *AssignedAddress,
00941 OUT PBOOLEAN AlreadyLoaded
00942 )
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 {
00987 PLIST_ENTRY NextEntry;
00988
PSESSIONWIDE_DRIVER_ADDRESS Vaddr;
00989
NTSTATUS Status;
00990 PWCHAR pName;
00991 PVOID NewAddress;
00992 ULONG_PTR AvailableAddress;
00993 ULONG_PTR SessionSpaceEnd;
00994 PVOID PreferredAddress;
00995 ULONG_PTR NumberOfBytes;
00996 ULONG WritablePages;
00997 BOOLEAN AtPreferredAddress;
00998
00999
PAGED_CODE();
01000
01001
SYSLOAD_LOCK_OWNED_BY_ME ();
01002
01003
ASSERT (
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 1);
01004
ASSERT (
MmIsAddressValid (
MmSessionSpace) ==
TRUE);
01005
01006 pName =
NULL;
01007 *AlreadyLoaded =
FALSE;
01008 PreferredAddress = Section->Segment->BasedAddress;
01009 NumberOfBytes = Section->Segment->TotalNumberOfPtes <<
PAGE_SHIFT;
01010
01011 AvailableAddress =
MI_SESSION_IMAGE_START;
01012 NumberOfBytes =
MI_ROUND_TO_SIZE (NumberOfBytes, Alignment);
01013 SessionSpaceEnd = AvailableAddress +
MI_SESSION_IMAGE_SIZE;
01014
01015
Status =
MiGetWritablePagesInSection(Section, &WritablePages);
01016
01017
if (!
NT_SUCCESS(
Status)) {
01018 WritablePages = Section->Segment->TotalNumberOfPtes;
01019 }
01020
01021
01022
01023
01024
01025
01026
if ((ULONG_PTR)PreferredAddress & (Alignment - 1)) {
01027
01028
#if DBG
01029
DbgPrint(
"MiSessionWideReserveImageAddress: Bad alignment 0x%x for PreferredAddress 0x%x\n",
01030 Alignment,
01031 PreferredAddress);
01032
#endif
01033
01034 PreferredAddress =
NULL;
01035 }
01036
else if ((ULONG_PTR)PreferredAddress < AvailableAddress ||
01037 ((ULONG_PTR)PreferredAddress + NumberOfBytes >= SessionSpaceEnd)) {
01038
01039
#if DBG
01040
if (MmDebug &
MM_DBG_SESSIONS) {
01041
DbgPrint (
"MiSessionWideReserveImageAddress: PreferredAddress 0x%x not in session space\n", PreferredAddress);
01042 }
01043
#endif
01044
01045 PreferredAddress =
NULL;
01046 }
01047
01048
01049
01050
01051
01052
01053 NextEntry =
MmSessionWideAddressList.Flink;
01054
01055
while (NextEntry != &
MmSessionWideAddressList) {
01056
01057 Vaddr = CONTAINING_RECORD (NextEntry,
01058
SESSIONWIDE_DRIVER_ADDRESS,
01059 Link);
01060
01061
if (Vaddr->
FullDllName.Buffer !=
NULL) {
01062
01063
if (
RtlEqualUnicodeString(ImageName, &Vaddr->
FullDllName,
TRUE)) {
01064
01065
01066
01067
01068
01069
if (Vaddr->
Size < NumberOfBytes) {
01070
#if DBG
01071
DbgPrint (
"MiSessionWideReserveImageAddress: Size %d Larger than Entry %d, DLL %wZ\n",
01072 NumberOfBytes,
01073 Vaddr->
Size,
01074 ImageName);
01075
#endif
01076
01077
return STATUS_CONFLICTING_ADDRESSES;
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
Status =
MiSessionInsertImage (Vaddr->
Address);
01088
01089
if (
Status == STATUS_ALREADY_COMMITTED) {
01090
01091 *AlreadyLoaded =
TRUE;
01092 *AssignedAddress = Vaddr->
Address;
01093
01094
return STATUS_SUCCESS;
01095 }
01096
01097
if (!
NT_SUCCESS (
Status)) {
01098
return Status;
01099 }
01100
01101
01102
01103
01104
01105 Vaddr->
ReferenceCount += 1;
01106
01107 *AssignedAddress = Vaddr->
Address;
01108
01109
return STATUS_SUCCESS;
01110 }
01111 }
01112
01113
01114
01115
01116
01117
01118
if (PreferredAddress) {
01119
01120
if ((PreferredAddress >= Vaddr->
Address) &&
01121 (PreferredAddress < (PVOID)((ULONG_PTR)Vaddr->
Address + Vaddr->
Size))) {
01122 PreferredAddress =
NULL;
01123 }
01124
else if ((PreferredAddress < Vaddr->
Address) &&
01125 ((PVOID)((ULONG_PTR)PreferredAddress + NumberOfBytes) > Vaddr->
Address)) {
01126 PreferredAddress =
NULL;
01127 }
01128 }
01129
01130
01131
01132
01133
01134
if (((PVOID)AvailableAddress >= Vaddr->
Address) &&
01135 (AvailableAddress <= (ULONG_PTR)Vaddr->
Address + Vaddr->
Size)) {
01136
01137 AvailableAddress = (ULONG_PTR)Vaddr->
Address + Vaddr->
Size;
01138
01139
if (AvailableAddress & (Alignment - 1)) {
01140 AvailableAddress =
MI_ROUND_TO_SIZE (AvailableAddress, Alignment);
01141 }
01142 }
01143
else if (AvailableAddress + NumberOfBytes > (ULONG_PTR)Vaddr->
Address) {
01144
01145 AvailableAddress = (ULONG_PTR)Vaddr->
Address + Vaddr->
Size;
01146
01147
if (AvailableAddress & (Alignment - 1)) {
01148 AvailableAddress =
MI_ROUND_TO_SIZE (AvailableAddress, Alignment);
01149 }
01150 }
01151
01152 NextEntry = NextEntry->Flink;
01153 }
01154
01155
if (PreferredAddress ==
NULL && (AvailableAddress + NumberOfBytes > (
MI_SESSION_IMAGE_START +
MI_SESSION_IMAGE_SIZE))) {
01156
MM_BUMP_SESSION_FAILURES (
MM_SESSION_FAILURE_NO_IMAGE_VA_SPACE);
01157
return STATUS_NO_MEMORY;
01158 }
01159
01160
01161
01162
01163
01164
if (PreferredAddress) {
01165
01166
#if DBG
01167
if (MmDebug &
MM_DBG_SESSIONS) {
01168
DbgPrint (
"MiSessionWideReserveImageAddress: Code Sharing on %wZ, Address 0x%x\n",ImageName,PreferredAddress);
01169 }
01170
#endif
01171
01172 NewAddress = PreferredAddress;
01173 }
01174
else {
01175
ASSERT (AvailableAddress != 0);
01176
ASSERT ((AvailableAddress & (Alignment - 1)) == 0);
01177
01178
#if DBG
01179
DbgPrint (
"MiSessionWideReserveImageAddress: NO Code Sharing on %wZ, Address 0x%x\n",ImageName,AvailableAddress);
01180
#endif
01181
01182 NewAddress = (PVOID)AvailableAddress;
01183 }
01184
01185
01186
01187
01188
01189
if (NewAddress == PreferredAddress) {
01190 AtPreferredAddress =
TRUE;
01191 }
01192
else {
01193 AtPreferredAddress =
FALSE;
01194 }
01195
01196
Status =
MiSessionWideInsertImageAddress (NewAddress,
01197 NumberOfBytes,
01198 WritablePages,
01199 ImageName,
01200 AtPreferredAddress);
01201
01202
if (!
NT_SUCCESS(
Status)) {
01203
return Status;
01204 }
01205
01206
01207
01208
01209
01210
Status =
MiSessionInsertImage (NewAddress);
01211
01212
if (!
NT_SUCCESS(
Status)) {
01213
MiSessionWideDereferenceImage (NewAddress);
01214
return Status;
01215 }
01216
01217 *AssignedAddress = NewAddress;
01218
01219
return STATUS_SUCCESS;
01220 }
01221
01222
NTSTATUS
01223 MiRemoveImageSessionWide(
01224 IN PVOID BaseAddress
01225 )
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250 {
01251
NTSTATUS Status;
01252
01253
PAGED_CODE();
01254
01255
SYSLOAD_LOCK_OWNED_BY_ME ();
01256
01257
ASSERT (
MmIsAddressValid(
MmSessionSpace) ==
TRUE);
01258
01259
Status =
MiSessionWideDereferenceImage (BaseAddress);
01260
01261
ASSERT (
NT_SUCCESS(
Status));
01262
01263
01264
01265
01266
01267
MiSessionRemoveImage (BaseAddress);
01268
01269
return Status;
01270 }
01271
01272 PLDR_DATA_TABLE_ENTRY
01273 MiLookupPsLoadedModule (
01274 IN PVOID Address
01275 )
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 {
01298 PLIST_ENTRY NextEntry;
01299 PLDR_DATA_TABLE_ENTRY DataTableEntry;
01300 PLDR_DATA_TABLE_ENTRY FoundDataTableEntry;
01301
01302
ASSERT (Address);
01303
01304 FoundDataTableEntry =
NULL;
01305
01306
KeWaitForSingleObject (&
MmSystemLoadLock,
01307
WrVirtualMemory,
01308
KernelMode,
01309
FALSE,
01310 (PLARGE_INTEGER)
NULL);
01311
01312
KeEnterCriticalRegion();
01313
ExAcquireResourceExclusive (&
PsLoadedModuleResource,
TRUE);
01314
01315 NextEntry =
PsLoadedModuleList.Flink;
01316
while (NextEntry != &
PsLoadedModuleList) {
01317 DataTableEntry = CONTAINING_RECORD(NextEntry,
01318 LDR_DATA_TABLE_ENTRY,
01319 InLoadOrderLinks);
01320
01321
if (DataTableEntry->DllBase == Address) {
01322
01323 FoundDataTableEntry = DataTableEntry;
01324
break;
01325 }
01326
01327 NextEntry = NextEntry->Flink;
01328 }
01329
01330
ExReleaseResource (&
PsLoadedModuleResource);
01331
KeLeaveCriticalRegion();
01332
01333
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
01334
01335
return FoundDataTableEntry;
01336 }