[ros-diffs] [ion] 25883: - Fix MmCreateImageSection to use previous mode instead of hardcoding UserMode. - Implement MiProcessLoaderEntry for adding/removing entries on the PsLoadedModuleList. - Move MmLoadSystemImage from loader.c to sysldr.c - Update MmLoadSystemImage: - Use MmSystemLoadLock. - Support returning the entry for an already-loaded image, instead of loading it twice. - Use Section APIs to map the image... we're still doing a dirty ZwReadFile hack, but at least now we can depend on the PE code to validate the image (so removed the hardcoded validation). - Add more generic cleanup got so we can just jump to it. - Add more stub code and detection code for upcoming features.

ion at svn.reactos.org ion at svn.reactos.org
Fri Feb 23 06:39:42 CET 2007


Author: ion
Date: Fri Feb 23 08:39:42 2007
New Revision: 25883

URL: http://svn.reactos.org/svn/reactos?rev=25883&view=rev
Log:
- Fix MmCreateImageSection to use previous mode instead of hardcoding UserMode.
- Implement MiProcessLoaderEntry for adding/removing entries on the PsLoadedModuleList.
- Move MmLoadSystemImage from loader.c to sysldr.c
- Update MmLoadSystemImage:
  - Use MmSystemLoadLock.
  - Support returning the entry for an already-loaded image, instead of loading it twice.
  - Use Section APIs to map the image... we're still doing a dirty ZwReadFile hack, but at least now we can depend on the PE code to validate the image (so removed the hardcoded validation).
  - Add more generic cleanup got so we can just jump to it.
  - Add more stub code and detection code for upcoming features.

Modified:
    trunk/reactos/ntoskrnl/ldr/loader.c
    trunk/reactos/ntoskrnl/mm/section.c
    trunk/reactos/ntoskrnl/mm/sysldr.c

Modified: trunk/reactos/ntoskrnl/ldr/loader.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ldr/loader.c?rev=25883&r1=25882&r2=25883&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ldr/loader.c (original)
+++ trunk/reactos/ntoskrnl/ldr/loader.c Fri Feb 23 08:39:42 2007
@@ -19,15 +19,6 @@
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
-
-NTSTATUS
-NTAPI
-MiResolveImageReferences(IN PVOID ImageBase,
-                         IN PUNICODE_STRING ImageFileDirectory,
-                         IN PUNICODE_STRING NamePrefix OPTIONAL,
-                         OUT PCHAR *MissingApi,
-                         OUT PWCHAR *MissingDriver,
-                         OUT PLOAD_IMPORTS *LoadImports);
 
 static LONG
 LdrpCompareModuleNames (
@@ -168,372 +159,4 @@
     return(STATUS_SUCCESS);
 }
 
-//
-// Used by NtLoadDriver/IoMgr
-//
-NTSTATUS
-NTAPI
-MmLoadSystemImage(IN PUNICODE_STRING FileName,
-                  IN PUNICODE_STRING NamePrefix OPTIONAL,
-                  IN PUNICODE_STRING LoadedName OPTIONAL,
-                  IN ULONG Flags,
-                  OUT PVOID *ModuleObject,
-                  OUT PVOID *ImageBaseAddress)
-{
-    PVOID ModuleLoadBase;
-    NTSTATUS Status;
-    HANDLE FileHandle;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    PLDR_DATA_TABLE_ENTRY Module;
-    FILE_STANDARD_INFORMATION FileStdInfo;
-    IO_STATUS_BLOCK IoStatusBlock;
-    unsigned int DriverSize, Idx;
-    ULONG CurrentSize;
-    PVOID DriverBase;
-    PIMAGE_DOS_HEADER PEDosHeader;
-    PIMAGE_NT_HEADERS PENtHeaders;
-    PIMAGE_SECTION_HEADER PESectionHeaders;
-    KIRQL Irql;
-    PIMAGE_NT_HEADERS NtHeader;
-    UNICODE_STRING BaseName, BaseDirectory, PrefixName;
-    PLDR_DATA_TABLE_ENTRY LdrEntry;
-    ULONG EntrySize;
-    PLOAD_IMPORTS LoadedImports = (PVOID)-2;
-    PCHAR MissingApiName, Buffer;
-    PWCHAR MissingDriverName;
-    PAGED_CODE();
-
-    /* Detect session-load */
-    if (Flags)
-    {
-        /* Sanity checks */
-        ASSERT(NamePrefix == NULL);
-        ASSERT(LoadedName == NULL);
-
-        /* Make sure the process is in session too */
-        if (!PsGetCurrentProcess()->ProcessInSession) return STATUS_NO_MEMORY;
-    }
-
-    if (ModuleObject) *ModuleObject = NULL;
-    if (ImageBaseAddress) *ImageBaseAddress = NULL;
-
-    /* Allocate a buffer we'll use for names */
-    Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
-    if (!Buffer)
-    {
-        /* Fail */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* Check for a separator */
-    if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
-    {
-        PWCHAR p;
-        ULONG BaseLength;
-
-        /* Loop the path until we get to the base name */
-        p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
-        while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
-
-        /* Get the length */
-        BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
-        BaseLength *= sizeof(WCHAR);
-
-        /* Setup the string */
-        BaseName.Length = (USHORT)BaseLength;
-        BaseName.Buffer = p;
-    }
-    else
-    {
-        /* Otherwise, we already have a base name */
-        BaseName.Length = FileName->Length;
-        BaseName.Buffer = FileName->Buffer;
-    }
-
-    /* Setup the maximum length */
-    BaseName.MaximumLength = BaseName.Length;
-
-    /* Now compute the base directory */
-    BaseDirectory = *FileName;
-    BaseDirectory.Length -= BaseName.Length;
-    BaseDirectory.MaximumLength = BaseDirectory.Length;
-
-    /* And the prefix, which for now is just the name itself */
-    PrefixName = *FileName;
-
-    /* Check if we have a prefix */
-    if (NamePrefix) DPRINT1("Prefixed images are not yet supported!\n");
-
-    /* Check if we already have a name, use it instead */
-    if (LoadedName) BaseName = *LoadedName;
-
-    /*  Open the Module  */
-    InitializeObjectAttributes(&ObjectAttributes,
-        FileName,
-        OBJ_CASE_INSENSITIVE,
-        NULL,
-        NULL);
-
-    Status = ZwOpenFile(&FileHandle,
-        GENERIC_READ,
-        &ObjectAttributes,
-        &IoStatusBlock,
-        FILE_SHARE_READ,
-        FILE_SYNCHRONOUS_IO_NONALERT);
-
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", FileName, Status);
-        return(Status);
-    }
-
-
-    /*  Get the size of the file  */
-    Status = ZwQueryInformationFile(FileHandle,
-        &IoStatusBlock,
-        &FileStdInfo,
-        sizeof(FileStdInfo),
-        FileStandardInformation);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("Could not get file size\n");
-        NtClose(FileHandle);
-        return(Status);
-    }
-
-
-    /*  Allocate nonpageable memory for driver  */
-    ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
-        FileStdInfo.EndOfFile.u.LowPart,
-        TAG_DRIVER_MEM);
-    if (ModuleLoadBase == NULL)
-    {
-        DPRINT("Could not allocate memory for module");
-        NtClose(FileHandle);
-        return(STATUS_INSUFFICIENT_RESOURCES);
-    }
-
-
-    /*  Load driver into memory chunk  */
-    Status = ZwReadFile(FileHandle,
-        0, 0, 0,
-        &IoStatusBlock,
-        ModuleLoadBase,
-        FileStdInfo.EndOfFile.u.LowPart,
-        0, 0);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("Could not read module file into memory");
-        ExFreePool(ModuleLoadBase);
-        NtClose(FileHandle);
-        return(Status);
-    }
-
-
-    ZwClose(FileHandle);
-
-    DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
-
-    /*  Get header pointers  */
-    PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
-    PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
-    NtHeader = PENtHeaders;
-    PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
-
-
-    /*  Check file magic numbers  */
-    if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
-    {
-        DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
-        return STATUS_UNSUCCESSFUL;
-    }
-    if (PEDosHeader->e_lfanew == 0)
-    {
-        DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
-        return STATUS_UNSUCCESSFUL;
-    }
-    if (PENtHeaders->Signature != IMAGE_NT_SIGNATURE)
-    {
-        DPRINT("Incorrect PE magic: %08x\n", PENtHeaders->Signature);
-        return STATUS_UNSUCCESSFUL;
-    }
-    if (PENtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
-    {
-        DPRINT("Incorrect Architechture: %04x\n", PENtHeaders->FileHeader.Machine);
-        return STATUS_UNSUCCESSFUL;
-    }
-
-
-    /* FIXME: if image is fixed-address load, then fail  */
-
-    /* FIXME: check/verify OS version number  */
-
-    DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
-        PENtHeaders->OptionalHeader.Magic,
-        PENtHeaders->OptionalHeader.MajorLinkerVersion,
-        PENtHeaders->OptionalHeader.MinorLinkerVersion);
-    DPRINT("Entry Point:%08lx\n", PENtHeaders->OptionalHeader.AddressOfEntryPoint);
-
-    /*  Determine the size of the module  */
-    DriverSize = 0;
-    for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
-    {
-        if (!(PESectionHeaders[Idx].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
-        {
-            CurrentSize = PESectionHeaders[Idx].VirtualAddress + PESectionHeaders[Idx].Misc.VirtualSize;
-            DriverSize = max(DriverSize, CurrentSize);
-        }
-    }
-    DriverSize = ROUND_UP(DriverSize, PENtHeaders->OptionalHeader.SectionAlignment);
-    DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize, PENtHeaders->OptionalHeader.SizeOfImage);
-
-    /*  Allocate a virtual section for the module  */
-    DriverBase = NULL;
-    DriverBase = MmAllocateSection(DriverSize, DriverBase);
-    if (DriverBase == 0)
-    {
-        DPRINT("Failed to allocate a virtual section for driver\n");
-        return STATUS_UNSUCCESSFUL;
-    }
-    DPRINT("DriverBase for %wZ: %x\n", FileName, DriverBase);
-
-    /*  Copy headers over */
-    memcpy(DriverBase, ModuleLoadBase, PENtHeaders->OptionalHeader.SizeOfHeaders);
-
-    /*  Copy image sections into virtual section  */
-    for (Idx = 0; Idx < PENtHeaders->FileHeader.NumberOfSections; Idx++)
-    {
-        CurrentSize = PESectionHeaders[Idx].VirtualAddress + PESectionHeaders[Idx].Misc.VirtualSize;
-        /* Copy current section into current offset of virtual section */
-        if (CurrentSize <= DriverSize &&
-            PESectionHeaders[Idx].SizeOfRawData)
-        {
-            DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
-                PESectionHeaders[Idx].VirtualAddress + (ULONG_PTR)DriverBase);
-            memcpy((PVOID)((ULONG_PTR)DriverBase + PESectionHeaders[Idx].VirtualAddress),
-                (PVOID)((ULONG_PTR)ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
-                PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
-                ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
-        }
-    }
-
-    /* Relocate the driver */
-    Status = LdrRelocateImageWithBias(DriverBase,
-                                      0,
-                                      "SYSLDR",
-                                      STATUS_SUCCESS,
-                                      STATUS_CONFLICTING_ADDRESSES,
-                                      STATUS_INVALID_IMAGE_FORMAT);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Fail */
-        return Status;
-    }
-
-    /* Calculate the size we'll need for the entry and allocate it */
-    EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
-                BaseName.Length +
-                sizeof(UNICODE_NULL);
-
-    /* Allocate the entry */
-    LdrEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_MODULE_OBJECT);
-    if (!LdrEntry)
-    {
-        /* Fail */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* Setup the entry */
-    LdrEntry->Flags = LDRP_LOAD_IN_PROGRESS;
-    LdrEntry->LoadCount = 1;
-    LdrEntry->LoadedImports = LoadedImports;
-    LdrEntry->PatchInformation = NULL;
-
-    /* Check the version */
-    if ((NtHeader->OptionalHeader.MajorOperatingSystemVersion >= 5) &&
-        (NtHeader->OptionalHeader.MajorImageVersion >= 5))
-    {
-        /* Mark this image as a native image */
-        LdrEntry->Flags |= 0x80000000;
-    }
-
-    /* Setup the rest of the entry */
-    LdrEntry->DllBase = DriverBase;
-    LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)DriverBase +
-                                   NtHeader->OptionalHeader.AddressOfEntryPoint);
-    LdrEntry->SizeOfImage = DriverSize;
-    LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum;
-    LdrEntry->SectionPointer = LdrEntry;
-
-    /* Now write the DLL name */
-    LdrEntry->BaseDllName.Buffer = (PVOID)(LdrEntry + 1);
-    LdrEntry->BaseDllName.Length = BaseName.Length;
-    LdrEntry->BaseDllName.MaximumLength = BaseName.Length;
-
-    /* Copy and null-terminate it */
-    RtlCopyMemory(LdrEntry->BaseDllName.Buffer,
-                  BaseName.Buffer,
-                  BaseName.Length);
-    LdrEntry->BaseDllName.Buffer[BaseName.Length / 2] = UNICODE_NULL;
-
-    /* Now allocate the full name */
-    LdrEntry->FullDllName.Buffer = ExAllocatePoolWithTag(PagedPool,
-                                                         PrefixName.Length +
-                                                         sizeof(UNICODE_NULL),
-                                                         TAG_LDR_WSTR);
-    if (!LdrEntry->FullDllName.Buffer)
-    {
-        /* Don't fail, just set it to zero */
-        LdrEntry->FullDllName.Length = 0;
-        LdrEntry->FullDllName.MaximumLength = 0;
-    }
-    else
-    {
-        /* Set it up */
-        LdrEntry->FullDllName.Length = PrefixName.Length;
-        LdrEntry->FullDllName.MaximumLength = PrefixName.Length;
-
-        /* Copy and null-terminate */
-        RtlCopyMemory(LdrEntry->FullDllName.Buffer,
-                      PrefixName.Buffer,
-                      PrefixName.Length);
-        LdrEntry->FullDllName.Buffer[PrefixName.Length / 2] = UNICODE_NULL;
-    }
-
-    /* Insert the entry */
-    KeAcquireSpinLock(&PsLoadedModuleSpinLock, &Irql);
-    InsertTailList(&PsLoadedModuleList, &LdrEntry->InLoadOrderLinks);
-    KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql);
-
-    /* Resolve imports */
-    MissingApiName = Buffer;
-    Status = MiResolveImageReferences(DriverBase,
-                                      &BaseDirectory,
-                                      NULL,
-                                      &MissingApiName,
-                                      &MissingDriverName,
-                                      &LoadedImports);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Fail */
-        ExFreePool(LdrEntry->FullDllName.Buffer);
-        ExFreePool(LdrEntry);
-        return Status;
-    }
-
-    /* Return */
-    Module = LdrEntry;
-
-    /*  Cleanup  */
-    ExFreePool(ModuleLoadBase);
-
-    if (ModuleObject) *ModuleObject = Module;
-    if (ImageBaseAddress) *ImageBaseAddress = Module->DllBase;
-
-    /* Hook for KDB on loading a driver. */
-    KDB_LOADDRIVER_HOOK(FileName, Module);
-
-    return(STATUS_SUCCESS);
-}
-
 /* EOF */

Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=25883&r1=25882&r2=25883&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c (original)
+++ trunk/reactos/ntoskrnl/mm/section.c Fri Feb 23 08:39:42 2007
@@ -3292,7 +3292,7 @@
    Status = ObReferenceObjectByHandle(FileHandle,
                                       FileAccess,
                                       IoFileObjectType,
-                                      UserMode,
+                                      ExGetPreviousMode(),
                                       (PVOID*)(PVOID)&FileObject,
                                       NULL);
 

Modified: trunk/reactos/ntoskrnl/mm/sysldr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=25883&r1=25882&r2=25883&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/sysldr.c (original)
+++ trunk/reactos/ntoskrnl/mm/sysldr.c Fri Feb 23 08:39:42 2007
@@ -20,6 +20,24 @@
 KMUTANT MmSystemLoadLock;
 
 /* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+MiProcessLoaderEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+                     IN BOOLEAN Insert)
+{
+    KIRQL OldIrql;
+
+    /* Acquire the lock */
+    KeAcquireSpinLock(&PsLoadedModuleSpinLock, &OldIrql);
+
+    /* Insert or remove from the list */
+    Insert ? InsertTailList(&PsLoadedModuleList, &LdrEntry->InLoadOrderLinks) :
+             RemoveEntryList(&LdrEntry->InLoadOrderLinks);
+
+    /* Release the lock */
+    KeReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
+}
 
 VOID
 NTAPI
@@ -1019,3 +1037,469 @@
     ZwClose(SectionHandle);
     return Status;
 }
+
+NTSTATUS
+NTAPI
+MmLoadSystemImage(IN PUNICODE_STRING FileName,
+                  IN PUNICODE_STRING NamePrefix OPTIONAL,
+                  IN PUNICODE_STRING LoadedName OPTIONAL,
+                  IN ULONG Flags,
+                  OUT PVOID *ModuleObject,
+                  OUT PVOID *ImageBaseAddress)
+{
+    PVOID ModuleLoadBase = NULL;
+    NTSTATUS Status;
+    HANDLE FileHandle = NULL;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    FILE_STANDARD_INFORMATION FileStdInfo;
+    IO_STATUS_BLOCK IoStatusBlock;
+    ULONG DriverSize = 0, Size, i;
+    PVOID DriverBase;
+    PIMAGE_SECTION_HEADER SectionHeaders;
+    PIMAGE_NT_HEADERS NtHeader;
+    UNICODE_STRING BaseName, BaseDirectory, PrefixName;
+    PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
+    ULONG EntrySize;
+    PLOAD_IMPORTS LoadedImports = (PVOID)-2;
+    PCHAR MissingApiName, Buffer;
+    PWCHAR MissingDriverName;
+    HANDLE SectionHandle;
+    ACCESS_MASK DesiredAccess;
+    PVOID Section = NULL;
+    BOOLEAN LockOwned = FALSE;
+    PLIST_ENTRY NextEntry;
+    PAGED_CODE();
+
+    /* Detect session-load */
+    if (Flags)
+    {
+        /* Sanity checks */
+        ASSERT(NamePrefix == NULL);
+        ASSERT(LoadedName == NULL);
+
+        /* Make sure the process is in session too */
+        if (!PsGetCurrentProcess()->ProcessInSession) return STATUS_NO_MEMORY;
+    }
+
+    if (ModuleObject) *ModuleObject = NULL;
+    if (ImageBaseAddress) *ImageBaseAddress = NULL;
+
+    /* Allocate a buffer we'll use for names */
+    Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
+    if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Check for a separator */
+    if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
+    {
+        PWCHAR p;
+        ULONG BaseLength;
+
+        /* Loop the path until we get to the base name */
+        p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
+        while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
+
+        /* Get the length */
+        BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
+        BaseLength *= sizeof(WCHAR);
+
+        /* Setup the string */
+        BaseName.Length = (USHORT)BaseLength;
+        BaseName.Buffer = p;
+    }
+    else
+    {
+        /* Otherwise, we already have a base name */
+        BaseName.Length = FileName->Length;
+        BaseName.Buffer = FileName->Buffer;
+    }
+
+    /* Setup the maximum length */
+    BaseName.MaximumLength = BaseName.Length;
+
+    /* Now compute the base directory */
+    BaseDirectory = *FileName;
+    BaseDirectory.Length -= BaseName.Length;
+    BaseDirectory.MaximumLength = BaseDirectory.Length;
+
+    /* And the prefix, which for now is just the name itself */
+    PrefixName = *FileName;
+
+    /* Check if we have a prefix */
+    if (NamePrefix) DPRINT1("Prefixed images are not yet supported!\n");
+
+    /* Check if we already have a name, use it instead */
+    if (LoadedName) BaseName = *LoadedName;
+
+    /* Acquire the load lock */
+LoaderScan:
+    ASSERT(LockOwned == FALSE);
+    LockOwned = TRUE;
+    KeEnterCriticalRegion();
+    KeWaitForSingleObject(&MmSystemLoadLock,
+                          WrVirtualMemory,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    /* Scan the module list */
+    NextEntry = PsLoadedModuleList.Flink;
+    while (NextEntry != &PsLoadedModuleList)
+    {
+        /* Get the entry and compare the names */
+        LdrEntry = CONTAINING_RECORD(NextEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
+        if (RtlEqualUnicodeString(&PrefixName, &LdrEntry->FullDllName, TRUE))
+        {
+            /* Found it, break out */
+            break;
+        }
+
+        /* Keep scanning */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Check if we found the image */
+    if (NextEntry != &PsLoadedModuleList)
+    {
+        /* Check if we had already mapped a section */
+        if (Section)
+        {
+            /* Dereference and clear */
+            ObDereferenceObject(Section);
+            Section = NULL;
+        }
+
+        /* Check if this was supposed to be a session load */
+        if (!Flags)
+        {
+            /* It wasn't, so just return the data */
+            *ModuleObject = LdrEntry;
+            *ImageBaseAddress = LdrEntry->DllBase;
+            Status = STATUS_IMAGE_ALREADY_LOADED;
+        }
+        else
+        {
+            /* We don't support session loading yet */
+            DPRINT1("Unsupported Session-Load!\n");
+            while (TRUE);
+        }
+
+        /* Do cleanup */
+        goto Quickie;
+    }
+    else if (!Section)
+    {
+        /* It wasn't loaded, and we didn't have a previous attempt */
+        KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
+        KeLeaveCriticalRegion();
+        LockOwned = FALSE;
+
+        /* Check if KD is enabled */
+        if ((KdDebuggerEnabled) && !(KdDebuggerNotPresent))
+        {
+            /* FIXME: Attempt to get image from KD */
+        }
+
+        /* We don't have a valid entry */
+        LdrEntry = NULL;
+
+        /* Setup image attributes */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   FileName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+
+        /* Open the image */
+        Status = ZwOpenFile(&FileHandle,
+                            FILE_EXECUTE,
+                            &ObjectAttributes,
+                            &IoStatusBlock,
+                            FILE_SHARE_READ | FILE_SHARE_DELETE,
+                            FILE_SYNCHRONOUS_IO_NONALERT);
+        if (!NT_SUCCESS(Status)) goto Quickie;
+
+        /* Validate it */
+        Status = MmCheckSystemImage(FileHandle, FALSE);
+        if ((Status == STATUS_IMAGE_CHECKSUM_MISMATCH) ||
+            (Status == STATUS_IMAGE_MP_UP_MISMATCH) ||
+            (Status == STATUS_INVALID_IMAGE_FORMAT))
+        {
+            /* Fail loading */
+            goto Quickie;
+        }
+
+        /* Get image size */
+        Status = ZwQueryInformationFile(FileHandle,
+                                        &IoStatusBlock,
+                                        &FileStdInfo,
+                                        sizeof(FileStdInfo),
+                                        FileStandardInformation);
+        if (!NT_SUCCESS(Status)) goto Quickie;
+
+        /* Allocate memory for image */
+        ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+                                               FileStdInfo.EndOfFile.u.LowPart,
+                                               TAG_DRIVER_MEM);
+
+        /* Read the image */
+        Status = ZwReadFile(FileHandle,
+                            0,
+                            0,
+                            0,
+                            &IoStatusBlock,
+                            ModuleLoadBase,
+                            FileStdInfo.EndOfFile.u.LowPart,
+                            0,
+                            0);
+        if (!NT_SUCCESS(Status)) goto Quickie;
+
+        /* Check if this is a session-load */
+        if (Flags)
+        {
+            /* Then we only need read and execute */
+            DesiredAccess = SECTION_MAP_READ | SECTION_MAP_EXECUTE;
+        }
+        else
+        {
+            /* Otherwise, we can allow write access */
+            DesiredAccess = SECTION_ALL_ACCESS;
+        }
+
+        /* Initialize the attributes for the section */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   NULL,
+                                   OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                                   NULL,
+                                   NULL);
+
+        /* Create the section */
+        Status = ZwCreateSection(&SectionHandle,
+                                 DesiredAccess,
+                                 &ObjectAttributes,
+                                 NULL,
+                                 PAGE_EXECUTE,
+                                 SEC_IMAGE,
+                                 FileHandle);
+        if (!NT_SUCCESS(Status)) goto Quickie;
+
+        /* Now get the section pointer */
+        Status = ObReferenceObjectByHandle(SectionHandle,
+                                           SECTION_MAP_EXECUTE,
+                                           MmSectionObjectType,
+                                           KernelMode,
+                                           &Section,
+                                           NULL);
+        ZwClose(SectionHandle);
+        if (!NT_SUCCESS(Status)) goto Quickie;
+
+        /* Check if this was supposed to be a session-load */
+        if (Flags)
+        {
+            /* We don't support session loading yet */
+            DPRINT1("Unsupported Session-Load!\n");
+            while (TRUE);
+        }
+
+        /* Check the loader list again, we should end up in the path below */
+        goto LoaderScan;
+    }
+    else
+    {
+        /* We don't have a valid entry */
+        LdrEntry = NULL;
+    }
+
+    /* We should have a valid module base */
+    ASSERT(ModuleLoadBase != NULL);
+
+    /*  Get header pointers  */
+    NtHeader = RtlImageNtHeader(ModuleLoadBase);
+
+    /* Get header pointers */
+    SectionHeaders = IMAGE_FIRST_SECTION(NtHeader);
+
+    /*  Determine the size of the module  */
+    for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
+    {
+        /* Skip this section if we're not supposed to load it */
+        if (!(SectionHeaders[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+        {
+            /* Add the size of this section into the total size */
+            Size = SectionHeaders[i].VirtualAddress +
+                   SectionHeaders[i].Misc.VirtualSize;
+            DriverSize = max(DriverSize, Size);
+        }
+    }
+
+    /* Round up the driver size to section alignment */
+    DriverSize = ROUND_UP(DriverSize, NtHeader->OptionalHeader.SectionAlignment);
+
+    /*  Allocate a virtual section for the module  */
+    DriverBase = MmAllocateSection(DriverSize, NULL);
+
+    /* Copy headers over */
+    RtlCopyMemory(DriverBase,
+                  ModuleLoadBase,
+                  NtHeader->OptionalHeader.SizeOfHeaders);
+
+    /*  Copy image sections into virtual section  */
+    for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
+    {
+        /* Get the size of this section and check if it's valid and on-disk */
+        Size = SectionHeaders[i].VirtualAddress +
+               SectionHeaders[i].Misc.VirtualSize;
+        if ((Size <= DriverSize) && (SectionHeaders[i].SizeOfRawData))
+        {
+            /* Copy the data from the disk to the image */
+            RtlCopyMemory((PVOID)((ULONG_PTR)DriverBase +
+                                  SectionHeaders[i].VirtualAddress),
+                          (PVOID)((ULONG_PTR)ModuleLoadBase +
+                                  SectionHeaders[i].PointerToRawData),
+                          SectionHeaders[i].Misc.VirtualSize >
+                          SectionHeaders[i].SizeOfRawData ?
+                          SectionHeaders[i].SizeOfRawData :
+                          SectionHeaders[i].Misc.VirtualSize);
+        }
+    }
+
+    /* Relocate the driver */
+    Status = LdrRelocateImageWithBias(DriverBase,
+                                      0,
+                                      "SYSLDR",
+                                      STATUS_SUCCESS,
+                                      STATUS_CONFLICTING_ADDRESSES,
+                                      STATUS_INVALID_IMAGE_FORMAT);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Calculate the size we'll need for the entry and allocate it */
+    EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
+                BaseName.Length +
+                sizeof(UNICODE_NULL);
+
+    /* Allocate the entry */
+    LdrEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_MODULE_OBJECT);
+    if (!LdrEntry)
+    {
+        /* Fail */
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto Quickie;
+    }
+
+    /* Setup the entry */
+    LdrEntry->Flags = LDRP_LOAD_IN_PROGRESS;
+    LdrEntry->LoadCount = 1;
+    LdrEntry->LoadedImports = LoadedImports;
+    LdrEntry->PatchInformation = NULL;
+
+    /* Check the version */
+    if ((NtHeader->OptionalHeader.MajorOperatingSystemVersion >= 5) &&
+        (NtHeader->OptionalHeader.MajorImageVersion >= 5))
+    {
+        /* Mark this image as a native image */
+        LdrEntry->Flags |= 0x80000000;
+    }
+
+    /* Setup the rest of the entry */
+    LdrEntry->DllBase = DriverBase;
+    LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)DriverBase +
+                                   NtHeader->OptionalHeader.AddressOfEntryPoint);
+    LdrEntry->SizeOfImage = DriverSize;
+    LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum;
+    LdrEntry->SectionPointer = LdrEntry;
+
+    /* Now write the DLL name */
+    LdrEntry->BaseDllName.Buffer = (PVOID)(LdrEntry + 1);
+    LdrEntry->BaseDllName.Length = BaseName.Length;
+    LdrEntry->BaseDllName.MaximumLength = BaseName.Length;
+
+    /* Copy and null-terminate it */
+    RtlCopyMemory(LdrEntry->BaseDllName.Buffer,
+                  BaseName.Buffer,
+                  BaseName.Length);
+    LdrEntry->BaseDllName.Buffer[BaseName.Length / 2] = UNICODE_NULL;
+
+    /* Now allocate the full name */
+    LdrEntry->FullDllName.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                         PrefixName.Length +
+                                                         sizeof(UNICODE_NULL),
+                                                         TAG_LDR_WSTR);
+    if (!LdrEntry->FullDllName.Buffer)
+    {
+        /* Don't fail, just set it to zero */
+        LdrEntry->FullDllName.Length = 0;
+        LdrEntry->FullDllName.MaximumLength = 0;
+    }
+    else
+    {
+        /* Set it up */
+        LdrEntry->FullDllName.Length = PrefixName.Length;
+        LdrEntry->FullDllName.MaximumLength = PrefixName.Length;
+
+        /* Copy and null-terminate */
+        RtlCopyMemory(LdrEntry->FullDllName.Buffer,
+                      PrefixName.Buffer,
+                      PrefixName.Length);
+        LdrEntry->FullDllName.Buffer[PrefixName.Length / 2] = UNICODE_NULL;
+    }
+
+    /* Add the entry */
+    MiProcessLoaderEntry(LdrEntry, TRUE);
+
+    /* Resolve imports */
+    MissingApiName = Buffer;
+    Status = MiResolveImageReferences(DriverBase,
+                                      &BaseDirectory,
+                                      NULL,
+                                      &MissingApiName,
+                                      &MissingDriverName,
+                                      &LoadedImports);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        MiProcessLoaderEntry(LdrEntry, FALSE);
+
+        /* Check if we need to free the name */
+        if (LdrEntry->FullDllName.Buffer)
+        {
+            /* Free it */
+            ExFreePool(LdrEntry->FullDllName.Buffer);
+        }
+
+        /* Free the entry itself */
+        ExFreePool(LdrEntry);
+        LdrEntry = NULL;
+        goto Quickie;
+    }
+
+    if (ModuleObject) *ModuleObject = LdrEntry;
+    if (ImageBaseAddress) *ImageBaseAddress = LdrEntry->DllBase;
+
+    /* Hook for KDB on loading a driver. */
+    KDB_LOADDRIVER_HOOK(FileName, LdrEntry);
+
+Quickie:
+    /* If we have a file handle, close it */
+    if (FileHandle) ZwClose(FileHandle);
+
+    /* Cleanup */
+    if (ModuleLoadBase) ExFreePool(ModuleLoadBase);
+
+    /* Check if we have the lock acquired */
+    if (LockOwned)
+    {
+        /* Release the lock */
+        KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
+        KeLeaveCriticalRegion();
+        LockOwned = FALSE;
+    }
+
+    /* Check if we had a prefix */
+    if (NamePrefix) ExFreePool(PrefixName.Buffer);
+
+    /* Free the name buffer and return status */
+    ExFreePool(Buffer);
+    return Status;
+}
+




More information about the Ros-diffs mailing list