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 PageNeedsWriteAccess(PVOID PageStart,
834 PIMAGE_FILE_HEADER PEFileHeader,
835 PIMAGE_SECTION_HEADER PESectionHeaders)
837 BOOL NeedsWriteAccess;
839 ULONG Characteristics;
843 NeedsWriteAccess = FALSE;
844 /* Set the protections for the various parts of the driver */
845 for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
847 Characteristics = PESectionHeaders[Idx].Characteristics;
848 if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
849 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
850 Characteristics & IMAGE_SECTION_CHAR_DATA ||
851 Characteristics & IMAGE_SECTION_CHAR_BSS))
854 max(PESectionHeaders[Idx].Misc.VirtualSize,
855 PESectionHeaders[Idx].SizeOfRawData);
856 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
857 NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
858 PageStart < (PVOID)((PCHAR) BaseAddress + Length);
862 return(NeedsWriteAccess);
866 LdrPEProcessModule(PVOID ModuleLoadBase,
867 PUNICODE_STRING FileName,
868 PMODULE_OBJECT *ModuleObject)
870 unsigned int DriverSize, Idx;
871 ULONG RelocDelta, NumRelocs;
872 DWORD CurrentSize, TotalRelocs;
875 PIMAGE_DOS_HEADER PEDosHeader;
876 PIMAGE_FILE_HEADER PEFileHeader;
877 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
878 PIMAGE_SECTION_HEADER PESectionHeaders;
879 PRELOCATION_DIRECTORY RelocDir;
880 PRELOCATION_ENTRY RelocEntry;
881 PMODULE_OBJECT LibraryModuleObject;
882 PMODULE_OBJECT CreatedModuleObject;
883 PVOID *ImportAddressList;
884 PULONG FunctionNameList;
887 UNICODE_STRING ModuleName;
888 UNICODE_STRING NameString;
889 WCHAR NameBuffer[60];
890 MODULE_TEXT_SECTION* ModuleTextSection;
894 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
896 /* Get header pointers */
897 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
898 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
899 PEDosHeader->e_lfanew);
900 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
901 PEDosHeader->e_lfanew + sizeof(ULONG));
902 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
903 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
904 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
905 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
906 sizeof(IMAGE_OPTIONAL_HEADER));
909 /* Check file magic numbers */
910 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
912 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
913 return STATUS_UNSUCCESSFUL;
915 if (PEDosHeader->e_lfanew == 0)
917 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
918 return STATUS_UNSUCCESSFUL;
920 if (*PEMagic != IMAGE_PE_MAGIC)
922 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
923 return STATUS_UNSUCCESSFUL;
925 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
927 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
928 return STATUS_UNSUCCESSFUL;
932 /* FIXME: if image is fixed-address load, then fail */
934 /* FIXME: check/verify OS version number */
936 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
937 PEOptionalHeader->Magic,
938 PEOptionalHeader->MajorLinkerVersion,
939 PEOptionalHeader->MinorLinkerVersion);
940 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
943 /* Determine the size of the module */
944 DriverSize = PEOptionalHeader->SizeOfImage;
945 DPRINT("DriverSize %x\n",DriverSize);
947 /* Allocate a virtual section for the module */
948 DriverBase = MmAllocateSection(DriverSize);
951 CPRINT("Failed to allocate a virtual section for driver\n");
952 return STATUS_UNSUCCESSFUL;
954 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
956 /* Copy headers over */
957 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
959 /* Copy image sections into virtual section */
960 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
962 // Copy current section into current offset of virtual section
963 if (PESectionHeaders[Idx].Characteristics &
964 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
966 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
967 PESectionHeaders[Idx].VirtualAddress + DriverBase);
968 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
969 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
970 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
971 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
975 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
976 PESectionHeaders[Idx].VirtualAddress + DriverBase);
977 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
978 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
981 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
982 PEOptionalHeader->SectionAlignment);
985 // CurrentBase = (PVOID)((DWORD)CurrentBase +
986 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
987 // PEOptionalHeader->SectionAlignment));
990 /* Perform relocation fixups */
991 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
992 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
993 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
994 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
996 PEOptionalHeader->ImageBase,
998 DPRINT("RelocDir %x\n",RelocDir);
1000 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1002 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1004 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1005 PESectionHeaders[Idx].Name,
1006 PESectionHeaders[Idx].PointerToRawData);
1007 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1009 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1014 RelocDir = RelocDir + (ULONG)DriverBase;
1015 CurrentSize = PEOptionalHeader->DataDirectory
1016 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1018 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1020 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1022 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1024 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1026 RelocDir->VirtualAddress,
1028 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1029 sizeof(RELOCATION_DIRECTORY));
1030 for (Idx = 0; Idx < NumRelocs; Idx++)
1036 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1037 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1038 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1040 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1043 Type ? "HIGHLOW" : "ABS",
1045 (*RelocItem) + RelocDelta); */
1048 (*RelocItem) += RelocDelta;
1052 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1053 return STATUS_UNSUCCESSFUL;
1056 TotalRelocs += RelocDir->SizeOfBlock;
1057 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1058 RelocDir->SizeOfBlock);
1059 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1062 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1063 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1065 /* Perform import fixups */
1066 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1068 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1070 /* Process each import module */
1071 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1072 ((DWORD)DriverBase + PEOptionalHeader->
1073 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1074 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1075 while (ImportModuleDirectory->dwRVAModuleName)
1077 /* Check to make sure that import lib is kernel */
1078 pName = (PCHAR) DriverBase +
1079 ImportModuleDirectory->dwRVAModuleName;
1081 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1082 DPRINT("Import module: %wZ\n", &ModuleName);
1084 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1085 if (LibraryModuleObject == NULL)
1087 CPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1088 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
1089 wcscat(NameBuffer, ModuleName.Buffer);
1090 RtlInitUnicodeString(&NameString, NameBuffer);
1091 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1092 if (!NT_SUCCESS(Status))
1094 CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1098 /* Get the import address list */
1099 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1100 ImportModuleDirectory->dwRVAFunctionAddressList);
1102 /* Get the list of functions to import */
1103 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1105 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1106 ImportModuleDirectory->dwRVAFunctionNameList);
1110 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1111 ImportModuleDirectory->dwRVAFunctionAddressList);
1113 /* Walk through function list and fixup addresses */
1114 while (*FunctionNameList != 0L)
1116 if ((*FunctionNameList) & 0x80000000) // hint
1121 Hint = (*FunctionNameList) & 0xffff;
1125 pName = (PCHAR)((DWORD)DriverBase +
1126 *FunctionNameList + 2);
1127 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1129 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1131 /* Fixup the current import symbol */
1132 if (LibraryModuleObject != NULL)
1134 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1140 CPRINT("Unresolved kernel symbol: %s\n", pName);
1141 return STATUS_UNSUCCESSFUL;
1143 ImportAddressList++;
1147 RtlFreeUnicodeString(&ModuleName);
1149 ImportModuleDirectory++;
1153 /* Set the protections for the various parts of the driver */
1154 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1156 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1160 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1161 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1162 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1163 Characteristics & IMAGE_SECTION_CHAR_BSS))
1166 max(PESectionHeaders[Idx].Misc.VirtualSize,
1167 PESectionHeaders[Idx].SizeOfRawData);
1168 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1169 PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
1170 if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1172 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1174 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1175 while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
1176 (PVOID)((PCHAR) BaseAddress + Length))
1178 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1179 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1181 if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
1182 ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1184 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1189 /* Create the module */
1190 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1191 if (CreatedModuleObject == NULL)
1193 return(STATUS_INSUFFICIENT_RESOURCES);
1196 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1198 /* Initialize ModuleObject data */
1199 CreatedModuleObject->Base = DriverBase;
1200 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1202 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1204 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1205 &CreatedModuleObject->FullName);
1207 CreatedModuleObject->EntryPoint =
1208 (PVOID)((DWORD)DriverBase +
1209 PEOptionalHeader->AddressOfEntryPoint);
1210 CreatedModuleObject->Length = DriverSize;
1211 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1213 CreatedModuleObject->Image.PE.FileHeader =
1214 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1216 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1217 CreatedModuleObject->Image.PE.OptionalHeader =
1218 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1219 sizeof(IMAGE_FILE_HEADER));
1220 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1221 CreatedModuleObject->Image.PE.SectionList =
1222 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1223 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1224 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1227 KeAcquireSpinLock(&ModuleListLock, &Irql);
1228 InsertTailList(&ModuleListHead,
1229 &CreatedModuleObject->ListEntry);
1230 KeReleaseSpinLock(&ModuleListLock, Irql);
1233 ModuleTextSection = ExAllocatePool(NonPagedPool,
1234 sizeof(MODULE_TEXT_SECTION));
1235 assert(ModuleTextSection);
1236 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1237 ModuleTextSection->Base = (ULONG)DriverBase;
1238 ModuleTextSection->Length = DriverSize;
1239 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1240 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1241 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1242 ModuleTextSection->OptionalHeader =
1243 CreatedModuleObject->Image.PE.OptionalHeader;
1244 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1246 CreatedModuleObject->TextSection = ModuleTextSection;
1248 *ModuleObject = CreatedModuleObject;
1250 DPRINT("Loading Module %wZ...\n", FileName);
1252 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1254 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1255 FileName, CreatedModuleObject->Base);
1258 return STATUS_SUCCESS;
1264 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1266 PVOID ImportModuleBase,
1270 ULONG RelocDelta, NumRelocs;
1271 ULONG CurrentSize, TotalRelocs;
1273 PIMAGE_DOS_HEADER PEDosHeader;
1274 PIMAGE_FILE_HEADER PEFileHeader;
1275 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1276 PIMAGE_SECTION_HEADER PESectionHeaders;
1277 PRELOCATION_DIRECTORY RelocDir;
1278 PRELOCATION_ENTRY RelocEntry;
1279 PVOID *ImportAddressList;
1280 PULONG FunctionNameList;
1284 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1286 /* Get header pointers */
1287 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1288 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1289 PEDosHeader->e_lfanew);
1290 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1291 PEDosHeader->e_lfanew + sizeof(ULONG));
1292 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1293 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1294 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1295 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1296 sizeof(IMAGE_OPTIONAL_HEADER));
1299 /* Check file magic numbers */
1300 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1304 if (PEDosHeader->e_lfanew == 0)
1308 if (*PEMagic != IMAGE_PE_MAGIC)
1312 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1317 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1318 PEOptionalHeader->Magic,
1319 PEOptionalHeader->MajorLinkerVersion,
1320 PEOptionalHeader->MinorLinkerVersion);
1321 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1323 /* Determine the size of the module */
1324 *DriverSize = PEOptionalHeader->SizeOfImage;
1325 ps("DriverSize %x\n",*DriverSize);
1327 /* Copy headers over */
1328 if (DriverBase != ModuleLoadBase)
1330 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1333 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1334 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1335 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1337 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1338 address as it is mapped */
1339 if (DriverBase != ModuleLoadBase)
1343 /* Copy image sections into virtual section */
1344 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1346 // Copy current section into current offset of virtual section
1347 if (PESectionHeaders[Idx].Characteristics &
1348 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1350 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1351 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1352 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1353 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1354 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1355 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1359 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1360 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1361 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1363 PESectionHeaders[Idx].Misc.VirtualSize);
1365 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1366 PEOptionalHeader->SectionAlignment);
1369 /* Perform relocation fixups */
1370 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1371 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1372 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1373 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1375 PEOptionalHeader->ImageBase,
1377 ps("RelocDir %x\n",RelocDir);
1379 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1381 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1383 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1384 PESectionHeaders[Idx].Name,
1385 PESectionHeaders[Idx].PointerToRawData);
1386 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1387 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1392 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1395 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1397 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1399 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1400 sizeof(RELOCATION_DIRECTORY));
1401 for (Idx = 0; Idx < NumRelocs; Idx++)
1407 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1408 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1409 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1412 (*RelocItem) += RelocDelta;
1416 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1420 TotalRelocs += RelocDir->SizeOfBlock;
1421 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1422 RelocDir->SizeOfBlock);
1425 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1426 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1430 /* Perform import fixups */
1431 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1433 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1435 /* Process each import module */
1436 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1437 ((ULONG)DriverBase + PEOptionalHeader->
1438 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1440 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1442 /* Check to make sure that import lib is kernel */
1443 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1445 ps("Import module: %s\n", pName);
1447 /* Get the import address list */
1448 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1449 ImportModuleDirectory->dwRVAFunctionAddressList);
1451 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1452 ImportModuleDirectory->dwRVAFunctionAddressList);
1453 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1455 /* Get the list of functions to import */
1456 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1458 ps("Using function name list.\n");
1460 FunctionNameList = (PULONG)((ULONG)DriverBase +
1461 ImportModuleDirectory->dwRVAFunctionNameList);
1465 ps("Using function address list.\n");
1467 FunctionNameList = (PULONG)((ULONG)DriverBase +
1468 ImportModuleDirectory->dwRVAFunctionAddressList);
1471 /* Walk through function list and fixup addresses */
1472 while (*FunctionNameList != 0L)
1474 if ((*FunctionNameList) & 0x80000000)
1478 Hint = (*FunctionNameList) & 0xffff;
1483 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1484 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1486 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1488 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1492 ImportAddressList++;
1497 ps("Finished importing.\n");
1502 #endif /* LIBCAPTIVE */
1505 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1509 PIMAGE_EXPORT_DIRECTORY ExportDir;
1510 ULONG ExportDirSize;
1512 PVOID ExportAddress;
1514 PDWORD FunctionList, NameList;
1516 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1517 RtlImageDirectoryEntryToData(ModuleObject->Base,
1519 IMAGE_DIRECTORY_ENTRY_EXPORT,
1521 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1522 if (ExportDir == NULL)
1527 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1528 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1529 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1535 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1538 DPRINT(" Name:%s NameList[%d]:%s\n",
1541 (DWORD) ModuleObject->Base + NameList[Idx]);
1544 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1546 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1547 FunctionList[OrdinalList[Idx]]);
1548 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1549 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1551 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1552 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1553 DPRINT("ExportAddress: %p\n", ExportAddress);
1563 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1564 FunctionList[Hint - ExportDir->Base]);
1565 #else /* !LIBCAPTIVE */
1566 /* Ordinals not supported by libcaptive */
1568 #endif /* !LIBCAPTIVE */
1571 if (ExportAddress == NULL)
1573 CPRINT("Export not found for %d:%s\n",
1575 Name != NULL ? Name : "(Ordinal)");
1579 return(ExportAddress);
1585 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1590 PVOID ExportAddress;
1592 PDWORD FunctionList, NameList;
1593 PIMAGE_EXPORT_DIRECTORY ExportDir;
1594 ULONG ExportDirSize;
1596 static BOOLEAN EP = FALSE;
1598 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1599 RtlImageDirectoryEntryToData(ImportModuleBase,
1601 IMAGE_DIRECTORY_ENTRY_EXPORT,
1606 ps("ExportDir %x\n", ExportDir);
1609 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1610 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1611 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1617 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1619 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1621 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1622 FunctionList[OrdinalList[Idx]]);
1629 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1631 FunctionList[Hint - ExportDir->Base]);
1634 if (ExportAddress == 0)
1636 ps("Export not found for %d:%s\n",
1638 Name != NULL ? Name : "(Ordinal)");
1641 return ExportAddress;
1644 #endif /* LIBCAPTIVE */
1647 LdrPEFixupForward(PCHAR ForwardName)
1649 CHAR NameBuffer[128];
1650 UNICODE_STRING ModuleName;
1652 PMODULE_OBJECT ModuleObject;
1654 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1656 strcpy(NameBuffer, ForwardName);
1657 p = strchr(NameBuffer, '.');
1665 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1667 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1669 ModuleObject = LdrGetModuleObject(&ModuleName);
1670 RtlFreeUnicodeString(&ModuleName);
1672 DPRINT("ModuleObject: %p\n", ModuleObject);
1674 if (ModuleObject == NULL)
1676 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1680 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));