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,
76 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
77 PUNICODE_STRING FullName);
80 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
81 IN PUNICODE_STRING String2);
84 /* PE Driver load support */
85 static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
86 PUNICODE_STRING FileName,
87 PMODULE_OBJECT *ModuleObject);
89 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
95 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
98 #endif /* LIBCAPTIVE */
101 LdrPEFixupForward(PCHAR ForwardName);
104 /* FUNCTIONS *****************************************************************/
109 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
111 PLIST_ENTRY current_entry;
112 MODULE_TEXT_SECTION* current;
114 current_entry = ModuleTextListHead.Flink;
115 while (current_entry != &ModuleTextListHead)
118 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
119 if (wcscmp(current->Name, Name) == 0)
123 current_entry = current_entry->Flink;
126 if (current_entry == &ModuleTextListHead)
135 PIMAGE_DOS_HEADER DosHeader;
136 PIMAGE_FILE_HEADER FileHeader;
137 PIMAGE_OPTIONAL_HEADER OptionalHeader;
138 PIMAGE_SECTION_HEADER SectionList;
140 InitializeListHead(&ModuleTextListHead);
142 /* Setup ntoskrnl.exe text section */
143 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
145 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
146 DosHeader->e_lfanew + sizeof(ULONG));
147 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
148 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
149 SectionList = (PIMAGE_SECTION_HEADER)
150 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
151 NtoskrnlTextSection.Base = KERNEL_BASE;
152 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
153 SectionList[0].VirtualAddress;
154 NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
155 NtoskrnlTextSection.OptionalHeader = OptionalHeader;
156 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
158 /* Setup hal.dll text section */
159 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
161 (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
162 DosHeader->e_lfanew + sizeof(ULONG));
163 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
164 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
165 SectionList = (PIMAGE_SECTION_HEADER)
166 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
167 LdrHalTextSection.Base = LdrHalBase;
168 LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
169 SectionList[0].VirtualAddress;
170 LdrHalTextSection.Name = HAL_MODULE_NAME;
171 LdrHalTextSection.OptionalHeader = OptionalHeader;
172 InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
174 /* Hook for KDB on initialization of the loader. */
175 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
180 LdrInitModuleManagement(VOID)
182 PIMAGE_DOS_HEADER DosHeader;
183 PMODULE_OBJECT ModuleObject;
185 /* Initialize the module list and spinlock */
186 InitializeListHead(&ModuleListHead);
187 KeInitializeSpinLock(&ModuleListLock);
189 /* Create module object for NTOSKRNL */
190 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
191 assert(ModuleObject != NULL);
192 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
194 /* Initialize ModuleObject data */
195 ModuleObject->Base = (PVOID) KERNEL_BASE;
196 ModuleObject->Flags = MODULE_FLAG_PE;
197 RtlCreateUnicodeString(&ModuleObject->FullName,
199 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
200 &ModuleObject->FullName);
202 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
203 ModuleObject->Image.PE.FileHeader =
204 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
205 DosHeader->e_lfanew + sizeof(ULONG));
206 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
207 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
208 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
209 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
210 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
211 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
212 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
213 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
214 ModuleObject->TextSection = &NtoskrnlTextSection;
216 InsertTailList(&ModuleListHead,
217 &ModuleObject->ListEntry);
219 /* Create module object for HAL */
220 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
221 assert(ModuleObject != NULL);
222 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
224 /* Initialize ModuleObject data */
225 ModuleObject->Base = (PVOID) LdrHalBase;
226 ModuleObject->Flags = MODULE_FLAG_PE;
228 RtlCreateUnicodeString(&ModuleObject->FullName,
230 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
231 &ModuleObject->FullName);
233 DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
234 ModuleObject->Image.PE.FileHeader =
235 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
236 DosHeader->e_lfanew + sizeof(ULONG));
237 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
238 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
239 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
240 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
241 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
242 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
243 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
244 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
245 ModuleObject->TextSection = &LdrHalTextSection;
247 InsertTailList(&ModuleListHead,
248 &ModuleObject->ListEntry);
252 LdrpLoadImage(PUNICODE_STRING DriverName,
254 PVOID *SectionPointer,
256 PVOID *ExportSectionPointer)
258 PMODULE_OBJECT ModuleObject;
261 ModuleObject = LdrGetModuleObject(DriverName);
262 if (ModuleObject == NULL)
264 Status = LdrLoadModule(DriverName, &ModuleObject);
265 if (!NT_SUCCESS(Status))
272 *ModuleBase = ModuleObject->Base;
274 // if (SectionPointer)
275 // *SectionPointer = ModuleObject->
278 *EntryPoint = ModuleObject->EntryPoint;
280 // if (ExportSectionPointer)
281 // *ExportSectionPointer = ModuleObject->
283 return(STATUS_SUCCESS);
288 LdrpUnloadImage(PVOID ModuleBase)
290 return(STATUS_NOT_IMPLEMENTED);
295 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
297 PDRIVER_INITIALIZE DriverEntry;
298 PMODULE_OBJECT ModuleObject;
301 ModuleObject = LdrGetModuleObject(ModuleName);
302 if (ModuleObject != NULL)
304 return(STATUS_IMAGE_ALREADY_LOADED);
307 Status = LdrLoadModule(ModuleName, &ModuleObject);
308 if (!NT_SUCCESS(Status))
313 DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
315 Status = DriverEntry(NULL, NULL);
316 if (!NT_SUCCESS(Status))
318 LdrUnloadModule(ModuleObject);
326 LdrLoadModule(PUNICODE_STRING Filename,
327 PMODULE_OBJECT *ModuleObject)
329 PVOID ModuleLoadBase;
332 OBJECT_ATTRIBUTES ObjectAttributes;
333 PMODULE_OBJECT Module;
334 FILE_STANDARD_INFORMATION FileStdInfo;
335 IO_STATUS_BLOCK IoStatusBlock;
337 *ModuleObject = NULL;
339 DPRINT("Loading Module %wZ...\n", Filename);
341 /* Open the Module */
342 InitializeObjectAttributes(&ObjectAttributes,
348 Status = NtOpenFile(&FileHandle,
353 FILE_SYNCHRONOUS_IO_NONALERT);
355 if (!NT_SUCCESS(Status))
357 CPRINT("Could not open module file: %wZ\n", Filename);
362 /* Get the size of the file */
363 Status = NtQueryInformationFile(FileHandle,
367 FileStandardInformation);
368 if (!NT_SUCCESS(Status))
370 CPRINT("Could not get file size\n");
376 /* Allocate nonpageable memory for driver */
377 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
378 FileStdInfo.EndOfFile.u.LowPart,
380 if (ModuleLoadBase == NULL)
382 CPRINT("Could not allocate memory for module");
384 return(STATUS_INSUFFICIENT_RESOURCES);
388 /* Load driver into memory chunk */
389 Status = NtReadFile(FileHandle,
393 FileStdInfo.EndOfFile.u.LowPart,
395 if (!NT_SUCCESS(Status))
397 CPRINT("Could not read module file into memory");
398 ExFreePool(ModuleLoadBase);
406 Status = LdrProcessModule(ModuleLoadBase,
409 if (!NT_SUCCESS(Status))
411 CPRINT("Could not process module");
412 ExFreePool(ModuleLoadBase);
417 ExFreePool(ModuleLoadBase);
419 *ModuleObject = Module;
421 /* Hook for KDB on loading a driver. */
422 KDB_LOADDRIVER_HOOK(Filename, Module);
424 return(STATUS_SUCCESS);
427 #endif /* LIBCAPTIVE */
430 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
434 /* Remove the module from the module list */
435 KeAcquireSpinLock(&ModuleListLock,&Irql);
436 RemoveEntryList(&ModuleObject->ListEntry);
437 KeReleaseSpinLock(&ModuleListLock, Irql);
439 /* Hook for KDB on unloading a driver. */
440 KDB_UNLOADDRIVER_HOOK(ModuleObject);
442 /* Free text section */
443 if (ModuleObject->TextSection != NULL)
445 ExFreePool(ModuleObject->TextSection->Name);
446 RemoveEntryList(&ModuleObject->TextSection->ListEntry);
447 ExFreePool(ModuleObject->TextSection);
448 ModuleObject->TextSection = NULL;
451 /* Free module section */
452 // MmFreeSection(ModuleObject->Base);
454 ExFreePool(ModuleObject);
456 return(STATUS_SUCCESS);
462 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
466 PMODULE_OBJECT ModuleObject;
467 UNICODE_STRING ModuleName;
468 PDEVICE_NODE DeviceNode;
471 WCHAR Buffer[MAX_PATH];
476 CHAR TextBuffer [256];
479 HalQueryDisplayParameters(&x, &y, &cx, &cy);
480 RtlFillMemory(TextBuffer, x, ' ');
481 TextBuffer[x] = '\0';
482 HalSetDisplayParameters(0, y-1);
483 HalDisplayString(TextBuffer);
485 sprintf(TextBuffer, "Initializing %s...\n", FileName);
486 HalSetDisplayParameters(0, y-1);
487 HalDisplayString(TextBuffer);
488 HalSetDisplayParameters(cx, cy);
490 /* Split the filename into base name and extension */
491 FileExt = strrchr(FileName, '.');
493 Length = FileExt - FileName;
495 Length = strlen(FileName);
497 if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
499 KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
500 return(STATUS_SUCCESS);
502 else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
504 CPRINT("Ignoring non-driver file %s\n", FileName);
505 return STATUS_SUCCESS;
508 /* Use IopRootDeviceNode for now */
509 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
510 if (!NT_SUCCESS(Status))
512 CPRINT("Driver load failed, status (%x)\n", Status);
516 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
518 Status = LdrProcessModule(ModuleLoadBase,
521 RtlFreeUnicodeString(&ModuleName);
522 if (ModuleObject == NULL)
524 IopFreeDeviceNode(DeviceNode);
525 CPRINT("Driver load failed, status (%x)\n", Status);
526 return(STATUS_UNSUCCESSFUL);
530 /* Get the service name from the module name */
531 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
533 Start = ModuleObject->BaseName.Buffer;
537 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
539 Length = Ext - Start;
541 Length = wcslen(Start);
543 wcsncpy(Buffer, Start, Length);
544 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
546 Status = IopInitializeDriver(ModuleObject->EntryPoint,
548 if (!NT_SUCCESS(Status))
550 IopFreeDeviceNode(DeviceNode);
551 CPRINT("Driver load failed, status (%x)\n", Status);
557 #endif /* LIBCAPTIVE */
560 LdrProcessModule(PVOID ModuleLoadBase,
561 PUNICODE_STRING ModuleName,
562 PMODULE_OBJECT *ModuleObject)
564 PIMAGE_DOS_HEADER PEDosHeader;
566 /* If MZ header exists */
567 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
568 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
570 return LdrPEProcessModule(ModuleLoadBase,
575 CPRINT("Module wasn't PE\n");
576 return STATUS_UNSUCCESSFUL;
581 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
585 if (ModuleObject->Flags & MODULE_FLAG_PE)
587 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
598 LdrpQueryModuleInformation(PVOID Buffer,
602 PLIST_ENTRY current_entry;
603 PMODULE_OBJECT current;
604 ULONG ModuleCount = 0;
605 PSYSTEM_MODULE_INFORMATION Smi;
606 ANSI_STRING AnsiName;
610 KeAcquireSpinLock(&ModuleListLock,&Irql);
612 /* calculate required size */
613 current_entry = ModuleListHead.Flink;
614 while (current_entry != (&ModuleListHead))
617 current_entry = current_entry->Flink;
620 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
621 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
625 KeReleaseSpinLock(&ModuleListLock, Irql);
626 return(STATUS_INFO_LENGTH_MISMATCH);
629 /* fill the buffer */
630 memset(Buffer, '=', Size);
632 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
633 Smi->Count = ModuleCount;
636 current_entry = ModuleListHead.Flink;
637 while (current_entry != (&ModuleListHead))
639 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
641 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
642 Smi->Module[ModuleCount].BaseAddress = current->Base;
643 Smi->Module[ModuleCount].Size = current->Length;
644 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
645 Smi->Module[ModuleCount].EntryIndex = ModuleCount;
648 AnsiName.MaximumLength = 256;
649 AnsiName.Buffer = Smi->Module[ModuleCount].Name;
650 RtlUnicodeStringToAnsiString(&AnsiName,
654 p = strrchr(AnsiName.Buffer, '\\');
657 Smi->Module[ModuleCount].PathLength = 0;
658 Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
663 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
664 Smi->Module[ModuleCount].NameLength = strlen(p);
668 current_entry = current_entry->Flink;
671 KeReleaseSpinLock(&ModuleListLock, Irql);
673 return(STATUS_SUCCESS);
676 #endif /* LIBCAPTIVE */
679 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
680 PUNICODE_STRING FullName)
686 DPRINT("LdrpBuildModuleBaseName()\n");
687 DPRINT("FullName %wZ\n", FullName);
689 p = wcsrchr(FullName->Buffer, L'\\');
692 p = FullName->Buffer;
701 RtlCreateUnicodeString(&Name, p);
703 q = wcschr(Name.Buffer, L'.');
711 RtlCreateUnicodeString(BaseName, Name.Buffer);
712 RtlFreeUnicodeString(&Name);
717 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
718 IN PUNICODE_STRING String2)
724 if (String1 && String2)
726 /* Search String1 for last path component */
727 len1 = String1->Length / sizeof(WCHAR);
728 s1 = String1->Buffer;
729 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
733 if (i == String1->Length - sizeof(WCHAR))
741 len1 = (String1->Length - i) / sizeof(WCHAR);
746 /* Search String2 for last path component */
747 len2 = String2->Length / sizeof(WCHAR);
748 s2 = String2->Buffer;
749 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
753 if (i == String2->Length - sizeof(WCHAR))
761 len2 = (String2->Length - i) / sizeof(WCHAR);
766 /* Compare last path components */
771 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
772 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
773 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
775 if (!c1 || !c2 || c1 != c2)
786 LdrGetModuleObject(PUNICODE_STRING ModuleName)
788 PMODULE_OBJECT Module;
792 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
794 KeAcquireSpinLock(&ModuleListLock,&Irql);
796 Entry = ModuleListHead.Flink;
797 while (Entry != &ModuleListHead)
799 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
801 DPRINT("Comparing %wZ and %wZ\n",
805 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
807 DPRINT("Module %wZ\n", &Module->BaseName);
808 KeReleaseSpinLock(&ModuleListLock, Irql);
812 Entry = Entry->Flink;
815 KeReleaseSpinLock(&ModuleListLock, Irql);
817 DPRINT("Could not find module '%wZ'\n", ModuleName);
823 /* ---------------------------------------------- PE Module support */
826 LdrPEProcessModule(PVOID ModuleLoadBase,
827 PUNICODE_STRING FileName,
828 PMODULE_OBJECT *ModuleObject)
830 unsigned int DriverSize, Idx;
831 ULONG RelocDelta, NumRelocs;
832 DWORD CurrentSize, TotalRelocs;
835 PIMAGE_DOS_HEADER PEDosHeader;
836 PIMAGE_FILE_HEADER PEFileHeader;
837 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
838 PIMAGE_SECTION_HEADER PESectionHeaders;
839 PRELOCATION_DIRECTORY RelocDir;
840 PRELOCATION_ENTRY RelocEntry;
841 PMODULE_OBJECT LibraryModuleObject;
842 PMODULE_OBJECT CreatedModuleObject;
843 PVOID *ImportAddressList;
844 PULONG FunctionNameList;
847 UNICODE_STRING ModuleName;
848 UNICODE_STRING NameString;
849 WCHAR NameBuffer[60];
850 MODULE_TEXT_SECTION* ModuleTextSection;
854 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
856 /* Get header pointers */
857 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
858 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
859 PEDosHeader->e_lfanew);
860 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
861 PEDosHeader->e_lfanew + sizeof(ULONG));
862 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
863 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
864 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
865 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
866 sizeof(IMAGE_OPTIONAL_HEADER));
869 /* Check file magic numbers */
870 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
872 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
873 return STATUS_UNSUCCESSFUL;
875 if (PEDosHeader->e_lfanew == 0)
877 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
878 return STATUS_UNSUCCESSFUL;
880 if (*PEMagic != IMAGE_PE_MAGIC)
882 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
883 return STATUS_UNSUCCESSFUL;
885 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
887 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
888 return STATUS_UNSUCCESSFUL;
892 /* FIXME: if image is fixed-address load, then fail */
894 /* FIXME: check/verify OS version number */
896 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
897 PEOptionalHeader->Magic,
898 PEOptionalHeader->MajorLinkerVersion,
899 PEOptionalHeader->MinorLinkerVersion);
900 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
903 /* Determine the size of the module */
904 DriverSize = PEOptionalHeader->SizeOfImage;
905 DPRINT("DriverSize %x\n",DriverSize);
907 /* Allocate a virtual section for the module */
908 DriverBase = MmAllocateSection(DriverSize);
911 CPRINT("Failed to allocate a virtual section for driver\n");
912 return STATUS_UNSUCCESSFUL;
914 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
916 /* Copy headers over */
917 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
919 /* Copy image sections into virtual section */
920 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
922 // Copy current section into current offset of virtual section
923 if (PESectionHeaders[Idx].Characteristics &
924 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
926 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
927 PESectionHeaders[Idx].VirtualAddress + DriverBase);
928 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
929 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
930 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
931 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
935 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
936 PESectionHeaders[Idx].VirtualAddress + DriverBase);
937 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
938 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
941 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
942 PEOptionalHeader->SectionAlignment);
945 // CurrentBase = (PVOID)((DWORD)CurrentBase +
946 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
947 // PEOptionalHeader->SectionAlignment));
950 /* Perform relocation fixups */
951 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
952 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
953 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
954 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
956 PEOptionalHeader->ImageBase,
958 DPRINT("RelocDir %x\n",RelocDir);
960 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
962 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
964 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
965 PESectionHeaders[Idx].Name,
966 PESectionHeaders[Idx].PointerToRawData);
967 RelocDir = PESectionHeaders[Idx].PointerToRawData +
969 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
974 RelocDir = RelocDir + (ULONG)DriverBase;
975 CurrentSize = PEOptionalHeader->DataDirectory
976 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
978 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
980 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
982 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
984 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
986 RelocDir->VirtualAddress,
988 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
989 sizeof(RELOCATION_DIRECTORY));
990 for (Idx = 0; Idx < NumRelocs; Idx++)
996 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
997 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
998 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1000 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1003 Type ? "HIGHLOW" : "ABS",
1005 (*RelocItem) + RelocDelta); */
1008 (*RelocItem) += RelocDelta;
1012 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1013 return STATUS_UNSUCCESSFUL;
1016 TotalRelocs += RelocDir->SizeOfBlock;
1017 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1018 RelocDir->SizeOfBlock);
1019 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1022 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1023 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1025 /* Perform import fixups */
1026 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1028 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1030 /* Process each import module */
1031 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1032 ((DWORD)DriverBase + PEOptionalHeader->
1033 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1034 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1035 while (ImportModuleDirectory->dwRVAModuleName)
1037 /* Check to make sure that import lib is kernel */
1038 pName = (PCHAR) DriverBase +
1039 ImportModuleDirectory->dwRVAModuleName;
1041 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1042 DPRINT("Import module: %wZ\n", &ModuleName);
1044 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1045 if (LibraryModuleObject == NULL)
1047 CPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1048 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
1049 wcscat(NameBuffer, ModuleName.Buffer);
1050 RtlInitUnicodeString(&NameString, NameBuffer);
1051 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1052 if (!NT_SUCCESS(Status))
1054 CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1058 /* Get the import address list */
1059 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1060 ImportModuleDirectory->dwRVAFunctionAddressList);
1062 /* Get the list of functions to import */
1063 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1065 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1066 ImportModuleDirectory->dwRVAFunctionNameList);
1070 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1071 ImportModuleDirectory->dwRVAFunctionAddressList);
1073 /* Walk through function list and fixup addresses */
1074 while (*FunctionNameList != 0L)
1076 if ((*FunctionNameList) & 0x80000000) // hint
1081 Hint = (*FunctionNameList) & 0xffff;
1085 pName = (PCHAR)((DWORD)DriverBase +
1086 *FunctionNameList + 2);
1087 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1089 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1091 /* Fixup the current import symbol */
1092 if (LibraryModuleObject != NULL)
1094 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1100 CPRINT("Unresolved kernel symbol: %s\n", pName);
1101 return STATUS_UNSUCCESSFUL;
1103 ImportAddressList++;
1107 RtlFreeUnicodeString(&ModuleName);
1109 ImportModuleDirectory++;
1113 /* Set the protections for the various parts of the driver */
1114 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1116 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1121 max(PESectionHeaders[Idx].Misc.VirtualSize,
1122 PESectionHeaders[Idx].SizeOfRawData);
1123 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1124 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1125 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1126 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1127 Characteristics & IMAGE_SECTION_CHAR_BSS))
1129 for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
1131 MmSetPageProtect(NULL, BaseAddress + (i * PAGE_SIZE),
1137 /* Create the module */
1138 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1139 if (CreatedModuleObject == NULL)
1141 return(STATUS_INSUFFICIENT_RESOURCES);
1144 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1146 /* Initialize ModuleObject data */
1147 CreatedModuleObject->Base = DriverBase;
1148 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1150 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1152 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1153 &CreatedModuleObject->FullName);
1155 CreatedModuleObject->EntryPoint =
1156 (PVOID)((DWORD)DriverBase +
1157 PEOptionalHeader->AddressOfEntryPoint);
1158 CreatedModuleObject->Length = DriverSize;
1159 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1161 CreatedModuleObject->Image.PE.FileHeader =
1162 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1164 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1165 CreatedModuleObject->Image.PE.OptionalHeader =
1166 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1167 sizeof(IMAGE_FILE_HEADER));
1168 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1169 CreatedModuleObject->Image.PE.SectionList =
1170 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1171 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1172 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1175 KeAcquireSpinLock(&ModuleListLock, &Irql);
1176 InsertTailList(&ModuleListHead,
1177 &CreatedModuleObject->ListEntry);
1178 KeReleaseSpinLock(&ModuleListLock, Irql);
1181 ModuleTextSection = ExAllocatePool(NonPagedPool,
1182 sizeof(MODULE_TEXT_SECTION));
1183 assert(ModuleTextSection);
1184 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1185 ModuleTextSection->Base = (ULONG)DriverBase;
1186 ModuleTextSection->Length = DriverSize;
1187 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1188 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1189 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1190 ModuleTextSection->OptionalHeader =
1191 CreatedModuleObject->Image.PE.OptionalHeader;
1192 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1194 CreatedModuleObject->TextSection = ModuleTextSection;
1196 *ModuleObject = CreatedModuleObject;
1198 DPRINT("Loading Module %wZ...\n", FileName);
1200 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1202 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1203 FileName, CreatedModuleObject->Base);
1206 return STATUS_SUCCESS;
1212 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1214 PVOID ImportModuleBase,
1218 ULONG RelocDelta, NumRelocs;
1219 ULONG CurrentSize, TotalRelocs;
1221 PIMAGE_DOS_HEADER PEDosHeader;
1222 PIMAGE_FILE_HEADER PEFileHeader;
1223 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1224 PIMAGE_SECTION_HEADER PESectionHeaders;
1225 PRELOCATION_DIRECTORY RelocDir;
1226 PRELOCATION_ENTRY RelocEntry;
1227 PVOID *ImportAddressList;
1228 PULONG FunctionNameList;
1232 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1234 /* Get header pointers */
1235 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1236 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1237 PEDosHeader->e_lfanew);
1238 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1239 PEDosHeader->e_lfanew + sizeof(ULONG));
1240 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1241 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1242 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1243 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1244 sizeof(IMAGE_OPTIONAL_HEADER));
1247 /* Check file magic numbers */
1248 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1252 if (PEDosHeader->e_lfanew == 0)
1256 if (*PEMagic != IMAGE_PE_MAGIC)
1260 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1265 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1266 PEOptionalHeader->Magic,
1267 PEOptionalHeader->MajorLinkerVersion,
1268 PEOptionalHeader->MinorLinkerVersion);
1269 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1271 /* Determine the size of the module */
1272 *DriverSize = PEOptionalHeader->SizeOfImage;
1273 ps("DriverSize %x\n",*DriverSize);
1275 /* Copy headers over */
1276 if (DriverBase != ModuleLoadBase)
1278 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1281 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1282 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1283 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1285 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1286 address as it is mapped */
1287 if (DriverBase != ModuleLoadBase)
1291 /* Copy image sections into virtual section */
1292 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1294 // Copy current section into current offset of virtual section
1295 if (PESectionHeaders[Idx].Characteristics &
1296 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1298 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1299 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1300 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1301 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1302 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1303 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1307 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1308 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1309 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1311 PESectionHeaders[Idx].Misc.VirtualSize);
1313 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1314 PEOptionalHeader->SectionAlignment);
1317 /* Perform relocation fixups */
1318 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1319 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1320 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1321 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1323 PEOptionalHeader->ImageBase,
1325 ps("RelocDir %x\n",RelocDir);
1327 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1329 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1331 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1332 PESectionHeaders[Idx].Name,
1333 PESectionHeaders[Idx].PointerToRawData);
1334 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1335 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1340 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1343 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1345 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1347 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1348 sizeof(RELOCATION_DIRECTORY));
1349 for (Idx = 0; Idx < NumRelocs; Idx++)
1355 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1356 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1357 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1360 (*RelocItem) += RelocDelta;
1364 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1368 TotalRelocs += RelocDir->SizeOfBlock;
1369 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1370 RelocDir->SizeOfBlock);
1373 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1374 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1378 /* Perform import fixups */
1379 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1381 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1383 /* Process each import module */
1384 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1385 ((ULONG)DriverBase + PEOptionalHeader->
1386 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1388 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1390 /* Check to make sure that import lib is kernel */
1391 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1393 ps("Import module: %s\n", pName);
1395 /* Get the import address list */
1396 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1397 ImportModuleDirectory->dwRVAFunctionAddressList);
1399 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1400 ImportModuleDirectory->dwRVAFunctionAddressList);
1401 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1403 /* Get the list of functions to import */
1404 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1406 ps("Using function name list.\n");
1408 FunctionNameList = (PULONG)((ULONG)DriverBase +
1409 ImportModuleDirectory->dwRVAFunctionNameList);
1413 ps("Using function address list.\n");
1415 FunctionNameList = (PULONG)((ULONG)DriverBase +
1416 ImportModuleDirectory->dwRVAFunctionAddressList);
1419 /* Walk through function list and fixup addresses */
1420 while (*FunctionNameList != 0L)
1422 if ((*FunctionNameList) & 0x80000000)
1426 Hint = (*FunctionNameList) & 0xffff;
1431 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1432 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1434 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1436 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1440 ImportAddressList++;
1445 ps("Finished importing.\n");
1450 #endif /* LIBCAPTIVE */
1453 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1457 PIMAGE_EXPORT_DIRECTORY ExportDir;
1458 ULONG ExportDirSize;
1460 PVOID ExportAddress;
1462 PDWORD FunctionList, NameList;
1464 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1465 RtlImageDirectoryEntryToData(ModuleObject->Base,
1467 IMAGE_DIRECTORY_ENTRY_EXPORT,
1469 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1470 if (ExportDir == NULL)
1475 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1476 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1477 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1483 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1486 DPRINT(" Name:%s NameList[%d]:%s\n",
1489 (DWORD) ModuleObject->Base + NameList[Idx]);
1492 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1494 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1495 FunctionList[OrdinalList[Idx]]);
1496 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1497 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1499 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1500 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1501 DPRINT("ExportAddress: %p\n", ExportAddress);
1511 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1512 FunctionList[Hint - ExportDir->Base]);
1513 #else /* !LIBCAPTIVE */
1514 /* Ordinals not supported by libcaptive */
1515 #endif /* !LIBCAPTIVE */
1518 if (ExportAddress == NULL)
1520 CPRINT("Export not found for %d:%s\n",
1522 Name != NULL ? Name : "(Ordinal)");
1526 return(ExportAddress);
1532 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1537 PVOID ExportAddress;
1539 PDWORD FunctionList, NameList;
1540 PIMAGE_EXPORT_DIRECTORY ExportDir;
1541 ULONG ExportDirSize;
1543 static BOOLEAN EP = FALSE;
1545 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1546 RtlImageDirectoryEntryToData(ImportModuleBase,
1548 IMAGE_DIRECTORY_ENTRY_EXPORT,
1553 ps("ExportDir %x\n", ExportDir);
1556 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1557 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1558 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1564 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1566 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1568 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1569 FunctionList[OrdinalList[Idx]]);
1576 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1578 FunctionList[Hint - ExportDir->Base]);
1581 if (ExportAddress == 0)
1583 ps("Export not found for %d:%s\n",
1585 Name != NULL ? Name : "(Ordinal)");
1588 return ExportAddress;
1591 #endif /* LIBCAPTIVE */
1594 LdrPEFixupForward(PCHAR ForwardName)
1596 CHAR NameBuffer[128];
1597 UNICODE_STRING ModuleName;
1599 PMODULE_OBJECT ModuleObject;
1601 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1603 strcpy(NameBuffer, ForwardName);
1604 p = strchr(NameBuffer, '.');
1612 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1614 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1616 ModuleObject = LdrGetModuleObject(&ModuleName);
1617 RtlFreeUnicodeString(&ModuleName);
1619 DPRINT("ModuleObject: %p\n", ModuleObject);
1621 if (ModuleObject == NULL)
1623 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1627 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));