test: sysload.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# sysload.c File Reference

`#include "mi.h"`

Go to the source code of this file.

## Classes

struct | _LOAD_IMPORTS

## Defines

#define | LOADED_AT_BOOT ((PLOAD_IMPORTS)0)
#define | NO_IMPORTS_USED ((PLOAD_IMPORTS)-2)
#define | SINGLE_ENTRY(ImportVoid) ((ULONG)((ULONG_PTR)(ImportVoid) & 0x1))
#define | SINGLE_ENTRY_TO_POINTER(ImportVoid) ((PLDR_DATA_TABLE_ENTRY)((ULONG_PTR)(ImportVoid) & ~0x1))
#define | POINTER_TO_SINGLE_ENTRY(Pointer) ((PLDR_DATA_TABLE_ENTRY)((ULONG_PTR)(Pointer) | 0x1))

## Typedefs

typedef _LOAD_IMPORTS | LOAD_IMPORTS
typedef _LOAD_IMPORTS * | PLOAD_IMPORTS

## Functions

ULONG | LdrDoubleRelocateImage (IN PVOID NewBase, IN PVOID CurrentBase, IN PUCHAR LoaderName, IN ULONG Success, IN ULONG Conflict, IN ULONG Invalid)
ULONG | CacheImageSymbols (IN PVOID ImageBase)
NTSTATUS | MiResolveImageReferences (PVOID ImageBase, IN PUNICODE_STRING ImageFileDirectory, IN PUNICODE_STRING NamePrefix OPTIONAL, IN BOOLEAN LoadInSessionSpace, OUT PCHAR *MissingProcedureName, OUT PWSTR *MissingDriverName, OUT PLOAD_IMPORTS *LoadedImports)
NTSTATUS | MiSnapThunk (IN PVOID DllBase, IN PVOID ImageBase, IN PIMAGE_THUNK_DATA NameThunk, OUT PIMAGE_THUNK_DATA AddrThunk, IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, IN ULONG ExportSize, IN BOOLEAN SnapForwarder, OUT PCHAR *MissingProcedureName)
NTSTATUS | MiLoadImageSection (IN PSECTION SectionPointer, OUT PVOID *ImageBase, IN PUNICODE_STRING ImageFileName, IN BOOLEAN LoadInSessionSpace)
VOID | MiEnablePagingOfDriver (IN PVOID ImageHandle)
VOID | MiSetPagingOfDriver (IN PMMPTE PointerPte, IN PMMPTE LastPte, IN BOOLEAN SessionSpace)
PVOID | MiLookupImageSectionByName (IN PVOID Base, IN BOOLEAN MappedAsImage, IN PCHAR SectionName, OUT PULONG SectionSize)
VOID | MiClearImports (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
NTSTATUS | MiBuildImportsForBootDrivers (VOID)
NTSTATUS | MmCheckSystemImage (IN HANDLE ImageFileHandle)
LONG | MiMapCacheExceptionFilter (OUT PNTSTATUS Status, IN PEXCEPTION_POINTERS ExceptionPointer)
ULONG | MiSetProtectionOnTransitionPte (IN PMMPTE PointerPte, IN ULONG ProtectionMask)
NTSTATUS | MiDereferenceImports (IN PLOAD_IMPORTS ImportList)
LOGICAL | MiCallDllUnloadAndUnloadDll (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
PVOID | MiLocateExportName (IN PVOID DllBase, IN PCHAR FunctionName)
NTSTATUS | MiLoadSystemImage (IN PUNICODE_STRING ImageFileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedBaseName OPTIONAL, IN BOOLEAN LoadInSessionSpace, OUT PVOID *ImageHandle, OUT PVOID *ImageBaseAddress, IN BOOLEAN LockDownPages)
VOID | MiRememberUnloadedDriver (IN PUNICODE_STRING DriverName, IN PVOID Address, IN ULONG Length)
VOID | MiWriteProtectSystemImage (IN PVOID DllBase)
VOID | MiLocateKernelSections (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
VOID | MiUpdateThunks (IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PVOID OldAddress, IN PVOID NewAddress, IN ULONG NumberOfBytes)
NTSTATUS | MiCheckPageFilePath (PFILE_OBJECT FileObject)
PVOID | MiFindExportedRoutineByName (IN PLDR_DATA_TABLE_ENTRY DataTableEntry, IN PANSI_STRING AnsiImageRoutineName)
VOID | MiRemoveLowPages (VOID)
NTSTATUS | MmLoadSystemImage (IN PUNICODE_STRING ImageFileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedBaseName OPTIONAL, IN BOOLEAN LoadInSessionSpace, OUT PVOID *ImageHandle, OUT PVOID *ImageBaseAddress)
NTSTATUS | MmLoadAndLockSystemImage (IN PUNICODE_STRING ImageFileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedBaseName OPTIONAL, OUT PVOID *ImageHandle, OUT PVOID *ImageBaseAddress)
VOID | MmFreeDriverInitialization (IN PVOID ImageHandle)
PVOID | MmPageEntireDriver (IN PVOID AddressWithinSection)
VOID | MmResetDriverPaging (IN PVOID AddressWithinSection)
PUNICODE_STRING | MmLocateUnloadedDriver (IN PVOID VirtualAddress)
NTSTATUS | MmUnloadSystemImage (IN PVOID ImageHandle)
BOOLEAN | MmVerifyImageIsOkForMpUse (IN PVOID BaseAddress)
PFN_NUMBER | MiDeleteSystemPagableVm (IN PMMPTE PointerPte, IN PFN_NUMBER NumberOfPtes, IN MMPTE NewPteValue, IN LOGICAL SessionAllocation, OUT PPFN_NUMBER ResidentPages)
VOID | MiSetImageProtect (IN PSEGMENT Segment, IN ULONG Protection)
VOID | MiSetSystemCodeProtection (IN PMMPTE FirstPte, IN PMMPTE LastPte)
VOID | MiReloadBootLoadedDrivers (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID | MmMakeKernelResourceSectionWritable (VOID)
LOGICAL | MiInitializeLoadedModuleList (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
NTSTATUS | MmCallDllInitialize (IN PLDR_DATA_TABLE_ENTRY DataTableEntry)
NTKERNELAPI PVOID | MmGetSystemRoutineAddress (IN PUNICODE_STRING SystemRoutineName)

## Variables

KMUTANT | MmSystemLoadLock
ULONG | MmTotalSystemDriverPages
ULONG | MmDriverCommit
BOOLEAN | MiFirstDriverLoadEver = TRUE
LOGICAL | MmMakeLowMemory = TRUE
PUNLOADED_DRIVERS | MiUnloadedDrivers
ULONG | MiLastUnloadedDriver
ULONG | MiTotalUnloads
ULONG | MiUnloadsSkipped
ULONG | MmEnforceWriteProtection = 1
PVOID | ExPoolCodeStart
PVOID | ExPoolCodeEnd
PVOID | MmPoolCodeStart
PVOID | MmPoolCodeEnd
PVOID | MmPteCodeStart
PVOID | MmPteCodeEnd
KSPIN_LOCK | PsLoadedModuleSpinLock
LOGICAL | MiNoLowMemory
CHAR | MiPteStr [] = "\0"
PVOID | PsNtosImageBase
LIST_ENTRY | PsLoadedModuleList
ERESOURCE | PsLoadedModuleResource

## Define Documentation

#define LOADED_AT_BOOT ((PLOAD_IMPORTS)0)

| Definition at line 46 of file sysload.c. Referenced by MiBuildImportsForBootDrivers(), MiClearImports(), MiDereferenceImports(), and MmUnloadSystemImage().

#define NO_IMPORTS_USED ((PLOAD_IMPORTS)-2)

| Definition at line 47 of file sysload.c. Referenced by MiBuildImportsForBootDrivers(), MiClearImports(), MiDereferenceImports(), MiLoadSystemImage(), and MiResolveImageReferences().

#define POINTER_TO_SINGLE_ENTRY | ( | Pointer |  | ) | ((PLDR_DATA_TABLE_ENTRY)((ULONG_PTR)(Pointer) | 0x1))

| Definition at line 53 of file sysload.c. Referenced by MiBuildImportsForBootDrivers(), and MiResolveImageReferences().

#define SINGLE_ENTRY | ( | ImportVoid |  | ) | ((ULONG)((ULONG_PTR)(ImportVoid) & 0x1))

| Definition at line 49 of file sysload.c. Referenced by MiBuildImportsForBootDrivers(), MiClearImports(), and MiDereferenceImports().

#define SINGLE_ENTRY_TO_POINTER | ( | ImportVoid |  | ) | ((PLDR_DATA_TABLE_ENTRY)((ULONG_PTR)(ImportVoid) & ~0x1))

| Definition at line 51 of file sysload.c. Referenced by MiDereferenceImports().

## Typedef Documentation

typedef struct _LOAD_IMPORTS LOAD_IMPORTS

typedef struct _LOAD_IMPORTS * PLOAD_IMPORTS

| Referenced by MiBuildImportsForBootDrivers(), MiDereferenceImports(), MiLoadSystemImage(), MiResolveImageReferences(), and MmUnloadSystemImage().

## Function Documentation

ULONG CacheImageSymbols | ( | IN PVOID | ImageBase | ) |

| Referenced by MiLoadSystemImage(), and MiMapViewOfImageSection().

ULONG LdrDoubleRelocateImage | ( | IN PVOID | NewBase,
|  | IN PVOID | CurrentBase,
|  | IN PUCHAR | LoaderName,
|  | IN ULONG | Success,
|  | IN ULONG | Conflict,
|  | IN ULONG | Invalid
| ) |

| Referenced by MiReloadBootLoadedDrivers().

NTSTATUS MiBuildImportsForBootDrivers | ( | VOID |  | ) |

Definition at line 3326 of file sysload.c.

References ASSERT, _LOAD_IMPORTS::Count, DbgPrint, _LOAD_IMPORTS::Entry, ExAllocatePoolWithTag, ExFreePool(), FALSE, L, LOADED_AT_BOOT, NO_IMPORTS_USED, NULL, PAGED_CODE, PagedPool, PLOAD_IMPORTS, POINTER_TO_SINGLE_ENTRY, PsLoadedModuleList, RtlEqualUnicodeString(), RtlImageDirectoryEntryToData(), RtlInitUnicodeString(), SINGLE_ENTRY, and TRUE.

Referenced by MiInitializeLoadedModuleList().

    03332                    :
    03333
    03334     Construct an import list chain for boot-loaded drivers.
    03335     If this cannot be done for an entry, its chain is set to LOADED_AT_BOOT.
    03336
    03337     If a chain can be successfully built, then this driver's DLLs
    03338     will be automatically unloaded if this driver goes away (provided
    03339     no other driver is also using them).  Otherwise, on driver unload,
    03340     its dependent DLLs would have to be explicitly unloaded.
    03341
    03342     Note that the incoming LoadCount values are not correct and thus, they
    03343     are reinitialized here.
    03344
    03345 Arguments:
    03346
    03347     None.
    03348
    03349 Return Value:
    03350
    03351     Various NTSTATUS codes.
    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         // Initialize these properly so error recovery is simplified.
    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             // Check the hint first.
    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     // The kernel and HAL are never unloaded.
    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         // An error occurred and this is an all or nothing operation so
    03614         // roll everything back.
    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 }

LOGICAL MiCallDllUnloadAndUnloadDll | ( | IN PLDR_DATA_TABLE_ENTRY | DataTableEntry | ) |

Definition at line 3645 of file sysload.c.

References ASSERT, FALSE, MiLocateExportName(), MmUnloadSystemImage(), NT_SUCCESS, NTSTATUS(), PAGED_CODE, PMM_DLL_UNLOAD, Status, and TRUE.

Referenced by MiDereferenceImports().

    03651                    :
    03652
    03653     All the references from other drivers to this DLL have been cleared.
    03654     The only remaining issue is that this DLL must support being unloaded.
    03655     This means having no outstanding DPCs, allocated pool, etc.
    03656
    03657     If the DLL has an unload routine that returns SUCCESS, then we clean
    03658     it up and free up its memory now.
    03659
    03660     Note this routine is NEVER called for drivers - only for DLLs that were
    03661     loaded due to import references from various drivers.
    03662
    03663 Arguments:
    03664
    03665     DataTableEntry - provided for the DLL.
    03666
    03667 Return Value:
    03668
    03669     None.
    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         // The unload function was found in the DLL so unload it now.
    03688         //
    03689
    03690         Status = Func();
    03691
    03692         if (NT_SUCCESS(Status)) {
    03693
    03694             //
    03695             // Set up the reference count so the import DLL looks like a regular
    03696             // driver image is being unloaded.
    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 }

NTSTATUS MiCheckPageFilePath | ( | PFILE_OBJECT | FileObject | ) |

Definition at line 166 of file modwrite.c.

References ASSERT, _IRP::AssociatedIrp, DeviceUsageTypePaging, Executive, FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, IoAllocateIrp(), IoCallDriver, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IoQueueThreadIrp(), _IRP::IoStatus, IRP_MJ_PNP, IRP_MN_DEVICE_USAGE_NOTIFICATION, IRP_SYNCHRONOUS_API, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), NULL, ObReferenceObject, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, and VOID().

Referenced by MiLoadSystemImage(), and NtCreatePagingFile().

    00169 {
    00170     PIRP irp;
    00171     NTSTATUS status;
    00172     PDEVICE_OBJECT deviceObject;
    00173     KEVENT event;
    00174     PIO_STACK_LOCATION irpSp;
    00175     IO_STATUS_BLOCK localIoStatus;
    00176
    00177     PAGED_CODE();
    00178
    00179     //
    00180     // Reference the file object here so that no special checks need be made
    00181     // in I/O completion to determine whether or not to dereference the file
    00182     // object.
    00183     //
    00184
    00185     ObReferenceObject( FileObject );
    00186
    00187     //
    00188     // Initialize the local event.
    00189     //
    00190
    00191     KeInitializeEvent( &event, SynchronizationEvent, FALSE );
    00192
    00193     //
    00194     // Get the address of the target device object.
    00195     //
    00196
    00197     deviceObject = IoGetRelatedDeviceObject( FileObject );
    00198
    00199     //
    00200     // Allocate and initialize the I/O Request Packet (IRP) for this operation.
    00201     //
    00202
    00203     irp = IoAllocateIrp( deviceObject->StackSize, FALSE );
    00204     ASSERT( irp != NULL );
    00205
    00206     if (irp == NULL) {
    00207
    00208         //
    00209         // Don't dereference the file object, our caller will take care of that.
    00210         //
    00211
    00212         return STATUS_NO_MEMORY;
    00213     }
    00214
    00215     irp->Tail.Overlay.OriginalFileObject = FileObject;
    00216     irp->Tail.Overlay.Thread = PsGetCurrentThread();
    00217     irp->RequestorMode = KernelMode;
    00218
    00219     //
    00220     // Fill in the service independent parameters in the IRP.
    00221     //
    00222
    00223     irp->UserEvent = &event;
    00224     irp->Flags = IRP_SYNCHRONOUS_API;
    00225     irp->UserIosb = &localIoStatus;
    00226     irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;
    00227
    00228     //
    00229     // Get a pointer to the stack location for the first driver.  This will be
    00230     // used to pass the original function codes and parameters.
    00231     //
    00232
    00233     irpSp = IoGetNextIrpStackLocation( irp );
    00234     irpSp->MajorFunction = IRP_MJ_PNP;
    00235     irpSp->MinorFunction = IRP_MN_DEVICE_USAGE_NOTIFICATION;
    00236     irpSp->FileObject = FileObject;
    00237     irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    00238     irp->AssociatedIrp.SystemBuffer = NULL;
    00239     // irp->Flags = 0;
    00240
    00241     irpSp->Parameters.UsageNotification.InPath = TRUE;
    00242     irpSp->Parameters.UsageNotification.Type = DeviceUsageTypePaging;
    00243
    00244     //
    00245     // Insert the packet at the head of the IRP list for the thread.
    00246     //
    00247
    00248     IoQueueThreadIrp( irp );
    00249
    00250     //
    00251     // Now simply invoke the driver at its dispatch entry with the IRP.
    00252     //
    00253
    00254     status = IoCallDriver( deviceObject, irp );
    00255
    00256     //
    00257     // Wait for the local event and copy the final status information
    00258     // back to the caller.
    00259     //
    00260
    00261     if (status == STATUS_PENDING) {
    00262         (VOID) KeWaitForSingleObject( &event,
    00263                                       Executive,
    00264                                       KernelMode,
    00265                                       FALSE,
    00266                                       (PLARGE_INTEGER) NULL );
    00267         status = localIoStatus.Status;
    00268     }
    00269
    00270     return status;
    00271 }

VOID MiClearImports | ( | IN PLDR_DATA_TABLE_ENTRY | DataTableEntry | ) |

Definition at line 2693 of file sysload.c.

References ExFreePool(), LOADED_AT_BOOT, NO_IMPORTS_USED, PAGED_CODE, and SINGLE_ENTRY.

Referenced by MmUnloadSystemImage().

    02698                    :
    02699
    02700     Free up the import list and clear the pointer.  This stops the
    02701     recursion performed in MiDereferenceImports().
    02702
    02703 Arguments:
    02704
    02705     DataTableEntry - provided for the driver.
    02706
    02707 Return Value:
    02708
    02709     Status of the import list construction operation.
    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         // free the memory
    02729         //
    02730         ExFreePool ((PVOID)DataTableEntry->LoadedImports);
    02731     }
    02732
    02733     //
    02734     // stop the recursion
    02735     //
    02736     DataTableEntry->LoadedImports = (PVOID)LOADED_AT_BOOT;
    02737 }

PFN_NUMBER MiDeleteSystemPagableVm | ( | IN PMMPTE | PointerPte,
|  | IN PFN_NUMBER | NumberOfPtes,
|  | IN MMPTE | NewPteValue,
|  | IN LOGICAL | SessionAllocation,
|  | OUT PPFN_NUMBER | ResidentPages
| ) |

Definition at line 4950 of file sysload.c.

References APC_LEVEL, ASSERT, _MMPTE_FLUSH_LIST::Count, DbgPrint, FALSE, _MMWSL::FirstDynamic, _MMPTE_FLUSH_LIST::FlushPte, _MMPTE_FLUSH_LIST::FlushVa, FreePageList, KeBugCheckEx(), LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, _MMWSLENTRY::LockedInMemory, _MMWSLENTRY::LockedInWs, MI_CAPTURE_DIRTY_BIT_TO_PFN, MI_FLUSH_ENTIRE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MiCheckPdeForPagedPool(), MiDecrementShareAndValidCount, MiDecrementShareCount(), MiDecrementShareCountOnly, MiFlushPteList(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHighestUserPte, MiInsertPageInList(), MiLocateWsle(), MiReleasePageFileSpace(), MiReleaseWsle(), MiRemoveWsle(), MiSwapWslEntries(), MiUnlinkPageFromList(), MM_MAXIMUM_FLUSH_COUNT, MmPageLocationList, MmSessionSpace, MmSystemCacheWorkingSetList, MmSystemCacheWs, NT_SUCCESS, _MMPFN::OriginalPte, PAGE_ALIGN, _MMPFN::PteFrame, TRUE, _MMPTE::u, _MMWSLE::u1, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, _MM_SESSION_SPACE::Vm, _MMSUPPORT::VmWorkingSetList, _MM_SESSION_SPACE::Wsle, WSLE_NULL_INDEX, WSLE_NUMBER, and ZeroKernelPte.

Referenced by MiFreeInitializationCode(), MiFreePoolPages(), MiLoadImageSection(), MmFreeDriverInitialization(), MmFreeSpecialPool(), and MmUnloadSystemImage().

    04960                    :
    04961
    04962     This function deletes pagable system address space (paged pool
    04963     or driver pagable sections).
    04964
    04965 Arguments:
    04966
    04967     PointerPte - Supplies the start of the PTE range to delete.
    04968
    04969     NumberOfPtes - Supplies the number of PTEs in the range.
    04970
    04971     NewPteValue - Supplies the new value for the PTE.
    04972
    04973     SessionAllocation - Supplies TRUE if this is a range in session space.  If
    04974                         TRUE is specified, it is assumed that the caller has
    04975                         already attached to the relevant session.
    04976
    04977                         If FALSE is supplied, then it is assumed that the range
    04978                         is in the systemwide global space instead.
    04979
    04980     ResidentPages - If not NULL, the number of resident pages freed is
    04981                     returned here.
    04982
    04983 Return Value:
    04984
    04985     Returns the number of pages actually freed.
    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                 // Delete the page.
    05036                 //
    05037
    05038                 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&PteContents);
    05039
    05040                 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    05041
    05042                 //
    05043                 // Check to see if this is a pagable page in which
    05044                 // case it needs to be removed from the working set list.
    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                         // Check to see if this entry is locked in
    05067                         // the working set or locked in memory.
    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                             // This entry is locked.
    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                     // This case is valid only if the page being deleted
    05130                     // contained a lookaside free list entry that wasn't mapped
    05131                     // and multiple threads faulted on it and waited together.
    05132                     // Some of the faulted threads are still on the ready
    05133                     // list but haven't run yet, and so still have references
    05134                     // to this page that they picked up during the fault.
    05135                     // But this current thread has already allocated the
    05136                     // lookaside entry and is now freeing the entire page.
    05137                     //
    05138                     // BUT - if it is NOT the above case, we really should
    05139                     // trap here.  However, we don't have a good way to
    05140                     // distinguish between the two cases.  Note
    05141                     // that this complication was inserted when we went to
    05142                     // cmpxchg8 because using locks would prevent anyone from
    05143                     // accessing the lookaside freelist flinks like this.
    05144                     //
    05145                     // So, the ASSERT below comes out, but we leave the print
    05146                     // above in (with more data added) for the case where it's
    05147                     // not a lookaside contender with the reference count, but
    05148                     // is instead a truly bad reference that needs to be
    05149                     // debugged.  The system should crash shortly thereafter
    05150                     // and we'll at least have the above print to help us out.
    05151                     //
    05152                     // ASSERT (Pfn1->u3.e2.ReferenceCount == 1);
    05153                 }
    05154 #endif //DBG
    05155                 //
    05156                 // Check if this is a prototype PTE
    05157                 //
    05158                 if (Pfn1->u3.e1.PrototypePte == 1) {
    05159
    05160                     PMMPTE PointerPde;
    05161
    05162                     ASSERT (SessionAllocation == TRUE);
    05163
    05164                     //
    05165                     // Capture the state of the modified bit for this
    05166                     // PTE.
    05167                     //
    05168
    05169                     MI_CAPTURE_DIRTY_BIT_TO_PFN (PointerPte, Pfn1);
    05170
    05171                     //
    05172                     // Decrement the share and valid counts of the page table
    05173                     // page which maps this PTE.
    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                     // Decrement the share count for the physical page.
    05195                     //
    05196
    05197                     MiDecrementShareCount (PageFrameIndex);
    05198
    05199                     //
    05200                     // No need to worry about fork prototype PTEs
    05201                     // for kernel addresses.
    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                 // Flush the TB for this page.
    05217                 //
    05218
    05219                 if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) {
    05220
    05221                     //
    05222                     // We cannot rewrite the PTE without creating a race
    05223                     // condition.  So don't let the TB flush do it anymore.
    05224                     //
    05225                     // PteFlushList.FlushPte[PteFlushList.Count] = PointerPte;
    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                 // No need to worry about fork prototype PTEs
    05242                 // for kernel addresses.
    05243                 //
    05244
    05245                 ASSERT (PointerPte >= MiHighestUserPte);
    05246
    05247                 MI_WRITE_INVALID_PTE (PointerPte, NewContents);
    05248
    05249                 //
    05250                 // We currently commit for all prototype kernel mappings since
    05251                 // we could copy-on-write.
    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                 // Transition, release page.
    05267                 //
    05268
    05269                 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (&PteContents);
    05270
    05271                 //
    05272                 // Set the pointer to PTE as empty so the page
    05273                 // is deleted when the reference count goes to zero.
    05274                 //
    05275
    05276                 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    05277
    05278                 MI_SET_PFN_DELETED (Pfn1);
    05279
    05280                 MiDecrementShareCount (Pfn1->PteFrame);
    05281
    05282                 //
    05283                 // Check the reference count for the page, if the reference
    05284                 // count is zero, move the page to the free list, if the
    05285                 // reference count is not zero, ignore this page.  When the
    05286                 // reference count goes to zero, it will be placed on the
    05287                 // free list.
    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                 // Demand zero, release page file space.
    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     // There is the thorny case where one of the pages we just deleted could
    05330     // get faulted back in when we released the PFN lock above within the loop.
    05331     // The only time when this can happen is if a thread faulted during an
    05332     // interlocked pool allocation for an address that we've just deleted.
    05333     //
    05334     // If this thread sees the NewContents in the PTE, it will treat it as
    05335     // demand zero, and incorrectly allocate a page, PTE and WSL.  It will
    05336     // reference it once and realize it needs to reread the lookaside listhead
    05337     // and restart the operation.  But this page would live on in paged pool
    05338     // as modified (but unused) until the paged pool allocator chose to give
    05339     // out its virtual address again.
    05340     //
    05341     // The code below rewrites the PTEs which is really bad if another thread
    05342     // gets a zero page between our first setting of the PTEs above and our
    05343     // second setting below - because we'll reset the PTE to demand zero, but
    05344     // we'll still have a WSL entry that's valid, and we spiral from there.
    05345     //
    05346     // We really should remove the writing of the PTE below since we've already
    05347     // done it above.  But for now, we're leaving it in - it's harmless because
    05348     // we've chosen to fix this problem by checking for this case when we
    05349     // materialize demand zero pages.  Note that we have to fix this problem
    05350     // by checking in the demand zero path because a thread could be coming into
    05351     // that path any time before or after we flush the PTE list and any fixes
    05352     // here could only address the before case, not the after.
    05353     //
    05354
    05355     if (SessionAllocation == TRUE) {
    05356
    05357         //
    05358         // Session space has no ASN - flush the entire TB.
    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 }

NTSTATUS MiDereferenceImports | ( | IN PLOAD_IMPORTS | ImportList | ) |

Definition at line 3822 of file sysload.c.

References ASSERT, _LOAD_IMPORTS::Count, _LOAD_IMPORTS::Entry, ExFreePool(), LOADED_AT_BOOT, MiCallDllUnloadAndUnloadDll(), NO_IMPORTS_USED, PAGED_CODE, PLOAD_IMPORTS, PsLoadedModuleList, SINGLE_ENTRY, SINGLE_ENTRY_TO_POINTER, and TRUE.

Referenced by MiResolveImageReferences(), and MmUnloadSystemImage().

    03828                    :
    03829
    03830     Decrement the reference count on each DLL specified in the image import
    03831     list.  If any DLL's reference count reaches zero, then free the DLL.
    03832
    03833     No locks may be held on entry as MmUnloadSystemImage may be called.
    03834
    03835     The parameter list is freed here as well.
    03836
    03837 Arguments:
    03838
    03839     ImportList - Supplies the list of DLLs to dereference.
    03840
    03841 Return Value:
    03842
    03843     Status of the dereference operation.
    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             // Skip this one - it was loaded by ntldr.
    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             // Assert that the first 2 entries are never dereferenced as
    03886             // unloading the kernel or HAL would be fatal.
    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             // Unload this dependent DLL - we only do this to non-referenced
    03912             // non-boot-loaded drivers.  Stop the import list recursion prior
    03913             // to unloading - we know we're done at this point.
    03914             //
    03915             // Note we can continue on afterwards without restarting
    03916             // regardless of which locks get released and reacquired
    03917             // because this chain is private.
    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                 // This DLL was unloaded so recurse through its imports and
    03930                 // attempt to unload all of those too.
    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 }

VOID MiEnablePagingOfDriver | ( | IN PVOID | ImageHandle | ) |

Definition at line 2208 of file sysload.c.

References DbgPrint, FALSE, MiGetPteAddress, MiSetPagingOfDriver(), MmDisablePagingExecutive, NULL, PAGE_SIZE, ROUND_TO_PAGES, and RtlImageNtHeader().

Referenced by MiLoadSystemImage().

    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     // Don't page kernel mode code if customer does not want it paged.
    02224     //
    02225
    02226     if (MmDisablePagingExecutive) {
    02227         return;
    02228     }
    02229
    02230     //
    02231     // If the driver has pagable code, make it paged.
    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         // Mark as pagable any section which starts with the
    02263         // first 4 characters PAGE or .eda (for the .edata section).
    02264         //
    02265
    02266         if ((*(PULONG)FoundSection->Name == 'EGAP') ||
    02267            (*(PULONG)FoundSection->Name == 'ade.')) {
    02268
    02269             //
    02270             // This section is pagable, save away the start and end.
    02271             //
    02272
    02273             if (PointerPte == NULL) {
    02274
    02275                 //
    02276                 // Previous section was NOT pagable, get the start address.
    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             // This section is not pagable, if the previous section was
    02291             // pagable, enable it.
    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 }

PVOID MiFindExportedRoutineByName | ( | IN PLDR_DATA_TABLE_ENTRY | DataTableEntry,
|  | IN PANSI_STRING | AnsiImageRoutineName
| ) |

Definition at line 6928 of file sysload.c.

References ASSERT, NULL, PAGED_CODE, PUSHORT, RtlImageDirectoryEntryToData(), TRUE, and USHORT.

Referenced by MmGetSystemRoutineAddress().

    06935                    :
    06936
    06937     This function snaps a thunk using the specified Export Section data.
    06938     If the section data does not support the thunk, then the thunk is
    06939     partially snapped (Dll field is still non-null, but snap address is
    06940     set).
    06941
    06942 Arguments:
    06943
    06944     DllBase - Base of DLL being snapped to.
    06945
    06946     ImageBase - Base of image that contains the thunks to snap.
    06947
    06948     Thunk - On input, supplies the thunk to snap.  When successfully
    06949         snapped, the function field is set to point to the address in
    06950         the DLL, and the DLL field is set to NULL.
    06951
    06952     ExportDirectory - Supplies the Export Section data from a DLL.
    06953
    06954     SnapForwarder - determine if the snap is for a forwarder, and therefore
    06955        Address of Data is already setup.
    06956
    06957 Return Value:
    06958
    06959
    06960     STATUS_SUCCESS or STATUS_DRIVER_ENTRYPOINT_NOT_FOUND or
    06961         STATUS_DRIVER_ORDINAL_NOT_FOUND
    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     // Initialize the pointer to the array of RVA-based ansi export strings.
    06994     //
    06995
    06996     NameTableBase = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfNames);
    06997
    06998     //
    06999     // Initialize the pointer to the array of USHORT ordinal numbers.
    07000     //
    07001
    07002     NameOrdinalTableBase = (PUSHORT)(DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
    07003
    07004     //
    07005     // Lookup the desired name in the name table using a binary search.
    07006     //
    07007
    07008     Low = 0;
    07009     High = ExportDirectory->NumberOfNames - 1;
    07010
    07011     while (High >= Low) {
    07012
    07013         //
    07014         // Compute the next probe index and compare the import name
    07015         // with the export name entry.
    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     // If the high index is less than the low index, then a matching
    07036     // table entry was not found. Otherwise, get the ordinal number
    07037     // from the ordinal table.
    07038     //
    07039
    07040     if (High < Low) {
    07041         return NULL;
    07042     }
    07043
    07044     OrdinalNumber = NameOrdinalTableBase[Middle];
    07045
    07046     //
    07047     // If the OrdinalNumber is not within the Export Address Table,
    07048     // then this image does not implement the function.  Return not found.
    07049     //
    07050
    07051     if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
    07052         return NULL;
    07053     }
    07054
    07055     //
    07056     // Index into the array of RVA export addresses by ordinal number.
    07057     //
    07058
    07059     Addr = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
    07060
    07061     FunctionAddress = (PVOID)(DllBase + Addr[OrdinalNumber]);
    07062
    07063     //
    07064     // Forwarders are not used by the kernel and HAL to each other.
    07065     //
    07066
    07067     ASSERT ((FunctionAddress <= (PVOID)ExportDirectory) ||
    07068             (FunctionAddress >= (PVOID)((PCHAR)ExportDirectory + ExportSize)));
    07069
    07070     return FunctionAddress;
    07071 }
    }

LOGICAL MiInitializeLoadedModuleList | ( | IN PLOADER_PARAMETER_BLOCK | LoaderBlock | ) |

Definition at line 6591 of file sysload.c.

References ExAllocatePoolWithTag, ExFreePool(), ExInitializeResource, FALSE, KeInitializeSpinLock(), MiBuildImportsForBootDrivers(), MiLocateKernelSections(), NonPagedPool, NULL, PagedPool, PsLoadedModuleList, PsLoadedModuleResource, PsLoadedModuleSpinLock, PsNtosImageBase, and TRUE.

Referenced by MmInitSystem().

    06597                    :
    06598
    06599     This function initializes the loaded module list based on the LoaderBlock.
    06600
    06601 Arguments:
    06602
    06603     LoaderBlock - Supplies a pointer to the system loader block.
    06604
    06605 Return Value:
    06606
    06607     None.
    06608
    06609 Environment:
    06610
    06611     Kernel mode, Phase 0 Initialization.
    06612
    06613 --*/
    06614
    06615 {
    06616     PLIST_ENTRY NextEntry;
    06617     PLDR_DATA_TABLE_ENTRY DataTableEntry1;
    06618     PLDR_DATA_TABLE_ENTRY DataTableEntry2;
    06619
    06620     //
    06621     // Initialize the loaded module list executive resource and spin lock.
    06622     //
    06623
    06624     ExInitializeResource (&PsLoadedModuleResource);
    06625     KeInitializeSpinLock (&PsLoadedModuleSpinLock);
    06626
    06627     InitializeListHead (&PsLoadedModuleList);
    06628
    06629     //
    06630     // Scan the loaded module list and allocate and initialize a data table
    06631     // entry for each module. The data table entry is inserted in the loaded
    06632     // module list and the initialization order list in the order specified
    06633     // in the loader parameter block. The data table entry is inserted in the
    06634     // memory order list in memory order.
    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         // Allocate a data table entry.
    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         // Copy the data table entry.
    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         // Copy the strings.
    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         // Insert the data table entry in the load order list in the order
    06702         // they are specified.
    06703         //
    06704
    06705         InsertTailList(&PsLoadedModuleList,
    06706                        &DataTableEntry1->InLoadOrderLinks);
    06707
    06708         NextEntry = NextEntry->Flink;
    06709     }
    06710
    06711     MiBuildImportsForBootDrivers ();
    06712
    06713     return TRUE;
    06714 }

NTSTATUS MiLoadImageSection | ( | IN PSECTION | SectionPointer,
|  | OUT PVOID * | ImageBase,
|  | IN PUNICODE_STRING | ImageFileName,
|  | IN BOOLEAN | LoadInSessionSpace
| ) |

Definition at line 1474 of file sysload.c.

References ASSERT, BYTES_TO_PAGES, _MM_SESSION_SPACE::CommittedPages, DbgPrint, ExpDefaultErrorPortProcess, FALSE, KeAttachProcess(), KeDetachProcess(), LOCK_EXPANSION, LOCK_PFN, LOCK_SESSION_SPACE_WS, MI_GET_PAGE_COLOR_FROM_PTE, MI_GET_PAGE_FRAME_FROM_PTE, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MI_WRITE_VALID_PTE, MiChargeCommitmentCantExpand(), MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiDeleteSystemPagableVm(), MiEnsureAvailablePageOrWait(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHydra, MiInitializePfn(), MiMapCacheExceptionFilter(), MiReleaseSystemPtes(), MiRemoveAnyPage(), MiRemoveImageSessionWide(), MiReserveSystemPtes(), MiReturnCommitment(), MiSessionCommitImagePages(), MiSessionWideReserveImageAddress(), MiShareSessionImage(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_DBG_COMMIT_DRIVER_PAGES, MM_DBG_COMMIT_RETURN_SESSION_DRIVER_LOAD_FAILURE1, MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED1, MM_DBG_SESSION_COMMIT_IMAGELOAD_FAILED2, MM_DBG_SESSION_COMMIT_IMAGELOAD_NOACCESS, MM_EXECUTE, MM_KERNEL_DEMAND_ZERO_PTE, MM_NOACCESS, MM_PTE_EXECUTE, MM_TRACK_COMMIT, MmDriverCommit, MmMapViewOfSection(), MmResidentAvailablePages, MmSessionSpace, MmUnmapViewOfSection(), NT_SUCCESS, NtGlobalFlag, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGE_SIZE, PAGED_CODE, _EPROCESS::Pcb, _MM_SESSION_SPACE::ProcessList, PsGetCurrentProcess, _MMPFN::PteFrame, SESSION_GLOBAL, Status, SystemPteSpace, TRUE, _MM_SESSION_SPACE::u, _MMPTE::u, UNLOCK_EXPANSION, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, ValidKernelPte, ZERO_LARGE, ZeroKernelPte, and ZeroPte.

Referenced by MiLoadSystemImage().

    01483                    :
    01484
    01485     This routine loads the specified image into the kernel part of the
    01486     address space.
    01487
    01488 Arguments:
    01489
    01490     SectionPointer - Supplies the section object for the image.
    01491
    01492     ImageBaseAddress - Returns the address that the image header is at.
    01493
    01494     ImageFileName - Supplies the full path name (including the image name)
    01495                     of the image to load.
    01496
    01497     LoadInSessionSpace - Supplies whether to load this image in session space.
    01498                          Each session gets a different copy of this driver with
    01499                          pages shared as much as possible via copy on write.
    01500
    01501 Return Value:
    01502
    01503     Status of the operation.
    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     // Calculate the number of pages required to load this image.
    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         // Allocate a unique systemwide session space virtual address for
    01567         // the driver.
    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         // This is a request to load an existing driver.  This can
    01587         // occur with printer drivers for example.
    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             // We were able to load the image at its based address, so
    01617             // map its image segments as backed directly by the file image.
    01618             // All pristine pages of the image will be shared across all
    01619             // sessions, with each page treated as copy-on-write on first write.
    01620             //
    01621             // NOTE: This makes the file image "busy", a different behavior
    01622             // as normal kernel drivers are backed by the paging file only.
    01623             //
    01624
    01625 #if DBG
    01626             if (SectionPointer->Segment->SystemImageBase != 0) {
    01627                 ASSERT (BaseAddress == SectionPointer->Segment->SystemImageBase);
    01628             }
    01629 #endif
    01630
    01631             //
    01632             // Map the image into session space.
    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             // Indicate that this section has been loaded into the system.
    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         // The image could not be loaded at its based address.  It must be
    01676         // copied to its new address using private page file backed pages.
    01677         // Our caller will relocate the internal references and then bind the
    01678         // image.  Allocate the pages and page tables for the image now.
    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         // See if ample pages exist to load this image.
    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         // Reserve the necessary system address space.
    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     // Map a view into the user portion of the address space.
    01737     //
    01738
    01739     Process = PsGetCurrentProcess();
    01740
    01741     //
    01742     // Since callees are not always in the context of the system process,
    01743     // attach here when necessary to guarantee the driver load occurs in a
    01744     // known safe address space to prevent security holes.
    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                 // Return the commitment we took out on the pagefile when
    01799                 // the page was allocated.  This is needed for collided images
    01800                 // since all the pages get committed regardless of writability.
    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             // Return the commitment we took out on the pagefile when
    01880             // the page was allocated.  This is needed for collided images
    01881             // since all the pages get committed regardless of writability.
    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     // Allocate a physical page(s) and copy the image data.
    01901     // Note Hydra has already allocated the physical pages and just does
    01902     // data copying here.
    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                 // EM needs execute permission.
    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                 // An exception occurred, unmap the view and
    01955                 // return the error to the caller.
    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                     // Return the commitment we took out on the pagefile when
    01981                     // the page was allocated.  This is needed for collided
    01982                     // images since all the pages get committed regardless
    01983                     // of writability.
    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                             // Delete the page.
    01997                             //
    01998
    01999                             PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (ProtoPte);
    02000
    02001                             //
    02002                             // Set the pointer to PTE as empty so the page
    02003                             // is deleted when the reference count goes to zero.
    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             // The PTE is no access - if this driver is being loaded in session
    02047             // space we already preloaded the page so free it now.  The
    02048             // commitment is returned when the whole image is unmapped.
    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     // Indicate that this section has been loaded into the system.
    02087     //
    02088
    02089     SectionPointer->Segment->SystemImageBase = *ImageBaseAddress;
    02090
    02091     //
    02092     // Charge commitment for the number of pages that were used by
    02093     // the driver.
    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 }

NTSTATUS MiLoadSystemImage | ( | IN PUNICODE_STRING | ImageFileName,
|  | IN PUNICODE_STRING NamePrefix | OPTIONAL,
|  | IN PUNICODE_STRING LoadedBaseName | OPTIONAL,
|  | IN BOOLEAN | LoadInSessionSpace,
|  | OUT PVOID * | ImageHandle,
|  | OUT PVOID * | ImageBaseAddress,
|  | IN BOOLEAN | LockDownPages
| ) |

Definition at line 443 of file sysload.c.

References ASSERT, BaseName, CacheImageSymbols(), CHAR, DbgPrint, ExAcquireResourceExclusive, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExPageLockHandle, ExReleaseResource, FALSE, IMAGE_ADDRESSING_MODE_32BIT, _IMAGE_INFO::ImageAddressingMode, _IMAGE_INFO::ImageBase, _IMAGE_INFO::ImageSectionNumber, _IMAGE_INFO::ImageSelector, _IMAGE_INFO::ImageSize, KeAttachProcess(), KeDetachProcess(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KeReleaseMutant(), KernelMode, KeSweepIcache(), KeWaitForSingleObject(), L, LdrRelocateImage(), MI_IS_SESSION_ADDRESS, MiApplyDriverVerifier(), MiCheckPageFilePath(), MiEnablePagingOfDriver(), MiFirstDriverLoadEver, MiGetPpeAddress, MiHydra, MiLoadImageSection(), MiResolveImageReferences(), MiSetImageProtect(), MiWriteProtectSystemImage(), MM_EXECUTE_READWRITE, MmCheckSystemImage(), MmIsAddressValid(), MmLockPagableSectionByHandle(), MmMapViewInSystemSpace(), MmPageEntireDriver(), MmSectionObjectType, MmSession, MmSessionSpace, MmSystemLoadLock, MmUnloadSystemImage(), MmUnlockPagableImageSection(), NO_IMPORTS_USED, NonPagedPool, NT_SUCCESS, NtGlobalFlag, NTSTATUS(), NULL, ObDereferenceObject, ObjectAttributes, ObReferenceObjectByHandle(), PAGE_SHIFT, PAGED_CODE, PagedPool, _EPROCESS::Pcb, PERFINFO_IMAGE_LOAD, PLOAD_IMPORTS, _IMAGE_INFO::Properties, PsCallImageNotifyRoutines(), PSECTION, PsGetCurrentProcess, PsImageNotifyEnabled, PsInitialSystemProcess, PsLoadedModuleList, PsLoadedModuleResource, PsLoadedModuleSpinLock, RtlAnsiStringToUnicodeString(), RtlAppendUnicodeStringToString(), RtlEqualUnicodeString(), RtlFreeUnicodeString(), RtlImageNtHeader(), RtlInitAnsiString(), RtlInitString(), RtlInitUnicodeString(), _MM_SESSION_SPACE::Session, _MM_SESSION_SPACE::SessionId, sprintf(), Status, _IMAGE_INFO::SystemModeImage, _MMSESSION::SystemSpaceViewStart, TRUE, _MMPTE::u, USHORT, WrVirtualMemory, X64K, and ZwOpenFile().

Referenced by MmLoadAndLockSystemImage(), and MmLoadSystemImage().

    00455                    :
    00456
    00457     This routine reads the image pages from the specified section into
    00458     the system and returns the address of the DLL's header.
    00459
    00460     At successful completion, the Section is referenced so it remains
    00461     until the system image is unloaded.
    00462
    00463 Arguments:
    00464
    00465     ImageFileName - Supplies the full path name (including the image name)
    00466                     of the image to load.
    00467
    00468     NamePrefix - If present, supplies the prefix to use with the image name on
    00469                  load operations.  This is used to load the same image multiple
    00470                  times, by using different prefixes.
    00471
    00472     LoadedBaseName - If present, supplies the base name to use on the
    00473                      loaded image instead of the base name found on the
    00474                      image name.
    00475
    00476     LoadInSessionSpace - Supplies whether to load this image in session space.
    00477                          Each session gets a different copy of this driver with
    00478                          pages shared as much as possible via copy on write.
    00479
    00480     ImageHandle - Returns an opaque pointer to the referenced section object
    00481                   of the image that was loaded.
    00482
    00483     ImageBaseAddress - Returns the image base within the system.
    00484
    00485     LockDownPages - Supplies TRUE if the image pages should be made nonpagable.
    00486
    00487 Return Value:
    00488
    00489     Status of the load operation.
    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     // Get name roots
    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     // If there's a name prefix, add it to the PrefixedImageName.
    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         // Alter the basename to match
    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     // If there's a loaded base name, use it instead of the base name.
    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     // Arbitrary process context so prevent suspend APCs now.
    00637     //
    00638
    00639     KeEnterCriticalRegion();
    00640
    00641     KeWaitForSingleObject (&MmSystemLoadLock,
    00642                            WrVirtualMemory,
    00643                            KernelMode,
    00644                            FALSE,
    00645                            (PLARGE_INTEGER)NULL);
    00646
    00647     //
    00648     // Check to see if this name already exists in the loader database.
    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                     // The caller is trying to load a driver in session space
    00668                     // that has already been loaded in system space.  This is
    00669                     // not allowed.
    00670                     //
    00671
    00672                     Status = STATUS_CONFLICTING_ADDRESSES;
    00673                     goto return2;
    00674                 }
    00675
    00676                 AlreadyOpen = TRUE;
    00677
    00678                 //
    00679                 // The LoadCount should generally not be 0 here, but it is
    00680                 // possible in the case where an attempt has been made to
    00681                 // unload a DLL on last dereference, but the DLL refused to
    00682                 // unload.
    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                     // The caller is trying to load a driver in systemwide space
    00694                     // that has already been loaded in session space.  This is
    00695                     // not allowed.
    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         // Attempt to open the driver image itself.  If this fails, then the
    00720         // driver image cannot be located, so nothing else matters.
    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             // Don't raise hard error status for file not found.
    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         // Now attempt to create an image section for the file.  If this fails,
    00760         // then the driver file is not an image.  Session space drivers are
    00761         // shared text with copy on write data, so don't allow writes here.
    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         // Now reference the section handle.
    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                 // The driver was linked with subsection alignment such that
    00807                 // it is mapped with one subsection.  Since the CreateSection
    00808                 // above guarantees that the driver image is indeed a
    00809                 // satisfactory executable, map it directly now to reuse the
    00810                 // cache from the MmCheckSystemImage call above.
    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                         // The number of PTEs won't match if the image is
    00837                         // stripped and the debug directory crosses the last
    00838                         // sector boundary of the file.  We could still use the
    00839                         // new section, but these cases are under 2% of all the
    00840                         // drivers loaded so don't bother.
    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             // This is needed because win32k calls are made from the system
    00878             // process on non-Hydra systems.  On Hydra systems, these calls
    00879             // are always made from the relevant session's csrss process.
    00880             // If these were the same, this PPE duplication could be removed.
    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     // Load the driver from the filesystem and pick a virtual address for it.
    00899     // For Hydra, this means also allocating session virtual space, and
    00900     // after mapping a view of the image, either copying or sharing the
    00901     // driver's code and data in the session virtual space.
    00902     //
    00903     // If it is a share map because the image was loaded at its based address,
    00904     // the disk image will remain busy.
    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         // This is a driver that was relocated that is being loaded into
    00920         // the same session space twice.  Don't increment the overall load
    00921         // count - just the image count in the session which has already been
    00922         // done.
    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         // Check with all of the drivers along the path to win32k.sys to
    00945         // ensure that they are willing to follow the rules required
    00946         // of them and to give them a chance to lock down code and data
    00947         // that needs to be locked.  If any of the drivers along the path
    00948         // refuses to participate, fail the win32k.sys load.
    00949         //
    00950
    00951         //
    00952         // It is assumed that all drivers live on the same physical drive, so
    00953         // when the very first driver is loaded, this check can be made.
    00954         // This eliminates the need to check for things like relocated win32ks,
    00955         // Terminal Server systems, etc.
    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             // BUGBUG: Failing the insertion of win32k.sys' device in the
    00967             // pagefile path is commented out until the storage drivers have
    00968             // been modified to correctly handle this request.  Add code
    00969             // here to release relevant resources for the error path.
    00970             //
    00971         }
    00972
    00973         MiFirstDriverLoadEver = FALSE;
    00974     }
    00975
    00976     //
    00977     // Normal drivers are dereferenced here and their images can then be
    00978     // overwritten.  This is ok because we've already read the whole thing
    00979     // into memory and from here until reboot (or unload), we back them
    00980     // with the pagefile.
    00981     //
    00982     // win32k.sys and session space drivers are the exception - these images
    00983     // are inpaged from the filesystem and we need to keep our reference to
    00984     // the file so that it doesn't get overwritten.
    00985     //
    00986
    00987     if (LoadInSessionSpace == FALSE) {
    00988         ObDereferenceObject (SectionPointer);
    00989         SectionPointer = (PVOID)-1;
    00990     }
    00991
    00992     //
    00993     // The module LoadCount will be 1 here if the module was just loaded.
    00994     // The LoadCount will be >1 if it was attached to by a session (as opposed
    00995     // to just loaded).
    00996     //
    00997
    00998     if (!NT_SUCCESS(Status)) {
    00999         if (AlreadyOpen == TRUE) {
    01000
    01001             //
    01002             // We're failing and we were just attaching to an already loaded
    01003             // driver.  We don't want to go through the forced unload path
    01004             // because we've already deleted the address space.  Simply
    01005             // decrement our reference and null the DataTableEntry
    01006             // so we don't go through the forced unload path.
    01007             //
    01008
    01009             ASSERT (DataTableEntry != NULL);
    01010             DataTableEntry->LoadCount -= 1;
    01011             DataTableEntry = NULL;
    01012         }
    01013         goto return1;
    01014     }
    01015
    01016     //
    01017     // Error recovery from this point out for sessions works as follows:
    01018     //
    01019     // For sessions, we may or may not have a DataTableEntry at this point.
    01020     // If we do, it's because we're attaching to a driver that has already
    01021     // been loaded - and the DataTableEntry->LoadCount has been bumped - so
    01022     // the error recovery from here on out is to just call
    01023     // MmUnloadSystemImage with the DataTableEntry.
    01024     //
    01025     // If this is the first load of a given driver into a session space, we
    01026     // have no DataTableEntry at this point.  The view has already been mapped
    01027     // and committed and the group/session addresses reserved for this DLL.
    01028     // The error recovery path handles all this because
    01029     // MmUnloadSystemImage will zero the relevant fields in the
    01030     // LDR_DATA_TABLE_ENTRY so that MmUnloadSystemImage will work properly.
    01031     //
    01032
    01033     IssueUnloadOnFailure = TRUE;
    01034
    01035     if (LoadInSessionSpace == FALSE || *ImageBaseAddress != SectionPointer->Segment->BasedAddress) {
    01036
    01037 #if DBG
    01038
    01039         //
    01040         // Warn users about session images that cannot be shared
    01041         // because they were linked at a bad address.
    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         // Apply the fixups to the section and resolve its image references.
    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             // Unload the system image and dereference the section.
    01077             //
    01078
    01079             goto return1;
    01080         }
    01081     }
    01082
    01083 BindImage:
    01084
    01085     try {
    01086         MissingProcedureName = NameBuffer;
    01087
    01088         //
    01089         // Resolving the image references results in other DLLs being
    01090         // loaded if they are referenced by the module that was just loaded.
    01091         // An example is when an OEM printer or FAX driver links with
    01092         // other general libraries.  This is not a problem for session space
    01093         // because the general libraries do not have the global data issues
    01094         // that win32k.sys and the video drivers do.  So we just call the
    01095         // standard kernel reference resolver and any referenced libraries
    01096         // get loaded into system global space.  Code in the routine
    01097         // restricts which libraries can be referenced by a driver.
    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                 // If not an ordinal, print string
    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         // Since there was no loaded module list entry for this driver, create
    01147         // one now.
    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         // Allocate a data table entry for structured exception handling.
    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         // Initialize the address of the DLL image file header and the entry
    01197         // point address.
    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         // Store the DLL name.
    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             // Pool could not be allocated, just set the length to 0.
    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         // Initialize the flags, load count, and insert the data table entry
    01244         // in the loaded module list.
    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         // Acquire the loaded module list resource and insert this entry
    01276         // into the list.
    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             //  TEMP TEMP TEMP rip out when debugger converted
    01295             //
    01296
    01297             ANSI_STRING AnsiName;
    01298             UNICODE_STRING UnicodeName;
    01299
    01300             //
    01301             //  \SystemRoot is 11 characters in length
    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     // Flush the instruction cache on all systems in the configuration.
    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         // Only way we should fail after we get a valid DataTableEntry is if
    01345         // we're Hydra loading a 2nd instance of a driver.
    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             // This is needed for failed win32k.sys loads or any Hydra session's
    01357             // load of the first instance of a driver.
    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                 // If DataTableEntry is NULL, then we are unloading before one
    01380                 // got created.  Once a LDR_DATA_TABLE_ENTRY is created, the
    01381                 // load cannot fail, so if exists here, at least one other
    01382                 // session contains this image as well.
    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         // Hard error time.  A driver could not be loaded.
    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                 // If not an ordinal, pass as a Unicode string
    01430                 //
    01431
    01432                 RtlInitAnsiString( &AnsiString, MissingProcedureName );
    01433                 RtlAnsiStringToUnicodeString( &ProcedureName, &AnsiString, TRUE );
    01434                 ErrorParameters[ 1 ] = (ULONG_PTR)&ProcedureName;
    01435                 UnicodeStringParameterMask |= 0x2;
    01436             } else {
    01437                 //
    01438                 // Just pass ordinal values as is.
    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 }

PVOID MiLocateExportName | ( | IN PVOID | DllBase,
|  | IN PCHAR | FunctionName
| ) |

Definition at line 3712 of file sysload.c.

References NULL, PAGED_CODE, PUSHORT, RtlImageDirectoryEntryToData(), TRUE, and USHORT.

Referenced by MiCallDllUnloadAndUnloadDll(), MiResolveImageReferences(), and MmCallDllInitialize().

    03719                    :
    03720
    03721     This function is invoked to locate a function name in an export directory.
    03722
    03723 Arguments:
    03724
    03725     DllBase - Supplies the image base.
    03726
    03727     FunctionName - Supplies the the name to be located.
    03728
    03729 Return Value:
    03730
    03731     The address of the located function or NULL.
    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     // Locate the DLL's export directory.
    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         // Look in the export name table for the specified function name.
    03767         //
    03768
    03769         Low = 0;
    03770         High = ExportDirectory->NumberOfNames - 1;
    03771
    03772         while (High >= Low && (LONG)High >= 0) {
    03773
    03774             //
    03775             // Compute the next probe index and compare the export name entry
    03776             // with the specified function name.
    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         // If the high index is less than the low index, then a matching table
    03794         // entry was not found.  Otherwise, get the ordinal number from the
    03795         // ordinal table and location the function address.
    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             // If the function address is w/in range of the export directory,
    03806             // then the function is forwarded, which is not allowed, so ignore
    03807             // it.
    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 }

VOID MiLocateKernelSections | ( | IN PLDR_DATA_TABLE_ENTRY | DataTableEntry | ) |

Definition at line 6395 of file sysload.c.

References ExPoolCodeEnd, ExPoolCodeStart, MiGetPteAddress, MmPoolCodeEnd, MmPoolCodeStart, MmPteCodeEnd, MmPteCodeStart, NULL, PAGE_SIZE, PUSHORT, ROUND_TO_PAGES, RtlImageNtHeader(), and SECTION_BASE_ADDRESS.

Referenced by MiInitializeLoadedModuleList().

    06401                    :
    06402
    06403     This function locates the resource section in the kernel so it can be
    06404     made readwrite if we bugcheck later, as the bugcheck code will write
    06405     into it.
    06406
    06407 Arguments:
    06408
    06409     DataTableEntry - Supplies the kernel's data table entry.
    06410
    06411 Return Value:
    06412
    06413     None.
    06414
    06415 Environment:
    06416
    06417     Kernel mode, Phase 0 Initialization.
    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     // From the image header, locate the section named '.rsrc'.
    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 }

PVOID MiLookupImageSectionByName | ( | IN PVOID | Base,
|  | IN BOOLEAN | MappedAsImage,
|  | IN PCHAR | SectionName,
|  | OUT PULONG | SectionSize
| ) |

LONG MiMapCacheExceptionFilter | ( | OUT PNTSTATUS | Status,
|  | IN PEXCEPTION_POINTERS | ExceptionPointer
| ) |

VOID MiReloadBootLoadedDrivers | ( | IN PLOADER_PARAMETER_BLOCK | LoaderBlock | ) |

Definition at line 5956 of file sysload.c.

References ASSERT, DbgPrint, FALSE, InitializationPhase, LdrDoubleRelocateImage(), LdrRelocateImage(), LOCK_PFN, MI_GET_PAGE_COLOR_FROM_PTE, MI_GET_PAGE_FRAME_FROM_PTE, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_SET_ACCESSED_IN_PTE, MI_SET_PFN_DELETED, MI_SET_PTE_DIRTY, MI_WRITE_VALID_PTE, MiDecrementShareAndValidCount, MiDecrementShareCountOnly, MiEnsureAvailablePageOrWait(), MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInitializePfn(), MiNoLowMemory, MiReleaseSystemPtes(), MiRemoveAnyPage(), MiRemoveLowPages(), MiReserveSystemPtes(), MiUpdateThunks(), MM_EXECUTE_READWRITE, MmMakeLowMemory, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SHIFT, PAGE_SIZE, _MMPFN::PteAddress, _MMPFN::PteFrame, ROUND_TO_PAGES, RtlImageNtHeader(), Status, SystemPteSpace, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, and ZeroPte.

Referenced by MmInitSystem().

    05962                    :
    05963
    05964     The kernel, HAL and boot drivers are relocated by the loader.
    05965     All the boot drivers are then relocated again here.
    05966
    05967     This function relocates osloader-loaded images into system PTEs.  This
    05968     gives these images the benefits that all other drivers already enjoy,
    05969     including :
    05970
    05971     1. Paging of the drivers (this is more than 500K today).
    05972     2. Write-protection of their text sections.
    05973     3. Automatic unload of drivers on last dereference.
    05974
    05975     Note care must be taken when processing HIGHADJ relocations more than once.
    05976
    05977 Arguments:
    05978
    05979     LoaderBlock - Supplies a pointer to the system loader block.
    05980
    05981 Return Value:
    05982
    05983     None.
    05984
    05985 Environment:
    05986
    05987     Kernel mode, Phase 0 Initialization.
    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     // Non-x86 platforms have map registers so no memory shuffling is needed.
    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         // Skip the kernel and the HAL.  Note their relocation sections will
    06034         // be automatically reclaimed.
    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         // Ensure that the relocation section exists and that the loader
    06048         // hasn't freed it already.
    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             // The relocation section has already been freed, the user must
    06071             // be using an old loader that didn't save the relocations.
    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             // Mark the page as modified so boot drivers that call
    06093             // MmPageEntireDriver don't lose their unmodified data !
    06094             //
    06095
    06096             Pfn1->u3.e1.Modified = 1;
    06097             PointerPte += 1;
    06098         }
    06099
    06100         UNLOCK_PFN (OldIrql);
    06101
    06102         //
    06103         // Extra PTEs are allocated here to map the relocation section at the
    06104         // new address so the image can be relocated.
    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         // This assert is important because the assumption is made that PTEs
    06134         // (not superpages) are mapping these drivers.
    06135         //
    06136
    06137         ASSERT (InitializationPhase == 0);
    06138
    06139         //
    06140         // If the system is configured to make low memory available for ISA
    06141         // type drivers, then copy the boot loaded drivers now.  Otherwise
    06142         // only PTE adjustment is done.  Presumably some day when ISA goes
    06143         // away this code can be removed.
    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                     // If the frames cannot be replaced with high pages
    06169                     // then stop copying.
    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                 // Initialize the WsIndex just like the original page had it.
    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         // Image is now mapped at the new address.  Relocate it (again).
    06220         //
    06221
    06222 #if defined(_ALPHA_)
    06223
    06224         //
    06225         // HIGHADJ relocations need special re-processing.  This needs to be
    06226         // done before resetting ImageBase.
    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         // Update the IATs for all other loaded modules that reference this one.
    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         // Update the loaded module list entry.
    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         // Update the PFNs of the image to support trimming.
    06302         // Note that the loader addresses are freed now so no references
    06303         // to it are permitted after this point.
    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                 // Decrement the share count on the original page table
    06322                 // page so it can be freed.
    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                 // Decrement the share count on the original page table
    06341                 // page so it can be freed.
    06342                 //
    06343
    06344                 MiDecrementShareAndValidCount (Pfn1->PteFrame);
    06345                 *Pfn1->PteAddress = ZeroPte;
    06346 #endif
    06347
    06348                 //
    06349                 // Chain the PFN entry to its new page table.
    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                 // Increment the share count for the page table page that now
    06360                 // contains the PTE that was copied.
    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         // The physical pages mapping the relocation section are freed
    06374         // later with the rest of the initialization code spanned by the
    06375         // DataTableEntry->SizeOfImage.
    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 }

VOID MiRememberUnloadedDriver | ( | IN PUNICODE_STRING | DriverName,
|  | IN PVOID | Address,
|  | IN ULONG | Length
| ) |

Definition at line 2740 of file sysload.c.

References _UNLOADED_DRIVERS::CurrentTime, _UNLOADED_DRIVERS::EndAddress, ExAllocatePoolWithTag, KeQuerySystemTime(), MI_UNLOADED_DRIVERS, MiLastUnloadedDriver, MiTotalUnloads, MiUnloadedDrivers, MiUnloadsSkipped, _UNLOADED_DRIVERS::Name, NonPagedPool, NULL, RtlFreeUnicodeString(), and _UNLOADED_DRIVERS::StartAddress.

Referenced by MmUnloadSystemImage().

    02748                    :
    02749
    02750     This routine saves information about unloaded drivers so that ones that
    02751     forget to delete lookaside lists or queues can be caught.
    02752
    02753 Arguments:
    02754
    02755     DriverName - Supplies a Unicode string containing the driver's name.
    02756
    02757     Address - Supplies the address the driver was loaded at.
    02758
    02759     Length - Supplies the number of bytes the driver load spanned.
    02760
    02761 Return Value:
    02762
    02763     None.
    02764
    02765 --*/
    02766
    02767 {
    02768     PUNLOADED_DRIVERS Entry;
    02769     ULONG NumberOfBytes;
    02770
    02771     if (DriverName->Length == 0) {
    02772
    02773         //
    02774         // This is an aborted load and the driver name hasn't been filled
    02775         // in yet.  No need to save it.
    02776         //
    02777
    02778         return;
    02779     }
    02780
    02781     //
    02782     // Serialization is provided by the caller, so just update the list now.
    02783     // Note the allocations are nonpaged so they can be searched at bugcheck
    02784     // time.
    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     // Free the old entry as we recycle into the new.
    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 }

VOID MiRemoveLowPages | ( | VOID |  | ) |

| Referenced by MiInitMachineDependent(), and MiReloadBootLoadedDrivers().

NTSTATUS MiResolveImageReferences | ( | PVOID | ImageBase,
|  | IN PUNICODE_STRING | ImageFileDirectory,
|  | IN PUNICODE_STRING NamePrefix | OPTIONAL,
|  | IN BOOLEAN | LoadInSessionSpace,
|  | OUT PCHAR * | MissingProcedureName,
|  | OUT PWSTR * | MissingDriverName,
|  | OUT PLOAD_IMPORTS * | LoadedImports
| ) |

Definition at line 3953 of file sysload.c.

References ASSERT, CmRegistryMachineSystemCurrentControlSetServices, _LOAD_IMPORTS::Count, Count, _LOAD_IMPORTS::Entry, ExAllocatePoolWithTag, ExFreePool(), FALSE, L, MiDereferenceImports(), MiLocateExportName(), MiSnapThunk(), MmLoadSystemImage(), MmUnloadSystemImage(), NO_IMPORTS_USED, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, PLOAD_IMPORTS, PMM_DLL_INITIALIZE, POINTER_TO_SINGLE_ENTRY, PsLoadedModuleList, RtlAnsiStringToUnicodeString(), RtlAppendStringToString(), RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlEqualUnicodeString(), RtlFreeUnicodeString(), RtlImageDirectoryEntryToData(), RtlInitAnsiString(), TRUE, and USHORT.

Referenced by MiLoadSystemImage().

    03965                    :
    03966
    03967     This routine resolves the references from the newly loaded driver
    03968     to the kernel, HAL and other drivers.
    03969
    03970 Arguments:
    03971
    03972     ImageBase - Supplies the address of which the image header resides.
    03973
    03974     ImageFileDirectory - Supplies the directory to load referenced DLLs.
    03975
    03976 Return Value:
    03977
    03978     Status of the image reference resolution.
    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     // Count the number of imports so we can allocate enough room to
    04031     // store them all chained off this module's LDR_DATA_TABLE_ENTRY.
    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         // Zero it so we can recover gracefully if we fail in the middle.
    04048         // If the allocation failed, just don't build the import list.
    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         // A driver can link with win32k.sys if and only if it is a GDI
    04067         // driver.
    04068         // Also display drivers can only link to win32k.sys (and lego ...).
    04069         //
    04070         // So if we get a driver that links to win32k.sys and has more
    04071         // than one set of imports, we will fail to load it.
    04072         //
    04073
    04074         LinkWin32k = LinkWin32k |
    04075              (!_strnicmp(ImportName, "win32k", sizeof("win32k") - 1));
    04076
    04077         //
    04078         // We don't want to count coverage, win32k and irt (lego) since
    04079         // display drivers CAN link against these.
    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                 // These imports don't get refcounted because we don't
    04118                 // ever want to unload them.
    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                 // Only bump the LoadCount if this thread did not initiate
    04184                 // the load below.  If this thread initiated the load, then
    04185                 // the LoadCount has already been bumped as part of the
    04186                 // load - we only want to increment it here if we are
    04187                 // "attaching" to a previously loaded DLL.
    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             // The DLL name was not located, attempt to load this dll.
    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             // Call any needed DLL initialization now.
    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                     // This DLL has an initialization routine.  Manufacture
    04250                     // the service name string and invoke the function with
    04251                     // it.
    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                         // Now invoke the DLL's initialization routine.
    04278                         //
    04279
    04280                         st = Func (&RegistryPath);
    04281                         ExFreePool (RegistryPath.Buffer);
    04282
    04283                         if (!NT_SUCCESS(st)) {
    04284
    04285                             //
    04286                             // Unload the DLL now as its initialization
    04287                             // routine failed.
    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         // Walk through the IAT and snap all the thunks.
    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     // All the imports are successfully loaded so establish and compact
    04399     // the import unload list.
    04400     //
    04401
    04402     if (ImportList) {
    04403
    04404         //
    04405         // Blank entries occur for things like the kernel, HAL & win32k.sys
    04406         // that we never want to unload.  Especially for things like
    04407         // win32k.sys where the reference count can really hit 0.
    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 }

VOID MiSetImageProtect | ( | IN PSEGMENT | Segment,
|  | IN ULONG | Protection
| ) |

Definition at line 5376 of file sysload.c.

References ASSERT, MiSetProtectionOnTransitionPte(), MM_PROTECTION_WRITE_MASK, MmLockPagedPool(), MMPTE, MmUnlockPagedPool(), _MMPTE::u, _SUBSECTION::u, and ZeroPte.

Referenced by MiLoadSystemImage(), and MiShareSessionImage().

    05383                    :
    05384
    05385     This function sets the protection of all prototype PTEs to the specified
    05386     protection.
    05387
    05388 Arguments:
    05389
    05390      Segment - Supplies a pointer to the segment to protect.
    05391
    05392      Protection - Supplies the protection value to set.
    05393
    05394 Return Value:
    05395
    05396      None.
    05397
    05398 --*/
    05399
    05400 {
    05401     PMMPTE PointerPte;
    05402     PMMPTE LastPte;
    05403     MMPTE PteContents;
    05404     PSUBSECTION SubSection;
    05405
    05406     //
    05407     // Set the subsection protections.
    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 }

VOID MiSetPagingOfDriver | ( | IN PMMPTE | PointerPte,
|  | IN PMMPTE | LastPte,
|  | IN BOOLEAN | SessionSpace
| ) |

Definition at line 2309 of file sysload.c.

References ASSERT, ExPageLockHandle, FALSE, KeFlushSingleTb(), LOCK_PFN, LOCK_SESSION_SPACE_WS, LOCK_SYSTEM_WS, MI_CAPTURE_DIRTY_BIT_TO_PFN, MI_FLUSH_ENTIRE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_MAKE_VALID_PTE_TRANSITION, MI_PFN_ELEMENT, MiDecrementShareCount(), MiGetVirtualAddressMappedByPte, MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_DBG_SESSION_DRIVER_PAGES_UNLOCKED, MM_EXECUTE, MM_KERNEL_DEMAND_ZERO_PTE, MmIsAddressValid(), MmLockPagableSectionByHandle(), MmResidentAvailablePages, MmSessionSpace, MmTotalSystemDriverPages, MmUnlockPagableImageSection(), _MM_SESSION_SPACE::NonPagablePages, _MMPFN::OriginalPte, PAGE_SIZE, PAGED_CODE, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, and UNLOCK_SYSTEM_WS.

Referenced by MiEnablePagingOfDriver(), and MmPageEntireDriver().

    02317                    :
    02318
    02319     This routine marks the specified range of PTEs as pagable.
    02320
    02321 Arguments:
    02322
    02323     PointerPte - Supplies the starting PTE.
    02324
    02325     LastPte - Supplies the ending PTE.
    02326
    02327 Return Value:
    02328
    02329     None.
    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         // No need to lock physical addresses.
    02352         //
    02353
    02354         return;
    02355     }
    02356
    02357     PageCount = 0;
    02358
    02359     //
    02360     // Lock this routine into memory.
    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         // Check to make sure this PTE has not already been
    02380         // made pagable (or deleted).  It is pagable if it
    02381         // is not valid, or if the PFN database wsindex element
    02382         // is non zero.
    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                 // Original PTE may need to be set for drivers loaded
    02394                 // via ntldr.
    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                 // Flush the translation buffer and decrement the number of valid
    02419                 // PTEs within the containing page table page.  Note that for a
    02420                 // private page, the page table page is still needed because the
    02421                 // page is in transition.
    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                 // This page is already pagable and has a WSLE entry.
    02433                 // Ignore it here and let the trimmer take it if memory
    02434                 // comes under pressure.
    02435                 //
    02436             }
    02437         }
    02438         Base = (PVOID)((PCHAR)Base + PAGE_SIZE);
    02439         PointerPte += 1;
    02440     }
    02441
    02442     if (SessionSpace == TRUE) {
    02443
    02444         //
    02445         // Session space has no ASN - flush the entire TB.
    02446         //
    02447
    02448         MI_FLUSH_ENTIRE_SESSION_TB (TRUE, TRUE);
    02449     }
    02450
    02451     UNLOCK_PFN (OldIrql);
    02452
    02453     if (SessionSpace == TRUE) {
    02454
    02455         //
    02456         // These pages are no longer locked down.
    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 }

ULONG MiSetProtectionOnTransitionPte | ( | IN PMMPTE | PointerPte,
|  | IN ULONG | ProtectionMask
| ) |

| Referenced by MiProtectVirtualMemory(), MiSetImageProtect(), and MiSetProtectionOnSection().

VOID MiSetSystemCodeProtection | ( | IN PMMPTE | FirstPte,
|  | IN PMMPTE | LastPte
| ) |

Definition at line 5448 of file sysload.c.

References ASSERT, FALSE, KeFlushSingleTb(), LOCK_PFN, MI_ADD_LOCKED_PAGE_CHARGE, MI_CAPTURE_DIRTY_BIT_TO_PFN, MI_FLUSH_SINGLE_SESSION_TB, MI_IS_PHYSICAL_ADDRESS, MI_IS_PTE_DIRTY, MI_IS_SESSION_ADDRESS, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_REMOVE_LOCKED_PAGE_CHARGE, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiMakeSystemAddressValidPfn(), MiPteStr, MiPteToProto, MM_EXECUTE_READ, _MMPFN::OriginalPte, TRUE, _MMPTE::u, _MMPFN::u3, UNLOCK_PFN, and ZeroPte.

Referenced by MiWriteProtectSystemImage().

    05455                    :
    05456
    05457     This function sets the protection of system code to read only.
    05458     Note this is different from protecting section-backed code like win32k.
    05459
    05460 Arguments:
    05461
    05462     FirstPte - Supplies the starting PTE.
    05463
    05464     LastPte - Supplies the ending PTE.
    05465
    05466 Return Value:
    05467
    05468     None.
    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     // Make these PTEs read only.
    05499     //
    05500     // Note that the write bit may already be off (in the valid PTE) if the
    05501     // page has already been inpaged from the paging file and has not since
    05502     // been dirtied.
    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             // Note the dirty and write bits get turned off here.
    05525             // Any existing pagefile addresses for clean pages are preserved.
    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                 // Session space has no ASN - flush the entire TB.
    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                         // The world may change if we had to wait.
    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             // Must be page file space or demand zero.
    05621             //
    05622
    05623             PointerPte->u.Soft.Protection = ProtectionMask;
    05624         }
    05625         PointerPte += 1;
    05626     }
    05627
    05628     UNLOCK_PFN (OldIrql);
    05629 }

NTSTATUS MiSnapThunk | ( | IN PVOID | DllBase,
|  | IN PVOID | ImageBase,
|  | IN PIMAGE_THUNK_DATA | NameThunk,
|  | OUT PIMAGE_THUNK_DATA | AddrThunk,
|  | IN PIMAGE_EXPORT_DIRECTORY | ExportDirectory,
|  | IN ULONG | ExportSize,
|  | IN BOOLEAN | SnapForwarder,
|  | OUT PCHAR * | MissingProcedureName
| ) |

Definition at line 4464 of file sysload.c.

References CHAR, ExAllocatePoolWithTag, ExFreePool(), NT_SUCCESS, NTSTATUS(), PAGED_CODE, PagedPool, PsLoadedModuleList, PUSHORT, RtlAnsiStringToUnicodeString(), RtlFreeUnicodeString(), RtlImageDirectoryEntryToData(), RtlPrefixString(), Status, strlen(), TRUE, and USHORT.

Referenced by MiResolveImageReferences().

    04477                    :
    04478
    04479     This function snaps a thunk using the specified Export Section data.
    04480     If the section data does not support the thunk, then the thunk is
    04481     partially snapped (Dll field is still non-null, but snap address is
    04482     set).
    04483
    04484 Arguments:
    04485
    04486     DllBase - Base of DLL being snapped to.
    04487
    04488     ImageBase - Base of image that contains the thunks to snap.
    04489
    04490     Thunk - On input, supplies the thunk to snap.  When successfully
    04491         snapped, the function field is set to point to the address in
    04492         the DLL, and the DLL field is set to NULL.
    04493
    04494     ExportDirectory - Supplies the Export Section data from a DLL.
    04495
    04496     SnapForwarder - determine if the snap is for a forwarder, and therefore
    04497        Address of Data is already setup.
    04498
    04499 Return Value:
    04500
    04501
    04502     STATUS_SUCCESS or STATUS_DRIVER_ENTRYPOINT_NOT_FOUND or
    04503         STATUS_DRIVER_ORDINAL_NOT_FOUND
    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     // Determine if snap is by name, or by ordinal
    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         // Change AddressOfData from an RVA to a VA.
    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         // Lookup Name in NameTable
    04554         //
    04555
    04556         NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
    04557         NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
    04558
    04559         //
    04560         // Before dropping into binary search, see if
    04561         // the hint index results in a successful
    04562         // match. If the hint index is zero, then
    04563         // drop into binary search.
    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             // Lookup the import name in the name table using a binary search.
    04576             //
    04577
    04578             Low = 0;
    04579             High = ExportDirectory->NumberOfNames - 1;
    04580
    04581             while (High >= Low) {
    04582
    04583                 //
    04584                 // Compute the next probe index and compare the import name
    04585                 // with the export name entry.
    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             // If the high index is less than the low index, then a matching
    04605             // table entry was not found. Otherwise, get the ordinal number
    04606             // from the ordinal table.
    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     // If OrdinalNumber is not within the Export Address Table,
    04619     // then DLL does not implement function. Snap to LDRP_BAD_DLL.
    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         // AddrThunk s/b used from here on.
    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             // Include the dot in the length so we can do prefix later on.
    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                     // We have to do a case INSENSITIVE comparison for
    04672                     // forwarder because the linker just took what is in the
    04673                     // def file, as opposed to looking in the exporting
    04674                     // image for the name.
    04675                     // we also use the prefix function to ignore the .exe or
    04676                     // .sys or .dll at the end.
    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                             // one extra byte for NULL,
    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 }
    #if 0

VOID MiUpdateThunks | ( | IN PLOADER_PARAMETER_BLOCK | LoaderBlock,
|  | IN PVOID | OldAddress,
|  | IN PVOID | NewAddress,
|  | IN ULONG | NumberOfBytes
| ) |

Definition at line 5878 of file sysload.c.

References NULL, RtlImageDirectoryEntryToData(), and TRUE.

Referenced by MiReloadBootLoadedDrivers().

    05887                    :
    05888
    05889     This function updates the IATs of all the loaded modules in the system
    05890     to handle a newly relocated image.
    05891
    05892 Arguments:
    05893
    05894     LoaderBlock - Supplies a pointer to the system loader block.
    05895
    05896     OldAddress - Supplies the old address of the DLL which was just relocated.
    05897
    05898     NewAddress - Supplies the new address of the DLL which was just relocated.
    05899
    05900     NumberOfBytes - Supplies the number of bytes spanned by the DLL.
    05901
    05902 Return Value:
    05903
    05904     None.
    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     // Note this routine must not call any modules outside the kernel.
    05919     // This is because that module may itself be the one being relocated right
    05920     // now.
    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 }

VOID MiWriteProtectSystemImage | ( | IN PVOID | DllBase | ) |

| Referenced by MiLoadSystemImage(), and MmInitSystem().

NTSTATUS MmCallDllInitialize | ( | IN PLDR_DATA_TABLE_ENTRY | DataTableEntry | ) |

Definition at line 6717 of file sysload.c.

References CmRegistryMachineSystemCurrentControlSetServices, ExAllocatePoolWithTag, ExFreePool(), L, MiLocateExportName(), NonPagedPool, NTSTATUS(), NULL, PMM_DLL_INITIALIZE, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), and USHORT.

Referenced by IopInitializeBootDrivers().

    06723                    :
    06724
    06725     This function calls the DLL's initialize routine.
    06726
    06727 Arguments:
    06728
    06729     DataTableEntry - Supplies the kernel's data table entry.
    06730
    06731 Return Value:
    06732
    06733     Various NTSTATUS error codes.
    06734
    06735 Environment:
    06736
    06737     Kernel mode.
    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     // Invoke the DLL's initialization routine.
    06797     //
    06798
    06799     st = Func (&RegistryPath);
    06800
    06801     ExFreePool (RegistryPath.Buffer);
    06802
    06803     return st;
    06804 }

NTSTATUS MmCheckSystemImage | ( | IN HANDLE | ImageFileHandle | ) |

Definition at line 4820 of file sysload.c.

References EXCEPTION_EXECUTE_HANDLER, L, LdrVerifyMappedImageMatchesChecksum(), MmVerifyImageIsOkForMpUse(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, and Status.

    04826                    :
    04827
    04828     This function ensures the checksum for a system image is correct
    04829     and matches the data in the image.
    04830
    04831 Arguments:
    04832
    04833     ImageFileHandle - Supplies the file handle of the image.
    04834
    04835 Return Value:
    04836
    04837     Status value.
    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                 0L,
    04874                 0L,
    04875                 NULL,
    04876                 &ViewSize,
    04877                 ViewShare,
    04878                 0L,
    04879                 PAGE_EXECUTE
    04880                 );
    04881
    04882     if ( !NT_SUCCESS(Status) ) {
    04883         ZwClose(Section);
    04884         return Status;
    04885     }
    04886
    04887     //
    04888     // Now the image is mapped as a data file... Calculate its size and then
    04889     // check its checksum.
    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 }

VOID MmFreeDriverInitialization | ( | IN PVOID | ImageHandle | ) |

Definition at line 2106 of file sysload.c.

References ASSERT, ExPageLockHandle, FALSE, MI_IS_SESSION_ADDRESS, MiDeleteSystemPagableVm(), MiGetPteAddress, MiReturnCommitment(), MM_BUMP_COUNTER, MM_DBG_COMMIT_RETURN_DRIVER_INIT_CODE, MM_TRACK_COMMIT, MmDriverCommit, MmLockPagableSectionByHandle(), MmResidentAvailablePages, MmUnlockPagableImageSection(), NULL, PAGE_SHIFT, ROUND_TO_PAGES, RtlImageNtHeader(), and ZeroKernelPte.

Referenced by IopLoadDriver().

    02112                    :
    02113
    02114     This routine removes the pages that relocate and debug information from
    02115     the address space of the driver.
    02116
    02117     NOTE:  This routine looks at the last sections defined in the image
    02118            header and if that section is marked as DISCARDABLE in the
    02119            characteristics, it is removed from the image.  This means
    02120            that all discardable sections at the end of the driver are
    02121            deleted.
    02122
    02123 Arguments:
    02124
    02125     SectionObject - Supplies the section object for the image.
    02126
    02127 Return Value:
    02128
    02129     None.
    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             // There was a non discardable section between the this
    02173             // section and the last non discardable section, don't
    02174             // discard this section and don't look any more.
    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 }

NTKERNELAPI PVOID MmGetSystemRoutineAddress | ( | IN PUNICODE_STRING | SystemRoutineName | ) |

Definition at line 6808 of file sysload.c.

References ASSERT, ExAcquireResourceShared, ExReleaseResource, FALSE, KeDelayExecutionThread(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KernelMode, L, MiFindExportedRoutineByName(), MmShortTime, NT_SUCCESS, NTSTATUS(), NULL, PASSIVE_LEVEL, PsLoadedModuleList, PsLoadedModuleResource, RtlEqualUnicodeString(), RtlFreeAnsiString(), RtlInitUnicodeString(), RtlUnicodeStringToAnsiString(), Status, and TRUE.

    06814                    :
    06815
    06816     This function returns the address of the argument function pointer if
    06817     it is in the kernel or HAL, NULL if it is not.
    06818
    06819 Arguments:
    06820
    06821     SystemRoutineName - Supplies the name of the desired routine.
    06822
    06823 Return Value:
    06824
    06825     Non-NULL function pointer if successful.  NULL if not.
    06826
    06827 Environment:
    06828
    06829     Kernel mode.
    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     // Arbitrary process context so prevent suspend APCs now.
    06868     //
    06869
    06870     KeEnterCriticalRegion();
    06871     ExAcquireResourceShared (&PsLoadedModuleResource, TRUE);
    06872
    06873     //
    06874     // Check only the kernel and the HAL for exports.
    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 }

NTSTATUS MmLoadAndLockSystemImage | ( | IN PUNICODE_STRING | ImageFileName,
|  | IN PUNICODE_STRING NamePrefix | OPTIONAL,
|  | IN PUNICODE_STRING LoadedBaseName | OPTIONAL,
|  | OUT PVOID * | ImageHandle,
|  | OUT PVOID * | ImageBaseAddress
| ) |

Definition at line 379 of file sysload.c.

References FALSE, MiLoadSystemImage(), PAGED_CODE, and TRUE.

Referenced by IopLoadDumpDriver().

    00389                    :
    00390
    00391     This routine reads the image pages from the specified section into
    00392     the system and returns the address of the DLL's header.  Very similar
    00393     to MmLoadSystemImage, except that it also locks down the driver pages.
    00394     This is needed for things like the dump driver because we cannot page it
    00395     back in after the system has crashed (when we want to write the system
    00396     dump to the pagefile).
    00397
    00398     At successful completion, the Section is referenced so it remains
    00399     until the system image is unloaded.
    00400
    00401 Arguments:
    00402
    00403     ImageName - Supplies the Unicode name of the image to load.
    00404
    00405     ImageFileName - Supplies the full path name (including the image name)
    00406                     of the image to load.
    00407
    00408     NamePrefix - Supplies the prefix to use with the image name on load
    00409                  operations.  This is used to load the same image multiple
    00410                  times, by using different prefixes
    00411
    00412     LoadedBaseName - If present, supplies the base name to use on the
    00413                      loaded image instead of the base name found on the
    00414                      image name.
    00415
    00416     ImageHandle - Returns an opaque pointer to the referenced section object
    00417                   of the image that was loaded.
    00418
    00419     ImageBaseAddress - Returns the image base within the system.
    00420
    00421 Return Value:
    00422
    00423     Status of the load operation.
    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 }

NTSTATUS MmLoadSystemImage | ( | IN PUNICODE_STRING | ImageFileName,
|  | IN PUNICODE_STRING NamePrefix | OPTIONAL,
|  | IN PUNICODE_STRING LoadedBaseName | OPTIONAL,
|  | IN BOOLEAN | LoadInSessionSpace,
|  | OUT PVOID * | ImageHandle,
|  | OUT PVOID * | ImageBaseAddress
| ) |

Definition at line 315 of file sysload.c.

References FALSE, MiLoadSystemImage(), and PAGED_CODE.

Referenced by IopLoadDriver(), MiResolveImageReferences(), and NtSetSystemInformation().

    00326                    :
    00327
    00328     This routine reads the image pages from the specified section into
    00329     the system and returns the address of the DLL's header.
    00330
    00331     At successful completion, the Section is referenced so it remains
    00332     until the system image is unloaded.
    00333
    00334 Arguments:
    00335
    00336     ImageName - Supplies the Unicode name of the image to load.
    00337
    00338     ImageFileName - Supplies the full path name (including the image name)
    00339                     of the image to load.
    00340
    00341     NamePrefix - Supplies the prefix to use with the image name on load
    00342                  operations.  This is used to load the same image multiple
    00343                  times, by using different prefixes
    00344
    00345     LoadedBaseName - If present, supplies the base name to use on the
    00346                      loaded image instead of the base name found on the
    00347                      image name.
    00348
    00349     LoadInSessionSpace - Supplies whether to load this image in session space -
    00350                      ie: each session will have a different copy of this driver
    00351                      with pages shared as much as possible via copy on write.
    00352
    00353     ImageHandle - Returns an opaque pointer to the referenced section object
    00354                   of the image that was loaded.
    00355
    00356     ImageBaseAddress - Returns the image base within the system.
    00357
    00358 Return Value:
    00359
    00360     Status of the load operation.
    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 }

PUNICODE_STRING MmLocateUnloadedDriver | ( | IN PVOID | VirtualAddress | ) |

Definition at line 2836 of file sysload.c.

References _UNLOADED_DRIVERS::EndAddress, Index, MI_UNLOADED_DRIVERS, MiLastUnloadedDriver, MiUnloadedDrivers, _UNLOADED_DRIVERS::Name, NULL, and _UNLOADED_DRIVERS::StartAddress.

Referenced by KeBugCheckEx(), and KiDumpParameterImages().

    02842                    :
    02843
    02844     This routine attempts to find the specified virtual address in the
    02845     unloaded driver list.
    02846
    02847 Arguments:
    02848
    02849     VirtualAddress - Supplies a virtual address that might be within a driver
    02850                      that has already unloaded.
    02851
    02852 Return Value:
    02853
    02854     A pointer to a Unicode string containing the unloaded driver's name.
    02855
    02856 Environment:
    02857
    02858     Kernel mode, bugcheck time.
    02859
    02860 --*/
    02861
    02862 {
    02863     PUNLOADED_DRIVERS Entry;
    02864     ULONG i;
    02865     ULONG Index;
    02866
    02867     //
    02868     // No serialization is needed because we've crashed.
    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 }

VOID MmMakeKernelResourceSectionWritable | ( | VOID |  | ) |

Definition at line 6495 of file sysload.c.

References KeFlushCurrentTb(), MI_IS_PHYSICAL_ADDRESS, MI_MAKE_VALID_PTE, MI_WRITE_VALID_PTE_NEW_PROTECTION, MiGetVirtualAddressMappedByPte, MM_READWRITE, NULL, and _MMPTE::u.

Referenced by KeGetBugMessageText().

    06501                    :
    06502
    06503     This function makes the kernel's resource section readwrite so the bugcheck
    06504     code can write into it.
    06505
    06506 Arguments:
    06507
    06508     None.
    06509
    06510 Return Value:
    06511
    06512     None.
    06513
    06514 Environment:
    06515
    06516     Kernel mode.  Any IRQL.
    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         // Mapped physically, doesn't need to be made readwrite.
    06536         //
    06537
    06538         return;
    06539     }
    06540
    06541     //
    06542     // Since the entry state and IRQL are unknown, just go through the
    06543     // PTEs without a lock and make them all readwrite.
    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     // Don't do this more than once.
    06568     //
    06569
    06570     MiKernelResourceStartPte = NULL;
    06571
    06572     //
    06573     // Only flush this processor as the state of the others is unknown.
    06574     //
    06575
    06576     KeFlushCurrentTb ();
    06577 #endif
    06578 }

PVOID MmPageEntireDriver | ( | IN PVOID | AddressWithinSection | ) |

Definition at line 2472 of file sysload.c.

References FALSE, MI_IS_SESSION_IMAGE_ADDRESS, MiGetPteAddress, MiLookupDataTableEntry(), MiSetPagingOfDriver(), MmDisablePagingExecutive, NULL, PAGE_SHIFT, PAGED_CODE, PSECTION, and TRUE.

Referenced by DriverEntry(), MiLoadSystemImage(), and NtSetSystemInformation().

    02478                    :
    02479
    02480     This routine allows a driver to page out all of its code and
    02481     data regardless of the attributes of the various image sections.
    02482
    02483     Note, this routine can be called multiple times with no
    02484     intervening calls to MmResetDriverPaging.
    02485
    02486 Arguments:
    02487
    02488     AddressWithinSection - Supplies an address within the driver, e.g.
    02489                            DriverEntry.
    02490
    02491 Return Value:
    02492
    02493     Base address of driver.
    02494
    02495 Environment:
    02496
    02497     Kernel mode, APC_LEVEL or below.
    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     // Don't page kernel mode code if disabled via registry.
    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         // Driver is mapped as an image (ie: win32k), this is always pagable.
    02533         // For session space, an image that has been loaded at its desired
    02534         // address is also always pagable.  If there was an address collision,
    02535         // then we fall through because we have to explicitly page it.
    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 }

VOID MmResetDriverPaging | ( | IN PVOID | AddressWithinSection | ) |

Definition at line 2560 of file sysload.c.

References ASSERT, DbgPrint, ExPageLockHandle, FALSE, LOCK_PFN, LOCK_SYSTEM_WS, MI_IS_PHYSICAL_ADDRESS, MiGetPteAddress, MiLockCode(), MiLookupDataTableEntry(), MM_LOCK_BY_NONPAGE, MmDisablePagingExecutive, MmLockPagableSectionByHandle(), MmUnlockPagableImageSection(), NULL, PAGED_CODE, RtlImageNtHeader(), UNLOCK_PFN, and UNLOCK_SYSTEM_WS.

    02566                    :
    02567
    02568     This routines resets the driver paging to what the image specified.
    02569     Hence image sections such as the IAT, .text, .data will be locked
    02570     down in memory.
    02571
    02572     Note, there is no requirement that MmPageEntireDriver was called.
    02573
    02574 Arguments:
    02575
    02576      AddressWithinSection - Supplies an address within the driver, e.g.
    02577                             DriverEntry.
    02578
    02579 Return Value:
    02580
    02581     None.
    02582
    02583 Environment:
    02584
    02585     Kernel mode, APC_LEVEL or below.
    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     // Don't page kernel mode code if disabled via registry.
    02604     //
    02605
    02606     if (MmDisablePagingExecutive) {
    02607         return;
    02608     }
    02609
    02610     if (MI_IS_PHYSICAL_ADDRESS(AddressWithinSection)) {
    02611         return;
    02612     }
    02613
    02614     //
    02615     // If the driver has pagable code, make it paged.
    02616     //
    02617
    02618     DataTableEntry = MiLookupDataTableEntry (AddressWithinSection, FALSE);
    02619
    02620     if ((DataTableEntry->SectionPointer != NULL) &&
    02621         (DataTableEntry->SectionPointer != (PVOID)-1)) {
    02622
    02623         //
    02624         // Driver is mapped by image hence already paged.
    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         // Don't lock down code for sections marked as discardable or
    02654         // sections marked with the first 4 characters PAGE or .eda
    02655         // (for the .edata section) or INIT.
    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             // This section is nonpagable.
    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 }

NTSTATUS MmUnloadSystemImage | ( | IN PVOID | ImageHandle | ) |

Definition at line 2896 of file sysload.c.

References ASSERT, _MM_SESSION_SPACE::CommittedPages, DbgPrint, ExAcquireResourceExclusive, ExFreePool(), ExPageLockHandle, ExpCheckForResource(), ExReleaseResource, FALSE, _IMAGE_ENTRY_IN_SESSION::ImageCountInThisSession, KeBugCheckEx(), KeCheckForTimer(), KeEnterCriticalRegion, KeLeaveCriticalRegion, KeReleaseMutant(), KernelMode, KeWaitForSingleObject(), LOADED_AT_BOOT, LOCK_PFN, LOCK_SESSION_SPACE_WS, MI_IS_SESSION_IMAGE_ADDRESS, MiActiveVerifierThunks, MiClearImports(), MiDeleteSystemPagableVm(), MiDereferenceImports(), MiGetPteAddress, MiReleaseSystemPtes(), MiRememberUnloadedDriver(), MiRemoveImageSessionWide(), MiReturnCommitment(), MiSessionLookupImage(), MiSessionWideGetImageSize(), MiVerifierCheckThunks(), MiVerifyingDriverUnloading(), MM_BUMP_COUNTER, MM_BUMP_SESS_COUNTER, MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD, MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD1, MM_DBG_SESSION_COMMIT_IMAGE_UNLOAD, MM_TRACK_COMMIT, MmDisablePagingExecutive, MmDriverCommit, MmLockPagableSectionByHandle(), MmResidentAvailablePages, MmSessionSpace, MmSnapUnloads, MmSystemLoadLock, MmTotalSystemDriverPages, MmUnlockPagableImageSection(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PAGE_SHIFT, PERFINFO_IMAGE_UNLOAD, PLOAD_IMPORTS, PSECTION, PsLoadedModuleList, PsLoadedModuleResource, PsLoadedModuleSpinLock, RtlFreeAnsiString(), RtlUnicodeStringToAnsiString(), _MM_SESSION_SPACE::SessionId, Status, SystemPteSpace, TRUE, UNLOCK_PFN, UNLOCK_SESSION_SPACE_WS, WrVirtualMemory, and ZeroKernelPte.

Referenced by IoFreeDumpStack(), IopDeleteDriver(), IopLoadDriver(), MiCallDllUnloadAndUnloadDll(), MiLoadSystemImage(), MiResolveImageReferences(), MiSessionUnloadAllImages(), and NtSetSystemInformation().

    02902                    :
    02903
    02904     This routine unloads a previously loaded system image and returns
    02905     the allocated resources.
    02906
    02907 Arguments:
    02908
    02909     ImageHandle - Supplies a pointer to the section object of the
    02910                   image to unload.
    02911
    02912 Return Value:
    02913
    02914     Various NTSTATUS codes.
    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     // Arbitrary process context so prevent suspend APCs now.
    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     // MiUnloadSystemImageByForce violates this check so remove it for now.
    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     // Any driver loaded at boot that did not have its import list
    02994     // and LoadCount reconstructed cannot be unloaded because we don't
    02995     // know how many other drivers may be linked to it.
    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         // A printer driver may be referenced multiple times for the
    03011         // same session space.  Only unload the last reference.
    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         // The reference count for this image has dropped to zero in this
    03032         // session, so we can delete this session's view of the image.
    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         // Free the session space taken up by the image, unmapping it from
    03050         // the current VA space - note this does not remove page table pages
    03051         // from the session PageTables[].  Each data page is only freed
    03052         // if there are no other references to it (ie: from any other
    03053         // sessions).
    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         // Return the commitment we took out on the pagefile when the
    03090         // image was allocated.
    03091         //
    03092
    03093         MiReturnCommitment (CommittedPages);
    03094         MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_DRIVER_UNLOAD, CommittedPages);
    03095
    03096         //
    03097         // Tell the session space image handler that we are releasing
    03098         // our claim to the image.
    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     // Unload symbols from debugger.
    03159     //
    03160
    03161     if (DataTableEntry->Flags & LDRP_DEBUG_SYMBOLS_LOADED) {
    03162
    03163         //
    03164         //  TEMP TEMP TEMP rip out when debugger converted
    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     // No unload can happen till after Mm has finished Phase 1 initialization.
    03184     // Therefore, large pages are already in effect (if this platform supports
    03185     // it).
    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             // Note that drivers loaded at boot that have not been relocated
    03212             // have no system PTEs or commit charged.
    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             // Only return commitment for drivers that weren't loaded by the
    03226             // boot loader.
    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             // This must be a boot driver that was not relocated into
    03239             // system PTEs.  If large or super pages are enabled, the
    03240             // image pages must be freed without referencing the
    03241             // non-existent page table pages.  If large/super pages are
    03242             // not enabled, note that system PTEs were not used to map the
    03243             // image and thus, cannot be freed.
    03244
    03245             //
    03246             // This is further complicated by the fact that the INIT and/or
    03247             // discardable portions of these images may have already been freed.
    03248             //
    03249         }
    03250     }
    03251
    03252     //
    03253     // Search the loaded module list for the data table entry that describes
    03254     // the DLL that was just unloaded. It is possible an entry is not in the
    03255     // list if a failure occurred at a point in loading the DLL just before
    03256     // the data table entry was generated.
    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     // Handle unloading of any dependent DLLs that we loaded automatically
    03279     // for this image.
    03280     //
    03281
    03282     MiDereferenceImports ((PLOAD_IMPORTS)DataTableEntry->LoadedImports);
    03283
    03284     MiClearImports (DataTableEntry);
    03285
    03286     //
    03287     // Free this loader entry.
    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         // Dereference the section object if there is one.
    03302         // There should only be one for win32k.sys and Hydra session images.
    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 }

BOOLEAN MmVerifyImageIsOkForMpUse | ( | IN PVOID | BaseAddress | ) |

Definition at line 4923 of file sysload.c.

References FALSE, KeNumberProcessors, NULL, PAGED_CODE, RtlImageNtHeader(), and TRUE.

Referenced by MmCheckSystemImage().

    04926 {
    04927     PIMAGE_NT_HEADERS NtHeaders;
    04928
    04929     PAGED_CODE();
    04930
    04931     //
    04932     // If the file is an image file, then subtract the two checksum words
    04933     // in the optional header from the computed checksum before adding
    04934     // the file length, and set the value of the header checksum.
    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 }

## Variable Documentation

PVOID ExPoolCodeEnd

| Definition at line 92 of file sysload.c. Referenced by KeBugCheckEx(), and MiLocateKernelSections().

PVOID ExPoolCodeStart

| Definition at line 91 of file sysload.c. Referenced by KeBugCheckEx(), and MiLocateKernelSections().

BOOLEAN MiFirstDriverLoadEver = TRUE

| Definition at line 61 of file sysload.c. Referenced by MiLoadSystemImage().

ULONG MiLastUnloadedDriver

| Definition at line 77 of file sysload.c. Referenced by MiRememberUnloadedDriver(), and MmLocateUnloadedDriver().

LOGICAL MiNoLowMemory

| Definition at line 268 of file sysload.c.

CHAR MiPteStr[] = "\0"

| Definition at line 311 of file sysload.c. Referenced by MiSetSystemCodeProtection(), and MmInitSystem().

ULONG MiTotalUnloads

| Definition at line 78 of file sysload.c. Referenced by MiRememberUnloadedDriver().

PUNLOADED_DRIVERS MiUnloadedDrivers

| Definition at line 75 of file sysload.c.

ULONG MiUnloadsSkipped

| Definition at line 79 of file sysload.c. Referenced by MiRememberUnloadedDriver().

ULONG MmDriverCommit

| Definition at line 59 of file sysload.c.

ULONG MmEnforceWriteProtection = 1

| Definition at line 85 of file sysload.c.

LOGICAL MmMakeLowMemory = TRUE

| Definition at line 68 of file sysload.c.

PVOID MmPoolCodeEnd

| Definition at line 94 of file sysload.c. Referenced by KeBugCheckEx(), and MiLocateKernelSections().

PVOID MmPoolCodeStart

| Definition at line 93 of file sysload.c. Referenced by KeBugCheckEx(), and MiLocateKernelSections().

PVOID MmPteCodeEnd

| Definition at line 96 of file sysload.c. Referenced by KeBugCheckEx(), and MiLocateKernelSections().

PVOID MmPteCodeStart

| Definition at line 95 of file sysload.c. Referenced by KeBugCheckEx(), and MiLocateKernelSections().

KMUTANT MmSystemLoadLock

| Definition at line 55 of file sysload.c.

ULONG MmTotalSystemDriverPages

| Definition at line 57 of file sysload.c.

LIST_ENTRY PsLoadedModuleList

| Definition at line 6586 of file sysload.c.

ERESOURCE PsLoadedModuleResource

| Definition at line 6587 of file sysload.c. Referenced by IopInitializeBootLogging(), IopLoadDriver(), MiEnablePagingTheExecutive(), MiFindInitializationCode(), MiInitializeLoadedModuleList(), MiLoadSystemImage(), MiLookupDataTableEntry(), MiLookupPsLoadedModule(), MiMapViewOfImageSection(), MmGetSectionRange(), MmGetSystemRoutineAddress(), MmInitSystem(), MmLockPagableDataSection(), MmUnloadSystemImage(), NtQuerySystemInformation(), and NtSystemDebugControl().

KSPIN_LOCK PsLoadedModuleSpinLock

| Definition at line 106 of file sysload.c.

PVOID PsNtosImageBase

| Definition at line 6583 of file sysload.c. Referenced by KdpGetVersion(), KiInitializeKernel(), and MiInitializeLoadedModuleList().