1 /* $Id: loader.c,v 1.144 2004/09/25 06:41:16 arty Exp $
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 *****************************************************************/
30 #include <internal/ntosdbg.h>
40 #include <internal/debug.h>
42 /* GLOBALS *******************************************************************/
44 LIST_ENTRY ModuleListHead
;
45 KSPIN_LOCK ModuleListLock
;
47 LIST_ENTRY ModuleTextListHead
;
48 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
49 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
52 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
54 /* FORWARD DECLARATIONS ******************************************************/
57 LdrProcessModule(PVOID ModuleLoadBase
,
58 PUNICODE_STRING ModuleName
,
59 PMODULE_OBJECT
*ModuleObject
);
62 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
67 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
68 PUNICODE_STRING FullName
);
71 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
72 IN PUNICODE_STRING String2
);
75 /* PE Driver load support */
76 static NTSTATUS
LdrPEProcessModule(PVOID ModuleLoadBase
,
77 PUNICODE_STRING FileName
,
78 PMODULE_OBJECT
*ModuleObject
);
80 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
85 LdrSafePEGetExportAddress(PVOID ImportModuleBase
,
90 LdrPEFixupForward(PCHAR ForwardName
);
93 /* FUNCTIONS *****************************************************************/
96 LdrInitDebug(PLOADER_MODULE Module
, PWCH Name
)
98 PLIST_ENTRY current_entry
;
99 MODULE_TEXT_SECTION
* current
;
101 current_entry
= ModuleTextListHead
.Flink
;
102 while (current_entry
!= &ModuleTextListHead
)
105 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
106 if (wcscmp(current
->Name
, Name
) == 0)
110 current_entry
= current_entry
->Flink
;
113 if (current_entry
== &ModuleTextListHead
)
122 PIMAGE_NT_HEADERS NtHeader
;
123 PIMAGE_SECTION_HEADER SectionList
;
125 InitializeListHead(&ModuleTextListHead
);
127 /* Setup ntoskrnl.exe text section */
129 * This isn't the base of the text segment, but the start of the
130 * full image (in memory)
131 * Also, the Length field isn't set to the length of the segment,
132 * but is more like the offset, from the image base, to the end
135 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
136 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
137 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
138 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
139 SectionList
[0].VirtualAddress
;
140 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
141 NtoskrnlTextSection
.OptionalHeader
= OPTHDROFFSET(KERNEL_BASE
);
142 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
144 /* Setup hal.dll text section */
145 /* Same comment as above applies */
146 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
147 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
148 LdrHalTextSection
.Base
= LdrHalBase
;
149 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
150 SectionList
[0].VirtualAddress
;
151 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
152 LdrHalTextSection
.OptionalHeader
= OPTHDROFFSET(LdrHalBase
);
153 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
155 /* Hook for KDB on initialization of the loader. */
156 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection
, &LdrHalTextSection
);
161 LdrInitModuleManagement(VOID
)
163 PIMAGE_DOS_HEADER DosHeader
;
164 PMODULE_OBJECT ModuleObject
;
166 /* Initialize the module list and spinlock */
167 InitializeListHead(&ModuleListHead
);
168 KeInitializeSpinLock(&ModuleListLock
);
170 /* Create module object for NTOSKRNL */
171 ModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
172 assert(ModuleObject
!= NULL
);
173 RtlZeroMemory(ModuleObject
, sizeof(MODULE_OBJECT
));
175 /* Initialize ModuleObject data */
176 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
177 ModuleObject
->Flags
= MODULE_FLAG_PE
;
178 RtlCreateUnicodeString(&ModuleObject
->FullName
,
180 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
181 &ModuleObject
->FullName
);
183 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
184 ModuleObject
->Image
.PE
.FileHeader
=
185 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
186 DosHeader
->e_lfanew
+ sizeof(ULONG
));
187 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
188 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
189 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
190 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
191 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
192 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
193 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
194 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
195 ModuleObject
->TextSection
= &NtoskrnlTextSection
;
197 InsertTailList(&ModuleListHead
,
198 &ModuleObject
->ListEntry
);
200 /* Create module object for HAL */
201 ModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
202 assert(ModuleObject
!= NULL
);
203 RtlZeroMemory(ModuleObject
, sizeof(MODULE_OBJECT
));
205 /* Initialize ModuleObject data */
206 ModuleObject
->Base
= (PVOID
) LdrHalBase
;
207 ModuleObject
->Flags
= MODULE_FLAG_PE
;
209 RtlCreateUnicodeString(&ModuleObject
->FullName
,
211 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
212 &ModuleObject
->FullName
);
214 DosHeader
= (PIMAGE_DOS_HEADER
) LdrHalBase
;
215 ModuleObject
->Image
.PE
.FileHeader
=
216 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
217 DosHeader
->e_lfanew
+ sizeof(ULONG
));
218 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
219 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
220 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
221 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
222 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
223 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
224 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
225 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
226 ModuleObject
->TextSection
= &LdrHalTextSection
;
228 InsertTailList(&ModuleListHead
,
229 &ModuleObject
->ListEntry
);
233 LdrpLoadImage(PUNICODE_STRING DriverName
,
235 PVOID
*SectionPointer
,
237 PVOID
*ExportSectionPointer
)
239 PMODULE_OBJECT ModuleObject
;
242 ModuleObject
= LdrGetModuleObject(DriverName
);
243 if (ModuleObject
== NULL
)
245 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
246 if (!NT_SUCCESS(Status
))
253 *ModuleBase
= ModuleObject
->Base
;
255 // if (SectionPointer)
256 // *SectionPointer = ModuleObject->
259 *EntryPoint
= ModuleObject
->EntryPoint
;
261 // if (ExportSectionPointer)
262 // *ExportSectionPointer = ModuleObject->
264 return(STATUS_SUCCESS
);
269 LdrpUnloadImage(PVOID ModuleBase
)
271 return(STATUS_NOT_IMPLEMENTED
);
276 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName
)
278 PDRIVER_INITIALIZE DriverEntry
;
279 PMODULE_OBJECT ModuleObject
;
282 ModuleObject
= LdrGetModuleObject(ModuleName
);
283 if (ModuleObject
!= NULL
)
285 return(STATUS_IMAGE_ALREADY_LOADED
);
288 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
289 if (!NT_SUCCESS(Status
))
294 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
296 Status
= DriverEntry(NULL
, NULL
);
297 if (!NT_SUCCESS(Status
))
299 LdrUnloadModule(ModuleObject
);
307 LdrLoadModule(PUNICODE_STRING Filename
,
308 PMODULE_OBJECT
*ModuleObject
)
310 PVOID ModuleLoadBase
;
313 OBJECT_ATTRIBUTES ObjectAttributes
;
314 PMODULE_OBJECT Module
;
315 FILE_STANDARD_INFORMATION FileStdInfo
;
316 IO_STATUS_BLOCK IoStatusBlock
;
318 *ModuleObject
= NULL
;
320 DPRINT("Loading Module %wZ...\n", Filename
);
322 /* Open the Module */
323 InitializeObjectAttributes(&ObjectAttributes
,
325 OBJ_CASE_INSENSITIVE
,
329 Status
= NtOpenFile(&FileHandle
,
334 FILE_SYNCHRONOUS_IO_NONALERT
);
336 if (!NT_SUCCESS(Status
))
338 CPRINT("Could not open module file: %wZ\n", Filename
);
343 /* Get the size of the file */
344 Status
= NtQueryInformationFile(FileHandle
,
348 FileStandardInformation
);
349 if (!NT_SUCCESS(Status
))
351 CPRINT("Could not get file size\n");
357 /* Allocate nonpageable memory for driver */
358 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
359 FileStdInfo
.EndOfFile
.u
.LowPart
,
361 if (ModuleLoadBase
== NULL
)
363 CPRINT("Could not allocate memory for module");
365 return(STATUS_INSUFFICIENT_RESOURCES
);
369 /* Load driver into memory chunk */
370 Status
= NtReadFile(FileHandle
,
374 FileStdInfo
.EndOfFile
.u
.LowPart
,
376 if (!NT_SUCCESS(Status
))
378 CPRINT("Could not read module file into memory");
379 ExFreePool(ModuleLoadBase
);
387 Status
= LdrProcessModule(ModuleLoadBase
,
390 if (!NT_SUCCESS(Status
))
392 CPRINT("Could not process module\n");
393 ExFreePool(ModuleLoadBase
);
398 ExFreePool(ModuleLoadBase
);
400 *ModuleObject
= Module
;
402 /* Hook for KDB on loading a driver. */
403 KDB_LOADDRIVER_HOOK(Filename
, Module
);
405 return(STATUS_SUCCESS
);
410 LdrUnloadModule(PMODULE_OBJECT ModuleObject
)
414 /* Remove the module from the module list */
415 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
416 RemoveEntryList(&ModuleObject
->ListEntry
);
417 KeReleaseSpinLock(&ModuleListLock
, Irql
);
419 /* Hook for KDB on unloading a driver. */
420 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
422 /* Free text section */
423 if (ModuleObject
->TextSection
!= NULL
)
425 ExFreePool(ModuleObject
->TextSection
->Name
);
426 RemoveEntryList(&ModuleObject
->TextSection
->ListEntry
);
427 ExFreePool(ModuleObject
->TextSection
);
428 ModuleObject
->TextSection
= NULL
;
431 /* Free module section */
432 // MmFreeSection(ModuleObject->Base);
434 ExFreePool(ModuleObject
);
436 return(STATUS_SUCCESS
);
441 LdrProcessModule(PVOID ModuleLoadBase
,
442 PUNICODE_STRING ModuleName
,
443 PMODULE_OBJECT
*ModuleObject
)
445 PIMAGE_DOS_HEADER PEDosHeader
;
447 /* If MZ header exists */
448 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
449 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
451 return LdrPEProcessModule(ModuleLoadBase
,
456 CPRINT("Module wasn't PE\n");
457 return STATUS_UNSUCCESSFUL
;
462 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
466 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
468 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
478 LdrpQueryModuleInformation(PVOID Buffer
,
482 PLIST_ENTRY current_entry
;
483 PMODULE_OBJECT current
;
484 ULONG ModuleCount
= 0;
485 PSYSTEM_MODULE_INFORMATION Smi
;
486 ANSI_STRING AnsiName
;
490 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
492 /* calculate required size */
493 current_entry
= ModuleListHead
.Flink
;
494 while (current_entry
!= (&ModuleListHead
))
497 current_entry
= current_entry
->Flink
;
500 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
501 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
505 KeReleaseSpinLock(&ModuleListLock
, Irql
);
506 return(STATUS_INFO_LENGTH_MISMATCH
);
509 /* fill the buffer */
510 memset(Buffer
, '=', Size
);
512 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
513 Smi
->Count
= ModuleCount
;
516 current_entry
= ModuleListHead
.Flink
;
517 while (current_entry
!= (&ModuleListHead
))
519 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
521 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
522 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
523 Smi
->Module
[ModuleCount
].Base
= current
->Base
;
524 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
525 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
526 Smi
->Module
[ModuleCount
].Index
= (USHORT
)ModuleCount
;
527 Smi
->Module
[ModuleCount
].NameLength
= 0;
528 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
531 AnsiName
.MaximumLength
= 256;
532 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
533 RtlUnicodeStringToAnsiString(&AnsiName
,
537 p
= strrchr(AnsiName
.Buffer
, '\\');
540 Smi
->Module
[ModuleCount
].PathLength
= 0;
545 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
549 current_entry
= current_entry
->Flink
;
552 KeReleaseSpinLock(&ModuleListLock
, Irql
);
554 return(STATUS_SUCCESS
);
559 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
560 PUNICODE_STRING FullName
)
564 DPRINT("LdrpBuildModuleBaseName()\n");
565 DPRINT("FullName %wZ\n", FullName
);
567 p
= wcsrchr(FullName
->Buffer
, L
'\\');
570 p
= FullName
->Buffer
;
579 RtlCreateUnicodeString(BaseName
, p
);
584 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
585 IN PUNICODE_STRING String2
)
591 if (String1
&& String2
)
593 /* Search String1 for last path component */
594 len1
= String1
->Length
/ sizeof(WCHAR
);
595 s1
= String1
->Buffer
;
596 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
600 if (i
== String1
->Length
- sizeof(WCHAR
))
608 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
613 /* Search String2 for last path component */
614 len2
= String2
->Length
/ sizeof(WCHAR
);
615 s2
= String2
->Buffer
;
616 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
620 if (i
== String2
->Length
- sizeof(WCHAR
))
628 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
633 /* Compare last path components */
638 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
639 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
640 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
642 if (!c1
|| !c2
|| c1
!= c2
)
653 LdrGetModuleObject(PUNICODE_STRING ModuleName
)
655 PMODULE_OBJECT Module
;
659 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName
);
661 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
663 Entry
= ModuleListHead
.Flink
;
664 while (Entry
!= &ModuleListHead
)
666 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
668 DPRINT("Comparing %wZ and %wZ\n",
672 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
674 DPRINT("Module %wZ\n", &Module
->BaseName
);
675 KeReleaseSpinLock(&ModuleListLock
, Irql
);
679 Entry
= Entry
->Flink
;
682 KeReleaseSpinLock(&ModuleListLock
, Irql
);
684 DPRINT("Could not find module '%wZ'\n", ModuleName
);
690 /* ---------------------------------------------- PE Module support */
693 PageNeedsWriteAccess(PVOID PageStart
,
695 PIMAGE_FILE_HEADER PEFileHeader
,
696 PIMAGE_SECTION_HEADER PESectionHeaders
)
698 BOOL NeedsWriteAccess
;
700 ULONG Characteristics
;
704 NeedsWriteAccess
= FALSE
;
705 /* Set the protections for the various parts of the driver */
706 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& ! NeedsWriteAccess
; Idx
++)
708 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
709 if (!(Characteristics
& IMAGE_SECTION_CHAR_CODE
) ||
710 (Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
||
711 Characteristics
& IMAGE_SECTION_CHAR_DATA
||
712 Characteristics
& IMAGE_SECTION_CHAR_BSS
))
715 max(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
716 PESectionHeaders
[Idx
].SizeOfRawData
);
717 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
718 NeedsWriteAccess
= (char*)BaseAddress
< (char*)PageStart
+ PAGE_SIZE
&&
719 PageStart
< (PVOID
)((PCHAR
) BaseAddress
+ Length
);
723 return(NeedsWriteAccess
);
727 LdrPEProcessModule(PVOID ModuleLoadBase
,
728 PUNICODE_STRING FileName
,
729 PMODULE_OBJECT
*ModuleObject
)
731 unsigned int DriverSize
, Idx
;
732 ULONG RelocDelta
, NumRelocs
;
733 DWORD CurrentSize
, TotalRelocs
;
736 PIMAGE_DOS_HEADER PEDosHeader
;
737 PIMAGE_FILE_HEADER PEFileHeader
;
738 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
739 PIMAGE_SECTION_HEADER PESectionHeaders
;
740 PRELOCATION_DIRECTORY RelocDir
;
741 PRELOCATION_ENTRY RelocEntry
;
742 PMODULE_OBJECT LibraryModuleObject
;
743 PMODULE_OBJECT CreatedModuleObject
;
744 PVOID
*ImportAddressList
;
745 PULONG FunctionNameList
;
748 UNICODE_STRING ModuleName
;
749 UNICODE_STRING NameString
;
750 WCHAR NameBuffer
[PATH_MAX
];
751 MODULE_TEXT_SECTION
* ModuleTextSection
;
755 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
757 /* Get header pointers */
758 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
759 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
760 PEDosHeader
->e_lfanew
);
761 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
762 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
763 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
764 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
765 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
766 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
767 sizeof(IMAGE_OPTIONAL_HEADER
));
770 /* Check file magic numbers */
771 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
773 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
774 return STATUS_UNSUCCESSFUL
;
776 if (PEDosHeader
->e_lfanew
== 0)
778 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
779 return STATUS_UNSUCCESSFUL
;
781 if (*PEMagic
!= IMAGE_PE_MAGIC
)
783 CPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
784 return STATUS_UNSUCCESSFUL
;
786 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
788 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
789 return STATUS_UNSUCCESSFUL
;
793 /* FIXME: if image is fixed-address load, then fail */
795 /* FIXME: check/verify OS version number */
797 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
798 PEOptionalHeader
->Magic
,
799 PEOptionalHeader
->MajorLinkerVersion
,
800 PEOptionalHeader
->MinorLinkerVersion
);
801 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
804 /* Determine the size of the module */
805 DriverSize
= PEOptionalHeader
->SizeOfImage
;
806 DPRINT("DriverSize %x\n",DriverSize
);
808 /* Allocate a virtual section for the module */
809 DriverBase
= MmAllocateSection(DriverSize
);
812 CPRINT("Failed to allocate a virtual section for driver\n");
813 return STATUS_UNSUCCESSFUL
;
815 DbgPrint("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
817 /* Copy headers over */
818 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
820 /* Copy image sections into virtual section */
821 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
823 // Copy current section into current offset of virtual section
824 if (PESectionHeaders
[Idx
].Characteristics
&
825 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
827 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
828 PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
);
829 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
,
830 (PVOID
)((char*)ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
831 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
832 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
836 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
837 PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
);
838 memset(PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
,
839 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
842 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
843 PEOptionalHeader
->SectionAlignment
);
846 // CurrentBase = (PVOID)((DWORD)CurrentBase +
847 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
848 // PEOptionalHeader->SectionAlignment));
851 /* Perform relocation fixups */
852 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
853 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
854 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
855 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
857 PEOptionalHeader
->ImageBase
,
859 DPRINT("RelocDir %x\n",RelocDir
);
861 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
863 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
865 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
866 PESectionHeaders
[Idx
].Name
,
867 PESectionHeaders
[Idx
].PointerToRawData
);
868 RelocDir
= (PRELOCATION_DIRECTORY
)(PESectionHeaders
[Idx
].PointerToRawData
+
869 (char*)ModuleLoadBase
);
870 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
875 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
876 CurrentSize
= PEOptionalHeader
->DataDirectory
877 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
879 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
881 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
883 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
885 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
887 RelocDir->VirtualAddress,
889 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
890 sizeof(RELOCATION_DIRECTORY
));
891 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
897 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
898 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
899 RelocItem
= (PDWORD
)((char*)DriverBase
+ RelocDir
->VirtualAddress
+
901 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
904 Type ? "HIGHLOW" : "ABS",
906 (*RelocItem) + RelocDelta); */
909 (*RelocItem
) += RelocDelta
;
913 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
914 return STATUS_UNSUCCESSFUL
;
917 TotalRelocs
+= RelocDir
->SizeOfBlock
;
918 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
919 RelocDir
->SizeOfBlock
);
920 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
923 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
924 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
926 /* Perform import fixups */
927 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
929 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
931 /* Process each import module */
932 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
933 ((DWORD
)DriverBase
+ PEOptionalHeader
->
934 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
935 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
936 while (ImportModuleDirectory
->dwRVAModuleName
)
938 /* Check to make sure that import lib is kernel */
939 pName
= (PCHAR
) DriverBase
+
940 ImportModuleDirectory
->dwRVAModuleName
;
942 RtlCreateUnicodeStringFromAsciiz(&ModuleName
, pName
);
943 DPRINT("Import module: %wZ\n", &ModuleName
);
945 LibraryModuleObject
= LdrGetModuleObject(&ModuleName
);
946 if (LibraryModuleObject
== NULL
)
951 PathEnd
= wcsrchr(FileName
->Buffer
, L
'\\');
954 PathLength
= (PathEnd
- FileName
->Buffer
+ 1) * sizeof(WCHAR
);
960 NameBuffer
+ (PathLength
/ sizeof(WCHAR
)),
963 NameString
.Buffer
= NameBuffer
;
964 NameString
.MaximumLength
=
965 NameString
.Length
= PathLength
+ ModuleName
.Length
;
968 NameString
.MaximumLength
++;
969 NameBuffer
[NameString
.Length
/ sizeof(WCHAR
)] = 0;
971 Status
= LdrLoadModule(&NameString
, &LibraryModuleObject
);
975 DPRINT("Module '%wZ' not loaded yet\n", &ModuleName
);
976 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
977 wcscat(NameBuffer
, ModuleName
.Buffer
);
978 RtlInitUnicodeString(&NameString
, NameBuffer
);
979 Status
= LdrLoadModule(&NameString
, &LibraryModuleObject
);
981 if (!NT_SUCCESS(Status
))
983 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
984 wcscat(NameBuffer
, ModuleName
.Buffer
);
985 RtlInitUnicodeString(&NameString
, NameBuffer
);
986 Status
= LdrLoadModule(&NameString
, &LibraryModuleObject
);
987 if (!NT_SUCCESS(Status
))
989 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName
, Status
);
994 /* Get the import address list */
995 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
996 ImportModuleDirectory
->dwRVAFunctionAddressList
);
998 /* Get the list of functions to import */
999 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1001 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1002 ImportModuleDirectory
->dwRVAFunctionNameList
);
1006 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1007 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1009 /* Walk through function list and fixup addresses */
1010 while (*FunctionNameList
!= 0L)
1012 if ((*FunctionNameList
) & 0x80000000) // hint
1017 Hint
= (WORD
)((*FunctionNameList
) & 0xffff);
1021 pName
= (PCHAR
)((DWORD
)DriverBase
+
1022 *FunctionNameList
+ 2);
1023 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
1025 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
1027 /* Fixup the current import symbol */
1028 if (LibraryModuleObject
!= NULL
)
1030 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
1033 if (*ImportAddressList
== NULL
)
1035 return STATUS_PROCEDURE_NOT_FOUND
;
1040 CPRINT("Unresolved kernel symbol: %s\n", pName
);
1041 return STATUS_PROCEDURE_NOT_FOUND
;
1043 ImportAddressList
++;
1047 RtlFreeUnicodeString(&ModuleName
);
1049 ImportModuleDirectory
++;
1053 /* Set the protections for the various parts of the driver */
1054 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1056 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1060 if (Characteristics
& IMAGE_SECTION_CHAR_CODE
&&
1061 !(Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
||
1062 Characteristics
& IMAGE_SECTION_CHAR_DATA
||
1063 Characteristics
& IMAGE_SECTION_CHAR_BSS
))
1066 max(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1067 PESectionHeaders
[Idx
].SizeOfRawData
);
1068 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
1069 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1070 if (! PageNeedsWriteAccess(PageAddress
, DriverBase
, PEFileHeader
, PESectionHeaders
))
1072 MmSetPageProtect(NULL
, PageAddress
, PAGE_READONLY
);
1074 PageAddress
= (PVOID
)((PCHAR
) PageAddress
+ PAGE_SIZE
);
1075 while ((PVOID
)((PCHAR
) PageAddress
+ PAGE_SIZE
) <
1076 (PVOID
)((PCHAR
) BaseAddress
+ Length
))
1078 MmSetPageProtect(NULL
, PageAddress
, PAGE_READONLY
);
1079 PageAddress
= (PVOID
)((PCHAR
) PageAddress
+ PAGE_SIZE
);
1081 if (PageAddress
< (PVOID
)((PCHAR
) BaseAddress
+ Length
) &&
1082 ! PageNeedsWriteAccess(PageAddress
, DriverBase
, PEFileHeader
, PESectionHeaders
))
1084 MmSetPageProtect(NULL
, PageAddress
, PAGE_READONLY
);
1089 /* Create the module */
1090 CreatedModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
1091 if (CreatedModuleObject
== NULL
)
1093 return(STATUS_INSUFFICIENT_RESOURCES
);
1096 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
1098 /* Initialize ModuleObject data */
1099 CreatedModuleObject
->Base
= DriverBase
;
1100 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
1102 CreatedModuleObject
->FullName
.Length
= 0;
1103 CreatedModuleObject
->FullName
.MaximumLength
= FileName
->Length
+ sizeof(UNICODE_NULL
);
1104 CreatedModuleObject
->FullName
.Buffer
= ExAllocatePool(PagedPool
, CreatedModuleObject
->FullName
.MaximumLength
);
1105 RtlCopyUnicodeString(&CreatedModuleObject
->FullName
, FileName
);
1106 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
1107 &CreatedModuleObject
->FullName
);
1109 CreatedModuleObject
->EntryPoint
=
1110 (PVOID
)((DWORD
)DriverBase
+
1111 PEOptionalHeader
->AddressOfEntryPoint
);
1112 CreatedModuleObject
->Length
= DriverSize
;
1113 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
1115 CreatedModuleObject
->Image
.PE
.FileHeader
=
1116 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1118 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
1119 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
1120 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1121 sizeof(IMAGE_FILE_HEADER
));
1122 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
1123 CreatedModuleObject
->Image
.PE
.SectionList
=
1124 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1125 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
1126 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
1129 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
1130 InsertTailList(&ModuleListHead
,
1131 &CreatedModuleObject
->ListEntry
);
1132 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1135 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
1136 sizeof(MODULE_TEXT_SECTION
));
1137 assert(ModuleTextSection
);
1138 RtlZeroMemory(ModuleTextSection
, sizeof(MODULE_TEXT_SECTION
));
1139 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
1140 ModuleTextSection
->Length
= DriverSize
;
1141 ModuleTextSection
->Name
= ExAllocatePool(NonPagedPool
,
1142 (CreatedModuleObject
->BaseName
.Length
+ 1) * sizeof(WCHAR
));
1143 RtlCopyMemory(ModuleTextSection
->Name
,
1144 CreatedModuleObject
->BaseName
.Buffer
,
1145 CreatedModuleObject
->BaseName
.Length
);
1146 ModuleTextSection
->Name
[CreatedModuleObject
->BaseName
.Length
/ sizeof(WCHAR
)] = 0;
1147 ModuleTextSection
->OptionalHeader
=
1148 CreatedModuleObject
->Image
.PE
.OptionalHeader
;
1149 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
1151 CreatedModuleObject
->TextSection
= ModuleTextSection
;
1153 *ModuleObject
= CreatedModuleObject
;
1155 DPRINT("Loading Module %wZ...\n", FileName
);
1157 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_GDB
))
1159 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1160 FileName
, CreatedModuleObject
->Base
);
1163 return STATUS_SUCCESS
;
1168 LdrSafePEProcessModule(PVOID ModuleLoadBase
,
1170 PVOID ImportModuleBase
,
1174 ULONG RelocDelta
, NumRelocs
;
1175 ULONG CurrentSize
, TotalRelocs
;
1177 PIMAGE_DOS_HEADER PEDosHeader
;
1178 PIMAGE_FILE_HEADER PEFileHeader
;
1179 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1180 PIMAGE_SECTION_HEADER PESectionHeaders
;
1181 PRELOCATION_DIRECTORY RelocDir
;
1182 PRELOCATION_ENTRY RelocEntry
;
1183 PVOID
*ImportAddressList
;
1184 PULONG FunctionNameList
;
1188 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1190 /* Get header pointers */
1191 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1192 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1193 PEDosHeader
->e_lfanew
);
1194 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1195 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1196 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1197 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1198 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1199 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1200 sizeof(IMAGE_OPTIONAL_HEADER
));
1203 /* Check file magic numbers */
1204 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1208 if (PEDosHeader
->e_lfanew
== 0)
1212 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1216 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1221 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1222 PEOptionalHeader
->Magic
,
1223 PEOptionalHeader
->MajorLinkerVersion
,
1224 PEOptionalHeader
->MinorLinkerVersion
);
1225 ps("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1227 /* Determine the size of the module */
1228 *DriverSize
= PEOptionalHeader
->SizeOfImage
;
1229 ps("DriverSize %x\n",*DriverSize
);
1231 /* Copy headers over */
1232 if (DriverBase
!= ModuleLoadBase
)
1234 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1237 ps("Hdr: 0x%X\n", (ULONG
)PEOptionalHeader
);
1238 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG
)PEOptionalHeader
->SizeOfHeaders
);
1239 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG
)PEFileHeader
->NumberOfSections
);
1241 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1242 address as it is mapped */
1243 if (DriverBase
!= ModuleLoadBase
)
1247 /* Copy image sections into virtual section */
1248 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1250 PIMAGE_SECTION_HEADER Section
= &PESectionHeaders
[Idx
];
1251 // Copy current section into current offset of virtual section
1252 // if (PESectionHeaders[Idx].Characteristics &
1253 // (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1254 if (Section
->SizeOfRawData
)
1256 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1257 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1258 memcpy(Section
->VirtualAddress
+ (char*)DriverBase
,
1259 Section
->PointerToRawData
+ (char*)ModuleLoadBase
,
1260 Section
->SizeOfRawData
);
1262 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
)
1264 memset(Section
->VirtualAddress
+ Section
->SizeOfRawData
+ (char*)DriverBase
,
1266 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
1268 CurrentSize
+= ROUND_UP(Section
->Misc
.VirtualSize
,
1269 PEOptionalHeader
->SectionAlignment
);
1272 /* Perform relocation fixups */
1273 RelocDelta
= (ULONG
) DriverBase
- PEOptionalHeader
->ImageBase
;
1274 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1275 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1276 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1278 PEOptionalHeader
->ImageBase
,
1280 ps("RelocDir %x\n",RelocDir
);
1282 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1284 if (PESectionHeaders
[Idx
].VirtualAddress
== (ULONG
)RelocDir
)
1286 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1287 PESectionHeaders
[Idx
].Name
,
1288 PESectionHeaders
[Idx
].PointerToRawData
);
1289 RelocDir
= (PRELOCATION_DIRECTORY
)(PESectionHeaders
[Idx
].PointerToRawData
+ (char*)ModuleLoadBase
);
1290 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1295 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1298 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1300 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1302 RelocEntry
= (PRELOCATION_ENTRY
)((ULONG
)RelocDir
+
1303 sizeof(RELOCATION_DIRECTORY
));
1304 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1310 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1311 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1312 RelocItem
= (PULONG
)((char*)DriverBase
+ RelocDir
->VirtualAddress
+ Offset
);
1315 (*RelocItem
) += RelocDelta
;
1319 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1323 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1324 RelocDir
= (PRELOCATION_DIRECTORY
)((ULONG
)RelocDir
+
1325 RelocDir
->SizeOfBlock
);
1328 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1329 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1333 /* Perform import fixups */
1334 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1336 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1338 /* Process each import module */
1339 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1340 ((ULONG
)DriverBase
+ PEOptionalHeader
->
1341 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1343 ps("Processeing import directory at %p\n", ImportModuleDirectory
);
1345 /* Check to make sure that import lib is kernel */
1346 pName
= (PCHAR
)DriverBase
+ ImportModuleDirectory
->dwRVAModuleName
;
1348 ps("Import module: %s\n", pName
);
1350 /* Get the import address list */
1351 ImportAddressList
= (PVOID
*)((ULONG
)DriverBase
+
1352 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1354 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1355 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1356 ps(" ImportAddressList: 0x%X\n", ImportAddressList
);
1358 /* Get the list of functions to import */
1359 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1361 ps("Using function name list.\n");
1363 FunctionNameList
= (PULONG
)((ULONG
)DriverBase
+
1364 ImportModuleDirectory
->dwRVAFunctionNameList
);
1368 ps("Using function address list.\n");
1370 FunctionNameList
= (PULONG
)((ULONG
)DriverBase
+
1371 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1374 /* Walk through function list and fixup addresses */
1375 while (*FunctionNameList
!= 0L)
1377 if ((*FunctionNameList
) & 0x80000000)
1381 Hint
= (USHORT
)((*FunctionNameList
) & 0xffff);
1386 pName
= (PCHAR
)((ULONG
)DriverBase
+ *FunctionNameList
+ 2);
1387 Hint
= *(PWORD
)((ULONG
)DriverBase
+ *FunctionNameList
);
1389 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1391 *ImportAddressList
= LdrSafePEGetExportAddress(ImportModuleBase
,
1395 ImportAddressList
++;
1400 ps("Finished importing.\n");
1407 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
1411 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1412 ULONG ExportDirSize
;
1414 PVOID ExportAddress
;
1416 PDWORD FunctionList
, NameList
;
1417 PCHAR ModuleBase
= (PCHAR
)ModuleObject
->Base
;
1419 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1420 RtlImageDirectoryEntryToData(ModuleBase
,
1422 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1424 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir
, ExportDirSize
);
1425 if (ExportDir
== NULL
)
1430 FunctionList
= (PDWORD
)((char*)ModuleBase
+ (DWORD
)ExportDir
->AddressOfFunctions
);
1431 NameList
= (PDWORD
)((char*)ModuleBase
+ (DWORD
)ExportDir
->AddressOfNames
);
1432 OrdinalList
= (PWORD
) ((char*)ModuleBase
+ (DWORD
)ExportDir
->AddressOfNameOrdinals
);
1438 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
1441 DPRINT(" Name:%s NameList[%d]:%s\n",
1444 (DWORD
) ModuleBase
+ NameList
[Idx
]);
1447 if (!strcmp(Name
, ModuleBase
+ NameList
[Idx
]))
1449 ExportAddress
= (PVOID
) ((DWORD
)ModuleBase
+
1450 FunctionList
[OrdinalList
[Idx
]]);
1451 if (((ULONG
)ExportAddress
>= (ULONG
)ExportDir
) &&
1452 ((ULONG
)ExportAddress
< (ULONG
)ExportDir
+ ExportDirSize
))
1454 DPRINT("Forward: %s\n", (PCHAR
)ExportAddress
);
1455 ExportAddress
= LdrPEFixupForward((PCHAR
)ExportAddress
);
1456 DPRINT("ExportAddress: %p\n", ExportAddress
);
1465 ExportAddress
= (PVOID
) ((DWORD
)ModuleBase
+
1466 FunctionList
[Hint
- ExportDir
->Base
]);
1469 if (ExportAddress
== NULL
)
1471 DbgPrint("Export not found for %d:%s\n",
1473 Name
!= NULL
? Name
: "(Ordinal)");
1476 return(ExportAddress
);
1481 LdrSafePEGetExportAddress(PVOID ImportModuleBase
,
1486 PVOID ExportAddress
;
1488 PDWORD FunctionList
, NameList
;
1489 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1490 ULONG ExportDirSize
;
1492 static BOOLEAN EP
= FALSE
;
1494 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1495 RtlImageDirectoryEntryToData(ImportModuleBase
,
1497 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1502 ps("ExportDir %x\n", ExportDir
);
1505 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ (char*)ImportModuleBase
);
1506 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ (char*)ImportModuleBase
);
1507 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ (char*)ImportModuleBase
);
1513 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
1515 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ImportModuleBase
+ NameList
[Idx
])))
1517 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
1518 FunctionList
[OrdinalList
[Idx
]]);
1525 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
1527 FunctionList
[Hint
- ExportDir
->Base
]);
1530 if (ExportAddress
== 0)
1532 ps("Export not found for %d:%s\n",
1534 Name
!= NULL
? Name
: "(Ordinal)");
1537 return ExportAddress
;
1542 LdrPEFixupForward(PCHAR ForwardName
)
1544 CHAR NameBuffer
[128];
1545 UNICODE_STRING ModuleName
;
1547 PMODULE_OBJECT ModuleObject
;
1549 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1551 strcpy(NameBuffer
, ForwardName
);
1552 p
= strchr(NameBuffer
, '.');
1560 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1562 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1564 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1565 RtlFreeUnicodeString(&ModuleName
);
1567 DPRINT("ModuleObject: %p\n", ModuleObject
);
1569 if (ModuleObject
== NULL
)
1571 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1575 return(LdrPEGetExportAddress(ModuleObject
, p
+1, 0));