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,
554 ModuleObject->Length);
555 if (!NT_SUCCESS(Status))
557 IopFreeDeviceNode(DeviceNode);
558 CPRINT("Driver load failed, status (%x)\n", Status);
564 #endif /* LIBCAPTIVE */
567 LdrProcessModule(PVOID ModuleLoadBase,
568 PUNICODE_STRING ModuleName,
569 PMODULE_OBJECT *ModuleObject)
571 PIMAGE_DOS_HEADER PEDosHeader;
573 /* If MZ header exists */
574 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
575 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
577 return LdrPEProcessModule(ModuleLoadBase,
582 CPRINT("Module wasn't PE\n");
583 return STATUS_UNSUCCESSFUL;
588 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
592 if (ModuleObject->Flags & MODULE_FLAG_PE)
594 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
605 LdrpQueryModuleInformation(PVOID Buffer,
609 PLIST_ENTRY current_entry;
610 PMODULE_OBJECT current;
611 ULONG ModuleCount = 0;
612 PSYSTEM_MODULE_INFORMATION Smi;
613 ANSI_STRING AnsiName;
617 KeAcquireSpinLock(&ModuleListLock,&Irql);
619 /* calculate required size */
620 current_entry = ModuleListHead.Flink;
621 while (current_entry != (&ModuleListHead))
624 current_entry = current_entry->Flink;
627 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
628 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY);
632 KeReleaseSpinLock(&ModuleListLock, Irql);
633 return(STATUS_INFO_LENGTH_MISMATCH);
636 /* fill the buffer */
637 memset(Buffer, '=', Size);
639 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
640 Smi->Count = ModuleCount;
643 current_entry = ModuleListHead.Flink;
644 while (current_entry != (&ModuleListHead))
646 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
648 Smi->Module[ModuleCount].Unknown1 = 0; /* Always 0 */
649 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
650 Smi->Module[ModuleCount].Base = current->Base;
651 Smi->Module[ModuleCount].Size = current->Length;
652 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
653 Smi->Module[ModuleCount].Index = ModuleCount;
654 Smi->Module[ModuleCount].NameLength = 0;
655 Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */
658 AnsiName.MaximumLength = 256;
659 AnsiName.Buffer = Smi->Module[ModuleCount].ImageName;
660 RtlUnicodeStringToAnsiString(&AnsiName,
664 p = strrchr(AnsiName.Buffer, '\\');
667 Smi->Module[ModuleCount].PathLength = 0;
672 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
676 current_entry = current_entry->Flink;
679 KeReleaseSpinLock(&ModuleListLock, Irql);
681 return(STATUS_SUCCESS);
684 #endif /* LIBCAPTIVE */
688 #endif /* LIBCAPTIVE */
690 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
691 PUNICODE_STRING FullName)
697 DPRINT("LdrpBuildModuleBaseName()\n");
698 DPRINT("FullName %wZ\n", FullName);
700 p = wcsrchr(FullName->Buffer, L'\\');
703 p = FullName->Buffer;
712 RtlCreateUnicodeString(&Name, p);
714 q = wcschr(Name.Buffer, L'.');
722 RtlCreateUnicodeString(BaseName, Name.Buffer);
723 RtlFreeUnicodeString(&Name);
728 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
729 IN PUNICODE_STRING String2)
735 if (String1 && String2)
737 /* Search String1 for last path component */
738 len1 = String1->Length / sizeof(WCHAR);
739 s1 = String1->Buffer;
740 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
744 if (i == String1->Length - sizeof(WCHAR))
752 len1 = (String1->Length - i) / sizeof(WCHAR);
757 /* Search String2 for last path component */
758 len2 = String2->Length / sizeof(WCHAR);
759 s2 = String2->Buffer;
760 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
764 if (i == String2->Length - sizeof(WCHAR))
772 len2 = (String2->Length - i) / sizeof(WCHAR);
777 /* Compare last path components */
782 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
783 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
784 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
786 if (!c1 || !c2 || c1 != c2)
797 LdrGetModuleObject(PUNICODE_STRING ModuleName)
799 PMODULE_OBJECT Module;
803 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
805 KeAcquireSpinLock(&ModuleListLock,&Irql);
807 Entry = ModuleListHead.Flink;
808 while (Entry != &ModuleListHead)
810 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
812 DPRINT("Comparing %wZ and %wZ\n",
816 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
818 DPRINT("Module %wZ\n", &Module->BaseName);
819 KeReleaseSpinLock(&ModuleListLock, Irql);
823 Entry = Entry->Flink;
826 KeReleaseSpinLock(&ModuleListLock, Irql);
828 DPRINT("Could not find module '%wZ'\n", ModuleName);
834 /* ---------------------------------------------- PE Module support */
837 PageNeedsWriteAccess(PVOID PageStart,
839 PIMAGE_FILE_HEADER PEFileHeader,
840 PIMAGE_SECTION_HEADER PESectionHeaders)
842 BOOL NeedsWriteAccess;
844 ULONG Characteristics;
848 NeedsWriteAccess = FALSE;
849 /* Set the protections for the various parts of the driver */
850 for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
852 Characteristics = PESectionHeaders[Idx].Characteristics;
853 if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
854 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
855 Characteristics & IMAGE_SECTION_CHAR_DATA ||
856 Characteristics & IMAGE_SECTION_CHAR_BSS))
859 max(PESectionHeaders[Idx].Misc.VirtualSize,
860 PESectionHeaders[Idx].SizeOfRawData);
861 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
862 NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
863 PageStart < (PVOID)((PCHAR) BaseAddress + Length);
867 return(NeedsWriteAccess);
871 LdrPEProcessModule(PVOID ModuleLoadBase,
872 PUNICODE_STRING FileName,
873 PMODULE_OBJECT *ModuleObject)
875 unsigned int DriverSize, Idx;
876 ULONG RelocDelta, NumRelocs;
877 DWORD CurrentSize, TotalRelocs;
880 PIMAGE_DOS_HEADER PEDosHeader;
881 PIMAGE_FILE_HEADER PEFileHeader;
882 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
883 PIMAGE_SECTION_HEADER PESectionHeaders;
884 PRELOCATION_DIRECTORY RelocDir;
885 PRELOCATION_ENTRY RelocEntry;
886 PMODULE_OBJECT LibraryModuleObject;
887 PMODULE_OBJECT CreatedModuleObject;
888 PVOID *ImportAddressList;
889 PULONG FunctionNameList;
892 UNICODE_STRING ModuleName;
893 UNICODE_STRING NameString;
894 WCHAR NameBuffer[60];
895 MODULE_TEXT_SECTION* ModuleTextSection;
899 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
901 /* Get header pointers */
902 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
903 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
904 PEDosHeader->e_lfanew);
905 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
906 PEDosHeader->e_lfanew + sizeof(ULONG));
907 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
908 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
909 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
910 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
911 sizeof(IMAGE_OPTIONAL_HEADER));
914 /* Check file magic numbers */
915 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
917 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
918 return STATUS_UNSUCCESSFUL;
920 if (PEDosHeader->e_lfanew == 0)
922 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
923 return STATUS_UNSUCCESSFUL;
925 if (*PEMagic != IMAGE_PE_MAGIC)
927 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
928 return STATUS_UNSUCCESSFUL;
930 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
932 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
933 return STATUS_UNSUCCESSFUL;
937 /* FIXME: if image is fixed-address load, then fail */
939 /* FIXME: check/verify OS version number */
941 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
942 PEOptionalHeader->Magic,
943 PEOptionalHeader->MajorLinkerVersion,
944 PEOptionalHeader->MinorLinkerVersion);
945 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
948 /* Determine the size of the module */
949 DriverSize = PEOptionalHeader->SizeOfImage;
950 DPRINT("DriverSize %x\n",DriverSize);
952 /* Allocate a virtual section for the module */
953 DriverBase = MmAllocateSection(DriverSize);
956 CPRINT("Failed to allocate a virtual section for driver\n");
957 return STATUS_UNSUCCESSFUL;
959 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
961 /* Copy headers over */
962 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
964 /* Copy image sections into virtual section */
965 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
967 // Copy current section into current offset of virtual section
968 if (PESectionHeaders[Idx].Characteristics &
969 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
971 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
972 PESectionHeaders[Idx].VirtualAddress + DriverBase);
973 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
974 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
975 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
976 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
980 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
981 PESectionHeaders[Idx].VirtualAddress + DriverBase);
982 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
983 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
986 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
987 PEOptionalHeader->SectionAlignment);
990 // CurrentBase = (PVOID)((DWORD)CurrentBase +
991 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
992 // PEOptionalHeader->SectionAlignment));
995 /* Perform relocation fixups */
996 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
997 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
998 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
999 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1001 PEOptionalHeader->ImageBase,
1003 DPRINT("RelocDir %x\n",RelocDir);
1005 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1007 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1009 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1010 PESectionHeaders[Idx].Name,
1011 PESectionHeaders[Idx].PointerToRawData);
1012 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1014 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1019 RelocDir = RelocDir + (ULONG)DriverBase;
1020 CurrentSize = PEOptionalHeader->DataDirectory
1021 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1023 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1025 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1027 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1029 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1031 RelocDir->VirtualAddress,
1033 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1034 sizeof(RELOCATION_DIRECTORY));
1035 for (Idx = 0; Idx < NumRelocs; Idx++)
1041 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1042 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1043 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1045 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1048 Type ? "HIGHLOW" : "ABS",
1050 (*RelocItem) + RelocDelta); */
1053 (*RelocItem) += RelocDelta;
1057 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1058 return STATUS_UNSUCCESSFUL;
1061 TotalRelocs += RelocDir->SizeOfBlock;
1062 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1063 RelocDir->SizeOfBlock);
1064 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1067 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1068 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1070 /* Perform import fixups */
1071 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1073 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1075 /* Process each import module */
1076 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1077 ((DWORD)DriverBase + PEOptionalHeader->
1078 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1079 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1080 while (ImportModuleDirectory->dwRVAModuleName)
1082 /* Check to make sure that import lib is kernel */
1083 pName = (PCHAR) DriverBase +
1084 ImportModuleDirectory->dwRVAModuleName;
1086 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1087 DPRINT("Import module: %wZ\n", &ModuleName);
1089 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1090 if (LibraryModuleObject == NULL)
1092 DPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1093 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
1094 wcscat(NameBuffer, ModuleName.Buffer);
1095 RtlInitUnicodeString(&NameString, NameBuffer);
1096 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1097 if (!NT_SUCCESS(Status))
1099 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\"));
1100 wcscat(NameBuffer, ModuleName.Buffer);
1101 RtlInitUnicodeString(&NameString, NameBuffer);
1102 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1103 if (!NT_SUCCESS(Status))
1105 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1110 /* Get the import address list */
1111 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1112 ImportModuleDirectory->dwRVAFunctionAddressList);
1114 /* Get the list of functions to import */
1115 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1117 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1118 ImportModuleDirectory->dwRVAFunctionNameList);
1122 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1123 ImportModuleDirectory->dwRVAFunctionAddressList);
1125 /* Walk through function list and fixup addresses */
1126 while (*FunctionNameList != 0L)
1128 if ((*FunctionNameList) & 0x80000000) // hint
1133 Hint = (*FunctionNameList) & 0xffff;
1137 pName = (PCHAR)((DWORD)DriverBase +
1138 *FunctionNameList + 2);
1139 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1141 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1143 /* Fixup the current import symbol */
1144 if (LibraryModuleObject != NULL)
1146 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1152 CPRINT("Unresolved kernel symbol: %s\n", pName);
1153 return STATUS_UNSUCCESSFUL;
1155 ImportAddressList++;
1159 RtlFreeUnicodeString(&ModuleName);
1161 ImportModuleDirectory++;
1165 /* Set the protections for the various parts of the driver */
1166 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1168 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1172 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1173 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1174 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1175 Characteristics & IMAGE_SECTION_CHAR_BSS))
1178 max(PESectionHeaders[Idx].Misc.VirtualSize,
1179 PESectionHeaders[Idx].SizeOfRawData);
1180 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1181 PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
1182 if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1184 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1186 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1187 while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
1188 (PVOID)((PCHAR) BaseAddress + Length))
1190 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1191 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1193 if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
1194 ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1196 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1201 /* Create the module */
1202 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1203 if (CreatedModuleObject == NULL)
1205 return(STATUS_INSUFFICIENT_RESOURCES);
1208 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1210 /* Initialize ModuleObject data */
1211 CreatedModuleObject->Base = DriverBase;
1212 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1214 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1216 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1217 &CreatedModuleObject->FullName);
1219 CreatedModuleObject->EntryPoint =
1220 (PVOID)((DWORD)DriverBase +
1221 PEOptionalHeader->AddressOfEntryPoint);
1222 CreatedModuleObject->Length = DriverSize;
1223 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1225 CreatedModuleObject->Image.PE.FileHeader =
1226 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1228 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1229 CreatedModuleObject->Image.PE.OptionalHeader =
1230 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1231 sizeof(IMAGE_FILE_HEADER));
1232 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1233 CreatedModuleObject->Image.PE.SectionList =
1234 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1235 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1236 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1239 KeAcquireSpinLock(&ModuleListLock, &Irql);
1240 InsertTailList(&ModuleListHead,
1241 &CreatedModuleObject->ListEntry);
1242 KeReleaseSpinLock(&ModuleListLock, Irql);
1245 ModuleTextSection = ExAllocatePool(NonPagedPool,
1246 sizeof(MODULE_TEXT_SECTION));
1247 assert(ModuleTextSection);
1248 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1249 ModuleTextSection->Base = (ULONG)DriverBase;
1250 ModuleTextSection->Length = DriverSize;
1251 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1252 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1253 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1254 ModuleTextSection->OptionalHeader =
1255 CreatedModuleObject->Image.PE.OptionalHeader;
1256 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1258 CreatedModuleObject->TextSection = ModuleTextSection;
1260 *ModuleObject = CreatedModuleObject;
1262 DPRINT("Loading Module %wZ...\n", FileName);
1264 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1266 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1267 FileName, CreatedModuleObject->Base);
1270 return STATUS_SUCCESS;
1276 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1278 PVOID ImportModuleBase,
1282 ULONG RelocDelta, NumRelocs;
1283 ULONG CurrentSize, TotalRelocs;
1285 PIMAGE_DOS_HEADER PEDosHeader;
1286 PIMAGE_FILE_HEADER PEFileHeader;
1287 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1288 PIMAGE_SECTION_HEADER PESectionHeaders;
1289 PRELOCATION_DIRECTORY RelocDir;
1290 PRELOCATION_ENTRY RelocEntry;
1291 PVOID *ImportAddressList;
1292 PULONG FunctionNameList;
1296 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1298 /* Get header pointers */
1299 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1300 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1301 PEDosHeader->e_lfanew);
1302 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1303 PEDosHeader->e_lfanew + sizeof(ULONG));
1304 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1305 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1306 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1307 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1308 sizeof(IMAGE_OPTIONAL_HEADER));
1311 /* Check file magic numbers */
1312 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1316 if (PEDosHeader->e_lfanew == 0)
1320 if (*PEMagic != IMAGE_PE_MAGIC)
1324 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1329 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1330 PEOptionalHeader->Magic,
1331 PEOptionalHeader->MajorLinkerVersion,
1332 PEOptionalHeader->MinorLinkerVersion);
1333 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1335 /* Determine the size of the module */
1336 *DriverSize = PEOptionalHeader->SizeOfImage;
1337 ps("DriverSize %x\n",*DriverSize);
1339 /* Copy headers over */
1340 if (DriverBase != ModuleLoadBase)
1342 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1345 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1346 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1347 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1349 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1350 address as it is mapped */
1351 if (DriverBase != ModuleLoadBase)
1355 /* Copy image sections into virtual section */
1356 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1358 // Copy current section into current offset of virtual section
1359 if (PESectionHeaders[Idx].Characteristics &
1360 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1362 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1363 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1364 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1365 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1366 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1367 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1371 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1372 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1373 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1375 PESectionHeaders[Idx].Misc.VirtualSize);
1377 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1378 PEOptionalHeader->SectionAlignment);
1381 /* Perform relocation fixups */
1382 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1383 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1384 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1385 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1387 PEOptionalHeader->ImageBase,
1389 ps("RelocDir %x\n",RelocDir);
1391 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1393 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1395 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1396 PESectionHeaders[Idx].Name,
1397 PESectionHeaders[Idx].PointerToRawData);
1398 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1399 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1404 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1407 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1409 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1411 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1412 sizeof(RELOCATION_DIRECTORY));
1413 for (Idx = 0; Idx < NumRelocs; Idx++)
1419 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1420 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1421 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1424 (*RelocItem) += RelocDelta;
1428 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1432 TotalRelocs += RelocDir->SizeOfBlock;
1433 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1434 RelocDir->SizeOfBlock);
1437 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1438 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1442 /* Perform import fixups */
1443 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1445 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1447 /* Process each import module */
1448 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1449 ((ULONG)DriverBase + PEOptionalHeader->
1450 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1452 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1454 /* Check to make sure that import lib is kernel */
1455 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1457 ps("Import module: %s\n", pName);
1459 /* Get the import address list */
1460 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1461 ImportModuleDirectory->dwRVAFunctionAddressList);
1463 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1464 ImportModuleDirectory->dwRVAFunctionAddressList);
1465 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1467 /* Get the list of functions to import */
1468 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1470 ps("Using function name list.\n");
1472 FunctionNameList = (PULONG)((ULONG)DriverBase +
1473 ImportModuleDirectory->dwRVAFunctionNameList);
1477 ps("Using function address list.\n");
1479 FunctionNameList = (PULONG)((ULONG)DriverBase +
1480 ImportModuleDirectory->dwRVAFunctionAddressList);
1483 /* Walk through function list and fixup addresses */
1484 while (*FunctionNameList != 0L)
1486 if ((*FunctionNameList) & 0x80000000)
1490 Hint = (*FunctionNameList) & 0xffff;
1495 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1496 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1498 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1500 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1504 ImportAddressList++;
1509 ps("Finished importing.\n");
1514 #endif /* LIBCAPTIVE */
1517 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1521 PIMAGE_EXPORT_DIRECTORY ExportDir;
1522 ULONG ExportDirSize;
1524 PVOID ExportAddress;
1526 PDWORD FunctionList, NameList;
1528 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1529 RtlImageDirectoryEntryToData(ModuleObject->Base,
1531 IMAGE_DIRECTORY_ENTRY_EXPORT,
1533 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1534 if (ExportDir == NULL)
1539 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1540 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1541 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1547 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1550 DPRINT(" Name:%s NameList[%d]:%s\n",
1553 (DWORD) ModuleObject->Base + NameList[Idx]);
1556 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1558 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1559 FunctionList[OrdinalList[Idx]]);
1560 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1561 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1563 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1564 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1565 DPRINT("ExportAddress: %p\n", ExportAddress);
1575 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1576 FunctionList[Hint - ExportDir->Base]);
1577 #else /* !LIBCAPTIVE */
1578 /* Ordinals not supported by libcaptive */
1580 #endif /* !LIBCAPTIVE */
1583 if (ExportAddress == NULL)
1585 DbgPrint("Export not found for %d:%s\n",
1587 Name != NULL ? Name : "(Ordinal)");
1591 return(ExportAddress);
1597 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1602 PVOID ExportAddress;
1604 PDWORD FunctionList, NameList;
1605 PIMAGE_EXPORT_DIRECTORY ExportDir;
1606 ULONG ExportDirSize;
1608 static BOOLEAN EP = FALSE;
1610 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1611 RtlImageDirectoryEntryToData(ImportModuleBase,
1613 IMAGE_DIRECTORY_ENTRY_EXPORT,
1618 ps("ExportDir %x\n", ExportDir);
1621 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1622 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1623 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1629 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1631 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1633 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1634 FunctionList[OrdinalList[Idx]]);
1641 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1643 FunctionList[Hint - ExportDir->Base]);
1646 if (ExportAddress == 0)
1648 ps("Export not found for %d:%s\n",
1650 Name != NULL ? Name : "(Ordinal)");
1653 return ExportAddress;
1656 #endif /* LIBCAPTIVE */
1659 LdrPEFixupForward(PCHAR ForwardName)
1661 CHAR NameBuffer[128];
1662 UNICODE_STRING ModuleName;
1664 PMODULE_OBJECT ModuleObject;
1666 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1668 strcpy(NameBuffer, ForwardName);
1669 p = strchr(NameBuffer, '.');
1677 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1679 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1681 ModuleObject = LdrGetModuleObject(&ModuleName);
1682 RtlFreeUnicodeString(&ModuleName);
1684 DPRINT("ModuleObject: %p\n", ModuleObject);
1686 if (ModuleObject == NULL)
1688 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1692 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));