[ros-diffs] [akorotaev] 31572: Fix some bugs. Now it bugchecks.

akorotaev at svn.reactos.org akorotaev at svn.reactos.org
Wed Jan 2 22:49:20 CET 2008


Author: akorotaev
Date: Thu Jan  3 00:49:19 2008
New Revision: 31572

URL: http://svn.reactos.org/svn/reactos?rev=31572&view=rev
Log:
Fix some bugs. Now it bugchecks.

Added:
    branches/cache_manager_rewrite/mm/sysldr.c   (with props)
Modified:
    branches/cache_manager_rewrite/mm/mminit.c
    branches/cache_manager_rewrite/mm/section.c

Modified: branches/cache_manager_rewrite/mm/mminit.c
URL: http://svn.reactos.org/svn/reactos/branches/cache_manager_rewrite/mm/mminit.c?rev=31572&r1=31571&r2=31572&view=diff
==============================================================================
--- branches/cache_manager_rewrite/mm/mminit.c (original)
+++ branches/cache_manager_rewrite/mm/mminit.c Thu Jan  3 00:49:19 2008
@@ -493,29 +493,10 @@
     return TRUE;
 }
 
-#if 0
-
-VOID static
-MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
-                     PFN_TYPE Page, SWAPENTRY SwapEntry,
-                     BOOLEAN Dirty)
-{
-   ASSERT(SwapEntry == 0);
-   if (Page != 0)
-   {
-      MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
-   }
-}
-
 VOID
 NTAPI
 MiFreeInitMemory(VOID)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
-                         (PVOID)&_init_start__,
-                         MiFreeInitMemoryPage,
-                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
-#endif

Modified: branches/cache_manager_rewrite/mm/section.c
URL: http://svn.reactos.org/svn/reactos/branches/cache_manager_rewrite/mm/section.c?rev=31572&r1=31571&r2=31572&view=diff
==============================================================================
--- branches/cache_manager_rewrite/mm/section.c (original)
+++ branches/cache_manager_rewrite/mm/section.c Thu Jan  3 00:49:19 2008
@@ -3197,6 +3197,7 @@
    OBJECT_ATTRIBUTES Obj;
    UNICODE_STRING Name = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
    LARGE_INTEGER SectionSize;
+   HANDLE Handle;
 
    /*
     * Create the section mapping physical memory
@@ -3225,11 +3226,12 @@
                            SECTION_ALL_ACCESS,
                            0,
                            NULL,
-                           NULL);
+                           &Handle);
    if (!NT_SUCCESS(Status))
    {
       ObDereferenceObject(PhysSection);
    }
+   ObCloseHandle(Handle, KernelMode);
    PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY;
    PhysSection->Segment->Flags &= ~MM_PAGEFILE_SEGMENT;
 

Added: branches/cache_manager_rewrite/mm/sysldr.c
URL: http://svn.reactos.org/svn/reactos/branches/cache_manager_rewrite/mm/sysldr.c?rev=31572&view=auto
==============================================================================
--- branches/cache_manager_rewrite/mm/sysldr.c (added)
+++ branches/cache_manager_rewrite/mm/sysldr.c Thu Jan  3 00:49:19 2008
@@ -1,0 +1,2009 @@
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            ntoskrnl/mm/sysldr.c
+* PURPOSE:         Contains the Kernel Loader (SYSLDR) for loading PE files.
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
+*/
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GCC's incompetence strikes again */
+FORCEINLINE
+VOID
+sprintf_nt(IN PCHAR Buffer,
+           IN PCHAR Format,
+           IN ...)
+{
+    va_list ap;
+    va_start(ap, Format);
+    vsprintf(Buffer, Format, ap);
+    va_end(ap);
+}
+
+/* GLOBALS *******************************************************************/
+
+LIST_ENTRY PsLoadedModuleList;
+KSPIN_LOCK PsLoadedModuleSpinLock;
+ULONG PsNtosImageBase;
+KMUTANT MmSystemLoadLock;
+extern ULONG NtGlobalFlag;
+
+/* FUNCTIONS *****************************************************************/
+
+PVOID
+NTAPI
+MiCacheImageSymbols(IN PVOID BaseAddress)
+{
+    ULONG DebugSize;
+    PVOID DebugDirectory = NULL;
+    PAGED_CODE();
+
+    /* Make sure it's safe to access the image */
+    _SEH_TRY
+    {
+        /* Get the debug directory */
+        DebugDirectory = RtlImageDirectoryEntryToData(BaseAddress,
+                                                      TRUE,
+                                                      IMAGE_DIRECTORY_ENTRY_DEBUG,
+                                                      &DebugSize);
+    }
+    _SEH_HANDLE
+    {
+        /* Nothing */
+    }
+    _SEH_END;
+
+    /* Return the directory */
+    return DebugDirectory;
+}
+
+VOID
+NTAPI
+MiFreeBootDriverMemory(PVOID BaseAddress,
+                       ULONG Length)
+{
+    ULONG i;
+
+    /* Loop each page */
+    for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
+    {
+        /* Free the page */
+        MmDeleteVirtualMapping(NULL,
+                               (PVOID)((ULONG_PTR)BaseAddress + i * PAGE_SIZE),
+                               TRUE,
+                               NULL,
+                               NULL);
+    }
+}
+
+NTSTATUS
+NTAPI
+MiLoadImageSection(IN OUT PVOID *SectionPtr,
+                   OUT PVOID *ImageBase,
+                   IN PUNICODE_STRING FileName,
+                   IN BOOLEAN SessionLoad,
+                   IN PLDR_DATA_TABLE_ENTRY LdrEntry)
+{
+    PROS_SECTION_OBJECT Section = *SectionPtr;
+    NTSTATUS Status;
+    PEPROCESS Process;
+    PVOID Base = NULL;
+    SIZE_T ViewSize = 0;
+    KAPC_STATE ApcState;
+    LARGE_INTEGER SectionOffset = {{0}};
+    BOOLEAN LoadSymbols = FALSE;
+    ULONG DriverSize;
+    PVOID DriverBase;
+    PAGED_CODE();
+
+    /* Detect session load */
+    if (SessionLoad)
+    {
+        /* Fail */
+        DPRINT1("Session loading not yet supported!\n");
+        while (TRUE);
+    }
+
+    /* Not session load, shouldn't have an entry */
+    ASSERT(LdrEntry == NULL);
+
+    /* Attach to the system process */
+    KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
+
+    /* Check if we need to load symbols */
+    if (NtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD)
+    {
+        /* Yes we do */
+        LoadSymbols = TRUE;
+        NtGlobalFlag &= ~FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
+    }
+
+    /* Map the driver */
+    Process = PsGetCurrentProcess();
+    Status = MmMapViewOfSection(Section,
+                                Process,
+                                &Base,
+                                0,
+                                0,
+                                &SectionOffset,
+                                &ViewSize,
+                                ViewUnmap,
+                                0,
+                                PAGE_EXECUTE);
+
+    /* Re-enable the flag */
+    if (LoadSymbols) NtGlobalFlag |= FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
+
+    /* Check if we failed with distinguished status code */
+    if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)
+    {
+        /* Change it to something more generic */
+        Status = STATUS_INVALID_IMAGE_FORMAT;
+    }
+
+    /* Now check if we failed */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Detach and return */
+        KeUnstackDetachProcess(&ApcState);
+        return Status;
+    }
+
+    /* Get the driver size */
+    DriverSize = Section->ImageSection->ImageSize;
+
+    /*  Allocate a virtual section for the module  */
+    DriverBase = MmAllocateSection(DriverSize, NULL);
+    *ImageBase = DriverBase;
+
+    /* Copy the image */
+    RtlCopyMemory(DriverBase, Base, DriverSize);
+
+    /* Now unmap the view */
+    Status = MmUnmapViewOfSection(Process, Base);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Detach and return status */
+    KeUnstackDetachProcess(&ApcState);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+MiDereferenceImports(IN PLOAD_IMPORTS ImportList)
+{
+    SIZE_T i;
+
+    /* Check if there's no imports or if we're a boot driver */
+    if ((ImportList == (PVOID)-1) ||
+        (ImportList == (PVOID)-2) ||
+        (ImportList->Count == 0))
+    {
+        /* Then there's nothing to do */
+        return STATUS_SUCCESS;
+    }
+
+    /* Otherwise, FIXME */
+    DPRINT1("%u imports not dereferenced!\n", ImportList->Count);
+    for (i = 0; i < ImportList->Count; i++)
+    {
+        DPRINT1("%wZ <%wZ>\n", &ImportList->Entry[i]->FullDllName, &ImportList->Entry[i]->BaseDllName);
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+VOID
+NTAPI
+MiClearImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
+{
+    PAGED_CODE();
+
+    /* Check if there's no imports or we're a boot driver or only one entry */
+    if ((LdrEntry->LoadedImports == (PVOID)-1) ||
+        (LdrEntry->LoadedImports == (PVOID)-2) ||
+        ((ULONG_PTR)LdrEntry->LoadedImports & 1))
+    {
+        /* Nothing to do */
+        return;
+    }
+
+    /* Otherwise, free the import list */
+    ExFreePool(LdrEntry->LoadedImports);
+}
+
+PVOID
+NTAPI
+MiFindExportedRoutineByName(IN PVOID DllBase,
+                            IN PANSI_STRING ExportName)
+{
+    PULONG NameTable;
+    PUSHORT OrdinalTable;
+    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
+    LONG Low = 0, Mid = 0, High, Ret;
+    USHORT Ordinal;
+    PVOID Function;
+    ULONG ExportSize;
+    PULONG ExportTable;
+    PAGED_CODE();
+
+    /* Get the export directory */
+    ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
+                                                   TRUE,
+                                                   IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                                   &ExportSize);
+    if (!ExportDirectory) return NULL;
+
+    /* Setup name tables */
+    NameTable = (PULONG)((ULONG_PTR)DllBase +
+                         ExportDirectory->AddressOfNames);
+    OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
+                             ExportDirectory->AddressOfNameOrdinals);
+
+    /* Do a binary search */
+    High = ExportDirectory->NumberOfNames - 1;
+    while (High >= Low)
+    {
+        /* Get new middle value */
+        Mid = (Low + High) >> 1;
+
+        /* Compare name */
+        Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]);
+        if (Ret < 0)
+        {
+            /* Update high */
+            High = Mid - 1;
+        }
+        else if (Ret > 0)
+        {
+            /* Update low */
+            Low = Mid + 1;
+        }
+        else
+        {
+            /* We got it */
+            break;
+        }
+    }
+
+    /* Check if we couldn't find it */
+    if (High < Low) return NULL;
+
+    /* Otherwise, this is the ordinal */
+    Ordinal = OrdinalTable[Mid];
+
+    /* Resolve the address and write it */
+    ExportTable = (PULONG)((ULONG_PTR)DllBase +
+                           ExportDirectory->AddressOfFunctions);
+    Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
+
+    /* We found it! */
+    ASSERT((Function > (PVOID)ExportDirectory) &&
+           (Function < (PVOID)((ULONG_PTR)ExportDirectory + ExportSize)));
+    return Function;
+}
+
+PVOID
+NTAPI
+MiLocateExportName(IN PVOID DllBase,
+                   IN PCHAR ExportName)
+{
+    PULONG NameTable;
+    PUSHORT OrdinalTable;
+    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
+    LONG Low = 0, Mid = 0, High, Ret;
+    USHORT Ordinal;
+    PVOID Function;
+    ULONG ExportSize;
+    PULONG ExportTable;
+    PAGED_CODE();
+
+    /* Get the export directory */
+    ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
+                                                   TRUE,
+                                                   IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                                   &ExportSize);
+    if (!ExportDirectory) return NULL;
+
+    /* Setup name tables */
+    NameTable = (PULONG)((ULONG_PTR)DllBase +
+                         ExportDirectory->AddressOfNames);
+    OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
+                             ExportDirectory->AddressOfNameOrdinals);
+
+    /* Do a binary search */
+    High = ExportDirectory->NumberOfNames - 1;
+    while (High >= Low)
+    {
+        /* Get new middle value */
+        Mid = (Low + High) >> 1;
+
+        /* Compare name */
+        Ret = strcmp(ExportName, (PCHAR)DllBase + NameTable[Mid]);
+        if (Ret < 0)
+        {
+            /* Update high */
+            High = Mid - 1;
+        }
+        else if (Ret > 0)
+        {
+            /* Update low */
+            Low = Mid + 1;
+        }
+        else
+        {
+            /* We got it */
+            break;
+        }
+    }
+
+    /* Check if we couldn't find it */
+    if (High < Low) return NULL;
+
+    /* Otherwise, this is the ordinal */
+    Ordinal = OrdinalTable[Mid];
+
+    /* Resolve the address and write it */
+    ExportTable = (PULONG)((ULONG_PTR)DllBase +
+                           ExportDirectory->AddressOfFunctions);
+    Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
+
+    /* Check if the function is actually a forwarder */
+    if (((ULONG_PTR)Function > (ULONG_PTR)ExportDirectory) &&
+        ((ULONG_PTR)Function < ((ULONG_PTR)ExportDirectory + ExportSize)))
+    {
+        /* It is, fail */
+        return NULL;
+    }
+
+    /* We found it */
+    return Function;
+}
+
+NTSTATUS
+NTAPI
+MmCallDllInitialize(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+                    IN PLIST_ENTRY ListHead)
+{
+    PMM_DLL_INITIALIZE DllInit;
+
+    /* Try to see if the image exports a DllInitialize routine */
+    DllInit = (PMM_DLL_INITIALIZE)MiLocateExportName(LdrEntry->DllBase,
+                                                     "DllInitialize");
+    if (!DllInit) return STATUS_SUCCESS;
+
+    /* FIXME: TODO */
+    DPRINT1("DllInitialize not called!\n");
+    return STATUS_UNSUCCESSFUL;
+}
+
+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
+MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+               IN PVOID OldBase,
+               IN PVOID NewBase,
+               IN ULONG Size)
+{
+    ULONG_PTR OldBaseTop, Delta;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PLIST_ENTRY NextEntry;
+    ULONG ImportSize;
+    PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
+    PULONG ImageThunk;
+
+    /* Calculate the top and delta */
+    OldBaseTop = (ULONG_PTR)OldBase + Size - 1;
+    Delta = (ULONG_PTR)NewBase - (ULONG_PTR)OldBase;
+
+    /* Loop the loader block */
+    for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
+         NextEntry != &LoaderBlock->LoadOrderListHead;
+         NextEntry = NextEntry->Flink)
+    {
+        /* Get the loader entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
+
+        /* Get the import table */
+        ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+                                                        TRUE,
+                                                        IMAGE_DIRECTORY_ENTRY_IMPORT,
+                                                        &ImportSize);
+        if (!ImportDescriptor) continue;
+
+        /* Make sure we have an IAT */
+        DPRINT("[Mm0]: Updating thunks in: %wZ\n", &LdrEntry->BaseDllName);
+        while ((ImportDescriptor->Name) &&
+               (ImportDescriptor->OriginalFirstThunk))
+        {
+            /* Get the image thunk */
+            ImageThunk = (PVOID)((ULONG_PTR)LdrEntry->DllBase +
+                                 ImportDescriptor->FirstThunk);
+            while (*ImageThunk)
+            {
+                /* Check if it's within this module */
+                if ((*ImageThunk >= (ULONG_PTR)OldBase) && (*ImageThunk <= OldBaseTop))
+                {
+                    /* Relocate it */
+                    DPRINT("[Mm0]: Updating IAT at: %p. Old Entry: %p. New Entry: %p.\n",
+                            ImageThunk, *ImageThunk, *ImageThunk + Delta);
+                    *ImageThunk += Delta;
+                }
+
+                /* Go to the next thunk */
+                ImageThunk++;
+            }
+
+            /* Go to the next import */
+            ImportDescriptor++;
+        }
+    }
+}
+
+NTSTATUS
+NTAPI
+MiSnapThunk(IN PVOID DllBase,
+            IN PVOID ImageBase,
+            IN PIMAGE_THUNK_DATA Name,
+            IN PIMAGE_THUNK_DATA Address,
+            IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
+            IN ULONG ExportSize,
+            IN BOOLEAN SnapForwarder,
+            OUT PCHAR *MissingApi)
+{
+    BOOLEAN IsOrdinal;
+    USHORT Ordinal;
+    PULONG NameTable;
+    PUSHORT OrdinalTable;
+    PIMAGE_IMPORT_BY_NAME NameImport;
+    USHORT Hint;
+    ULONG Low = 0, Mid = 0, High;
+    LONG Ret;
+    NTSTATUS Status;
+    PCHAR MissingForwarder;
+    CHAR NameBuffer[MAXIMUM_FILENAME_LENGTH];
+    PULONG ExportTable;
+    ANSI_STRING DllName;
+    UNICODE_STRING ForwarderName;
+    PLIST_ENTRY NextEntry;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    ULONG ForwardExportSize;
+    PIMAGE_EXPORT_DIRECTORY ForwardExportDirectory;
+    PIMAGE_IMPORT_BY_NAME ForwardName;
+    ULONG ForwardLength;
+    IMAGE_THUNK_DATA ForwardThunk;
+    PAGED_CODE();
+
+    /* Check if this is an ordinal */
+    IsOrdinal = IMAGE_SNAP_BY_ORDINAL(Name->u1.Ordinal);
+    if ((IsOrdinal) && !(SnapForwarder))
+    {
+        /* Get the ordinal number and set it as missing */
+        Ordinal = (USHORT)(IMAGE_ORDINAL(Name->u1.Ordinal) -
+                           ExportDirectory->Base);
+        *MissingApi = (PCHAR)(ULONG_PTR)Ordinal;
+    }
+    else
+    {
+        /* Get the VA if we don't have to snap */
+        if (!SnapForwarder) Name->u1.AddressOfData += (ULONG_PTR)ImageBase;
+        NameImport = (PIMAGE_IMPORT_BY_NAME)Name->u1.AddressOfData;
+
+        /* Copy the procedure name */
+        strncpy(*MissingApi,
+                (PCHAR)&NameImport->Name[0],
+                MAXIMUM_FILENAME_LENGTH - 1);
+
+        /* Setup name tables */
+        DPRINT("Import name: %s\n", NameImport->Name);
+        NameTable = (PULONG)((ULONG_PTR)DllBase +
+                             ExportDirectory->AddressOfNames);
+        OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
+                                 ExportDirectory->AddressOfNameOrdinals);
+
+        /* Get the hint and check if it's valid */
+        Hint = NameImport->Hint;
+        if ((Hint < ExportDirectory->NumberOfNames) &&
+            !(strcmp((PCHAR) NameImport->Name, (PCHAR)DllBase + NameTable[Hint])))
+        {
+            /* We have a match, get the ordinal number from here */
+            Ordinal = OrdinalTable[Hint];
+        }
+        else
+        {
+            /* Do a binary search */
+            High = ExportDirectory->NumberOfNames - 1;
+            while (High >= Low)
+            {
+                /* Get new middle value */
+                Mid = (Low + High) >> 1;
+
+                /* Compare name */
+                Ret = strcmp((PCHAR)NameImport->Name, (PCHAR)DllBase + NameTable[Mid]);
+                if (Ret < 0)
+                {
+                    /* Update high */
+                    High = Mid - 1;
+                }
+                else if (Ret > 0)
+                {
+                    /* Update low */
+                    Low = Mid + 1;
+                }
+                else
+                {
+                    /* We got it */
+                    break;
+                }
+            }
+
+            /* Check if we couldn't find it */
+            if (High < Low) return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
+
+            /* Otherwise, this is the ordinal */
+            Ordinal = OrdinalTable[Mid];
+        }
+    }
+
+    /* Check if the ordinal is invalid */
+    if (Ordinal >= ExportDirectory->NumberOfFunctions)
+    {
+        /* Fail */
+        Status = STATUS_DRIVER_ORDINAL_NOT_FOUND;
+    }
+    else
+    {
+        /* In case the forwarder is missing */
+        MissingForwarder = NameBuffer;
+
+        /* Resolve the address and write it */
+        ExportTable = (PULONG)((ULONG_PTR)DllBase +
+                               ExportDirectory->AddressOfFunctions);
+        Address->u1.Function = (ULONG_PTR)DllBase + ExportTable[Ordinal];
+
+        /* Assume success from now on */
+        Status = STATUS_SUCCESS;
+
+        /* Check if the function is actually a forwarder */
+        if ((Address->u1.Function > (ULONG_PTR)ExportDirectory) &&
+            (Address->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize)))
+        {
+            /* Now assume failure in case the forwarder doesn't exist */
+            Status = STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
+
+            /* Build the forwarder name */
+            DllName.Buffer = (PCHAR)Address->u1.Function;
+            DllName.Length = strchr(DllName.Buffer, '.') -
+                             DllName.Buffer +
+                             sizeof(ANSI_NULL);
+            DllName.MaximumLength = DllName.Length;
+
+            /* Convert it */
+            if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ForwarderName,
+                                                         &DllName,
+                                                         TRUE)))
+            {
+                /* We failed, just return an error */
+                return Status;
+            }
+
+            /* Loop the module list */
+            NextEntry = PsLoadedModuleList.Flink;
+            while (NextEntry != &PsLoadedModuleList)
+            {
+                /* Get the loader entry */
+                LdrEntry = CONTAINING_RECORD(NextEntry,
+                                             LDR_DATA_TABLE_ENTRY,
+                                             InLoadOrderLinks);
+
+                /* Check if it matches */
+                if (RtlPrefixString((PSTRING)&ForwarderName,
+                                    (PSTRING)&LdrEntry->BaseDllName,
+                                    TRUE))
+                {
+                    /* Get the forwarder export directory */
+                    ForwardExportDirectory =
+                        RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+                                                     TRUE,
+                                                     IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                                     &ForwardExportSize);
+                    if (!ForwardExportDirectory) break;
+
+                    /* Allocate a name entry */
+                    ForwardLength = strlen(DllName.Buffer + DllName.Length) +
+                                    sizeof(ANSI_NULL);
+                    ForwardName = ExAllocatePoolWithTag(PagedPool,
+                                                        sizeof(*ForwardName) +
+                                                        ForwardLength,
+                                                        TAG_LDR_WSTR);
+                    if (!ForwardName) break;
+
+                    /* Copy the data */
+                    RtlCopyMemory(&ForwardName->Name[0],
+                                  DllName.Buffer + DllName.Length,
+                                  ForwardLength);
+                    ForwardName->Hint = 0;
+
+                    /* Set the new address */
+                    *(PULONG)&ForwardThunk.u1.AddressOfData = (ULONG)ForwardName;
+
+                    /* Snap the forwarder */
+                    Status = MiSnapThunk(LdrEntry->DllBase,
+                                         ImageBase,
+                                         &ForwardThunk,
+                                         &ForwardThunk,
+                                         ForwardExportDirectory,
+                                         ForwardExportSize,
+                                         TRUE,
+                                         &MissingForwarder);
+
+                    /* Free the forwarder name and set the thunk */
+                    ExFreePool(ForwardName);
+                    Address->u1 = ForwardThunk.u1;
+                    break;
+                }
+
+                /* Go to the next entry */
+                NextEntry = NextEntry->Flink;
+            }
+
+            /* Free the name */
+            RtlFreeUnicodeString(&ForwarderName);
+        }
+    }
+
+    /* Return status */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+MmUnloadSystemImage(IN PVOID ImageHandle)
+{
+    PLDR_DATA_TABLE_ENTRY LdrEntry = ImageHandle;
+    PVOID BaseAddress = LdrEntry->DllBase;
+    NTSTATUS Status;
+    ANSI_STRING TempName;
+    BOOLEAN HadEntry = FALSE;
+
+    /* Acquire the loader lock */
+    KeEnterCriticalRegion();
+    KeWaitForSingleObject(&MmSystemLoadLock,
+                          WrVirtualMemory,
+                          KernelMode,
+                          FALSE,
+                          NULL);
+
+    /* Check if this driver was loaded at boot and didn't get imports parsed */
+    if (LdrEntry->LoadedImports == (PVOID)-1) goto Done;
+
+    /* We should still be alive */
+    ASSERT(LdrEntry->LoadCount != 0);
+    LdrEntry->LoadCount--;
+
+    /* Check if we're still loaded */
+    if (LdrEntry->LoadCount) goto Done;
+
+    /* We should cleanup... are symbols loaded */
+    if (LdrEntry->Flags & LDRP_DEBUG_SYMBOLS_LOADED)
+    {
+        /* Create the ANSI name */
+        Status = RtlUnicodeStringToAnsiString(&TempName,
+                                              &LdrEntry->BaseDllName,
+                                              TRUE);
+        if (NT_SUCCESS(Status))
+        {
+            /* Unload the symbols */
+            DbgUnLoadImageSymbols(&TempName, BaseAddress, -1);
+            RtlFreeAnsiString(&TempName);
+        }
+    }
+
+    /* FIXME: Free the driver */
+    //MmFreeSection(LdrEntry->DllBase);
+
+    /* Check if we're linked in */
+    if (LdrEntry->InLoadOrderLinks.Flink)
+    {
+        /* Remove us */
+        MiProcessLoaderEntry(LdrEntry, FALSE);
+        HadEntry = TRUE;
+    }
+
+    /* Dereference and clear the imports */
+    MiDereferenceImports(LdrEntry->LoadedImports);
+    MiClearImports(LdrEntry);
+
+    /* Check if the entry needs to go away */
+    if (HadEntry)
+    {
+        /* Check if it had a name */
+        if (LdrEntry->FullDllName.Buffer)
+        {
+            /* Free it */
+            ExFreePool(LdrEntry->FullDllName.Buffer);
+        }
+
+        /* Check if we had a section */
+        if (LdrEntry->SectionPointer)
+        {
+            /* Dereference it */
+            ObDereferenceObject(LdrEntry->SectionPointer);
+        }
+
+        /* Free the entry */
+        ExFreePool(LdrEntry);
+    }
+
+    /* Release the system lock and return */
+Done:
+    KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE);
+    KeLeaveCriticalRegion();
+    return STATUS_SUCCESS;
+}
+
+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)
+{
+    PCHAR MissingApiBuffer = *MissingApi, ImportName;
+    PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor, CurrentImport;
+    ULONG ImportSize, ImportCount = 0, LoadedImportsSize, ExportSize;
+    PLOAD_IMPORTS LoadedImports, NewImports;
+    ULONG GdiLink, NormalLink, i;
+    BOOLEAN ReferenceNeeded, Loaded;
+    ANSI_STRING TempString;
+    UNICODE_STRING NameString, DllName;
+    PLDR_DATA_TABLE_ENTRY LdrEntry = NULL, DllEntry, ImportEntry = NULL;
+    PVOID ImportBase, DllBase;
+    PLIST_ENTRY NextEntry;
+    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
+    NTSTATUS Status;
+    PIMAGE_THUNK_DATA OrigThunk, FirstThunk;
+    PAGED_CODE();
+    DPRINT("%s - ImageBase: %p. ImageFileDirectory: %wZ\n",
+           __FUNCTION__, ImageBase, ImageFileDirectory);
+
+    /* Assume no imports */
+    *LoadImports = (PVOID)-2;
+
+    /* Get the import descriptor */
+    ImportDescriptor = RtlImageDirectoryEntryToData(ImageBase,
+                                                    TRUE,
+                                                    IMAGE_DIRECTORY_ENTRY_IMPORT,
+                                                    &ImportSize);
+    if (!ImportDescriptor) return STATUS_SUCCESS;
+
+    /* Loop all imports to count them */
+    for (CurrentImport = ImportDescriptor;
+         (CurrentImport->Name) && (CurrentImport->OriginalFirstThunk);
+         CurrentImport++)
+    {
+        /* One more */
+        ImportCount++;
+    }
+
+    /* Make sure we have non-zero imports */
+    if (ImportCount)
+    {
+        /* Calculate and allocate the list we'll need */
+        LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
+        LoadedImports = ExAllocatePoolWithTag(PagedPool,
+                                              LoadedImportsSize,
+                                              TAG_LDR_WSTR);
+        if (LoadedImports)
+        {
+            /* Zero it */
+            RtlZeroMemory(LoadedImports, LoadedImportsSize);
+        }
+    }
+    else
+    {
+        /* No table */
+        LoadedImports = NULL;
+    }
+
+    /* Reset the import count and loop descriptors again */
+    ImportCount = GdiLink = NormalLink = 0;
+    while ((ImportDescriptor->Name) && (ImportDescriptor->OriginalFirstThunk))
+    {
+        /* Get the name */
+        ImportName = (PCHAR)((ULONG_PTR)ImageBase + ImportDescriptor->Name);
+
+        /* Check if this is a GDI driver */
+        GdiLink = GdiLink |
+                  !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1));
+
+        /* We can also allow dxapi */
+        NormalLink = NormalLink |
+                     ((_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) &&
+                      (_strnicmp(ImportName, "dxapi", sizeof("dxapi") - 1)));
+
+        /* Check if this is a valid GDI driver */
+        if ((GdiLink) && (NormalLink))
+        {
+            /* It's not, it's importing stuff it shouldn't be! */
+            MiDereferenceImports(LoadedImports);
+            if (LoadedImports) ExFreePool(LoadedImports);
+            return STATUS_PROCEDURE_NOT_FOUND;
+        }
+
+        /* Check if this is a "core" import, which doesn't get referenced */
+        if (!(_strnicmp(ImportName, "ntoskrnl", sizeof("ntoskrnl") - 1)) ||
+            !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) ||
+            !(_strnicmp(ImportName, "hal", sizeof("hal") - 1)))
+        {
+            /* Don't reference this */
+            ReferenceNeeded = FALSE;
+        }
+        else
+        {
+            /* Reference these modules */
+            ReferenceNeeded = TRUE;
+        }
+
+        /* Now setup a unicode string for the import */
+        RtlInitAnsiString(&TempString, ImportName);
+        Status = RtlAnsiStringToUnicodeString(&NameString, &TempString, TRUE);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Failed */
+            MiDereferenceImports(LoadedImports);
+            if (LoadedImports) ExFreePool(LoadedImports);
+            return Status;
+        }
+
+        /* We don't support name prefixes yet */
+        if (NamePrefix) DPRINT1("Name Prefix not yet supported!\n");
+
+        /* Remember that we haven't loaded the import at this point */
+CheckDllState:
+        Loaded = FALSE;
+        ImportBase = NULL;
+
+        /* Loop the driver list */
+        NextEntry = PsLoadedModuleList.Flink;
+        while (NextEntry != &PsLoadedModuleList)
+        {
+            /* Get the loader entry and compare the name */
+            LdrEntry = CONTAINING_RECORD(NextEntry,
+                                         LDR_DATA_TABLE_ENTRY,
+                                         InLoadOrderLinks);
+            if (RtlEqualUnicodeString(&NameString,
+                                      &LdrEntry->BaseDllName,
+                                      TRUE))
+            {
+                /* Get the base address */
+                ImportBase = LdrEntry->DllBase;
+
+                /* Check if we haven't loaded yet, and we need references */
+                if (!(Loaded) && (ReferenceNeeded))
+                {
+                    /* Make sure we're not already loading */
+                    if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS))
+                    {
+                        /* Increase the load count */
+                        LdrEntry->LoadCount++;
+                    }
+                }
+
+                /* Done, break out */
+                break;
+            }
+
+            /* Go to the next entry */
+            NextEntry = NextEntry->Flink;
+        }
+
+        /* Check if we haven't loaded the import yet */
+        if (!ImportBase)
+        {
+            /* Setup the import DLL name */
+            DllName.MaximumLength = NameString.Length +
+                                    ImageFileDirectory->Length +
+                                    sizeof(UNICODE_NULL);
+            DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                   DllName.MaximumLength,
+                                                   TAG_LDR_WSTR);
+            if (DllName.Buffer)
+            {
+                /* Setup the base length and copy it */
+                DllName.Length = ImageFileDirectory->Length;
+                RtlCopyMemory(DllName.Buffer,
+                              ImageFileDirectory->Buffer,
+                              ImageFileDirectory->Length);
+
+                /* Now add the import name and null-terminate it */
+                RtlAppendStringToString((PSTRING)&DllName,
+                                        (PSTRING)&NameString);
+                DllName.Buffer[(DllName.MaximumLength - 1) / 2] = UNICODE_NULL;
+
+                /* Load the image */
+                Status = MmLoadSystemImage(&DllName,
+                                           NamePrefix,
+                                           NULL,
+                                           0,
+                                           (PVOID)&DllEntry,
+                                           &DllBase);
+                if (NT_SUCCESS(Status))
+                {
+                    /* We can free the DLL Name */
+                    ExFreePool(DllName.Buffer);
+                }
+                else
+                {
+                    /* Fill out the information for the error */
+                    *MissingDriver = DllName.Buffer;
+                    *(PULONG)MissingDriver |= 1;
+                    *MissingApi = NULL;
+                }
+            }
+            else
+            {
+                /* We're out of resources */
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            /* Check if we're OK until now */
+            if (NT_SUCCESS(Status))
+            {
+                /* We're now loaded */
+                Loaded = TRUE;
+
+                /* Sanity check */
+                ASSERT(DllBase = DllEntry->DllBase);
+
+                /* Call the initialization routines */
+                Status = MmCallDllInitialize(DllEntry, &PsLoadedModuleList);
+                if (!NT_SUCCESS(Status))
+                {
+                    /* We failed, unload the image */
+                    MmUnloadSystemImage(DllEntry);
+                    while (TRUE);
+                    Loaded = FALSE;
+                }
+            }
+
+            /* Check if we failed by here */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Cleanup and return */
+                RtlFreeUnicodeString(&NameString);
+                MiDereferenceImports(LoadedImports);
+                if (LoadedImports) ExFreePool(LoadedImports);
+                return Status;
+            }
+
+            /* Loop again to make sure that everything is OK */
+            goto CheckDllState;
+        }
+
+        /* Check if we're support to reference this import */
+        if ((ReferenceNeeded) && (LoadedImports))
+        {
+            /* Make sure we're not already loading */
+            if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS))
+            {
+                /* Add the entry */
+                LoadedImports->Entry[LoadedImports->Count] = LdrEntry;
+                LoadedImports->Count++;
+            }
+        }
+
+        /* Free the import name */
+        RtlFreeUnicodeString(&NameString);
+
+        /* Set the missing driver name and get the export directory */
+        *MissingDriver = LdrEntry->BaseDllName.Buffer;
+        ExportDirectory = RtlImageDirectoryEntryToData(ImportBase,
+                                                       TRUE,
+                                                       IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                                       &ExportSize);
+        if (!ExportDirectory)
+        {
+            /* Cleanup and return */
+            MiDereferenceImports(LoadedImports);
+            if (LoadedImports) ExFreePool(LoadedImports);
+            return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
+        }
+
+        /* Make sure we have an IAT */
+        if (ImportDescriptor->OriginalFirstThunk)
+        {
+            /* Get the first thunks */
+            OrigThunk = (PVOID)((ULONG_PTR)ImageBase +
+                                ImportDescriptor->OriginalFirstThunk);
+            FirstThunk = (PVOID)((ULONG_PTR)ImageBase +
+                                 ImportDescriptor->FirstThunk);
+
+            /* Loop the IAT */
+            while (OrigThunk->u1.AddressOfData)
+            {
+                /* Snap thunk */
+                Status = MiSnapThunk(ImportBase,
+                                     ImageBase,
+                                     OrigThunk++,
+                                     FirstThunk++,
+                                     ExportDirectory,
+                                     ExportSize,
+                                     FALSE,
+                                     MissingApi);
+                if (!NT_SUCCESS(Status))
+                {
+                    /* Cleanup and return */
+                    MiDereferenceImports(LoadedImports);
+                    if (LoadedImports) ExFreePool(LoadedImports);
+                    return Status;
+                }
+
+                /* Reset the buffer */
+                *MissingApi = MissingApiBuffer;
+            }
+        }
+
+        /* Go to the next import */
+        ImportDescriptor++;
+    }
+
+    /* Check if we have an import list */
+    if (LoadedImports)
+    {
+        /* Reset the count again, and loop entries*/
+        ImportCount = 0;
+        for (i = 0; i < LoadedImports->Count; i++)
+        {
+            if (LoadedImports->Entry[i])
+            {
+                /* Got an entry, OR it with 1 in case it's the single entry */
+                ImportEntry = (PVOID)((ULONG_PTR)LoadedImports->Entry[i] | 1);
+                ImportCount++;
+            }
+        }
+
+        /* Check if we had no imports */
+        if (!ImportCount)
+        {
+            /* Free the list and set it to no imports */
+            ExFreePool(LoadedImports);
+            LoadedImports = (PVOID)-2;
+        }
+        else if (ImportCount == 1)
+        {
+            /* Just one entry, we can free the table and only use our entry */
+            ExFreePool(LoadedImports);
+            LoadedImports = (PLOAD_IMPORTS)ImportEntry;
+        }
+        else if (ImportCount != LoadedImports->Count)
+        {
+            /* Allocate a new list */
+            LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T);
+            NewImports = ExAllocatePoolWithTag(PagedPool,
+                                               LoadedImportsSize,
+                                               TAG_LDR_WSTR);
+            if (NewImports)
+            {
+                /* Set count */
+                NewImports->Count = 0;
+
+                /* Loop all the imports */
+                for (i = 0; i < LoadedImports->Count; i++)
+                {
+                    /* Make sure it's valid */
+                    if (LoadedImports->Entry[i])
+                    {
+                        /* Copy it */
+                        NewImports->Entry[NewImports->Count] = LoadedImports->Entry[i];
+                        NewImports->Count++;
+                    }
+                }
+
+                /* Free the old copy */
+                ExFreePool(LoadedImports);
+                LoadedImports = NewImports;
+            }
+        }
+
+        /* Return the list */
+        *LoadImports = LoadedImports;
+    }
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    PLIST_ENTRY NextEntry;
+    ULONG i = 0;
+    PIMAGE_NT_HEADERS NtHeader;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    PIMAGE_FILE_HEADER FileHeader;
+    BOOLEAN ValidRelocs;
+    PIMAGE_DATA_DIRECTORY DataDirectory;
+    PVOID DllBase, NewImageAddress;
+    NTSTATUS Status;
+
+    /* Loop driver list */
+    for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
+         NextEntry != &LoaderBlock->LoadOrderListHead;
+         NextEntry = NextEntry->Flink)
+    {
+        /* Get the loader entry and NT header */
+        LdrEntry = CONTAINING_RECORD(NextEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
+        NtHeader = RtlImageNtHeader(LdrEntry->DllBase);
+
+        /* Debug info */
+        DPRINT("[Mm0]: Driver at: %p ending at: %p for module: %wZ\n",
+                LdrEntry->DllBase,
+                (ULONG_PTR)LdrEntry->DllBase+ LdrEntry->SizeOfImage,
+                &LdrEntry->FullDllName);
+
+        /* Skip kernel and HAL */
+        /* ROS HACK: Skip BOOTVID/KDCOM too */
+        i++;
+        if (i <= 4) continue;
+
+        /* Skip non-drivers */
+        if (!NtHeader) continue;
+
+        /* Get the file header and make sure we can relocate */
+        FileHeader = &NtHeader->FileHeader;
+        if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) continue;
+        if (NtHeader->OptionalHeader.NumberOfRvaAndSizes <
+            IMAGE_DIRECTORY_ENTRY_BASERELOC) continue;
+
+        /* Everything made sense until now, check the relocation section too */
+        DataDirectory = &NtHeader->OptionalHeader.
+                        DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+        if (!DataDirectory->VirtualAddress)
+        {
+            /* We don't really have relocations */
+            ValidRelocs = FALSE;
+        }
+        else
+        {
+            /* Make sure the size is valid */
+            if ((DataDirectory->VirtualAddress + DataDirectory->Size) >
+                LdrEntry->SizeOfImage)
+            {
+                /* They're not, skip */
+                continue;
+            }
+
+            /* We have relocations */
+            ValidRelocs = TRUE;
+        }
+
+        /* Remember the original address */
+        DllBase = LdrEntry->DllBase;
+
+        /*  Allocate a virtual section for the module  */
+        NewImageAddress = MmAllocateSection(LdrEntry->SizeOfImage, NULL);
+        if (!NewImageAddress)
+        {
+            /* Shouldn't happen */
+            DPRINT1("[Mm0]: Couldn't allocate driver section!\n");
+            while (TRUE);
+        }
+
+        /* Sanity check */
+        DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase, NewImageAddress);
+        ASSERT(ExpInitializationPhase == 0);
+
+        /* Now copy the entire driver over */
+        RtlCopyMemory(NewImageAddress, DllBase, LdrEntry->SizeOfImage);
+
+        /* Sanity check */
+        ASSERT(*(PULONG)NewImageAddress == *(PULONG)DllBase);
+
+        /* Set the image base to the address where the loader put it */
+        NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
+        NtHeader = RtlImageNtHeader(NewImageAddress);
+        NtHeader->OptionalHeader.ImageBase = (ULONG_PTR)DllBase;
+
+        /* Check if we had relocations */
+        if (ValidRelocs)
+        {
+            /* Relocate the image */
+            Status = LdrRelocateImageWithBias(NewImageAddress,
+                                              0,
+                                              "SYSLDR",
+                                              STATUS_SUCCESS,
+                                              STATUS_CONFLICTING_ADDRESSES,
+                                              STATUS_INVALID_IMAGE_FORMAT);
+            if (!NT_SUCCESS(Status))
+            {
+                /* This shouldn't happen */
+                DPRINT1("Relocations failed!\n");
+                while (TRUE);
+            }
+        }
+
+        /* Update the loader entry */
+        LdrEntry->DllBase = NewImageAddress;
+
+        /* Update the thunks */
+        DPRINT("[Mm0]: Updating thunks to: %wZ\n", &LdrEntry->BaseDllName);
+        MiUpdateThunks(LoaderBlock,
+                       DllBase,
+                       NewImageAddress,
+                       LdrEntry->SizeOfImage);
+
+        /* Update the loader entry */
+        LdrEntry->Flags |= 0x01000000;
+        LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)NewImageAddress +
+                                NtHeader->OptionalHeader.AddressOfEntryPoint);
+        LdrEntry->SizeOfImage = LdrEntry->SizeOfImage;
+
+        /* Free the old copy */
+        MiFreeBootDriverMemory(DllBase, LdrEntry->SizeOfImage);
+    }
+}
+
+BOOLEAN
+NTAPI
+MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    PLDR_DATA_TABLE_ENTRY LdrEntry, NewEntry;
+    PLIST_ENTRY ListHead, NextEntry;
+    ULONG EntrySize;
+
+    /* Setup the loaded module list and lock */
+    KeInitializeSpinLock(&PsLoadedModuleSpinLock);
+    InitializeListHead(&PsLoadedModuleList);
+
+    /* Get loop variables and the kernel entry */
+    ListHead = &LoaderBlock->LoadOrderListHead;
+    NextEntry = ListHead->Flink;
+    LdrEntry = CONTAINING_RECORD(NextEntry,
+                                 LDR_DATA_TABLE_ENTRY,
+                                 InLoadOrderLinks);
+    PsNtosImageBase = (ULONG)LdrEntry->DllBase;
+
+    /* Loop the loader block */
+    while (NextEntry != ListHead)
+    {
+        /* Get the loader entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
+
+        /* FIXME: ROS HACK. Make sure this is a driver */
+        if (!RtlImageNtHeader(LdrEntry->DllBase))
+        {
+            /* Skip this entry */
+            NextEntry= NextEntry->Flink;
+            continue;
+        }
+
+        /* Calculate the size we'll need and allocate a copy */
+        EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
+                    LdrEntry->BaseDllName.MaximumLength +
+                    sizeof(UNICODE_NULL);
+        NewEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_LDR_WSTR);
+        if (!NewEntry) return FALSE;
+
+        /* Copy the entry over */
+        *NewEntry = *LdrEntry;
+
+        /* Allocate the name */
+        NewEntry->FullDllName.Buffer =
+            ExAllocatePoolWithTag(PagedPool,
+                                  LdrEntry->FullDllName.MaximumLength +
+                                  sizeof(UNICODE_NULL),
+                                  TAG_LDR_WSTR);
+        if (!NewEntry->FullDllName.Buffer) return FALSE;
+
+        /* Set the base name */
+        NewEntry->BaseDllName.Buffer = (PVOID)(NewEntry + 1);
+
+        /* Copy the full and base name */
+        RtlCopyMemory(NewEntry->FullDllName.Buffer,
+                      LdrEntry->FullDllName.Buffer,
+                      LdrEntry->FullDllName.MaximumLength);
+        RtlCopyMemory(NewEntry->BaseDllName.Buffer,
+                      LdrEntry->BaseDllName.Buffer,
+                      LdrEntry->BaseDllName.MaximumLength);
+
+        /* Null-terminate the base name */
+        NewEntry->BaseDllName.Buffer[NewEntry->BaseDllName.Length /
+                                     sizeof(WCHAR)] = UNICODE_NULL;
+
+        /* Insert the entry into the list */
+        InsertTailList(&PsLoadedModuleList, &NewEntry->InLoadOrderLinks);
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Build the import lists for the boot drivers */
+    //MiBuildImportsForBootDrivers();
+
+    /* We're done */
+    return TRUE;
+}
+
+#if 0
+
+BOOLEAN
+NTAPI
+MmVerifyImageIsOkForMpUse(IN PVOID BaseAddress)
+{
+    PIMAGE_NT_HEADERS NtHeader;
+    PAGED_CODE();
+
+    /* Get NT Headers */
+    NtHeader = RtlImageNtHeader(BaseAddress);
+    if (NtHeader)
+    {
+        /* Check if this image is only safe for UP while we have 2+ CPUs */
+        if ((KeNumberProcessors > 1) &&
+            (NtHeader->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY))
+        {
+            /* Fail */
+            return FALSE;
+        }
+    }
+
+    /* Otherwise, it's safe */
+    return TRUE;
+}
+
+NTSTATUS
+NTAPI
+MmCheckSystemImage(IN HANDLE ImageHandle,
+                   IN BOOLEAN PurgeSection)
+{
+    NTSTATUS Status;
+    HANDLE SectionHandle;
+    PVOID ViewBase = NULL;
+    SIZE_T ViewSize = 0;
+    IO_STATUS_BLOCK IoStatusBlock;
+    FILE_STANDARD_INFORMATION FileStandardInfo;
+    KAPC_STATE ApcState;
+    PAGED_CODE();
+
+    /* Create a section for the DLL */
+    Status = ZwCreateSection(&SectionHandle,
+                             SECTION_MAP_EXECUTE,
+                             NULL,
+                             NULL,
+                             PAGE_EXECUTE,
+                             SEC_COMMIT,
+                             ImageHandle);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Make sure we're in the system process */
+    KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
+
+    /* Map it */
+    Status = ZwMapViewOfSection(SectionHandle,
+                                NtCurrentProcess(),
+                                &ViewBase,
+                                0,
+                                0,
+                                NULL,
+                                &ViewSize,
+                                ViewShare,
+                                0,
+                                PAGE_EXECUTE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed, close the handle and return */
+        KeUnstackDetachProcess(&ApcState);
+        ZwClose(SectionHandle);
+        return Status;
+    }
+
+    /* Now query image information */
+    Status = ZwQueryInformationFile(ImageHandle,
+                                    &IoStatusBlock,
+                                    &FileStandardInfo,
+                                    sizeof(FileStandardInfo),
+                                    FileStandardInformation);
+    if ( NT_SUCCESS(Status) )
+    {
+        /* First, verify the checksum */
+        if (!LdrVerifyMappedImageMatchesChecksum(ViewBase,
+                                                 FileStandardInfo.
+                                                 EndOfFile.LowPart,
+                                                 FileStandardInfo.
+                                                 EndOfFile.LowPart))
+        {
+            /* Set checksum failure */
+            Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
+        }
+
+        /* Check that it's a valid SMP image if we have more then one CPU */
+        if (!MmVerifyImageIsOkForMpUse(ViewBase))
+        {
+            /* Otherwise it's not the right image */
+            Status = STATUS_IMAGE_MP_UP_MISMATCH;
+        }
+    }
+
+    /* Unmap the section, close the handle, and return status */
+    ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
+    KeUnstackDetachProcess(&ApcState);
+    ZwClose(SectionHandle);
+    return Status;
+}
+
+#endif
+
+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;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PIMAGE_NT_HEADERS NtHeader;
+    UNICODE_STRING BaseName, BaseDirectory, PrefixName, UnicodeTemp;
+    PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
+    ULONG EntrySize, DriverSize;
+    PLOAD_IMPORTS LoadedImports = (PVOID)-2;
+    PCHAR MissingApiName, Buffer;
+    PWCHAR MissingDriverName;
+    HANDLE SectionHandle;
+    ACCESS_MASK DesiredAccess;
+    PVOID Section = NULL;
+    BOOLEAN LockOwned = FALSE;
+    PLIST_ENTRY NextEntry;
+    IMAGE_INFO ImageInfo;
+    ANSI_STRING AnsiTemp;
+    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 */
+            if (ModuleObject) *ModuleObject = LdrEntry;
+            if (ImageBaseAddress) *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 | OBJ_KERNEL_HANDLE,
+                                   NULL,
+                                   NULL);
+
+        /* Open the image */
+        Status = ZwOpenFile(&FileHandle,
+                            FILE_EXECUTE,
+                            &ObjectAttributes,
+                            &IoStatusBlock,
+                            FILE_SHARE_READ | FILE_SHARE_DELETE,
+                            0);
+        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;
+        }
+
+        /* 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;
+    }
+
+    /* Load the image */
+    Status = MiLoadImageSection(&Section,
+                                &ModuleLoadBase,
+                                FileName,
+                                FALSE,
+                                NULL);
+    ASSERT(Status != STATUS_ALREADY_COMMITTED);
+
+    /* Get the size of the driver */
+    DriverSize = ((PROS_SECTION_OBJECT)Section)->ImageSection->ImageSize;
+
+    /* Make sure we're not being loaded into session space */
+    if (!Flags)
+    {
+        /* Check for success */
+        if (NT_SUCCESS(Status))
+        {
+            /* FIXME: Support large pages for drivers */
+        }
+
+        /* Dereference the section */
+        ObDereferenceObject(Section);
+        Section = NULL;
+    }
+
+    /* Get the NT Header */
+    NtHeader = RtlImageNtHeader(ModuleLoadBase);
+
+    /* Relocate the driver */
+    Status = LdrRelocateImageWithBias(ModuleLoadBase,
+                                      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 = ModuleLoadBase;
+    LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)ModuleLoadBase +
+                                   NtHeader->OptionalHeader.AddressOfEntryPoint);
+    LdrEntry->SizeOfImage = DriverSize;
+    LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum;
+    LdrEntry->SectionPointer = Section;
+
+    /* 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(ModuleLoadBase,
+                                      &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;
+    }
+
+    /* Update the loader entry */
+    LdrEntry->Flags |= (LDRP_SYSTEM_MAPPED |
+                        LDRP_ENTRY_PROCESSED |
+                        LDRP_MM_LOADED);
+    LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS;
+    LdrEntry->LoadedImports = LoadedImports;
+
+    /* FIXME: Apply driver verifier */
+
+    /* FIXME: Write-protect the system image */
+
+    /* Check if notifications are enabled */
+    if (PsImageNotifyEnabled)
+    {
+        /* Fill out the notification data */
+        ImageInfo.Properties = 0;
+        ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
+        ImageInfo.SystemModeImage = TRUE;
+        ImageInfo.ImageSize = LdrEntry->SizeOfImage;
+        ImageInfo.ImageBase = LdrEntry->DllBase;
+        ImageInfo.ImageSectionNumber = ImageInfo.ImageSelector = 0;
+
+        /* Send the notification */
+        PspRunLoadImageNotifyRoutines(FileName, NULL, &ImageInfo);
+    }
+
+    /* Check if there's symbols */
+#ifdef KDBG
+    /* If KDBG is defined, then we always have symbols */
+    if (TRUE)
+#else
+    if (MiCacheImageSymbols(LdrEntry->DllBase))
+#endif
+    {
+        /* Check if the system root is present */
+        if ((PrefixName.Length > (11 * sizeof(WCHAR))) &&
+            !(_wcsnicmp(PrefixName.Buffer, L"\\SystemRoot", 11)))
+        {
+            /* Add the system root */
+            UnicodeTemp = PrefixName;
+            UnicodeTemp.Buffer += 11;
+            UnicodeTemp.Length -= (11 * sizeof(WCHAR));
+            sprintf_nt(Buffer,
+                       "%ws%wZ",
+                       &SharedUserData->NtSystemRoot[2],
+                       &UnicodeTemp);
+        }
+        else
+        {
+            /* Build the name */
+            sprintf_nt(Buffer, "%wZ", &BaseName);
+        }
+
+        /* Setup the ansi string */
+        RtlInitString(&AnsiTemp, Buffer);
+
+        /* Notify the debugger */
+        DbgLoadImageSymbols(&AnsiTemp, LdrEntry->DllBase, -1);
+        LdrEntry->Flags |= LDRP_DEBUG_SYMBOLS_LOADED;
+    }
+
+    /* FIXME: Page the driver */
+    ASSERT(Section == NULL);
+
+    /* Return pointers */
+    if (ModuleObject) *ModuleObject = LdrEntry;
+    if (ImageBaseAddress) *ImageBaseAddress = LdrEntry->DllBase;
+
+Quickie:
+    /* If we have a file handle, close it */
+    if (FileHandle) ZwClose(FileHandle);
+
+    /* 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;
+}
+
+/*
+ * @implemented
+ */
+PVOID
+NTAPI
+MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
+{
+    PVOID ProcAddress = NULL;
+    ANSI_STRING AnsiRoutineName;
+    NTSTATUS Status;
+    PLIST_ENTRY NextEntry;
+    extern LIST_ENTRY PsLoadedModuleList;
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    BOOLEAN Found = FALSE;
+    UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
+    UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll");
+    ULONG Modules = 0;
+
+    /* Convert routine to ansi name */
+    Status = RtlUnicodeStringToAnsiString(&AnsiRoutineName,
+                                          SystemRoutineName,
+                                          TRUE);
+    if (!NT_SUCCESS(Status)) return NULL;
+
+    /* Lock the list */
+    KeEnterCriticalRegion();
+
+    /* Loop the loaded module list */
+    NextEntry = PsLoadedModuleList.Flink;
+    while (NextEntry != &PsLoadedModuleList)
+    {
+        /* Get the entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
+
+        /* Check if it's the kernel or HAL */
+        if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))
+        {
+            /* Found it */
+            Found = TRUE;
+            Modules++;
+        }
+        else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE))
+        {
+            /* Found it */
+            Found = TRUE;
+            Modules++;
+        }
+
+        /* Check if we found a valid binary */
+        if (Found)
+        {
+            /* Find the procedure name */
+            ProcAddress = MiFindExportedRoutineByName(LdrEntry->DllBase,
+                                                      &AnsiRoutineName);
+
+            /* Break out if we found it or if we already tried both modules */
+            if (ProcAddress) break;
+            if (Modules == 2) break;
+        }
+
+        /* Keep looping */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Release the lock */
+    KeLeaveCriticalRegion();
+
+    /* Free the string and return */
+    RtlFreeAnsiString(&AnsiRoutineName);
+    return ProcAddress;
+}
+

Propchange: branches/cache_manager_rewrite/mm/sysldr.c
------------------------------------------------------------------------------
    svn:eol-style = native




More information about the Ros-diffs mailing list