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;
56 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
57 STATIC MODULE_TEXT_SECTION LdrHalTextSection;
60 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
62 /* FORWARD DECLARATIONS ******************************************************/
65 LdrProcessModule(PVOID ModuleLoadBase,
66 PUNICODE_STRING ModuleName,
67 PMODULE_OBJECT *ModuleObject);
70 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
75 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
76 PUNICODE_STRING FullName);
79 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
80 IN PUNICODE_STRING String2);
83 /* PE Driver load support */
84 static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
85 PUNICODE_STRING FileName,
86 PMODULE_OBJECT *ModuleObject);
88 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
93 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
98 LdrPEFixupForward(PCHAR ForwardName);
101 /* FUNCTIONS *****************************************************************/
104 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
106 PLIST_ENTRY current_entry;
107 MODULE_TEXT_SECTION* current;
109 current_entry = ModuleTextListHead.Flink;
110 while (current_entry != &ModuleTextListHead)
113 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
114 if (wcscmp(current->Name, Name) == 0)
118 current_entry = current_entry->Flink;
121 if (current_entry == &ModuleTextListHead)
130 PIMAGE_DOS_HEADER DosHeader;
131 PIMAGE_FILE_HEADER FileHeader;
132 PIMAGE_OPTIONAL_HEADER OptionalHeader;
133 PIMAGE_SECTION_HEADER SectionList;
135 InitializeListHead(&ModuleTextListHead);
137 /* Setup ntoskrnl.exe text section */
138 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
140 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
141 DosHeader->e_lfanew + sizeof(ULONG));
142 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
143 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
144 SectionList = (PIMAGE_SECTION_HEADER)
145 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
146 NtoskrnlTextSection.Base = KERNEL_BASE;
147 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
148 SectionList[0].VirtualAddress;
149 NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
150 NtoskrnlTextSection.OptionalHeader = OptionalHeader;
151 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
153 /* Setup hal.dll text section */
154 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
156 (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
157 DosHeader->e_lfanew + sizeof(ULONG));
158 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
159 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
160 SectionList = (PIMAGE_SECTION_HEADER)
161 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
162 LdrHalTextSection.Base = LdrHalBase;
163 LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
164 SectionList[0].VirtualAddress;
165 LdrHalTextSection.Name = HAL_MODULE_NAME;
166 LdrHalTextSection.OptionalHeader = OptionalHeader;
167 InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
169 /* Hook for KDB on initialization of the loader. */
170 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
175 LdrInitModuleManagement(VOID)
177 PIMAGE_DOS_HEADER DosHeader;
178 PMODULE_OBJECT ModuleObject;
180 /* Initialize the module list and spinlock */
181 InitializeListHead(&ModuleListHead);
182 KeInitializeSpinLock(&ModuleListLock);
184 /* Create module object for NTOSKRNL */
185 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
186 assert(ModuleObject != NULL);
187 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
189 /* Initialize ModuleObject data */
190 ModuleObject->Base = (PVOID) KERNEL_BASE;
191 ModuleObject->Flags = MODULE_FLAG_PE;
192 RtlCreateUnicodeString(&ModuleObject->FullName,
194 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
195 &ModuleObject->FullName);
197 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
198 ModuleObject->Image.PE.FileHeader =
199 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
200 DosHeader->e_lfanew + sizeof(ULONG));
201 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
202 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
203 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
204 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
205 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
206 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
207 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
208 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
209 ModuleObject->TextSection = &NtoskrnlTextSection;
211 InsertTailList(&ModuleListHead,
212 &ModuleObject->ListEntry);
214 /* Create module object for HAL */
215 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
216 assert(ModuleObject != NULL);
217 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
219 /* Initialize ModuleObject data */
220 ModuleObject->Base = (PVOID) LdrHalBase;
221 ModuleObject->Flags = MODULE_FLAG_PE;
223 RtlCreateUnicodeString(&ModuleObject->FullName,
225 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
226 &ModuleObject->FullName);
228 DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
229 ModuleObject->Image.PE.FileHeader =
230 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
231 DosHeader->e_lfanew + sizeof(ULONG));
232 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
233 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
234 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
235 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
236 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
237 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
238 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
239 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
240 ModuleObject->TextSection = &LdrHalTextSection;
242 InsertTailList(&ModuleListHead,
243 &ModuleObject->ListEntry);
247 LdrpLoadImage(PUNICODE_STRING DriverName,
249 PVOID *SectionPointer,
251 PVOID *ExportSectionPointer)
253 PMODULE_OBJECT ModuleObject;
256 ModuleObject = LdrGetModuleObject(DriverName);
257 if (ModuleObject == NULL)
259 Status = LdrLoadModule(DriverName, &ModuleObject);
260 if (!NT_SUCCESS(Status))
267 *ModuleBase = ModuleObject->Base;
269 // if (SectionPointer)
270 // *SectionPointer = ModuleObject->
273 *EntryPoint = ModuleObject->EntryPoint;
275 // if (ExportSectionPointer)
276 // *ExportSectionPointer = ModuleObject->
278 return(STATUS_SUCCESS);
283 LdrpUnloadImage(PVOID ModuleBase)
285 return(STATUS_NOT_IMPLEMENTED);
290 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
292 PDRIVER_INITIALIZE DriverEntry;
293 PMODULE_OBJECT ModuleObject;
296 ModuleObject = LdrGetModuleObject(ModuleName);
297 if (ModuleObject != NULL)
299 return(STATUS_IMAGE_ALREADY_LOADED);
302 Status = LdrLoadModule(ModuleName, &ModuleObject);
303 if (!NT_SUCCESS(Status))
308 DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
310 Status = DriverEntry(NULL, NULL);
311 if (!NT_SUCCESS(Status))
313 LdrUnloadModule(ModuleObject);
321 LdrLoadModule(PUNICODE_STRING Filename,
322 PMODULE_OBJECT *ModuleObject)
324 PVOID ModuleLoadBase;
327 OBJECT_ATTRIBUTES ObjectAttributes;
328 PMODULE_OBJECT Module;
329 FILE_STANDARD_INFORMATION FileStdInfo;
330 IO_STATUS_BLOCK IoStatusBlock;
332 *ModuleObject = NULL;
334 DPRINT("Loading Module %wZ...\n", Filename);
336 /* Open the Module */
337 InitializeObjectAttributes(&ObjectAttributes,
343 Status = NtOpenFile(&FileHandle,
348 FILE_SYNCHRONOUS_IO_NONALERT);
350 if (!NT_SUCCESS(Status))
352 CPRINT("Could not open module file: %wZ\n", Filename);
357 /* Get the size of the file */
358 Status = NtQueryInformationFile(FileHandle,
362 FileStandardInformation);
363 if (!NT_SUCCESS(Status))
365 CPRINT("Could not get file size\n");
371 /* Allocate nonpageable memory for driver */
372 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
373 FileStdInfo.EndOfFile.u.LowPart,
375 if (ModuleLoadBase == NULL)
377 CPRINT("Could not allocate memory for module");
379 return(STATUS_INSUFFICIENT_RESOURCES);
383 /* Load driver into memory chunk */
384 Status = NtReadFile(FileHandle,
388 FileStdInfo.EndOfFile.u.LowPart,
390 if (!NT_SUCCESS(Status))
392 CPRINT("Could not read module file into memory");
393 ExFreePool(ModuleLoadBase);
401 Status = LdrProcessModule(ModuleLoadBase,
404 if (!NT_SUCCESS(Status))
406 CPRINT("Could not process module");
407 ExFreePool(ModuleLoadBase);
412 ExFreePool(ModuleLoadBase);
414 *ModuleObject = Module;
416 /* Hook for KDB on loading a driver. */
417 KDB_LOADDRIVER_HOOK(Filename, Module);
419 return(STATUS_SUCCESS);
424 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
428 /* Remove the module from the module list */
429 KeAcquireSpinLock(&ModuleListLock,&Irql);
430 RemoveEntryList(&ModuleObject->ListEntry);
431 KeReleaseSpinLock(&ModuleListLock, Irql);
433 /* Hook for KDB on unloading a driver. */
434 KDB_UNLOADDRIVER_HOOK(ModuleObject);
436 /* Free text section */
437 if (ModuleObject->TextSection != NULL)
439 ExFreePool(ModuleObject->TextSection->Name);
440 RemoveEntryList(&ModuleObject->TextSection->ListEntry);
441 ExFreePool(ModuleObject->TextSection);
442 ModuleObject->TextSection = NULL;
445 /* Free module section */
446 // MmFreeSection(ModuleObject->Base);
448 ExFreePool(ModuleObject);
450 return(STATUS_SUCCESS);
455 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
459 PMODULE_OBJECT ModuleObject;
460 UNICODE_STRING ModuleName;
461 PDEVICE_NODE DeviceNode;
464 WCHAR Buffer[MAX_PATH];
469 CHAR TextBuffer [256];
472 HalQueryDisplayParameters(&x, &y, &cx, &cy);
473 RtlFillMemory(TextBuffer, x, ' ');
474 TextBuffer[x] = '\0';
475 HalSetDisplayParameters(0, y-1);
476 HalDisplayString(TextBuffer);
478 sprintf(TextBuffer, "Initializing %s...\n", FileName);
479 HalSetDisplayParameters(0, y-1);
480 HalDisplayString(TextBuffer);
481 HalSetDisplayParameters(cx, cy);
483 /* Split the filename into base name and extension */
484 FileExt = strrchr(FileName, '.');
486 Length = FileExt - FileName;
488 Length = strlen(FileName);
490 if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
492 KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
493 return(STATUS_SUCCESS);
495 else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
497 CPRINT("Ignoring non-driver file %s\n", FileName);
498 return STATUS_SUCCESS;
501 /* Use IopRootDeviceNode for now */
502 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
503 if (!NT_SUCCESS(Status))
505 CPRINT("Driver load failed, status (%x)\n", Status);
509 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
511 Status = LdrProcessModule(ModuleLoadBase,
514 RtlFreeUnicodeString(&ModuleName);
515 if (ModuleObject == NULL)
517 IopFreeDeviceNode(DeviceNode);
518 CPRINT("Driver load failed, status (%x)\n", Status);
519 return(STATUS_UNSUCCESSFUL);
523 /* Get the service name from the module name */
524 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
526 Start = ModuleObject->BaseName.Buffer;
530 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
532 Length = Ext - Start;
534 Length = wcslen(Start);
536 wcsncpy(Buffer, Start, Length);
538 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
540 Status = IopInitializeDriver(ModuleObject->EntryPoint,
543 ModuleObject->Length);
544 if (!NT_SUCCESS(Status))
546 IopFreeDeviceNode(DeviceNode);
547 CPRINT("Driver load failed, status (%x)\n", Status);
555 LdrProcessModule(PVOID ModuleLoadBase,
556 PUNICODE_STRING ModuleName,
557 PMODULE_OBJECT *ModuleObject)
559 PIMAGE_DOS_HEADER PEDosHeader;
561 /* If MZ header exists */
562 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
563 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
565 return LdrPEProcessModule(ModuleLoadBase,
570 CPRINT("Module wasn't PE\n");
571 return STATUS_UNSUCCESSFUL;
576 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
580 if (ModuleObject->Flags & MODULE_FLAG_PE)
582 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
592 LdrpQueryModuleInformation(PVOID Buffer,
596 PLIST_ENTRY current_entry;
597 PMODULE_OBJECT current;
598 ULONG ModuleCount = 0;
599 PSYSTEM_MODULE_INFORMATION Smi;
600 ANSI_STRING AnsiName;
604 KeAcquireSpinLock(&ModuleListLock,&Irql);
606 /* calculate required size */
607 current_entry = ModuleListHead.Flink;
608 while (current_entry != (&ModuleListHead))
611 current_entry = current_entry->Flink;
614 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
615 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY);
619 KeReleaseSpinLock(&ModuleListLock, Irql);
620 return(STATUS_INFO_LENGTH_MISMATCH);
623 /* fill the buffer */
624 memset(Buffer, '=', Size);
626 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
627 Smi->Count = ModuleCount;
630 current_entry = ModuleListHead.Flink;
631 while (current_entry != (&ModuleListHead))
633 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
635 Smi->Module[ModuleCount].Unknown1 = 0; /* Always 0 */
636 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
637 Smi->Module[ModuleCount].Base = current->Base;
638 Smi->Module[ModuleCount].Size = current->Length;
639 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
640 Smi->Module[ModuleCount].Index = ModuleCount;
641 Smi->Module[ModuleCount].NameLength = 0;
642 Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */
645 AnsiName.MaximumLength = 256;
646 AnsiName.Buffer = Smi->Module[ModuleCount].ImageName;
647 RtlUnicodeStringToAnsiString(&AnsiName,
651 p = strrchr(AnsiName.Buffer, '\\');
654 Smi->Module[ModuleCount].PathLength = 0;
659 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
663 current_entry = current_entry->Flink;
666 KeReleaseSpinLock(&ModuleListLock, Irql);
668 return(STATUS_SUCCESS);
673 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
674 PUNICODE_STRING FullName)
680 DPRINT("LdrpBuildModuleBaseName()\n");
681 DPRINT("FullName %wZ\n", FullName);
683 p = wcsrchr(FullName->Buffer, L'\\');
686 p = FullName->Buffer;
695 RtlCreateUnicodeString(&Name, p);
697 q = wcschr(Name.Buffer, L'.');
705 RtlCreateUnicodeString(BaseName, Name.Buffer);
706 RtlFreeUnicodeString(&Name);
711 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
712 IN PUNICODE_STRING String2)
718 if (String1 && String2)
720 /* Search String1 for last path component */
721 len1 = String1->Length / sizeof(WCHAR);
722 s1 = String1->Buffer;
723 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
727 if (i == String1->Length - sizeof(WCHAR))
735 len1 = (String1->Length - i) / sizeof(WCHAR);
740 /* Search String2 for last path component */
741 len2 = String2->Length / sizeof(WCHAR);
742 s2 = String2->Buffer;
743 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
747 if (i == String2->Length - sizeof(WCHAR))
755 len2 = (String2->Length - i) / sizeof(WCHAR);
760 /* Compare last path components */
765 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
766 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
767 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
769 if (!c1 || !c2 || c1 != c2)
780 LdrGetModuleObject(PUNICODE_STRING ModuleName)
782 PMODULE_OBJECT Module;
786 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
788 KeAcquireSpinLock(&ModuleListLock,&Irql);
790 Entry = ModuleListHead.Flink;
791 while (Entry != &ModuleListHead)
793 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
795 DPRINT("Comparing %wZ and %wZ\n",
799 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
801 DPRINT("Module %wZ\n", &Module->BaseName);
802 KeReleaseSpinLock(&ModuleListLock, Irql);
806 Entry = Entry->Flink;
809 KeReleaseSpinLock(&ModuleListLock, Irql);
811 DPRINT("Could not find module '%wZ'\n", ModuleName);
817 /* ---------------------------------------------- PE Module support */
820 PageNeedsWriteAccess(PVOID PageStart,
822 PIMAGE_FILE_HEADER PEFileHeader,
823 PIMAGE_SECTION_HEADER PESectionHeaders)
825 BOOL NeedsWriteAccess;
827 ULONG Characteristics;
831 NeedsWriteAccess = FALSE;
832 /* Set the protections for the various parts of the driver */
833 for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
835 Characteristics = PESectionHeaders[Idx].Characteristics;
836 if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
837 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
838 Characteristics & IMAGE_SECTION_CHAR_DATA ||
839 Characteristics & IMAGE_SECTION_CHAR_BSS))
842 max(PESectionHeaders[Idx].Misc.VirtualSize,
843 PESectionHeaders[Idx].SizeOfRawData);
844 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
845 NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
846 PageStart < (PVOID)((PCHAR) BaseAddress + Length);
850 return(NeedsWriteAccess);
854 LdrPEProcessModule(PVOID ModuleLoadBase,
855 PUNICODE_STRING FileName,
856 PMODULE_OBJECT *ModuleObject)
858 unsigned int DriverSize, Idx;
859 ULONG RelocDelta, NumRelocs;
860 DWORD CurrentSize, TotalRelocs;
863 PIMAGE_DOS_HEADER PEDosHeader;
864 PIMAGE_FILE_HEADER PEFileHeader;
865 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
866 PIMAGE_SECTION_HEADER PESectionHeaders;
867 PRELOCATION_DIRECTORY RelocDir;
868 PRELOCATION_ENTRY RelocEntry;
869 PMODULE_OBJECT LibraryModuleObject;
870 PMODULE_OBJECT CreatedModuleObject;
871 PVOID *ImportAddressList;
872 PULONG FunctionNameList;
875 UNICODE_STRING ModuleName;
876 UNICODE_STRING NameString;
877 WCHAR NameBuffer[60];
878 MODULE_TEXT_SECTION* ModuleTextSection;
882 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
884 /* Get header pointers */
885 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
886 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
887 PEDosHeader->e_lfanew);
888 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
889 PEDosHeader->e_lfanew + sizeof(ULONG));
890 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
891 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
892 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
893 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
894 sizeof(IMAGE_OPTIONAL_HEADER));
897 /* Check file magic numbers */
898 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
900 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
901 return STATUS_UNSUCCESSFUL;
903 if (PEDosHeader->e_lfanew == 0)
905 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
906 return STATUS_UNSUCCESSFUL;
908 if (*PEMagic != IMAGE_PE_MAGIC)
910 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
911 return STATUS_UNSUCCESSFUL;
913 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
915 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
916 return STATUS_UNSUCCESSFUL;
920 /* FIXME: if image is fixed-address load, then fail */
922 /* FIXME: check/verify OS version number */
924 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
925 PEOptionalHeader->Magic,
926 PEOptionalHeader->MajorLinkerVersion,
927 PEOptionalHeader->MinorLinkerVersion);
928 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
931 /* Determine the size of the module */
932 DriverSize = PEOptionalHeader->SizeOfImage;
933 DPRINT("DriverSize %x\n",DriverSize);
935 /* Allocate a virtual section for the module */
936 DriverBase = MmAllocateSection(DriverSize);
939 CPRINT("Failed to allocate a virtual section for driver\n");
940 return STATUS_UNSUCCESSFUL;
942 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
944 /* Copy headers over */
945 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
947 /* Copy image sections into virtual section */
948 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
950 // Copy current section into current offset of virtual section
951 if (PESectionHeaders[Idx].Characteristics &
952 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
954 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
955 PESectionHeaders[Idx].VirtualAddress + DriverBase);
956 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
957 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
958 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
959 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
963 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
964 PESectionHeaders[Idx].VirtualAddress + DriverBase);
965 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
966 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
969 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
970 PEOptionalHeader->SectionAlignment);
973 // CurrentBase = (PVOID)((DWORD)CurrentBase +
974 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
975 // PEOptionalHeader->SectionAlignment));
978 /* Perform relocation fixups */
979 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
980 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
981 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
982 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
984 PEOptionalHeader->ImageBase,
986 DPRINT("RelocDir %x\n",RelocDir);
988 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
990 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
992 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
993 PESectionHeaders[Idx].Name,
994 PESectionHeaders[Idx].PointerToRawData);
995 RelocDir = PESectionHeaders[Idx].PointerToRawData +
997 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1002 RelocDir = RelocDir + (ULONG)DriverBase;
1003 CurrentSize = PEOptionalHeader->DataDirectory
1004 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1006 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1008 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1010 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1012 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1014 RelocDir->VirtualAddress,
1016 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1017 sizeof(RELOCATION_DIRECTORY));
1018 for (Idx = 0; Idx < NumRelocs; Idx++)
1024 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1025 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1026 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1028 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1031 Type ? "HIGHLOW" : "ABS",
1033 (*RelocItem) + RelocDelta); */
1036 (*RelocItem) += RelocDelta;
1040 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1041 return STATUS_UNSUCCESSFUL;
1044 TotalRelocs += RelocDir->SizeOfBlock;
1045 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1046 RelocDir->SizeOfBlock);
1047 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1050 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1051 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1053 /* Perform import fixups */
1054 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1056 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1058 /* Process each import module */
1059 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1060 ((DWORD)DriverBase + PEOptionalHeader->
1061 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1062 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1063 while (ImportModuleDirectory->dwRVAModuleName)
1065 /* Check to make sure that import lib is kernel */
1066 pName = (PCHAR) DriverBase +
1067 ImportModuleDirectory->dwRVAModuleName;
1069 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1070 DPRINT("Import module: %wZ\n", &ModuleName);
1072 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1073 if (LibraryModuleObject == NULL)
1075 DPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1076 wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\");
1077 wcscat(NameBuffer, ModuleName.Buffer);
1078 RtlInitUnicodeString(&NameString, NameBuffer);
1079 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1080 if (!NT_SUCCESS(Status))
1082 wcscpy(NameBuffer, L"\\SystemRoot\\system32\\");
1083 wcscat(NameBuffer, ModuleName.Buffer);
1084 RtlInitUnicodeString(&NameString, NameBuffer);
1085 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1086 if (!NT_SUCCESS(Status))
1088 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1093 /* Get the import address list */
1094 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1095 ImportModuleDirectory->dwRVAFunctionAddressList);
1097 /* Get the list of functions to import */
1098 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1100 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1101 ImportModuleDirectory->dwRVAFunctionNameList);
1105 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1106 ImportModuleDirectory->dwRVAFunctionAddressList);
1108 /* Walk through function list and fixup addresses */
1109 while (*FunctionNameList != 0L)
1111 if ((*FunctionNameList) & 0x80000000) // hint
1116 Hint = (*FunctionNameList) & 0xffff;
1120 pName = (PCHAR)((DWORD)DriverBase +
1121 *FunctionNameList + 2);
1122 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1124 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1126 /* Fixup the current import symbol */
1127 if (LibraryModuleObject != NULL)
1129 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1135 CPRINT("Unresolved kernel symbol: %s\n", pName);
1136 return STATUS_UNSUCCESSFUL;
1138 ImportAddressList++;
1142 RtlFreeUnicodeString(&ModuleName);
1144 ImportModuleDirectory++;
1148 /* Set the protections for the various parts of the driver */
1149 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1151 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1155 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1156 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1157 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1158 Characteristics & IMAGE_SECTION_CHAR_BSS))
1161 max(PESectionHeaders[Idx].Misc.VirtualSize,
1162 PESectionHeaders[Idx].SizeOfRawData);
1163 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1164 PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
1165 if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1167 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1169 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1170 while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
1171 (PVOID)((PCHAR) BaseAddress + Length))
1173 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1174 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1176 if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
1177 ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1179 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1184 /* Create the module */
1185 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1186 if (CreatedModuleObject == NULL)
1188 return(STATUS_INSUFFICIENT_RESOURCES);
1191 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1193 /* Initialize ModuleObject data */
1194 CreatedModuleObject->Base = DriverBase;
1195 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1197 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1199 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1200 &CreatedModuleObject->FullName);
1202 CreatedModuleObject->EntryPoint =
1203 (PVOID)((DWORD)DriverBase +
1204 PEOptionalHeader->AddressOfEntryPoint);
1205 CreatedModuleObject->Length = DriverSize;
1206 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1208 CreatedModuleObject->Image.PE.FileHeader =
1209 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1211 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1212 CreatedModuleObject->Image.PE.OptionalHeader =
1213 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1214 sizeof(IMAGE_FILE_HEADER));
1215 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1216 CreatedModuleObject->Image.PE.SectionList =
1217 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1218 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1219 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1222 KeAcquireSpinLock(&ModuleListLock, &Irql);
1223 InsertTailList(&ModuleListHead,
1224 &CreatedModuleObject->ListEntry);
1225 KeReleaseSpinLock(&ModuleListLock, Irql);
1228 ModuleTextSection = ExAllocatePool(NonPagedPool,
1229 sizeof(MODULE_TEXT_SECTION));
1230 assert(ModuleTextSection);
1231 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1232 ModuleTextSection->Base = (ULONG)DriverBase;
1233 ModuleTextSection->Length = DriverSize;
1234 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1235 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1236 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1237 ModuleTextSection->OptionalHeader =
1238 CreatedModuleObject->Image.PE.OptionalHeader;
1239 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1241 CreatedModuleObject->TextSection = ModuleTextSection;
1243 *ModuleObject = CreatedModuleObject;
1245 DPRINT("Loading Module %wZ...\n", FileName);
1247 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1249 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1250 FileName, CreatedModuleObject->Base);
1253 return STATUS_SUCCESS;
1258 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1260 PVOID ImportModuleBase,
1264 ULONG RelocDelta, NumRelocs;
1265 ULONG CurrentSize, TotalRelocs;
1267 PIMAGE_DOS_HEADER PEDosHeader;
1268 PIMAGE_FILE_HEADER PEFileHeader;
1269 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1270 PIMAGE_SECTION_HEADER PESectionHeaders;
1271 PRELOCATION_DIRECTORY RelocDir;
1272 PRELOCATION_ENTRY RelocEntry;
1273 PVOID *ImportAddressList;
1274 PULONG FunctionNameList;
1278 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1280 /* Get header pointers */
1281 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1282 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1283 PEDosHeader->e_lfanew);
1284 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1285 PEDosHeader->e_lfanew + sizeof(ULONG));
1286 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1287 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1288 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1289 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1290 sizeof(IMAGE_OPTIONAL_HEADER));
1293 /* Check file magic numbers */
1294 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1298 if (PEDosHeader->e_lfanew == 0)
1302 if (*PEMagic != IMAGE_PE_MAGIC)
1306 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1311 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1312 PEOptionalHeader->Magic,
1313 PEOptionalHeader->MajorLinkerVersion,
1314 PEOptionalHeader->MinorLinkerVersion);
1315 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1317 /* Determine the size of the module */
1318 *DriverSize = PEOptionalHeader->SizeOfImage;
1319 ps("DriverSize %x\n",*DriverSize);
1321 /* Copy headers over */
1322 if (DriverBase != ModuleLoadBase)
1324 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1327 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1328 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1329 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1331 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1332 address as it is mapped */
1333 if (DriverBase != ModuleLoadBase)
1337 /* Copy image sections into virtual section */
1338 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1340 // Copy current section into current offset of virtual section
1341 if (PESectionHeaders[Idx].Characteristics &
1342 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1344 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1345 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1346 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1347 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1348 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1349 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1353 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1354 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1355 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1357 PESectionHeaders[Idx].Misc.VirtualSize);
1359 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1360 PEOptionalHeader->SectionAlignment);
1363 /* Perform relocation fixups */
1364 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1365 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1366 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1367 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1369 PEOptionalHeader->ImageBase,
1371 ps("RelocDir %x\n",RelocDir);
1373 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1375 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1377 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1378 PESectionHeaders[Idx].Name,
1379 PESectionHeaders[Idx].PointerToRawData);
1380 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1381 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1386 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1389 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1391 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1393 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1394 sizeof(RELOCATION_DIRECTORY));
1395 for (Idx = 0; Idx < NumRelocs; Idx++)
1401 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1402 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1403 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1406 (*RelocItem) += RelocDelta;
1410 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1414 TotalRelocs += RelocDir->SizeOfBlock;
1415 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1416 RelocDir->SizeOfBlock);
1419 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1420 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1424 /* Perform import fixups */
1425 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1427 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1429 /* Process each import module */
1430 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1431 ((ULONG)DriverBase + PEOptionalHeader->
1432 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1434 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1436 /* Check to make sure that import lib is kernel */
1437 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1439 ps("Import module: %s\n", pName);
1441 /* Get the import address list */
1442 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1443 ImportModuleDirectory->dwRVAFunctionAddressList);
1445 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1446 ImportModuleDirectory->dwRVAFunctionAddressList);
1447 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1449 /* Get the list of functions to import */
1450 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1452 ps("Using function name list.\n");
1454 FunctionNameList = (PULONG)((ULONG)DriverBase +
1455 ImportModuleDirectory->dwRVAFunctionNameList);
1459 ps("Using function address list.\n");
1461 FunctionNameList = (PULONG)((ULONG)DriverBase +
1462 ImportModuleDirectory->dwRVAFunctionAddressList);
1465 /* Walk through function list and fixup addresses */
1466 while (*FunctionNameList != 0L)
1468 if ((*FunctionNameList) & 0x80000000)
1472 Hint = (*FunctionNameList) & 0xffff;
1477 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1478 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1480 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1482 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1486 ImportAddressList++;
1491 ps("Finished importing.\n");
1498 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1502 PIMAGE_EXPORT_DIRECTORY ExportDir;
1503 ULONG ExportDirSize;
1505 PVOID ExportAddress;
1507 PDWORD FunctionList, NameList;
1509 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1510 RtlImageDirectoryEntryToData(ModuleObject->Base,
1512 IMAGE_DIRECTORY_ENTRY_EXPORT,
1514 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1515 if (ExportDir == NULL)
1520 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1521 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1522 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1528 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1531 DPRINT(" Name:%s NameList[%d]:%s\n",
1534 (DWORD) ModuleObject->Base + NameList[Idx]);
1537 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1539 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1540 FunctionList[OrdinalList[Idx]]);
1541 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1542 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1544 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1545 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1546 DPRINT("ExportAddress: %p\n", ExportAddress);
1555 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1556 FunctionList[Hint - ExportDir->Base]);
1559 if (ExportAddress == NULL)
1561 DbgPrint("Export not found for %d:%s\n",
1563 Name != NULL ? Name : "(Ordinal)");
1567 return(ExportAddress);
1572 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1577 PVOID ExportAddress;
1579 PDWORD FunctionList, NameList;
1580 PIMAGE_EXPORT_DIRECTORY ExportDir;
1581 ULONG ExportDirSize;
1583 static BOOLEAN EP = FALSE;
1585 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1586 RtlImageDirectoryEntryToData(ImportModuleBase,
1588 IMAGE_DIRECTORY_ENTRY_EXPORT,
1593 ps("ExportDir %x\n", ExportDir);
1596 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1597 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1598 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1604 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1606 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1608 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1609 FunctionList[OrdinalList[Idx]]);
1616 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1618 FunctionList[Hint - ExportDir->Base]);
1621 if (ExportAddress == 0)
1623 ps("Export not found for %d:%s\n",
1625 Name != NULL ? Name : "(Ordinal)");
1628 return ExportAddress;
1633 LdrPEFixupForward(PCHAR ForwardName)
1635 CHAR NameBuffer[128];
1636 UNICODE_STRING ModuleName;
1638 PMODULE_OBJECT ModuleObject;
1640 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1642 strcpy(NameBuffer, ForwardName);
1643 p = strchr(NameBuffer, '.');
1651 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1653 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1655 ModuleObject = LdrGetModuleObject(&ModuleName);
1656 RtlFreeUnicodeString(&ModuleName);
1658 DPRINT("ModuleObject: %p\n", ModuleObject);
1660 if (ModuleObject == NULL)
1662 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1666 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));