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;
56 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
57 STATIC MODULE_TEXT_SECTION LdrHalTextSection;
58 #endif /* LIBCAPTIVE */
61 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
63 /* FORWARD DECLARATIONS ******************************************************/
66 LdrProcessModule(PVOID ModuleLoadBase,
67 PUNICODE_STRING ModuleName,
68 PMODULE_OBJECT *ModuleObject);
71 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
77 #endif /* LIBCAPTIVE */
79 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
80 PUNICODE_STRING FullName);
83 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
84 IN PUNICODE_STRING String2);
87 /* PE Driver load support */
88 static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
89 PUNICODE_STRING FileName,
90 PMODULE_OBJECT *ModuleObject);
92 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
98 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
101 #endif /* LIBCAPTIVE */
104 LdrPEFixupForward(PCHAR ForwardName);
107 /* FUNCTIONS *****************************************************************/
112 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
114 PLIST_ENTRY current_entry;
115 MODULE_TEXT_SECTION* current;
117 current_entry = ModuleTextListHead.Flink;
118 while (current_entry != &ModuleTextListHead)
121 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
122 if (wcscmp(current->Name, Name) == 0)
126 current_entry = current_entry->Flink;
129 if (current_entry == &ModuleTextListHead)
138 PIMAGE_DOS_HEADER DosHeader;
139 PIMAGE_FILE_HEADER FileHeader;
140 PIMAGE_OPTIONAL_HEADER OptionalHeader;
141 PIMAGE_SECTION_HEADER SectionList;
143 InitializeListHead(&ModuleTextListHead);
145 /* Setup ntoskrnl.exe text section */
146 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
148 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
149 DosHeader->e_lfanew + sizeof(ULONG));
150 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
151 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
152 SectionList = (PIMAGE_SECTION_HEADER)
153 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
154 NtoskrnlTextSection.Base = KERNEL_BASE;
155 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
156 SectionList[0].VirtualAddress;
157 NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
158 NtoskrnlTextSection.OptionalHeader = OptionalHeader;
159 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
161 /* Setup hal.dll text section */
162 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
164 (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
165 DosHeader->e_lfanew + sizeof(ULONG));
166 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
167 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
168 SectionList = (PIMAGE_SECTION_HEADER)
169 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
170 LdrHalTextSection.Base = LdrHalBase;
171 LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
172 SectionList[0].VirtualAddress;
173 LdrHalTextSection.Name = HAL_MODULE_NAME;
174 LdrHalTextSection.OptionalHeader = OptionalHeader;
175 InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
177 /* Hook for KDB on initialization of the loader. */
178 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
183 LdrInitModuleManagement(VOID)
185 PIMAGE_DOS_HEADER DosHeader;
186 PMODULE_OBJECT ModuleObject;
188 /* Initialize the module list and spinlock */
189 InitializeListHead(&ModuleListHead);
190 KeInitializeSpinLock(&ModuleListLock);
192 /* Create module object for NTOSKRNL */
193 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
194 assert(ModuleObject != NULL);
195 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
197 /* Initialize ModuleObject data */
198 ModuleObject->Base = (PVOID) KERNEL_BASE;
199 ModuleObject->Flags = MODULE_FLAG_PE;
200 RtlCreateUnicodeString(&ModuleObject->FullName,
202 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
203 &ModuleObject->FullName);
205 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
206 ModuleObject->Image.PE.FileHeader =
207 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
208 DosHeader->e_lfanew + sizeof(ULONG));
209 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
210 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
211 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
212 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
213 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
214 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
215 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
216 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
217 ModuleObject->TextSection = &NtoskrnlTextSection;
219 InsertTailList(&ModuleListHead,
220 &ModuleObject->ListEntry);
222 /* Create module object for HAL */
223 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
224 assert(ModuleObject != NULL);
225 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
227 /* Initialize ModuleObject data */
228 ModuleObject->Base = (PVOID) LdrHalBase;
229 ModuleObject->Flags = MODULE_FLAG_PE;
231 RtlCreateUnicodeString(&ModuleObject->FullName,
233 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
234 &ModuleObject->FullName);
236 DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
237 ModuleObject->Image.PE.FileHeader =
238 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
239 DosHeader->e_lfanew + sizeof(ULONG));
240 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
241 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
242 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
243 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
244 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
245 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
246 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
247 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
248 ModuleObject->TextSection = &LdrHalTextSection;
250 InsertTailList(&ModuleListHead,
251 &ModuleObject->ListEntry);
255 LdrpLoadImage(PUNICODE_STRING DriverName,
257 PVOID *SectionPointer,
259 PVOID *ExportSectionPointer)
261 PMODULE_OBJECT ModuleObject;
264 ModuleObject = LdrGetModuleObject(DriverName);
265 if (ModuleObject == NULL)
267 Status = LdrLoadModule(DriverName, &ModuleObject);
268 if (!NT_SUCCESS(Status))
275 *ModuleBase = ModuleObject->Base;
277 // if (SectionPointer)
278 // *SectionPointer = ModuleObject->
281 *EntryPoint = ModuleObject->EntryPoint;
283 // if (ExportSectionPointer)
284 // *ExportSectionPointer = ModuleObject->
286 return(STATUS_SUCCESS);
291 LdrpUnloadImage(PVOID ModuleBase)
293 return(STATUS_NOT_IMPLEMENTED);
298 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
300 PDRIVER_INITIALIZE DriverEntry;
301 PMODULE_OBJECT ModuleObject;
304 ModuleObject = LdrGetModuleObject(ModuleName);
305 if (ModuleObject != NULL)
307 return(STATUS_IMAGE_ALREADY_LOADED);
310 Status = LdrLoadModule(ModuleName, &ModuleObject);
311 if (!NT_SUCCESS(Status))
316 DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
318 Status = DriverEntry(NULL, NULL);
319 if (!NT_SUCCESS(Status))
321 LdrUnloadModule(ModuleObject);
329 LdrLoadModule(PUNICODE_STRING Filename,
330 PMODULE_OBJECT *ModuleObject)
332 PVOID ModuleLoadBase;
335 OBJECT_ATTRIBUTES ObjectAttributes;
336 PMODULE_OBJECT Module;
337 FILE_STANDARD_INFORMATION FileStdInfo;
338 IO_STATUS_BLOCK IoStatusBlock;
340 *ModuleObject = NULL;
342 DPRINT("Loading Module %wZ...\n", Filename);
344 /* Open the Module */
345 InitializeObjectAttributes(&ObjectAttributes,
351 Status = NtOpenFile(&FileHandle,
356 FILE_SYNCHRONOUS_IO_NONALERT);
358 if (!NT_SUCCESS(Status))
360 CPRINT("Could not open module file: %wZ\n", Filename);
365 /* Get the size of the file */
366 Status = NtQueryInformationFile(FileHandle,
370 FileStandardInformation);
371 if (!NT_SUCCESS(Status))
373 CPRINT("Could not get file size\n");
379 /* Allocate nonpageable memory for driver */
380 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
381 FileStdInfo.EndOfFile.u.LowPart,
383 if (ModuleLoadBase == NULL)
385 CPRINT("Could not allocate memory for module");
387 return(STATUS_INSUFFICIENT_RESOURCES);
391 /* Load driver into memory chunk */
392 Status = NtReadFile(FileHandle,
396 FileStdInfo.EndOfFile.u.LowPart,
398 if (!NT_SUCCESS(Status))
400 CPRINT("Could not read module file into memory");
401 ExFreePool(ModuleLoadBase);
409 Status = LdrProcessModule(ModuleLoadBase,
412 if (!NT_SUCCESS(Status))
414 CPRINT("Could not process module");
415 ExFreePool(ModuleLoadBase);
420 ExFreePool(ModuleLoadBase);
422 *ModuleObject = Module;
424 /* Hook for KDB on loading a driver. */
425 KDB_LOADDRIVER_HOOK(Filename, Module);
427 return(STATUS_SUCCESS);
430 #endif /* LIBCAPTIVE */
433 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
437 /* Remove the module from the module list */
438 KeAcquireSpinLock(&ModuleListLock,&Irql);
439 RemoveEntryList(&ModuleObject->ListEntry);
440 KeReleaseSpinLock(&ModuleListLock, Irql);
442 /* Hook for KDB on unloading a driver. */
443 KDB_UNLOADDRIVER_HOOK(ModuleObject);
445 /* Free text section */
446 if (ModuleObject->TextSection != NULL)
448 ExFreePool(ModuleObject->TextSection->Name);
449 RemoveEntryList(&ModuleObject->TextSection->ListEntry);
450 ExFreePool(ModuleObject->TextSection);
451 ModuleObject->TextSection = NULL;
454 /* Free module section */
455 // MmFreeSection(ModuleObject->Base);
457 ExFreePool(ModuleObject);
459 return(STATUS_SUCCESS);
465 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
469 PMODULE_OBJECT ModuleObject;
470 UNICODE_STRING ModuleName;
471 PDEVICE_NODE DeviceNode;
474 WCHAR Buffer[MAX_PATH];
479 CHAR TextBuffer [256];
482 HalQueryDisplayParameters(&x, &y, &cx, &cy);
483 RtlFillMemory(TextBuffer, x, ' ');
484 TextBuffer[x] = '\0';
485 HalSetDisplayParameters(0, y-1);
486 HalDisplayString(TextBuffer);
488 sprintf(TextBuffer, "Initializing %s...\n", FileName);
489 HalSetDisplayParameters(0, y-1);
490 HalDisplayString(TextBuffer);
491 HalSetDisplayParameters(cx, cy);
493 /* Split the filename into base name and extension */
494 FileExt = strrchr(FileName, '.');
496 Length = FileExt - FileName;
498 Length = strlen(FileName);
500 if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
502 KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
503 return(STATUS_SUCCESS);
505 else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
507 CPRINT("Ignoring non-driver file %s\n", FileName);
508 return STATUS_SUCCESS;
511 /* Use IopRootDeviceNode for now */
512 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
513 if (!NT_SUCCESS(Status))
515 CPRINT("Driver load failed, status (%x)\n", Status);
519 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
521 Status = LdrProcessModule(ModuleLoadBase,
524 RtlFreeUnicodeString(&ModuleName);
525 if (ModuleObject == NULL)
527 IopFreeDeviceNode(DeviceNode);
528 CPRINT("Driver load failed, status (%x)\n", Status);
529 return(STATUS_UNSUCCESSFUL);
533 /* Get the service name from the module name */
534 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
536 Start = ModuleObject->BaseName.Buffer;
540 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
542 Length = Ext - Start;
544 Length = wcslen(Start);
546 wcsncpy(Buffer, Start, Length);
547 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
549 Status = IopInitializeDriver(ModuleObject->EntryPoint,
551 if (!NT_SUCCESS(Status))
553 IopFreeDeviceNode(DeviceNode);
554 CPRINT("Driver load failed, status (%x)\n", Status);
560 #endif /* LIBCAPTIVE */
563 LdrProcessModule(PVOID ModuleLoadBase,
564 PUNICODE_STRING ModuleName,
565 PMODULE_OBJECT *ModuleObject)
567 PIMAGE_DOS_HEADER PEDosHeader;
569 /* If MZ header exists */
570 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
571 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
573 return LdrPEProcessModule(ModuleLoadBase,
578 CPRINT("Module wasn't PE\n");
579 return STATUS_UNSUCCESSFUL;
584 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
588 if (ModuleObject->Flags & MODULE_FLAG_PE)
590 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
601 LdrpQueryModuleInformation(PVOID Buffer,
605 PLIST_ENTRY current_entry;
606 PMODULE_OBJECT current;
607 ULONG ModuleCount = 0;
608 PSYSTEM_MODULE_INFORMATION Smi;
609 ANSI_STRING AnsiName;
613 KeAcquireSpinLock(&ModuleListLock,&Irql);
615 /* calculate required size */
616 current_entry = ModuleListHead.Flink;
617 while (current_entry != (&ModuleListHead))
620 current_entry = current_entry->Flink;
623 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
624 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
628 KeReleaseSpinLock(&ModuleListLock, Irql);
629 return(STATUS_INFO_LENGTH_MISMATCH);
632 /* fill the buffer */
633 memset(Buffer, '=', Size);
635 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
636 Smi->Count = ModuleCount;
639 current_entry = ModuleListHead.Flink;
640 while (current_entry != (&ModuleListHead))
642 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
644 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
645 Smi->Module[ModuleCount].BaseAddress = current->Base;
646 Smi->Module[ModuleCount].Size = current->Length;
647 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
648 Smi->Module[ModuleCount].EntryIndex = ModuleCount;
651 AnsiName.MaximumLength = 256;
652 AnsiName.Buffer = Smi->Module[ModuleCount].Name;
653 RtlUnicodeStringToAnsiString(&AnsiName,
657 p = strrchr(AnsiName.Buffer, '\\');
660 Smi->Module[ModuleCount].PathLength = 0;
661 Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
666 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
667 Smi->Module[ModuleCount].NameLength = strlen(p);
671 current_entry = current_entry->Flink;
674 KeReleaseSpinLock(&ModuleListLock, Irql);
676 return(STATUS_SUCCESS);
679 #endif /* LIBCAPTIVE */
683 #endif /* LIBCAPTIVE */
685 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
686 PUNICODE_STRING FullName)
692 DPRINT("LdrpBuildModuleBaseName()\n");
693 DPRINT("FullName %wZ\n", FullName);
695 p = wcsrchr(FullName->Buffer, L'\\');
698 p = FullName->Buffer;
707 RtlCreateUnicodeString(&Name, p);
709 q = wcschr(Name.Buffer, L'.');
717 RtlCreateUnicodeString(BaseName, Name.Buffer);
718 RtlFreeUnicodeString(&Name);
723 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
724 IN PUNICODE_STRING String2)
730 if (String1 && String2)
732 /* Search String1 for last path component */
733 len1 = String1->Length / sizeof(WCHAR);
734 s1 = String1->Buffer;
735 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
739 if (i == String1->Length - sizeof(WCHAR))
747 len1 = (String1->Length - i) / sizeof(WCHAR);
752 /* Search String2 for last path component */
753 len2 = String2->Length / sizeof(WCHAR);
754 s2 = String2->Buffer;
755 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
759 if (i == String2->Length - sizeof(WCHAR))
767 len2 = (String2->Length - i) / sizeof(WCHAR);
772 /* Compare last path components */
777 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
778 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
779 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
781 if (!c1 || !c2 || c1 != c2)
792 LdrGetModuleObject(PUNICODE_STRING ModuleName)
794 PMODULE_OBJECT Module;
798 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
800 KeAcquireSpinLock(&ModuleListLock,&Irql);
802 Entry = ModuleListHead.Flink;
803 while (Entry != &ModuleListHead)
805 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
807 DPRINT("Comparing %wZ and %wZ\n",
811 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
813 DPRINT("Module %wZ\n", &Module->BaseName);
814 KeReleaseSpinLock(&ModuleListLock, Irql);
818 Entry = Entry->Flink;
821 KeReleaseSpinLock(&ModuleListLock, Irql);
823 DPRINT("Could not find module '%wZ'\n", ModuleName);
829 /* ---------------------------------------------- PE Module support */
832 LdrPEProcessModule(PVOID ModuleLoadBase,
833 PUNICODE_STRING FileName,
834 PMODULE_OBJECT *ModuleObject)
836 unsigned int DriverSize, Idx;
837 ULONG RelocDelta, NumRelocs;
838 DWORD CurrentSize, TotalRelocs;
841 PIMAGE_DOS_HEADER PEDosHeader;
842 PIMAGE_FILE_HEADER PEFileHeader;
843 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
844 PIMAGE_SECTION_HEADER PESectionHeaders;
845 PRELOCATION_DIRECTORY RelocDir;
846 PRELOCATION_ENTRY RelocEntry;
847 PMODULE_OBJECT LibraryModuleObject;
848 PMODULE_OBJECT CreatedModuleObject;
849 PVOID *ImportAddressList;
850 PULONG FunctionNameList;
853 UNICODE_STRING ModuleName;
854 UNICODE_STRING NameString;
855 WCHAR NameBuffer[60];
856 MODULE_TEXT_SECTION* ModuleTextSection;
860 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
862 /* Get header pointers */
863 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
864 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
865 PEDosHeader->e_lfanew);
866 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
867 PEDosHeader->e_lfanew + sizeof(ULONG));
868 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
869 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
870 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
871 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
872 sizeof(IMAGE_OPTIONAL_HEADER));
875 /* Check file magic numbers */
876 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
878 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
879 return STATUS_UNSUCCESSFUL;
881 if (PEDosHeader->e_lfanew == 0)
883 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
884 return STATUS_UNSUCCESSFUL;
886 if (*PEMagic != IMAGE_PE_MAGIC)
888 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
889 return STATUS_UNSUCCESSFUL;
891 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
893 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
894 return STATUS_UNSUCCESSFUL;
898 /* FIXME: if image is fixed-address load, then fail */
900 /* FIXME: check/verify OS version number */
902 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
903 PEOptionalHeader->Magic,
904 PEOptionalHeader->MajorLinkerVersion,
905 PEOptionalHeader->MinorLinkerVersion);
906 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
909 /* Determine the size of the module */
910 DriverSize = PEOptionalHeader->SizeOfImage;
911 DPRINT("DriverSize %x\n",DriverSize);
913 /* Allocate a virtual section for the module */
914 DriverBase = MmAllocateSection(DriverSize);
917 CPRINT("Failed to allocate a virtual section for driver\n");
918 return STATUS_UNSUCCESSFUL;
920 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
922 /* Copy headers over */
923 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
925 /* Copy image sections into virtual section */
926 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
928 // Copy current section into current offset of virtual section
929 if (PESectionHeaders[Idx].Characteristics &
930 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
932 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
933 PESectionHeaders[Idx].VirtualAddress + DriverBase);
934 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
935 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
936 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
937 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
941 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
942 PESectionHeaders[Idx].VirtualAddress + DriverBase);
943 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
944 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
947 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
948 PEOptionalHeader->SectionAlignment);
951 // CurrentBase = (PVOID)((DWORD)CurrentBase +
952 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
953 // PEOptionalHeader->SectionAlignment));
956 /* Perform relocation fixups */
957 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
958 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
959 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
960 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
962 PEOptionalHeader->ImageBase,
964 DPRINT("RelocDir %x\n",RelocDir);
966 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
968 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
970 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
971 PESectionHeaders[Idx].Name,
972 PESectionHeaders[Idx].PointerToRawData);
973 RelocDir = PESectionHeaders[Idx].PointerToRawData +
975 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
980 RelocDir = RelocDir + (ULONG)DriverBase;
981 CurrentSize = PEOptionalHeader->DataDirectory
982 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
984 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
986 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
988 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
990 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
992 RelocDir->VirtualAddress,
994 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
995 sizeof(RELOCATION_DIRECTORY));
996 for (Idx = 0; Idx < NumRelocs; Idx++)
1002 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1003 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1004 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1006 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1009 Type ? "HIGHLOW" : "ABS",
1011 (*RelocItem) + RelocDelta); */
1014 (*RelocItem) += RelocDelta;
1018 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1019 return STATUS_UNSUCCESSFUL;
1022 TotalRelocs += RelocDir->SizeOfBlock;
1023 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1024 RelocDir->SizeOfBlock);
1025 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1028 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1029 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1031 /* Perform import fixups */
1032 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1034 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1036 /* Process each import module */
1037 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1038 ((DWORD)DriverBase + PEOptionalHeader->
1039 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1040 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1041 while (ImportModuleDirectory->dwRVAModuleName)
1043 /* Check to make sure that import lib is kernel */
1044 pName = (PCHAR) DriverBase +
1045 ImportModuleDirectory->dwRVAModuleName;
1047 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1048 DPRINT("Import module: %wZ\n", &ModuleName);
1050 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1051 if (LibraryModuleObject == NULL)
1053 CPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1054 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
1055 wcscat(NameBuffer, ModuleName.Buffer);
1056 RtlInitUnicodeString(&NameString, NameBuffer);
1057 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1058 if (!NT_SUCCESS(Status))
1060 CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1064 /* Get the import address list */
1065 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1066 ImportModuleDirectory->dwRVAFunctionAddressList);
1068 /* Get the list of functions to import */
1069 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1071 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1072 ImportModuleDirectory->dwRVAFunctionNameList);
1076 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1077 ImportModuleDirectory->dwRVAFunctionAddressList);
1079 /* Walk through function list and fixup addresses */
1080 while (*FunctionNameList != 0L)
1082 if ((*FunctionNameList) & 0x80000000) // hint
1087 Hint = (*FunctionNameList) & 0xffff;
1091 pName = (PCHAR)((DWORD)DriverBase +
1092 *FunctionNameList + 2);
1093 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1095 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1097 /* Fixup the current import symbol */
1098 if (LibraryModuleObject != NULL)
1100 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1106 CPRINT("Unresolved kernel symbol: %s\n", pName);
1107 return STATUS_UNSUCCESSFUL;
1109 ImportAddressList++;
1113 RtlFreeUnicodeString(&ModuleName);
1115 ImportModuleDirectory++;
1119 /* Set the protections for the various parts of the driver */
1120 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1122 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1127 max(PESectionHeaders[Idx].Misc.VirtualSize,
1128 PESectionHeaders[Idx].SizeOfRawData);
1129 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1130 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1131 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1132 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1133 Characteristics & IMAGE_SECTION_CHAR_BSS))
1135 for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
1137 MmSetPageProtect(NULL, BaseAddress + (i * PAGE_SIZE),
1143 /* Create the module */
1144 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1145 if (CreatedModuleObject == NULL)
1147 return(STATUS_INSUFFICIENT_RESOURCES);
1150 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1152 /* Initialize ModuleObject data */
1153 CreatedModuleObject->Base = DriverBase;
1154 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1156 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1158 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1159 &CreatedModuleObject->FullName);
1161 CreatedModuleObject->EntryPoint =
1162 (PVOID)((DWORD)DriverBase +
1163 PEOptionalHeader->AddressOfEntryPoint);
1164 CreatedModuleObject->Length = DriverSize;
1165 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1167 CreatedModuleObject->Image.PE.FileHeader =
1168 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1170 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1171 CreatedModuleObject->Image.PE.OptionalHeader =
1172 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1173 sizeof(IMAGE_FILE_HEADER));
1174 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1175 CreatedModuleObject->Image.PE.SectionList =
1176 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1177 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1178 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1181 KeAcquireSpinLock(&ModuleListLock, &Irql);
1182 InsertTailList(&ModuleListHead,
1183 &CreatedModuleObject->ListEntry);
1184 KeReleaseSpinLock(&ModuleListLock, Irql);
1187 ModuleTextSection = ExAllocatePool(NonPagedPool,
1188 sizeof(MODULE_TEXT_SECTION));
1189 assert(ModuleTextSection);
1190 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1191 ModuleTextSection->Base = (ULONG)DriverBase;
1192 ModuleTextSection->Length = DriverSize;
1193 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1194 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1195 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1196 ModuleTextSection->OptionalHeader =
1197 CreatedModuleObject->Image.PE.OptionalHeader;
1198 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1200 CreatedModuleObject->TextSection = ModuleTextSection;
1202 *ModuleObject = CreatedModuleObject;
1204 DPRINT("Loading Module %wZ...\n", FileName);
1206 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1208 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1209 FileName, CreatedModuleObject->Base);
1212 return STATUS_SUCCESS;
1218 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1220 PVOID ImportModuleBase,
1224 ULONG RelocDelta, NumRelocs;
1225 ULONG CurrentSize, TotalRelocs;
1227 PIMAGE_DOS_HEADER PEDosHeader;
1228 PIMAGE_FILE_HEADER PEFileHeader;
1229 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1230 PIMAGE_SECTION_HEADER PESectionHeaders;
1231 PRELOCATION_DIRECTORY RelocDir;
1232 PRELOCATION_ENTRY RelocEntry;
1233 PVOID *ImportAddressList;
1234 PULONG FunctionNameList;
1238 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1240 /* Get header pointers */
1241 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1242 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1243 PEDosHeader->e_lfanew);
1244 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1245 PEDosHeader->e_lfanew + sizeof(ULONG));
1246 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1247 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1248 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1249 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1250 sizeof(IMAGE_OPTIONAL_HEADER));
1253 /* Check file magic numbers */
1254 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1258 if (PEDosHeader->e_lfanew == 0)
1262 if (*PEMagic != IMAGE_PE_MAGIC)
1266 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1271 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1272 PEOptionalHeader->Magic,
1273 PEOptionalHeader->MajorLinkerVersion,
1274 PEOptionalHeader->MinorLinkerVersion);
1275 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1277 /* Determine the size of the module */
1278 *DriverSize = PEOptionalHeader->SizeOfImage;
1279 ps("DriverSize %x\n",*DriverSize);
1281 /* Copy headers over */
1282 if (DriverBase != ModuleLoadBase)
1284 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1287 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1288 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1289 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1291 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1292 address as it is mapped */
1293 if (DriverBase != ModuleLoadBase)
1297 /* Copy image sections into virtual section */
1298 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1300 // Copy current section into current offset of virtual section
1301 if (PESectionHeaders[Idx].Characteristics &
1302 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1304 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1305 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1306 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1307 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1308 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1309 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1313 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1314 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1315 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1317 PESectionHeaders[Idx].Misc.VirtualSize);
1319 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1320 PEOptionalHeader->SectionAlignment);
1323 /* Perform relocation fixups */
1324 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1325 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1326 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1327 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1329 PEOptionalHeader->ImageBase,
1331 ps("RelocDir %x\n",RelocDir);
1333 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1335 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1337 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1338 PESectionHeaders[Idx].Name,
1339 PESectionHeaders[Idx].PointerToRawData);
1340 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1341 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1346 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1349 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1351 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1353 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1354 sizeof(RELOCATION_DIRECTORY));
1355 for (Idx = 0; Idx < NumRelocs; Idx++)
1361 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1362 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1363 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1366 (*RelocItem) += RelocDelta;
1370 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1374 TotalRelocs += RelocDir->SizeOfBlock;
1375 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1376 RelocDir->SizeOfBlock);
1379 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1380 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1384 /* Perform import fixups */
1385 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1387 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1389 /* Process each import module */
1390 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1391 ((ULONG)DriverBase + PEOptionalHeader->
1392 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1394 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1396 /* Check to make sure that import lib is kernel */
1397 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1399 ps("Import module: %s\n", pName);
1401 /* Get the import address list */
1402 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1403 ImportModuleDirectory->dwRVAFunctionAddressList);
1405 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1406 ImportModuleDirectory->dwRVAFunctionAddressList);
1407 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1409 /* Get the list of functions to import */
1410 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1412 ps("Using function name list.\n");
1414 FunctionNameList = (PULONG)((ULONG)DriverBase +
1415 ImportModuleDirectory->dwRVAFunctionNameList);
1419 ps("Using function address list.\n");
1421 FunctionNameList = (PULONG)((ULONG)DriverBase +
1422 ImportModuleDirectory->dwRVAFunctionAddressList);
1425 /* Walk through function list and fixup addresses */
1426 while (*FunctionNameList != 0L)
1428 if ((*FunctionNameList) & 0x80000000)
1432 Hint = (*FunctionNameList) & 0xffff;
1437 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1438 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1440 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1442 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1446 ImportAddressList++;
1451 ps("Finished importing.\n");
1456 #endif /* LIBCAPTIVE */
1459 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1463 PIMAGE_EXPORT_DIRECTORY ExportDir;
1464 ULONG ExportDirSize;
1466 PVOID ExportAddress;
1468 PDWORD FunctionList, NameList;
1470 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1471 RtlImageDirectoryEntryToData(ModuleObject->Base,
1473 IMAGE_DIRECTORY_ENTRY_EXPORT,
1475 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1476 if (ExportDir == NULL)
1481 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1482 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1483 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1489 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1492 DPRINT(" Name:%s NameList[%d]:%s\n",
1495 (DWORD) ModuleObject->Base + NameList[Idx]);
1498 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1500 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1501 FunctionList[OrdinalList[Idx]]);
1502 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1503 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1505 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1506 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1507 DPRINT("ExportAddress: %p\n", ExportAddress);
1517 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1518 FunctionList[Hint - ExportDir->Base]);
1519 #else /* !LIBCAPTIVE */
1520 /* Ordinals not supported by libcaptive */
1522 #endif /* !LIBCAPTIVE */
1525 if (ExportAddress == NULL)
1527 CPRINT("Export not found for %d:%s\n",
1529 Name != NULL ? Name : "(Ordinal)");
1533 return(ExportAddress);
1539 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1544 PVOID ExportAddress;
1546 PDWORD FunctionList, NameList;
1547 PIMAGE_EXPORT_DIRECTORY ExportDir;
1548 ULONG ExportDirSize;
1550 static BOOLEAN EP = FALSE;
1552 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1553 RtlImageDirectoryEntryToData(ImportModuleBase,
1555 IMAGE_DIRECTORY_ENTRY_EXPORT,
1560 ps("ExportDir %x\n", ExportDir);
1563 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1564 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1565 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1571 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1573 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1575 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1576 FunctionList[OrdinalList[Idx]]);
1583 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1585 FunctionList[Hint - ExportDir->Base]);
1588 if (ExportAddress == 0)
1590 ps("Export not found for %d:%s\n",
1592 Name != NULL ? Name : "(Ordinal)");
1595 return ExportAddress;
1598 #endif /* LIBCAPTIVE */
1601 LdrPEFixupForward(PCHAR ForwardName)
1603 CHAR NameBuffer[128];
1604 UNICODE_STRING ModuleName;
1606 PMODULE_OBJECT ModuleObject;
1608 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1610 strcpy(NameBuffer, ForwardName);
1611 p = strchr(NameBuffer, '.');
1619 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1621 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1623 ModuleObject = LdrGetModuleObject(&ModuleName);
1624 RtlFreeUnicodeString(&ModuleName);
1626 DPRINT("ModuleObject: %p\n", ModuleObject);
1628 if (ModuleObject == NULL)
1630 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1634 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));