3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ldr/loader.c
6 * PURPOSE: Loaders for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
9 * Jason Filby (jasonfilby@yahoo.com)
10 * Casper S. Hornstrup (chorns@users.sourceforge.net)
13 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
14 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
15 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
16 * JM 14/12/98 Built initial PE user module loader
17 * RJJ 06/03/99 Moved user PE loader into NTDLL
18 * JF 26/01/2000 Recoded some parts to retrieve export details correctly
19 * DW 27/06/2000 Removed redundant header files
20 * CSH 11/04/2001 Added automatic loading of module symbols if they exist
24 /* INCLUDES *****************************************************************/
27 #include <ddk/ntddk.h>
29 #include <internal/module.h>
30 #include <internal/ntoskrnl.h>
31 #include <internal/kd.h>
32 #include <internal/io.h>
33 #include <internal/mm.h>
34 #include <internal/ps.h>
35 #include <internal/ldr.h>
36 #include <internal/pool.h>
37 #include <internal/kd.h>
38 #include <ntos/minmax.h>
41 #include <internal/ntosdbg.h>
47 #include <internal/debug.h>
49 /* GLOBALS *******************************************************************/
51 LIST_ENTRY ModuleListHead;
52 KSPIN_LOCK ModuleListLock;
54 LIST_ENTRY ModuleTextListHead;
55 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
56 STATIC MODULE_TEXT_SECTION LdrHalTextSection;
59 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
61 /* FORWARD DECLARATIONS ******************************************************/
64 LdrProcessModule(PVOID ModuleLoadBase,
65 PUNICODE_STRING ModuleName,
66 PMODULE_OBJECT *ModuleObject);
69 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
74 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
75 PUNICODE_STRING FullName);
78 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
79 IN PUNICODE_STRING String2);
82 /* PE Driver load support */
83 static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
84 PUNICODE_STRING FileName,
85 PMODULE_OBJECT *ModuleObject);
87 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
92 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
97 LdrPEFixupForward(PCHAR ForwardName);
100 /* FUNCTIONS *****************************************************************/
103 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
105 PLIST_ENTRY current_entry;
106 MODULE_TEXT_SECTION* current;
108 current_entry = ModuleTextListHead.Flink;
109 while (current_entry != &ModuleTextListHead)
112 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
113 if (wcscmp(current->Name, Name) == 0)
117 current_entry = current_entry->Flink;
120 if (current_entry == &ModuleTextListHead)
129 PIMAGE_DOS_HEADER DosHeader;
130 PIMAGE_FILE_HEADER FileHeader;
131 PIMAGE_OPTIONAL_HEADER OptionalHeader;
132 PIMAGE_SECTION_HEADER SectionList;
134 InitializeListHead(&ModuleTextListHead);
136 /* Setup ntoskrnl.exe text section */
137 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
139 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
140 DosHeader->e_lfanew + sizeof(ULONG));
141 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
142 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
143 SectionList = (PIMAGE_SECTION_HEADER)
144 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
145 NtoskrnlTextSection.Base = KERNEL_BASE;
146 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
147 SectionList[0].VirtualAddress;
148 NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
149 NtoskrnlTextSection.OptionalHeader = OptionalHeader;
150 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
152 /* Setup hal.dll text section */
153 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
155 (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
156 DosHeader->e_lfanew + sizeof(ULONG));
157 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
158 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
159 SectionList = (PIMAGE_SECTION_HEADER)
160 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
161 LdrHalTextSection.Base = LdrHalBase;
162 LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
163 SectionList[0].VirtualAddress;
164 LdrHalTextSection.Name = HAL_MODULE_NAME;
165 LdrHalTextSection.OptionalHeader = OptionalHeader;
166 InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
168 /* Hook for KDB on initialization of the loader. */
169 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
174 LdrInitModuleManagement(VOID)
176 PIMAGE_DOS_HEADER DosHeader;
177 PMODULE_OBJECT ModuleObject;
179 /* Initialize the module list and spinlock */
180 InitializeListHead(&ModuleListHead);
181 KeInitializeSpinLock(&ModuleListLock);
183 /* Create module object for NTOSKRNL */
184 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
185 assert(ModuleObject != NULL);
186 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
188 /* Initialize ModuleObject data */
189 ModuleObject->Base = (PVOID) KERNEL_BASE;
190 ModuleObject->Flags = MODULE_FLAG_PE;
191 RtlCreateUnicodeString(&ModuleObject->FullName,
193 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
194 &ModuleObject->FullName);
196 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
197 ModuleObject->Image.PE.FileHeader =
198 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
199 DosHeader->e_lfanew + sizeof(ULONG));
200 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
201 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
202 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
203 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
204 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
205 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
206 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
207 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
208 ModuleObject->TextSection = &NtoskrnlTextSection;
210 InsertTailList(&ModuleListHead,
211 &ModuleObject->ListEntry);
213 /* Create module object for HAL */
214 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
215 assert(ModuleObject != NULL);
216 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
218 /* Initialize ModuleObject data */
219 ModuleObject->Base = (PVOID) LdrHalBase;
220 ModuleObject->Flags = MODULE_FLAG_PE;
222 RtlCreateUnicodeString(&ModuleObject->FullName,
224 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
225 &ModuleObject->FullName);
227 DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
228 ModuleObject->Image.PE.FileHeader =
229 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
230 DosHeader->e_lfanew + sizeof(ULONG));
231 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
232 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
233 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
234 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
235 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
236 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
237 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
238 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
239 ModuleObject->TextSection = &LdrHalTextSection;
241 InsertTailList(&ModuleListHead,
242 &ModuleObject->ListEntry);
246 LdrpLoadImage(PUNICODE_STRING DriverName,
248 PVOID *SectionPointer,
250 PVOID *ExportSectionPointer)
252 PMODULE_OBJECT ModuleObject;
255 ModuleObject = LdrGetModuleObject(DriverName);
256 if (ModuleObject == NULL)
258 Status = LdrLoadModule(DriverName, &ModuleObject);
259 if (!NT_SUCCESS(Status))
266 *ModuleBase = ModuleObject->Base;
268 // if (SectionPointer)
269 // *SectionPointer = ModuleObject->
272 *EntryPoint = ModuleObject->EntryPoint;
274 // if (ExportSectionPointer)
275 // *ExportSectionPointer = ModuleObject->
277 return(STATUS_SUCCESS);
282 LdrpUnloadImage(PVOID ModuleBase)
284 return(STATUS_NOT_IMPLEMENTED);
289 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
291 PDRIVER_INITIALIZE DriverEntry;
292 PMODULE_OBJECT ModuleObject;
295 ModuleObject = LdrGetModuleObject(ModuleName);
296 if (ModuleObject != NULL)
298 return(STATUS_IMAGE_ALREADY_LOADED);
301 Status = LdrLoadModule(ModuleName, &ModuleObject);
302 if (!NT_SUCCESS(Status))
307 DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
309 Status = DriverEntry(NULL, NULL);
310 if (!NT_SUCCESS(Status))
312 LdrUnloadModule(ModuleObject);
320 LdrLoadModule(PUNICODE_STRING Filename,
321 PMODULE_OBJECT *ModuleObject)
323 PVOID ModuleLoadBase;
326 OBJECT_ATTRIBUTES ObjectAttributes;
327 PMODULE_OBJECT Module;
328 FILE_STANDARD_INFORMATION FileStdInfo;
329 IO_STATUS_BLOCK IoStatusBlock;
331 *ModuleObject = NULL;
333 DPRINT("Loading Module %wZ...\n", Filename);
335 /* Open the Module */
336 InitializeObjectAttributes(&ObjectAttributes,
342 Status = NtOpenFile(&FileHandle,
347 FILE_SYNCHRONOUS_IO_NONALERT);
349 if (!NT_SUCCESS(Status))
351 CPRINT("Could not open module file: %wZ\n", Filename);
356 /* Get the size of the file */
357 Status = NtQueryInformationFile(FileHandle,
361 FileStandardInformation);
362 if (!NT_SUCCESS(Status))
364 CPRINT("Could not get file size\n");
370 /* Allocate nonpageable memory for driver */
371 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
372 FileStdInfo.EndOfFile.u.LowPart,
374 if (ModuleLoadBase == NULL)
376 CPRINT("Could not allocate memory for module");
378 return(STATUS_INSUFFICIENT_RESOURCES);
382 /* Load driver into memory chunk */
383 Status = NtReadFile(FileHandle,
387 FileStdInfo.EndOfFile.u.LowPart,
389 if (!NT_SUCCESS(Status))
391 CPRINT("Could not read module file into memory");
392 ExFreePool(ModuleLoadBase);
400 Status = LdrProcessModule(ModuleLoadBase,
403 if (!NT_SUCCESS(Status))
405 CPRINT("Could not process module");
406 ExFreePool(ModuleLoadBase);
411 ExFreePool(ModuleLoadBase);
413 *ModuleObject = Module;
415 /* Hook for KDB on loading a driver. */
416 KDB_LOADDRIVER_HOOK(Filename, Module);
418 return(STATUS_SUCCESS);
423 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
427 /* Remove the module from the module list */
428 KeAcquireSpinLock(&ModuleListLock,&Irql);
429 RemoveEntryList(&ModuleObject->ListEntry);
430 KeReleaseSpinLock(&ModuleListLock, Irql);
432 /* Hook for KDB on unloading a driver. */
433 KDB_UNLOADDRIVER_HOOK(ModuleObject);
435 /* Free text section */
436 if (ModuleObject->TextSection != NULL)
438 ExFreePool(ModuleObject->TextSection->Name);
439 RemoveEntryList(&ModuleObject->TextSection->ListEntry);
440 ExFreePool(ModuleObject->TextSection);
441 ModuleObject->TextSection = NULL;
444 /* Free module section */
445 // MmFreeSection(ModuleObject->Base);
447 ExFreePool(ModuleObject);
449 return(STATUS_SUCCESS);
454 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
458 PMODULE_OBJECT ModuleObject;
459 UNICODE_STRING ModuleName;
460 PDEVICE_NODE DeviceNode;
463 WCHAR Buffer[MAX_PATH];
468 CHAR TextBuffer [256];
471 HalQueryDisplayParameters(&x, &y, &cx, &cy);
472 RtlFillMemory(TextBuffer, x, ' ');
473 TextBuffer[x] = '\0';
474 HalSetDisplayParameters(0, y-1);
475 HalDisplayString(TextBuffer);
477 sprintf(TextBuffer, "Initializing %s...\n", FileName);
478 HalSetDisplayParameters(0, y-1);
479 HalDisplayString(TextBuffer);
480 HalSetDisplayParameters(cx, cy);
482 /* Split the filename into base name and extension */
483 FileExt = strrchr(FileName, '.');
485 Length = FileExt - FileName;
487 Length = strlen(FileName);
489 if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
491 KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
492 return(STATUS_SUCCESS);
494 else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
496 CPRINT("Ignoring non-driver file %s\n", FileName);
497 return STATUS_SUCCESS;
500 /* Use IopRootDeviceNode for now */
501 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
502 if (!NT_SUCCESS(Status))
504 CPRINT("Driver load failed, status (%x)\n", Status);
508 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
510 Status = LdrProcessModule(ModuleLoadBase,
513 RtlFreeUnicodeString(&ModuleName);
514 if (ModuleObject == NULL)
516 IopFreeDeviceNode(DeviceNode);
517 CPRINT("Driver load failed, status (%x)\n", Status);
518 return(STATUS_UNSUCCESSFUL);
522 /* Get the service name from the module name */
523 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
525 Start = ModuleObject->BaseName.Buffer;
529 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
531 Length = Ext - Start;
533 Length = wcslen(Start);
535 wcsncpy(Buffer, Start, Length);
536 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
538 Status = IopInitializeDriver(ModuleObject->EntryPoint,
540 if (!NT_SUCCESS(Status))
542 IopFreeDeviceNode(DeviceNode);
543 CPRINT("Driver load failed, status (%x)\n", Status);
551 LdrProcessModule(PVOID ModuleLoadBase,
552 PUNICODE_STRING ModuleName,
553 PMODULE_OBJECT *ModuleObject)
555 PIMAGE_DOS_HEADER PEDosHeader;
557 /* If MZ header exists */
558 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
559 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
561 return LdrPEProcessModule(ModuleLoadBase,
566 CPRINT("Module wasn't PE\n");
567 return STATUS_UNSUCCESSFUL;
572 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
576 if (ModuleObject->Flags & MODULE_FLAG_PE)
578 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
588 LdrpQueryModuleInformation(PVOID Buffer,
592 PLIST_ENTRY current_entry;
593 PMODULE_OBJECT current;
594 ULONG ModuleCount = 0;
595 PSYSTEM_MODULE_INFORMATION Smi;
596 ANSI_STRING AnsiName;
600 KeAcquireSpinLock(&ModuleListLock,&Irql);
602 /* calculate required size */
603 current_entry = ModuleListHead.Flink;
604 while (current_entry != (&ModuleListHead))
607 current_entry = current_entry->Flink;
610 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
611 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
615 KeReleaseSpinLock(&ModuleListLock, Irql);
616 return(STATUS_INFO_LENGTH_MISMATCH);
619 /* fill the buffer */
620 memset(Buffer, '=', Size);
622 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
623 Smi->Count = ModuleCount;
626 current_entry = ModuleListHead.Flink;
627 while (current_entry != (&ModuleListHead))
629 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
631 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
632 Smi->Module[ModuleCount].BaseAddress = current->Base;
633 Smi->Module[ModuleCount].Size = current->Length;
634 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
635 Smi->Module[ModuleCount].EntryIndex = ModuleCount;
638 AnsiName.MaximumLength = 256;
639 AnsiName.Buffer = Smi->Module[ModuleCount].Name;
640 RtlUnicodeStringToAnsiString(&AnsiName,
644 p = strrchr(AnsiName.Buffer, '\\');
647 Smi->Module[ModuleCount].PathLength = 0;
648 Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
653 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
654 Smi->Module[ModuleCount].NameLength = strlen(p);
658 current_entry = current_entry->Flink;
661 KeReleaseSpinLock(&ModuleListLock, Irql);
663 return(STATUS_SUCCESS);
668 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
669 PUNICODE_STRING FullName)
675 DPRINT("LdrpBuildModuleBaseName()\n");
676 DPRINT("FullName %wZ\n", FullName);
678 p = wcsrchr(FullName->Buffer, L'\\');
681 p = FullName->Buffer;
690 RtlCreateUnicodeString(&Name, p);
692 q = wcschr(Name.Buffer, L'.');
700 RtlCreateUnicodeString(BaseName, Name.Buffer);
701 RtlFreeUnicodeString(&Name);
706 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
707 IN PUNICODE_STRING String2)
713 if (String1 && String2)
715 /* Search String1 for last path component */
716 len1 = String1->Length / sizeof(WCHAR);
717 s1 = String1->Buffer;
718 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
722 if (i == String1->Length - sizeof(WCHAR))
730 len1 = (String1->Length - i) / sizeof(WCHAR);
735 /* Search String2 for last path component */
736 len2 = String2->Length / sizeof(WCHAR);
737 s2 = String2->Buffer;
738 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
742 if (i == String2->Length - sizeof(WCHAR))
750 len2 = (String2->Length - i) / sizeof(WCHAR);
755 /* Compare last path components */
760 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
761 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
762 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
764 if (!c1 || !c2 || c1 != c2)
775 LdrGetModuleObject(PUNICODE_STRING ModuleName)
777 PMODULE_OBJECT Module;
781 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
783 KeAcquireSpinLock(&ModuleListLock,&Irql);
785 Entry = ModuleListHead.Flink;
786 while (Entry != &ModuleListHead)
788 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
790 DPRINT("Comparing %wZ and %wZ\n",
794 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
796 DPRINT("Module %wZ\n", &Module->BaseName);
797 KeReleaseSpinLock(&ModuleListLock, Irql);
801 Entry = Entry->Flink;
804 KeReleaseSpinLock(&ModuleListLock, Irql);
806 DPRINT("Could not find module '%wZ'\n", ModuleName);
812 /* ---------------------------------------------- PE Module support */
815 PageNeedsWriteAccess(PVOID PageStart,
817 PIMAGE_FILE_HEADER PEFileHeader,
818 PIMAGE_SECTION_HEADER PESectionHeaders)
820 BOOL NeedsWriteAccess;
822 ULONG Characteristics;
826 NeedsWriteAccess = FALSE;
827 /* Set the protections for the various parts of the driver */
828 for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
830 Characteristics = PESectionHeaders[Idx].Characteristics;
831 if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
832 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
833 Characteristics & IMAGE_SECTION_CHAR_DATA ||
834 Characteristics & IMAGE_SECTION_CHAR_BSS))
837 max(PESectionHeaders[Idx].Misc.VirtualSize,
838 PESectionHeaders[Idx].SizeOfRawData);
839 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
840 NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
841 PageStart < (PVOID)((PCHAR) BaseAddress + Length);
845 return(NeedsWriteAccess);
849 LdrPEProcessModule(PVOID ModuleLoadBase,
850 PUNICODE_STRING FileName,
851 PMODULE_OBJECT *ModuleObject)
853 unsigned int DriverSize, Idx;
854 ULONG RelocDelta, NumRelocs;
855 DWORD CurrentSize, TotalRelocs;
858 PIMAGE_DOS_HEADER PEDosHeader;
859 PIMAGE_FILE_HEADER PEFileHeader;
860 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
861 PIMAGE_SECTION_HEADER PESectionHeaders;
862 PRELOCATION_DIRECTORY RelocDir;
863 PRELOCATION_ENTRY RelocEntry;
864 PMODULE_OBJECT LibraryModuleObject;
865 PMODULE_OBJECT CreatedModuleObject;
866 PVOID *ImportAddressList;
867 PULONG FunctionNameList;
870 UNICODE_STRING ModuleName;
871 UNICODE_STRING NameString;
872 WCHAR NameBuffer[60];
873 MODULE_TEXT_SECTION* ModuleTextSection;
877 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
879 /* Get header pointers */
880 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
881 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
882 PEDosHeader->e_lfanew);
883 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
884 PEDosHeader->e_lfanew + sizeof(ULONG));
885 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
886 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
887 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
888 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
889 sizeof(IMAGE_OPTIONAL_HEADER));
892 /* Check file magic numbers */
893 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
895 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
896 return STATUS_UNSUCCESSFUL;
898 if (PEDosHeader->e_lfanew == 0)
900 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
901 return STATUS_UNSUCCESSFUL;
903 if (*PEMagic != IMAGE_PE_MAGIC)
905 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
906 return STATUS_UNSUCCESSFUL;
908 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
910 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
911 return STATUS_UNSUCCESSFUL;
915 /* FIXME: if image is fixed-address load, then fail */
917 /* FIXME: check/verify OS version number */
919 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
920 PEOptionalHeader->Magic,
921 PEOptionalHeader->MajorLinkerVersion,
922 PEOptionalHeader->MinorLinkerVersion);
923 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
926 /* Determine the size of the module */
927 DriverSize = PEOptionalHeader->SizeOfImage;
928 DPRINT("DriverSize %x\n",DriverSize);
930 /* Allocate a virtual section for the module */
931 DriverBase = MmAllocateSection(DriverSize);
934 CPRINT("Failed to allocate a virtual section for driver\n");
935 return STATUS_UNSUCCESSFUL;
937 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
939 /* Copy headers over */
940 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
942 /* Copy image sections into virtual section */
943 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
945 // Copy current section into current offset of virtual section
946 if (PESectionHeaders[Idx].Characteristics &
947 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
949 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
950 PESectionHeaders[Idx].VirtualAddress + DriverBase);
951 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
952 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
953 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
954 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
958 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
959 PESectionHeaders[Idx].VirtualAddress + DriverBase);
960 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
961 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
964 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
965 PEOptionalHeader->SectionAlignment);
968 // CurrentBase = (PVOID)((DWORD)CurrentBase +
969 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
970 // PEOptionalHeader->SectionAlignment));
973 /* Perform relocation fixups */
974 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
975 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
976 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
977 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
979 PEOptionalHeader->ImageBase,
981 DPRINT("RelocDir %x\n",RelocDir);
983 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
985 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
987 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
988 PESectionHeaders[Idx].Name,
989 PESectionHeaders[Idx].PointerToRawData);
990 RelocDir = PESectionHeaders[Idx].PointerToRawData +
992 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
997 RelocDir = RelocDir + (ULONG)DriverBase;
998 CurrentSize = PEOptionalHeader->DataDirectory
999 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1001 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1003 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1005 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1007 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1009 RelocDir->VirtualAddress,
1011 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1012 sizeof(RELOCATION_DIRECTORY));
1013 for (Idx = 0; Idx < NumRelocs; Idx++)
1019 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1020 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1021 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1023 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1026 Type ? "HIGHLOW" : "ABS",
1028 (*RelocItem) + RelocDelta); */
1031 (*RelocItem) += RelocDelta;
1035 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1036 return STATUS_UNSUCCESSFUL;
1039 TotalRelocs += RelocDir->SizeOfBlock;
1040 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1041 RelocDir->SizeOfBlock);
1042 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1045 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1046 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1048 /* Perform import fixups */
1049 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1051 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1053 /* Process each import module */
1054 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1055 ((DWORD)DriverBase + PEOptionalHeader->
1056 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1057 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1058 while (ImportModuleDirectory->dwRVAModuleName)
1060 /* Check to make sure that import lib is kernel */
1061 pName = (PCHAR) DriverBase +
1062 ImportModuleDirectory->dwRVAModuleName;
1064 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1065 DPRINT("Import module: %wZ\n", &ModuleName);
1067 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1068 if (LibraryModuleObject == NULL)
1070 CPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1071 wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
1072 wcscat(NameBuffer, ModuleName.Buffer);
1073 RtlInitUnicodeString(&NameString, NameBuffer);
1074 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1075 if (!NT_SUCCESS(Status))
1077 CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1081 /* Get the import address list */
1082 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1083 ImportModuleDirectory->dwRVAFunctionAddressList);
1085 /* Get the list of functions to import */
1086 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1088 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1089 ImportModuleDirectory->dwRVAFunctionNameList);
1093 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1094 ImportModuleDirectory->dwRVAFunctionAddressList);
1096 /* Walk through function list and fixup addresses */
1097 while (*FunctionNameList != 0L)
1099 if ((*FunctionNameList) & 0x80000000) // hint
1104 Hint = (*FunctionNameList) & 0xffff;
1108 pName = (PCHAR)((DWORD)DriverBase +
1109 *FunctionNameList + 2);
1110 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1112 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1114 /* Fixup the current import symbol */
1115 if (LibraryModuleObject != NULL)
1117 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1123 CPRINT("Unresolved kernel symbol: %s\n", pName);
1124 return STATUS_UNSUCCESSFUL;
1126 ImportAddressList++;
1130 RtlFreeUnicodeString(&ModuleName);
1132 ImportModuleDirectory++;
1136 /* Set the protections for the various parts of the driver */
1137 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1139 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1143 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1144 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1145 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1146 Characteristics & IMAGE_SECTION_CHAR_BSS))
1149 max(PESectionHeaders[Idx].Misc.VirtualSize,
1150 PESectionHeaders[Idx].SizeOfRawData);
1151 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1152 PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
1153 if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1155 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1157 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1158 while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
1159 (PVOID)((PCHAR) BaseAddress + Length))
1161 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1162 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1164 if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
1165 ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1167 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1172 /* Create the module */
1173 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1174 if (CreatedModuleObject == NULL)
1176 return(STATUS_INSUFFICIENT_RESOURCES);
1179 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1181 /* Initialize ModuleObject data */
1182 CreatedModuleObject->Base = DriverBase;
1183 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1185 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1187 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1188 &CreatedModuleObject->FullName);
1190 CreatedModuleObject->EntryPoint =
1191 (PVOID)((DWORD)DriverBase +
1192 PEOptionalHeader->AddressOfEntryPoint);
1193 CreatedModuleObject->Length = DriverSize;
1194 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1196 CreatedModuleObject->Image.PE.FileHeader =
1197 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1199 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1200 CreatedModuleObject->Image.PE.OptionalHeader =
1201 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1202 sizeof(IMAGE_FILE_HEADER));
1203 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1204 CreatedModuleObject->Image.PE.SectionList =
1205 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1206 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1207 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1210 KeAcquireSpinLock(&ModuleListLock, &Irql);
1211 InsertTailList(&ModuleListHead,
1212 &CreatedModuleObject->ListEntry);
1213 KeReleaseSpinLock(&ModuleListLock, Irql);
1216 ModuleTextSection = ExAllocatePool(NonPagedPool,
1217 sizeof(MODULE_TEXT_SECTION));
1218 assert(ModuleTextSection);
1219 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1220 ModuleTextSection->Base = (ULONG)DriverBase;
1221 ModuleTextSection->Length = DriverSize;
1222 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1223 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1224 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1225 ModuleTextSection->OptionalHeader =
1226 CreatedModuleObject->Image.PE.OptionalHeader;
1227 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1229 CreatedModuleObject->TextSection = ModuleTextSection;
1231 *ModuleObject = CreatedModuleObject;
1233 DPRINT("Loading Module %wZ...\n", FileName);
1235 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1237 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1238 FileName, CreatedModuleObject->Base);
1241 return STATUS_SUCCESS;
1246 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1248 PVOID ImportModuleBase,
1252 ULONG RelocDelta, NumRelocs;
1253 ULONG CurrentSize, TotalRelocs;
1255 PIMAGE_DOS_HEADER PEDosHeader;
1256 PIMAGE_FILE_HEADER PEFileHeader;
1257 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1258 PIMAGE_SECTION_HEADER PESectionHeaders;
1259 PRELOCATION_DIRECTORY RelocDir;
1260 PRELOCATION_ENTRY RelocEntry;
1261 PVOID *ImportAddressList;
1262 PULONG FunctionNameList;
1266 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1268 /* Get header pointers */
1269 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1270 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1271 PEDosHeader->e_lfanew);
1272 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1273 PEDosHeader->e_lfanew + sizeof(ULONG));
1274 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1275 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1276 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1277 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1278 sizeof(IMAGE_OPTIONAL_HEADER));
1281 /* Check file magic numbers */
1282 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1286 if (PEDosHeader->e_lfanew == 0)
1290 if (*PEMagic != IMAGE_PE_MAGIC)
1294 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1299 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1300 PEOptionalHeader->Magic,
1301 PEOptionalHeader->MajorLinkerVersion,
1302 PEOptionalHeader->MinorLinkerVersion);
1303 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1305 /* Determine the size of the module */
1306 *DriverSize = PEOptionalHeader->SizeOfImage;
1307 ps("DriverSize %x\n",*DriverSize);
1309 /* Copy headers over */
1310 if (DriverBase != ModuleLoadBase)
1312 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1315 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1316 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1317 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1319 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1320 address as it is mapped */
1321 if (DriverBase != ModuleLoadBase)
1325 /* Copy image sections into virtual section */
1326 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1328 // Copy current section into current offset of virtual section
1329 if (PESectionHeaders[Idx].Characteristics &
1330 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1332 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1333 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1334 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1335 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1336 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1337 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1341 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1342 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1343 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1345 PESectionHeaders[Idx].Misc.VirtualSize);
1347 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1348 PEOptionalHeader->SectionAlignment);
1351 /* Perform relocation fixups */
1352 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1353 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1354 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1355 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1357 PEOptionalHeader->ImageBase,
1359 ps("RelocDir %x\n",RelocDir);
1361 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1363 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1365 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1366 PESectionHeaders[Idx].Name,
1367 PESectionHeaders[Idx].PointerToRawData);
1368 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1369 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1374 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1377 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1379 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1381 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1382 sizeof(RELOCATION_DIRECTORY));
1383 for (Idx = 0; Idx < NumRelocs; Idx++)
1389 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1390 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1391 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1394 (*RelocItem) += RelocDelta;
1398 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1402 TotalRelocs += RelocDir->SizeOfBlock;
1403 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1404 RelocDir->SizeOfBlock);
1407 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1408 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1412 /* Perform import fixups */
1413 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1415 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1417 /* Process each import module */
1418 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1419 ((ULONG)DriverBase + PEOptionalHeader->
1420 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1422 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1424 /* Check to make sure that import lib is kernel */
1425 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1427 ps("Import module: %s\n", pName);
1429 /* Get the import address list */
1430 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1431 ImportModuleDirectory->dwRVAFunctionAddressList);
1433 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1434 ImportModuleDirectory->dwRVAFunctionAddressList);
1435 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1437 /* Get the list of functions to import */
1438 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1440 ps("Using function name list.\n");
1442 FunctionNameList = (PULONG)((ULONG)DriverBase +
1443 ImportModuleDirectory->dwRVAFunctionNameList);
1447 ps("Using function address list.\n");
1449 FunctionNameList = (PULONG)((ULONG)DriverBase +
1450 ImportModuleDirectory->dwRVAFunctionAddressList);
1453 /* Walk through function list and fixup addresses */
1454 while (*FunctionNameList != 0L)
1456 if ((*FunctionNameList) & 0x80000000)
1460 Hint = (*FunctionNameList) & 0xffff;
1465 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1466 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1468 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1470 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1474 ImportAddressList++;
1479 ps("Finished importing.\n");
1486 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1490 PIMAGE_EXPORT_DIRECTORY ExportDir;
1491 ULONG ExportDirSize;
1493 PVOID ExportAddress;
1495 PDWORD FunctionList, NameList;
1497 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1498 RtlImageDirectoryEntryToData(ModuleObject->Base,
1500 IMAGE_DIRECTORY_ENTRY_EXPORT,
1502 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1503 if (ExportDir == NULL)
1508 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1509 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1510 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1516 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1519 DPRINT(" Name:%s NameList[%d]:%s\n",
1522 (DWORD) ModuleObject->Base + NameList[Idx]);
1525 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1527 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1528 FunctionList[OrdinalList[Idx]]);
1529 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1530 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1532 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1533 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1534 DPRINT("ExportAddress: %p\n", ExportAddress);
1543 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1544 FunctionList[Hint - ExportDir->Base]);
1547 if (ExportAddress == NULL)
1549 CPRINT("Export not found for %d:%s\n",
1551 Name != NULL ? Name : "(Ordinal)");
1555 return(ExportAddress);
1560 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1565 PVOID ExportAddress;
1567 PDWORD FunctionList, NameList;
1568 PIMAGE_EXPORT_DIRECTORY ExportDir;
1569 ULONG ExportDirSize;
1571 static BOOLEAN EP = FALSE;
1573 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1574 RtlImageDirectoryEntryToData(ImportModuleBase,
1576 IMAGE_DIRECTORY_ENTRY_EXPORT,
1581 ps("ExportDir %x\n", ExportDir);
1584 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1585 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1586 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1592 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1594 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1596 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1597 FunctionList[OrdinalList[Idx]]);
1604 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1606 FunctionList[Hint - ExportDir->Base]);
1609 if (ExportAddress == 0)
1611 ps("Export not found for %d:%s\n",
1613 Name != NULL ? Name : "(Ordinal)");
1616 return ExportAddress;
1621 LdrPEFixupForward(PCHAR ForwardName)
1623 CHAR NameBuffer[128];
1624 UNICODE_STRING ModuleName;
1626 PMODULE_OBJECT ModuleObject;
1628 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1630 strcpy(NameBuffer, ForwardName);
1631 p = strchr(NameBuffer, '.');
1639 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1641 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1643 ModuleObject = LdrGetModuleObject(&ModuleName);
1644 RtlFreeUnicodeString(&ModuleName);
1646 DPRINT("ModuleObject: %p\n", ModuleObject);
1648 if (ModuleObject == NULL)
1650 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1654 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));