00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "mi.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 typedef struct _LOAD_IMPORTS {
00042 SIZE_T
Count;
00043 PLDR_DATA_TABLE_ENTRY
Entry[1];
00044 }
LOAD_IMPORTS, *
PLOAD_IMPORTS;
00045
00046 #define LOADED_AT_BOOT ((PLOAD_IMPORTS)0)
00047 #define NO_IMPORTS_USED ((PLOAD_IMPORTS)-2)
00048
00049 #define SINGLE_ENTRY(ImportVoid) ((ULONG)((ULONG_PTR)(ImportVoid) & 0x1))
00050
00051 #define SINGLE_ENTRY_TO_POINTER(ImportVoid) ((PLDR_DATA_TABLE_ENTRY)((ULONG_PTR)(ImportVoid) & ~0x1))
00052
00053 #define POINTER_TO_SINGLE_ENTRY(Pointer) ((PLDR_DATA_TABLE_ENTRY)((ULONG_PTR)(Pointer) | 0x1))
00054
00055 KMUTANT MmSystemLoadLock;
00056
00057 ULONG
MmTotalSystemDriverPages;
00058
00059 ULONG
MmDriverCommit;
00060
00061 BOOLEAN
MiFirstDriverLoadEver =
TRUE;
00062
00063
00064
00065
00066
00067
00068 LOGICAL
MmMakeLowMemory =
TRUE;
00069
00070
00071
00072
00073
00074
00075 PUNLOADED_DRIVERS MiUnloadedDrivers;
00076
00077 ULONG
MiLastUnloadedDriver;
00078 ULONG
MiTotalUnloads;
00079 ULONG
MiUnloadsSkipped;
00080
00081
00082
00083
00084
00085 ULONG
MmEnforceWriteProtection = 1;
00086
00087
00088
00089
00090
00091 PVOID
ExPoolCodeStart;
00092 PVOID
ExPoolCodeEnd;
00093 PVOID
MmPoolCodeStart;
00094 PVOID
MmPoolCodeEnd;
00095 PVOID
MmPteCodeStart;
00096 PVOID
MmPteCodeEnd;
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 extern KSPIN_LOCK
PsLoadedModuleSpinLock;
00107
00108 ULONG
00109
LdrDoubleRelocateImage (
00110 IN PVOID NewBase,
00111 IN PVOID CurrentBase,
00112 IN PUCHAR LoaderName,
00113 IN ULONG Success,
00114 IN ULONG Conflict,
00115 IN ULONG Invalid
00116 );
00117
00118
#if DBG
00119
PFN_NUMBER MiPagesConsumed;
00120
#endif
00121
00122 ULONG
00123
CacheImageSymbols(
00124 IN PVOID ImageBase
00125 );
00126
00127
NTSTATUS
00128
MiResolveImageReferences(
00129 PVOID ImageBase,
00130 IN PUNICODE_STRING ImageFileDirectory,
00131 IN PUNICODE_STRING NamePrefix OPTIONAL,
00132 IN BOOLEAN LoadInSessionSpace,
00133 OUT PCHAR *MissingProcedureName,
00134 OUT PWSTR *MissingDriverName,
00135 OUT PLOAD_IMPORTS *LoadedImports
00136 );
00137
00138
NTSTATUS
00139
MiSnapThunk(
00140 IN PVOID DllBase,
00141 IN PVOID ImageBase,
00142 IN PIMAGE_THUNK_DATA NameThunk,
00143 OUT PIMAGE_THUNK_DATA AddrThunk,
00144 IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
00145 IN ULONG ExportSize,
00146 IN BOOLEAN SnapForwarder,
00147 OUT PCHAR *MissingProcedureName
00148 );
00149
00150
NTSTATUS
00151
MiLoadImageSection (
00152 IN PSECTION SectionPointer,
00153 OUT PVOID *ImageBase,
00154 IN PUNICODE_STRING ImageFileName,
00155 IN BOOLEAN LoadInSessionSpace
00156 );
00157
00158
VOID
00159
MiEnablePagingOfDriver (
00160 IN PVOID ImageHandle
00161 );
00162
00163
VOID
00164
MiSetPagingOfDriver (
00165 IN
PMMPTE PointerPte,
00166 IN
PMMPTE LastPte,
00167 IN BOOLEAN SessionSpace
00168 );
00169
00170 PVOID
00171
MiLookupImageSectionByName (
00172 IN PVOID Base,
00173 IN BOOLEAN MappedAsImage,
00174 IN PCHAR SectionName,
00175 OUT PULONG SectionSize
00176 );
00177
00178
VOID
00179
MiClearImports(
00180 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
00181 );
00182
00183
NTSTATUS
00184
MiBuildImportsForBootDrivers(
00185 VOID
00186 );
00187
00188
NTSTATUS
00189
MmCheckSystemImage(
00190 IN HANDLE ImageFileHandle
00191 );
00192
00193 LONG
00194
MiMapCacheExceptionFilter (
00195 OUT PNTSTATUS Status,
00196 IN PEXCEPTION_POINTERS ExceptionPointer
00197 );
00198
00199 ULONG
00200
MiSetProtectionOnTransitionPte (
00201 IN
PMMPTE PointerPte,
00202 IN ULONG ProtectionMask
00203 );
00204
00205
NTSTATUS
00206
MiDereferenceImports (
00207 IN PLOAD_IMPORTS ImportList
00208 );
00209
00210 LOGICAL
00211
MiCallDllUnloadAndUnloadDll(
00212 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
00213 );
00214
00215 PVOID
00216
MiLocateExportName (
00217 IN PVOID DllBase,
00218 IN PCHAR FunctionName
00219 );
00220
00221
NTSTATUS
00222
MiLoadSystemImage (
00223 IN PUNICODE_STRING ImageFileName,
00224 IN PUNICODE_STRING NamePrefix OPTIONAL,
00225 IN PUNICODE_STRING LoadedBaseName OPTIONAL,
00226 IN BOOLEAN LoadInSessionSpace,
00227 OUT PVOID *ImageHandle,
00228 OUT PVOID *ImageBaseAddress,
00229 IN BOOLEAN LockDownPages
00230 );
00231
00232
VOID
00233
MiRememberUnloadedDriver (
00234 IN PUNICODE_STRING DriverName,
00235 IN PVOID Address,
00236 IN ULONG Length
00237 );
00238
00239
VOID
00240
MiWriteProtectSystemImage (
00241 IN PVOID DllBase
00242 );
00243
00244
VOID
00245
MiLocateKernelSections (
00246 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
00247 );
00248
00249
VOID
00250
MiUpdateThunks (
00251 IN
PLOADER_PARAMETER_BLOCK LoaderBlock,
00252 IN PVOID OldAddress,
00253 IN PVOID NewAddress,
00254 IN ULONG NumberOfBytes
00255 );
00256
00257
NTSTATUS
00258
MiCheckPageFilePath (
00259
PFILE_OBJECT FileObject
00260 );
00261
00262 PVOID
00263
MiFindExportedRoutineByName(
00264 IN PLDR_DATA_TABLE_ENTRY DataTableEntry,
00265 IN PANSI_STRING AnsiImageRoutineName
00266 );
00267
00268 extern LOGICAL
MiNoLowMemory;
00269
00270
VOID
00271
MiRemoveLowPages (
00272 VOID
00273 );
00274
00275
#ifdef ALLOC_PRAGMA
00276
#pragma alloc_text(PAGE,MmCheckSystemImage)
00277
#pragma alloc_text(PAGE,MmLoadSystemImage)
00278
#pragma alloc_text(PAGE,MmLoadAndLockSystemImage)
00279
#pragma alloc_text(PAGE,MiLoadSystemImage)
00280
#pragma alloc_text(PAGE,MiResolveImageReferences)
00281
#pragma alloc_text(PAGE,MiSnapThunk)
00282
#pragma alloc_text(PAGE,MiEnablePagingOfDriver)
00283
#pragma alloc_text(PAGE,MmPageEntireDriver)
00284
#pragma alloc_text(PAGE,MiSetImageProtect)
00285
#pragma alloc_text(PAGE,MiDereferenceImports)
00286
#pragma alloc_text(PAGE,MiCallDllUnloadAndUnloadDll)
00287
#pragma alloc_text(PAGE,MiLocateExportName)
00288
#pragma alloc_text(PAGE,MiClearImports)
00289
#pragma alloc_text(PAGE,MiWriteProtectSystemImage)
00290
#pragma alloc_text(PAGE,MmGetSystemRoutineAddress)
00291
#pragma alloc_text(PAGE,MiFindExportedRoutineByName)
00292
#pragma alloc_text(INIT,MiBuildImportsForBootDrivers)
00293
#pragma alloc_text(INIT,MiReloadBootLoadedDrivers)
00294
#pragma alloc_text(INIT,MiUpdateThunks)
00295
#pragma alloc_text(INIT,MiInitializeLoadedModuleList)
00296
#pragma alloc_text(INIT,MiLocateKernelSections)
00297
#pragma alloc_text(INIT,MmCallDllInitialize)
00298
00299
#if !defined(NT_UP)
00300
#pragma alloc_text(PAGE,MmVerifyImageIsOkForMpUse)
00301
#endif // NT_UP
00302
00303
#pragma alloc_text(PAGELK,MiLoadImageSection)
00304
#pragma alloc_text(PAGELK,MmFreeDriverInitialization)
00305
#pragma alloc_text(PAGELK,MmUnloadSystemImage)
00306
#pragma alloc_text(PAGELK,MiRememberUnloadedDriver)
00307
#pragma alloc_text(PAGELK,MiSetPagingOfDriver)
00308
#pragma alloc_text(PAGELK,MmResetDriverPaging)
00309
#endif
00310
00311 CHAR MiPteStr[] =
"\0";
00312
00313
00314
NTSTATUS
00315 MmLoadSystemImage (
00316 IN PUNICODE_STRING ImageFileName,
00317 IN PUNICODE_STRING NamePrefix OPTIONAL,
00318 IN PUNICODE_STRING LoadedBaseName OPTIONAL,
00319 IN BOOLEAN LoadInSessionSpace,
00320 OUT PVOID *ImageHandle,
00321 OUT PVOID *ImageBaseAddress
00322 )
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 {
00365
PAGED_CODE();
00366
00367
return MiLoadSystemImage (
00368 ImageFileName,
00369 NamePrefix,
00370 LoadedBaseName,
00371 LoadInSessionSpace,
00372 ImageHandle,
00373 ImageBaseAddress,
00374
FALSE
00375 );
00376 }
00377
00378
NTSTATUS
00379 MmLoadAndLockSystemImage (
00380 IN PUNICODE_STRING ImageFileName,
00381 IN PUNICODE_STRING NamePrefix OPTIONAL,
00382 IN PUNICODE_STRING LoadedBaseName OPTIONAL,
00383 OUT PVOID *ImageHandle,
00384 OUT PVOID *ImageBaseAddress
00385 )
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 {
00428
PAGED_CODE();
00429
00430
return MiLoadSystemImage (
00431 ImageFileName,
00432 NamePrefix,
00433 LoadedBaseName,
00434
FALSE,
00435 ImageHandle,
00436 ImageBaseAddress,
00437
TRUE
00438 );
00439 }
00440
00441
00442
NTSTATUS
00443 MiLoadSystemImage (
00444 IN PUNICODE_STRING ImageFileName,
00445 IN PUNICODE_STRING NamePrefix OPTIONAL,
00446 IN PUNICODE_STRING LoadedBaseName OPTIONAL,
00447 IN BOOLEAN LoadInSessionSpace,
00448 OUT PVOID *ImageHandle,
00449 OUT PVOID *ImageBaseAddress,
00450 IN BOOLEAN LockDownPages
00451 )
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
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
00488
00489
00490
00491
00492
00493 {
00494 KIRQL OldIrql;
00495 PLDR_DATA_TABLE_ENTRY DataTableEntry;
00496 LDR_DATA_TABLE_ENTRY TempDataTableEntry;
00497
NTSTATUS Status;
00498
PSECTION SectionPointer;
00499 PIMAGE_NT_HEADERS NtHeaders;
00500 UNICODE_STRING PrefixedImageName;
00501 UNICODE_STRING
BaseName;
00502 UNICODE_STRING BaseDirectory;
00503 OBJECT_ATTRIBUTES
ObjectAttributes;
00504 HANDLE FileHandle;
00505 HANDLE SectionHandle;
00506 IO_STATUS_BLOCK IoStatus;
00507
CHAR NameBuffer[ MAXIMUM_FILENAME_LENGTH ];
00508 PLIST_ENTRY NextEntry;
00509 ULONG NumberOfPtes;
00510 ULONG_PTR ViewSize;
00511 PCHAR MissingProcedureName;
00512 PWSTR MissingDriverName;
00513
PLOAD_IMPORTS LoadedImports;
00514
PMMSESSION Session;
00515 BOOLEAN AlreadyOpen;
00516 BOOLEAN IssueUnloadOnFailure;
00517 ULONG SectionAccess;
00518
volatile PMMPTE PointerPpe;
00519
MMPTE PpeContents;
00520
00521
PAGED_CODE();
00522
00523 LoadedImports = (
PLOAD_IMPORTS)
NO_IMPORTS_USED;
00524 SectionPointer = (PVOID)-1;
00525 FileHandle = (HANDLE)0;
00526 MissingProcedureName =
NULL;
00527 MissingDriverName =
NULL;
00528 IssueUnloadOnFailure =
FALSE;
00529
00530
if (LoadInSessionSpace ==
TRUE) {
00531
00532
ASSERT (NamePrefix ==
NULL);
00533
ASSERT (LoadedBaseName ==
NULL);
00534
00535
if (
MiHydra ==
TRUE) {
00536
00537
if (
PsGetCurrentProcess()->Vm.u.Flags.ProcessInSession == 0) {
00538
#if DBG
00539
DbgPrint (
"MiLoadSystemImage: no session space!\n");
00540
#endif
00541
return STATUS_NO_MEMORY;
00542 }
00543
00544
ASSERT (
MmIsAddressValid (
MmSessionSpace) ==
TRUE);
00545
00546 Session = &
MmSessionSpace->
Session;
00547 }
00548
else {
00549 Session = &
MmSession;
00550 LoadInSessionSpace =
FALSE;
00551 }
00552 }
00553
else {
00554 Session = &
MmSession;
00555 }
00556
00557
00558
00559
00560
00561
if (ImageFileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) {
00562 PWCHAR p;
00563 ULONG l;
00564
00565 p = &ImageFileName->Buffer[ImageFileName->Length>>1];
00566
while (*(p-1) != OBJ_NAME_PATH_SEPARATOR) {
00567 p--;
00568 }
00569 l = (ULONG)(&ImageFileName->Buffer[ImageFileName->Length>>1] - p);
00570 l *=
sizeof(WCHAR);
00571
BaseName.Length = (
USHORT)l;
00572
BaseName.Buffer = p;
00573 }
else {
00574
BaseName.Length = ImageFileName->Length;
00575
BaseName.Buffer = ImageFileName->Buffer;
00576 }
00577
00578
BaseName.MaximumLength =
BaseName.Length;
00579 BaseDirectory = *ImageFileName;
00580 BaseDirectory.Length -=
BaseName.Length;
00581 BaseDirectory.MaximumLength = BaseDirectory.Length;
00582 PrefixedImageName = *ImageFileName;
00583
00584
00585
00586
00587
00588
if (NamePrefix) {
00589 PrefixedImageName.MaximumLength =
00590 BaseDirectory.Length + NamePrefix->Length +
BaseName.Length;
00591
00592 PrefixedImageName.Buffer =
ExAllocatePoolWithTag (
00593
NonPagedPool,
00594 PrefixedImageName.MaximumLength,
00595 'dLmM'
00596 );
00597
00598
if (!PrefixedImageName.Buffer) {
00599
return STATUS_INSUFFICIENT_RESOURCES;
00600 }
00601
00602 PrefixedImageName.Length = 0;
00603
RtlAppendUnicodeStringToString(&PrefixedImageName, &BaseDirectory);
00604
RtlAppendUnicodeStringToString(&PrefixedImageName, NamePrefix);
00605
RtlAppendUnicodeStringToString(&PrefixedImageName, &
BaseName);
00606
00607
00608
00609
00610
00611
BaseName.Buffer = PrefixedImageName.Buffer + BaseDirectory.Length /
sizeof(WCHAR);
00612
BaseName.Length += NamePrefix->Length;
00613
BaseName.MaximumLength += NamePrefix->Length;
00614 }
00615
00616
00617
00618
00619
00620
if (LoadedBaseName) {
00621
BaseName = *LoadedBaseName;
00622 }
00623
00624
#if DBG
00625
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS ) {
00626
DbgPrint(
"MM:SYSLDR Loading %wZ (%wZ) %s\n",
00627 &PrefixedImageName,
00628 &
BaseName,
00629 LoadInSessionSpace ?
"in session space" :
" ");
00630 }
00631
#endif
00632
00633 AlreadyOpen =
FALSE;
00634
00635
00636
00637
00638
00639
KeEnterCriticalRegion();
00640
00641
KeWaitForSingleObject (&
MmSystemLoadLock,
00642
WrVirtualMemory,
00643
KernelMode,
00644
FALSE,
00645 (PLARGE_INTEGER)
NULL);
00646
00647
00648
00649
00650
00651 NextEntry =
PsLoadedModuleList.Flink;
00652
while (NextEntry != &
PsLoadedModuleList) {
00653
00654 DataTableEntry = CONTAINING_RECORD(NextEntry,
00655 LDR_DATA_TABLE_ENTRY,
00656 InLoadOrderLinks);
00657
00658
if (
RtlEqualUnicodeString (&PrefixedImageName,
00659 &DataTableEntry->FullDllName,
00660
TRUE)) {
00661
00662
if (LoadInSessionSpace ==
TRUE) {
00663
00664
if (
MI_IS_SESSION_ADDRESS (DataTableEntry->DllBase) ==
FALSE) {
00665
00666
00667
00668
00669
00670
00671
00672
Status = STATUS_CONFLICTING_ADDRESSES;
00673
goto return2;
00674 }
00675
00676 AlreadyOpen =
TRUE;
00677
00678
00679
00680
00681
00682
00683
00684
00685 DataTableEntry->LoadCount += 1;
00686 SectionPointer = DataTableEntry->SectionPointer;
00687
break;
00688 }
00689
else {
00690
if (
MI_IS_SESSION_ADDRESS (DataTableEntry->DllBase) ==
TRUE) {
00691
00692
00693
00694
00695
00696
00697
00698
Status = STATUS_CONFLICTING_ADDRESSES;
00699
goto return2;
00700 }
00701 }
00702
00703 *ImageHandle = DataTableEntry;
00704 *ImageBaseAddress = DataTableEntry->DllBase;
00705
Status = STATUS_IMAGE_ALREADY_LOADED;
00706
goto return2;
00707 }
00708
00709 NextEntry = NextEntry->Flink;
00710 }
00711
00712
ASSERT (AlreadyOpen ==
TRUE || NextEntry == &
PsLoadedModuleList);
00713
00714
if (AlreadyOpen ==
FALSE) {
00715
00716 DataTableEntry =
NULL;
00717
00718
00719
00720
00721
00722
00723 InitializeObjectAttributes (&
ObjectAttributes,
00724 ImageFileName,
00725 OBJ_CASE_INSENSITIVE,
00726
NULL,
00727
NULL );
00728
00729
Status =
ZwOpenFile (&FileHandle,
00730 FILE_EXECUTE,
00731 &
ObjectAttributes,
00732 &IoStatus,
00733 FILE_SHARE_READ | FILE_SHARE_DELETE,
00734 0 );
00735
00736
if (!
NT_SUCCESS(
Status)) {
00737
00738
#if DBG
00739
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
00740
DbgPrint (
"MiLoadImageSection: cannot open %wZ\n",
00741 ImageFileName);
00742 }
00743
#endif
00744
00745
00746
00747
00748
goto return2;
00749 }
00750
00751
Status =
MmCheckSystemImage(FileHandle);
00752
if ((
Status == STATUS_IMAGE_CHECKSUM_MISMATCH) ||
00753 (
Status == STATUS_IMAGE_MP_UP_MISMATCH) ||
00754 (
Status == STATUS_INVALID_IMAGE_PROTECT)) {
00755
goto return1;
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
if (LoadInSessionSpace ==
TRUE) {
00765 SectionAccess = SECTION_MAP_READ | SECTION_MAP_EXECUTE;
00766 }
00767
else {
00768 SectionAccess = SECTION_ALL_ACCESS;
00769 }
00770
00771
Status = ZwCreateSection (&SectionHandle,
00772 SectionAccess,
00773 (POBJECT_ATTRIBUTES)
NULL,
00774 (PLARGE_INTEGER)
NULL,
00775 PAGE_EXECUTE,
00776 SEC_IMAGE,
00777 FileHandle );
00778
00779
if (!
NT_SUCCESS(
Status)) {
00780
goto return1;
00781 }
00782
00783
00784
00785
00786
00787
Status =
ObReferenceObjectByHandle (SectionHandle,
00788 SECTION_MAP_EXECUTE,
00789
MmSectionObjectType,
00790
KernelMode,
00791 (PVOID *) &SectionPointer,
00792 (
POBJECT_HANDLE_INFORMATION)
NULL );
00793
00794 ZwClose (SectionHandle);
00795
if (!
NT_SUCCESS (
Status)) {
00796
goto return1;
00797 }
00798
00799
if (SectionPointer->Segment->ControlArea->NumberOfSubsections == 1) {
00800
if ((LoadInSessionSpace ==
FALSE) &&
00801 (SectionPointer->Segment->BasedAddress != (PVOID)Session->
SystemSpaceViewStart)) {
00802
00803
PSECTION SectionPointer2;
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
Status = ZwCreateSection (&SectionHandle,
00814 SectionAccess,
00815 (POBJECT_ATTRIBUTES)
NULL,
00816 (PLARGE_INTEGER)
NULL,
00817 PAGE_EXECUTE,
00818 SEC_COMMIT,
00819 FileHandle );
00820
00821
if (
NT_SUCCESS(
Status)) {
00822
00823
Status =
ObReferenceObjectByHandle (
00824 SectionHandle,
00825 SECTION_MAP_EXECUTE,
00826
MmSectionObjectType,
00827
KernelMode,
00828 (PVOID *) &SectionPointer2,
00829 (
POBJECT_HANDLE_INFORMATION)
NULL );
00830
00831 ZwClose (SectionHandle);
00832
00833
if (
NT_SUCCESS (
Status)) {
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
if (SectionPointer->Segment->TotalNumberOfPtes == SectionPointer2->Segment->TotalNumberOfPtes) {
00844
ObDereferenceObject (SectionPointer);
00845 SectionPointer = SectionPointer2;
00846 }
00847
else {
00848
ObDereferenceObject (SectionPointer2);
00849 }
00850 }
00851 }
00852 }
00853 }
00854
00855 }
00856
00857
if ((LoadInSessionSpace ==
FALSE) &&
00858 (SectionPointer->Segment->BasedAddress == (PVOID)Session->
SystemSpaceViewStart) &&
00859 (SectionPointer->Segment->ControlArea->NumberOfMappedViews == 0)) {
00860 NumberOfPtes = 0;
00861 ViewSize = 0;
00862
00863
Status =
MmMapViewInSystemSpace (SectionPointer,
00864 ImageBaseAddress,
00865 &ViewSize);
00866
if ((
NT_SUCCESS(
Status ) &&
00867 (*ImageBaseAddress == SectionPointer->Segment->BasedAddress))) {
00868
00869 SectionPointer->Segment->SystemImageBase = *ImageBaseAddress;
00870 SectionPointer->Segment->ControlArea->u.Flags.ImageMappedInSystemSpace = 1;
00871 NumberOfPtes = (ULONG)((ViewSize + 1) >>
PAGE_SHIFT);
00872
MiSetImageProtect(SectionPointer->Segment,
MM_EXECUTE_READWRITE);
00873
00874
#if defined (_AXP64_)
00875
00876
00877
00878
00879
00880
00881
00882
00883 PointerPpe =
MiGetPpeAddress (*ImageBaseAddress);
00884
ASSERT (PointerPpe->
u.Long != 0);
00885 PpeContents = *PointerPpe;
00886
KeAttachProcess (&
PsInitialSystemProcess->
Pcb);
00887
ASSERT (PointerPpe->u.Long == 0);
00888 *PointerPpe = PpeContents;
00889
KeDetachProcess();
00890
#endif
00891
goto BindImage;
00892 }
00893 }
00894
00895
MmLockPagableSectionByHandle (
ExPageLockHandle);
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
Status =
MiLoadImageSection (SectionPointer,
00908 ImageBaseAddress,
00909 ImageFileName,
00910 LoadInSessionSpace);
00911
00912
MmUnlockPagableImageSection (
ExPageLockHandle);
00913
00914 NumberOfPtes = SectionPointer->Segment->TotalNumberOfPtes;
00915
00916
if (
Status == STATUS_ALREADY_COMMITTED) {
00917
00918
00919
00920
00921
00922
00923
00924
00925
ASSERT (
MiHydra ==
TRUE);
00926
ASSERT (AlreadyOpen ==
TRUE);
00927
ASSERT (LoadInSessionSpace ==
TRUE);
00928
ASSERT (DataTableEntry !=
NULL);
00929
ASSERT (DataTableEntry->LoadCount > 1);
00930
00931 *ImageHandle = DataTableEntry;
00932 *ImageBaseAddress = DataTableEntry->DllBase;
00933
00934 DataTableEntry->LoadCount -= 1;
00935
Status = STATUS_SUCCESS;
00936
goto return1;
00937 }
00938
00939
if (
MiFirstDriverLoadEver ==
TRUE) {
00940
00941
NTSTATUS PagingPathStatus;
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 PagingPathStatus =
MiCheckPageFilePath (SectionPointer->Segment->ControlArea->FilePointer);
00959
00960
if (!
NT_SUCCESS(PagingPathStatus)) {
00961
00962 KdPrint((
"MiCheckPageFilePath FAILED for win32k.sys: %x\n",
00963 PagingPathStatus ));
00964
00965
00966
00967
00968
00969
00970
00971 }
00972
00973
MiFirstDriverLoadEver =
FALSE;
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
if (LoadInSessionSpace ==
FALSE) {
00988
ObDereferenceObject (SectionPointer);
00989 SectionPointer = (PVOID)-1;
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
if (!
NT_SUCCESS(
Status)) {
00999
if (AlreadyOpen ==
TRUE) {
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
ASSERT (DataTableEntry !=
NULL);
01010 DataTableEntry->LoadCount -= 1;
01011 DataTableEntry =
NULL;
01012 }
01013
goto return1;
01014 }
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 IssueUnloadOnFailure =
TRUE;
01034
01035
if (LoadInSessionSpace ==
FALSE || *ImageBaseAddress != SectionPointer->Segment->BasedAddress) {
01036
01037
#if DBG
01038
01039
01040
01041
01042
01043
01044
if (LoadInSessionSpace ==
TRUE &&
MmSessionSpace->
SessionId) {
01045
DbgPrint (
"MM: Session %d image %wZ is linked at a nonsharable address (%p)\n",
01046
MmSessionSpace->
SessionId,
01047 ImageFileName,
01048 SectionPointer->Segment->BasedAddress);
01049
DbgPrint (
"MM: Image %wZ has been moved to address (%p) by the system so it can run,\n",
01050 ImageFileName,
01051 *ImageBaseAddress);
01052
DbgPrint (
" but this needs to be fixed in the image for sharing to occur.\n");
01053 }
01054
#endif
01055
01056
01057
01058
01059
01060
try {
01061
Status = (
NTSTATUS)
LdrRelocateImage(*ImageBaseAddress,
01062
"SYSLDR",
01063 (ULONG)STATUS_SUCCESS,
01064 (ULONG)STATUS_CONFLICTING_ADDRESSES,
01065 (ULONG)STATUS_INVALID_IMAGE_FORMAT
01066 );
01067 } except (
EXCEPTION_EXECUTE_HANDLER) {
01068
Status = GetExceptionCode();
01069 KdPrint((
"MM:sysload - LdrRelocateImage failed status %lx\n",
01070
Status));
01071 }
01072
01073
if (!
NT_SUCCESS(
Status)) {
01074
01075
01076
01077
01078
01079
goto return1;
01080 }
01081 }
01082
01083 BindImage:
01084
01085
try {
01086 MissingProcedureName = NameBuffer;
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
Status =
MiResolveImageReferences(*ImageBaseAddress,
01101 &BaseDirectory,
01102 NamePrefix,
01103
FALSE,
01104 &MissingProcedureName,
01105 &MissingDriverName,
01106 &LoadedImports
01107 );
01108 } except (
EXCEPTION_EXECUTE_HANDLER) {
01109
Status = GetExceptionCode();
01110 KdPrint((
"MM:sysload - ResolveImageReferences failed status %x\n",
01111
Status));
01112 }
01113
01114
if (!
NT_SUCCESS(
Status)) {
01115
#if DBG
01116
if (
Status == STATUS_DRIVER_ORDINAL_NOT_FOUND ||
01117
Status == STATUS_DRIVER_ENTRYPOINT_NOT_FOUND) {
01118
01119
if ((ULONG_PTR)MissingProcedureName & ~((ULONG_PTR) (
X64K-1))) {
01120
01121
01122
01123
DbgPrint(
"MissingProcedureName %s\n", MissingProcedureName);
01124 }
01125
else {
01126
DbgPrint(
"MissingProcedureName 0x%p\n", MissingProcedureName);
01127 }
01128
01129
if (MissingDriverName) {
01130
DbgPrint(
"MissingDriverName %ws\n", MissingDriverName);
01131 }
01132 }
01133
#endif
01134
goto return1;
01135 }
01136
01137
#if DBG
01138
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01139 KdPrint ((
"MM:loaded driver - consumed %ld. pages\n",MiPagesConsumed));
01140 }
01141
#endif
01142
01143
if (AlreadyOpen ==
FALSE) {
01144
01145
01146
01147
01148
01149
01150
#if DBG
01151
NextEntry =
PsLoadedModuleList.Flink;
01152
while (NextEntry != &
PsLoadedModuleList) {
01153 DataTableEntry = CONTAINING_RECORD(NextEntry,
01154 LDR_DATA_TABLE_ENTRY,
01155 InLoadOrderLinks);
01156
01157
if (
RtlEqualUnicodeString (ImageFileName,
01158 &DataTableEntry->FullDllName,
01159
TRUE)) {
01160
01161
DbgPrint(
"MM SYSLDR: Image already loaded! RefCount %x\n",
01162 DataTableEntry->LoadCount);
01163 DbgBreakPoint();
01164 }
01165
01166 NextEntry = NextEntry->Flink;
01167 }
01168
#endif
01169
01170
01171
01172
01173
01174 DataTableEntry =
ExAllocatePoolWithTag (
NonPagedPool,
01175
sizeof(LDR_DATA_TABLE_ENTRY),
01176 'dLmM');
01177
01178
if (DataTableEntry ==
NULL) {
01179
Status = STATUS_INSUFFICIENT_RESOURCES;
01180
goto return1;
01181 }
01182
01183 DataTableEntry->BaseDllName.Buffer =
ExAllocatePoolWithTag (
01184
NonPagedPool,
01185
BaseName.Length +
sizeof(UNICODE_NULL),
01186 'dLmM');
01187
01188
if (DataTableEntry->BaseDllName.Buffer ==
NULL) {
01189
ExFreePool (DataTableEntry);
01190 DataTableEntry =
NULL;
01191
Status = STATUS_INSUFFICIENT_RESOURCES;
01192
goto return1;
01193 }
01194
01195
01196
01197
01198
01199
01200 NtHeaders =
RtlImageNtHeader(*ImageBaseAddress);
01201
01202 DataTableEntry->DllBase = *ImageBaseAddress;
01203 DataTableEntry->EntryPoint =
01204 ((PCHAR)*ImageBaseAddress + NtHeaders->OptionalHeader.AddressOfEntryPoint);
01205 DataTableEntry->SizeOfImage = NumberOfPtes <<
PAGE_SHIFT;
01206 DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
01207 DataTableEntry->SectionPointer = (PVOID)SectionPointer;
01208
01209
01210
01211
01212
01213 DataTableEntry->BaseDllName.Length =
BaseName.Length;
01214 DataTableEntry->BaseDllName.MaximumLength =
BaseName.Length;
01215 RtlMoveMemory (DataTableEntry->BaseDllName.Buffer,
01216
BaseName.Buffer,
01217
BaseName.Length );
01218 DataTableEntry->BaseDllName.Buffer[
BaseName.Length/
sizeof(WCHAR)] = UNICODE_NULL;
01219
01220 DataTableEntry->FullDllName.Buffer =
ExAllocatePoolWithTag (
PagedPool,
01221 PrefixedImageName.Length +
sizeof(UNICODE_NULL),
01222 'TDmM');
01223
if (DataTableEntry->FullDllName.Buffer ==
NULL) {
01224
01225
01226
01227
01228
01229 DataTableEntry->FullDllName.Length = 0;
01230 DataTableEntry->FullDllName.MaximumLength = 0;
01231 }
else {
01232 DataTableEntry->FullDllName.Length = PrefixedImageName.Length;
01233 DataTableEntry->FullDllName.MaximumLength = PrefixedImageName.Length;
01234 RtlMoveMemory (DataTableEntry->FullDllName.Buffer,
01235 PrefixedImageName.Buffer,
01236 PrefixedImageName.Length);
01237 DataTableEntry->FullDllName.Buffer[PrefixedImageName.Length/
sizeof(WCHAR)] = UNICODE_NULL;
01238 }
01239
01240
PERFINFO_IMAGE_LOAD(DataTableEntry);
01241
01242
01243
01244
01245
01246
01247 DataTableEntry->Flags = LDRP_ENTRY_PROCESSED | LDRP_SYSTEM_MAPPED;
01248 DataTableEntry->LoadCount = 1;
01249 DataTableEntry->LoadedImports = (PVOID)LoadedImports;
01250
01251
if ((NtHeaders->OptionalHeader.MajorOperatingSystemVersion >= 5) &&
01252 (NtHeaders->OptionalHeader.MajorImageVersion >= 5)) {
01253 DataTableEntry->Flags |= LDRP_ENTRY_NATIVE;
01254 }
01255
01256
MiApplyDriverVerifier (DataTableEntry,
NULL);
01257
01258
MiWriteProtectSystemImage (DataTableEntry->DllBase);
01259
01260
if (
PsImageNotifyEnabled) {
01261
IMAGE_INFO ImageInfo;
01262
01263 ImageInfo.
Properties = 0;
01264 ImageInfo.
ImageAddressingMode =
IMAGE_ADDRESSING_MODE_32BIT;
01265 ImageInfo.
SystemModeImage =
TRUE;
01266 ImageInfo.
ImageSize = DataTableEntry->SizeOfImage;
01267 ImageInfo.
ImageBase = *ImageBaseAddress;
01268 ImageInfo.
ImageSelector = 0;
01269 ImageInfo.
ImageSectionNumber = 0;
01270
01271
PsCallImageNotifyRoutines(ImageFileName, (HANDLE)
NULL, &ImageInfo);
01272 }
01273
01274
01275
01276
01277
01278
01279
KeEnterCriticalRegion();
01280
ExAcquireResourceExclusive (&
PsLoadedModuleResource,
TRUE);
01281
01282 ExAcquireSpinLock (&
PsLoadedModuleSpinLock, &OldIrql);
01283
01284 InsertTailList(&
PsLoadedModuleList, &DataTableEntry->InLoadOrderLinks);
01285
01286 ExReleaseSpinLock (&
PsLoadedModuleSpinLock, OldIrql);
01287
01288
ExReleaseResource (&
PsLoadedModuleResource);
01289
KeLeaveCriticalRegion();
01290
01291
if (
CacheImageSymbols (*ImageBaseAddress)) {
01292
01293
01294
01295
01296
01297 ANSI_STRING AnsiName;
01298 UNICODE_STRING UnicodeName;
01299
01300
01301
01302
01303
if (PrefixedImageName.Length > (11 *
sizeof( WCHAR )) &&
01304 !_wcsnicmp( PrefixedImageName.Buffer,
L"\\SystemRoot", 11 )
01305 ) {
01306 UnicodeName = PrefixedImageName;
01307 UnicodeName.Buffer += 11;
01308 UnicodeName.Length -= (11 *
sizeof( WCHAR ));
01309
sprintf (NameBuffer,
"%ws%wZ", &SharedUserData->NtSystemRoot[2], &UnicodeName);
01310 }
else {
01311
sprintf (NameBuffer,
"%wZ", &
BaseName);
01312 }
01313
RtlInitString (&AnsiName, NameBuffer);
01314 DbgLoadImageSymbols (&AnsiName,
01315 *ImageBaseAddress,
01316 (ULONG_PTR) -1
01317 );
01318 DataTableEntry->Flags |= LDRP_DEBUG_SYMBOLS_LOADED;
01319 }
01320 }
01321
01322
01323
01324
01325
01326
KeSweepIcache (
TRUE);
01327 *ImageHandle = DataTableEntry;
01328
Status = STATUS_SUCCESS;
01329
01330
if (LoadInSessionSpace ==
TRUE) {
01331
MmPageEntireDriver (DataTableEntry->EntryPoint);
01332 }
01333
else if (SectionPointer == (PVOID)-1 && LockDownPages ==
FALSE) {
01334
MiEnablePagingOfDriver (DataTableEntry);
01335 }
01336
01337 return1:
01338
01339
if (!
NT_SUCCESS(
Status)) {
01340
01341
#if DBG
01342
01343
01344
01345
01346
01347
01348
if (DataTableEntry) {
01349
ASSERT (
MiHydra ==
TRUE && AlreadyOpen ==
TRUE && DataTableEntry->LoadCount > 1);
01350 }
01351
#endif
01352
01353
if (AlreadyOpen ==
FALSE && SectionPointer != (PVOID)-1) {
01354
01355
01356
01357
01358
01359
01360
ObDereferenceObject (SectionPointer);
01361 }
01362
01363
if (IssueUnloadOnFailure ==
TRUE) {
01364
01365
if (DataTableEntry ==
NULL) {
01366 RtlZeroMemory (&TempDataTableEntry,
sizeof(LDR_DATA_TABLE_ENTRY));
01367
01368 DataTableEntry = &TempDataTableEntry;
01369
01370 DataTableEntry->DllBase = *ImageBaseAddress;
01371 DataTableEntry->SizeOfImage = NumberOfPtes <<
PAGE_SHIFT;
01372 DataTableEntry->LoadCount = 1;
01373 DataTableEntry->LoadedImports = LoadedImports;
01374 }
01375
#if DBG
01376
else {
01377
01378
01379
01380
01381
01382
01383
01384
01385
ASSERT (
MiHydra ==
TRUE);
01386
ASSERT (DataTableEntry->LoadCount > 1);
01387 }
01388
#endif
01389
01390
MmUnloadSystemImage ((PVOID)DataTableEntry);
01391 }
01392 }
01393
01394
if (FileHandle) {
01395 ZwClose (FileHandle);
01396 }
01397
if (!
NT_SUCCESS(
Status)) {
01398
01399 ULONG_PTR ErrorParameters[ 3 ];
01400 ULONG NumberOfParameters;
01401 ULONG UnicodeStringParameterMask;
01402 ULONG ErrorResponse;
01403 ANSI_STRING AnsiString;
01404 UNICODE_STRING ProcedureName;
01405 UNICODE_STRING DriverName;
01406
01407
01408
01409
01410
01411
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
01412
KeLeaveCriticalRegion();
01413 ErrorParameters[ 0 ] = (ULONG_PTR)ImageFileName;
01414 NumberOfParameters = 1;
01415 UnicodeStringParameterMask = 1;
01416
01417
RtlInitUnicodeString( &ProcedureName,
NULL );
01418
if (
Status == STATUS_DRIVER_ORDINAL_NOT_FOUND ||
01419
Status == STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ||
01420
Status == STATUS_PROCEDURE_NOT_FOUND
01421 ) {
01422 NumberOfParameters = 3;
01423 UnicodeStringParameterMask = 0x5;
01424
RtlInitUnicodeString( &DriverName, MissingDriverName );
01425 ErrorParameters[ 2 ] = (ULONG_PTR)&DriverName;
01426
01427
if ((ULONG_PTR)MissingProcedureName & ~((ULONG_PTR) (
X64K-1))) {
01428
01429
01430
01431
01432
RtlInitAnsiString( &AnsiString, MissingProcedureName );
01433
RtlAnsiStringToUnicodeString( &ProcedureName, &AnsiString,
TRUE );
01434 ErrorParameters[ 1 ] = (ULONG_PTR)&ProcedureName;
01435 UnicodeStringParameterMask |= 0x2;
01436 }
else {
01437
01438
01439
01440
01441 ErrorParameters[ 1 ] = (ULONG_PTR)MissingProcedureName;
01442 }
01443 }
else {
01444 NumberOfParameters = 2;
01445 ErrorParameters[ 1 ] = (ULONG)
Status;
01446
Status = STATUS_DRIVER_UNABLE_TO_LOAD;
01447 }
01448
01449 ZwRaiseHardError (
Status,
01450 NumberOfParameters,
01451 UnicodeStringParameterMask,
01452 ErrorParameters,
01453 OptionOkNoWait,
01454 &ErrorResponse);
01455
01456
if (ProcedureName.Buffer !=
NULL) {
01457
RtlFreeUnicodeString( &ProcedureName );
01458 }
01459
return Status;
01460 }
01461
01462 return2:
01463
if (NamePrefix) {
01464
ExFreePool (PrefixedImageName.Buffer);
01465 }
01466
01467
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
01468
KeLeaveCriticalRegion();
01469
return Status;
01470 }
01471
01472
01473
NTSTATUS
01474 MiLoadImageSection (
01475 IN PSECTION SectionPointer,
01476 OUT PVOID *ImageBaseAddress,
01477 IN PUNICODE_STRING ImageFileName,
01478 IN BOOLEAN LoadInSessionSpace
01479 )
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507 {
01508 PFN_NUMBER PagesRequired;
01509
PMMPTE ProtoPte;
01510
PMMPTE FirstPte;
01511
PMMPTE LastPte;
01512
PMMPTE PointerPte;
01513
PEPROCESS Process;
01514
PEPROCESS TargetProcess;
01515 ULONG NumberOfPtes;
01516
MMPTE PteContents;
01517
MMPTE TempPte;
01518
PMMPFN Pfn1;
01519 PFN_NUMBER PageFrameIndex;
01520 KIRQL OldIrql;
01521 PVOID UserVa;
01522 PVOID SystemVa;
01523
NTSTATUS Status;
01524
NTSTATUS ExceptionStatus;
01525 PVOID Base;
01526 ULONG_PTR ViewSize;
01527 LARGE_INTEGER SectionOffset;
01528 BOOLEAN LoadSymbols;
01529 PVOID BaseAddress;
01530 PFN_NUMBER CommittedPages;
01531 SIZE_T SectionSize;
01532 BOOLEAN AlreadyLoaded;
01533
PMM_SESSION_SPACE SessionGlobal;
01534 LOGICAL ProcessReferenced;
01535 PLIST_ENTRY NextProcessEntry;
01536
01537
PAGED_CODE();
01538
01539 PagesRequired = 0;
01540
01541
01542
01543
01544
01545 ProtoPte = SectionPointer->Segment->PrototypePte;
01546 NumberOfPtes = SectionPointer->Segment->TotalNumberOfPtes;
01547
01548
while (NumberOfPtes != 0) {
01549 PteContents = *ProtoPte;
01550
01551
if ((PteContents.
u.Hard.Valid == 1) ||
01552 (PteContents.
u.Soft.Protection !=
MM_NOACCESS)) {
01553 PagesRequired += 1;
01554 }
01555 NumberOfPtes -= 1;
01556 ProtoPte += 1;
01557 }
01558
01559
if (LoadInSessionSpace ==
TRUE) {
01560
01561
ASSERT (
MiHydra ==
TRUE);
01562
01563 SectionSize = (ULONG_PTR)SectionPointer->Segment->TotalNumberOfPtes *
PAGE_SIZE;
01564
01565
01566
01567
01568
01569
01570
Status =
MiSessionWideReserveImageAddress (ImageFileName,
01571 SectionPointer,
01572
PAGE_SIZE,
01573 &BaseAddress,
01574 &AlreadyLoaded);
01575
01576
if (!
NT_SUCCESS(
Status)) {
01577
#if DBG
01578
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01579
DbgPrint (
"MiLoadImageSection: Error 0x%x Allocating session space %p Bytes\n",
Status,SectionSize);
01580 }
01581
#endif
01582
return Status;
01583 }
01584
01585
01586
01587
01588
01589
01590
if (AlreadyLoaded ==
TRUE) {
01591 *ImageBaseAddress = BaseAddress;
01592
return STATUS_ALREADY_COMMITTED;
01593 }
01594
01595
#if DBG
01596
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01597
if (ImageFileName) {
01598
DbgPrint (
"MM: MiLoadImageSection: Image %wZ, BasedAddress 0x%p, SegmentBaseAddress 0x%p, Allocated Session BaseAddress 0x%p\n",
01599 ImageFileName,
01600 SectionPointer->Segment->BasedAddress,
01601 SectionPointer->Segment->SegmentBaseAddress,
01602 BaseAddress);
01603 }
01604
else {
01605
DbgPrint (
"MM: MiLoadImageSection: Image <NULL> BasedAddress 0x%p, SegmentBaseAddress 0x%p, Allocated Session BaseAddress 0x%p\n",
01606 SectionPointer->Segment->BasedAddress,
01607 SectionPointer->Segment->SegmentBaseAddress,
01608 BaseAddress);
01609 }
01610 }
01611
#endif
01612
01613
if (BaseAddress == SectionPointer->Segment->BasedAddress) {
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
#if DBG
01626
if (SectionPointer->Segment->SystemImageBase != 0) {
01627
ASSERT (BaseAddress == SectionPointer->Segment->SystemImageBase);
01628 }
01629
#endif
01630
01631
01632
01633
01634
01635
Status =
MiShareSessionImage (SectionPointer, &SectionSize);
01636
01637
if (!
NT_SUCCESS(
Status)) {
01638
#if DBG
01639
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01640
DbgPrint (
"MM: MiLoadImageSection: Error 0x%x Allocating session space %p Bytes\n",
Status, SectionSize);
01641 }
01642
#endif
01643
MiRemoveImageSessionWide (BaseAddress);
01644
return Status;
01645 }
01646
01647
ASSERT (BaseAddress == SectionPointer->Segment->BasedAddress);
01648
01649 *ImageBaseAddress = BaseAddress;
01650
01651
01652
01653
01654
01655 SectionPointer->Segment->SystemImageBase = BaseAddress;
01656
01657
#if DBG
01658
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01659
if (ImageFileName) {
01660
DbgPrint (
"MM: MiLoadImageSection: Mapped image %wZ at requested session address 0x%p\n",
01661 ImageFileName,
01662 BaseAddress);
01663 }
01664
else {
01665
DbgPrint (
"MM: MiLoadImageSection: Mapped a session image at requested address 0x%p\n",
01666 BaseAddress);
01667 }
01668 }
01669
#endif
01670
01671
return Status;
01672 }
01673
01674
01675
01676
01677
01678
01679
01680
01681
Status =
MiSessionCommitImagePages (BaseAddress, SectionSize);
01682
01683
if (!
NT_SUCCESS(
Status)) {
01684
#if DBG
01685
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01686
DbgPrint (
"MM: MiLoadImageSection: Error 0x%x Allocating session space %p Bytes\n",
Status, SectionSize);
01687 }
01688
#endif
01689
MiRemoveImageSessionWide (BaseAddress);
01690
return Status;
01691 }
01692 SystemVa = BaseAddress;
01693 }
01694
else {
01695
01696
01697
01698
01699
01700
#if DBG
01701
MiPagesConsumed = PagesRequired;
01702
#endif
01703
01704
LOCK_PFN (OldIrql);
01705
01706
if (
MmResidentAvailablePages <= (SPFN_NUMBER)PagesRequired) {
01707
UNLOCK_PFN (OldIrql);
01708
return STATUS_INSUFFICIENT_RESOURCES;
01709 }
01710
MmResidentAvailablePages -= PagesRequired;
01711
MM_BUMP_COUNTER(14, PagesRequired);
01712
UNLOCK_PFN (OldIrql);
01713
01714
01715
01716
01717
01718 FirstPte =
MiReserveSystemPtes (SectionPointer->Segment->TotalNumberOfPtes,
01719
SystemPteSpace,
01720 0,
01721 0,
01722
FALSE );
01723
01724
if (FirstPte ==
NULL) {
01725
LOCK_PFN (OldIrql);
01726
MmResidentAvailablePages += PagesRequired;
01727
MM_BUMP_COUNTER(15, PagesRequired);
01728
UNLOCK_PFN (OldIrql);
01729
return STATUS_INSUFFICIENT_RESOURCES;
01730 }
01731 PointerPte = FirstPte;
01732 SystemVa =
MiGetVirtualAddressMappedByPte (PointerPte);
01733 }
01734
01735
01736
01737
01738
01739 Process =
PsGetCurrentProcess();
01740
01741
01742
01743
01744
01745
01746
01747 ProcessReferenced =
FALSE;
01748 TargetProcess = Process;
01749
if (Process->Peb && Process->Vm.u.Flags.SessionLeader == 0) {
01750
if (
MiHydra ==
FALSE) {
01751
if (
ExpDefaultErrorPortProcess && (Process !=
ExpDefaultErrorPortProcess)) {
01752 TargetProcess =
ExpDefaultErrorPortProcess;
01753
KeAttachProcess (&TargetProcess->
Pcb);
01754 }
01755 }
01756
else {
01757
01758 SessionGlobal =
SESSION_GLOBAL(
MmSessionSpace);
01759
LOCK_EXPANSION (OldIrql);
01760 NextProcessEntry = SessionGlobal->
ProcessList.Flink;
01761
01762
if ((SessionGlobal->
u.Flags.DeletePending == 0) &&
01763 (NextProcessEntry != &SessionGlobal->
ProcessList)) {
01764
01765 TargetProcess = CONTAINING_RECORD (NextProcessEntry,
01766
EPROCESS,
01767 SessionProcessLinks);
01768
01769
if (Process != TargetProcess) {
01770
ObReferenceObject (TargetProcess);
01771 ProcessReferenced =
TRUE;
01772 }
01773 }
01774
else {
01775
UNLOCK_EXPANSION (OldIrql);
01776
01777
LOCK_PFN (OldIrql);
01778
MmResidentAvailablePages += PagesRequired;
01779
MM_BUMP_COUNTER(15, PagesRequired);
01780
UNLOCK_PFN (OldIrql);
01781
01782 CommittedPages =
MiDeleteSystemPagableVm (
01783
MiGetPteAddress (BaseAddress),
01784
BYTES_TO_PAGES (SectionSize),
01785
ZeroKernelPte,
01786
TRUE,
01787
NULL);
01788
01789
LOCK_SESSION_SPACE_WS (OldIrql);
01790
MmSessionSpace->
CommittedPages -= CommittedPages;
01791
01792
MM_BUMP_SESS_COUNTER(
MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED1,
01793 CommittedPages);
01794
01795
UNLOCK_SESSION_SPACE_WS (OldIrql);
01796
01797
01798
01799
01800
01801
01802
01803
MiRemoveImageSessionWide (BaseAddress);
01804
01805
return STATUS_PROCESS_IS_TERMINATING;
01806 }
01807
01808
UNLOCK_EXPANSION (OldIrql);
01809
01810
if (Process != TargetProcess) {
01811
KeAttachProcess (&TargetProcess->
Pcb);
01812 }
01813 }
01814 }
01815
01816
ZERO_LARGE (SectionOffset);
01817 Base =
NULL;
01818 ViewSize = 0;
01819
01820
if (
NtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD) {
01821 LoadSymbols =
TRUE;
01822
NtGlobalFlag &= ~FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
01823 }
01824
else {
01825 LoadSymbols =
FALSE;
01826 }
01827
01828
Status =
MmMapViewOfSection ( SectionPointer,
01829 TargetProcess,
01830 &Base,
01831 0,
01832 0,
01833 &SectionOffset,
01834 &ViewSize,
01835 ViewUnmap,
01836 0,
01837 PAGE_EXECUTE);
01838
01839
if (LoadSymbols) {
01840
NtGlobalFlag |= FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
01841 }
01842
01843
if (
Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) {
01844
Status = STATUS_INVALID_IMAGE_FORMAT;
01845 }
01846
01847
if (!
NT_SUCCESS(
Status)) {
01848
if (TargetProcess != Process) {
01849
KeDetachProcess();
01850
if (ProcessReferenced ==
TRUE) {
01851
ObDereferenceObject (TargetProcess);
01852 }
01853 }
01854
01855
if (LoadInSessionSpace ==
TRUE) {
01856
01857
#if DBG
01858
if (
NtGlobalFlag & FLG_SHOW_LDR_SNAPS) {
01859
DbgPrint (
"MiLoadImageSection: Error 0x%x in session space mapping via MmMapViewOfSection\n",
Status);
01860 }
01861
#endif
01862
01863 CommittedPages =
MiDeleteSystemPagableVm (
01864
MiGetPteAddress (BaseAddress),
01865
BYTES_TO_PAGES (SectionSize),
01866
ZeroKernelPte,
01867
TRUE,
01868
NULL);
01869
01870
LOCK_SESSION_SPACE_WS (OldIrql);
01871
MmSessionSpace->
CommittedPages -= CommittedPages;
01872
01873
MM_BUMP_SESS_COUNTER(
MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED1,
01874 CommittedPages);
01875
01876
UNLOCK_SESSION_SPACE_WS (OldIrql);
01877
01878
01879
01880
01881
01882
01883
01884
MiRemoveImageSessionWide (BaseAddress);
01885 }
01886
else {
01887
LOCK_PFN (OldIrql);
01888
MmResidentAvailablePages += PagesRequired;
01889
MM_BUMP_COUNTER(16, PagesRequired);
01890
UNLOCK_PFN (OldIrql);
01891
MiReleaseSystemPtes (FirstPte,
01892 SectionPointer->Segment->TotalNumberOfPtes,
01893
SystemPteSpace);
01894 }
01895
01896
return Status;
01897 }
01898
01899
01900
01901
01902
01903
01904
01905 ProtoPte = SectionPointer->Segment->PrototypePte;
01906 NumberOfPtes = SectionPointer->Segment->TotalNumberOfPtes;
01907
01908 *ImageBaseAddress = SystemVa;
01909
01910 UserVa = Base;
01911 TempPte =
ValidKernelPte;
01912
#if defined(_IA64_)
01913
TempPte.
u.Long |=
MM_PTE_EXECUTE;
01914
#endif
01915
01916
while (NumberOfPtes != 0) {
01917 PteContents = *ProtoPte;
01918
if ((PteContents.
u.Hard.Valid == 1) ||
01919 (PteContents.
u.Soft.Protection !=
MM_NOACCESS)) {
01920
01921
if (LoadInSessionSpace ==
FALSE) {
01922
LOCK_PFN (OldIrql);
01923
MiEnsureAvailablePageOrWait (
NULL,
NULL);
01924 PageFrameIndex =
MiRemoveAnyPage(
01925
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
01926 PointerPte->u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
01927
#if defined(_IA64_)
01928
01929
01930
01931
01932
01933 PointerPte->u.Soft.Protection |=
MM_EXECUTE;
01934
01935
#endif
01936
MiInitializePfn (PageFrameIndex, PointerPte, 1);
01937
01938
UNLOCK_PFN (OldIrql);
01939 TempPte.
u.Hard.PageFrameNumber = PageFrameIndex;
01940
MI_WRITE_VALID_PTE (PointerPte, TempPte);
01941 LastPte = PointerPte;
01942
01943
ASSERT (
MI_PFN_ELEMENT (PageFrameIndex)->u1.WsIndex == 0);
01944 }
01945
01946
try {
01947
01948 RtlMoveMemory (SystemVa, UserVa,
PAGE_SIZE);
01949
01950 } except (
MiMapCacheExceptionFilter (&ExceptionStatus,
01951 GetExceptionInformation())) {
01952
01953
01954
01955
01956
01957
01958
#if DBG
01959
DbgPrint(
"MiLoadImageSection: Exception 0x%x copying driver SystemVa 0x%p, UserVa 0x%p\n",ExceptionStatus,SystemVa,UserVa);
01960
#endif
01961
01962
if (LoadInSessionSpace ==
TRUE) {
01963
ASSERT (
MiHydra ==
TRUE);
01964 CommittedPages =
MiDeleteSystemPagableVm (
01965
MiGetPteAddress (BaseAddress),
01966
BYTES_TO_PAGES (SectionSize),
01967
ZeroKernelPte,
01968
TRUE,
01969
NULL);
01970
01971
LOCK_SESSION_SPACE_WS (OldIrql);
01972
MmSessionSpace->
CommittedPages -= CommittedPages;
01973
01974
MM_BUMP_SESS_COUNTER(
MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED2,
01975 CommittedPages);
01976
01977
UNLOCK_SESSION_SPACE_WS (OldIrql);
01978
01979
01980
01981
01982
01983
01984
01985
01986
MiReturnCommitment (CommittedPages);
01987
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_SESSION_DRIVER_LOAD_FAILURE1, CommittedPages);
01988 }
01989
else {
01990 ProtoPte = FirstPte;
01991
LOCK_PFN (OldIrql);
01992
while (ProtoPte <= PointerPte) {
01993
if (ProtoPte->u.Hard.Valid == 1) {
01994
01995
01996
01997
01998
01999 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (ProtoPte);
02000
02001
02002
02003
02004
02005
02006 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
02007
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
02008
MI_SET_PFN_DELETED (Pfn1);
02009
MiDecrementShareCountOnly (PageFrameIndex);
02010
02011
MI_WRITE_INVALID_PTE (ProtoPte,
ZeroPte);
02012 }
02013 ProtoPte += 1;
02014 }
02015
02016
MmResidentAvailablePages += PagesRequired;
02017
MM_BUMP_COUNTER(17, PagesRequired);
02018
UNLOCK_PFN (OldIrql);
02019
MiReleaseSystemPtes (FirstPte,
02020 SectionPointer->Segment->TotalNumberOfPtes,
02021
SystemPteSpace);
02022 }
02023
02024
Status =
MmUnmapViewOfSection (TargetProcess, Base);
02025
02026
ASSERT (
NT_SUCCESS (
Status));
02027
02028
if (TargetProcess != Process) {
02029
KeDetachProcess();
02030
if (ProcessReferenced ==
TRUE) {
02031
ObDereferenceObject (TargetProcess);
02032 }
02033 }
02034
02035
if (LoadInSessionSpace ==
TRUE) {
02036
MiRemoveImageSessionWide (BaseAddress);
02037 }
02038
02039
return ExceptionStatus;
02040 }
02041
02042 }
02043
else {
02044
02045
02046
02047
02048
02049
02050
02051
if (LoadInSessionSpace ==
TRUE) {
02052
ASSERT (
MiHydra ==
TRUE);
02053 CommittedPages =
MiDeleteSystemPagableVm (
02054
MiGetPteAddress (SystemVa),
02055 1,
02056
ZeroKernelPte,
02057
TRUE,
02058
NULL);
02059
02060
MM_BUMP_SESS_COUNTER(
MM_DBG_SESSION_COMMIT_IMAGELOAD_NOACCESS,
02061 1);
02062 }
02063
else {
02064
MI_WRITE_INVALID_PTE (PointerPte,
ZeroKernelPte);
02065 }
02066 }
02067
02068 NumberOfPtes -= 1;
02069 ProtoPte += 1;
02070 PointerPte += 1;
02071 SystemVa = ((PCHAR)SystemVa +
PAGE_SIZE);
02072 UserVa = ((PCHAR)UserVa +
PAGE_SIZE);
02073 }
02074
02075
Status =
MmUnmapViewOfSection (TargetProcess, Base);
02076
ASSERT (
NT_SUCCESS (
Status));
02077
02078
if (TargetProcess != Process) {
02079
KeDetachProcess();
02080
if (ProcessReferenced ==
TRUE) {
02081
ObDereferenceObject (TargetProcess);
02082 }
02083 }
02084
02085
02086
02087
02088
02089 SectionPointer->Segment->SystemImageBase = *ImageBaseAddress;
02090
02091
02092
02093
02094
02095
02096
if (LoadInSessionSpace ==
FALSE) {
02097
MiChargeCommitmentCantExpand (PagesRequired,
TRUE);
02098
MM_TRACK_COMMIT (
MM_DBG_COMMIT_DRIVER_PAGES, PagesRequired);
02099
MmDriverCommit += (ULONG)PagesRequired;
02100 }
02101
02102
return Status;
02103 }
02104
02105
VOID
02106 MmFreeDriverInitialization (
02107 IN PVOID ImageHandle
02108 )
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 PLDR_DATA_TABLE_ENTRY DataTableEntry;
02135
PMMPTE PointerPte;
02136
PMMPTE LastPte;
02137 PFN_NUMBER NumberOfPtes;
02138 PVOID Base;
02139 ULONG i;
02140 PIMAGE_NT_HEADERS NtHeaders;
02141 PIMAGE_SECTION_HEADER NtSection;
02142 PIMAGE_SECTION_HEADER FoundSection;
02143 PFN_NUMBER PagesDeleted;
02144
02145
MmLockPagableSectionByHandle(
ExPageLockHandle);
02146 DataTableEntry = (PLDR_DATA_TABLE_ENTRY)ImageHandle;
02147 Base = DataTableEntry->DllBase;
02148
02149
ASSERT (
MI_IS_SESSION_ADDRESS (Base) ==
FALSE);
02150
02151 NumberOfPtes = DataTableEntry->SizeOfImage >>
PAGE_SHIFT;
02152 LastPte =
MiGetPteAddress (Base) + NumberOfPtes;
02153
02154 NtHeaders = (PIMAGE_NT_HEADERS)
RtlImageNtHeader(Base);
02155
02156 NtSection = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders +
02157
sizeof(ULONG) +
02158
sizeof(IMAGE_FILE_HEADER) +
02159 NtHeaders->FileHeader.SizeOfOptionalHeader
02160 );
02161
02162 NtSection += NtHeaders->FileHeader.NumberOfSections;
02163
02164 FoundSection =
NULL;
02165
for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i += 1) {
02166 NtSection -= 1;
02167
if ((NtSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0) {
02168 FoundSection = NtSection;
02169 }
else {
02170
02171
02172
02173
02174
02175
02176
02177
break;
02178 }
02179 }
02180
02181
if (FoundSection !=
NULL) {
02182
02183 PointerPte =
MiGetPteAddress (
ROUND_TO_PAGES (
02184 (PCHAR)Base + FoundSection->VirtualAddress));
02185 NumberOfPtes = (PFN_NUMBER)(LastPte - PointerPte);
02186
02187 PagesDeleted =
MiDeleteSystemPagableVm (PointerPte,
02188 NumberOfPtes,
02189
ZeroKernelPte,
02190
FALSE,
02191
NULL);
02192
02193
MmResidentAvailablePages += PagesDeleted;
02194
MM_BUMP_COUNTER(18, PagesDeleted);
02195
MiReturnCommitment (PagesDeleted);
02196
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_DRIVER_INIT_CODE, PagesDeleted);
02197
MmDriverCommit -= (ULONG)PagesDeleted;
02198
#if DBG
02199
MiPagesConsumed -= PagesDeleted;
02200
#endif
02201
}
02202
02203
MmUnlockPagableImageSection(
ExPageLockHandle);
02204
return;
02205 }
02206
02207
VOID
02208 MiEnablePagingOfDriver (
02209 IN PVOID ImageHandle
02210 )
02211
02212 {
02213 PLDR_DATA_TABLE_ENTRY DataTableEntry;
02214
PMMPTE LastPte;
02215
PMMPTE PointerPte;
02216 PVOID Base;
02217 ULONG i;
02218 PIMAGE_NT_HEADERS NtHeaders;
02219 PIMAGE_SECTION_HEADER FoundSection;
02220 PIMAGE_OPTIONAL_HEADER OptionalHeader;
02221
02222
02223
02224
02225
02226
if (
MmDisablePagingExecutive) {
02227
return;
02228 }
02229
02230
02231
02232
02233
02234 DataTableEntry = (PLDR_DATA_TABLE_ENTRY)ImageHandle;
02235 Base = DataTableEntry->DllBase;
02236
02237 NtHeaders = (PIMAGE_NT_HEADERS)
RtlImageNtHeader(Base);
02238
02239 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)((PCHAR)NtHeaders +
02240
#if defined (_WIN64)
02241
FIELD_OFFSET (IMAGE_NT_HEADERS64, OptionalHeader));
02242
#else
02243
FIELD_OFFSET (IMAGE_NT_HEADERS32, OptionalHeader));
02244
#endif
02245
02246 FoundSection = IMAGE_FIRST_SECTION (NtHeaders);
02247
02248 i = NtHeaders->FileHeader.NumberOfSections;
02249
02250 PointerPte =
NULL;
02251
02252
while (i > 0) {
02253
#if DBG
02254
if ((*(PULONG)FoundSection->Name == 'tini') ||
02255 (*(PULONG)FoundSection->Name == 'egap')) {
02256
DbgPrint(
"driver %wZ has lower case sections (init or pagexxx)\n",
02257 &DataTableEntry->FullDllName);
02258 }
02259
#endif //DBG
02260
02261
02262
02263
02264
02265
02266
if ((*(PULONG)FoundSection->Name == 'EGAP') ||
02267 (*(PULONG)FoundSection->Name == 'ade.')) {
02268
02269
02270
02271
02272
02273
if (PointerPte ==
NULL) {
02274
02275
02276
02277
02278
02279 PointerPte =
MiGetPteAddress (
ROUND_TO_PAGES (
02280 (PCHAR)Base + FoundSection->VirtualAddress));
02281 }
02282 LastPte =
MiGetPteAddress ((PCHAR)Base +
02283 FoundSection->VirtualAddress +
02284 (OptionalHeader->SectionAlignment - 1) +
02285 FoundSection->SizeOfRawData -
PAGE_SIZE);
02286
02287 }
else {
02288
02289
02290
02291
02292
02293
02294
if (PointerPte !=
NULL) {
02295
MiSetPagingOfDriver (PointerPte, LastPte,
FALSE);
02296 PointerPte =
NULL;
02297 }
02298 }
02299 i -= 1;
02300 FoundSection += 1;
02301 }
02302
if (PointerPte !=
NULL) {
02303
MiSetPagingOfDriver (PointerPte, LastPte,
FALSE);
02304 }
02305 }
02306
02307
02308
VOID
02309 MiSetPagingOfDriver (
02310 IN
PMMPTE PointerPte,
02311 IN
PMMPTE LastPte,
02312 IN BOOLEAN SessionSpace
02313 )
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333 {
02334 PVOID Base;
02335 PFN_NUMBER PageCount;
02336 PFN_NUMBER PageFrameIndex;
02337
PMMPFN Pfn;
02338
MMPTE TempPte;
02339
MMPTE PreviousPte;
02340 KIRQL OldIrql1;
02341 KIRQL OldIrql;
02342
02343
PAGED_CODE ();
02344
02345
ASSERT ((SessionSpace ==
FALSE) ||
02346 (
MmIsAddressValid(
MmSessionSpace) ==
TRUE));
02347
02348
if (
MI_IS_PHYSICAL_ADDRESS(
MiGetVirtualAddressMappedByPte(PointerPte))) {
02349
02350
02351
02352
02353
02354
return;
02355 }
02356
02357 PageCount = 0;
02358
02359
02360
02361
02362
02363
MmLockPagableSectionByHandle(
ExPageLockHandle);
02364
02365
if (SessionSpace ==
TRUE) {
02366
LOCK_SESSION_SPACE_WS (OldIrql1);
02367 }
02368
else {
02369
LOCK_SYSTEM_WS (OldIrql1);
02370 }
02371
02372
LOCK_PFN (OldIrql);
02373
02374 Base =
MiGetVirtualAddressMappedByPte (PointerPte);
02375
02376
while (PointerPte <= LastPte) {
02377
02378
02379
02380
02381
02382
02383
02384
02385
if (PointerPte->u.Hard.Valid == 1) {
02386 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
02387 Pfn =
MI_PFN_ELEMENT (PageFrameIndex);
02388
ASSERT (Pfn->
u2.ShareCount == 1);
02389
02390
if (Pfn->
u1.WsIndex == 0) {
02391
02392
02393
02394
02395
02396
02397
if (Pfn->
OriginalPte.
u.Long == 0) {
02398 Pfn->
OriginalPte.
u.Long =
MM_KERNEL_DEMAND_ZERO_PTE;
02399
#if defined(_IA64_)
02400
Pfn->
OriginalPte.
u.Soft.Protection |=
MM_EXECUTE;
02401
#endif
02402
}
02403
02404 TempPte = *PointerPte;
02405
02406
MI_MAKE_VALID_PTE_TRANSITION (TempPte,
02407 Pfn->
OriginalPte.
u.Soft.Protection);
02408
02409 PreviousPte.
u.Flush =
KeFlushSingleTb (Base,
02410
TRUE,
02411
TRUE,
02412 (PHARDWARE_PTE)PointerPte,
02413 TempPte.
u.Flush);
02414
02415
MI_CAPTURE_DIRTY_BIT_TO_PFN (&PreviousPte, Pfn);
02416
02417
02418
02419
02420
02421
02422
02423
02424
MiDecrementShareCount (PageFrameIndex);
02425
MmResidentAvailablePages += 1;
02426
MM_BUMP_COUNTER(19, 1);
02427
MmTotalSystemDriverPages += 1;
02428 PageCount += 1;
02429 }
02430
else {
02431
02432
02433
02434
02435
02436 }
02437 }
02438 Base = (PVOID)((PCHAR)Base +
PAGE_SIZE);
02439 PointerPte += 1;
02440 }
02441
02442
if (SessionSpace ==
TRUE) {
02443
02444
02445
02446
02447
02448
MI_FLUSH_ENTIRE_SESSION_TB (
TRUE,
TRUE);
02449 }
02450
02451
UNLOCK_PFN (OldIrql);
02452
02453
if (SessionSpace ==
TRUE) {
02454
02455
02456
02457
02458
02459
MmSessionSpace->
NonPagablePages -= PageCount;
02460
MM_BUMP_SESS_COUNTER(
MM_DBG_SESSION_DRIVER_PAGES_UNLOCKED, PageCount);
02461
02462
UNLOCK_SESSION_SPACE_WS (OldIrql1);
02463 }
02464
else {
02465
UNLOCK_SYSTEM_WS (OldIrql1);
02466 }
02467
MmUnlockPagableImageSection(
ExPageLockHandle);
02468 }
02469
02470
02471 PVOID
02472 MmPageEntireDriver (
02473 IN PVOID AddressWithinSection
02474 )
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501 {
02502 PLDR_DATA_TABLE_ENTRY DataTableEntry;
02503
PMMPTE FirstPte;
02504
PMMPTE LastPte;
02505 PVOID BaseAddress;
02506
PSECTION SectionPointer;
02507 BOOLEAN SessionSpace;
02508
02509
PAGED_CODE();
02510
02511
02512
02513
02514
02515 DataTableEntry =
MiLookupDataTableEntry (AddressWithinSection,
FALSE);
02516
02517
if (DataTableEntry ==
NULL) {
02518
return NULL;
02519 }
02520
02521 SectionPointer = (
PSECTION)DataTableEntry->SectionPointer;
02522
02523
if (
MmDisablePagingExecutive) {
02524
return DataTableEntry->DllBase;
02525 }
02526
02527 SessionSpace =
MI_IS_SESSION_IMAGE_ADDRESS (AddressWithinSection);
02528
02529
if ((SectionPointer !=
NULL) && (SectionPointer != (PVOID)-1)) {
02530
02531
02532
02533
02534
02535
02536
02537
02538
if (SessionSpace ==
TRUE) {
02539
if (SectionPointer->Segment &&
02540 SectionPointer->Segment->BasedAddress == SectionPointer->Segment->SystemImageBase) {
02541
return DataTableEntry->DllBase;
02542 }
02543 }
02544
else {
02545
return DataTableEntry->DllBase;
02546 }
02547 }
02548
02549 BaseAddress = DataTableEntry->DllBase;
02550 FirstPte =
MiGetPteAddress (BaseAddress);
02551 LastPte = (FirstPte - 1) + (DataTableEntry->SizeOfImage >>
PAGE_SHIFT);
02552
02553
MiSetPagingOfDriver (FirstPte, LastPte, SessionSpace);
02554
02555
return BaseAddress;
02556 }
02557
02558
02559
VOID
02560 MmResetDriverPaging (
02561 IN PVOID AddressWithinSection
02562 )
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589 {
02590 PLDR_DATA_TABLE_ENTRY DataTableEntry;
02591
PMMPTE LastPte;
02592
PMMPTE PointerPte;
02593 PVOID Base;
02594 ULONG i;
02595 PIMAGE_NT_HEADERS NtHeaders;
02596 PIMAGE_SECTION_HEADER FoundSection;
02597 KIRQL OldIrql;
02598 KIRQL OldIrqlWs;
02599
02600
PAGED_CODE();
02601
02602
02603
02604
02605
02606
if (
MmDisablePagingExecutive) {
02607
return;
02608 }
02609
02610
if (
MI_IS_PHYSICAL_ADDRESS(AddressWithinSection)) {
02611
return;
02612 }
02613
02614
02615
02616
02617
02618 DataTableEntry =
MiLookupDataTableEntry (AddressWithinSection,
FALSE);
02619
02620
if ((DataTableEntry->SectionPointer !=
NULL) &&
02621 (DataTableEntry->SectionPointer != (PVOID)-1)) {
02622
02623
02624
02625
02626
02627
return;
02628 }
02629
02630 Base = DataTableEntry->DllBase;
02631
02632 NtHeaders = (PIMAGE_NT_HEADERS)
RtlImageNtHeader(Base);
02633
02634 FoundSection = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeaders +
02635
sizeof(ULONG) +
02636
sizeof(IMAGE_FILE_HEADER) +
02637 NtHeaders->FileHeader.SizeOfOptionalHeader
02638 );
02639
02640 i = NtHeaders->FileHeader.NumberOfSections;
02641 PointerPte =
NULL;
02642
02643
while (i > 0) {
02644
#if DBG
02645
if ((*(PULONG)FoundSection->Name == 'tini') ||
02646 (*(PULONG)FoundSection->Name == 'egap')) {
02647
DbgPrint(
"driver %wZ has lower case sections (init or pagexxx)\n",
02648 &DataTableEntry->FullDllName);
02649 }
02650
#endif
02651
02652
02653
02654
02655
02656
02657
02658
if (((FoundSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0) ||
02659 (*(PULONG)FoundSection->Name == 'EGAP') ||
02660 (*(PULONG)FoundSection->Name == 'ade.') ||
02661 (*(PULONG)FoundSection->Name == 'TINI')) {
02662
02663 NOTHING;
02664
02665 }
else {
02666
02667
02668
02669
02670
02671 PointerPte =
MiGetPteAddress (
02672 (PCHAR)Base + FoundSection->VirtualAddress);
02673 LastPte =
MiGetPteAddress ((PCHAR)Base +
02674 FoundSection->VirtualAddress +
02675 (FoundSection->SizeOfRawData - 1));
02676
ASSERT (PointerPte <= LastPte);
02677
MmLockPagableSectionByHandle(
ExPageLockHandle);
02678
LOCK_SYSTEM_WS (OldIrqlWs);
02679
LOCK_PFN (OldIrql);
02680
MiLockCode (PointerPte, LastPte,
MM_LOCK_BY_NONPAGE);
02681
UNLOCK_PFN (OldIrql);
02682
UNLOCK_SYSTEM_WS (OldIrqlWs);
02683
MmUnlockPagableImageSection(
ExPageLockHandle);
02684 }
02685 i -= 1;
02686 FoundSection += 1;
02687 }
02688
return;
02689 }
02690
02691
02692
VOID
02693 MiClearImports(
02694 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
02695 )
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713 {
02714
PAGED_CODE();
02715
02716
if (DataTableEntry->LoadedImports == (PVOID)
LOADED_AT_BOOT) {
02717
return;
02718 }
02719
02720
if (DataTableEntry->LoadedImports == (PVOID)
NO_IMPORTS_USED) {
02721 NOTHING;
02722 }
02723
else if (
SINGLE_ENTRY(DataTableEntry->LoadedImports)) {
02724 NOTHING;
02725 }
02726
else {
02727
02728
02729
02730
ExFreePool ((PVOID)DataTableEntry->LoadedImports);
02731 }
02732
02733
02734
02735
02736 DataTableEntry->LoadedImports = (PVOID)
LOADED_AT_BOOT;
02737 }
02738
02739
VOID
02740 MiRememberUnloadedDriver (
02741 IN PUNICODE_STRING DriverName,
02742 IN PVOID Address,
02743 IN ULONG Length
02744 )
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767 {
02768
PUNLOADED_DRIVERS Entry;
02769 ULONG NumberOfBytes;
02770
02771
if (DriverName->Length == 0) {
02772
02773
02774
02775
02776
02777
02778
return;
02779 }
02780
02781
02782
02783
02784
02785
02786
02787
if (
MiUnloadedDrivers ==
NULL) {
02788 NumberOfBytes =
MI_UNLOADED_DRIVERS *
sizeof (
UNLOADED_DRIVERS);
02789
02790
MiUnloadedDrivers = (
PUNLOADED_DRIVERS)
ExAllocatePoolWithTag (
NonPagedPool,
02791 NumberOfBytes,
02792 'TDmM');
02793
if (
MiUnloadedDrivers ==
NULL) {
02794
return;
02795 }
02796 RtlZeroMemory (
MiUnloadedDrivers, NumberOfBytes);
02797
MiLastUnloadedDriver = 0;
02798 }
02799
else if (
MiLastUnloadedDriver >=
MI_UNLOADED_DRIVERS) {
02800
MiLastUnloadedDriver = 0;
02801 }
02802
02803 Entry = &
MiUnloadedDrivers[
MiLastUnloadedDriver];
02804
02805
02806
02807
02808
02809
RtlFreeUnicodeString (&Entry->
Name);
02810
02811 Entry->
Name.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
02812 DriverName->Length,
02813 'TDmM');
02814
02815
if (Entry->
Name.Buffer ==
NULL) {
02816 Entry->
Name.MaximumLength = 0;
02817 Entry->
Name.Length = 0;
02818
MiUnloadsSkipped += 1;
02819
return;
02820 }
02821
02822 RtlMoveMemory(Entry->
Name.Buffer, DriverName->Buffer, DriverName->Length);
02823 Entry->
Name.Length = DriverName->Length;
02824 Entry->
Name.MaximumLength = DriverName->MaximumLength;
02825
02826 Entry->
StartAddress = Address;
02827 Entry->
EndAddress = (PVOID)((PCHAR)Address + Length);
02828
02829
KeQuerySystemTime (&Entry->
CurrentTime);
02830
02831
MiTotalUnloads += 1;
02832
MiLastUnloadedDriver += 1;
02833 }
02834
02835 PUNICODE_STRING
02836 MmLocateUnloadedDriver (
02837 IN PVOID VirtualAddress
02838 )
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862 {
02863
PUNLOADED_DRIVERS Entry;
02864 ULONG i;
02865 ULONG
Index;
02866
02867
02868
02869
02870
02871
if (
MiUnloadedDrivers ==
NULL) {
02872
return NULL;
02873 }
02874
02875
Index =
MiLastUnloadedDriver - 1;
02876
02877
for (i = 0; i <
MI_UNLOADED_DRIVERS; i += 1) {
02878
if (
Index >=
MI_UNLOADED_DRIVERS) {
02879
Index =
MI_UNLOADED_DRIVERS - 1;
02880 }
02881 Entry = &
MiUnloadedDrivers[
Index];
02882
if (Entry->
Name.Buffer !=
NULL) {
02883
if ((VirtualAddress >= Entry->
StartAddress) &&
02884 (VirtualAddress < Entry->
EndAddress)) {
02885
return &Entry->
Name;
02886 }
02887 }
02888
Index -= 1;
02889 }
02890
02891
return NULL;
02892 }
02893
02894
02895
NTSTATUS
02896 MmUnloadSystemImage (
02897 IN PVOID ImageHandle
02898 )
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918 {
02919 PLDR_DATA_TABLE_ENTRY DataTableEntry;
02920
PMMPTE LastPte;
02921 PFN_NUMBER PagesRequired;
02922 PFN_NUMBER ResidentPages;
02923
PMMPTE PointerPte;
02924 PFN_NUMBER NumberOfPtes;
02925 KIRQL OldIrql;
02926 PVOID BasedAddress;
02927 SIZE_T NumberOfBytes;
02928 BOOLEAN MustFree;
02929 SIZE_T CommittedPages;
02930 BOOLEAN ViewDeleted;
02931
PIMAGE_ENTRY_IN_SESSION DriverImage;
02932
NTSTATUS Status;
02933 PVOID StillQueued;
02934
PSECTION SectionPointer;
02935
02936
02937
02938
02939
02940
KeEnterCriticalRegion();
02941
02942
KeWaitForSingleObject (&
MmSystemLoadLock,
02943
WrVirtualMemory,
02944
KernelMode,
02945
FALSE,
02946 (PLARGE_INTEGER)
NULL);
02947
02948
MmLockPagableSectionByHandle(
ExPageLockHandle);
02949
02950 ViewDeleted =
FALSE;
02951 DataTableEntry = (PLDR_DATA_TABLE_ENTRY)ImageHandle;
02952 BasedAddress = DataTableEntry->DllBase;
02953
02954
#if DBGXX
02955
02956
02957
02958
02959
if (
PsLoadedModuleList.Flink) {
02960 LOGICAL Found;
02961 PLIST_ENTRY NextEntry;
02962 PLDR_DATA_TABLE_ENTRY DataTableEntry2;
02963
02964 Found =
FALSE;
02965 NextEntry =
PsLoadedModuleList.Flink;
02966
while (NextEntry != &
PsLoadedModuleList) {
02967
02968 DataTableEntry2 = CONTAINING_RECORD(NextEntry,
02969 LDR_DATA_TABLE_ENTRY,
02970 InLoadOrderLinks);
02971
if (DataTableEntry == DataTableEntry2) {
02972 Found =
TRUE;
02973
break;
02974 }
02975 NextEntry = NextEntry->Flink;
02976 }
02977
ASSERT (Found ==
TRUE);
02978 }
02979
#endif
02980
02981
#if DBG_SYSLOAD
02982
if (DataTableEntry->SectionPointer ==
NULL) {
02983
DbgPrint (
"MM: Called to unload boot driver %wZ\n",
02984 &DataTableEntry->FullDllName);
02985 }
02986
else {
02987
DbgPrint (
"MM: Called to unload non-boot driver %wZ\n",
02988 &DataTableEntry->FullDllName);
02989 }
02990
#endif
02991
02992
02993
02994
02995
02996
02997
02998
if (DataTableEntry->LoadedImports == (PVOID)
LOADED_AT_BOOT) {
02999
MmUnlockPagableImageSection(
ExPageLockHandle);
03000
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
03001
KeLeaveCriticalRegion();
03002
return STATUS_SUCCESS;
03003 }
03004
03005
ASSERT (DataTableEntry->LoadCount != 0);
03006
03007
if (
MI_IS_SESSION_IMAGE_ADDRESS (BasedAddress)) {
03008
03009
03010
03011
03012
03013
03014 DriverImage =
MiSessionLookupImage (BasedAddress);
03015
03016
ASSERT (DriverImage);
03017
03018
ASSERT (DriverImage->
ImageCountInThisSession);
03019
03020
if (DriverImage->
ImageCountInThisSession > 1) {
03021
03022 DriverImage->
ImageCountInThisSession -= 1;
03023
MmUnlockPagableImageSection(
ExPageLockHandle);
03024
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
03025
KeLeaveCriticalRegion();
03026
03027
return STATUS_SUCCESS;
03028 }
03029
03030
03031
03032
03033
03034
03035
Status =
MiSessionWideGetImageSize (BasedAddress,
03036 &NumberOfBytes,
03037 &CommittedPages);
03038
03039
if (!
NT_SUCCESS(
Status)) {
03040
03041
KeBugCheckEx (MEMORY_MANAGEMENT,
03042 0x41286,
03043 (ULONG_PTR)
MmSessionSpace->
SessionId,
03044 (ULONG_PTR)BasedAddress,
03045 0);
03046 }
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056 PointerPte =
MiGetPteAddress (BasedAddress);
03057 LastPte =
MiGetPteAddress ((ULONG_PTR)BasedAddress + NumberOfBytes);
03058
03059 PagesRequired =
MiDeleteSystemPagableVm (PointerPte,
03060 (PFN_NUMBER)(LastPte - PointerPte),
03061
ZeroKernelPte,
03062
TRUE,
03063 &ResidentPages);
03064
03065
if (
MmDisablePagingExecutive == 0) {
03066
03067 SectionPointer = (
PSECTION)DataTableEntry->SectionPointer;
03068
03069
if ((SectionPointer ==
NULL) ||
03070 (SectionPointer == (PVOID)-1) ||
03071 (SectionPointer->Segment ==
NULL) ||
03072 (SectionPointer->Segment->BasedAddress != SectionPointer->Segment->SystemImageBase)) {
03073
03074
MmTotalSystemDriverPages -= (ULONG)(PagesRequired - ResidentPages);
03075 }
03076 }
03077
03078
LOCK_SESSION_SPACE_WS (OldIrql);
03079
MmSessionSpace->
CommittedPages -= CommittedPages;
03080
03081
MM_BUMP_SESS_COUNTER(
MM_DBG_SESSION_COMMIT_IMAGE_UNLOAD,
03082 CommittedPages);
03083
03084
UNLOCK_SESSION_SPACE_WS (OldIrql);
03085
03086 ViewDeleted =
TRUE;
03087
03088
03089
03090
03091
03092
03093
MiReturnCommitment (CommittedPages);
03094
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD, CommittedPages);
03095
03096
03097
03098
03099
03100
03101
Status =
MiRemoveImageSessionWide (BasedAddress);
03102
03103
ASSERT (
NT_SUCCESS (
Status));
03104 }
03105
03106
ASSERT (DataTableEntry->LoadCount != 0);
03107
03108 DataTableEntry->LoadCount -= 1;
03109
03110
if (DataTableEntry->LoadCount != 0) {
03111
MmUnlockPagableImageSection(
ExPageLockHandle);
03112
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
03113
KeLeaveCriticalRegion();
03114
return STATUS_SUCCESS;
03115 }
03116
03117
#if DBG
03118
if (
MI_IS_SESSION_IMAGE_ADDRESS (BasedAddress)) {
03119
ASSERT (
MiSessionLookupImage (BasedAddress) ==
NULL);
03120 }
03121
#endif
03122
03123
if (
MmSnapUnloads) {
03124
#if 0
03125
StillQueued =
KeCheckForTimer (DataTableEntry->DllBase,
03126 DataTableEntry->SizeOfImage);
03127
03128
if (StillQueued !=
NULL) {
03129
KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
03130 0x18,
03131 (ULONG_PTR)StillQueued,
03132 (ULONG_PTR)-1,
03133 (ULONG_PTR)DataTableEntry->DllBase);
03134 }
03135
03136 StillQueued =
ExpCheckForResource (DataTableEntry->DllBase,
03137 DataTableEntry->SizeOfImage);
03138
03139
if (StillQueued !=
NULL) {
03140
KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
03141 0x19,
03142 (ULONG_PTR)StillQueued,
03143 (ULONG_PTR)-1,
03144 (ULONG_PTR)DataTableEntry->DllBase);
03145 }
03146
#endif
03147
}
03148
03149
if (DataTableEntry->Flags & LDRP_IMAGE_VERIFYING) {
03150
MiVerifyingDriverUnloading (DataTableEntry);
03151 }
03152
03153
if (
MiActiveVerifierThunks != 0) {
03154
MiVerifierCheckThunks (DataTableEntry);
03155 }
03156
03157
03158
03159
03160
03161
if (DataTableEntry->Flags & LDRP_DEBUG_SYMBOLS_LOADED) {
03162
03163
03164
03165
03166
03167 ANSI_STRING AnsiName;
03168
NTSTATUS Status;
03169
03170
Status =
RtlUnicodeStringToAnsiString( &AnsiName,
03171 &DataTableEntry->BaseDllName,
03172
TRUE );
03173
03174
if (
NT_SUCCESS(
Status)) {
03175 DbgUnLoadImageSymbols( &AnsiName,
03176 BasedAddress,
03177 (ULONG)-1);
03178
RtlFreeAnsiString( &AnsiName );
03179 }
03180 }
03181
03182
03183
03184
03185
03186
03187
03188
if (ViewDeleted ==
FALSE) {
03189
03190 NumberOfPtes = DataTableEntry->SizeOfImage >>
PAGE_SHIFT;
03191
03192
if (
MmSnapUnloads) {
03193
MiRememberUnloadedDriver (&DataTableEntry->BaseDllName,
03194 BasedAddress,
03195 (ULONG)(NumberOfPtes <<
PAGE_SHIFT));
03196 }
03197
03198
if (DataTableEntry->Flags & LDRP_SYSTEM_MAPPED) {
03199
03200 PointerPte =
MiGetPteAddress (BasedAddress);
03201
03202 PagesRequired =
MiDeleteSystemPagableVm (PointerPte,
03203 NumberOfPtes,
03204
ZeroKernelPte,
03205
FALSE,
03206 &ResidentPages);
03207
03208
MmTotalSystemDriverPages -= (ULONG)(PagesRequired - ResidentPages);
03209
03210
03211
03212
03213
03214
03215
MiReleaseSystemPtes (PointerPte,
03216 (ULONG)NumberOfPtes,
03217
SystemPteSpace);
03218
03219
LOCK_PFN (OldIrql);
03220
MmResidentAvailablePages += ResidentPages;
03221
MM_BUMP_COUNTER(21, ResidentPages);
03222
UNLOCK_PFN (OldIrql);
03223
03224
03225
03226
03227
03228
03229
if (DataTableEntry->SectionPointer !=
NULL) {
03230
MiReturnCommitment (PagesRequired);
03231
MM_TRACK_COMMIT (
MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD1, PagesRequired);
03232
MmDriverCommit -= (ULONG)PagesRequired;
03233 }
03234 }
03235
else {
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249 }
03250 }
03251
03252
03253
03254
03255
03256
03257
03258
03259
if (DataTableEntry->InLoadOrderLinks.Flink !=
NULL) {
03260
KeEnterCriticalRegion();
03261
ExAcquireResourceExclusive (&
PsLoadedModuleResource,
TRUE);
03262
03263 ExAcquireSpinLock (&
PsLoadedModuleSpinLock, &OldIrql);
03264
03265 RemoveEntryList(&DataTableEntry->InLoadOrderLinks);
03266 ExReleaseSpinLock (&
PsLoadedModuleSpinLock, OldIrql);
03267
03268
ExReleaseResource (&
PsLoadedModuleResource);
03269
KeLeaveCriticalRegion();
03270
03271 MustFree =
TRUE;
03272 }
03273
else {
03274 MustFree =
FALSE;
03275 }
03276
03277
03278
03279
03280
03281
03282
MiDereferenceImports ((
PLOAD_IMPORTS)DataTableEntry->LoadedImports);
03283
03284
MiClearImports (DataTableEntry);
03285
03286
03287
03288
03289
03290
if (MustFree ==
TRUE) {
03291
03292
if (DataTableEntry->FullDllName.Buffer !=
NULL) {
03293
ExFreePool (DataTableEntry->FullDllName.Buffer);
03294 }
03295
03296
if (DataTableEntry->BaseDllName.Buffer !=
NULL) {
03297
ExFreePool (DataTableEntry->BaseDllName.Buffer);
03298 }
03299
03300
03301
03302
03303
03304
03305
if ((DataTableEntry->SectionPointer !=
NULL) &&
03306 (DataTableEntry->SectionPointer != (PVOID)-1)) {
03307
03308
ObDereferenceObject (DataTableEntry->SectionPointer);
03309 }
03310
03311
ExFreePool((PVOID)DataTableEntry);
03312 }
03313
03314
MmUnlockPagableImageSection(
ExPageLockHandle);
03315
03316
KeReleaseMutant (&
MmSystemLoadLock, 1,
FALSE,
FALSE);
03317
KeLeaveCriticalRegion();
03318
03319
PERFINFO_IMAGE_UNLOAD(BasedAddress);
03320
03321
return STATUS_SUCCESS;
03322 }
03323
03324
03325
NTSTATUS
03326 MiBuildImportsForBootDrivers(
03327 VOID
03328 )
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355 {
03356 PLDR_DATA_TABLE_ENTRY DataTableEntry;
03357 PLIST_ENTRY NextEntry;
03358 PLDR_DATA_TABLE_ENTRY DataTableEntry2;
03359 PLIST_ENTRY NextEntry2;
03360 ULONG i;
03361 ULONG j;
03362 ULONG ImageCount;
03363 PVOID *ImageReferences;
03364 PVOID LastImageReference;
03365 PULONG_PTR ImportThunk;
03366 ULONG_PTR BaseAddress;
03367 ULONG_PTR LastAddress;
03368 ULONG ImportSize;
03369 ULONG ImportListSize;
03370
PLOAD_IMPORTS ImportList;
03371 LOGICAL UndoEverything;
03372 PLDR_DATA_TABLE_ENTRY KernelDataTableEntry;
03373 PLDR_DATA_TABLE_ENTRY HalDataTableEntry;
03374 UNICODE_STRING KernelString;
03375 UNICODE_STRING HalString;
03376
03377
PAGED_CODE();
03378
03379 ImageCount = 0;
03380
03381 KernelDataTableEntry =
NULL;
03382 HalDataTableEntry =
NULL;
03383
03384
RtlInitUnicodeString (&KernelString,
L"ntoskrnl.exe");
03385
RtlInitUnicodeString (&HalString,
L"hal.dll");
03386
03387 NextEntry =
PsLoadedModuleList.Flink;
03388
while (NextEntry != &
PsLoadedModuleList) {
03389
03390 DataTableEntry = CONTAINING_RECORD(NextEntry,
03391 LDR_DATA_TABLE_ENTRY,
03392 InLoadOrderLinks);
03393
03394
if (
RtlEqualUnicodeString (&KernelString,
03395 &DataTableEntry->BaseDllName,
03396
TRUE)) {
03397
03398 KernelDataTableEntry = CONTAINING_RECORD(NextEntry,
03399 LDR_DATA_TABLE_ENTRY,
03400 InLoadOrderLinks);
03401 }
03402
else if (
RtlEqualUnicodeString (&HalString,
03403 &DataTableEntry->BaseDllName,
03404
TRUE)) {
03405
03406 HalDataTableEntry = CONTAINING_RECORD(NextEntry,
03407 LDR_DATA_TABLE_ENTRY,
03408 InLoadOrderLinks);
03409 }
03410
03411
03412
03413
03414
03415 DataTableEntry->LoadCount = 1;
03416 DataTableEntry->LoadedImports = (PVOID)
LOADED_AT_BOOT;
03417
03418 ImageCount += 1;
03419 NextEntry = NextEntry->Flink;
03420 }
03421
03422
if (KernelDataTableEntry ==
NULL || HalDataTableEntry ==
NULL) {
03423
return STATUS_NOT_FOUND;
03424 }
03425
03426 ImageReferences = (PVOID *)
ExAllocatePoolWithTag (
PagedPool,
03427 ImageCount *
sizeof (PVOID),
03428 'TDmM');
03429
03430
if (ImageReferences ==
NULL) {
03431
return STATUS_INSUFFICIENT_RESOURCES;
03432 }
03433
03434 UndoEverything =
FALSE;
03435
03436 NextEntry =
PsLoadedModuleList.Flink;
03437
03438
for ( ; NextEntry != &
PsLoadedModuleList; NextEntry = NextEntry->Flink) {
03439
03440 DataTableEntry = CONTAINING_RECORD(NextEntry,
03441 LDR_DATA_TABLE_ENTRY,
03442 InLoadOrderLinks);
03443
03444 ImportThunk = (PULONG_PTR)
RtlImageDirectoryEntryToData(
03445 DataTableEntry->DllBase,
03446
TRUE,
03447 IMAGE_DIRECTORY_ENTRY_IAT,
03448 &ImportSize);
03449
03450
if (ImportThunk ==
NULL) {
03451 DataTableEntry->LoadedImports =
NO_IMPORTS_USED;
03452
continue;
03453 }
03454
03455 RtlZeroMemory (ImageReferences, ImageCount *
sizeof (PVOID));
03456
03457 ImportSize /=
sizeof(PULONG_PTR);
03458
03459 BaseAddress = 0;
03460
for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) {
03461
03462
03463
03464
03465
03466
if (BaseAddress) {
03467
if (*ImportThunk >= BaseAddress && *ImportThunk < LastAddress) {
03468
ASSERT (ImageReferences[j]);
03469
continue;
03470 }
03471 }
03472
03473 j = 0;
03474 NextEntry2 =
PsLoadedModuleList.Flink;
03475
03476
while (NextEntry2 != &
PsLoadedModuleList) {
03477
03478 DataTableEntry2 = CONTAINING_RECORD(NextEntry2,
03479 LDR_DATA_TABLE_ENTRY,
03480 InLoadOrderLinks);
03481
03482 BaseAddress = (ULONG_PTR) DataTableEntry2->DllBase;
03483 LastAddress = BaseAddress + DataTableEntry2->SizeOfImage;
03484
03485
if (*ImportThunk >= BaseAddress && *ImportThunk < LastAddress) {
03486 ImageReferences[j] = DataTableEntry2;
03487
break;
03488 }
03489
03490 NextEntry2 = NextEntry2->Flink;
03491 j += 1;
03492 }
03493
03494
if (*ImportThunk < BaseAddress || *ImportThunk >= LastAddress) {
03495
if (*ImportThunk) {
03496
#if DBG
03497
DbgPrint (
"MM: broken import linkage %p %p %p\n",
03498 DataTableEntry,
03499 ImportThunk,
03500 *ImportThunk);
03501 DbgBreakPoint ();
03502
#endif
03503
UndoEverything =
TRUE;
03504
goto finished;
03505 }
03506
03507 BaseAddress = 0;
03508 }
03509 }
03510
03511 ImportSize = 0;
03512
03513
for (i = 0; i < ImageCount; i += 1) {
03514
03515
if ((ImageReferences[i] !=
NULL) &&
03516 (ImageReferences[i] != KernelDataTableEntry) &&
03517 (ImageReferences[i] != HalDataTableEntry)) {
03518
03519 LastImageReference = ImageReferences[i];
03520 ImportSize += 1;
03521 }
03522 }
03523
03524
if (ImportSize == 0) {
03525 DataTableEntry->LoadedImports =
NO_IMPORTS_USED;
03526 }
03527
else if (ImportSize == 1) {
03528
#if DBG_SYSLOAD
03529
DbgPrint(
"driver %wZ imports %wZ\n",
03530 &DataTableEntry->FullDllName,
03531 &((PLDR_DATA_TABLE_ENTRY)LastImageReference)->FullDllName);
03532
#endif
03533
03534 DataTableEntry->LoadedImports =
POINTER_TO_SINGLE_ENTRY (LastImageReference);
03535 ((PLDR_DATA_TABLE_ENTRY)LastImageReference)->LoadCount += 1;
03536 }
03537
else {
03538
#if DBG_SYSLOAD
03539
DbgPrint(
"driver %wZ imports many\n", &DataTableEntry->FullDllName);
03540
#endif
03541
03542 ImportListSize = ImportSize *
sizeof(PVOID) +
sizeof(SIZE_T);
03543
03544 ImportList = (
PLOAD_IMPORTS)
ExAllocatePoolWithTag (
PagedPool,
03545 ImportListSize,
03546 'TDmM');
03547
03548
if (ImportList ==
NULL) {
03549 UndoEverything =
TRUE;
03550
break;
03551 }
03552
03553 ImportList->
Count = ImportSize;
03554
03555 j = 0;
03556
for (i = 0; i < ImageCount; i += 1) {
03557
03558
if ((ImageReferences[i] !=
NULL) &&
03559 (ImageReferences[i] != KernelDataTableEntry) &&
03560 (ImageReferences[i] != HalDataTableEntry)) {
03561
03562
#if DBG_SYSLOAD
03563
DbgPrint(
"driver %wZ imports %wZ\n",
03564 &DataTableEntry->FullDllName,
03565 &((PLDR_DATA_TABLE_ENTRY)ImageReferences[i])->FullDllName);
03566
#endif
03567
03568 ImportList->
Entry[j] = ImageReferences[i];
03569 ((PLDR_DATA_TABLE_ENTRY)ImageReferences[i])->LoadCount += 1;
03570 j += 1;
03571 }
03572 }
03573
03574
ASSERT (j == ImportSize);
03575
03576 DataTableEntry->LoadedImports = ImportList;
03577 }
03578
#if DBG_SYSLOAD
03579
DbgPrint(
"\n");
03580
#endif
03581
}
03582
03583 finished:
03584
03585
ExFreePool ((PVOID)ImageReferences);
03586
03587
03588
03589
03590
03591
if ((KernelDataTableEntry->LoadedImports !=
NO_IMPORTS_USED) &&
03592 (!
POINTER_TO_SINGLE_ENTRY(KernelDataTableEntry->LoadedImports))) {
03593
ExFreePool ((PVOID)KernelDataTableEntry->LoadedImports);
03594 }
03595
03596
if ((HalDataTableEntry->LoadedImports !=
NO_IMPORTS_USED) &&
03597 (!
POINTER_TO_SINGLE_ENTRY(HalDataTableEntry->LoadedImports))) {
03598
ExFreePool ((PVOID)HalDataTableEntry->LoadedImports);
03599 }
03600
03601 KernelDataTableEntry->LoadedImports = (PVOID)
LOADED_AT_BOOT;
03602 HalDataTableEntry->LoadedImports = (PVOID)
LOADED_AT_BOOT;
03603
03604
if (UndoEverything ==
TRUE) {
03605
03606
#if DBG_SYSLOAD
03607
DbgPrint(
"driver %wZ import rebuild failed\n",
03608 &DataTableEntry->FullDllName);
03609 DbgBreakPoint();
03610
#endif
03611
03612
03613
03614
03615
03616
03617 NextEntry =
PsLoadedModuleList.Flink;
03618
while (NextEntry != &
PsLoadedModuleList) {
03619 DataTableEntry = CONTAINING_RECORD(NextEntry,
03620 LDR_DATA_TABLE_ENTRY,
03621 InLoadOrderLinks);
03622
03623 ImportList = DataTableEntry->LoadedImports;
03624
if (ImportList ==
LOADED_AT_BOOT || ImportList ==
NO_IMPORTS_USED ||
03625
SINGLE_ENTRY(ImportList)) {
03626 NOTHING;
03627 }
03628
else {
03629
ExFreePool (ImportList);
03630 }
03631
03632 DataTableEntry->LoadedImports = (PVOID)
LOADED_AT_BOOT;
03633 DataTableEntry->LoadCount = 1;
03634 NextEntry = NextEntry->Flink;
03635 }
03636
03637
return STATUS_INSUFFICIENT_RESOURCES;
03638 }
03639
03640
return STATUS_SUCCESS;
03641 }
03642
03643
03644 LOGICAL
03645 MiCallDllUnloadAndUnloadDll(
03646 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
03647 )
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673 {
03674
PMM_DLL_UNLOAD Func;
03675
NTSTATUS Status;
03676 LOGICAL Unloaded;
03677
03678
PAGED_CODE();
03679
03680 Unloaded =
FALSE;
03681
03682 Func =
MiLocateExportName (DataTableEntry->DllBase,
"DllUnload");
03683
03684
if (Func) {
03685
03686
03687
03688
03689
03690
Status = Func();
03691
03692
if (
NT_SUCCESS(
Status)) {
03693
03694
03695
03696
03697
03698
03699
ASSERT (DataTableEntry->LoadCount == 0);
03700 DataTableEntry->LoadCount = 1;
03701
03702
MmUnloadSystemImage ((PVOID)DataTableEntry);
03703 Unloaded =
TRUE;
03704 }
03705 }
03706
03707
return Unloaded;
03708 }
03709
03710
03711 PVOID
03712 MiLocateExportName (
03713 IN PVOID DllBase,
03714 IN PCHAR FunctionName
03715 )
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735 {
03736 PVOID Func =
NULL;
03737 PULONG NameTableBase;
03738
PUSHORT NameOrdinalTableBase;
03739 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
03740 PULONG Addr;
03741 ULONG ExportSize;
03742 ULONG Low;
03743 ULONG Middle;
03744 ULONG High;
03745 LONG Result;
03746
USHORT OrdinalNumber;
03747
03748
PAGED_CODE();
03749
03750
03751
03752
03753
03754 ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData(
03755 DllBase,
03756
TRUE,
03757 IMAGE_DIRECTORY_ENTRY_EXPORT,
03758 &ExportSize
03759 );
03760
if (ExportDirectory) {
03761
03762 NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
03763 NameOrdinalTableBase = (
PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
03764
03765
03766
03767
03768
03769 Low = 0;
03770 High = ExportDirectory->NumberOfNames - 1;
03771
03772
while (High >= Low && (LONG)High >= 0) {
03773
03774
03775
03776
03777
03778
03779 Middle = (Low + High) >> 1;
03780 Result = strcmp(FunctionName,
03781 (PCHAR)((PCHAR)DllBase + NameTableBase[Middle]));
03782
03783
if (Result < 0) {
03784 High = Middle - 1;
03785 }
else if (Result > 0) {
03786 Low = Middle + 1;
03787 }
else {
03788
break;
03789 }
03790 }
03791
03792
03793
03794
03795
03796
03797
03798
if ((LONG)High >= (LONG)Low) {
03799
03800 OrdinalNumber = NameOrdinalTableBase[Middle];
03801 Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
03802 Func = (PVOID)((PCHAR)DllBase + Addr[OrdinalNumber]);
03803
03804
03805
03806
03807
03808
03809
03810
if ((ULONG_PTR)Func > (ULONG_PTR)ExportDirectory &&
03811 (ULONG_PTR)Func < ((ULONG_PTR)ExportDirectory + ExportSize)) {
03812 Func =
NULL;
03813 }
03814 }
03815 }
03816
03817
return Func;
03818 }
03819
03820
03821
NTSTATUS
03822 MiDereferenceImports (
03823 IN PLOAD_IMPORTS ImportList
03824 )
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847 {
03848 ULONG i;
03849 LOGICAL Unloaded;
03850 PVOID SavedImports;
03851
LOAD_IMPORTS SingleTableEntry;
03852 PLDR_DATA_TABLE_ENTRY ImportTableEntry;
03853
03854
PAGED_CODE();
03855
03856
if (ImportList ==
LOADED_AT_BOOT || ImportList ==
NO_IMPORTS_USED) {
03857
return STATUS_SUCCESS;
03858 }
03859
03860
if (
SINGLE_ENTRY(ImportList)) {
03861 SingleTableEntry.
Count = 1;
03862 SingleTableEntry.
Entry[0] =
SINGLE_ENTRY_TO_POINTER(ImportList);
03863 ImportList = &SingleTableEntry;
03864 }
03865
03866
for (i = 0; i < ImportList->Count && ImportList->Entry[i]; i += 1) {
03867 ImportTableEntry = ImportList->
Entry[i];
03868
03869
if (ImportTableEntry->LoadedImports == (PVOID)
LOADED_AT_BOOT) {
03870
03871
03872
03873
03874
03875
continue;
03876 }
03877
03878
#if DBG
03879
{
03880 ULONG ImageCount;
03881 PLIST_ENTRY NextEntry;
03882 PLDR_DATA_TABLE_ENTRY DataTableEntry;
03883
03884
03885
03886
03887
03888
03889 NextEntry =
PsLoadedModuleList.Flink;
03890
03891 ImageCount = 0;
03892
while (NextEntry != &
PsLoadedModuleList && ImageCount < 2) {
03893 DataTableEntry = CONTAINING_RECORD(NextEntry,
03894 LDR_DATA_TABLE_ENTRY,
03895 InLoadOrderLinks);
03896
ASSERT (ImportTableEntry != DataTableEntry);
03897
ASSERT (DataTableEntry->LoadCount == 1);
03898 NextEntry = NextEntry->Flink;
03899 ImageCount += 1;
03900 }
03901 }
03902
#endif
03903
03904
ASSERT (ImportTableEntry->LoadCount >= 1);
03905
03906 ImportTableEntry->LoadCount -= 1;
03907
03908
if (ImportTableEntry->LoadCount == 0) {
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 SavedImports = ImportTableEntry->LoadedImports;
03921
03922 ImportTableEntry->LoadedImports = (PVOID)
NO_IMPORTS_USED;
03923
03924 Unloaded =
MiCallDllUnloadAndUnloadDll ((PVOID)ImportTableEntry);
03925
03926
if (Unloaded ==
TRUE) {
03927
03928
03929
03930
03931
03932
03933
MiDereferenceImports ((
PLOAD_IMPORTS)SavedImports);
03934
03935
if ((SavedImports != (PVOID)
LOADED_AT_BOOT) &&
03936 (SavedImports != (PVOID)
NO_IMPORTS_USED) &&
03937 (!
SINGLE_ENTRY(SavedImports))) {
03938
03939
ExFreePool (SavedImports);
03940 }
03941 }
03942
else {
03943 ImportTableEntry->LoadedImports = SavedImports;
03944 }
03945 }
03946 }
03947
03948
return STATUS_SUCCESS;
03949 }
03950
03951
03952
NTSTATUS
03953 MiResolveImageReferences (
03954 PVOID ImageBase,
03955 IN PUNICODE_STRING ImageFileDirectory,
03956 IN PUNICODE_STRING NamePrefix OPTIONAL,
03957 IN BOOLEAN LoadInSessionSpace,
03958 OUT PCHAR *MissingProcedureName,
03959 OUT PWSTR *MissingDriverName,
03960 OUT PLOAD_IMPORTS *LoadedImports
03961 )
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982 {
03983 PCHAR MissingProcedureStorageArea;
03984 PVOID ImportBase;
03985 ULONG ImportSize;
03986 ULONG ImportListSize;
03987 ULONG
Count;
03988 ULONG i;
03989 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
03990 PIMAGE_IMPORT_DESCRIPTOR Imp;
03991
NTSTATUS st;
03992 ULONG ExportSize;
03993 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
03994 PIMAGE_THUNK_DATA NameThunk;
03995 PIMAGE_THUNK_DATA AddrThunk;
03996 PSZ ImportName;
03997 PLIST_ENTRY NextEntry;
03998 PLDR_DATA_TABLE_ENTRY DataTableEntry;
03999 PLDR_DATA_TABLE_ENTRY SingleEntry;
04000 ANSI_STRING AnsiString;
04001 UNICODE_STRING ImportName_U;
04002 UNICODE_STRING ImportDescriptorName_U;
04003 UNICODE_STRING DllToLoad;
04004 PVOID Section;
04005 PVOID BaseAddress;
04006 BOOLEAN PrefixedNameAllocated;
04007 BOOLEAN ReferenceImport;
04008 ULONG LinkWin32k = 0;
04009 ULONG LinkNonWin32k = 0;
04010
PLOAD_IMPORTS ImportList;
04011
PLOAD_IMPORTS CompactedImportList;
04012 BOOLEAN Loaded;
04013
04014
PAGED_CODE();
04015
04016 *LoadedImports =
NO_IMPORTS_USED;
04017
04018 MissingProcedureStorageArea = *MissingProcedureName;
04019
04020 ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)
RtlImageDirectoryEntryToData(
04021 ImageBase,
04022
TRUE,
04023 IMAGE_DIRECTORY_ENTRY_IMPORT,
04024 &ImportSize);
04025
04026
if (ImportDescriptor ==
NULL) {
04027
return STATUS_SUCCESS;
04028 }
04029
04030
04031
04032
04033
04034
Count = 0;
04035
for (Imp = ImportDescriptor; Imp->Name && Imp->OriginalFirstThunk; Imp += 1) {
04036
Count += 1;
04037 }
04038
04039
if (
Count) {
04040 ImportListSize =
Count *
sizeof(PVOID) +
sizeof(SIZE_T);
04041
04042 ImportList = (
PLOAD_IMPORTS)
ExAllocatePoolWithTag (
PagedPool,
04043 ImportListSize,
04044 'TDmM');
04045
04046
04047
04048
04049
04050
04051
if (ImportList) {
04052 RtlZeroMemory (ImportList, ImportListSize);
04053 ImportList->
Count =
Count;
04054 }
04055 }
04056
else {
04057 ImportList = (
PLOAD_IMPORTS) 0;
04058 }
04059
04060
Count = 0;
04061
while (ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk) {
04062
04063 ImportName = (PSZ)((PCHAR)ImageBase + ImportDescriptor->Name);
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074 LinkWin32k = LinkWin32k |
04075 (!_strnicmp(ImportName,
"win32k",
sizeof(
"win32k") - 1));
04076
04077
04078
04079
04080
04081
04082 LinkNonWin32k = LinkNonWin32k |
04083 ((_strnicmp(ImportName,
"win32k",
sizeof(
"win32k") - 1)) &&
04084 (_strnicmp(ImportName,
"dxapi",
sizeof(
"dxapi") - 1)) &&
04085 (_strnicmp(ImportName,
"coverage",
sizeof(
"coverage") - 1)) &&
04086 (_strnicmp(ImportName,
"irt",
sizeof(
"irt") - 1)));
04087
04088
04089
if (LinkNonWin32k && LinkWin32k) {
04090
MiDereferenceImports (ImportList);
04091
if (ImportList) {
04092
ExFreePool (ImportList);
04093 }
04094
return (STATUS_PROCEDURE_NOT_FOUND);
04095 }
04096
04097
if ((!_strnicmp(ImportName,
"ntdll",
sizeof(
"ntdll") - 1)) ||
04098 (!_strnicmp(ImportName,
"winsrv",
sizeof(
"winsrv") - 1)) ||
04099 (!_strnicmp(ImportName,
"advapi32",
sizeof(
"advapi32") - 1)) ||
04100 (!_strnicmp(ImportName,
"kernel32",
sizeof(
"kernel32") - 1)) ||
04101 (!_strnicmp(ImportName,
"user32",
sizeof(
"user32") - 1)) ||
04102 (!_strnicmp(ImportName,
"gdi32",
sizeof(
"gdi32") - 1)) ) {
04103
04104
MiDereferenceImports (ImportList);
04105
04106
if (ImportList) {
04107
ExFreePool (ImportList);
04108 }
04109
return (STATUS_PROCEDURE_NOT_FOUND);
04110 }
04111
04112
if ((!_strnicmp(ImportName,
"ntoskrnl",
sizeof(
"ntoskrnl") - 1)) ||
04113 (!_strnicmp(ImportName,
"win32k",
sizeof(
"win32k") - 1)) ||
04114 (!_strnicmp(ImportName,
"hal",
sizeof(
"hal") - 1))) {
04115
04116
04117
04118
04119
04120
04121 ReferenceImport =
FALSE;
04122 }
04123
else {
04124 ReferenceImport =
TRUE;
04125 }
04126
04127
RtlInitAnsiString(&AnsiString, ImportName);
04128 st =
RtlAnsiStringToUnicodeString(&ImportName_U, &AnsiString,
TRUE);
04129
if (!
NT_SUCCESS(st)) {
04130
MiDereferenceImports (ImportList);
04131
if (ImportList) {
04132
ExFreePool (ImportList);
04133 }
04134
return st;
04135 }
04136
04137
if (NamePrefix &&
04138 (_strnicmp(ImportName,
"ntoskrnl",
sizeof(
"ntoskrnl") - 1) &&
04139 _strnicmp(ImportName,
"hal",
sizeof(
"hal") - 1))) {
04140
04141 ImportDescriptorName_U.MaximumLength = ImportName_U.Length + NamePrefix->Length;
04142 ImportDescriptorName_U.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
04143 ImportDescriptorName_U.MaximumLength,
04144 'TDmM');
04145
if (!ImportDescriptorName_U.Buffer) {
04146
RtlFreeUnicodeString(&ImportName_U);
04147
MiDereferenceImports (ImportList);
04148
if (ImportList) {
04149
ExFreePool (ImportList);
04150 }
04151
return STATUS_INSUFFICIENT_RESOURCES;
04152 }
04153
04154 ImportDescriptorName_U.Length = 0;
04155
RtlAppendUnicodeStringToString(&ImportDescriptorName_U, NamePrefix);
04156
RtlAppendUnicodeStringToString(&ImportDescriptorName_U, &ImportName_U);
04157 PrefixedNameAllocated =
TRUE;
04158 }
else {
04159 ImportDescriptorName_U = ImportName_U;
04160 PrefixedNameAllocated =
FALSE;
04161 }
04162
04163 Loaded =
FALSE;
04164
04165 ReCheck:
04166 NextEntry =
PsLoadedModuleList.Flink;
04167 ImportBase =
NULL;
04168
04169
while (NextEntry != &
PsLoadedModuleList) {
04170
04171 DataTableEntry = CONTAINING_RECORD(NextEntry,
04172 LDR_DATA_TABLE_ENTRY,
04173 InLoadOrderLinks);
04174
04175
if (
RtlEqualUnicodeString (&ImportDescriptorName_U,
04176 &DataTableEntry->BaseDllName,
04177
TRUE
04178 )) {
04179
04180 ImportBase = DataTableEntry->DllBase;
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
if (Loaded ==
FALSE && ReferenceImport ==
TRUE) {
04191 DataTableEntry->LoadCount += 1;
04192 }
04193
04194
break;
04195 }
04196 NextEntry = NextEntry->Flink;
04197 }
04198
04199
if (!ImportBase) {
04200
04201
04202
04203
04204
04205 DllToLoad.MaximumLength = ImportName_U.Length +
04206 ImageFileDirectory->Length +
04207 (
USHORT)
sizeof(WCHAR);
04208
04209 DllToLoad.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
04210 DllToLoad.MaximumLength,
04211 'TDmM');
04212
04213
if (DllToLoad.Buffer) {
04214 DllToLoad.Length = ImageFileDirectory->Length;
04215 RtlMoveMemory (DllToLoad.Buffer,
04216 ImageFileDirectory->Buffer,
04217 ImageFileDirectory->Length);
04218
04219
RtlAppendStringToString ((PSTRING)&DllToLoad,
04220 (PSTRING)&ImportName_U);
04221
04222 st =
MmLoadSystemImage (&DllToLoad,
04223 NamePrefix,
04224
NULL,
04225 LoadInSessionSpace,
04226 &Section,
04227 &BaseAddress);
04228
04229
ExFreePool (DllToLoad.Buffer);
04230 }
else {
04231 st = STATUS_INSUFFICIENT_RESOURCES;
04232 }
04233
04234
04235
04236
04237
04238
if (
NT_SUCCESS(st)) {
04239
04240
PMM_DLL_INITIALIZE Func;
04241 UNICODE_STRING RegistryPath;
04242
04243 Loaded =
TRUE;
04244
04245 Func =
MiLocateExportName (BaseAddress,
"DllInitialize");
04246
if (Func) {
04247
04248
04249
04250
04251
04252
04253
04254 RegistryPath.MaximumLength =
CmRegistryMachineSystemCurrentControlSetServices.Length +
04255 ImportName_U.Length +
04256 (
USHORT)(2*
sizeof(WCHAR));
04257 RegistryPath.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
04258 RegistryPath.MaximumLength,
04259 'TDmM');
04260
if (RegistryPath.Buffer) {
04261 PWCHAR Dot;
04262
04263 RegistryPath.Length =
CmRegistryMachineSystemCurrentControlSetServices.Length;
04264 RtlMoveMemory (RegistryPath.Buffer,
04265
CmRegistryMachineSystemCurrentControlSetServices.Buffer,
04266
CmRegistryMachineSystemCurrentControlSetServices.Length);
04267
04268
RtlAppendUnicodeToString (&RegistryPath,
L"\\");
04269 Dot = wcschr (ImportName_U.Buffer,
L'.');
04270
if (Dot) {
04271 ImportName_U.Length = (
USHORT)((Dot - ImportName_U.Buffer)*
sizeof(WCHAR));
04272 }
04273
RtlAppendUnicodeStringToString (&RegistryPath,
04274 &ImportName_U);
04275
04276
04277
04278
04279
04280 st = Func (&RegistryPath);
04281
ExFreePool (RegistryPath.Buffer);
04282
04283
if (!
NT_SUCCESS(st)) {
04284
04285
04286
04287
04288
04289
04290 BOOLEAN Found;
04291 PLIST_ENTRY Entry;
04292 PLDR_DATA_TABLE_ENTRY DataTableEntry2;
04293
04294 Entry =
PsLoadedModuleList.Flink;
04295
04296 Found =
FALSE;
04297
while (Entry != &
PsLoadedModuleList) {
04298
04299 DataTableEntry2 = CONTAINING_RECORD(
04300 Entry,
04301 LDR_DATA_TABLE_ENTRY,
04302 InLoadOrderLinks);
04303
04304
if (BaseAddress == DataTableEntry2->DllBase) {
04305
04306 Found =
TRUE;
04307
break;
04308 }
04309
04310 Entry = Entry->Flink;
04311 }
04312
04313
ASSERT (Found ==
TRUE);
04314
MmUnloadSystemImage ((PVOID)DataTableEntry2);
04315 }
04316 }
04317
04318 }
04319 }
04320
04321
if (!
NT_SUCCESS(st)) {
04322
04323
RtlFreeUnicodeString( &ImportName_U );
04324
if (PrefixedNameAllocated) {
04325
ExFreePool( ImportDescriptorName_U.Buffer );
04326 }
04327
MiDereferenceImports (ImportList);
04328
if (ImportList) {
04329
ExFreePool (ImportList);
04330 }
04331
return st;
04332 }
04333
04334
goto ReCheck;
04335 }
04336
04337
if (ReferenceImport ==
TRUE && ImportList) {
04338 ImportList->
Entry[
Count] = DataTableEntry;
04339
Count += 1;
04340 }
04341
04342
RtlFreeUnicodeString( &ImportName_U );
04343
if (PrefixedNameAllocated) {
04344
ExFreePool ( ImportDescriptorName_U.Buffer );
04345 }
04346
04347 *MissingDriverName = DataTableEntry->BaseDllName.Buffer;
04348
04349 ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData(
04350 ImportBase,
04351
TRUE,
04352 IMAGE_DIRECTORY_ENTRY_EXPORT,
04353 &ExportSize
04354 );
04355
04356
if (!ExportDirectory) {
04357
MiDereferenceImports (ImportList);
04358
if (ImportList) {
04359
ExFreePool (ImportList);
04360 }
04361
return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
04362 }
04363
04364
04365
04366
04367
04368
if (ImportDescriptor->OriginalFirstThunk) {
04369
04370 NameThunk = (PIMAGE_THUNK_DATA)((PCHAR)ImageBase + (ULONG)ImportDescriptor->OriginalFirstThunk);
04371 AddrThunk = (PIMAGE_THUNK_DATA)((PCHAR)ImageBase + (ULONG)ImportDescriptor->FirstThunk);
04372
04373
while (NameThunk->u1.AddressOfData) {
04374 st =
MiSnapThunk(ImportBase,
04375 ImageBase,
04376 NameThunk++,
04377 AddrThunk++,
04378 ExportDirectory,
04379 ExportSize,
04380
FALSE,
04381 MissingProcedureName
04382 );
04383
if (!
NT_SUCCESS(st) ) {
04384
MiDereferenceImports (ImportList);
04385
if (ImportList) {
04386
ExFreePool (ImportList);
04387 }
04388
return st;
04389 }
04390 *MissingProcedureName = MissingProcedureStorageArea;
04391 }
04392 }
04393
04394 ImportDescriptor += 1;
04395 }
04396
04397
04398
04399
04400
04401
04402
if (ImportList) {
04403
04404
04405
04406
04407
04408
04409
04410
Count = 0;
04411
for (i = 0; i < ImportList->
Count; i += 1) {
04412
if (ImportList->
Entry[i]) {
04413
Count += 1;
04414 }
04415 }
04416
04417
if (
Count == 0) {
04418
04419
ExFreePool(ImportList);
04420 ImportList =
NO_IMPORTS_USED;
04421 }
04422
else if (
Count == 1) {
04423
for (i = 0; i < ImportList->
Count; i += 1) {
04424
if (ImportList->
Entry[i]) {
04425 SingleEntry =
POINTER_TO_SINGLE_ENTRY(ImportList->
Entry[i]);
04426
break;
04427 }
04428 }
04429
04430
ExFreePool(ImportList);
04431 ImportList = (
PLOAD_IMPORTS)SingleEntry;
04432 }
04433
else if (
Count != ImportList->
Count) {
04434
04435 ImportListSize =
Count *
sizeof(PVOID) +
sizeof(SIZE_T);
04436
04437 CompactedImportList = (
PLOAD_IMPORTS)
04438
ExAllocatePoolWithTag (
PagedPool,
04439 ImportListSize,
04440 'TDmM');
04441
if (CompactedImportList) {
04442 CompactedImportList->
Count =
Count;
04443
04444
Count = 0;
04445
for (i = 0; i < ImportList->
Count; i += 1) {
04446
if (ImportList->
Entry[i]) {
04447 CompactedImportList->
Entry[
Count] = ImportList->
Entry[i];
04448
Count += 1;
04449 }
04450 }
04451
04452
ExFreePool(ImportList);
04453 ImportList = CompactedImportList;
04454 }
04455 }
04456
04457 *LoadedImports = ImportList;
04458 }
04459
return STATUS_SUCCESS;
04460 }
04461
04462
04463
NTSTATUS
04464 MiSnapThunk(
04465 IN PVOID DllBase,
04466 IN PVOID ImageBase,
04467 IN PIMAGE_THUNK_DATA NameThunk,
04468 OUT PIMAGE_THUNK_DATA AddrThunk,
04469 IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
04470 IN ULONG ExportSize,
04471 IN BOOLEAN SnapForwarder,
04472 OUT PCHAR *MissingProcedureName
04473 )
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499
04500
04501
04502
04503
04504
04505
04506
04507 {
04508 BOOLEAN Ordinal;
04509
USHORT OrdinalNumber;
04510 PULONG NameTableBase;
04511
PUSHORT NameOrdinalTableBase;
04512 PULONG Addr;
04513
USHORT HintIndex;
04514 ULONG High;
04515 ULONG Low;
04516 ULONG Middle;
04517 LONG Result;
04518
NTSTATUS Status;
04519 PCHAR MissingProcedureName2;
04520
CHAR NameBuffer[ MAXIMUM_FILENAME_LENGTH ];
04521
04522
PAGED_CODE();
04523
04524
04525
04526
04527
04528 Ordinal = (BOOLEAN)IMAGE_SNAP_BY_ORDINAL(NameThunk->u1.Ordinal);
04529
04530
if (Ordinal && !SnapForwarder) {
04531
04532 OrdinalNumber = (
USHORT)(IMAGE_ORDINAL(NameThunk->u1.Ordinal) -
04533 ExportDirectory->Base);
04534
04535 *MissingProcedureName = (PCHAR)(ULONG_PTR)OrdinalNumber;
04536
04537 }
else {
04538
04539
04540
04541
04542
04543
if (!SnapForwarder) {
04544 NameThunk->u1.AddressOfData = (ULONG_PTR)ImageBase + NameThunk->u1.AddressOfData;
04545 }
04546
04547 strncpy( *MissingProcedureName,
04548 &((PIMAGE_IMPORT_BY_NAME)NameThunk->u1.AddressOfData)->Name[0],
04549 MAXIMUM_FILENAME_LENGTH - 1
04550 );
04551
04552
04553
04554
04555
04556 NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
04557 NameOrdinalTableBase = (
PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
04558
04559
04560
04561
04562
04563
04564
04565
04566 HintIndex = ((PIMAGE_IMPORT_BY_NAME)NameThunk->u1.AddressOfData)->Hint;
04567
if ((ULONG)HintIndex < ExportDirectory->NumberOfNames &&
04568 !strcmp((PSZ)((PIMAGE_IMPORT_BY_NAME)NameThunk->u1.AddressOfData)->Name,
04569 (PSZ)((PCHAR)DllBase + NameTableBase[HintIndex]))) {
04570 OrdinalNumber = NameOrdinalTableBase[HintIndex];
04571
04572 }
else {
04573
04574
04575
04576
04577
04578 Low = 0;
04579 High = ExportDirectory->NumberOfNames - 1;
04580
04581
while (High >= Low) {
04582
04583
04584
04585
04586
04587
04588 Middle = (Low + High) >> 1;
04589 Result = strcmp(&((PIMAGE_IMPORT_BY_NAME)NameThunk->u1.AddressOfData)->Name[0],
04590 (PCHAR)((PCHAR)DllBase + NameTableBase[Middle]));
04591
04592
if (Result < 0) {
04593 High = Middle - 1;
04594
04595 }
else if (Result > 0) {
04596 Low = Middle + 1;
04597
04598 }
else {
04599
break;
04600 }
04601 }
04602
04603
04604
04605
04606
04607
04608
04609
if (High < Low) {
04610
return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
04611 }
else {
04612 OrdinalNumber = NameOrdinalTableBase[Middle];
04613 }
04614 }
04615 }
04616
04617
04618
04619
04620
04621
04622
if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
04623
Status = STATUS_DRIVER_ORDINAL_NOT_FOUND;
04624
04625 }
else {
04626
04627 MissingProcedureName2 = NameBuffer;
04628
04629 Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
04630 (PULONG)(AddrThunk->u1.Function) = (PULONG)((PCHAR)DllBase + Addr[OrdinalNumber]);
04631
04632
04633
04634
Status = STATUS_SUCCESS;
04635
04636
if ( ((ULONG_PTR)AddrThunk->u1.Function > (ULONG_PTR)ExportDirectory) &&
04637 ((ULONG_PTR)AddrThunk->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize)) ) {
04638
04639 UNICODE_STRING UnicodeString;
04640 ANSI_STRING ForwardDllName;
04641
04642 PLIST_ENTRY NextEntry;
04643 PLDR_DATA_TABLE_ENTRY DataTableEntry;
04644 ULONG ExportSize;
04645 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
04646
04647
Status = STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
04648
04649
04650
04651
04652
04653 ForwardDllName.Buffer = (PCHAR)AddrThunk->u1.Function;
04654 ForwardDllName.Length = (
USHORT)(strchr(ForwardDllName.Buffer,
'.') -
04655 ForwardDllName.Buffer + 1);
04656 ForwardDllName.MaximumLength = ForwardDllName.Length;
04657
04658
if (
NT_SUCCESS(
RtlAnsiStringToUnicodeString(&UnicodeString,
04659 &ForwardDllName,
04660
TRUE))) {
04661
04662 NextEntry =
PsLoadedModuleList.Flink;
04663
04664
while (NextEntry != &
PsLoadedModuleList) {
04665
04666 DataTableEntry = CONTAINING_RECORD(NextEntry,
04667 LDR_DATA_TABLE_ENTRY,
04668 InLoadOrderLinks);
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
if (
RtlPrefixString((PSTRING)&UnicodeString,
04680 (PSTRING)&DataTableEntry->BaseDllName,
04681
TRUE)) {
04682
04683 ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
04684
RtlImageDirectoryEntryToData(DataTableEntry->DllBase,
04685
TRUE,
04686 IMAGE_DIRECTORY_ENTRY_EXPORT,
04687 &ExportSize);
04688
04689
if (ExportDirectory) {
04690
04691 IMAGE_THUNK_DATA thunkData;
04692 PIMAGE_IMPORT_BY_NAME addressOfData;
04693 ULONG length;
04694
04695
04696
04697 length =
strlen(ForwardDllName.Buffer +
04698 ForwardDllName.Length) + 1;
04699
04700 addressOfData = (PIMAGE_IMPORT_BY_NAME)
04701
ExAllocatePoolWithTag (
PagedPool,
04702 length +
04703
sizeof(IMAGE_IMPORT_BY_NAME),
04704 ' mM');
04705
04706
if (addressOfData) {
04707
04708 RtlCopyMemory(&(addressOfData->Name[0]),
04709 ForwardDllName.Buffer +
04710 ForwardDllName.Length,
04711 length);
04712
04713 addressOfData->Hint = 0;
04714
04715 (PIMAGE_IMPORT_BY_NAME)(thunkData.u1.AddressOfData) = addressOfData;
04716
04717
Status =
MiSnapThunk(DataTableEntry->DllBase,
04718 ImageBase,
04719 &thunkData,
04720 &thunkData,
04721 ExportDirectory,
04722 ExportSize,
04723
TRUE,
04724 &MissingProcedureName2
04725 );
04726
04727
ExFreePool(addressOfData);
04728
04729 AddrThunk->u1 = thunkData.u1;
04730 }
04731 }
04732
04733
break;
04734 }
04735
04736 NextEntry = NextEntry->Flink;
04737 }
04738
04739
RtlFreeUnicodeString(&UnicodeString);
04740 }
04741
04742 }
04743
04744 }
04745
return Status;
04746 }
04747
#if 0
04748
PVOID
04749
MiLookupImageSectionByName (
04750 IN PVOID Base,
04751 IN BOOLEAN MappedAsImage,
04752 IN PCHAR SectionName,
04753 OUT PULONG SectionSize
04754 )
04755
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783 {
04784 ULONG i, j, Match;
04785 PIMAGE_NT_HEADERS NtHeaders;
04786 PIMAGE_SECTION_HEADER NtSection;
04787
04788 NtHeaders =
RtlImageNtHeader(Base);
04789 NtSection = IMAGE_FIRST_SECTION( NtHeaders );
04790
for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++) {
04791 Match =
TRUE;
04792
for (j = 0; j < IMAGE_SIZEOF_SHORT_NAME; j++) {
04793
if (SectionName[j] != NtSection->Name[j]) {
04794 Match =
FALSE;
04795
break;
04796 }
04797
if (SectionName[j] ==
'\0') {
04798
break;
04799 }
04800 }
04801
if (Match) {
04802
break;
04803 }
04804 NtSection += 1;
04805 }
04806
if (Match) {
04807 *SectionSize = NtSection->SizeOfRawData;
04808
if (MappedAsImage) {
04809
return( ((PCHAR)Base + NtSection->VirtualAddress));
04810 }
else {
04811
return( ((PCHAR)Base + NtSection->PointerToRawData));
04812 }
04813 }
04814
return(
NULL );
04815 }
04816
#endif //0
04817
04818
04819
NTSTATUS
04820 MmCheckSystemImage(
04821 IN HANDLE ImageFileHandle
04822 )
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836
04837
04838
04839
04840
04841 {
04842
04843
NTSTATUS Status;
04844 HANDLE Section;
04845 PVOID ViewBase;
04846 SIZE_T ViewSize;
04847 IO_STATUS_BLOCK IoStatusBlock;
04848 FILE_STANDARD_INFORMATION StandardInfo;
04849
04850
PAGED_CODE();
04851
04852
Status = ZwCreateSection(
04853 &Section,
04854 SECTION_MAP_EXECUTE,
04855
NULL,
04856
NULL,
04857 PAGE_EXECUTE,
04858 SEC_COMMIT,
04859 ImageFileHandle
04860 );
04861
04862
if ( !
NT_SUCCESS(
Status) ) {
04863
return Status;
04864 }
04865
04866 ViewBase =
NULL;
04867 ViewSize = 0;
04868
04869
Status = ZwMapViewOfSection(
04870 Section,
04871 NtCurrentProcess(),
04872 (PVOID *)&ViewBase,
04873 0
L,
04874 0
L,
04875
NULL,
04876 &ViewSize,
04877 ViewShare,
04878 0
L,
04879 PAGE_EXECUTE
04880 );
04881
04882
if ( !
NT_SUCCESS(
Status) ) {
04883 ZwClose(Section);
04884
return Status;
04885 }
04886
04887
04888
04889
04890
04891
04892
Status = ZwQueryInformationFile(
04893 ImageFileHandle,
04894 &IoStatusBlock,
04895 &StandardInfo,
04896
sizeof(StandardInfo),
04897 FileStandardInformation
04898 );
04899
04900
if (
NT_SUCCESS(
Status) ) {
04901
04902
try {
04903
if (!
LdrVerifyMappedImageMatchesChecksum(ViewBase,StandardInfo.EndOfFile.LowPart)) {
04904
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
04905 }
04906
#if !defined(NT_UP)
04907
if ( !
MmVerifyImageIsOkForMpUse(ViewBase) ) {
04908
Status = STATUS_IMAGE_MP_UP_MISMATCH;
04909 }
04910
#endif // NT_UP
04911
} except (
EXCEPTION_EXECUTE_HANDLER) {
04912
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
04913 }
04914 }
04915
04916 ZwUnmapViewOfSection(NtCurrentProcess(),ViewBase);
04917 ZwClose(Section);
04918
return Status;
04919 }
04920
04921
#if !defined(NT_UP)
04922
BOOLEAN
04923 MmVerifyImageIsOkForMpUse(
04924 IN PVOID BaseAddress
04925 )
04926 {
04927 PIMAGE_NT_HEADERS NtHeaders;
04928
04929
PAGED_CODE();
04930
04931
04932
04933
04934
04935
04936
04937 NtHeaders =
RtlImageNtHeader(BaseAddress);
04938
if (NtHeaders !=
NULL) {
04939
if (
KeNumberProcessors > 1 &&
04940 (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) ) {
04941
return FALSE;
04942 }
04943 }
04944
return TRUE;
04945 }
04946
#endif // NT_UP
04947
04948
04949 PFN_NUMBER
04950 MiDeleteSystemPagableVm (
04951 IN
PMMPTE PointerPte,
04952 IN PFN_NUMBER NumberOfPtes,
04953 IN
MMPTE NewPteValue,
04954 IN LOGICAL SessionAllocation,
04955 OUT PPFN_NUMBER ResidentPages
04956 )
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989 {
04990 PFN_NUMBER PageFrameIndex;
04991
MMPTE PteContents;
04992
PMMPFN Pfn1;
04993 PFN_NUMBER ValidPages;
04994 PFN_NUMBER PagesRequired;
04995
MMPTE NewContents;
04996
WSLE_NUMBER WsIndex;
04997 KIRQL OldIrql;
04998
MMPTE_FLUSH_LIST PteFlushList;
04999
MMPTE JunkPte;
05000
MMWSLENTRY Locked;
05001
05002
ASSERT (KeGetCurrentIrql() <=
APC_LEVEL);
05003
05004 ValidPages = 0;
05005 PagesRequired = 0;
05006 PteFlushList.
Count = 0;
05007 NewContents = NewPteValue;
05008
while (NumberOfPtes != 0) {
05009 PteContents = *PointerPte;
05010
05011
if (PteContents.
u.Long !=
ZeroKernelPte.
u.Long) {
05012
05013
if (PteContents.
u.Hard.Valid == 1) {
05014
05015
if (SessionAllocation ==
TRUE) {
05016
LOCK_SESSION_SPACE_WS (OldIrql);
05017 }
05018
else {
05019
LOCK_SYSTEM_WS (OldIrql);
05020 }
05021
05022 PteContents = *(
volatile MMPTE *)PointerPte;
05023
if (PteContents.
u.Hard.Valid == 0) {
05024
if (SessionAllocation ==
TRUE) {
05025
UNLOCK_SESSION_SPACE_WS (OldIrql);
05026 }
05027
else {
05028
UNLOCK_SYSTEM_WS (OldIrql);
05029 }
05030
05031
continue;
05032 }
05033
05034
05035
05036
05037
05038 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
05039
05040 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
05041
05042
05043
05044
05045
05046
05047 WsIndex = Pfn1->
u1.WsIndex;
05048
if (WsIndex == 0) {
05049 ValidPages += 1;
05050 }
else {
05051
if (SessionAllocation ==
FALSE) {
05052
MiRemoveWsle (WsIndex,
05053
MmSystemCacheWorkingSetList );
05054
MiReleaseWsle (WsIndex, &
MmSystemCacheWs);
05055 }
05056
else {
05057 WsIndex =
MiLocateWsle(
05058
MiGetVirtualAddressMappedByPte(PointerPte),
05059
MmSessionSpace->
Vm.
VmWorkingSetList,
05060 WsIndex
05061 );
05062
05063
ASSERT (WsIndex !=
WSLE_NULL_INDEX);
05064
05065
05066
05067
05068
05069
05070 Locked =
MmSessionSpace->
Wsle[WsIndex].
u1.e1;
05071
05072
MiRemoveWsle (WsIndex,
MmSessionSpace->
Vm.
VmWorkingSetList);
05073
05074
MiReleaseWsle (WsIndex, &
MmSessionSpace->
Vm);
05075
05076
if (Locked.
LockedInWs == 1 || Locked.
LockedInMemory == 1) {
05077
05078
05079
05080
05081
#if DBG
05082
DbgPrint(
"MiDeleteSystemPagableVm: Session PointerPte 0x%p, Pfn 0x%p Locked in memory\n",
05083 PointerPte,
05084 Pfn1);
05085
05086 DbgBreakPoint();
05087
#endif
05088
ASSERT (WsIndex < MmSessionSpace->Vm.VmWorkingSetList->FirstDynamic);
05089
MmSessionSpace->
Vm.
VmWorkingSetList->
FirstDynamic -= 1;
05090
05091
if (WsIndex !=
MmSessionSpace->
Vm.
VmWorkingSetList->
FirstDynamic) {
05092 ULONG Entry;
05093 PVOID SwapVa;
05094
05095 Entry =
MmSessionSpace->
Vm.
VmWorkingSetList->
FirstDynamic;
05096
ASSERT (
MmSessionSpace->
Wsle[Entry].
u1.e1.Valid);
05097 SwapVa =
MmSessionSpace->
Wsle[Entry].
u1.VirtualAddress;
05098 SwapVa =
PAGE_ALIGN (SwapVa);
05099
05100
MiSwapWslEntries (Entry,
05101 WsIndex,
05102 &
MmSessionSpace->
Vm);
05103 }
05104 }
05105
else {
05106
ASSERT (WsIndex >=
MmSessionSpace->
Vm.
VmWorkingSetList->
FirstDynamic);
05107 }
05108 }
05109 }
05110
05111
if (SessionAllocation ==
TRUE) {
05112
UNLOCK_SESSION_SPACE_WS (OldIrql);
05113 }
05114
else {
05115
UNLOCK_SYSTEM_WS (OldIrql);
05116 }
05117
05118
LOCK_PFN (OldIrql);
05119
#if DBG
05120
if ((Pfn1->
u3.e2.ReferenceCount > 1) &&
05121 (Pfn1->
u3.e1.WriteInProgress == 0)) {
05122
DbgPrint (
"MM:SYSLOAD - deleting pool locked for I/O pte %p, pfn %p, share=%x, refcount=%x, wsindex=%x\n",
05123 PointerPte,
05124 PageFrameIndex,
05125 Pfn1->
u2.ShareCount,
05126 Pfn1->
u3.e2.ReferenceCount,
05127 Pfn1->
u1.WsIndex);
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153 }
05154
#endif //DBG
05155
05156
05157
05158
if (Pfn1->
u3.e1.PrototypePte == 1) {
05159
05160
PMMPTE PointerPde;
05161
05162
ASSERT (SessionAllocation ==
TRUE);
05163
05164
05165
05166
05167
05168
05169
MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
05170
05171
05172
05173
05174
05175
05176 PointerPde =
MiGetPteAddress (PointerPte);
05177
if (PointerPde->
u.Hard.Valid == 0) {
05178
#if !defined (_WIN64)
05179
if (!
NT_SUCCESS(
MiCheckPdeForPagedPool (PointerPte))) {
05180
#endif
05181
KeBugCheckEx (MEMORY_MANAGEMENT,
05182 0x61940,
05183 (ULONG_PTR)PointerPte,
05184 (ULONG_PTR)PointerPde->
u.Long,
05185 (ULONG_PTR)
MiGetVirtualAddressMappedByPte(PointerPte));
05186
#if !defined (_WIN64)
05187
}
05188
#endif
05189
}
05190
05191
MiDecrementShareAndValidCount (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPde));
05192
05193
05194
05195
05196
05197
MiDecrementShareCount (PageFrameIndex);
05198
05199
05200
05201
05202
05203
05204
ASSERT (PointerPte >
MiHighestUserPte);
05205
05206 }
else {
05207
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
05208
MI_SET_PFN_DELETED (Pfn1);
05209
MiDecrementShareCountOnly (PageFrameIndex);
05210 }
05211
05212
MI_WRITE_INVALID_PTE (PointerPte, NewContents);
05213
UNLOCK_PFN (OldIrql);
05214
05215
05216
05217
05218
05219
if (PteFlushList.
Count !=
MM_MAXIMUM_FLUSH_COUNT) {
05220
05221
05222
05223
05224
05225
05226
05227
05228 PteFlushList.
FlushPte[PteFlushList.
Count] =
05229 (
PMMPTE)&JunkPte;
05230
05231 PteFlushList.
FlushVa[PteFlushList.
Count] =
05232
MiGetVirtualAddressMappedByPte (PointerPte);
05233 PteFlushList.
Count += 1;
05234 }
05235
05236 }
else if (PteContents.
u.Soft.Prototype) {
05237
05238
ASSERT (SessionAllocation ==
TRUE);
05239
05240
05241
05242
05243
05244
05245
ASSERT (PointerPte >=
MiHighestUserPte);
05246
05247
MI_WRITE_INVALID_PTE (PointerPte, NewContents);
05248
05249
05250
05251
05252
05253
05254 }
else if (PteContents.
u.Soft.Transition == 1) {
05255
05256
LOCK_PFN (OldIrql);
05257
05258 PteContents = *(
volatile MMPTE *)PointerPte;
05259
05260
if (PteContents.
u.Soft.Transition == 0) {
05261
UNLOCK_PFN (OldIrql);
05262
continue;
05263 }
05264
05265
05266
05267
05268
05269 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
05270
05271
05272
05273
05274
05275
05276 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
05277
05278
MI_SET_PFN_DELETED (Pfn1);
05279
05280
MiDecrementShareCount (Pfn1->
PteFrame);
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
if (Pfn1->
u3.e2.ReferenceCount == 0) {
05291
MiUnlinkPageFromList (Pfn1);
05292
MiReleasePageFileSpace (Pfn1->
OriginalPte);
05293
MiInsertPageInList (
MmPageLocationList[
FreePageList],
05294 PageFrameIndex);
05295 }
05296
#if DBG
05297
if ((Pfn1->
u3.e2.ReferenceCount > 1) &&
05298 (Pfn1->
u3.e1.WriteInProgress == 0)) {
05299
DbgPrint (
"MM:SYSLOAD - deleting pool locked for I/O %p\n",
05300 PageFrameIndex);
05301 DbgBreakPoint();
05302 }
05303
#endif //DBG
05304
05305
MI_WRITE_INVALID_PTE (PointerPte, NewContents);
05306
UNLOCK_PFN (OldIrql);
05307 }
else {
05308
05309
05310
05311
05312
if (PteContents.
u.Soft.PageFileHigh != 0) {
05313
LOCK_PFN (OldIrql);
05314
MiReleasePageFileSpace (PteContents);
05315
UNLOCK_PFN (OldIrql);
05316 }
05317
05318
MI_WRITE_INVALID_PTE (PointerPte, NewContents);
05319 }
05320
05321 PagesRequired += 1;
05322 }
05323
05324 NumberOfPtes -= 1;
05325 PointerPte += 1;
05326 }
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
if (SessionAllocation ==
TRUE) {
05356
05357
05358
05359
05360
05361
MI_FLUSH_ENTIRE_SESSION_TB (
TRUE,
TRUE);
05362 }
05363
05364
LOCK_PFN (OldIrql);
05365
MiFlushPteList (&PteFlushList,
TRUE, NewContents);
05366
UNLOCK_PFN (OldIrql);
05367
05368
if (ARGUMENT_PRESENT(ResidentPages)) {
05369 *ResidentPages = ValidPages;
05370 }
05371
05372
return PagesRequired;
05373 }
05374
05375
VOID
05376 MiSetImageProtect (
05377 IN
PSEGMENT Segment,
05378 IN ULONG Protection
05379 )
05380
05381
05382
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400 {
05401
PMMPTE PointerPte;
05402
PMMPTE LastPte;
05403
MMPTE PteContents;
05404
PSUBSECTION SubSection;
05405
05406
05407
05408
05409
05410
ASSERT (Segment->ControlArea->u.Flags.GlobalOnlyPerSession == 0);
05411
05412
if ((Protection &
MM_PROTECTION_WRITE_MASK) == 0) {
05413 SubSection = (
PSUBSECTION)(Segment->ControlArea + 1);
05414 SubSection->
u.SubsectionFlags.Protection = Protection;
05415 SubSection->
u.SubsectionFlags.ReadOnly = 1;
05416 }
05417
05418 PointerPte = Segment->PrototypePte;
05419 LastPte = PointerPte + Segment->NonExtendedPtes;
05420
05421
MmLockPagedPool (PointerPte, (LastPte - PointerPte) *
sizeof (
MMPTE));
05422
05423
do {
05424 PteContents = *PointerPte;
05425
ASSERT (PteContents.
u.Hard.Valid == 0);
05426
if (PteContents.
u.Long !=
ZeroPte.
u.Long) {
05427
if ((PteContents.
u.Soft.Prototype == 0) &&
05428 (PteContents.
u.Soft.Transition == 1)) {
05429
if (
MiSetProtectionOnTransitionPte (PointerPte, Protection)) {
05430
continue;
05431 }
05432 }
05433
else {
05434 PointerPte->u.Soft.Protection = Protection;
05435 }
05436 }
05437 PointerPte += 1;
05438 }
while (PointerPte < LastPte);
05439
05440 PointerPte = Segment->PrototypePte;
05441
MmUnlockPagedPool (PointerPte, (LastPte - PointerPte) *
sizeof (
MMPTE));
05442
05443
return;
05444 }
05445
05446
05447
VOID
05448 MiSetSystemCodeProtection (
05449 IN
PMMPTE FirstPte,
05450 IN
PMMPTE LastPte
05451 )
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471
05472 {
05473 KIRQL OldIrql;
05474
MMPTE PteContents;
05475
MMPTE TempPte;
05476
MMPTE PreviousPte;
05477
PMMPTE PointerPte;
05478
PMMPTE PointerPde;
05479
PMMPTE PointerProtoPte;
05480 ULONG ProtectionMask;
05481
PMMPFN Pfn1;
05482
PMMPFN ProtoPfn;
05483 LOGICAL SessionAddress;
05484
05485
#if defined(_X86_)
05486
ASSERT (
MI_IS_PHYSICAL_ADDRESS(
MiGetVirtualAddressMappedByPte(FirstPte)) == 0);
05487
#endif
05488
05489 SessionAddress =
FALSE;
05490
05491
if (
MI_IS_SESSION_ADDRESS(
MiGetVirtualAddressMappedByPte(FirstPte))) {
05492 SessionAddress =
TRUE;
05493 }
05494
05495 ProtectionMask =
MM_EXECUTE_READ;
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505 PointerPte = FirstPte;
05506
05507
LOCK_PFN (OldIrql);
05508
05509
while (PointerPte <= LastPte) {
05510
05511 PteContents = *PointerPte;
05512
05513
if ((PteContents.
u.Long == 0) || (!*
MiPteStr)) {
05514 PointerPte += 1;
05515
continue;
05516 }
05517
05518
if (PteContents.
u.Hard.Valid == 1) {
05519
05520 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Hard.PageFrameNumber);
05521 Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
05522
05523
05524
05525
05526
05527
05528
if (
MI_IS_PTE_DIRTY(PteContents)) {
05529
MI_CAPTURE_DIRTY_BIT_TO_PFN (&PteContents, Pfn1);
05530 }
05531
05532
MI_MAKE_VALID_PTE (TempPte,
05533 PteContents.
u.Hard.PageFrameNumber,
05534 Pfn1->
OriginalPte.
u.Soft.Protection,
05535 PointerPte);
05536
05537
if (SessionAddress ==
TRUE) {
05538
05539
05540
05541
05542
05543
MI_FLUSH_SINGLE_SESSION_TB (
MiGetVirtualAddressMappedByPte (PointerPte),
05544
TRUE,
05545
TRUE,
05546 (PHARDWARE_PTE)PointerPte,
05547 TempPte.
u.Flush,
05548 PreviousPte);
05549 }
05550
else {
05551
KeFlushSingleTb (
MiGetVirtualAddressMappedByPte (PointerPte),
05552
TRUE,
05553
TRUE,
05554 (PHARDWARE_PTE)PointerPte,
05555 TempPte.
u.Flush);
05556 }
05557 }
05558
else if (PteContents.
u.Soft.Prototype == 1) {
05559
05560
if (SessionAddress ==
TRUE) {
05561 PointerPte->u.Proto.ReadOnly = 1;
05562 }
05563
else {
05564 PointerProtoPte =
MiPteToProto(PointerPte);
05565
05566
if (!
MI_IS_PHYSICAL_ADDRESS(PointerProtoPte)) {
05567 PointerPde =
MiGetPteAddress (PointerProtoPte);
05568
if (PointerPde->
u.Hard.Valid == 0) {
05569
MiMakeSystemAddressValidPfn (PointerProtoPte);
05570
05571
05572
05573
05574
05575 PteContents = *PointerPte;
05576
if ((PteContents.
u.Hard.Valid == 1) ||
05577 (PteContents.
u.Soft.Prototype == 0)) {
05578
continue;
05579 }
05580 }
05581
05582 ProtoPfn =
MI_PFN_ELEMENT (PointerPde->
u.Hard.PageFrameNumber);
05583
MI_ADD_LOCKED_PAGE_CHARGE(ProtoPfn, 12);
05584 ProtoPfn->
u3.e2.ReferenceCount += 1;
05585
ASSERT (ProtoPfn->
u3.e2.ReferenceCount > 1);
05586 }
05587
05588 PteContents = *PointerProtoPte;
05589
05590
if (PteContents.
u.Long !=
ZeroPte.
u.Long) {
05591
05592
ASSERT (PteContents.
u.Hard.Valid == 0);
05593
05594 PointerProtoPte->u.Soft.Protection = ProtectionMask;
05595
05596
if ((PteContents.
u.Soft.Prototype == 0) &&
05597 (PteContents.
u.Soft.Transition == 1)) {
05598 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
05599 Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
05600 }
05601 }
05602
05603
if (!
MI_IS_PHYSICAL_ADDRESS(PointerProtoPte)) {
05604
ASSERT (ProtoPfn->
u3.e2.ReferenceCount > 1);
05605
MI_REMOVE_LOCKED_PAGE_CHARGE(ProtoPfn, 13);
05606 ProtoPfn->
u3.e2.ReferenceCount -= 1;
05607 }
05608 }
05609 }
05610
else if (PteContents.
u.Soft.Transition == 1) {
05611
05612 Pfn1 =
MI_PFN_ELEMENT (PteContents.
u.Trans.PageFrameNumber);
05613 Pfn1->
OriginalPte.
u.Soft.Protection = ProtectionMask;
05614 PointerPte->u.Soft.Protection = ProtectionMask;
05615
05616 }
05617
else {
05618
05619
05620
05621
05622
05623 PointerPte->u.Soft.Protection = ProtectionMask;
05624 }
05625 PointerPte += 1;
05626 }
05627
05628
UNLOCK_PFN (OldIrql);
05629 }
05630
05631
05632
VOID
05633 MiWriteProtectSystemImage (
05634 IN PVOID DllBase
05635 )
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653 {
05654 ULONG SectionProtection;
05655 ULONG NumberOfSubsections;
05656 ULONG SectionVirtualSize;
05657 ULONG ImageAlignment;
05658 ULONG OffsetToSectionTable;
05659 ULONG NumberOfPtes;
05660 ULONG_PTR VirtualAddress;
05661 ULONG_PTR LastVirtualAddress;
05662
PMMPTE PointerPte;
05663
PMMPTE FirstPte;
05664
PMMPTE LastPte;
05665
PMMPTE LastImagePte;
05666
PMMPTE WritablePte;
05667 PIMAGE_NT_HEADERS NtHeader;
05668 PIMAGE_FILE_HEADER FileHeader;
05669 PIMAGE_SECTION_HEADER SectionTableEntry;
05670
05671
PAGED_CODE();
05672
05673
if (
MI_IS_PHYSICAL_ADDRESS(DllBase)) {
05674
return;
05675 }
05676
05677 NtHeader =
RtlImageNtHeader (DllBase);
05678
05679
ASSERT (NtHeader);
05680
05681 ImageAlignment = NtHeader->OptionalHeader.SectionAlignment;
05682
05683
05684
05685
05686
05687
05688
if (
MI_IS_SESSION_ADDRESS(DllBase) == 0) {
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
if ((NtHeader->OptionalHeader.MajorOperatingSystemVersion < 5) ||
05702 (NtHeader->OptionalHeader.MajorOperatingSystemVersion > 10)) {
05703
return;
05704 }
05705
05706
if ((NtHeader->OptionalHeader.MajorImageVersion < 5) ||
05707 (NtHeader->OptionalHeader.MajorImageVersion > 10)) {
05708
return;
05709 }
05710 }
05711
05712 NumberOfPtes =
BYTES_TO_PAGES (NtHeader->OptionalHeader.SizeOfImage);
05713
05714 FileHeader = &NtHeader->FileHeader;
05715
05716 NumberOfSubsections = FileHeader->NumberOfSections;
05717
05718
ASSERT (NumberOfSubsections != 0);
05719
05720 OffsetToSectionTable =
sizeof(ULONG) +
05721
sizeof(IMAGE_FILE_HEADER) +
05722 FileHeader->SizeOfOptionalHeader;
05723
05724 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader +
05725 OffsetToSectionTable);
05726
05727
05728
05729
05730
05731
05732 FirstPte =
NULL;
05733 LastVirtualAddress = (ULONG_PTR)DllBase;
05734
05735
for ( ; NumberOfSubsections > 0; NumberOfSubsections -= 1, SectionTableEntry += 1) {
05736
05737
if (SectionTableEntry->Misc.VirtualSize == 0) {
05738 SectionVirtualSize = SectionTableEntry->SizeOfRawData;
05739 }
05740
else {
05741 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize;
05742 }
05743
05744 VirtualAddress = (ULONG_PTR)DllBase + SectionTableEntry->VirtualAddress;
05745
if (VirtualAddress <= LastVirtualAddress) {
05746
05747
05748
05749
05750
05751
05752 KdPrint ((
"MM:sysload - Image at %p is badly linked\n", DllBase));
05753
return;
05754 }
05755 LastVirtualAddress = VirtualAddress + SectionVirtualSize - 1;
05756 }
05757
05758 NumberOfSubsections = FileHeader->NumberOfSections;
05759
ASSERT (NumberOfSubsections != 0);
05760
05761 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader +
05762 OffsetToSectionTable);
05763
05764 LastVirtualAddress = 0;
05765
05766
05767
05768
05769
05770
05771
05772 WritablePte =
MiGetPteAddress ((ULONG_PTR)(SectionTableEntry + NumberOfSubsections) - 1);
05773 LastImagePte =
MiGetPteAddress(DllBase) + NumberOfPtes;
05774
05775
for ( ; NumberOfSubsections > 0; NumberOfSubsections -= 1, SectionTableEntry += 1) {
05776
05777
if (SectionTableEntry->Misc.VirtualSize == 0) {
05778 SectionVirtualSize = SectionTableEntry->SizeOfRawData;
05779 }
05780
else {
05781 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize;
05782 }
05783
05784 VirtualAddress = (ULONG_PTR)DllBase + SectionTableEntry->VirtualAddress;
05785
05786 PointerPte =
MiGetPteAddress (VirtualAddress);
05787
05788
if (PointerPte >= LastImagePte) {
05789
05790
05791
05792
05793
05794
break;
05795 }
05796
05797 SectionProtection = (SectionTableEntry->Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE));
05798
05799
if (SectionProtection & IMAGE_SCN_MEM_WRITE) {
05800
05801
05802
05803
05804
05805
05806
05807
05808 WritablePte =
MiGetPteAddress (VirtualAddress + SectionVirtualSize - 1);
05809
05810
if (LastVirtualAddress) {
05811 LastPte =
MiGetPteAddress (LastVirtualAddress);
05812
05813
if (LastPte == PointerPte) {
05814 LastPte -= 1;
05815 }
05816
05817
if (FirstPte <= LastPte) {
05818
05819
ASSERT (PointerPte < LastImagePte);
05820
05821
if (LastPte >= LastImagePte) {
05822 LastPte = LastImagePte - 1;
05823 }
05824
05825
MiSetSystemCodeProtection (FirstPte, LastPte);
05826 }
05827
05828 LastVirtualAddress = 0;
05829 }
05830
continue;
05831 }
05832
05833
if (LastVirtualAddress == 0) {
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
if (PointerPte == WritablePte) {
05844 LastPte =
MiGetPteAddress (VirtualAddress + SectionVirtualSize - 1);
05845
if (PointerPte == LastPte) {
05846
05847
05848
05849
05850
05851
05852
continue;
05853 }
05854 PointerPte += 1;
05855 }
05856 FirstPte = PointerPte;
05857 }
05858
05859 LastVirtualAddress = VirtualAddress + SectionVirtualSize - 1;
05860 }
05861
05862
if (LastVirtualAddress) {
05863 LastPte =
MiGetPteAddress (LastVirtualAddress);
05864
05865
if ((FirstPte <= LastPte) && (FirstPte < LastImagePte)) {
05866
05867
if (LastPte >= LastImagePte) {
05868 LastPte = LastImagePte - 1;
05869 }
05870
05871
MiSetSystemCodeProtection (FirstPte, LastPte);
05872 }
05873 }
05874 }
05875
05876
05877
VOID
05878 MiUpdateThunks (
05879 IN
PLOADER_PARAMETER_BLOCK LoaderBlock,
05880 IN PVOID OldAddress,
05881 IN PVOID NewAddress,
05882 IN ULONG NumberOfBytes
05883 )
05884
05885
05886
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908 {
05909 PULONG_PTR ImportThunk;
05910 ULONG_PTR OldAddressHigh;
05911 ULONG_PTR AddressDifference;
05912 PLDR_DATA_TABLE_ENTRY DataTableEntry;
05913 PLIST_ENTRY NextEntry;
05914 ULONG_PTR i;
05915 ULONG ImportSize;
05916
05917
05918
05919
05920
05921
05922
05923 OldAddressHigh = (ULONG_PTR)((PCHAR)OldAddress + NumberOfBytes - 1);
05924 AddressDifference = (ULONG_PTR)NewAddress - (ULONG_PTR)OldAddress;
05925
05926 NextEntry = LoaderBlock->LoadOrderListHead.Flink;
05927
05928
for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) {
05929
05930 DataTableEntry = CONTAINING_RECORD(NextEntry,
05931 LDR_DATA_TABLE_ENTRY,
05932 InLoadOrderLinks);
05933
05934 ImportThunk = (PULONG_PTR)
RtlImageDirectoryEntryToData(
05935 DataTableEntry->DllBase,
05936
TRUE,
05937 IMAGE_DIRECTORY_ENTRY_IAT,
05938 &ImportSize);
05939
05940
if (ImportThunk ==
NULL) {
05941
continue;
05942 }
05943
05944 ImportSize /=
sizeof(PULONG_PTR);
05945
05946
for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) {
05947
if (*ImportThunk >= (ULONG_PTR)OldAddress && *ImportThunk <= OldAddressHigh) {
05948 *ImportThunk += AddressDifference;
05949 }
05950 }
05951 }
05952 }
05953
05954
05955
VOID
05956 MiReloadBootLoadedDrivers (
05957 IN
PLOADER_PARAMETER_BLOCK LoaderBlock
05958 )
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981
05982
05983
05984
05985
05986
05987
05988
05989
05990
05991 {
05992 PLDR_DATA_TABLE_ENTRY DataTableEntry;
05993 PLIST_ENTRY NextEntry;
05994 PIMAGE_NT_HEADERS NtHeader;
05995 PIMAGE_DATA_DIRECTORY DataDirectory;
05996 ULONG_PTR i;
05997 ULONG NumberOfPtes;
05998 ULONG NumberOfLoaderPtes;
05999
PMMPTE PointerPte;
06000
PMMPTE LastPte;
06001
PMMPTE LoaderPte;
06002
MMPTE PteContents;
06003
MMPTE TempPte;
06004 PVOID LoaderImageAddress;
06005 PVOID NewImageAddress;
06006
NTSTATUS Status;
06007 PFN_NUMBER PageFrameIndex;
06008 PFN_NUMBER PteFramePage;
06009
PMMPTE PteFramePointer;
06010
PMMPFN Pfn1;
06011
PMMPFN Pfn2;
06012 KIRQL OldIrql;
06013 PCHAR RelocatedVa;
06014 PCHAR NonRelocatedVa;
06015 LOGICAL StopMoving;
06016
06017
#if !defined (_X86_)
06018
06019
06020
06021
06022
06023
MmMakeLowMemory =
FALSE;
06024
#endif
06025
StopMoving =
FALSE;
06026
06027 i = 0;
06028 NextEntry = LoaderBlock->LoadOrderListHead.Flink;
06029
06030
for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) {
06031
06032
06033
06034
06035
06036
06037 i += 1;
06038
if (i <= 2) {
06039
continue;
06040 }
06041
06042 DataTableEntry = CONTAINING_RECORD(NextEntry,
06043 LDR_DATA_TABLE_ENTRY,
06044 InLoadOrderLinks);
06045
06046
06047
06048
06049
06050
06051 NtHeader =
RtlImageNtHeader(DataTableEntry->DllBase);
06052
06053
if (NtHeader ==
NULL) {
06054
continue;
06055 }
06056
06057
if (IMAGE_DIRECTORY_ENTRY_BASERELOC >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) {
06058
continue;
06059 }
06060
06061 DataDirectory = &NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
06062
06063
if (DataDirectory->VirtualAddress == 0) {
06064
continue;
06065 }
06066
06067
if (DataDirectory->VirtualAddress + DataDirectory->Size > DataTableEntry->SizeOfImage) {
06068
06069
06070
06071
06072
06073
06074
continue;
06075 }
06076
06077 LoaderImageAddress = DataTableEntry->DllBase;
06078 LoaderPte =
MiGetPteAddress(DataTableEntry->DllBase);
06079 NumberOfLoaderPtes = (ULONG)((
ROUND_TO_PAGES(DataTableEntry->SizeOfImage)) >>
PAGE_SHIFT);
06080
06081
LOCK_PFN (OldIrql);
06082
06083 PointerPte = LoaderPte;
06084 LastPte = PointerPte + NumberOfLoaderPtes;
06085
06086
while (PointerPte < LastPte) {
06087
ASSERT (PointerPte->
u.Hard.Valid == 1);
06088 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
06089 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06090
06091
06092
06093
06094
06095
06096 Pfn1->
u3.e1.Modified = 1;
06097 PointerPte += 1;
06098 }
06099
06100
UNLOCK_PFN (OldIrql);
06101
06102
06103
06104
06105
06106
06107 NumberOfPtes = NumberOfLoaderPtes;
06108
06109 PointerPte =
MiReserveSystemPtes (NumberOfPtes,
06110
SystemPteSpace,
06111 0,
06112 0,
06113
FALSE);
06114
06115
if (PointerPte ==
NULL) {
06116
continue;
06117 }
06118
06119 LastPte = PointerPte + NumberOfPtes;
06120
06121 NewImageAddress =
MiGetVirtualAddressMappedByPte (PointerPte);
06122
06123
#if DBG_SYSLOAD
06124
DbgPrint (
"Relocating %wZ from %p to %p, %x bytes\n",
06125 &DataTableEntry->FullDllName,
06126 DataTableEntry->DllBase,
06127 NewImageAddress,
06128 DataTableEntry->SizeOfImage
06129 );
06130
#endif
06131
06132
06133
06134
06135
06136
06137
ASSERT (
InitializationPhase == 0);
06138
06139
06140
06141
06142
06143
06144
06145
06146 RelocatedVa = NewImageAddress;
06147 NonRelocatedVa = (PCHAR) DataTableEntry->DllBase;
06148
06149
while (PointerPte < LastPte) {
06150
06151 PteContents = *LoaderPte;
06152
ASSERT (PteContents.
u.Hard.Valid == 1);
06153
06154
if (
MmMakeLowMemory ==
TRUE) {
06155
#if DBG
06156
PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (LoaderPte);
06157 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06158
ASSERT (Pfn1->
u1.WsIndex == 0);
06159
#endif
06160
LOCK_PFN (OldIrql);
06161
MiEnsureAvailablePageOrWait (
NULL,
NULL);
06162 PageFrameIndex =
MiRemoveAnyPage(
06163
MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
06164
06165
if (PageFrameIndex < (16*1024*1024)/
PAGE_SIZE) {
06166
06167
06168
06169
06170
06171
06172
#if defined (_X86PAE_)
06173
if (
MiNoLowMemory ==
FALSE)
06174
#endif
06175
StopMoving =
TRUE;
06176 }
06177
06178
MI_MAKE_VALID_PTE (TempPte,
06179 PageFrameIndex,
06180
MM_EXECUTE_READWRITE,
06181 PointerPte);
06182
06183
MI_SET_PTE_DIRTY (TempPte);
06184
MI_SET_ACCESSED_IN_PTE (&TempPte, 1);
06185
MI_WRITE_VALID_PTE (PointerPte, TempPte);
06186
06187
MiInitializePfn (PageFrameIndex, PointerPte, 1);
06188 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06189 Pfn1->
u3.e1.Modified = 1;
06190
06191
06192
06193
06194
06195 Pfn1->
u1.WsIndex = 0;
06196
06197
UNLOCK_PFN (OldIrql);
06198 RtlMoveMemory (RelocatedVa, NonRelocatedVa,
PAGE_SIZE);
06199 RelocatedVa +=
PAGE_SIZE;
06200 NonRelocatedVa +=
PAGE_SIZE;
06201 }
06202
else {
06203
MI_MAKE_VALID_PTE (TempPte,
06204 PteContents.
u.Hard.PageFrameNumber,
06205
MM_EXECUTE_READWRITE,
06206 PointerPte);
06207
06208
MI_WRITE_VALID_PTE (PointerPte, TempPte);
06209 }
06210
06211 PointerPte += 1;
06212 LoaderPte += 1;
06213 }
06214 PointerPte -= NumberOfPtes;
06215
06216
ASSERT (*(PULONG)NewImageAddress == *(PULONG)LoaderImageAddress);
06217
06218
06219
06220
06221
06222
#if defined(_ALPHA_)
06223
06224
06225
06226
06227
06228
06229
Status = (
NTSTATUS)
LdrDoubleRelocateImage(NewImageAddress,
06230 LoaderImageAddress,
06231
"SYSLDR",
06232 (ULONG)STATUS_SUCCESS,
06233 (ULONG)STATUS_CONFLICTING_ADDRESSES,
06234 (ULONG)STATUS_INVALID_IMAGE_FORMAT
06235 );
06236
#endif
06237
06238 NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)LoaderImageAddress;
06239
if (
MmMakeLowMemory ==
TRUE) {
06240 PIMAGE_NT_HEADERS NtHeader2;
06241
06242 NtHeader2 = (PIMAGE_NT_HEADERS)((PCHAR)NtHeader + (RelocatedVa - NonRelocatedVa));
06243 NtHeader2->OptionalHeader.ImageBase = (ULONG_PTR)LoaderImageAddress;
06244 }
06245
06246
Status = (
NTSTATUS)
LdrRelocateImage(NewImageAddress,
06247
"SYSLDR",
06248 (ULONG)STATUS_SUCCESS,
06249 (ULONG)STATUS_CONFLICTING_ADDRESSES,
06250 (ULONG)STATUS_INVALID_IMAGE_FORMAT
06251 );
06252
06253
if (!
NT_SUCCESS(
Status)) {
06254
06255
if (
MmMakeLowMemory ==
TRUE) {
06256
while (PointerPte < LastPte) {
06257 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
06258 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06259
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
06260
MI_SET_PFN_DELETED (Pfn1);
06261
MiDecrementShareCountOnly (PageFrameIndex);
06262 PointerPte += 1;
06263 }
06264 }
06265
06266
MiReleaseSystemPtes (PointerPte,
06267 NumberOfPtes,
06268
SystemPteSpace);
06269
06270
if (StopMoving ==
TRUE) {
06271
MmMakeLowMemory =
FALSE;
06272 }
06273
06274
continue;
06275 }
06276
06277
06278
06279
06280
06281 NonRelocatedVa = (PCHAR) DataTableEntry->DllBase;
06282 DataTableEntry->DllBase = NewImageAddress;
06283
06284
MiUpdateThunks (LoaderBlock,
06285 LoaderImageAddress,
06286 NewImageAddress,
06287 DataTableEntry->SizeOfImage);
06288
06289
06290
06291
06292
06293
06294 DataTableEntry->Flags |= LDRP_SYSTEM_MAPPED;
06295 DataTableEntry->DllBase = NewImageAddress;
06296 DataTableEntry->EntryPoint =
06297 (PVOID)((PCHAR)NewImageAddress + NtHeader->OptionalHeader.AddressOfEntryPoint);
06298 DataTableEntry->SizeOfImage = NumberOfPtes <<
PAGE_SHIFT;
06299
06300
06301
06302
06303
06304
06305
06306 LoaderPte =
MiGetPteAddress (NonRelocatedVa);
06307
06308
LOCK_PFN (OldIrql);
06309
06310
while (PointerPte < LastPte) {
06311
ASSERT (PointerPte->
u.Hard.Valid == 1);
06312
06313
if (
MmMakeLowMemory ==
TRUE) {
06314
ASSERT (LoaderPte->u.Hard.Valid == 1);
06315 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (LoaderPte);
06316 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06317
06318
#if defined (_X86_) || defined (_IA64_)
06319
06320
06321
06322
06323
06324
06325
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
06326
#endif
06327
06328
MI_SET_PFN_DELETED (Pfn1);
06329
MiDecrementShareCountOnly (PageFrameIndex);
06330 LoaderPte += 1;
06331 }
06332
else {
06333
06334 PageFrameIndex =
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
06335 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
06336
06337
#if defined (_X86_) || defined (_IA64_)
06338
06339
06340
06341
06342
06343
06344
MiDecrementShareAndValidCount (Pfn1->
PteFrame);
06345 *Pfn1->
PteAddress =
ZeroPte;
06346
#endif
06347
06348
06349
06350
06351
06352 PteFramePointer =
MiGetPteAddress(PointerPte);
06353 PteFramePage =
MI_GET_PAGE_FRAME_FROM_PTE (PteFramePointer);
06354
06355 Pfn1->
PteFrame = PteFramePage;
06356 Pfn1->
PteAddress = PointerPte;
06357
06358
06359
06360
06361
06362
06363 Pfn2 =
MI_PFN_ELEMENT (PteFramePage);
06364 Pfn2->
u2.ShareCount += 1;
06365 }
06366
06367 PointerPte += 1;
06368 }
06369
06370
UNLOCK_PFN (OldIrql);
06371
06372
06373
06374
06375
06376
06377
06378
if (StopMoving ==
TRUE) {
06379
MmMakeLowMemory =
FALSE;
06380 }
06381 }
06382
#if defined (_X86PAE_)
06383
if (
MiNoLowMemory ==
TRUE) {
06384
MiRemoveLowPages ();
06385 }
06386
#endif
06387
}
06388
06389
#if defined (_X86_)
06390
PMMPTE MiKernelResourceStartPte;
06391
PMMPTE MiKernelResourceEndPte;
06392
#endif
06393
06394
VOID
06395 MiLocateKernelSections (
06396 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
06397 )
06398
06399
06400
06401
06402
06403
06404
06405
06406
06407
06408
06409
06410
06411
06412
06413
06414
06415
06416
06417
06418
06419
06420
06421 {
06422 PVOID CurrentBase;
06423 PIMAGE_NT_HEADERS NtHeader;
06424 PIMAGE_SECTION_HEADER SectionTableEntry;
06425 LONG i;
06426
PMMPTE PointerPte;
06427 PVOID SectionBaseAddress;
06428
06429 CurrentBase = (PVOID)DataTableEntry->DllBase;
06430
06431 NtHeader =
RtlImageNtHeader(CurrentBase);
06432
06433 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader +
06434
sizeof(ULONG) +
06435
sizeof(IMAGE_FILE_HEADER) +
06436 NtHeader->FileHeader.SizeOfOptionalHeader);
06437
06438
06439
06440
06441
06442 i = NtHeader->FileHeader.NumberOfSections;
06443
06444 PointerPte =
NULL;
06445
06446
while (i > 0) {
06447
06448 SectionBaseAddress =
SECTION_BASE_ADDRESS(SectionTableEntry);
06449
06450
#if defined (_X86_)
06451
if (*(PULONG)SectionTableEntry->Name == 'rsr.') {
06452
06453 MiKernelResourceStartPte =
MiGetPteAddress ((ULONG_PTR)CurrentBase +
06454 SectionTableEntry->VirtualAddress);
06455
06456 MiKernelResourceEndPte =
MiGetPteAddress (
ROUND_TO_PAGES((ULONG_PTR)CurrentBase +
06457 SectionTableEntry->VirtualAddress +
06458 (NtHeader->OptionalHeader.SectionAlignment - 1) +
06459 SectionTableEntry->SizeOfRawData -
06460
PAGE_SIZE));
06461
break;
06462 }
06463
#endif
06464
if (*(PULONG)SectionTableEntry->Name == 'LOOP') {
06465
if (*(PULONG)&SectionTableEntry->Name[4] == 'EDOC') {
06466
ExPoolCodeStart = (PVOID)((ULONG_PTR)CurrentBase +
06467 SectionTableEntry->VirtualAddress);
06468
ExPoolCodeEnd = (PVOID)((ULONG_PTR)CurrentBase +
06469 SectionTableEntry->VirtualAddress +
06470 SectionTableEntry->SizeOfRawData);
06471 }
06472
else if (*(
PUSHORT)&SectionTableEntry->Name[4] == 'IM') {
06473
MmPoolCodeStart = (PVOID)((ULONG_PTR)CurrentBase +
06474 SectionTableEntry->VirtualAddress);
06475
MmPoolCodeEnd = (PVOID)((ULONG_PTR)CurrentBase +
06476 SectionTableEntry->VirtualAddress +
06477 SectionTableEntry->SizeOfRawData);
06478 }
06479 }
06480
else if ((*(PULONG)SectionTableEntry->Name == 'YSIM') &&
06481 (*(PULONG)&SectionTableEntry->Name[4] == 'ETPS')) {
06482
MmPteCodeStart = (PVOID)((ULONG_PTR)CurrentBase +
06483 SectionTableEntry->VirtualAddress);
06484
MmPteCodeEnd = (PVOID)((ULONG_PTR)CurrentBase +
06485 SectionTableEntry->VirtualAddress +
06486 SectionTableEntry->SizeOfRawData);
06487 }
06488
06489 i -= 1;
06490 SectionTableEntry += 1;
06491 }
06492 }
06493
06494
VOID
06495 MmMakeKernelResourceSectionWritable (
06496 VOID
06497 )
06498
06499
06500
06501
06502
06503
06504
06505
06506
06507
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517
06518
06519
06520 {
06521
#if defined (_X86_)
06522
MMPTE TempPte;
06523
MMPTE PteContents;
06524
PMMPTE PointerPte;
06525
06526
if (MiKernelResourceStartPte ==
NULL) {
06527
return;
06528 }
06529
06530 PointerPte = MiKernelResourceStartPte;
06531
06532
if (
MI_IS_PHYSICAL_ADDRESS (
MiGetVirtualAddressMappedByPte (PointerPte))) {
06533
06534
06535
06536
06537
06538
return;
06539 }
06540
06541
06542
06543
06544
06545
06546
do {
06547 PteContents = *PointerPte;
06548
#if defined(NT_UP)
06549
if (PteContents.
u.Hard.Write == 0)
06550
#else
06551
if (PteContents.
u.Hard.Writable == 0)
06552
#endif
06553
{
06554
MI_MAKE_VALID_PTE (TempPte,
06555 PteContents.
u.Hard.PageFrameNumber,
06556
MM_READWRITE,
06557 PointerPte);
06558
#if !defined(NT_UP)
06559
TempPte.
u.Hard.Writable = 1;
06560
#endif
06561
MI_WRITE_VALID_PTE_NEW_PROTECTION (PointerPte, TempPte);
06562 }
06563 PointerPte += 1;
06564 }
while (PointerPte <= MiKernelResourceEndPte);
06565
06566
06567
06568
06569
06570 MiKernelResourceStartPte =
NULL;
06571
06572
06573
06574
06575
06576
KeFlushCurrentTb ();
06577
#endif
06578
}
06579
06580
#ifdef i386
06581
PVOID
PsNtosImageBase = (PVOID)0x80100000;
06582
#else
06583 PVOID
PsNtosImageBase;
06584
#endif
06585
06586 LIST_ENTRY
PsLoadedModuleList;
06587 ERESOURCE PsLoadedModuleResource;
06588
extern KSPIN_LOCK
PsLoadedModuleSpinLock;
06589
06590 LOGICAL
06591 MiInitializeLoadedModuleList (
06592 IN
PLOADER_PARAMETER_BLOCK LoaderBlock
06593 )
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615 {
06616 PLIST_ENTRY NextEntry;
06617 PLDR_DATA_TABLE_ENTRY DataTableEntry1;
06618 PLDR_DATA_TABLE_ENTRY DataTableEntry2;
06619
06620
06621
06622
06623
06624
ExInitializeResource (&
PsLoadedModuleResource);
06625
KeInitializeSpinLock (&
PsLoadedModuleSpinLock);
06626
06627 InitializeListHead (&
PsLoadedModuleList);
06628
06629
06630
06631
06632
06633
06634
06635
06636
06637 NextEntry = LoaderBlock->LoadOrderListHead.Flink;
06638 DataTableEntry2 = CONTAINING_RECORD(NextEntry,
06639 LDR_DATA_TABLE_ENTRY,
06640 InLoadOrderLinks);
06641
PsNtosImageBase = DataTableEntry2->DllBase;
06642
06643
MiLocateKernelSections (DataTableEntry2);
06644
06645
while (NextEntry != &LoaderBlock->LoadOrderListHead) {
06646
06647 DataTableEntry2 = CONTAINING_RECORD(NextEntry,
06648 LDR_DATA_TABLE_ENTRY,
06649 InLoadOrderLinks);
06650
06651
06652
06653
06654
06655 DataTableEntry1 =
ExAllocatePoolWithTag (
NonPagedPool,
06656
sizeof(LDR_DATA_TABLE_ENTRY),
06657 'dLmM');
06658
06659
if (DataTableEntry1 ==
NULL) {
06660
return FALSE;
06661 }
06662
06663
06664
06665
06666
06667 *DataTableEntry1 = *DataTableEntry2;
06668
06669 DataTableEntry1->FullDllName.Buffer =
ExAllocatePoolWithTag (
PagedPool,
06670 DataTableEntry2->FullDllName.MaximumLength +
sizeof(UNICODE_NULL),
06671 'TDmM');
06672
06673
if (DataTableEntry1->FullDllName.Buffer ==
NULL) {
06674
ExFreePool (DataTableEntry1);
06675
return FALSE;
06676 }
06677
06678 DataTableEntry1->BaseDllName.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
06679 DataTableEntry2->BaseDllName.MaximumLength +
sizeof(UNICODE_NULL),
06680 'dLmM');
06681
06682
if (DataTableEntry1->BaseDllName.Buffer ==
NULL) {
06683
ExFreePool (DataTableEntry1->FullDllName.Buffer);
06684
ExFreePool (DataTableEntry1);
06685
return FALSE;
06686 }
06687
06688
06689
06690
06691
06692 RtlMoveMemory (DataTableEntry1->FullDllName.Buffer,
06693 DataTableEntry2->FullDllName.Buffer,
06694 DataTableEntry1->FullDllName.MaximumLength);
06695
06696 RtlMoveMemory (DataTableEntry1->BaseDllName.Buffer,
06697 DataTableEntry2->BaseDllName.Buffer,
06698 DataTableEntry1->BaseDllName.MaximumLength);
06699
06700
06701
06702
06703
06704
06705 InsertTailList(&
PsLoadedModuleList,
06706 &DataTableEntry1->InLoadOrderLinks);
06707
06708 NextEntry = NextEntry->Flink;
06709 }
06710
06711
MiBuildImportsForBootDrivers ();
06712
06713
return TRUE;
06714 }
06715
06716
NTSTATUS
06717 MmCallDllInitialize(
06718 IN PLDR_DATA_TABLE_ENTRY DataTableEntry
06719 )
06720
06721
06722
06723
06724
06725
06726
06727
06728
06729
06730
06731
06732
06733
06734
06735
06736
06737
06738
06739
06740
06741 {
06742
NTSTATUS st;
06743 PWCHAR Dot;
06744
PMM_DLL_INITIALIZE Func;
06745 UNICODE_STRING RegistryPath;
06746 UNICODE_STRING ImportName;
06747
06748 Func =
MiLocateExportName (DataTableEntry->DllBase,
"DllInitialize");
06749
06750
if (!Func) {
06751
return STATUS_SUCCESS;
06752 }
06753
06754 ImportName.MaximumLength = DataTableEntry->BaseDllName.Length;
06755 ImportName.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
06756 ImportName.MaximumLength,
06757 'TDmM');
06758
06759
if (ImportName.Buffer ==
NULL) {
06760
return STATUS_INSUFFICIENT_RESOURCES;
06761 }
06762
06763 ImportName.Length = DataTableEntry->BaseDllName.Length;
06764 RtlMoveMemory (ImportName.Buffer,
06765 DataTableEntry->BaseDllName.Buffer,
06766 ImportName.Length);
06767
06768 RegistryPath.MaximumLength =
CmRegistryMachineSystemCurrentControlSetServices.Length +
06769 ImportName.Length +
06770 (
USHORT)(2*
sizeof(WCHAR));
06771
06772 RegistryPath.Buffer =
ExAllocatePoolWithTag (
NonPagedPool,
06773 RegistryPath.MaximumLength,
06774 'TDmM');
06775
06776
if (RegistryPath.Buffer ==
NULL) {
06777
ExFreePool (ImportName.Buffer);
06778
return STATUS_INSUFFICIENT_RESOURCES;
06779 }
06780
06781 RegistryPath.Length =
CmRegistryMachineSystemCurrentControlSetServices.Length;
06782 RtlMoveMemory (RegistryPath.Buffer,
06783
CmRegistryMachineSystemCurrentControlSetServices.Buffer,
06784
CmRegistryMachineSystemCurrentControlSetServices.Length);
06785
06786
RtlAppendUnicodeToString (&RegistryPath,
L"\\");
06787 Dot = wcschr (ImportName.Buffer,
L'.');
06788
if (Dot) {
06789 ImportName.Length = (
USHORT)((Dot - ImportName.Buffer) *
sizeof(WCHAR));
06790 }
06791
06792
RtlAppendUnicodeStringToString (&RegistryPath, &ImportName);
06793
ExFreePool (ImportName.Buffer);
06794
06795
06796
06797
06798
06799 st = Func (&RegistryPath);
06800
06801
ExFreePool (RegistryPath.Buffer);
06802
06803
return st;
06804 }
06805
06806
NTKERNELAPI
06807 PVOID
06808 MmGetSystemRoutineAddress (
06809 IN PUNICODE_STRING SystemRoutineName
06810 )
06811
06812
06813
06814
06815
06816
06817
06818
06819
06820
06821
06822
06823
06824
06825
06826
06827
06828
06829
06830
06831
06832
06833 {
06834 ULONG AnsiLength;
06835
NTSTATUS Status;
06836 PLDR_DATA_TABLE_ENTRY DataTableEntry;
06837 ANSI_STRING AnsiString;
06838 PLIST_ENTRY NextEntry;
06839 UNICODE_STRING KernelString;
06840 UNICODE_STRING HalString;
06841 PVOID FunctionAddress;
06842 LOGICAL Found;
06843 ULONG EntriesChecked;
06844
06845
ASSERT (KeGetCurrentIrql() ==
PASSIVE_LEVEL);
06846
06847 EntriesChecked = 0;
06848 FunctionAddress =
NULL;
06849
06850
RtlInitUnicodeString (&KernelString,
L"ntoskrnl.exe");
06851
RtlInitUnicodeString (&HalString,
L"hal.dll");
06852
06853
do {
06854
Status =
RtlUnicodeStringToAnsiString( &AnsiString,
06855 SystemRoutineName,
06856
TRUE );
06857
06858
if (
NT_SUCCESS(
Status)) {
06859
break;
06860 }
06861
06862
KeDelayExecutionThread (
KernelMode,
FALSE, &
MmShortTime);
06863
06864 }
while (
TRUE);
06865
06866
06867
06868
06869
06870
KeEnterCriticalRegion();
06871
ExAcquireResourceShared (&
PsLoadedModuleResource,
TRUE);
06872
06873
06874
06875
06876
06877 NextEntry =
PsLoadedModuleList.Flink;
06878
while (NextEntry != &
PsLoadedModuleList) {
06879
06880 Found =
FALSE;
06881
06882 DataTableEntry = CONTAINING_RECORD(NextEntry,
06883 LDR_DATA_TABLE_ENTRY,
06884 InLoadOrderLinks);
06885
06886
if (
RtlEqualUnicodeString (&KernelString,
06887 &DataTableEntry->BaseDllName,
06888
TRUE)) {
06889
06890 Found =
TRUE;
06891 EntriesChecked += 1;
06892
06893 }
06894
else if (
RtlEqualUnicodeString (&HalString,
06895 &DataTableEntry->BaseDllName,
06896
TRUE)) {
06897
06898 Found =
TRUE;
06899 EntriesChecked += 1;
06900 }
06901
06902
if (Found ==
TRUE) {
06903
06904 FunctionAddress =
MiFindExportedRoutineByName (DataTableEntry,
06905 &AnsiString);
06906
06907
if (FunctionAddress !=
NULL) {
06908
break;
06909 }
06910
06911
if (EntriesChecked == 2) {
06912
break;
06913 }
06914 }
06915
06916 NextEntry = NextEntry->Flink;
06917 }
06918
06919
ExReleaseResource (&
PsLoadedModuleResource);
06920
KeLeaveCriticalRegion();
06921
06922
RtlFreeAnsiString (&AnsiString);
06923
06924
return FunctionAddress;
06925 }
06926
06927 PVOID
06928 MiFindExportedRoutineByName(
06929 IN PLDR_DATA_TABLE_ENTRY DataTableEntry,
06930 IN PANSI_STRING AnsiImageRoutineName
06931 )
06932
06933
06934
06935
06936
06937
06938
06939
06940
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952
06953
06954
06955
06956
06957
06958
06959
06960
06961
06962
06963
06964
06965 {
06966 PCHAR DllBase;
06967
USHORT OrdinalNumber;
06968 PULONG NameTableBase;
06969
PUSHORT NameOrdinalTableBase;
06970 PULONG Addr;
06971 ULONG High;
06972 ULONG Low;
06973 ULONG Middle;
06974 LONG Result;
06975 ULONG ExportSize;
06976 PVOID FunctionAddress;
06977 PIMAGE_EXPORT_DIRECTORY ExportDirectory;
06978
06979
PAGED_CODE();
06980
06981 DllBase = DataTableEntry->DllBase;
06982
06983 ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData(
06984 DllBase,
06985
TRUE,
06986 IMAGE_DIRECTORY_ENTRY_EXPORT,
06987 &ExportSize
06988 );
06989
06990
ASSERT (ExportDirectory !=
NULL);
06991
06992
06993
06994
06995
06996 NameTableBase = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfNames);
06997
06998
06999
07000
07001
07002 NameOrdinalTableBase = (
PUSHORT)(DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
07003
07004
07005
07006
07007
07008 Low = 0;
07009 High = ExportDirectory->NumberOfNames - 1;
07010
07011
while (High >= Low) {
07012
07013
07014
07015
07016
07017
07018 Middle = (Low + High) >> 1;
07019
07020 Result = strcmp(AnsiImageRoutineName->Buffer,
07021 (PCHAR)(DllBase + NameTableBase[Middle]));
07022
07023
if (Result < 0) {
07024 High = Middle - 1;
07025 }
07026
else if (Result > 0) {
07027 Low = Middle + 1;
07028 }
07029
else {
07030
break;
07031 }
07032 }
07033
07034
07035
07036
07037
07038
07039
07040
if (High < Low) {
07041
return NULL;
07042 }
07043
07044 OrdinalNumber = NameOrdinalTableBase[Middle];
07045
07046
07047
07048
07049
07050
07051
if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
07052
return NULL;
07053 }
07054
07055
07056
07057
07058
07059 Addr = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
07060
07061 FunctionAddress = (PVOID)(DllBase + Addr[OrdinalNumber]);
07062
07063
07064
07065
07066
07067
ASSERT ((FunctionAddress <= (PVOID)ExportDirectory) ||
07068 (FunctionAddress >= (PVOID)((PCHAR)ExportDirectory + ExportSize)));
07069
07070
return FunctionAddress;
07071 }