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
21 * KJK 02/04/2003 Nebbet-ized a couple of type names
25 /* INCLUDES *****************************************************************/
28 #include <ddk/ntddk.h>
30 #include <internal/module.h>
31 #include <internal/ntoskrnl.h>
32 #include <internal/kd.h>
33 #include <internal/io.h>
34 #include <internal/mm.h>
35 #include <internal/ps.h>
36 #include <internal/ldr.h>
37 #include <internal/pool.h>
38 #include <internal/kd.h>
39 #include <ntos/minmax.h>
42 #include <internal/ntosdbg.h>
48 #include <internal/debug.h>
50 /* GLOBALS *******************************************************************/
52 LIST_ENTRY ModuleListHead;
53 KSPIN_LOCK ModuleListLock;
55 LIST_ENTRY ModuleTextListHead;
57 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
58 STATIC MODULE_TEXT_SECTION LdrHalTextSection;
59 #endif /* LIBCAPTIVE */
62 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
64 /* FORWARD DECLARATIONS ******************************************************/
67 LdrProcessModule(PVOID ModuleLoadBase,
68 PUNICODE_STRING ModuleName,
69 PMODULE_OBJECT *ModuleObject);
72 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
78 #endif /* LIBCAPTIVE */
80 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
81 PUNICODE_STRING FullName);
84 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
85 IN PUNICODE_STRING String2);
88 /* PE Driver load support */
89 static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
90 PUNICODE_STRING FileName,
91 PMODULE_OBJECT *ModuleObject);
93 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
99 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
102 #endif /* LIBCAPTIVE */
105 LdrPEFixupForward(PCHAR ForwardName);
108 /* FUNCTIONS *****************************************************************/
113 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
115 PLIST_ENTRY current_entry;
116 MODULE_TEXT_SECTION* current;
118 current_entry = ModuleTextListHead.Flink;
119 while (current_entry != &ModuleTextListHead)
122 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
123 if (wcscmp(current->Name, Name) == 0)
127 current_entry = current_entry->Flink;
130 if (current_entry == &ModuleTextListHead)
139 PIMAGE_DOS_HEADER DosHeader;
140 PIMAGE_FILE_HEADER FileHeader;
141 PIMAGE_OPTIONAL_HEADER OptionalHeader;
142 PIMAGE_SECTION_HEADER SectionList;
144 InitializeListHead(&ModuleTextListHead);
146 /* Setup ntoskrnl.exe text section */
147 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
149 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
150 DosHeader->e_lfanew + sizeof(ULONG));
151 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
152 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
153 SectionList = (PIMAGE_SECTION_HEADER)
154 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
155 NtoskrnlTextSection.Base = KERNEL_BASE;
156 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
157 SectionList[0].VirtualAddress;
158 NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
159 NtoskrnlTextSection.OptionalHeader = OptionalHeader;
160 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
162 /* Setup hal.dll text section */
163 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
165 (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
166 DosHeader->e_lfanew + sizeof(ULONG));
167 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
168 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
169 SectionList = (PIMAGE_SECTION_HEADER)
170 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
171 LdrHalTextSection.Base = LdrHalBase;
172 LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
173 SectionList[0].VirtualAddress;
174 LdrHalTextSection.Name = HAL_MODULE_NAME;
175 LdrHalTextSection.OptionalHeader = OptionalHeader;
176 InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
178 /* Hook for KDB on initialization of the loader. */
179 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
184 LdrInitModuleManagement(VOID)
186 PIMAGE_DOS_HEADER DosHeader;
187 PMODULE_OBJECT ModuleObject;
189 /* Initialize the module list and spinlock */
190 InitializeListHead(&ModuleListHead);
191 KeInitializeSpinLock(&ModuleListLock);
193 /* Create module object for NTOSKRNL */
194 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
195 assert(ModuleObject != NULL);
196 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
198 /* Initialize ModuleObject data */
199 ModuleObject->Base = (PVOID) KERNEL_BASE;
200 ModuleObject->Flags = MODULE_FLAG_PE;
201 RtlCreateUnicodeString(&ModuleObject->FullName,
203 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
204 &ModuleObject->FullName);
206 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
207 ModuleObject->Image.PE.FileHeader =
208 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
209 DosHeader->e_lfanew + sizeof(ULONG));
210 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
211 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
212 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
213 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
214 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
215 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
216 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
217 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
218 ModuleObject->TextSection = &NtoskrnlTextSection;
220 InsertTailList(&ModuleListHead,
221 &ModuleObject->ListEntry);
223 /* Create module object for HAL */
224 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
225 assert(ModuleObject != NULL);
226 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
228 /* Initialize ModuleObject data */
229 ModuleObject->Base = (PVOID) LdrHalBase;
230 ModuleObject->Flags = MODULE_FLAG_PE;
232 RtlCreateUnicodeString(&ModuleObject->FullName,
234 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
235 &ModuleObject->FullName);
237 DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
238 ModuleObject->Image.PE.FileHeader =
239 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
240 DosHeader->e_lfanew + sizeof(ULONG));
241 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
242 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
243 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
244 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
245 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
246 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
247 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
248 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
249 ModuleObject->TextSection = &LdrHalTextSection;
251 InsertTailList(&ModuleListHead,
252 &ModuleObject->ListEntry);
256 LdrpLoadImage(PUNICODE_STRING DriverName,
258 PVOID *SectionPointer,
260 PVOID *ExportSectionPointer)
262 PMODULE_OBJECT ModuleObject;
265 ModuleObject = LdrGetModuleObject(DriverName);
266 if (ModuleObject == NULL)
268 Status = LdrLoadModule(DriverName, &ModuleObject);
269 if (!NT_SUCCESS(Status))
276 *ModuleBase = ModuleObject->Base;
278 // if (SectionPointer)
279 // *SectionPointer = ModuleObject->
282 *EntryPoint = ModuleObject->EntryPoint;
284 // if (ExportSectionPointer)
285 // *ExportSectionPointer = ModuleObject->
287 return(STATUS_SUCCESS);
292 LdrpUnloadImage(PVOID ModuleBase)
294 return(STATUS_NOT_IMPLEMENTED);
299 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
301 PDRIVER_INITIALIZE DriverEntry;
302 PMODULE_OBJECT ModuleObject;
305 ModuleObject = LdrGetModuleObject(ModuleName);
306 if (ModuleObject != NULL)
308 return(STATUS_IMAGE_ALREADY_LOADED);
311 Status = LdrLoadModule(ModuleName, &ModuleObject);
312 if (!NT_SUCCESS(Status))
317 DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
319 Status = DriverEntry(NULL, NULL);
320 if (!NT_SUCCESS(Status))
322 LdrUnloadModule(ModuleObject);
330 LdrLoadModule(PUNICODE_STRING Filename,
331 PMODULE_OBJECT *ModuleObject)
333 PVOID ModuleLoadBase;
336 OBJECT_ATTRIBUTES ObjectAttributes;
337 PMODULE_OBJECT Module;
338 FILE_STANDARD_INFORMATION FileStdInfo;
339 IO_STATUS_BLOCK IoStatusBlock;
341 *ModuleObject = NULL;
343 DPRINT("Loading Module %wZ...\n", Filename);
345 /* Open the Module */
346 InitializeObjectAttributes(&ObjectAttributes,
352 Status = NtOpenFile(&FileHandle,
357 FILE_SYNCHRONOUS_IO_NONALERT);
359 if (!NT_SUCCESS(Status))
361 CPRINT("Could not open module file: %wZ\n", Filename);
366 /* Get the size of the file */
367 Status = NtQueryInformationFile(FileHandle,
371 FileStandardInformation);
372 if (!NT_SUCCESS(Status))
374 CPRINT("Could not get file size\n");
380 /* Allocate nonpageable memory for driver */
381 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
382 FileStdInfo.EndOfFile.u.LowPart,
384 if (ModuleLoadBase == NULL)
386 CPRINT("Could not allocate memory for module");
388 return(STATUS_INSUFFICIENT_RESOURCES);
392 /* Load driver into memory chunk */
393 Status = NtReadFile(FileHandle,
397 FileStdInfo.EndOfFile.u.LowPart,
399 if (!NT_SUCCESS(Status))
401 CPRINT("Could not read module file into memory");
402 ExFreePool(ModuleLoadBase);
410 Status = LdrProcessModule(ModuleLoadBase,
413 if (!NT_SUCCESS(Status))
415 CPRINT("Could not process module");
416 ExFreePool(ModuleLoadBase);
421 ExFreePool(ModuleLoadBase);
423 *ModuleObject = Module;
425 /* Hook for KDB on loading a driver. */
426 KDB_LOADDRIVER_HOOK(Filename, Module);
428 return(STATUS_SUCCESS);
431 #endif /* LIBCAPTIVE */
434 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
438 /* Remove the module from the module list */
439 KeAcquireSpinLock(&ModuleListLock,&Irql);
440 RemoveEntryList(&ModuleObject->ListEntry);
441 KeReleaseSpinLock(&ModuleListLock, Irql);
443 /* Hook for KDB on unloading a driver. */
444 KDB_UNLOADDRIVER_HOOK(ModuleObject);
446 /* Free text section */
447 if (ModuleObject->TextSection != NULL)
449 ExFreePool(ModuleObject->TextSection->Name);
450 RemoveEntryList(&ModuleObject->TextSection->ListEntry);
451 ExFreePool(ModuleObject->TextSection);
452 ModuleObject->TextSection = NULL;
455 /* Free module section */
456 // MmFreeSection(ModuleObject->Base);
458 ExFreePool(ModuleObject);
460 return(STATUS_SUCCESS);
466 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
470 PMODULE_OBJECT ModuleObject;
471 UNICODE_STRING ModuleName;
472 PDEVICE_NODE DeviceNode;
475 WCHAR Buffer[MAX_PATH];
480 CHAR TextBuffer [256];
483 HalQueryDisplayParameters(&x, &y, &cx, &cy);
484 RtlFillMemory(TextBuffer, x, ' ');
485 TextBuffer[x] = '\0';
486 HalSetDisplayParameters(0, y-1);
487 HalDisplayString(TextBuffer);
489 sprintf(TextBuffer, "Initializing %s...\n", FileName);
490 HalSetDisplayParameters(0, y-1);
491 HalDisplayString(TextBuffer);
492 HalSetDisplayParameters(cx, cy);
494 /* Split the filename into base name and extension */
495 FileExt = strrchr(FileName, '.');
497 Length = FileExt - FileName;
499 Length = strlen(FileName);
501 if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
503 KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
504 return(STATUS_SUCCESS);
506 else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
508 CPRINT("Ignoring non-driver file %s\n", FileName);
509 return STATUS_SUCCESS;
512 /* Use IopRootDeviceNode for now */
513 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
514 if (!NT_SUCCESS(Status))
516 CPRINT("Driver load failed, status (%x)\n", Status);
520 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
522 Status = LdrProcessModule(ModuleLoadBase,
525 RtlFreeUnicodeString(&ModuleName);
526 if (ModuleObject == NULL)
528 IopFreeDeviceNode(DeviceNode);
529 CPRINT("Driver load failed, status (%x)\n", Status);
530 return(STATUS_UNSUCCESSFUL);
534 /* Get the service name from the module name */
535 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
537 Start = ModuleObject->BaseName.Buffer;
541 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
543 Length = Ext - Start;
545 Length = wcslen(Start);
547 wcsncpy(Buffer, Start, Length);
549 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
551 Status = IopInitializeDriver(ModuleObject->EntryPoint,
553 if (!NT_SUCCESS(Status))
555 IopFreeDeviceNode(DeviceNode);
556 CPRINT("Driver load failed, status (%x)\n", Status);
562 #endif /* LIBCAPTIVE */
565 LdrProcessModule(PVOID ModuleLoadBase,
566 PUNICODE_STRING ModuleName,
567 PMODULE_OBJECT *ModuleObject)
569 PIMAGE_DOS_HEADER PEDosHeader;
571 /* If MZ header exists */
572 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
573 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
575 return LdrPEProcessModule(ModuleLoadBase,
580 CPRINT("Module wasn't PE\n");
581 return STATUS_UNSUCCESSFUL;
586 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
590 if (ModuleObject->Flags & MODULE_FLAG_PE)
592 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
603 LdrpQueryModuleInformation(PVOID Buffer,
607 PLIST_ENTRY current_entry;
608 PMODULE_OBJECT current;
609 ULONG ModuleCount = 0;
611 ANSI_STRING AnsiName;
615 KeAcquireSpinLock(&ModuleListLock,&Irql);
617 /* calculate required size */
618 current_entry = ModuleListHead.Flink;
619 while (current_entry != (&ModuleListHead))
622 current_entry = current_entry->Flink;
625 *ReqSize = sizeof(SYSTEM_MODULES)+
626 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION);
630 KeReleaseSpinLock(&ModuleListLock, Irql);
631 return(STATUS_INFO_LENGTH_MISMATCH);
634 /* fill the buffer */
635 memset(Buffer, '=', Size);
637 Smi = (PSYSTEM_MODULES)Buffer;
638 Smi->Count = ModuleCount;
641 current_entry = ModuleListHead.Flink;
642 while (current_entry != (&ModuleListHead))
644 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
646 Smi->Modules[ModuleCount].Reserved[0] = 0; /* Always 0 */
647 Smi->Modules[ModuleCount].Reserved[1] = 0; /* Always 0 */
648 Smi->Modules[ModuleCount].Base = current->Base;
649 Smi->Modules[ModuleCount].Size = current->Length;
650 Smi->Modules[ModuleCount].Flags = 0; /* Flags ??? (GN) */
651 Smi->Modules[ModuleCount].Index = ModuleCount;
652 Smi->Modules[ModuleCount].Unknown = 0;
653 Smi->Modules[ModuleCount].LoadCount = 0; /* FIXME */
656 AnsiName.MaximumLength = 256;
657 AnsiName.Buffer = Smi->Modules[ModuleCount].ImageName;
658 RtlUnicodeStringToAnsiString(&AnsiName,
662 p = strrchr(AnsiName.Buffer, '\\');
665 Smi->Modules[ModuleCount].ModuleNameOffset = 0;
670 Smi->Modules[ModuleCount].ModuleNameOffset = p - AnsiName.Buffer;
674 current_entry = current_entry->Flink;
677 KeReleaseSpinLock(&ModuleListLock, Irql);
679 return(STATUS_SUCCESS);
682 #endif /* LIBCAPTIVE */
686 #endif /* LIBCAPTIVE */
688 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
689 PUNICODE_STRING FullName)
695 DPRINT("LdrpBuildModuleBaseName()\n");
696 DPRINT("FullName %wZ\n", FullName);
698 p = wcsrchr(FullName->Buffer, L'\\');
701 p = FullName->Buffer;
710 RtlCreateUnicodeString(&Name, p);
712 q = wcschr(Name.Buffer, L'.');
720 RtlCreateUnicodeString(BaseName, Name.Buffer);
721 RtlFreeUnicodeString(&Name);
726 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
727 IN PUNICODE_STRING String2)
733 if (String1 && String2)
735 /* Search String1 for last path component */
736 len1 = String1->Length / sizeof(WCHAR);
737 s1 = String1->Buffer;
738 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
742 if (i == String1->Length - sizeof(WCHAR))
750 len1 = (String1->Length - i) / sizeof(WCHAR);
755 /* Search String2 for last path component */
756 len2 = String2->Length / sizeof(WCHAR);
757 s2 = String2->Buffer;
758 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
762 if (i == String2->Length - sizeof(WCHAR))
770 len2 = (String2->Length - i) / sizeof(WCHAR);
775 /* Compare last path components */
780 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
781 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
782 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
784 if (!c1 || !c2 || c1 != c2)
795 LdrGetModuleObject(PUNICODE_STRING ModuleName)
797 PMODULE_OBJECT Module;
801 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
803 KeAcquireSpinLock(&ModuleListLock,&Irql);
805 Entry = ModuleListHead.Flink;
806 while (Entry != &ModuleListHead)
808 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
810 DPRINT("Comparing %wZ and %wZ\n",
814 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
816 DPRINT("Module %wZ\n", &Module->BaseName);
817 KeReleaseSpinLock(&ModuleListLock, Irql);
821 Entry = Entry->Flink;
824 KeReleaseSpinLock(&ModuleListLock, Irql);
826 DPRINT("Could not find module '%wZ'\n", ModuleName);
832 /* ---------------------------------------------- PE Module support */
835 PageNeedsWriteAccess(PVOID PageStart,
837 PIMAGE_FILE_HEADER PEFileHeader,
838 PIMAGE_SECTION_HEADER PESectionHeaders)
840 BOOL NeedsWriteAccess;
842 ULONG Characteristics;
846 NeedsWriteAccess = FALSE;
847 /* Set the protections for the various parts of the driver */
848 for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
850 Characteristics = PESectionHeaders[Idx].Characteristics;
851 if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
852 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
853 Characteristics & IMAGE_SECTION_CHAR_DATA ||
854 Characteristics & IMAGE_SECTION_CHAR_BSS))
857 max(PESectionHeaders[Idx].Misc.VirtualSize,
858 PESectionHeaders[Idx].SizeOfRawData);
859 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
860 NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
861 PageStart < (PVOID)((PCHAR) BaseAddress + Length);
865 return(NeedsWriteAccess);
869 LdrPEProcessModule(PVOID ModuleLoadBase,
870 PUNICODE_STRING FileName,
871 PMODULE_OBJECT *ModuleObject)
873 unsigned int DriverSize, Idx;
874 ULONG RelocDelta, NumRelocs;
875 DWORD CurrentSize, TotalRelocs;
878 PIMAGE_DOS_HEADER PEDosHeader;
879 PIMAGE_FILE_HEADER PEFileHeader;
880 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
881 PIMAGE_SECTION_HEADER PESectionHeaders;
882 PRELOCATION_DIRECTORY RelocDir;
883 PRELOCATION_ENTRY RelocEntry;
884 PMODULE_OBJECT LibraryModuleObject;
885 PMODULE_OBJECT CreatedModuleObject;
886 PVOID *ImportAddressList;
887 PULONG FunctionNameList;
890 UNICODE_STRING ModuleName;
891 UNICODE_STRING NameString;
892 WCHAR NameBuffer[60];
893 MODULE_TEXT_SECTION* ModuleTextSection;
897 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
899 /* Get header pointers */
900 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
901 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
902 PEDosHeader->e_lfanew);
903 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
904 PEDosHeader->e_lfanew + sizeof(ULONG));
905 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
906 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
907 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
908 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
909 sizeof(IMAGE_OPTIONAL_HEADER));
912 /* Check file magic numbers */
913 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
915 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
916 return STATUS_UNSUCCESSFUL;
918 if (PEDosHeader->e_lfanew == 0)
920 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
921 return STATUS_UNSUCCESSFUL;
923 if (*PEMagic != IMAGE_PE_MAGIC)
925 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
926 return STATUS_UNSUCCESSFUL;
928 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
930 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
931 return STATUS_UNSUCCESSFUL;
935 /* FIXME: if image is fixed-address load, then fail */
937 /* FIXME: check/verify OS version number */
939 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
940 PEOptionalHeader->Magic,
941 PEOptionalHeader->MajorLinkerVersion,
942 PEOptionalHeader->MinorLinkerVersion);
943 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
946 /* Determine the size of the module */
947 DriverSize = PEOptionalHeader->SizeOfImage;
948 DPRINT("DriverSize %x\n",DriverSize);
950 /* Allocate a virtual section for the module */
951 DriverBase = MmAllocateSection(DriverSize);
954 CPRINT("Failed to allocate a virtual section for driver\n");
955 return STATUS_UNSUCCESSFUL;
957 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
959 /* Copy headers over */
960 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
962 /* Copy image sections into virtual section */
963 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
965 // Copy current section into current offset of virtual section
966 if (PESectionHeaders[Idx].Characteristics &
967 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
969 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
970 PESectionHeaders[Idx].VirtualAddress + DriverBase);
971 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
972 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
973 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
974 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
978 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
979 PESectionHeaders[Idx].VirtualAddress + DriverBase);
980 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
981 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
984 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
985 PEOptionalHeader->SectionAlignment);
988 // CurrentBase = (PVOID)((DWORD)CurrentBase +
989 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
990 // PEOptionalHeader->SectionAlignment));
993 /* Perform relocation fixups */
994 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
995 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
996 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
997 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
999 PEOptionalHeader->ImageBase,
1001 DPRINT("RelocDir %x\n",RelocDir);
1003 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1005 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1007 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1008 PESectionHeaders[Idx].Name,
1009 PESectionHeaders[Idx].PointerToRawData);
1010 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1012 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1017 RelocDir = RelocDir + (ULONG)DriverBase;
1018 CurrentSize = PEOptionalHeader->DataDirectory
1019 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1021 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1023 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1025 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1027 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1029 RelocDir->VirtualAddress,
1031 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1032 sizeof(RELOCATION_DIRECTORY));
1033 for (Idx = 0; Idx < NumRelocs; Idx++)
1039 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1040 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1041 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1043 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1046 Type ? "HIGHLOW" : "ABS",
1048 (*RelocItem) + RelocDelta); */
1051 (*RelocItem) += RelocDelta;
1055 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1056 return STATUS_UNSUCCESSFUL;
1059 TotalRelocs += RelocDir->SizeOfBlock;
1060 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1061 RelocDir->SizeOfBlock);
1062 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1065 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1066 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1068 /* Perform import fixups */
1069 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1071 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1073 /* Process each import module */
1074 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1075 ((DWORD)DriverBase + PEOptionalHeader->
1076 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1077 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1078 while (ImportModuleDirectory->dwRVAModuleName)
1080 /* Check to make sure that import lib is kernel */
1081 pName = (PCHAR) DriverBase +
1082 ImportModuleDirectory->dwRVAModuleName;
1084 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1085 DPRINT("Import module: %wZ\n", &ModuleName);
1087 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1088 if (LibraryModuleObject == NULL)
1090 DPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1091 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
1092 wcscat(NameBuffer, ModuleName.Buffer);
1093 RtlInitUnicodeString(&NameString, NameBuffer);
1094 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1095 if (!NT_SUCCESS(Status))
1097 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\"));
1098 wcscat(NameBuffer, ModuleName.Buffer);
1099 RtlInitUnicodeString(&NameString, NameBuffer);
1100 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1101 if (!NT_SUCCESS(Status))
1103 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1108 /* Get the import address list */
1109 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1110 ImportModuleDirectory->dwRVAFunctionAddressList);
1112 /* Get the list of functions to import */
1113 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1115 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1116 ImportModuleDirectory->dwRVAFunctionNameList);
1120 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1121 ImportModuleDirectory->dwRVAFunctionAddressList);
1123 /* Walk through function list and fixup addresses */
1124 while (*FunctionNameList != 0L)
1126 if ((*FunctionNameList) & 0x80000000) // hint
1131 Hint = (*FunctionNameList) & 0xffff;
1135 pName = (PCHAR)((DWORD)DriverBase +
1136 *FunctionNameList + 2);
1137 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1139 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1141 /* Fixup the current import symbol */
1142 if (LibraryModuleObject != NULL)
1144 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1150 CPRINT("Unresolved kernel symbol: %s\n", pName);
1151 return STATUS_UNSUCCESSFUL;
1153 ImportAddressList++;
1157 RtlFreeUnicodeString(&ModuleName);
1159 ImportModuleDirectory++;
1163 /* Set the protections for the various parts of the driver */
1164 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1166 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1170 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1171 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1172 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1173 Characteristics & IMAGE_SECTION_CHAR_BSS))
1176 max(PESectionHeaders[Idx].Misc.VirtualSize,
1177 PESectionHeaders[Idx].SizeOfRawData);
1178 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1179 PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
1180 if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1182 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1184 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1185 while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
1186 (PVOID)((PCHAR) BaseAddress + Length))
1188 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1189 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1191 if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
1192 ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1194 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1199 /* Create the module */
1200 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1201 if (CreatedModuleObject == NULL)
1203 return(STATUS_INSUFFICIENT_RESOURCES);
1206 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1208 /* Initialize ModuleObject data */
1209 CreatedModuleObject->Base = DriverBase;
1210 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1212 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1214 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1215 &CreatedModuleObject->FullName);
1217 CreatedModuleObject->EntryPoint =
1218 (PVOID)((DWORD)DriverBase +
1219 PEOptionalHeader->AddressOfEntryPoint);
1220 CreatedModuleObject->Length = DriverSize;
1221 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1223 CreatedModuleObject->Image.PE.FileHeader =
1224 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1226 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1227 CreatedModuleObject->Image.PE.OptionalHeader =
1228 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1229 sizeof(IMAGE_FILE_HEADER));
1230 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1231 CreatedModuleObject->Image.PE.SectionList =
1232 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1233 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1234 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1237 KeAcquireSpinLock(&ModuleListLock, &Irql);
1238 InsertTailList(&ModuleListHead,
1239 &CreatedModuleObject->ListEntry);
1240 KeReleaseSpinLock(&ModuleListLock, Irql);
1243 ModuleTextSection = ExAllocatePool(NonPagedPool,
1244 sizeof(MODULE_TEXT_SECTION));
1245 assert(ModuleTextSection);
1246 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1247 ModuleTextSection->Base = (ULONG)DriverBase;
1248 ModuleTextSection->Length = DriverSize;
1249 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1250 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1251 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1252 ModuleTextSection->OptionalHeader =
1253 CreatedModuleObject->Image.PE.OptionalHeader;
1254 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1256 CreatedModuleObject->TextSection = ModuleTextSection;
1258 *ModuleObject = CreatedModuleObject;
1260 DPRINT("Loading Module %wZ...\n", FileName);
1262 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1264 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1265 FileName, CreatedModuleObject->Base);
1268 return STATUS_SUCCESS;
1274 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1276 PVOID ImportModuleBase,
1280 ULONG RelocDelta, NumRelocs;
1281 ULONG CurrentSize, TotalRelocs;
1283 PIMAGE_DOS_HEADER PEDosHeader;
1284 PIMAGE_FILE_HEADER PEFileHeader;
1285 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1286 PIMAGE_SECTION_HEADER PESectionHeaders;
1287 PRELOCATION_DIRECTORY RelocDir;
1288 PRELOCATION_ENTRY RelocEntry;
1289 PVOID *ImportAddressList;
1290 PULONG FunctionNameList;
1294 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1296 /* Get header pointers */
1297 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1298 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1299 PEDosHeader->e_lfanew);
1300 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1301 PEDosHeader->e_lfanew + sizeof(ULONG));
1302 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1303 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1304 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1305 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1306 sizeof(IMAGE_OPTIONAL_HEADER));
1309 /* Check file magic numbers */
1310 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1314 if (PEDosHeader->e_lfanew == 0)
1318 if (*PEMagic != IMAGE_PE_MAGIC)
1322 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1327 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1328 PEOptionalHeader->Magic,
1329 PEOptionalHeader->MajorLinkerVersion,
1330 PEOptionalHeader->MinorLinkerVersion);
1331 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1333 /* Determine the size of the module */
1334 *DriverSize = PEOptionalHeader->SizeOfImage;
1335 ps("DriverSize %x\n",*DriverSize);
1337 /* Copy headers over */
1338 if (DriverBase != ModuleLoadBase)
1340 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1343 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1344 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1345 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1347 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1348 address as it is mapped */
1349 if (DriverBase != ModuleLoadBase)
1353 /* Copy image sections into virtual section */
1354 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1356 // Copy current section into current offset of virtual section
1357 if (PESectionHeaders[Idx].Characteristics &
1358 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1360 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1361 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1362 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1363 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1364 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1365 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1369 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1370 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1371 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1373 PESectionHeaders[Idx].Misc.VirtualSize);
1375 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1376 PEOptionalHeader->SectionAlignment);
1379 /* Perform relocation fixups */
1380 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1381 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1382 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1383 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1385 PEOptionalHeader->ImageBase,
1387 ps("RelocDir %x\n",RelocDir);
1389 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1391 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1393 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1394 PESectionHeaders[Idx].Name,
1395 PESectionHeaders[Idx].PointerToRawData);
1396 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1397 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1402 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1405 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1407 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1409 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1410 sizeof(RELOCATION_DIRECTORY));
1411 for (Idx = 0; Idx < NumRelocs; Idx++)
1417 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1418 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1419 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1422 (*RelocItem) += RelocDelta;
1426 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1430 TotalRelocs += RelocDir->SizeOfBlock;
1431 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1432 RelocDir->SizeOfBlock);
1435 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1436 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1440 /* Perform import fixups */
1441 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1443 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1445 /* Process each import module */
1446 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1447 ((ULONG)DriverBase + PEOptionalHeader->
1448 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1450 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1452 /* Check to make sure that import lib is kernel */
1453 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1455 ps("Import module: %s\n", pName);
1457 /* Get the import address list */
1458 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1459 ImportModuleDirectory->dwRVAFunctionAddressList);
1461 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1462 ImportModuleDirectory->dwRVAFunctionAddressList);
1463 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1465 /* Get the list of functions to import */
1466 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1468 ps("Using function name list.\n");
1470 FunctionNameList = (PULONG)((ULONG)DriverBase +
1471 ImportModuleDirectory->dwRVAFunctionNameList);
1475 ps("Using function address list.\n");
1477 FunctionNameList = (PULONG)((ULONG)DriverBase +
1478 ImportModuleDirectory->dwRVAFunctionAddressList);
1481 /* Walk through function list and fixup addresses */
1482 while (*FunctionNameList != 0L)
1484 if ((*FunctionNameList) & 0x80000000)
1488 Hint = (*FunctionNameList) & 0xffff;
1493 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1494 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1496 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1498 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1502 ImportAddressList++;
1507 ps("Finished importing.\n");
1512 #endif /* LIBCAPTIVE */
1515 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1519 PIMAGE_EXPORT_DIRECTORY ExportDir;
1520 ULONG ExportDirSize;
1522 PVOID ExportAddress;
1524 PDWORD FunctionList, NameList;
1526 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1527 RtlImageDirectoryEntryToData(ModuleObject->Base,
1529 IMAGE_DIRECTORY_ENTRY_EXPORT,
1531 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1532 if (ExportDir == NULL)
1537 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1538 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1539 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1545 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1548 DPRINT(" Name:%s NameList[%d]:%s\n",
1551 (DWORD) ModuleObject->Base + NameList[Idx]);
1554 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1556 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1557 FunctionList[OrdinalList[Idx]]);
1558 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1559 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1561 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1562 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1563 DPRINT("ExportAddress: %p\n", ExportAddress);
1573 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1574 FunctionList[Hint - ExportDir->Base]);
1575 #else /* !LIBCAPTIVE */
1576 /* Ordinals not supported by libcaptive */
1578 #endif /* !LIBCAPTIVE */
1581 if (ExportAddress == NULL)
1583 CPRINT("Export not found for %d:%s\n",
1585 Name != NULL ? Name : "(Ordinal)");
1589 return(ExportAddress);
1595 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1600 PVOID ExportAddress;
1602 PDWORD FunctionList, NameList;
1603 PIMAGE_EXPORT_DIRECTORY ExportDir;
1604 ULONG ExportDirSize;
1606 static BOOLEAN EP = FALSE;
1608 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1609 RtlImageDirectoryEntryToData(ImportModuleBase,
1611 IMAGE_DIRECTORY_ENTRY_EXPORT,
1616 ps("ExportDir %x\n", ExportDir);
1619 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1620 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1621 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1627 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1629 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1631 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1632 FunctionList[OrdinalList[Idx]]);
1639 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1641 FunctionList[Hint - ExportDir->Base]);
1644 if (ExportAddress == 0)
1646 ps("Export not found for %d:%s\n",
1648 Name != NULL ? Name : "(Ordinal)");
1651 return ExportAddress;
1654 #endif /* LIBCAPTIVE */
1657 LdrPEFixupForward(PCHAR ForwardName)
1659 CHAR NameBuffer[128];
1660 UNICODE_STRING ModuleName;
1662 PMODULE_OBJECT ModuleObject;
1664 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1666 strcpy(NameBuffer, ForwardName);
1667 p = strchr(NameBuffer, '.');
1675 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1677 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1679 ModuleObject = LdrGetModuleObject(&ModuleName);
1680 RtlFreeUnicodeString(&ModuleName);
1682 DPRINT("ModuleObject: %p\n", ModuleObject);
1684 if (ModuleObject == NULL)
1686 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1690 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));