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>
51 #include <glib/gmessages.h>
52 #endif /* LIBCAPTIVE */
54 /* GLOBALS *******************************************************************/
56 LIST_ENTRY ModuleListHead;
57 KSPIN_LOCK ModuleListLock;
59 LIST_ENTRY ModuleTextListHead;
61 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
62 STATIC MODULE_TEXT_SECTION LdrHalTextSection;
63 #endif /* LIBCAPTIVE */
66 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
68 /* FORWARD DECLARATIONS ******************************************************/
71 LdrProcessModule(PVOID ModuleLoadBase,
72 PUNICODE_STRING ModuleName,
73 PMODULE_OBJECT *ModuleObject);
76 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
82 #endif /* LIBCAPTIVE */
84 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
85 PUNICODE_STRING FullName);
88 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
89 IN PUNICODE_STRING String2);
92 /* PE Driver load support */
93 static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase,
94 PUNICODE_STRING FileName,
95 PMODULE_OBJECT *ModuleObject);
97 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
103 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
106 #endif /* LIBCAPTIVE */
109 LdrPEFixupForward(PCHAR ForwardName);
112 /* FUNCTIONS *****************************************************************/
117 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
119 PLIST_ENTRY current_entry;
120 MODULE_TEXT_SECTION* current;
122 current_entry = ModuleTextListHead.Flink;
123 while (current_entry != &ModuleTextListHead)
126 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
127 if (wcscmp(current->Name, Name) == 0)
131 current_entry = current_entry->Flink;
134 if (current_entry == &ModuleTextListHead)
143 PIMAGE_DOS_HEADER DosHeader;
144 PIMAGE_FILE_HEADER FileHeader;
145 PIMAGE_OPTIONAL_HEADER OptionalHeader;
146 PIMAGE_SECTION_HEADER SectionList;
148 InitializeListHead(&ModuleTextListHead);
150 /* Setup ntoskrnl.exe text section */
151 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
153 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
154 DosHeader->e_lfanew + sizeof(ULONG));
155 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
156 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
157 SectionList = (PIMAGE_SECTION_HEADER)
158 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
159 NtoskrnlTextSection.Base = KERNEL_BASE;
160 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
161 SectionList[0].VirtualAddress;
162 NtoskrnlTextSection.Name = KERNEL_MODULE_NAME;
163 NtoskrnlTextSection.OptionalHeader = OptionalHeader;
164 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
166 /* Setup hal.dll text section */
167 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
169 (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase +
170 DosHeader->e_lfanew + sizeof(ULONG));
171 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
172 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
173 SectionList = (PIMAGE_SECTION_HEADER)
174 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
175 LdrHalTextSection.Base = LdrHalBase;
176 LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize +
177 SectionList[0].VirtualAddress;
178 LdrHalTextSection.Name = HAL_MODULE_NAME;
179 LdrHalTextSection.OptionalHeader = OptionalHeader;
180 InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry);
182 /* Hook for KDB on initialization of the loader. */
183 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection);
188 LdrInitModuleManagement(VOID)
190 PIMAGE_DOS_HEADER DosHeader;
191 PMODULE_OBJECT ModuleObject;
193 /* Initialize the module list and spinlock */
194 InitializeListHead(&ModuleListHead);
195 KeInitializeSpinLock(&ModuleListLock);
197 /* Create module object for NTOSKRNL */
198 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
199 assert(ModuleObject != NULL);
200 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
202 /* Initialize ModuleObject data */
203 ModuleObject->Base = (PVOID) KERNEL_BASE;
204 ModuleObject->Flags = MODULE_FLAG_PE;
205 RtlCreateUnicodeString(&ModuleObject->FullName,
207 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
208 &ModuleObject->FullName);
210 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
211 ModuleObject->Image.PE.FileHeader =
212 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
213 DosHeader->e_lfanew + sizeof(ULONG));
214 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
215 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
216 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
217 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
218 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
219 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
220 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
221 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
222 ModuleObject->TextSection = &NtoskrnlTextSection;
224 InsertTailList(&ModuleListHead,
225 &ModuleObject->ListEntry);
227 /* Create module object for HAL */
228 ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
229 assert(ModuleObject != NULL);
230 RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT));
232 /* Initialize ModuleObject data */
233 ModuleObject->Base = (PVOID) LdrHalBase;
234 ModuleObject->Flags = MODULE_FLAG_PE;
236 RtlCreateUnicodeString(&ModuleObject->FullName,
238 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
239 &ModuleObject->FullName);
241 DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase;
242 ModuleObject->Image.PE.FileHeader =
243 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
244 DosHeader->e_lfanew + sizeof(ULONG));
245 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
246 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
247 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
248 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
249 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
250 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
251 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
252 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
253 ModuleObject->TextSection = &LdrHalTextSection;
255 InsertTailList(&ModuleListHead,
256 &ModuleObject->ListEntry);
260 LdrpLoadImage(PUNICODE_STRING DriverName,
262 PVOID *SectionPointer,
264 PVOID *ExportSectionPointer)
266 PMODULE_OBJECT ModuleObject;
269 ModuleObject = LdrGetModuleObject(DriverName);
270 if (ModuleObject == NULL)
272 Status = LdrLoadModule(DriverName, &ModuleObject);
273 if (!NT_SUCCESS(Status))
280 *ModuleBase = ModuleObject->Base;
282 // if (SectionPointer)
283 // *SectionPointer = ModuleObject->
286 *EntryPoint = ModuleObject->EntryPoint;
288 // if (ExportSectionPointer)
289 // *ExportSectionPointer = ModuleObject->
291 return(STATUS_SUCCESS);
296 LdrpUnloadImage(PVOID ModuleBase)
298 return(STATUS_NOT_IMPLEMENTED);
303 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName)
305 PDRIVER_INITIALIZE DriverEntry;
306 PMODULE_OBJECT ModuleObject;
309 ModuleObject = LdrGetModuleObject(ModuleName);
310 if (ModuleObject != NULL)
312 return(STATUS_IMAGE_ALREADY_LOADED);
315 Status = LdrLoadModule(ModuleName, &ModuleObject);
316 if (!NT_SUCCESS(Status))
321 DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint;
323 Status = DriverEntry(NULL, NULL);
324 if (!NT_SUCCESS(Status))
326 LdrUnloadModule(ModuleObject);
334 LdrLoadModule(PUNICODE_STRING Filename,
335 PMODULE_OBJECT *ModuleObject)
337 PVOID ModuleLoadBase;
340 OBJECT_ATTRIBUTES ObjectAttributes;
341 PMODULE_OBJECT Module;
342 FILE_STANDARD_INFORMATION FileStdInfo;
343 IO_STATUS_BLOCK IoStatusBlock;
345 *ModuleObject = NULL;
347 DPRINT("Loading Module %wZ...\n", Filename);
349 /* Open the Module */
350 InitializeObjectAttributes(&ObjectAttributes,
356 Status = NtOpenFile(&FileHandle,
361 FILE_SYNCHRONOUS_IO_NONALERT);
363 if (!NT_SUCCESS(Status))
365 CPRINT("Could not open module file: %wZ\n", Filename);
370 /* Get the size of the file */
371 Status = NtQueryInformationFile(FileHandle,
375 FileStandardInformation);
376 if (!NT_SUCCESS(Status))
378 CPRINT("Could not get file size\n");
384 /* Allocate nonpageable memory for driver */
385 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
386 FileStdInfo.EndOfFile.u.LowPart,
388 if (ModuleLoadBase == NULL)
390 CPRINT("Could not allocate memory for module");
392 return(STATUS_INSUFFICIENT_RESOURCES);
396 /* Load driver into memory chunk */
397 Status = NtReadFile(FileHandle,
401 FileStdInfo.EndOfFile.u.LowPart,
403 if (!NT_SUCCESS(Status))
405 CPRINT("Could not read module file into memory");
406 ExFreePool(ModuleLoadBase);
414 Status = LdrProcessModule(ModuleLoadBase,
417 if (!NT_SUCCESS(Status))
419 CPRINT("Could not process module");
420 ExFreePool(ModuleLoadBase);
425 ExFreePool(ModuleLoadBase);
427 *ModuleObject = Module;
429 /* Hook for KDB on loading a driver. */
430 KDB_LOADDRIVER_HOOK(Filename, Module);
432 return(STATUS_SUCCESS);
435 #endif /* LIBCAPTIVE */
438 LdrUnloadModule(PMODULE_OBJECT ModuleObject)
442 /* Remove the module from the module list */
443 KeAcquireSpinLock(&ModuleListLock,&Irql);
444 RemoveEntryList(&ModuleObject->ListEntry);
445 KeReleaseSpinLock(&ModuleListLock, Irql);
447 /* Hook for KDB on unloading a driver. */
448 KDB_UNLOADDRIVER_HOOK(ModuleObject);
450 /* Free text section */
451 if (ModuleObject->TextSection != NULL)
453 ExFreePool(ModuleObject->TextSection->Name);
454 RemoveEntryList(&ModuleObject->TextSection->ListEntry);
455 ExFreePool(ModuleObject->TextSection);
456 ModuleObject->TextSection = NULL;
459 /* Free module section */
460 // MmFreeSection(ModuleObject->Base);
462 ExFreePool(ModuleObject);
464 return(STATUS_SUCCESS);
470 LdrInitializeBootStartDriver(PVOID ModuleLoadBase,
474 PMODULE_OBJECT ModuleObject;
475 UNICODE_STRING ModuleName;
476 PDEVICE_NODE DeviceNode;
479 WCHAR Buffer[MAX_PATH];
484 CHAR TextBuffer [256];
487 HalQueryDisplayParameters(&x, &y, &cx, &cy);
488 RtlFillMemory(TextBuffer, x, ' ');
489 TextBuffer[x] = '\0';
490 HalSetDisplayParameters(0, y-1);
491 HalDisplayString(TextBuffer);
493 sprintf(TextBuffer, "Initializing %s...\n", FileName);
494 HalSetDisplayParameters(0, y-1);
495 HalDisplayString(TextBuffer);
496 HalSetDisplayParameters(cx, cy);
498 /* Split the filename into base name and extension */
499 FileExt = strrchr(FileName, '.');
501 Length = FileExt - FileName;
503 Length = strlen(FileName);
505 if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0))
507 KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length);
508 return(STATUS_SUCCESS);
510 else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0))
512 CPRINT("Ignoring non-driver file %s\n", FileName);
513 return STATUS_SUCCESS;
516 /* Use IopRootDeviceNode for now */
517 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
518 if (!NT_SUCCESS(Status))
520 CPRINT("Driver load failed, status (%x)\n", Status);
524 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
526 Status = LdrProcessModule(ModuleLoadBase,
529 RtlFreeUnicodeString(&ModuleName);
530 if (ModuleObject == NULL)
532 IopFreeDeviceNode(DeviceNode);
533 CPRINT("Driver load failed, status (%x)\n", Status);
534 return(STATUS_UNSUCCESSFUL);
538 /* Get the service name from the module name */
539 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
541 Start = ModuleObject->BaseName.Buffer;
545 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
547 Length = Ext - Start;
549 Length = wcslen(Start);
551 wcsncpy(Buffer, Start, Length);
553 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
555 Status = IopInitializeDriver(ModuleObject->EntryPoint,
558 ModuleObject->Length);
559 if (!NT_SUCCESS(Status))
561 IopFreeDeviceNode(DeviceNode);
562 CPRINT("Driver load failed, status (%x)\n", Status);
568 #endif /* LIBCAPTIVE */
571 LdrProcessModule(PVOID ModuleLoadBase,
572 PUNICODE_STRING ModuleName,
573 PMODULE_OBJECT *ModuleObject)
575 PIMAGE_DOS_HEADER PEDosHeader;
577 /* If MZ header exists */
578 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
579 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
581 return LdrPEProcessModule(ModuleLoadBase,
586 CPRINT("Module wasn't PE\n");
587 return STATUS_UNSUCCESSFUL;
592 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
596 if (ModuleObject->Flags & MODULE_FLAG_PE)
598 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
609 LdrpQueryModuleInformation(PVOID Buffer,
613 PLIST_ENTRY current_entry;
614 PMODULE_OBJECT current;
615 ULONG ModuleCount = 0;
616 PSYSTEM_MODULE_INFORMATION Smi;
617 ANSI_STRING AnsiName;
621 KeAcquireSpinLock(&ModuleListLock,&Irql);
623 /* calculate required size */
624 current_entry = ModuleListHead.Flink;
625 while (current_entry != (&ModuleListHead))
628 current_entry = current_entry->Flink;
631 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
632 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY);
636 KeReleaseSpinLock(&ModuleListLock, Irql);
637 return(STATUS_INFO_LENGTH_MISMATCH);
640 /* fill the buffer */
641 memset(Buffer, '=', Size);
643 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
644 Smi->Count = ModuleCount;
647 current_entry = ModuleListHead.Flink;
648 while (current_entry != (&ModuleListHead))
650 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
652 Smi->Module[ModuleCount].Unknown1 = 0; /* Always 0 */
653 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
654 Smi->Module[ModuleCount].Base = current->Base;
655 Smi->Module[ModuleCount].Size = current->Length;
656 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
657 Smi->Module[ModuleCount].Index = ModuleCount;
658 Smi->Module[ModuleCount].NameLength = 0;
659 Smi->Module[ModuleCount].LoadCount = 0; /* FIXME */
662 AnsiName.MaximumLength = 256;
663 AnsiName.Buffer = Smi->Module[ModuleCount].ImageName;
664 RtlUnicodeStringToAnsiString(&AnsiName,
668 p = strrchr(AnsiName.Buffer, '\\');
671 Smi->Module[ModuleCount].PathLength = 0;
676 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
680 current_entry = current_entry->Flink;
683 KeReleaseSpinLock(&ModuleListLock, Irql);
685 return(STATUS_SUCCESS);
688 #endif /* LIBCAPTIVE */
692 #endif /* LIBCAPTIVE */
694 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
695 PUNICODE_STRING FullName)
701 DPRINT("LdrpBuildModuleBaseName()\n");
702 DPRINT("FullName %wZ\n", FullName);
704 p = wcsrchr(FullName->Buffer, L'\\');
707 p = FullName->Buffer;
716 RtlCreateUnicodeString(&Name, p);
718 q = wcschr(Name.Buffer, L'.');
726 RtlCreateUnicodeString(BaseName, Name.Buffer);
727 RtlFreeUnicodeString(&Name);
732 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
733 IN PUNICODE_STRING String2)
739 if (String1 && String2)
741 /* Search String1 for last path component */
742 len1 = String1->Length / sizeof(WCHAR);
743 s1 = String1->Buffer;
744 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
748 if (i == String1->Length - sizeof(WCHAR))
756 len1 = (String1->Length - i) / sizeof(WCHAR);
761 /* Search String2 for last path component */
762 len2 = String2->Length / sizeof(WCHAR);
763 s2 = String2->Buffer;
764 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
768 if (i == String2->Length - sizeof(WCHAR))
776 len2 = (String2->Length - i) / sizeof(WCHAR);
781 /* Compare last path components */
786 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
787 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
788 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
790 if (!c1 || !c2 || c1 != c2)
801 LdrGetModuleObject(PUNICODE_STRING ModuleName)
803 PMODULE_OBJECT Module;
807 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
809 KeAcquireSpinLock(&ModuleListLock,&Irql);
811 Entry = ModuleListHead.Flink;
812 while (Entry != &ModuleListHead)
814 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
816 DPRINT("Comparing %wZ and %wZ\n",
820 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
822 DPRINT("Module %wZ\n", &Module->BaseName);
823 KeReleaseSpinLock(&ModuleListLock, Irql);
827 Entry = Entry->Flink;
830 KeReleaseSpinLock(&ModuleListLock, Irql);
832 DPRINT("Could not find module '%wZ'\n", ModuleName);
838 /* ---------------------------------------------- PE Module support */
841 PageNeedsWriteAccess(PVOID PageStart,
843 PIMAGE_FILE_HEADER PEFileHeader,
844 PIMAGE_SECTION_HEADER PESectionHeaders)
846 BOOL NeedsWriteAccess;
848 ULONG Characteristics;
852 NeedsWriteAccess = FALSE;
853 /* Set the protections for the various parts of the driver */
854 for (Idx = 0; Idx < PEFileHeader->NumberOfSections && ! NeedsWriteAccess; Idx++)
856 Characteristics = PESectionHeaders[Idx].Characteristics;
857 if (!(Characteristics & IMAGE_SECTION_CHAR_CODE) ||
858 (Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
859 Characteristics & IMAGE_SECTION_CHAR_DATA ||
860 Characteristics & IMAGE_SECTION_CHAR_BSS))
863 max(PESectionHeaders[Idx].Misc.VirtualSize,
864 PESectionHeaders[Idx].SizeOfRawData);
865 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
866 NeedsWriteAccess = BaseAddress < PageStart + PAGE_SIZE &&
867 PageStart < (PVOID)((PCHAR) BaseAddress + Length);
871 return(NeedsWriteAccess);
875 LdrPEProcessModule(PVOID ModuleLoadBase,
876 PUNICODE_STRING FileName,
877 PMODULE_OBJECT *ModuleObject)
879 unsigned int DriverSize, Idx;
880 ULONG RelocDelta, NumRelocs;
881 DWORD CurrentSize, TotalRelocs;
884 PIMAGE_DOS_HEADER PEDosHeader;
885 PIMAGE_FILE_HEADER PEFileHeader;
886 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
887 PIMAGE_SECTION_HEADER PESectionHeaders;
888 PRELOCATION_DIRECTORY RelocDir;
889 PRELOCATION_ENTRY RelocEntry;
890 PMODULE_OBJECT LibraryModuleObject;
891 PMODULE_OBJECT CreatedModuleObject;
892 PVOID *ImportAddressList;
893 PULONG FunctionNameList;
896 UNICODE_STRING ModuleName;
897 UNICODE_STRING NameString;
898 WCHAR NameBuffer[60];
899 MODULE_TEXT_SECTION* ModuleTextSection;
903 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
905 /* Get header pointers */
906 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
907 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
908 PEDosHeader->e_lfanew);
909 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
910 PEDosHeader->e_lfanew + sizeof(ULONG));
911 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
912 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
913 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
914 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
915 sizeof(IMAGE_OPTIONAL_HEADER));
918 /* Check file magic numbers */
919 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
921 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
922 return STATUS_UNSUCCESSFUL;
924 if (PEDosHeader->e_lfanew == 0)
926 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
927 return STATUS_UNSUCCESSFUL;
929 if (*PEMagic != IMAGE_PE_MAGIC)
931 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
932 return STATUS_UNSUCCESSFUL;
934 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
936 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
937 return STATUS_UNSUCCESSFUL;
941 /* FIXME: if image is fixed-address load, then fail */
943 /* FIXME: check/verify OS version number */
945 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
946 PEOptionalHeader->Magic,
947 PEOptionalHeader->MajorLinkerVersion,
948 PEOptionalHeader->MinorLinkerVersion);
949 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
952 /* Determine the size of the module */
953 DriverSize = PEOptionalHeader->SizeOfImage;
954 DPRINT("DriverSize %x\n",DriverSize);
956 /* Allocate a virtual section for the module */
957 DriverBase = MmAllocateSection(DriverSize);
960 CPRINT("Failed to allocate a virtual section for driver\n");
961 return STATUS_UNSUCCESSFUL;
963 DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase);
965 /* Copy headers over */
966 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
968 /* Copy image sections into virtual section */
969 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
971 // Copy current section into current offset of virtual section
972 if (PESectionHeaders[Idx].Characteristics &
973 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
975 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
976 PESectionHeaders[Idx].VirtualAddress + DriverBase);
977 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
978 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
979 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData
980 ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
984 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
985 PESectionHeaders[Idx].VirtualAddress + DriverBase);
986 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
987 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
990 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
991 PEOptionalHeader->SectionAlignment);
994 // CurrentBase = (PVOID)((DWORD)CurrentBase +
995 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
996 // PEOptionalHeader->SectionAlignment));
999 /* Perform relocation fixups */
1000 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
1001 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1002 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1003 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1005 PEOptionalHeader->ImageBase,
1007 DPRINT("RelocDir %x\n",RelocDir);
1009 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1011 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1013 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1014 PESectionHeaders[Idx].Name,
1015 PESectionHeaders[Idx].PointerToRawData);
1016 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1018 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1023 RelocDir = RelocDir + (ULONG)DriverBase;
1024 CurrentSize = PEOptionalHeader->DataDirectory
1025 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1027 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1029 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1031 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1033 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1035 RelocDir->VirtualAddress,
1037 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1038 sizeof(RELOCATION_DIRECTORY));
1039 for (Idx = 0; Idx < NumRelocs; Idx++)
1045 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1046 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1047 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1049 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1052 Type ? "HIGHLOW" : "ABS",
1054 (*RelocItem) + RelocDelta); */
1057 (*RelocItem) += RelocDelta;
1061 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1062 return STATUS_UNSUCCESSFUL;
1065 TotalRelocs += RelocDir->SizeOfBlock;
1066 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1067 RelocDir->SizeOfBlock);
1068 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1071 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1072 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1074 /* Perform import fixups */
1075 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1077 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1079 /* Process each import module */
1080 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1081 ((DWORD)DriverBase + PEOptionalHeader->
1082 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1083 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1084 while (ImportModuleDirectory->dwRVAModuleName)
1086 /* Check to make sure that import lib is kernel */
1087 pName = (PCHAR) DriverBase +
1088 ImportModuleDirectory->dwRVAModuleName;
1090 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1091 DPRINT("Import module: %wZ\n", &ModuleName);
1093 LibraryModuleObject = LdrGetModuleObject(&ModuleName);
1094 if (LibraryModuleObject == NULL)
1096 DPRINT("Module '%wZ' not loaded yet\n", &ModuleName);
1097 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\drivers\\"));
1098 wcscat(NameBuffer, ModuleName.Buffer);
1099 RtlInitUnicodeString(&NameString, NameBuffer);
1100 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1101 if (!NT_SUCCESS(Status))
1103 wcscpy(NameBuffer, REACTOS_UCS2(L"\\SystemRoot\\system32\\"));
1104 wcscat(NameBuffer, ModuleName.Buffer);
1105 RtlInitUnicodeString(&NameString, NameBuffer);
1106 Status = LdrLoadModule(&NameString, &LibraryModuleObject);
1107 if (!NT_SUCCESS(Status))
1109 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1114 /* Get the import address list */
1115 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1116 ImportModuleDirectory->dwRVAFunctionAddressList);
1118 /* Get the list of functions to import */
1119 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1121 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1122 ImportModuleDirectory->dwRVAFunctionNameList);
1126 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1127 ImportModuleDirectory->dwRVAFunctionAddressList);
1129 /* Walk through function list and fixup addresses */
1130 while (*FunctionNameList != 0L)
1132 if ((*FunctionNameList) & 0x80000000) // hint
1137 Hint = (*FunctionNameList) & 0xffff;
1141 pName = (PCHAR)((DWORD)DriverBase +
1142 *FunctionNameList + 2);
1143 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1145 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1147 /* Fixup the current import symbol */
1148 if (LibraryModuleObject != NULL)
1150 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1156 CPRINT("Unresolved kernel symbol: %s\n", pName);
1157 return STATUS_UNSUCCESSFUL;
1159 ImportAddressList++;
1163 RtlFreeUnicodeString(&ModuleName);
1165 ImportModuleDirectory++;
1169 /* Set the protections for the various parts of the driver */
1170 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1172 ULONG Characteristics = PESectionHeaders[Idx].Characteristics;
1176 if (Characteristics & IMAGE_SECTION_CHAR_CODE &&
1177 !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE ||
1178 Characteristics & IMAGE_SECTION_CHAR_DATA ||
1179 Characteristics & IMAGE_SECTION_CHAR_BSS))
1182 max(PESectionHeaders[Idx].Misc.VirtualSize,
1183 PESectionHeaders[Idx].SizeOfRawData);
1184 BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase;
1185 PageAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
1186 if (! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1188 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1190 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1191 while ((PVOID)((PCHAR) PageAddress + PAGE_SIZE) <
1192 (PVOID)((PCHAR) BaseAddress + Length))
1194 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1195 PageAddress = (PVOID)((PCHAR) PageAddress + PAGE_SIZE);
1197 if (PageAddress < (PVOID)((PCHAR) BaseAddress + Length) &&
1198 ! PageNeedsWriteAccess(PageAddress, DriverBase, PEFileHeader, PESectionHeaders))
1200 MmSetPageProtect(NULL, PageAddress, PAGE_READONLY);
1205 /* Create the module */
1206 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1207 if (CreatedModuleObject == NULL)
1209 return(STATUS_INSUFFICIENT_RESOURCES);
1212 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1214 /* Initialize ModuleObject data */
1215 CreatedModuleObject->Base = DriverBase;
1216 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1218 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1220 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1221 &CreatedModuleObject->FullName);
1223 CreatedModuleObject->EntryPoint =
1224 (PVOID)((DWORD)DriverBase +
1225 PEOptionalHeader->AddressOfEntryPoint);
1226 CreatedModuleObject->Length = DriverSize;
1227 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1229 CreatedModuleObject->Image.PE.FileHeader =
1230 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1232 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1233 CreatedModuleObject->Image.PE.OptionalHeader =
1234 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1235 sizeof(IMAGE_FILE_HEADER));
1236 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1237 CreatedModuleObject->Image.PE.SectionList =
1238 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1239 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1240 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1243 KeAcquireSpinLock(&ModuleListLock, &Irql);
1244 InsertTailList(&ModuleListHead,
1245 &CreatedModuleObject->ListEntry);
1246 KeReleaseSpinLock(&ModuleListLock, Irql);
1249 ModuleTextSection = ExAllocatePool(NonPagedPool,
1250 sizeof(MODULE_TEXT_SECTION));
1251 assert(ModuleTextSection);
1252 RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION));
1253 ModuleTextSection->Base = (ULONG)DriverBase;
1254 ModuleTextSection->Length = DriverSize;
1255 ModuleTextSection->Name = ExAllocatePool(NonPagedPool,
1256 (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR));
1257 wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer);
1258 ModuleTextSection->OptionalHeader =
1259 CreatedModuleObject->Image.PE.OptionalHeader;
1260 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1262 CreatedModuleObject->TextSection = ModuleTextSection;
1264 *ModuleObject = CreatedModuleObject;
1266 DPRINT("Loading Module %wZ...\n", FileName);
1268 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1270 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1271 FileName, CreatedModuleObject->Base);
1274 return STATUS_SUCCESS;
1280 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1282 PVOID ImportModuleBase,
1286 ULONG RelocDelta, NumRelocs;
1287 ULONG CurrentSize, TotalRelocs;
1289 PIMAGE_DOS_HEADER PEDosHeader;
1290 PIMAGE_FILE_HEADER PEFileHeader;
1291 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1292 PIMAGE_SECTION_HEADER PESectionHeaders;
1293 PRELOCATION_DIRECTORY RelocDir;
1294 PRELOCATION_ENTRY RelocEntry;
1295 PVOID *ImportAddressList;
1296 PULONG FunctionNameList;
1300 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1302 /* Get header pointers */
1303 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1304 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1305 PEDosHeader->e_lfanew);
1306 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1307 PEDosHeader->e_lfanew + sizeof(ULONG));
1308 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1309 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1310 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1311 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1312 sizeof(IMAGE_OPTIONAL_HEADER));
1315 /* Check file magic numbers */
1316 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1320 if (PEDosHeader->e_lfanew == 0)
1324 if (*PEMagic != IMAGE_PE_MAGIC)
1328 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1333 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1334 PEOptionalHeader->Magic,
1335 PEOptionalHeader->MajorLinkerVersion,
1336 PEOptionalHeader->MinorLinkerVersion);
1337 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1339 /* Determine the size of the module */
1340 *DriverSize = PEOptionalHeader->SizeOfImage;
1341 ps("DriverSize %x\n",*DriverSize);
1343 /* Copy headers over */
1344 if (DriverBase != ModuleLoadBase)
1346 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1349 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1350 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1351 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1353 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1354 address as it is mapped */
1355 if (DriverBase != ModuleLoadBase)
1359 /* Copy image sections into virtual section */
1360 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1362 // Copy current section into current offset of virtual section
1363 if (PESectionHeaders[Idx].Characteristics &
1364 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1366 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1367 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1368 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1369 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1370 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1371 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1375 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1376 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1377 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1379 PESectionHeaders[Idx].Misc.VirtualSize);
1381 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1382 PEOptionalHeader->SectionAlignment);
1385 /* Perform relocation fixups */
1386 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1387 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1388 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1389 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1391 PEOptionalHeader->ImageBase,
1393 ps("RelocDir %x\n",RelocDir);
1395 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1397 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1399 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1400 PESectionHeaders[Idx].Name,
1401 PESectionHeaders[Idx].PointerToRawData);
1402 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1403 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1408 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1411 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1413 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1415 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1416 sizeof(RELOCATION_DIRECTORY));
1417 for (Idx = 0; Idx < NumRelocs; Idx++)
1423 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1424 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1425 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1428 (*RelocItem) += RelocDelta;
1432 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1436 TotalRelocs += RelocDir->SizeOfBlock;
1437 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1438 RelocDir->SizeOfBlock);
1441 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1442 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1446 /* Perform import fixups */
1447 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1449 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1451 /* Process each import module */
1452 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1453 ((ULONG)DriverBase + PEOptionalHeader->
1454 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1456 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1458 /* Check to make sure that import lib is kernel */
1459 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1461 ps("Import module: %s\n", pName);
1463 /* Get the import address list */
1464 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1465 ImportModuleDirectory->dwRVAFunctionAddressList);
1467 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1468 ImportModuleDirectory->dwRVAFunctionAddressList);
1469 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1471 /* Get the list of functions to import */
1472 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1474 ps("Using function name list.\n");
1476 FunctionNameList = (PULONG)((ULONG)DriverBase +
1477 ImportModuleDirectory->dwRVAFunctionNameList);
1481 ps("Using function address list.\n");
1483 FunctionNameList = (PULONG)((ULONG)DriverBase +
1484 ImportModuleDirectory->dwRVAFunctionAddressList);
1487 /* Walk through function list and fixup addresses */
1488 while (*FunctionNameList != 0L)
1490 if ((*FunctionNameList) & 0x80000000)
1494 Hint = (*FunctionNameList) & 0xffff;
1499 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1500 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1502 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1504 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1508 ImportAddressList++;
1513 ps("Finished importing.\n");
1518 #endif /* LIBCAPTIVE */
1521 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1525 PIMAGE_EXPORT_DIRECTORY ExportDir;
1526 ULONG ExportDirSize;
1528 PVOID ExportAddress;
1530 PDWORD FunctionList, NameList;
1532 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1533 RtlImageDirectoryEntryToData(ModuleObject->Base,
1535 IMAGE_DIRECTORY_ENTRY_EXPORT,
1537 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1538 if (ExportDir == NULL)
1543 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1544 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1545 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1551 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1554 DPRINT(" Name:%s NameList[%d]:%s\n",
1557 (DWORD) ModuleObject->Base + NameList[Idx]);
1560 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1562 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1563 FunctionList[OrdinalList[Idx]]);
1564 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1565 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1567 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1568 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1569 DPRINT("ExportAddress: %p\n", ExportAddress);
1579 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1580 FunctionList[Hint - ExportDir->Base]);
1581 #else /* !LIBCAPTIVE */
1582 /* Ordinals not supported by libcaptive */
1584 #endif /* !LIBCAPTIVE */
1587 if (ExportAddress == NULL)
1589 DbgPrint("Export not found for %d:%s\n",
1591 Name != NULL ? Name : "(Ordinal)");
1593 g_error("Please check the versions of \"ntfs.sys\" and \"ntoskrnl.exe\" - do they match each other?\n"
1594 "Because export not found for: %d:%s",Hint,(Name ? Name : "(Ordinal)"));
1595 #endif /* LIBCAPTIVE */
1599 return(ExportAddress);
1605 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
1610 PVOID ExportAddress;
1612 PDWORD FunctionList, NameList;
1613 PIMAGE_EXPORT_DIRECTORY ExportDir;
1614 ULONG ExportDirSize;
1616 static BOOLEAN EP = FALSE;
1618 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1619 RtlImageDirectoryEntryToData(ImportModuleBase,
1621 IMAGE_DIRECTORY_ENTRY_EXPORT,
1626 ps("ExportDir %x\n", ExportDir);
1629 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
1630 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
1631 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
1637 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1639 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
1641 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1642 FunctionList[OrdinalList[Idx]]);
1649 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
1651 FunctionList[Hint - ExportDir->Base]);
1654 if (ExportAddress == 0)
1656 ps("Export not found for %d:%s\n",
1658 Name != NULL ? Name : "(Ordinal)");
1661 return ExportAddress;
1664 #endif /* LIBCAPTIVE */
1667 LdrPEFixupForward(PCHAR ForwardName)
1669 CHAR NameBuffer[128];
1670 UNICODE_STRING ModuleName;
1672 PMODULE_OBJECT ModuleObject;
1674 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1676 strcpy(NameBuffer, ForwardName);
1677 p = strchr(NameBuffer, '.');
1685 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1687 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1689 ModuleObject = LdrGetModuleObject(&ModuleName);
1690 RtlFreeUnicodeString(&ModuleName);
1692 DPRINT("ModuleObject: %p\n", ModuleObject);
1694 if (ModuleObject == NULL)
1696 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1700 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));