Compilation bug fixed (due to having used an "unknown" field in the
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
index 43ea069..085f831 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: loader.c,v 1.32 1999/10/07 23:36:24 ekohl Exp $
+/* $Id: loader.c,v 1.74 2001/04/23 22:00:28 ea Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -6,34 +6,37 @@
  * PURPOSE:         Loaders for PE executables
  * PROGRAMMERS:     Jean Michault
  *                  Rex Jolliff (rex@lvcablemodem.com)
+ *                  Jason Filby (jasonfilby@yahoo.com)
+ *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
  * UPDATE HISTORY:
- *   DW   22/05/98  Created
- *   RJJ  10/12/98  Completed image loader function and added hooks for MZ/PE
- *   RJJ  10/12/98  Built driver loader function and added hooks for PE/COFF
- *   RJJ  10/12/98  Rolled in David's code to load COFF drivers
- *   JM   14/12/98  Built initial PE user module loader
- *   RJJ  06/03/99  Moved user PE loader into NTDLL
+ *   DW   22/05/98   Created
+ *   RJJ  10/12/98   Completed image loader function and added hooks for MZ/PE
+ *   RJJ  10/12/98   Built driver loader function and added hooks for PE/COFF
+ *   RJJ  10/12/98   Rolled in David's code to load COFF drivers
+ *   JM   14/12/98   Built initial PE user module loader
+ *   RJJ  06/03/99   Moved user PE loader into NTDLL
+ *   JF   26/01/2000 Recoded some parts to retrieve export details correctly
+ *   DW   27/06/2000 Removed redundant header files
+ *   CSH  11/04/2001 Added automatic loading of module symbols if they exist
  */
 
+
 /* INCLUDES *****************************************************************/
 
+#include <limits.h>
 #include <ddk/ntddk.h>
-#include <internal/i386/segment.h>
-#include <internal/linkage.h>
+#include <internal/config.h>
 #include <internal/module.h>
 #include <internal/ntoskrnl.h>
-#include <internal/mmhal.h>
+#include <internal/mm.h>
 #include <internal/ob.h>
 #include <internal/ps.h>
-#include <string.h>
-#include <internal/string.h>
-#include <internal/symbol.h>
+#include <internal/ldr.h>
+#include <internal/pool.h>
 
 #define NDEBUG
 #include <internal/debug.h>
 
-#include "syspath.h"
-
 
 /* FIXME: this should appear in a kernel header file  */
 NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry);
@@ -44,91 +47,147 @@ NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry);
 
 /* GLOBALS *******************************************************************/
 
-POBJECT_TYPE ObModuleType = NULL;
+LIST_ENTRY ModuleListHead;
+POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
+LIST_ENTRY ModuleTextListHead;
+STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
+/* STATIC MODULE_TEXT_SECTION HalTextSection; */
 
-/* FORWARD DECLARATIONS ******************************************************/
+#define TAG_DRIVER_MEM  TAG('D', 'R', 'V', 'M')
+#define TAG_SYM_BUF     TAG('S', 'Y', 'M', 'B')
 
-NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
-NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
+/* FORWARD DECLARATIONS ******************************************************/
 
 PMODULE_OBJECT  LdrLoadModule(PUNICODE_STRING Filename);
-PMODULE_OBJECT  LdrProcessModule(PVOID ModuleLoadBase);
+PMODULE_OBJECT  LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName);
 PVOID  LdrGetExportAddress(PMODULE_OBJECT ModuleObject, char *Name, unsigned short Hint);
 static PMODULE_OBJECT LdrOpenModule(PUNICODE_STRING  Filename);
-static PIMAGE_SECTION_HEADER LdrPEGetEnclosingSectionHeader(DWORD  RVA,
-                                                            PMODULE_OBJECT  ModuleObject);
 static NTSTATUS LdrCreateModule(PVOID ObjectBody,
                                 PVOID Parent,
                                 PWSTR RemainingPath,
                                 POBJECT_ATTRIBUTES ObjectAttributes);
+static VOID LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
+                                   PUNICODE_STRING FullName);
 
 /*  PE Driver load support  */
-static PMODULE_OBJECT  LdrPEProcessModule(PVOID ModuleLoadBase);
-static PVOID  LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject, 
-                                    char *Name, 
+static PMODULE_OBJECT  LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName);
+static PVOID  LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
+                                    char *Name,
                                     unsigned short Hint);
-static unsigned int LdrGetKernelSymbolAddr(char *Name);
+static PMODULE_OBJECT LdrPEGetModuleObject(PUNICODE_STRING ModuleName);
+static PVOID LdrPEFixupForward(PCHAR ForwardName);
 
 
 /* FUNCTIONS *****************************************************************/
 
+VOID
+LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
+{
+  PLIST_ENTRY current_entry;
+  MODULE_TEXT_SECTION* current;
+
+  current_entry = ModuleTextListHead.Flink;
+  while (current_entry != &ModuleTextListHead)
+    {
+      current = 
+       CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
+      if (wcscmp(current->Name, Name) == 0)
+       {
+         break;
+       }
+      current_entry = current_entry->Flink;
+    }
+
+  if (current_entry == &ModuleTextListHead)
+    {
+      return;
+    }
+  
+  current->SymbolsBase = (PVOID)Module->ModStart;
+  current->SymbolsLength = Module->ModEnd - Module->ModStart;
+}
+
+VOID
+LdrInit1(VOID)
+{
+  PIMAGE_DOS_HEADER DosHeader;
+  PIMAGE_FILE_HEADER FileHeader;
+  PIMAGE_OPTIONAL_HEADER OptionalHeader;
+  PIMAGE_SECTION_HEADER SectionList;
+
+  InitializeListHead(&ModuleTextListHead);
+
+  DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
+  FileHeader =
+    (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE + 
+                         DosHeader->e_lfanew + sizeof(ULONG));
+  OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
+    ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
+  SectionList = (PIMAGE_SECTION_HEADER)
+    ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
+  NtoskrnlTextSection.Base = KERNEL_BASE;
+  NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
+    SectionList[0].VirtualAddress;
+  NtoskrnlTextSection.Name = L"ntoskrnl.exe";
+  NtoskrnlTextSection.SymbolsBase = NULL;
+  NtoskrnlTextSection.SymbolsLength = 0;
+  InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
+}
+
 VOID LdrInitModuleManagement(VOID)
 {
   HANDLE DirHandle, ModuleHandle;
   NTSTATUS Status;
   WCHAR NameBuffer[60];
-  ANSI_STRING AnsiString;
   UNICODE_STRING ModuleName;
   OBJECT_ATTRIBUTES ObjectAttributes;
   PIMAGE_DOS_HEADER DosHeader;
   PMODULE_OBJECT ModuleObject;
 
-  /*  Register the process object type  */   
-  ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
-  ObModuleType->TotalObjects = 0;
-  ObModuleType->TotalHandles = 0;
-  ObModuleType->MaxObjects = ULONG_MAX;
-  ObModuleType->MaxHandles = ULONG_MAX;
-  ObModuleType->PagedPoolCharge = 0;
-  ObModuleType->NonpagedPoolCharge = sizeof(MODULE);
-  ObModuleType->Dump = NULL;
-  ObModuleType->Open = NULL;
-  ObModuleType->Close = NULL;
-  ObModuleType->Delete = NULL;
-  ObModuleType->Parse = NULL;
-  ObModuleType->Security = NULL;
-  ObModuleType->QueryName = NULL;
-  ObModuleType->OkayToClose = NULL;
-  ObModuleType->Create = LdrCreateModule;
-  RtlInitAnsiString(&AnsiString, "Module");
-  RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
+  /*  Register the process object type  */
+  IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+  IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'T');
+  IoDriverObjectType->TotalObjects = 0;
+  IoDriverObjectType->TotalHandles = 0;
+  IoDriverObjectType->MaxObjects = ULONG_MAX;
+  IoDriverObjectType->MaxHandles = ULONG_MAX;
+  IoDriverObjectType->PagedPoolCharge = 0;
+  IoDriverObjectType->NonpagedPoolCharge = sizeof(MODULE);
+  IoDriverObjectType->Dump = NULL;
+  IoDriverObjectType->Open = NULL;
+  IoDriverObjectType->Close = NULL;
+  IoDriverObjectType->Delete = NULL;
+  IoDriverObjectType->Parse = NULL;
+  IoDriverObjectType->Security = NULL;
+  IoDriverObjectType->QueryName = NULL;
+  IoDriverObjectType->OkayToClose = NULL;
+  IoDriverObjectType->Create = LdrCreateModule;
+  RtlInitUnicodeString(&IoDriverObjectType->TypeName, L"Driver");
 
   /*  Create Modules object directory  */
   wcscpy(NameBuffer, MODULE_ROOT_NAME);
   *(wcsrchr(NameBuffer, L'\\')) = 0;
-  ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
-  ModuleName.Buffer = NameBuffer;
-  InitializeObjectAttributes(&ObjectAttributes, 
-                             &ModuleName, 
-                             0, 
-                             NULL, 
+  RtlInitUnicodeString (&ModuleName, NameBuffer);
+  InitializeObjectAttributes(&ObjectAttributes,
+                             &ModuleName,
+                             0,
+                             NULL,
                              NULL);
-  DPRINT("Create dir: %W\n", &ModuleName);
-  Status = ZwCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
+  DPRINT("Create dir: %wZ\n", &ModuleName);
+  Status = NtCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
   assert(NT_SUCCESS(Status));
 
   /*  Add module entry for NTOSKRNL  */
   wcscpy(NameBuffer, MODULE_ROOT_NAME);
   wcscat(NameBuffer, L"ntoskrnl.exe");
-  ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
-  ModuleName.Buffer = NameBuffer;
-  DPRINT("Kernel's Module name is: %W\n", &ModuleName);
-  
+  RtlInitUnicodeString (&ModuleName, NameBuffer);
+  DPRINT("Kernel's Module name is: %wZ\n", &ModuleName);
+
   /*  Initialize ObjectAttributes for ModuleObject  */
-  InitializeObjectAttributes(&ObjectAttributes, 
-                             &ModuleName, 
-                             0, 
-                             NULL, 
+  InitializeObjectAttributes(&ObjectAttributes,
+                             &ModuleName,
+                             0,
+                             NULL,
                              NULL);
 
   /*  Create module object  */
@@ -136,23 +195,33 @@ VOID LdrInitModuleManagement(VOID)
   ModuleObject = ObCreateObject(&ModuleHandle,
                                 STANDARD_RIGHTS_REQUIRED,
                                 &ObjectAttributes,
-                                ObModuleType);
+                                IoDriverObjectType);
   assert(ModuleObject != NULL);
 
-  /*  Initialize ModuleObject data  */
-  ModuleObject->Base = (PVOID) KERNEL_BASE;
-  ModuleObject->Flags = MODULE_FLAG_PE;
+   InitializeListHead(&ModuleListHead);
+
+   /*  Initialize ModuleObject data  */
+   ModuleObject->Base = (PVOID) KERNEL_BASE;
+   ModuleObject->Flags = MODULE_FLAG_PE;
+   InsertTailList(&ModuleListHead,
+                 &ModuleObject->ListEntry);
+   RtlCreateUnicodeString(&ModuleObject->FullName,
+                         L"ntoskrnl.exe");
+   LdrpBuildModuleBaseName(&ModuleObject->BaseName,
+                          &ModuleObject->FullName);
+
   DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
-  ModuleObject->Image.PE.FileHeader = 
-    (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base + 
+  ModuleObject->Image.PE.FileHeader =
+    (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
     DosHeader->e_lfanew + sizeof(ULONG));
-  ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER) 
+  ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
     ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
-  ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER) 
+  ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
     ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
-  ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base + 
+  ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
     ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
   DPRINT("ModuleObject:%08x  entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
+   ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
 
   /* FIXME: Add fake module entry for HAL */
 
@@ -161,62 +230,387 @@ VOID LdrInitModuleManagement(VOID)
 /*
  * load the auto config drivers.
  */
-static
-VOID
-LdrLoadAutoConfigDriver (
-       LPWSTR  RelativeDriverName
-       )
+static VOID LdrLoadAutoConfigDriver (LPWSTR    RelativeDriverName)
 {
-       WCHAR           TmpFileName [MAX_PATH];
-       NTSTATUS        Status;
-       UNICODE_STRING  DriverName;
-
-       GetSystemDirectory(
-               TmpFileName,
-               (MAX_PATH * sizeof(WCHAR))
-               );
-       wcscat(
-               TmpFileName,
-               L"\\drivers\\"
-               );
-       wcscat(
-               TmpFileName,
-               RelativeDriverName
-               );
-
-       DriverName.Buffer = 
-               TmpFileName;
-       DriverName.Length = 
-               wcslen(TmpFileName) 
-               * sizeof (WCHAR);
-       DriverName.MaximumLength = 
-               DriverName.Length 
-               + sizeof(WCHAR);
-       
-       Status = LdrLoadDriver(&DriverName);
-       if (!NT_SUCCESS(Status))
-       {
-               DbgPrint(
-                       "driver load failed, status;%d(%x)\n",
-                       Status,
-                       Status
-                       );
-               DbgPrintErrorMessage(Status);
-       }
+   WCHAR               TmpFileName [MAX_PATH];
+   NTSTATUS    Status;
+   UNICODE_STRING      DriverName;
+
+   DbgPrint("Loading %S\n",RelativeDriverName);
+
+   wcscpy(TmpFileName, L"\\SystemRoot\\system32\\drivers\\");
+   wcscat(TmpFileName, RelativeDriverName);
+   RtlInitUnicodeString (&DriverName, TmpFileName);
+
+   Status = LdrLoadDriver(&DriverName);
+   if (!NT_SUCCESS(Status))
+     {
+       DbgPrint("driver load failed, status (%x)\n", Status);
+//     KeBugCheck(0);
+     }
 }
 
+#ifdef KDBG
 
-VOID
-LdrLoadAutoConfigDrivers (VOID)
+BOOLEAN LdrReadLine(PCHAR Line,
+                    PVOID *Buffer,
+                    PULONG Size)
 {
-       /*
-        * Keyboard driver
-        */
-       LdrLoadAutoConfigDriver( L"keyboard.sys" );
-       /*
-        * Raw console driver
-        */
-       LdrLoadAutoConfigDriver( L"blue.sys" );
+  CHAR ch;
+  PCHAR Block;
+
+  if (*Size == 0)
+    return FALSE;
+
+  Block = *Buffer;
+  while ((*Size > 0) && ((ch = *Block) != (CHAR)13))
+    {
+      *Line = ch;
+      Line++;
+      Block++;
+      *Size -= 1;
+    }
+  *Line = (CHAR)0;
+
+  Block++;
+  *Size -= 1;
+
+  if ((*Size > 0) && (*Block == (CHAR)10))
+    {
+      Block++;
+      *Size -= 1;
+    }
+
+  *Buffer = Block;
+
+  return TRUE;
+}
+
+ULONG HexL(PCHAR Buffer)
+{
+  CHAR ch;
+  UINT i, j;
+  ULONG Value;
+
+  j     = 32;
+  i     = 0;
+  Value = 0;
+  while ((j > 0) && ((ch = Buffer[i]) != ' '))
+    {
+      j -= 4;
+      if ((ch >= '0') && (ch <= '9'))
+        Value |= ((ch - '0') << j);
+        if ((ch >= 'A') && (ch <= 'F'))
+          Value |= ((10 + (ch - 'A')) << j);
+        else
+          if ((ch >= 'a') && (ch <= 'f'))
+            Value |= ((10 + (ch - 'a')) << j);
+      i++;
+    }
+  return Value;
+}
+
+PSYMBOL LdrParseLine(PCHAR Line,
+                     PULONG ImageBase,
+                     PBOOLEAN ImageBaseValid)
+/*
+    Line format: [ADDRESS] <TYPE> <NAME>
+    TYPE:
+      U = ?
+      A = Image information
+      t = Symbol in text segment
+      T = Symbol in text segment
+      d = Symbol in data segment
+      D = Symbol in data segment
+      b = Symbol in BSS segment
+      B = Symbol in BSS segment
+      ? = Unknown segment or symbol in unknown segment
+*/
+{
+  ANSI_STRING AnsiString;
+  CHAR Buffer[128];
+  PSYMBOL Symbol;
+  ULONG Address;
+  PCHAR Str;
+  CHAR Type;
+
+  *ImageBaseValid = FALSE;
+
+  if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
+    return NULL;
+
+  Address = HexL(Line);
+
+  Line = strchr(Line, ' ');
+  if (Line == NULL)
+    return NULL;
+
+  Line++;
+  Type = *Line;
+
+  Line = strchr(Line, ' ');
+  if (Line == NULL)
+    return NULL;
+
+  Line++;
+  Str = strchr(Line, ' ');
+  if (Str == NULL)
+    strcpy((char*)&Buffer, Line);
+  else
+    strncpy((char*)&Buffer, Line, Str - Line);
+
+  if ((Type == 'A') && (strcmp((char*)&Buffer, "__image_base__")) == 0)
+    {
+      *ImageBase      = Address;
+      *ImageBaseValid = TRUE;
+      return NULL;
+    }
+
+  /* We only want symbols in the .text segment */
+  if ((Type != 't') && (Type != 'T'))
+    return NULL;
+
+  /* Discard other symbols we can't use */
+  if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
+    return NULL;
+
+  Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
+  if (!Symbol)
+    return NULL;
+
+  Symbol->Next = NULL;
+
+  Symbol->RelativeAddress = Address;
+
+  RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
+  RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
+
+  return Symbol;
+}
+
+VOID LdrLoadModuleSymbols(PMODULE_OBJECT ModuleObject,
+                         MODULE_TEXT_SECTION* ModuleTextSection)
+/*
+   Symbols must be sorted by address, e.g.
+   "nm --numeric-sort module.sys > module.sym"
+ */
+{
+  WCHAR TmpFileName[MAX_PATH];
+  LPWSTR Start, Ext;
+  ULONG Length, Tmp;
+  UNICODE_STRING Filename;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  NTSTATUS Status;
+  HANDLE FileHandle;
+  PVOID FileBuffer, FilePtr;
+  CHAR Line[256];
+  FILE_STANDARD_INFORMATION FileStdInfo;
+  BOOLEAN ImageBaseValid;
+  ULONG ImageBase = 0;
+  PSYMBOL Symbol, CurrentSymbol = NULL;
+
+  /*  Get the path to the symbol store  */
+  wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
+
+  /*  Get the symbol filename from the module name  */
+  Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
+  if (Start == NULL)
+    Start = ModuleObject->BaseName.Buffer;
+  else
+    Start++;
+
+  Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
+  if (Ext != NULL)
+    Length = Ext - Start;
+  else
+    Length = wcslen(Start);
+
+  wcsncat(TmpFileName, Start, Length);
+  wcscat(TmpFileName, L".sym");
+  RtlInitUnicodeString(&Filename, TmpFileName);
+
+  /*  Open the file  */
+  InitializeObjectAttributes(&ObjectAttributes,
+                             &Filename,
+                             0,
+                             NULL,
+                             NULL);
+
+  Status = ZwOpenFile(&FileHandle,
+                      FILE_ALL_ACCESS,
+                      &ObjectAttributes,
+                      NULL, 0, 0);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Could not open symbol file: %wZ\n", &Filename);
+      return;
+    }
+
+  DbgPrint("Loading symbols from %wZ...\n", &Filename);
+
+  /*  Get the size of the file  */
+  Status = ZwQueryInformationFile(FileHandle,
+                                  NULL,
+                                  &FileStdInfo,
+                                  sizeof(FileStdInfo),
+                                  FileStandardInformation);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Could not get file size\n");
+      return;
+    }
+
+  /*  Allocate nonpageable memory for symbol file  */
+  FileBuffer = ExAllocatePool(NonPagedPool,
+                              FileStdInfo.EndOfFile.u.LowPart);
+
+  if (FileBuffer == NULL)
+    {
+      DPRINT("Could not allocate memory for symbol file\n");
+      return;
+    }
+   
+  /*  Load file into memory chunk  */
+  Status = ZwReadFile(FileHandle, 
+                      0, 0, 0, 0, 
+                      FileBuffer, 
+                      FileStdInfo.EndOfFile.u.LowPart, 
+                      0, 0);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Could not read symbol file into memory\n");
+      ExFreePool(FileBuffer);
+      return;
+    }
+
+  ZwClose(FileHandle);
+
+  ModuleTextSection->Symbols.SymbolCount = 0;
+  ModuleTextSection->Symbols.Symbols     = NULL;
+
+  FilePtr = FileBuffer;
+  Length  = FileStdInfo.EndOfFile.u.LowPart;
+
+  while (LdrReadLine((PCHAR)&Line, &FilePtr, &Length))
+    {
+      Symbol = LdrParseLine((PCHAR)&Line, &Tmp, &ImageBaseValid);
+
+      if (ImageBaseValid)
+        ImageBase = Tmp;
+
+      if (Symbol != NULL)
+        {
+          Symbol->RelativeAddress -= ImageBase;
+
+          if (ModuleTextSection->Symbols.Symbols == NULL)
+            ModuleTextSection->Symbols.Symbols = Symbol;
+          else
+            CurrentSymbol->Next = Symbol;
+
+          CurrentSymbol = Symbol;
+
+          ModuleTextSection->Symbols.SymbolCount++;
+        }
+    }
+
+  ExFreePool(FileBuffer);
+}
+
+#endif /* KDBG */
+
+VOID LdrLoadAutoConfigDrivers (VOID)
+{
+
+#ifdef KDBG
+
+  NTSTATUS Status;
+  WCHAR NameBuffer[60];
+  UNICODE_STRING ModuleName;
+  PMODULE_OBJECT ModuleObject;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING RemainingPath;
+
+  /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
+     is created after their module entries */
+
+  wcscpy(NameBuffer, MODULE_ROOT_NAME);
+  wcscat(NameBuffer, L"ntoskrnl.exe");
+  RtlInitUnicodeString(&ModuleName, NameBuffer);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                             &ModuleName,
+                             0,
+                             NULL,
+                             NULL);
+  
+  Status = ObFindObject(&ObjectAttributes,
+                        (PVOID*)&ModuleObject,
+                        &RemainingPath,
+                        NULL);
+  if (NT_SUCCESS(Status)) {
+    RtlFreeUnicodeString(&RemainingPath);
+
+    LdrLoadModuleSymbols(ModuleObject, &NtoskrnlTextSection);
+  }
+
+  /* FIXME: Load symbols for hal.dll */
+
+#endif /* KDBG */
+
+   /*
+    * Keyboard driver
+    */
+   LdrLoadAutoConfigDriver( L"keyboard.sys" );
+   
+   /*
+    * Raw console driver
+    */
+   LdrLoadAutoConfigDriver( L"blue.sys" );
+   
+   /*
+    * 
+    */
+   LdrLoadAutoConfigDriver(L"vidport.sys");
+   
+   /*
+    * 
+    */
+   LdrLoadAutoConfigDriver(L"vgamp.sys");
+   
+   /*
+    * Minix filesystem driver
+    */
+   LdrLoadAutoConfigDriver(L"minixfs.sys");
+
+   /*
+    * Networking
+    */
+#if 0
+   /*
+    * NDIS library
+    */
+   LdrLoadAutoConfigDriver(L"ndis.sys");
+
+   /*
+    * Novell Eagle 2000 driver
+    */
+   LdrLoadAutoConfigDriver(L"ne2000.sys");
+
+   /*
+    * TCP/IP protocol driver
+    */
+   LdrLoadAutoConfigDriver(L"tcpip.sys");
+
+   /*
+    * TDI test driver
+    */
+   LdrLoadAutoConfigDriver(L"tditest.sys");
+
+   /*
+    * Ancillary Function Driver
+    */
+   LdrLoadAutoConfigDriver(L"afd.sys");
+#endif
 }
 
 
@@ -226,9 +620,9 @@ LdrCreateModule(PVOID ObjectBody,
                 PWSTR RemainingPath,
                 POBJECT_ATTRIBUTES ObjectAttributes)
 {
-  DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %w)\n",
-         ObjectBody, 
-         Parent, 
+  DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+         ObjectBody,
+         Parent,
          RemainingPath);
   if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
     {
@@ -249,8 +643,7 @@ LdrCreateModule(PVOID ObjectBody,
  * RETURNS: Status
  */
 
-NTSTATUS 
-LdrLoadDriver(PUNICODE_STRING Filename)
+NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename)
 {
   PMODULE_OBJECT  ModuleObject;
 
@@ -262,10 +655,40 @@ LdrLoadDriver(PUNICODE_STRING Filename)
 
   /* FIXME: should we dereference the ModuleObject here?  */
 
-  return IoInitializeDriver(ModuleObject->EntryPoint); 
+  return IoInitializeDriver(ModuleObject->EntryPoint);
 }
-  
-PMODULE_OBJECT 
+
+NTSTATUS LdrLoadGdiDriver (PUNICODE_STRING DriverName,
+                          PVOID *ImageAddress,
+                          PVOID *SectionPointer,
+                          PVOID *EntryPoint,
+                          PVOID *ExportSectionPointer)
+{
+  PMODULE_OBJECT  ModuleObject;
+
+  ModuleObject = LdrLoadModule(DriverName);
+  if (ModuleObject == 0)
+    {
+      return  STATUS_UNSUCCESSFUL;
+    }
+
+  if (ImageAddress)
+    *ImageAddress = ModuleObject->Base;
+
+//  if (SectionPointer)
+//    *SectionPointer = ModuleObject->
+
+  if (EntryPoint)
+    *EntryPoint = ModuleObject->EntryPoint;
+
+//  if (ExportSectionPointer)
+//    *ExportSectionPointer = ModuleObject->
+
+  return STATUS_SUCCESS;
+}
+
+
+PMODULE_OBJECT
 LdrLoadModule(PUNICODE_STRING Filename)
 {
   PVOID ModuleLoadBase;
@@ -274,9 +697,6 @@ LdrLoadModule(PUNICODE_STRING Filename)
   OBJECT_ATTRIBUTES ObjectAttributes;
   PMODULE_OBJECT  ModuleObject;
   FILE_STANDARD_INFORMATION FileStdInfo;
-  WCHAR  NameBuffer[60];
-  PWSTR  RemainingPath;
-  UNICODE_STRING  ModuleName;
 
   /*  Check for module already loaded  */
   if ((ModuleObject = LdrOpenModule(Filename)) != NULL)
@@ -284,29 +704,29 @@ LdrLoadModule(PUNICODE_STRING Filename)
       return  ModuleObject;
     }
 
-  DPRINT("Loading Module %W...\n", Filename);
+  DPRINT("Loading Module %wZ...\n", Filename);
 
   /*  Open the Module  */
   InitializeObjectAttributes(&ObjectAttributes,
-                             Filename, 
+                             Filename,
                              0,
                              NULL,
                              NULL);
   CHECKPOINT;
-  Status = ZwOpenFile(&FileHandle, 
-                      FILE_ALL_ACCESS, 
-                      &ObjectAttributes, 
+  Status = NtOpenFile(&FileHandle,
+                      FILE_ALL_ACCESS,
+                      &ObjectAttributes,
                       NULL, 0, 0);
   CHECKPOINT;
   if (!NT_SUCCESS(Status))
     {
-      DbgPrint("Could not open module file: %W\n", Filename);
+      DbgPrint("Could not open module file: %wZ\n", Filename);
       return  0;
     }
   CHECKPOINT;
 
   /*  Get the size of the file  */
-  Status = ZwQueryInformationFile(FileHandle,
+  Status = NtQueryInformationFile(FileHandle,
                                   NULL,
                                   &FileStdInfo,
                                   sizeof(FileStdInfo),
@@ -319,17 +739,19 @@ LdrLoadModule(PUNICODE_STRING Filename)
   CHECKPOINT;
 
   /*  Allocate nonpageable memory for driver  */
-  ModuleLoadBase = ExAllocatePool(NonPagedPool,
-                                  FileStdInfo.EndOfFile.u.LowPart);
+  ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
+                                        FileStdInfo.EndOfFile.u.LowPart,
+                                        TAG_DRIVER_MEM);
+
   if (ModuleLoadBase == NULL)
     {
       DbgPrint("could not allocate memory for module");
       return  0;
     }
   CHECKPOINT;
-
+   
   /*  Load driver into memory chunk  */
-  Status = ZwReadFile(FileHandle, 
+  Status = NtReadFile(FileHandle, 
                       0, 0, 0, 0, 
                       ModuleLoadBase, 
                       FileStdInfo.EndOfFile.u.LowPart, 
@@ -343,9 +765,9 @@ LdrLoadModule(PUNICODE_STRING Filename)
     }
   CHECKPOINT;
 
-  ZwClose(FileHandle);
+  NtClose(FileHandle);
 
-  ModuleObject = LdrProcessModule(ModuleLoadBase);
+  ModuleObject = LdrProcessModule(ModuleLoadBase, Filename);
 
   /*  Cleanup  */
   ExFreePool(ModuleLoadBase);
@@ -354,23 +776,29 @@ LdrLoadModule(PUNICODE_STRING Filename)
 }
 
 NTSTATUS
-LdrProcessDriver(PVOID ModuleLoadBase)
+LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName)
 {
-  PMODULE_OBJECT ModuleObject;
-
-  ModuleObject = LdrProcessModule(ModuleLoadBase);
-  if (ModuleObject == 0)
-    {
-      return STATUS_UNSUCCESSFUL;
-    }
-
-  /* FIXME: should we dereference the ModuleObject here?  */
-
-  return IoInitializeDriver(ModuleObject->EntryPoint); 
+   PMODULE_OBJECT ModuleObject;
+   UNICODE_STRING ModuleName;
+
+   RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+                                   FileName);
+   ModuleObject = LdrProcessModule(ModuleLoadBase,
+                                  &ModuleName);
+   RtlFreeUnicodeString(&ModuleName);
+   if (ModuleObject == NULL)
+     {
+       DPRINT1("Driver load was unsuccessful\n");
+       return(STATUS_UNSUCCESSFUL);
+     }
+
+   /* FIXME: should we dereference the ModuleObject here?  */
+
+   return(IoInitializeDriver(ModuleObject->EntryPoint));
 }
 
 PMODULE_OBJECT
-LdrProcessModule(PVOID ModuleLoadBase)
+LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName)
 {
   PIMAGE_DOS_HEADER PEDosHeader;
 
@@ -378,19 +806,10 @@ LdrProcessModule(PVOID ModuleLoadBase)
   PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
   if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
     {
-      return LdrPEProcessModule(ModuleLoadBase);
+      return LdrPEProcessModule(ModuleLoadBase, ModuleName);
     }
-#if 0
-  if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
-    {
-      return 0;
-    }
-  else  /*  Assume COFF format and load  */
-    {
-      return LdrCOFFProcessModule(ModuleLoadBase);
-    }
-#endif
 
+  DPRINT1("Module wasn't PE\n");
   return 0;
 }
 
@@ -402,7 +821,7 @@ LdrOpenModule(PUNICODE_STRING  Filename)
   UNICODE_STRING  ModuleName;
   OBJECT_ATTRIBUTES  ObjectAttributes;
   PMODULE_OBJECT  ModuleObject;
-  PWSTR  RemainingPath;
+  UNICODE_STRING RemainingPath;
 
   wcscpy(NameBuffer, MODULE_ROOT_NAME);
   if (wcsrchr(Filename->Buffer, '\\') != 0)
@@ -413,30 +832,34 @@ LdrOpenModule(PUNICODE_STRING  Filename)
     {
       wcscat(NameBuffer, Filename->Buffer);
     }
-  ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
-  ModuleName.Buffer = NameBuffer;
+  RtlInitUnicodeString (&ModuleName, NameBuffer);
   InitializeObjectAttributes(&ObjectAttributes,
                              &ModuleName, 
                              0,
                              NULL,
                              NULL);
+
   Status = ObFindObject(&ObjectAttributes,
                         (PVOID *) &ModuleObject,
-                        &RemainingPath);
+                        &RemainingPath,
+                        NULL);
   CHECKPOINT;
-  if (NT_SUCCESS(Status) && (RemainingPath == NULL || *RemainingPath == 0))
+  if (NT_SUCCESS(Status) && (RemainingPath.Buffer == NULL || *(RemainingPath.Buffer) == 0))
     {
-      DPRINT("Module %W at %p\n", Filename, ModuleObject);
+      DPRINT("Module %wZ at %p\n", Filename, ModuleObject);
+      RtlFreeUnicodeString (&RemainingPath);
 
       return  ModuleObject;
     }
 
+  RtlFreeUnicodeString (&RemainingPath);
+
   return  NULL;
 }
 
-PVOID  
-LdrGetExportAddress(PMODULE_OBJECT ModuleObject, 
-                    char *Name, 
+PVOID
+LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
+                    char *Name,
                     unsigned short Hint)
 {
   if (ModuleObject->Flags & MODULE_FLAG_PE)
@@ -449,21 +872,137 @@ LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
     }
 }
 
+NTSTATUS
+LdrpQueryModuleInformation(PVOID Buffer,
+                          ULONG Size,
+                          PULONG ReqSize)
+{
+   PLIST_ENTRY current_entry;
+   PMODULE_OBJECT current;
+   ULONG ModuleCount = 0;
+   PSYSTEM_MODULE_INFORMATION Smi;
+   ANSI_STRING AnsiName;
+   PCHAR p;
+
+//   KeAcquireSpinLock(&ModuleListLock,&oldlvl);
+
+   /* calculate required size */
+   current_entry = ModuleListHead.Flink;
+   while (current_entry != (&ModuleListHead))
+     {
+       ModuleCount++;
+       current_entry = current_entry->Flink;
+     }
+
+   *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
+       (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
+
+   if (Size < *ReqSize)
+     {
+//     KeReleaseSpinLock(&ModuleListLock,oldlvl);
+       return STATUS_INFO_LENGTH_MISMATCH;
+     }
+
+   /* fill the buffer */
+   memset(Buffer, '=', Size);
+
+   Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
+   Smi->Count = ModuleCount;
+
+   ModuleCount = 0;
+   current_entry = ModuleListHead.Flink;
+   while (current_entry != (&ModuleListHead))
+     {
+       current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
+
+       Smi->Module[ModuleCount].Unknown2 = 0;          /* Always 0 */
+       Smi->Module[ModuleCount].BaseAddress = current->Base;
+       Smi->Module[ModuleCount].Size = current->Length;
+       Smi->Module[ModuleCount].Flags = 0;             /* Flags ??? (GN) */
+       Smi->Module[ModuleCount].EntryIndex = ModuleCount;
+
+       AnsiName.Length = 0;
+       AnsiName.MaximumLength = 256;
+       AnsiName.Buffer = Smi->Module[ModuleCount].Name;
+       RtlUnicodeStringToAnsiString(&AnsiName,
+                                    &current->FullName,
+                                    FALSE);
+
+       p = strrchr (AnsiName.Buffer, '\\');
+       if (p == NULL)
+         {
+            Smi->Module[ModuleCount].PathLength = 0;
+            Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
+         }
+       else
+         {
+            p++;
+            Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
+            Smi->Module[ModuleCount].NameLength = strlen(p);
+         }
+
+       ModuleCount++;
+       current_entry = current_entry->Flink;
+     }
+
+//   KeReleaseSpinLock(&ModuleListLock,oldlvl);
+
+   return STATUS_SUCCESS;
+}
+
+
+static VOID
+LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
+                       PUNICODE_STRING FullName)
+{
+   UNICODE_STRING Name;
+   PWCHAR p;
+   PWCHAR q;
+
+   DPRINT("LdrpBuildModuleBaseName()\n");
+   DPRINT("FullName %wZ\n", FullName);
+
+   p = wcsrchr(FullName->Buffer, '\\');
+   if (p == NULL)
+     {
+       p = FullName->Buffer;
+     }
+   else
+     {
+       p++;
+     }
+
+   DPRINT("p %S\n", p);
+
+   RtlCreateUnicodeString(&Name, p);
+
+   q = wcschr(p, '.');
+   if (q != NULL)
+     {
+       *q = (WCHAR)0;
+     }
+
+   DPRINT("p %S\n", p);
+
+   RtlCreateUnicodeString(BaseName, p);
+   RtlFreeUnicodeString(&Name);
+}
+
+
 /*  ----------------------------------------------  PE Module support */
 
 PMODULE_OBJECT
-LdrPEProcessModule(PVOID ModuleLoadBase)
+LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName)
 {
   unsigned int DriverSize, Idx, Idx2;
   ULONG RelocDelta, NumRelocs;
   DWORD CurrentSize, TotalRelocs;
-  PVOID DriverBase, CurrentBase;
+  PVOID DriverBase;
   PULONG PEMagic;
   PIMAGE_DOS_HEADER PEDosHeader;
   PIMAGE_FILE_HEADER PEFileHeader;
   PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
   PIMAGE_SECTION_HEADER PESectionHeaders;
-  PIMAGE_EXPORT_DIRECTORY  ExportDirectory;
   PRELOCATION_DIRECTORY RelocDir;
   PRELOCATION_ENTRY RelocEntry;
   PMODULE_OBJECT  LibraryModuleObject;
@@ -476,7 +1015,8 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
   OBJECT_ATTRIBUTES  ObjectAttributes;
   UNICODE_STRING  ModuleName;
   WCHAR  NameBuffer[60];
-  
+  MODULE_TEXT_SECTION* ModuleTextSection;
+
   DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
 
   /*  Get header pointers  */
@@ -527,48 +1067,49 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
   CHECKPOINT;
 
   /*  Determine the size of the module  */
-     
-   DriverSize = PEOptionalHeader->SizeOfImage;
-   DPRINT("DriverSize %x\n",DriverSize);
-   
-  /*  Allocate a virtual section for the module  */  
+  DriverSize = PEOptionalHeader->SizeOfImage;
+  DPRINT("DriverSize %x\n",DriverSize);
+
+  /*  Allocate a virtual section for the module  */
   DriverBase = MmAllocateSection(DriverSize);
   if (DriverBase == 0)
     {
       DbgPrint("Failed to allocate a virtual section for driver\n");
       return 0;
     }
+   DbgPrint("DriverBase: %x\n", DriverBase);
   CHECKPOINT;
-   DPRINT("Module is at base %x\n",DriverBase);
-   
-  /*  Copy image sections into virtual section  */
-  memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
-  CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
+  /*  Copy headers over */
+  memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
    CurrentSize = 0;
+  /*  Copy image sections into virtual section  */
   for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
     {
-      /*  Copy current section into current offset of virtual section  */
+      //  Copy current section into current offset of virtual section
       if (PESectionHeaders[Idx].Characteristics & 
           (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
         {
           DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
                  PESectionHeaders[Idx].VirtualAddress + DriverBase);
-          memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
-                 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
-                 PESectionHeaders[Idx].SizeOfRawData);
+           memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
+                  (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
+                  PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
         }
       else
         {
           DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
                  PESectionHeaders[Idx].VirtualAddress + DriverBase);
           memset(PESectionHeaders[Idx].VirtualAddress + DriverBase, 
-                 '\0', PESectionHeaders[Idx].SizeOfRawData);
+                 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
+
         }
-      CurrentSize += ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
+      CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
                               PEOptionalHeader->SectionAlignment);
-      CurrentBase = (PVOID)((DWORD)CurrentBase + 
-        ROUND_UP(PESectionHeaders[Idx].SizeOfRawData,
-                 PEOptionalHeader->SectionAlignment));
+
+
+//      CurrentBase = (PVOID)((DWORD)CurrentBase + 
+  //      ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
+    //             PEOptionalHeader->SectionAlignment));
     }
 
   /*  Perform relocation fixups  */
@@ -578,8 +1119,9 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
   DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n", 
          DriverBase,
          PEOptionalHeader->ImageBase,
-         RelocDelta);
+         RelocDelta);   
   DPRINT("RelocDir %x\n",RelocDir);
+#if 1
   for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
     {
        if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
@@ -593,6 +1135,11 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
            break;
         }
     }
+#else
+   RelocDir = RelocDir + (ULONG)DriverBase;
+   CurrentSize = PEOptionalHeader->DataDirectory
+                 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+#endif   
   DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
   TotalRelocs = 0;
   while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
@@ -627,7 +1174,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
             }
           else if (Type != 0)
             {
-              DbgPrint("Unknown relocation type %x\n",Type);
+              DbgPrint("Unknown relocation type %x at %x\n",Type, &Type);
               return 0;
             }
         }
@@ -641,12 +1188,11 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
          PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
          .VirtualAddress);
   /*  Perform import fixups  */
-  if (PEOptionalHeader->DataDirectory[
-      IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+  if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
     {
       PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
 
-      SymbolNameBuf = ExAllocatePool(NonPagedPool, 512);
+      SymbolNameBuf = ExAllocatePoolWithTag(NonPagedPool, 512, TAG_SYM_BUF);
 
       /*  Process each import module  */
       ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
@@ -666,13 +1212,13 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
               NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
             }
           NameBuffer[Idx + Idx2] = 0;
-          ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
-          ModuleName.Buffer = NameBuffer;
-          DPRINT("Import module: %W\n", &ModuleName);
+          RtlInitUnicodeString (&ModuleName, NameBuffer);
+          DPRINT("Import module: %wZ\n", &ModuleName);
+
           LibraryModuleObject = LdrLoadModule(&ModuleName);
           if (LibraryModuleObject == 0)
             {
-              DbgPrint("Unknown import module: %W\n", &ModuleName);
+              DbgPrint("Unknown import module: %wZ\n", &ModuleName);
             }
           /*  Get the import address list  */
           ImportAddressList = (PVOID *) ((DWORD)DriverBase + 
@@ -695,6 +1241,8 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
               if ((*FunctionNameList) & 0x80000000) // hint
                 {
                   pName = NULL;
+
+
                   Hint = (*FunctionNameList) & 0xffff;
                 }
               else // hint-name
@@ -714,7 +1262,8 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
                 }
               else
                 {
-                  DbgPrint("Unresolved kernel symbol: %s\n", pName);
+                   DbgPrint("Unresolved kernel symbol: %s\n", pName);
+                  return(NULL);
                 }
               ImportAddressList++;
               FunctionNameList++;
@@ -727,34 +1276,22 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
 
   /*  Create ModuleName string  */
   wcscpy(NameBuffer, MODULE_ROOT_NAME);
-  if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
-        .VirtualAddress != 0)
+  if (wcsrchr(FileName->Buffer, '\\') != 0)
     {
-      ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) (DriverBase +
-        PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
-          .VirtualAddress);
-      wcscat(NameBuffer, DriverBase + ExportDirectory->Name);
+      wcscat(NameBuffer, wcsrchr(FileName->Buffer, '\\') + 1);
     }
   else
     {
-      char buf[12];
-
-      sprintf(buf, "%08X", (DWORD) DriverBase);
-      for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
-        ;
-      Idx2 = 0;
-      while ((NameBuffer[Idx + Idx2] = (WCHAR) buf[Idx2]) != 0)
-        Idx2++;
+      wcscat(NameBuffer, FileName->Buffer);
     }
-  ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
-  ModuleName.Buffer = NameBuffer;
-  DPRINT("Module name is: %W\n", &ModuleName);
-  
+  RtlInitUnicodeString (&ModuleName, NameBuffer);
+  DbgPrint("Module name is: %wZ\n", &ModuleName);
+
   /*  Initialize ObjectAttributes for ModuleObject  */
-  InitializeObjectAttributes(&ObjectAttributes, 
-                             &ModuleName, 
-                             0, 
-                             NULL, 
+  InitializeObjectAttributes(&ObjectAttributes,
+                             &ModuleName,
+                             0,
+                             NULL,
                              NULL);
 
   /*  Create module object  */
@@ -762,88 +1299,111 @@ LdrPEProcessModule(PVOID ModuleLoadBase)
   ModuleObject = ObCreateObject(&ModuleHandle,
                                 STANDARD_RIGHTS_REQUIRED,
                                 &ObjectAttributes,
-                                ObModuleType);
+                                IoDriverObjectType);
+
+   /*  Initialize ModuleObject data  */
+   ModuleObject->Base = DriverBase;
+   ModuleObject->Flags = MODULE_FLAG_PE;
+   InsertTailList(&ModuleListHead,
+                 &ModuleObject->ListEntry);
+   RtlCreateUnicodeString(&ModuleObject->FullName,
+                         FileName->Buffer);
+   LdrpBuildModuleBaseName(&ModuleObject->BaseName,
+                          &ModuleObject->FullName);
 
-  /*  Initialize ModuleObject data  */
-  ModuleObject->Base = DriverBase;
-  ModuleObject->Flags = MODULE_FLAG_PE;
   ModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase + 
     PEOptionalHeader->AddressOfEntryPoint);
+  ModuleObject->Length = DriverSize;
   DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
-  ModuleObject->Image.PE.FileHeader = 
-    (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + 
-    PEDosHeader->e_lfanew + sizeof(ULONG));
+
+  ModuleObject->Image.PE.FileHeader =
+    (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
+
   DPRINT("FileHeader at %x\n", ModuleObject->Image.PE.FileHeader);
   ModuleObject->Image.PE.OptionalHeader = 
-    (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + 
-    PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
+    (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
+    sizeof(IMAGE_FILE_HEADER));
   DPRINT("OptionalHeader at %x\n", ModuleObject->Image.PE.OptionalHeader);
   ModuleObject->Image.PE.SectionList = 
-    (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + 
-    PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
-    sizeof(IMAGE_OPTIONAL_HEADER));
+    (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
+    sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
   DPRINT("SectionList at %x\n", ModuleObject->Image.PE.SectionList);
 
+  ModuleTextSection = ExAllocatePool(NonPagedPool, 
+                                    sizeof(MODULE_TEXT_SECTION));
+  ModuleTextSection->Base = (ULONG)DriverBase;
+  ModuleTextSection->Length = DriverSize;
+  ModuleTextSection->SymbolsBase = NULL;
+  ModuleTextSection->SymbolsLength = 0;
+  ModuleTextSection->Name = 
+    ExAllocatePool(NonPagedPool, 
+                  (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
+  wcscpy(ModuleTextSection->Name, NameBuffer);
+  InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
+
+#ifdef KDBG
+
+       /* Load symbols for module if available */
+  LdrLoadModuleSymbols(ModuleObject, ModuleTextSection);
+
+#endif /* KDBG */
+
   return  ModuleObject;
 }
 
-static PVOID  
-LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject, 
-                      char *Name, 
+static PVOID
+LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
+                      char *Name,
                       unsigned short Hint)
 {
   WORD  Idx;
-  DWORD  ExportsStartRVA, ExportsEndRVA, Delta;
   PVOID  ExportAddress;
   PWORD  OrdinalList;
   PDWORD  FunctionList, NameList;
-  PIMAGE_SECTION_HEADER  SectionHeader;
-  PIMAGE_EXPORT_DIRECTORY  ExportDirectory;
-
-  ExportsStartRVA = ModuleObject->Image.PE.OptionalHeader->DataDirectory
-    [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
-  ExportsEndRVA = ExportsStartRVA + 
-    ModuleObject->Image.PE.OptionalHeader->DataDirectory
-      [IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
-  /*  Get the IMAGE_SECTION_HEADER that contains the exports.  This is
-      usually the .edata section, but doesn't have to be.  */
-  SectionHeader = LdrPEGetEnclosingSectionHeader(ExportsStartRVA, ModuleObject);
-  if (!SectionHeader)
-    {
-      return 0;
-    }
-  Delta = (DWORD)(SectionHeader->VirtualAddress - 
-    SectionHeader->PointerToRawData);
-  ExportDirectory = MakePtr(PIMAGE_EXPORT_DIRECTORY, 
-                            ModuleObject->Base,
-                            ExportsStartRVA - Delta);
-
-  FunctionList = (PDWORD)((DWORD)ExportDirectory->AddressOfFunctions - 
-    Delta + ModuleObject->Base);
-  NameList = (PDWORD)((DWORD)ExportDirectory->AddressOfNames - 
-    Delta + ModuleObject->Base);
-  OrdinalList = (PWORD)((DWORD)ExportDirectory->AddressOfNameOrdinals - 
-    Delta + ModuleObject->Base);
-  DPRINT("Delta:%08x\n", Delta);
-  DPRINT("Func:%08x  RVA:%08x  Name:%08x  RVA:%08x\nOrd:%08x  RVA:%08x  ", 
-         FunctionList, ExportDirectory->AddressOfFunctions, 
-         NameList, ExportDirectory->AddressOfNames, 
-         OrdinalList, ExportDirectory->AddressOfNameOrdinals);
-  DPRINT("NumNames:%d NumFuncs:%d\n", ExportDirectory->NumberOfNames, 
-         ExportDirectory->NumberOfFunctions);
+   PIMAGE_EXPORT_DIRECTORY  ExportDir;
+   ULONG ExportDirSize;
+
+   ExportDir = (PIMAGE_EXPORT_DIRECTORY)
+     RtlImageDirectoryEntryToData(ModuleObject->Base,
+                                 TRUE,
+                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                 &ExportDirSize);
+   DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
+   if (ExportDir == NULL)
+     {
+       return NULL;
+     }
+
+
+   FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
+   NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
+   OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
+
   ExportAddress = 0;
+
   if (Name != NULL)
     {
-      for (Idx = 0; Idx < ExportDirectory->NumberOfNames; Idx++)
+      for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
         {
+#if 0
           DPRINT("  Name:%s  NameList[%d]:%s\n", 
                  Name, 
                  Idx, 
                  (DWORD) ModuleObject->Base + NameList[Idx]);
+
+#endif
           if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
             {
               ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
                 FunctionList[OrdinalList[Idx]]);
+                 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
+                     ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
+                   {
+                      DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
+                      ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
+                      DPRINT("ExportAddress: %p\n", ExportAddress);
+                   }
+
               break;
             }
         }
@@ -851,35 +1411,91 @@ LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
   else  /*  use hint  */
     {
       ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
-        FunctionList[Hint - ExportDirectory->Base]);
-    }
-  if (ExportAddress == 0)
-    {
-      DbgPrint("Export not found for %d:%s\n", Hint, Name != NULL ? Name : "(Ordinal)");
+        FunctionList[Hint - ExportDir->Base]);
     }
 
-  return  ExportAddress;
+   if (ExportAddress == 0)
+     {
+       DbgPrint("Export not found for %d:%s\n",
+                Hint,
+                Name != NULL ? Name : "(Ordinal)");
+       KeBugCheck(0);
+     }
+
+   return ExportAddress;
 }
 
-static PIMAGE_SECTION_HEADER 
-LdrPEGetEnclosingSectionHeader(DWORD  RVA,
-                               PMODULE_OBJECT  ModuleObject)
+
+static PMODULE_OBJECT
+LdrPEGetModuleObject(PUNICODE_STRING ModuleName)
 {
-  PIMAGE_SECTION_HEADER  SectionHeader = SECHDROFFSET(ModuleObject->Base);
-  unsigned  i;
-    
-  for (i = 0; i < ModuleObject->Image.PE.FileHeader->NumberOfSections; 
-       i++, SectionHeader++)
-    {
-      /*  Is the RVA within this section?  */
-      if ((RVA >= SectionHeader->VirtualAddress) && 
-          (RVA < (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize)))
-        {
-          return SectionHeader;
-        }
-    }
-    
-  return 0;
+   PLIST_ENTRY Entry;
+   PMODULE_OBJECT Module;
+
+   DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
+          ModuleName);
+
+   Entry = ModuleListHead.Flink;
+
+   while (Entry != &ModuleListHead)
+     {
+       Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
+
+       DPRINT("Comparing %wZ and %wZ\n",
+              &Module->BaseName,
+              ModuleName);
+
+       if (!RtlCompareUnicodeString(&Module->BaseName, ModuleName, TRUE))
+         {
+            DPRINT("Module %x\n", Module);
+            return Module;
+         }
+
+       Entry = Entry->Flink;
+     }
+
+   DbgPrint("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName);
+
+   return NULL;
+}
+
+
+static PVOID
+LdrPEFixupForward(PCHAR ForwardName)
+{
+   CHAR NameBuffer[128];
+   UNICODE_STRING ModuleName;
+   PCHAR p;
+   PMODULE_OBJECT ModuleObject;
+
+   DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
+
+   strcpy(NameBuffer, ForwardName);
+   p = strchr(NameBuffer, '.');
+   if (p == NULL)
+     {
+       return NULL;
+     }
+
+   *p = 0;
+
+   DPRINT("Driver: %s  Function: %s\n", NameBuffer, p+1);
+
+   RtlCreateUnicodeStringFromAsciiz(&ModuleName,
+                                   NameBuffer);
+   ModuleObject = LdrPEGetModuleObject(&ModuleName);
+   RtlFreeUnicodeString(&ModuleName);
+
+   DPRINT("ModuleObject: %p\n", ModuleObject);
+
+   if (ModuleObject == NULL)
+     {
+       DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+       return NULL;
+     }
+
+   return LdrPEGetExportAddress(ModuleObject, p+1, 0);
 }
 
 
+/* EOF */