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
8 * PROGRAMMERS: Jean Michault
9 * Rex Jolliff (rex@lvcablemodem.com)
10 * Jason Filby (jasonfilby@yahoo.com)
11 * Casper S. Hornstrup (chorns@users.sourceforge.net)
15 /* INCLUDES *****************************************************************/
20 #include <internal/ntosdbg.h>
30 #include <internal/debug.h>
32 /* GLOBALS *******************************************************************/
34 LIST_ENTRY ModuleListHead
;
35 KSPIN_LOCK ModuleListLock
;
36 MODULE_OBJECT NtoskrnlModuleObject
;
37 MODULE_OBJECT HalModuleObject
;
39 LIST_ENTRY ModuleTextListHead
;
40 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
41 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
44 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
47 #define HIWORD(X) ((WORD) (((DWORD) (X) >> 16) & 0xFFFF))
50 #define LOWORD(X) ((WORD) (X))
53 /* FORWARD DECLARATIONS ******************************************************/
56 LdrProcessModule(PVOID ModuleLoadBase
,
57 PUNICODE_STRING ModuleName
,
58 PMODULE_OBJECT
*ModuleObject
);
61 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
62 PUNICODE_STRING FullName
);
65 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
66 IN PUNICODE_STRING String2
);
69 /* PE Driver load support */
70 static NTSTATUS
LdrPEProcessModule(PVOID ModuleLoadBase
,
71 PUNICODE_STRING FileName
,
72 PMODULE_OBJECT
*ModuleObject
);
74 LdrPEGetExportByName(PVOID BaseAddress
,
79 LdrPEFixupForward(PCHAR ForwardName
);
82 LdrPEPerformRelocations(PVOID DriverBase
,
86 LdrPEFixupImports(PMODULE_OBJECT Module
);
88 /* FUNCTIONS *****************************************************************/
91 LdrInitDebug(PLOADER_MODULE Module
, PWCH Name
)
93 PLIST_ENTRY current_entry
;
94 MODULE_TEXT_SECTION
* current
;
96 current_entry
= ModuleTextListHead
.Flink
;
97 while (current_entry
!= &ModuleTextListHead
)
100 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
101 if (wcscmp(current
->Name
, Name
) == 0)
105 current_entry
= current_entry
->Flink
;
108 if (current_entry
== &ModuleTextListHead
)
117 PIMAGE_NT_HEADERS NtHeader
;
118 PIMAGE_SECTION_HEADER SectionList
;
120 InitializeListHead(&ModuleTextListHead
);
122 /* Setup ntoskrnl.exe text section */
124 * This isn't the base of the text segment, but the start of the
125 * full image (in memory)
126 * Also, the Length field isn't set to the length of the segment,
127 * but is more like the offset, from the image base, to the end
130 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
131 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
132 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
133 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
134 SectionList
[0].VirtualAddress
;
135 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
136 NtoskrnlTextSection
.OptionalHeader
= OPTHDROFFSET(KERNEL_BASE
);
137 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
139 /* Setup hal.dll text section */
140 /* Same comment as above applies */
141 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
142 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
143 LdrHalTextSection
.Base
= LdrHalBase
;
144 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
145 SectionList
[0].VirtualAddress
;
146 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
147 LdrHalTextSection
.OptionalHeader
= OPTHDROFFSET(LdrHalBase
);
148 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
150 /* Hook for KDB on initialization of the loader. */
151 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection
, &LdrHalTextSection
);
155 LdrInitModuleManagement(VOID
)
157 PIMAGE_NT_HEADERS NtHeader
;
159 /* Initialize the module list and spinlock */
160 InitializeListHead(&ModuleListHead
);
161 KeInitializeSpinLock(&ModuleListLock
);
163 /* Initialize ModuleObject for NTOSKRNL */
164 RtlZeroMemory(&NtoskrnlModuleObject
, sizeof(MODULE_OBJECT
));
165 NtoskrnlModuleObject
.Base
= (PVOID
) KERNEL_BASE
;
166 NtoskrnlModuleObject
.Flags
= MODULE_FLAG_PE
;
167 RtlInitUnicodeString(&NtoskrnlModuleObject
.FullName
, KERNEL_MODULE_NAME
);
168 LdrpBuildModuleBaseName(&NtoskrnlModuleObject
.BaseName
, &NtoskrnlModuleObject
.FullName
);
170 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
171 NtoskrnlModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
172 NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
173 NtoskrnlModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
174 NtoskrnlModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) NtoskrnlModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
175 DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject
, NtoskrnlModuleObject
.EntryPoint
);
176 NtoskrnlModuleObject
.Length
= NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
177 NtoskrnlModuleObject
.TextSection
= &NtoskrnlTextSection
;
179 InsertTailList(&ModuleListHead
,
180 &NtoskrnlModuleObject
.ListEntry
);
182 /* Initialize ModuleObject for HAL */
183 RtlZeroMemory(&HalModuleObject
, sizeof(MODULE_OBJECT
));
184 HalModuleObject
.Base
= (PVOID
) LdrHalBase
;
185 HalModuleObject
.Flags
= MODULE_FLAG_PE
;
187 RtlInitUnicodeString(&HalModuleObject
.FullName
, HAL_MODULE_NAME
);
188 LdrpBuildModuleBaseName(&HalModuleObject
.BaseName
, &HalModuleObject
.FullName
);
190 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
191 HalModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
192 HalModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
193 HalModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
194 HalModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) HalModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
195 DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject
, HalModuleObject
.EntryPoint
);
196 HalModuleObject
.Length
= HalModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
197 HalModuleObject
.TextSection
= &LdrHalTextSection
;
199 InsertTailList(&ModuleListHead
,
200 &HalModuleObject
.ListEntry
);
204 LdrpLoadImage(PUNICODE_STRING DriverName
,
206 PVOID
*SectionPointer
,
208 PVOID
*ExportSectionPointer
)
210 PMODULE_OBJECT ModuleObject
;
213 ModuleObject
= LdrGetModuleObject(DriverName
);
214 if (ModuleObject
== NULL
)
216 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
217 if (!NT_SUCCESS(Status
))
224 *ModuleBase
= ModuleObject
->Base
;
226 // if (SectionPointer)
227 // *SectionPointer = ModuleObject->
230 *EntryPoint
= ModuleObject
->EntryPoint
;
232 // if (ExportSectionPointer)
233 // *ExportSectionPointer = ModuleObject->
235 return(STATUS_SUCCESS
);
240 LdrpUnloadImage(PVOID ModuleBase
)
242 return(STATUS_NOT_IMPLEMENTED
);
247 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName
)
249 PDRIVER_INITIALIZE DriverEntry
;
250 PMODULE_OBJECT ModuleObject
;
253 ModuleObject
= LdrGetModuleObject(ModuleName
);
254 if (ModuleObject
!= NULL
)
256 return(STATUS_IMAGE_ALREADY_LOADED
);
259 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
260 if (!NT_SUCCESS(Status
))
265 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
267 Status
= DriverEntry(NULL
, NULL
);
268 if (!NT_SUCCESS(Status
))
270 LdrUnloadModule(ModuleObject
);
278 LdrLoadModule(PUNICODE_STRING Filename
,
279 PMODULE_OBJECT
*ModuleObject
)
281 PVOID ModuleLoadBase
;
284 OBJECT_ATTRIBUTES ObjectAttributes
;
285 PMODULE_OBJECT Module
;
286 FILE_STANDARD_INFORMATION FileStdInfo
;
287 IO_STATUS_BLOCK IoStatusBlock
;
289 *ModuleObject
= NULL
;
291 DPRINT("Loading Module %wZ...\n", Filename
);
293 /* Open the Module */
294 InitializeObjectAttributes(&ObjectAttributes
,
296 OBJ_CASE_INSENSITIVE
,
300 Status
= ZwOpenFile(&FileHandle
,
305 FILE_SYNCHRONOUS_IO_NONALERT
);
307 if (!NT_SUCCESS(Status
))
309 CPRINT("Could not open module file: %wZ\n", Filename
);
314 /* Get the size of the file */
315 Status
= ZwQueryInformationFile(FileHandle
,
319 FileStandardInformation
);
320 if (!NT_SUCCESS(Status
))
322 CPRINT("Could not get file size\n");
328 /* Allocate nonpageable memory for driver */
329 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
330 FileStdInfo
.EndOfFile
.u
.LowPart
,
332 if (ModuleLoadBase
== NULL
)
334 CPRINT("Could not allocate memory for module");
336 return(STATUS_INSUFFICIENT_RESOURCES
);
340 /* Load driver into memory chunk */
341 Status
= ZwReadFile(FileHandle
,
345 FileStdInfo
.EndOfFile
.u
.LowPart
,
347 if (!NT_SUCCESS(Status
))
349 CPRINT("Could not read module file into memory");
350 ExFreePool(ModuleLoadBase
);
358 Status
= LdrProcessModule(ModuleLoadBase
,
361 if (!NT_SUCCESS(Status
))
363 CPRINT("Could not process module\n");
364 ExFreePool(ModuleLoadBase
);
369 ExFreePool(ModuleLoadBase
);
371 *ModuleObject
= Module
;
373 /* Hook for KDB on loading a driver. */
374 KDB_LOADDRIVER_HOOK(Filename
, Module
);
376 return(STATUS_SUCCESS
);
381 LdrUnloadModule(PMODULE_OBJECT ModuleObject
)
385 /* Remove the module from the module list */
386 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
387 RemoveEntryList(&ModuleObject
->ListEntry
);
388 KeReleaseSpinLock(&ModuleListLock
, Irql
);
390 /* Hook for KDB on unloading a driver. */
391 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
393 /* Free text section */
394 if (ModuleObject
->TextSection
!= NULL
)
396 ExFreePool(ModuleObject
->TextSection
->Name
);
397 RemoveEntryList(&ModuleObject
->TextSection
->ListEntry
);
398 ExFreePool(ModuleObject
->TextSection
);
399 ModuleObject
->TextSection
= NULL
;
402 /* Free module section */
403 // MmFreeSection(ModuleObject->Base);
405 ExFreePool(ModuleObject
->FullName
.Buffer
);
406 ExFreePool(ModuleObject
);
408 return(STATUS_SUCCESS
);
413 LdrProcessModule(PVOID ModuleLoadBase
,
414 PUNICODE_STRING ModuleName
,
415 PMODULE_OBJECT
*ModuleObject
)
417 PIMAGE_DOS_HEADER PEDosHeader
;
419 /* If MZ header exists */
420 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
421 if (PEDosHeader
->e_magic
== IMAGE_DOS_SIGNATURE
&& PEDosHeader
->e_lfanew
!= 0L)
423 return LdrPEProcessModule(ModuleLoadBase
,
428 CPRINT("Module wasn't PE\n");
429 return STATUS_UNSUCCESSFUL
;
433 LdrpQueryModuleInformation(PVOID Buffer
,
437 PLIST_ENTRY current_entry
;
438 PMODULE_OBJECT current
;
439 ULONG ModuleCount
= 0;
440 PSYSTEM_MODULE_INFORMATION Smi
;
441 ANSI_STRING AnsiName
;
445 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
447 /* calculate required size */
448 current_entry
= ModuleListHead
.Flink
;
449 while (current_entry
!= (&ModuleListHead
))
452 current_entry
= current_entry
->Flink
;
455 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
456 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
460 KeReleaseSpinLock(&ModuleListLock
, Irql
);
461 return(STATUS_INFO_LENGTH_MISMATCH
);
464 /* fill the buffer */
465 memset(Buffer
, '=', Size
);
467 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
468 Smi
->Count
= ModuleCount
;
471 current_entry
= ModuleListHead
.Flink
;
472 while (current_entry
!= (&ModuleListHead
))
474 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
476 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
477 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
478 Smi
->Module
[ModuleCount
].Base
= current
->Base
;
479 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
480 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
481 Smi
->Module
[ModuleCount
].Index
= (USHORT
)ModuleCount
;
482 Smi
->Module
[ModuleCount
].NameLength
= 0;
483 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
486 AnsiName
.MaximumLength
= 256;
487 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
488 RtlUnicodeStringToAnsiString(&AnsiName
,
492 p
= strrchr(AnsiName
.Buffer
, '\\');
495 Smi
->Module
[ModuleCount
].PathLength
= 0;
500 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
504 current_entry
= current_entry
->Flink
;
507 KeReleaseSpinLock(&ModuleListLock
, Irql
);
509 return(STATUS_SUCCESS
);
514 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
515 PUNICODE_STRING FullName
)
519 DPRINT("LdrpBuildModuleBaseName()\n");
520 DPRINT("FullName %wZ\n", FullName
);
522 p
= wcsrchr(FullName
->Buffer
, L
'\\');
525 p
= FullName
->Buffer
;
534 RtlInitUnicodeString(BaseName
, p
);
539 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
540 IN PUNICODE_STRING String2
)
546 if (String1
&& String2
)
548 /* Search String1 for last path component */
549 len1
= String1
->Length
/ sizeof(WCHAR
);
550 s1
= String1
->Buffer
;
551 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
555 if (i
== String1
->Length
- sizeof(WCHAR
))
563 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
568 /* Search String2 for last path component */
569 len2
= String2
->Length
/ sizeof(WCHAR
);
570 s2
= String2
->Buffer
;
571 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
575 if (i
== String2
->Length
- sizeof(WCHAR
))
583 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
588 /* Compare last path components */
593 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
594 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
595 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
597 if (!c1
|| !c2
|| c1
!= c2
)
607 LdrGetModuleObject(PUNICODE_STRING ModuleName
)
609 PMODULE_OBJECT Module
;
613 DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName
);
615 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
617 Entry
= ModuleListHead
.Flink
;
618 while (Entry
!= &ModuleListHead
)
620 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
622 DPRINT("Comparing %wZ and %wZ\n",
626 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
628 DPRINT("Module %wZ\n", &Module
->BaseName
);
629 KeReleaseSpinLock(&ModuleListLock
, Irql
);
633 Entry
= Entry
->Flink
;
636 KeReleaseSpinLock(&ModuleListLock
, Irql
);
638 DPRINT("Could not find module '%wZ'\n", ModuleName
);
644 /* ---------------------------------------------- PE Module support */
647 LdrLookupPageProtection(PVOID PageStart
,
649 PIMAGE_FILE_HEADER PEFileHeader
,
650 PIMAGE_SECTION_HEADER PESectionHeaders
)
652 BOOLEAN Write
= FALSE
;
653 BOOLEAN Execute
= FALSE
;
654 ULONG Characteristics
;
659 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& (!Write
|| !Execute
); Idx
++)
661 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
662 if (!(Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
664 Length
= max(PESectionHeaders
[Idx
].Misc
.VirtualSize
, PESectionHeaders
[Idx
].SizeOfRawData
);
665 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
666 if (BaseAddress
< (PVOID
)((ULONG_PTR
)PageStart
+ PAGE_SIZE
) &&
667 PageStart
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
))
669 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
673 if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
680 if (Write
&& Execute
)
682 return PAGE_EXECUTE_READWRITE
;
686 return PAGE_EXECUTE_READ
;
690 return PAGE_READWRITE
;
694 return PAGE_READONLY
;
699 LdrPEProcessModule(PVOID ModuleLoadBase
,
700 PUNICODE_STRING FileName
,
701 PMODULE_OBJECT
*ModuleObject
)
703 unsigned int DriverSize
, Idx
;
706 PIMAGE_DOS_HEADER PEDosHeader
;
707 PIMAGE_NT_HEADERS PENtHeaders
;
708 PIMAGE_SECTION_HEADER PESectionHeaders
;
709 PMODULE_OBJECT CreatedModuleObject
;
710 MODULE_TEXT_SECTION
* ModuleTextSection
;
714 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
716 /* Get header pointers */
717 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
718 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
719 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
722 /* Check file magic numbers */
723 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
725 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
726 return STATUS_UNSUCCESSFUL
;
728 if (PEDosHeader
->e_lfanew
== 0)
730 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
731 return STATUS_UNSUCCESSFUL
;
733 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
735 CPRINT("Incorrect PE magic: %08x\n", PENtHeaders
->Signature
);
736 return STATUS_UNSUCCESSFUL
;
738 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
740 CPRINT("Incorrect Architechture: %04x\n", PENtHeaders
->FileHeader
.Machine
);
741 return STATUS_UNSUCCESSFUL
;
745 /* FIXME: if image is fixed-address load, then fail */
747 /* FIXME: check/verify OS version number */
749 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
750 PENtHeaders
->OptionalHeader
.Magic
,
751 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
752 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
753 DPRINT("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
755 /* Determine the size of the module */
757 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
759 if (!(PESectionHeaders
[Idx
].Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
761 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
762 DriverSize
= max(DriverSize
, CurrentSize
);
765 DriverSize
= ROUND_UP(DriverSize
, PENtHeaders
->OptionalHeader
.SectionAlignment
);
766 DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize
, PENtHeaders
->OptionalHeader
.SizeOfImage
);
768 /* Allocate a virtual section for the module */
770 DriverBase
= MmAllocateSection(DriverSize
, DriverBase
);
773 CPRINT("Failed to allocate a virtual section for driver\n");
774 return STATUS_UNSUCCESSFUL
;
776 DbgPrint("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
778 /* Copy headers over */
779 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
781 /* Copy image sections into virtual section */
782 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
784 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
785 /* Copy current section into current offset of virtual section */
786 if (CurrentSize
<= DriverSize
&&
787 PESectionHeaders
[Idx
].SizeOfRawData
)
789 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
790 PESectionHeaders
[Idx
].VirtualAddress
+ (ULONG_PTR
)DriverBase
);
791 memcpy((PVOID
)((ULONG_PTR
)DriverBase
+ PESectionHeaders
[Idx
].VirtualAddress
),
792 (PVOID
)((ULONG_PTR
)ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
793 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
794 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
798 /* Perform relocation fixups */
799 Status
= LdrPEPerformRelocations(DriverBase
, DriverSize
);
800 if (!NT_SUCCESS(Status
))
802 // MmFreeSection(DriverBase);
806 /* Create the module */
807 CreatedModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
808 if (CreatedModuleObject
== NULL
)
810 // MmFreeSection(DriverBase);
811 return STATUS_INSUFFICIENT_RESOURCES
;
814 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
816 /* Initialize ModuleObject data */
817 CreatedModuleObject
->Base
= DriverBase
;
818 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
820 CreatedModuleObject
->FullName
.Length
= 0;
821 CreatedModuleObject
->FullName
.MaximumLength
= FileName
->Length
+ sizeof(UNICODE_NULL
);
822 CreatedModuleObject
->FullName
.Buffer
= ExAllocatePool(PagedPool
, CreatedModuleObject
->FullName
.MaximumLength
);
823 if (CreatedModuleObject
->FullName
.Buffer
== NULL
)
825 ExFreePool(CreatedModuleObject
);
826 // MmFreeSection(DriverBase);
827 return STATUS_INSUFFICIENT_RESOURCES
;
830 RtlCopyUnicodeString(&CreatedModuleObject
->FullName
, FileName
);
831 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
832 &CreatedModuleObject
->FullName
);
834 CreatedModuleObject
->EntryPoint
=
835 (PVOID
)((ULONG_PTR
)DriverBase
+
836 PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
837 CreatedModuleObject
->Length
= DriverSize
;
838 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
840 CreatedModuleObject
->Image
.PE
.FileHeader
=
841 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
843 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
844 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
845 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
846 sizeof(IMAGE_FILE_HEADER
));
847 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
848 CreatedModuleObject
->Image
.PE
.SectionList
=
849 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
850 sizeof(IMAGE_FILE_HEADER
) + CreatedModuleObject
->Image
.PE
.FileHeader
->SizeOfOptionalHeader
);
851 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
853 /* Perform import fixups */
854 Status
= LdrPEFixupImports(CreatedModuleObject
);
855 if (!NT_SUCCESS(Status
))
857 // MmFreeSection(DriverBase);
858 ExFreePool(CreatedModuleObject
->FullName
.Buffer
);
859 ExFreePool(CreatedModuleObject
);
863 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
864 /* Set the protections for the various parts of the driver */
865 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
867 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
872 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
873 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
874 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
876 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
880 * This driver modifies a string in the first page of the text section while initialising.
882 if (0 == _wcsicmp(L
"fireport.sys", FileName
->Buffer
))
884 Protect
= PAGE_EXECUTE_READWRITE
;
887 if (PageAddress
< DriverBase
+ DriverSize
)
889 MmSetPageProtect(NULL
, PageAddress
, Protect
);
892 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
894 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
896 Protect
= PAGE_EXECUTE_READWRITE
;
900 Protect
= PAGE_EXECUTE_READ
;
903 else if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
905 Protect
= PAGE_READWRITE
;
909 Protect
= PAGE_READONLY
;
911 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
912 while ((ULONG_PTR
)PageAddress
+ PAGE_SIZE
< (ULONG_PTR
)BaseAddress
+ Length
)
914 if (PageAddress
< DriverBase
+ DriverSize
)
916 MmSetPageProtect(NULL
, PageAddress
, Protect
);
918 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
920 if (PageAddress
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
) &&
921 PageAddress
< DriverBase
+ DriverSize
)
923 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
924 MmSetPageProtect(NULL
, PageAddress
, Protect
);
929 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
930 InsertTailList(&ModuleListHead
,
931 &CreatedModuleObject
->ListEntry
);
932 KeReleaseSpinLock(&ModuleListLock
, Irql
);
935 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
936 sizeof(MODULE_TEXT_SECTION
));
937 ASSERT(ModuleTextSection
);
938 RtlZeroMemory(ModuleTextSection
, sizeof(MODULE_TEXT_SECTION
));
939 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
940 ModuleTextSection
->Length
= DriverSize
;
941 ModuleTextSection
->Name
= ExAllocatePool(NonPagedPool
,
942 (CreatedModuleObject
->BaseName
.Length
+ 1) * sizeof(WCHAR
));
943 RtlCopyMemory(ModuleTextSection
->Name
,
944 CreatedModuleObject
->BaseName
.Buffer
,
945 CreatedModuleObject
->BaseName
.Length
);
946 ModuleTextSection
->Name
[CreatedModuleObject
->BaseName
.Length
/ sizeof(WCHAR
)] = 0;
947 ModuleTextSection
->OptionalHeader
=
948 CreatedModuleObject
->Image
.PE
.OptionalHeader
;
949 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
951 CreatedModuleObject
->TextSection
= ModuleTextSection
;
953 *ModuleObject
= CreatedModuleObject
;
955 DPRINT("Loading Module %wZ...\n", FileName
);
957 if (KdDebuggerEnabled
&& (KdDebugState
& KD_DEBUG_GDB
))
959 DPRINT("Module %wZ loaded at 0x%.08x.\n",
960 FileName
, CreatedModuleObject
->Base
);
963 return STATUS_SUCCESS
;
968 LdrSafePEProcessModule(PVOID ModuleLoadBase
,
970 PVOID ImportModuleBase
,
975 PIMAGE_DOS_HEADER PEDosHeader
;
976 PIMAGE_NT_HEADERS PENtHeaders
;
977 PIMAGE_SECTION_HEADER PESectionHeaders
;
980 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
982 /* Get header pointers */
983 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
984 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
985 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
988 /* Check file magic numbers */
989 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
993 if (PEDosHeader
->e_lfanew
== 0)
997 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
1001 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
1006 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1007 PENtHeaders
->OptionalHeader
.Magic
,
1008 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
1009 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
1010 ps("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1012 /* Determine the size of the module */
1013 *DriverSize
= PENtHeaders
->OptionalHeader
.SizeOfImage
;
1014 ps("DriverSize %x\n",*DriverSize
);
1016 /* Copy headers over */
1017 if (DriverBase
!= ModuleLoadBase
)
1019 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1022 ps("Hdr: 0x%X\n", PENtHeaders
);
1023 ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1024 ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders
->FileHeader
.NumberOfSections
);
1026 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1027 address as it is mapped */
1028 if (DriverBase
!= ModuleLoadBase
)
1032 /* Copy image sections into virtual section */
1033 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1035 PIMAGE_SECTION_HEADER Section
= &PESectionHeaders
[Idx
];
1036 // Copy current section into current offset of virtual section
1037 if (Section
->SizeOfRawData
)
1039 // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1040 // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1041 memcpy(Section
->VirtualAddress
+ (char*)DriverBase
,
1042 Section
->PointerToRawData
+ (char*)ModuleLoadBase
,
1043 Section
->Misc
.VirtualSize
> Section
->SizeOfRawData
? Section
->SizeOfRawData
: Section
->Misc
.VirtualSize
);
1045 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
)
1047 memset(Section
->VirtualAddress
+ Section
->SizeOfRawData
+ (char*)DriverBase
,
1049 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
1051 CurrentSize
+= ROUND_UP(Section
->Misc
.VirtualSize
,
1052 PENtHeaders
->OptionalHeader
.SectionAlignment
);
1055 /* Perform relocation fixups */
1056 Status
= LdrPEPerformRelocations(DriverBase
, *DriverSize
);
1057 if (!NT_SUCCESS(Status
))
1063 /* Perform import fixups */
1064 Status
= LdrPEFixupImports(DriverBase
== ModuleLoadBase
? &NtoskrnlModuleObject
: &HalModuleObject
);
1065 if (!NT_SUCCESS(Status
))
1070 /* Set the page protection for the virtual sections */
1071 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
1072 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1074 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1079 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1080 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
1081 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1083 if (Characteristics
& IMAGE_SCN_MEM_EXECUTE
)
1085 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1087 Protect
= PAGE_EXECUTE_READWRITE
;
1091 Protect
= PAGE_EXECUTE_READ
;
1094 else if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1096 Protect
= PAGE_READWRITE
;
1100 Protect
= PAGE_READONLY
;
1102 while ((ULONG_PTR
)PageAddress
< (ULONG_PTR
)BaseAddress
+ Length
)
1104 MmSetPageProtect(NULL
, PageAddress
, Protect
);
1105 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
1107 if (DriverBase
== ModuleLoadBase
&&
1108 Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
1110 /* For ntoskrnl, we must stop after the bss section */
1120 LdrPEFixupForward(PCHAR ForwardName
)
1122 CHAR NameBuffer
[128];
1123 UNICODE_STRING ModuleName
;
1125 PMODULE_OBJECT ModuleObject
;
1127 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1129 strcpy(NameBuffer
, ForwardName
);
1130 p
= strchr(NameBuffer
, '.');
1138 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1140 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1142 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1143 RtlFreeUnicodeString(&ModuleName
);
1145 DPRINT("ModuleObject: %p\n", ModuleObject
);
1147 if (ModuleObject
== NULL
)
1149 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1152 return LdrPEGetExportByName(ModuleObject
->Base
, (PUCHAR
)(p
+1), 0xffff);
1156 LdrPEPerformRelocations(PVOID DriverBase
,
1159 PIMAGE_NT_HEADERS NtHeaders
;
1160 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1161 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1163 PVOID Address
, MaxAddress
;
1171 NtHeaders
= RtlImageNtHeader(DriverBase
);
1173 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1175 return STATUS_UNSUCCESSFUL
;
1178 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1180 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1182 return STATUS_SUCCESS
;
1185 Delta
= (ULONG_PTR
)DriverBase
- NtHeaders
->OptionalHeader
.ImageBase
;
1186 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)DriverBase
+ RelocationDDir
->VirtualAddress
);
1187 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
1188 MaxAddress
= DriverBase
+ DriverSize
;
1190 while (RelocationDir
< RelocationEnd
&&
1191 RelocationDir
->SizeOfBlock
> 0)
1193 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
1194 Address
= DriverBase
+ RelocationDir
->VirtualAddress
;
1195 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1197 for (i
= 0; i
< Count
; i
++)
1199 Offset
= *TypeOffset
& 0xFFF;
1200 Type
= *TypeOffset
>> 12;
1201 ShortPtr
= (PUSHORT
)(Address
+ Offset
);
1203 /* Don't relocate after the end of the loaded driver */
1204 if ((PVOID
)ShortPtr
>= MaxAddress
)
1210 * Don't relocate within the relocation section itself.
1211 * GCC/LD generates sometimes relocation records for the relecotion section.
1212 * This is a bug in GCC/LD.
1214 if ((ULONG_PTR
)ShortPtr
< (ULONG_PTR
)RelocationDir
||
1215 (ULONG_PTR
)ShortPtr
>= (ULONG_PTR
)RelocationEnd
)
1219 case IMAGE_REL_BASED_ABSOLUTE
:
1222 case IMAGE_REL_BASED_HIGH
:
1223 *ShortPtr
+= HIWORD(Delta
);
1226 case IMAGE_REL_BASED_LOW
:
1227 *ShortPtr
+= LOWORD(Delta
);
1230 case IMAGE_REL_BASED_HIGHLOW
:
1231 LongPtr
= (PULONG
)ShortPtr
;
1235 case IMAGE_REL_BASED_HIGHADJ
:
1236 case IMAGE_REL_BASED_MIPS_JMPADDR
:
1238 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
1239 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, *TypeOffset
);
1240 return STATUS_UNSUCCESSFUL
;
1245 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
1248 return STATUS_SUCCESS
;
1252 LdrPEGetOrLoadModule(PMODULE_OBJECT Module
,
1254 PMODULE_OBJECT
* ImportedModule
)
1256 UNICODE_STRING DriverName
;
1257 UNICODE_STRING NameString
;
1258 WCHAR NameBuffer
[PATH_MAX
];
1259 NTSTATUS Status
= STATUS_SUCCESS
;
1261 if (0 == _stricmp(ImportedName
, "ntoskrnl") ||
1262 0 == _stricmp(ImportedName
, "ntoskrnl.exe"))
1264 *ImportedModule
= &NtoskrnlModuleObject
;
1265 return STATUS_SUCCESS
;
1268 if (0 == _stricmp(ImportedName
, "hal") ||
1269 0 == _stricmp(ImportedName
, "hal.dll"))
1271 *ImportedModule
= &HalModuleObject
;
1272 return STATUS_SUCCESS
;
1275 RtlCreateUnicodeStringFromAsciiz (&DriverName
, ImportedName
);
1276 DPRINT("Import module: %wZ\n", &DriverName
);
1278 *ImportedModule
= LdrGetModuleObject(&DriverName
);
1279 if (*ImportedModule
== NULL
)
1284 PathEnd
= wcsrchr(Module
->FullName
.Buffer
, L
'\\');
1285 if (NULL
!= PathEnd
)
1287 PathLength
= (PathEnd
- Module
->FullName
.Buffer
+ 1) * sizeof(WCHAR
);
1288 RtlCopyMemory(NameBuffer
, Module
->FullName
.Buffer
, PathLength
);
1289 RtlCopyMemory(NameBuffer
+ (PathLength
/ sizeof(WCHAR
)), DriverName
.Buffer
, DriverName
.Length
);
1290 NameString
.Buffer
= NameBuffer
;
1291 NameString
.MaximumLength
= NameString
.Length
= PathLength
+ DriverName
.Length
;
1293 /* NULL-terminate */
1294 NameString
.MaximumLength
++;
1295 NameBuffer
[NameString
.Length
/ sizeof(WCHAR
)] = 0;
1297 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1301 DPRINT("Module '%wZ' not loaded yet\n", &DriverName
);
1302 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
1303 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1304 RtlInitUnicodeString(&NameString
, NameBuffer
);
1305 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1307 if (!NT_SUCCESS(Status
))
1309 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
1310 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1311 RtlInitUnicodeString(&NameString
, NameBuffer
);
1312 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1313 if (!NT_SUCCESS(Status
))
1315 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName
, Status
);
1319 RtlFreeUnicodeString(&DriverName
);
1324 LdrPEGetExportByName(PVOID BaseAddress
,
1328 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1329 PDWORD
* ExFunctions
;
1331 USHORT
* ExOrdinals
;
1337 ULONG ExportDirSize
;
1339 DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1341 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData(BaseAddress
,
1343 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1345 if (ExportDir
== NULL
)
1347 DPRINT1("LdrPEGetExportByName(): no export directory!\n");
1352 /* The symbol names may be missing entirely */
1353 if (ExportDir
->AddressOfNames
== 0)
1355 DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
1360 * Get header pointers
1362 ExNames
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
1363 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
1364 ExFunctions
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
1367 * Check the hint first
1369 if (Hint
< ExportDir
->NumberOfNames
)
1371 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1372 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1374 Ordinal
= ExOrdinals
[Hint
];
1375 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1376 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1377 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1379 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1380 Function
= LdrPEFixupForward((PCHAR
)Function
);
1381 if (Function
== NULL
)
1383 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1387 if (Function
!= NULL
)
1395 * Try a binary search first
1398 maxn
= ExportDir
->NumberOfNames
- 1;
1399 while (minn
<= maxn
)
1404 mid
= (minn
+ maxn
) / 2;
1406 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1407 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1410 Ordinal
= ExOrdinals
[mid
];
1411 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1412 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1413 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1415 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1416 Function
= LdrPEFixupForward((PCHAR
)Function
);
1417 if (Function
== NULL
)
1419 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1423 if (Function
!= NULL
)
1428 else if (minn
== maxn
)
1430 DPRINT("LdrPEGetExportByName(): binary search failed\n");
1444 * Fall back on a linear search
1446 DPRINT("LdrPEGetExportByName(): Falling back on a linear search of export table\n");
1447 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++)
1449 ExName
= RVA(BaseAddress
, ExNames
[i
]);
1450 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1452 Ordinal
= ExOrdinals
[i
];
1453 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1454 DPRINT("%x %x %x\n", Function
, ExportDir
, ExportDir
+ ExportDirSize
);
1455 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1456 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1458 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1459 Function
= LdrPEFixupForward((PCHAR
)Function
);
1461 if (Function
== NULL
)
1468 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1473 LdrPEGetExportByOrdinal (PVOID BaseAddress
,
1476 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1477 ULONG ExportDirSize
;
1478 PDWORD
* ExFunctions
;
1481 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData (BaseAddress
,
1483 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1486 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1487 ExportDir
->AddressOfFunctions
);
1488 DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
1490 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
]));
1492 Function
= 0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1493 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1496 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1497 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1499 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1500 Function
= LdrPEFixupForward((PCHAR
)Function
);
1507 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
1508 PMODULE_OBJECT ImportedModule
,
1509 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1511 PVOID
* ImportAddressList
;
1512 PULONG FunctionNameList
;
1515 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1517 return STATUS_UNSUCCESSFUL
;
1520 /* Get the import address list. */
1521 ImportAddressList
= (PVOID
*)(DriverBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1523 /* Get the list of functions to import. */
1524 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1526 FunctionNameList
= (PULONG
) (DriverBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1530 FunctionNameList
= (PULONG
)(DriverBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1533 /* Walk through function list and fixup addresses. */
1534 while (*FunctionNameList
!= 0L)
1536 if ((*FunctionNameList
) & 0x80000000)
1538 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1539 *ImportAddressList
= LdrPEGetExportByOrdinal(ImportedModule
->Base
, Ordinal
);
1540 if ((*ImportAddressList
) == NULL
)
1542 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullName
);
1543 return STATUS_UNSUCCESSFUL
;
1548 IMAGE_IMPORT_BY_NAME
*pe_name
;
1549 pe_name
= RVA(DriverBase
, *FunctionNameList
);
1550 *ImportAddressList
= LdrPEGetExportByName(ImportedModule
->Base
, pe_name
->Name
, pe_name
->Hint
);
1551 if ((*ImportAddressList
) == NULL
)
1553 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullName
);
1554 return STATUS_UNSUCCESSFUL
;
1557 ImportAddressList
++;
1560 return STATUS_SUCCESS
;
1564 LdrPEFixupImports(PMODULE_OBJECT Module
)
1566 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1568 PMODULE_OBJECT ImportedModule
;
1571 /* Process each import module */
1572 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1573 RtlImageDirectoryEntryToData(Module
->Base
,
1575 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1577 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1578 while (ImportModuleDirectory
->Name
)
1580 /* Check to make sure that import lib is kernel */
1581 ImportedName
= (PCHAR
) Module
->Base
+ ImportModuleDirectory
->Name
;
1583 Status
= LdrPEGetOrLoadModule(Module
, ImportedName
, &ImportedModule
);
1584 if (!NT_SUCCESS(Status
))
1589 Status
= LdrPEProcessImportDirectoryEntry(Module
->Base
, ImportedModule
, ImportModuleDirectory
);
1590 if (!NT_SUCCESS(Status
))
1595 ImportModuleDirectory
++;
1597 return STATUS_SUCCESS
;