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>
31 #define ps(args...) DPRINT1(args)
35 #include <internal/debug.h>
37 /* GLOBALS *******************************************************************/
39 LIST_ENTRY ModuleListHead
;
40 KSPIN_LOCK ModuleListLock
;
41 MODULE_OBJECT NtoskrnlModuleObject
;
42 MODULE_OBJECT HalModuleObject
;
44 LIST_ENTRY ModuleTextListHead
;
45 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
46 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
49 #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \
50 ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
51 IMAGE_SIZEOF_NT_OPTIONAL_HEADER + \
52 sizeof (IMAGE_FILE_HEADER)))
55 #define HIWORD(X) ((WORD) (((DWORD) (X) >> 16) & 0xFFFF))
58 #define LOWORD(X) ((WORD) (X))
61 /* FORWARD DECLARATIONS ******************************************************/
66 PUNICODE_STRING ModuleName
,
67 PMODULE_OBJECT
*ModuleObject
);
70 LdrpBuildModuleBaseName (
71 PUNICODE_STRING BaseName
,
72 PUNICODE_STRING FullName
);
75 LdrpCompareModuleNames (
76 IN PUNICODE_STRING String1
,
77 IN PUNICODE_STRING String2
);
80 /* PE Driver load support */
84 PUNICODE_STRING FileName
,
85 PMODULE_OBJECT
*ModuleObject
);
88 LdrPEGetExportByName (
94 LdrPEFixupForward ( PCHAR ForwardName
);
97 LdrPEPerformRelocations (
102 LdrPEFixupImports ( PMODULE_OBJECT Module
);
104 /* FUNCTIONS *****************************************************************/
107 LdrInitDebug ( PLOADER_MODULE Module
, PWCH Name
)
109 PLIST_ENTRY current_entry
;
110 MODULE_TEXT_SECTION
* current
;
112 current_entry
= ModuleTextListHead
.Flink
;
113 while (current_entry
!= &ModuleTextListHead
)
116 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
117 if (wcscmp(current
->Name
, Name
) == 0)
121 current_entry
= current_entry
->Flink
;
124 if (current_entry
== &ModuleTextListHead
)
133 PIMAGE_NT_HEADERS NtHeader
;
134 PIMAGE_SECTION_HEADER SectionList
;
136 InitializeListHead(&ModuleTextListHead
);
138 /* Setup ntoskrnl.exe text section */
140 * This isn't the base of the text segment, but the start of the
141 * full image (in memory)
142 * Also, the Length field isn't set to the length of the segment,
143 * but is more like the offset, from the image base, to the end
146 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
147 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
148 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
149 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
150 + SectionList
[0].VirtualAddress
;
151 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
152 NtoskrnlTextSection
.OptionalHeader
= OPTHDROFFSET(KERNEL_BASE
);
153 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
155 /* Setup hal.dll text section */
156 /* Same comment as above applies */
157 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
158 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
159 LdrHalTextSection
.Base
= LdrHalBase
;
160 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
161 + SectionList
[0].VirtualAddress
;
162 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
163 LdrHalTextSection
.OptionalHeader
= OPTHDROFFSET(LdrHalBase
);
164 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
166 /* Hook for KDB on initialization of the loader. */
167 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection
, &LdrHalTextSection
);
171 LdrInitModuleManagement ( VOID
)
173 PIMAGE_NT_HEADERS NtHeader
;
175 /* Initialize the module list and spinlock */
176 InitializeListHead(&ModuleListHead
);
177 KeInitializeSpinLock(&ModuleListLock
);
179 /* Initialize ModuleObject for NTOSKRNL */
180 RtlZeroMemory(&NtoskrnlModuleObject
, sizeof(MODULE_OBJECT
));
181 NtoskrnlModuleObject
.Base
= (PVOID
) KERNEL_BASE
;
182 NtoskrnlModuleObject
.Flags
= MODULE_FLAG_PE
;
183 RtlInitUnicodeString(&NtoskrnlModuleObject
.FullName
, KERNEL_MODULE_NAME
);
184 LdrpBuildModuleBaseName(&NtoskrnlModuleObject
.BaseName
, &NtoskrnlModuleObject
.FullName
);
186 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
187 NtoskrnlModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
188 NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
189 NtoskrnlModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
190 NtoskrnlModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) NtoskrnlModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
191 DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject
, NtoskrnlModuleObject
.EntryPoint
);
192 NtoskrnlModuleObject
.Length
= NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
193 NtoskrnlModuleObject
.TextSection
= &NtoskrnlTextSection
;
195 InsertTailList(&ModuleListHead
,
196 &NtoskrnlModuleObject
.ListEntry
);
198 /* Initialize ModuleObject for HAL */
199 RtlZeroMemory(&HalModuleObject
, sizeof(MODULE_OBJECT
));
200 HalModuleObject
.Base
= (PVOID
) LdrHalBase
;
201 HalModuleObject
.Flags
= MODULE_FLAG_PE
;
203 RtlInitUnicodeString(&HalModuleObject
.FullName
, HAL_MODULE_NAME
);
204 LdrpBuildModuleBaseName(&HalModuleObject
.BaseName
, &HalModuleObject
.FullName
);
206 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
207 HalModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
208 HalModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
209 HalModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
210 HalModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) HalModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
211 DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject
, HalModuleObject
.EntryPoint
);
212 HalModuleObject
.Length
= HalModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
213 HalModuleObject
.TextSection
= &LdrHalTextSection
;
215 InsertTailList(&ModuleListHead
,
216 &HalModuleObject
.ListEntry
);
221 PUNICODE_STRING DriverName
,
223 PVOID
*SectionPointer
,
225 PVOID
*ExportSectionPointer
)
227 PMODULE_OBJECT ModuleObject
;
230 ModuleObject
= LdrGetModuleObject(DriverName
);
231 if (ModuleObject
== NULL
)
233 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
234 if (!NT_SUCCESS(Status
))
241 *ModuleBase
= ModuleObject
->Base
;
243 //if (SectionPointer)
244 // *SectionPointer = ModuleObject->
247 *EntryPoint
= ModuleObject
->EntryPoint
;
249 //if (ExportSectionPointer)
250 // *ExportSectionPointer = ModuleObject->
252 return(STATUS_SUCCESS
);
257 LdrpUnloadImage ( PVOID ModuleBase
)
259 return(STATUS_NOT_IMPLEMENTED
);
264 LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName
)
266 PDRIVER_INITIALIZE DriverEntry
;
267 PMODULE_OBJECT ModuleObject
;
270 ModuleObject
= LdrGetModuleObject(ModuleName
);
271 if (ModuleObject
!= NULL
)
273 return(STATUS_IMAGE_ALREADY_LOADED
);
276 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
277 if (!NT_SUCCESS(Status
))
282 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
284 Status
= DriverEntry(NULL
, NULL
);
285 if (!NT_SUCCESS(Status
))
287 LdrUnloadModule(ModuleObject
);
296 PUNICODE_STRING Filename
,
297 PMODULE_OBJECT
*ModuleObject
)
299 PVOID ModuleLoadBase
;
302 OBJECT_ATTRIBUTES ObjectAttributes
;
303 PMODULE_OBJECT Module
;
304 FILE_STANDARD_INFORMATION FileStdInfo
;
305 IO_STATUS_BLOCK IoStatusBlock
;
307 *ModuleObject
= NULL
;
309 DPRINT("Loading Module %wZ...\n", Filename
);
311 /* Open the Module */
312 InitializeObjectAttributes(&ObjectAttributes
,
314 OBJ_CASE_INSENSITIVE
,
318 Status
= ZwOpenFile(&FileHandle
,
323 FILE_SYNCHRONOUS_IO_NONALERT
);
325 if (!NT_SUCCESS(Status
))
327 CPRINT("Could not open module file: %wZ\n", Filename
);
332 /* Get the size of the file */
333 Status
= ZwQueryInformationFile(FileHandle
,
337 FileStandardInformation
);
338 if (!NT_SUCCESS(Status
))
340 CPRINT("Could not get file size\n");
346 /* Allocate nonpageable memory for driver */
347 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
348 FileStdInfo
.EndOfFile
.u
.LowPart
,
350 if (ModuleLoadBase
== NULL
)
352 CPRINT("Could not allocate memory for module");
354 return(STATUS_INSUFFICIENT_RESOURCES
);
358 /* Load driver into memory chunk */
359 Status
= ZwReadFile(FileHandle
,
363 FileStdInfo
.EndOfFile
.u
.LowPart
,
365 if (!NT_SUCCESS(Status
))
367 CPRINT("Could not read module file into memory");
368 ExFreePool(ModuleLoadBase
);
376 Status
= LdrProcessModule(ModuleLoadBase
,
379 if (!NT_SUCCESS(Status
))
381 CPRINT("Could not process module\n");
382 ExFreePool(ModuleLoadBase
);
387 ExFreePool(ModuleLoadBase
);
389 *ModuleObject
= Module
;
391 /* Hook for KDB on loading a driver. */
392 KDB_LOADDRIVER_HOOK(Filename
, Module
);
394 return(STATUS_SUCCESS
);
399 LdrUnloadModule ( PMODULE_OBJECT ModuleObject
)
403 /* Remove the module from the module list */
404 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
405 RemoveEntryList(&ModuleObject
->ListEntry
);
406 KeReleaseSpinLock(&ModuleListLock
, Irql
);
408 /* Hook for KDB on unloading a driver. */
409 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
411 /* Free text section */
412 if (ModuleObject
->TextSection
!= NULL
)
414 ExFreePool(ModuleObject
->TextSection
->Name
);
415 RemoveEntryList(&ModuleObject
->TextSection
->ListEntry
);
416 ExFreePool(ModuleObject
->TextSection
);
417 ModuleObject
->TextSection
= NULL
;
420 /* Free module section */
421 // MmFreeSection(ModuleObject->Base);
423 ExFreePool(ModuleObject
->FullName
.Buffer
);
424 ExFreePool(ModuleObject
);
426 return(STATUS_SUCCESS
);
432 PVOID ModuleLoadBase
,
433 PUNICODE_STRING ModuleName
,
434 PMODULE_OBJECT
*ModuleObject
)
436 PIMAGE_DOS_HEADER PEDosHeader
;
438 /* If MZ header exists */
439 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
440 if (PEDosHeader
->e_magic
== IMAGE_DOS_SIGNATURE
&& PEDosHeader
->e_lfanew
!= 0L)
442 return LdrPEProcessModule(ModuleLoadBase
,
447 CPRINT("Module wasn't PE\n");
448 return STATUS_UNSUCCESSFUL
;
452 LdrpQueryModuleInformation (
457 PLIST_ENTRY current_entry
;
458 PMODULE_OBJECT current
;
459 ULONG ModuleCount
= 0;
460 PSYSTEM_MODULE_INFORMATION Smi
;
461 ANSI_STRING AnsiName
;
465 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
467 /* calculate required size */
468 current_entry
= ModuleListHead
.Flink
;
469 while (current_entry
!= (&ModuleListHead
))
472 current_entry
= current_entry
->Flink
;
475 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
476 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
480 KeReleaseSpinLock(&ModuleListLock
, Irql
);
481 return(STATUS_INFO_LENGTH_MISMATCH
);
484 /* fill the buffer */
485 memset(Buffer
, '=', Size
);
487 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
488 Smi
->Count
= ModuleCount
;
491 current_entry
= ModuleListHead
.Flink
;
492 while (current_entry
!= (&ModuleListHead
))
494 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
496 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
497 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
498 Smi
->Module
[ModuleCount
].Base
= current
->Base
;
499 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
500 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
501 Smi
->Module
[ModuleCount
].Index
= (USHORT
)ModuleCount
;
502 Smi
->Module
[ModuleCount
].NameLength
= 0;
503 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
506 AnsiName
.MaximumLength
= 256;
507 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
508 RtlUnicodeStringToAnsiString(&AnsiName
,
512 p
= strrchr(AnsiName
.Buffer
, '\\');
515 Smi
->Module
[ModuleCount
].PathLength
= 0;
520 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
524 current_entry
= current_entry
->Flink
;
527 KeReleaseSpinLock(&ModuleListLock
, Irql
);
529 return(STATUS_SUCCESS
);
534 LdrpBuildModuleBaseName (
535 PUNICODE_STRING BaseName
,
536 PUNICODE_STRING FullName
)
540 DPRINT("LdrpBuildModuleBaseName()\n");
541 DPRINT("FullName %wZ\n", FullName
);
543 p
= wcsrchr(FullName
->Buffer
, L
'\\');
546 p
= FullName
->Buffer
;
555 RtlInitUnicodeString(BaseName
, p
);
560 LdrpCompareModuleNames (
561 IN PUNICODE_STRING String1
,
562 IN PUNICODE_STRING String2
)
568 if (String1
&& String2
)
570 /* Search String1 for last path component */
571 len1
= String1
->Length
/ sizeof(WCHAR
);
572 s1
= String1
->Buffer
;
573 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
577 if (i
== String1
->Length
- sizeof(WCHAR
))
585 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
590 /* Search String2 for last path component */
591 len2
= String2
->Length
/ sizeof(WCHAR
);
592 s2
= String2
->Buffer
;
593 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
597 if (i
== String2
->Length
- sizeof(WCHAR
))
605 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
610 /* Compare last path components */
615 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
616 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
617 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
619 if (!c1
|| !c2
|| c1
!= c2
)
629 LdrGetModuleObject ( PUNICODE_STRING ModuleName
)
631 PMODULE_OBJECT Module
;
635 DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName
);
637 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
639 Entry
= ModuleListHead
.Flink
;
640 while (Entry
!= &ModuleListHead
)
642 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
644 DPRINT("Comparing %wZ and %wZ\n",
648 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
650 DPRINT("Module %wZ\n", &Module
->BaseName
);
651 KeReleaseSpinLock(&ModuleListLock
, Irql
);
655 Entry
= Entry
->Flink
;
658 KeReleaseSpinLock(&ModuleListLock
, Irql
);
660 DPRINT("Could not find module '%wZ'\n", ModuleName
);
666 /* ---------------------------------------------- PE Module support */
669 LdrLookupPageProtection (
672 PIMAGE_FILE_HEADER PEFileHeader
,
673 PIMAGE_SECTION_HEADER PESectionHeaders
)
675 BOOLEAN Write
= FALSE
;
676 BOOLEAN Execute
= FALSE
;
677 ULONG Characteristics
;
682 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& (!Write
|| !Execute
); Idx
++)
684 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
685 if (!(Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
687 Length
= max(PESectionHeaders
[Idx
].Misc
.VirtualSize
, PESectionHeaders
[Idx
].SizeOfRawData
);
688 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
689 if (BaseAddress
< (PVOID
)((ULONG_PTR
)PageStart
+ PAGE_SIZE
) &&
690 PageStart
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
))
692 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
696 if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
703 if (Write
&& Execute
)
705 return PAGE_EXECUTE_READWRITE
;
709 return PAGE_EXECUTE_READ
;
713 return PAGE_READWRITE
;
717 return PAGE_READONLY
;
723 PVOID ModuleLoadBase
,
724 PUNICODE_STRING FileName
,
725 PMODULE_OBJECT
*ModuleObject
)
727 unsigned int DriverSize
, Idx
;
730 PIMAGE_DOS_HEADER PEDosHeader
;
731 PIMAGE_NT_HEADERS PENtHeaders
;
732 PIMAGE_SECTION_HEADER PESectionHeaders
;
733 PMODULE_OBJECT CreatedModuleObject
;
734 MODULE_TEXT_SECTION
* ModuleTextSection
;
738 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
740 /* Get header pointers */
741 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
742 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
743 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
746 /* Check file magic numbers */
747 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
749 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
750 return STATUS_UNSUCCESSFUL
;
752 if (PEDosHeader
->e_lfanew
== 0)
754 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
755 return STATUS_UNSUCCESSFUL
;
757 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
759 CPRINT("Incorrect PE magic: %08x\n", PENtHeaders
->Signature
);
760 return STATUS_UNSUCCESSFUL
;
762 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
764 CPRINT("Incorrect Architechture: %04x\n", PENtHeaders
->FileHeader
.Machine
);
765 return STATUS_UNSUCCESSFUL
;
769 /* FIXME: if image is fixed-address load, then fail */
771 /* FIXME: check/verify OS version number */
773 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
774 PENtHeaders
->OptionalHeader
.Magic
,
775 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
776 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
777 DPRINT("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
779 /* Determine the size of the module */
781 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
783 if (!(PESectionHeaders
[Idx
].Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
785 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
786 DriverSize
= max(DriverSize
, CurrentSize
);
789 DriverSize
= ROUND_UP(DriverSize
, PENtHeaders
->OptionalHeader
.SectionAlignment
);
790 DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize
, PENtHeaders
->OptionalHeader
.SizeOfImage
);
792 /* Allocate a virtual section for the module */
794 DriverBase
= MmAllocateSection(DriverSize
, DriverBase
);
797 CPRINT("Failed to allocate a virtual section for driver\n");
798 return STATUS_UNSUCCESSFUL
;
800 DPRINT("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
802 /* Copy headers over */
803 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
805 /* Copy image sections into virtual section */
806 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
808 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
809 /* Copy current section into current offset of virtual section */
810 if (CurrentSize
<= DriverSize
&&
811 PESectionHeaders
[Idx
].SizeOfRawData
)
813 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
814 PESectionHeaders
[Idx
].VirtualAddress
+ (ULONG_PTR
)DriverBase
);
815 memcpy((PVOID
)((ULONG_PTR
)DriverBase
+ PESectionHeaders
[Idx
].VirtualAddress
),
816 (PVOID
)((ULONG_PTR
)ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
817 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
818 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
822 /* Perform relocation fixups */
823 Status
= LdrPEPerformRelocations(DriverBase
, DriverSize
);
824 if (!NT_SUCCESS(Status
))
826 // MmFreeSection(DriverBase);
830 /* Create the module */
831 CreatedModuleObject
= ExAllocatePoolWithTag (
832 NonPagedPool
, sizeof(MODULE_OBJECT
), TAG_MODULE_OBJECT
);
833 if (CreatedModuleObject
== NULL
)
835 // MmFreeSection(DriverBase);
836 return STATUS_INSUFFICIENT_RESOURCES
;
839 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
841 /* Initialize ModuleObject data */
842 CreatedModuleObject
->Base
= DriverBase
;
843 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
845 CreatedModuleObject
->FullName
.Length
= 0;
846 CreatedModuleObject
->FullName
.MaximumLength
= FileName
->Length
+ sizeof(UNICODE_NULL
);
847 CreatedModuleObject
->FullName
.Buffer
=
848 ExAllocatePoolWithTag(PagedPool
, CreatedModuleObject
->FullName
.MaximumLength
, TAG_LDR_WSTR
);
849 if (CreatedModuleObject
->FullName
.Buffer
== NULL
)
851 ExFreePool(CreatedModuleObject
);
852 // MmFreeSection(DriverBase);
853 return STATUS_INSUFFICIENT_RESOURCES
;
856 RtlCopyUnicodeString(&CreatedModuleObject
->FullName
, FileName
);
857 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
858 &CreatedModuleObject
->FullName
);
860 CreatedModuleObject
->EntryPoint
=
861 (PVOID
)((ULONG_PTR
)DriverBase
+
862 PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
863 CreatedModuleObject
->Length
= DriverSize
;
864 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
866 CreatedModuleObject
->Image
.PE
.FileHeader
=
867 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
869 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
870 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
871 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
872 sizeof(IMAGE_FILE_HEADER
));
873 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
874 CreatedModuleObject
->Image
.PE
.SectionList
=
875 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
876 sizeof(IMAGE_FILE_HEADER
) + CreatedModuleObject
->Image
.PE
.FileHeader
->SizeOfOptionalHeader
);
877 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
879 /* Perform import fixups */
880 Status
= LdrPEFixupImports(CreatedModuleObject
);
881 if (!NT_SUCCESS(Status
))
883 // MmFreeSection(DriverBase);
884 ExFreePool(CreatedModuleObject
->FullName
.Buffer
);
885 ExFreePool(CreatedModuleObject
);
889 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
890 /* Set the protections for the various parts of the driver */
891 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
893 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
898 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
899 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
900 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
902 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
906 * This driver modifies a string in the first page of the text section while initialising.
908 if (0 == _wcsicmp(L
"fireport.sys", FileName
->Buffer
))
910 Protect
= PAGE_EXECUTE_READWRITE
;
913 if (PageAddress
< RVA(DriverBase
, DriverSize
))
915 MmSetPageProtect(NULL
, PageAddress
, Protect
);
918 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
920 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
922 Protect
= PAGE_EXECUTE_READWRITE
;
926 Protect
= PAGE_EXECUTE_READ
;
929 else if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
931 Protect
= PAGE_READWRITE
;
935 Protect
= PAGE_READONLY
;
937 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
938 while ((ULONG_PTR
)PageAddress
+ PAGE_SIZE
< (ULONG_PTR
)BaseAddress
+ Length
)
940 if (PageAddress
< RVA(DriverBase
, DriverSize
))
942 MmSetPageProtect(NULL
, PageAddress
, Protect
);
944 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
946 if (PageAddress
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
) &&
947 PageAddress
< RVA(DriverBase
, DriverSize
))
949 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
950 MmSetPageProtect(NULL
, PageAddress
, Protect
);
955 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
956 InsertTailList(&ModuleListHead
,
957 &CreatedModuleObject
->ListEntry
);
958 KeReleaseSpinLock(&ModuleListLock
, Irql
);
961 ModuleTextSection
= ExAllocatePoolWithTag (
963 sizeof(MODULE_TEXT_SECTION
),
964 TAG_MODULE_TEXT_SECTION
);
965 ASSERT(ModuleTextSection
);
966 RtlZeroMemory(ModuleTextSection
, sizeof(MODULE_TEXT_SECTION
));
967 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
968 ModuleTextSection
->Length
= DriverSize
;
969 ModuleTextSection
->Name
= ExAllocatePoolWithTag (
971 (CreatedModuleObject
->BaseName
.Length
+ 1) * sizeof(WCHAR
),
973 RtlCopyMemory(ModuleTextSection
->Name
,
974 CreatedModuleObject
->BaseName
.Buffer
,
975 CreatedModuleObject
->BaseName
.Length
);
976 ModuleTextSection
->Name
[CreatedModuleObject
->BaseName
.Length
/ sizeof(WCHAR
)] = 0;
977 ModuleTextSection
->OptionalHeader
=
978 CreatedModuleObject
->Image
.PE
.OptionalHeader
;
979 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
981 CreatedModuleObject
->TextSection
= ModuleTextSection
;
983 *ModuleObject
= CreatedModuleObject
;
985 DPRINT("Loading Module %wZ...\n", FileName
);
987 DPRINT("Module %wZ loaded at 0x%.08x.\n",
988 FileName
, CreatedModuleObject
->Base
);
990 return STATUS_SUCCESS
;
995 LdrSafePEProcessModule (
996 PVOID ModuleLoadBase
,
998 PVOID ImportModuleBase
,
1003 PIMAGE_DOS_HEADER PEDosHeader
;
1004 PIMAGE_NT_HEADERS PENtHeaders
;
1005 PIMAGE_SECTION_HEADER PESectionHeaders
;
1008 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1010 /* Get header pointers */
1011 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1012 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
1013 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
1016 /* Check file magic numbers */
1017 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
1021 if (PEDosHeader
->e_lfanew
== 0)
1025 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
1029 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
1034 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1035 PENtHeaders
->OptionalHeader
.Magic
,
1036 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
1037 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
1038 ps("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1040 /* Determine the size of the module */
1041 *DriverSize
= PENtHeaders
->OptionalHeader
.SizeOfImage
;
1042 ps("DriverSize %x\n",*DriverSize
);
1044 /* Copy headers over */
1045 if (DriverBase
!= ModuleLoadBase
)
1047 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1050 ps("Hdr: 0x%X\n", PENtHeaders
);
1051 ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1052 ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders
->FileHeader
.NumberOfSections
);
1054 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1055 address as it is mapped */
1056 if (DriverBase
!= ModuleLoadBase
)
1060 /* Copy image sections into virtual section */
1061 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1063 PIMAGE_SECTION_HEADER Section
= &PESectionHeaders
[Idx
];
1064 // Copy current section into current offset of virtual section
1065 if (Section
->SizeOfRawData
)
1067 // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1068 // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1069 memcpy(Section
->VirtualAddress
+ (char*)DriverBase
,
1070 Section
->PointerToRawData
+ (char*)ModuleLoadBase
,
1071 Section
->Misc
.VirtualSize
> Section
->SizeOfRawData
? Section
->SizeOfRawData
: Section
->Misc
.VirtualSize
);
1073 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
)
1075 memset(Section
->VirtualAddress
+ Section
->SizeOfRawData
+ (char*)DriverBase
,
1077 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
1079 CurrentSize
+= ROUND_UP(Section
->Misc
.VirtualSize
,
1080 PENtHeaders
->OptionalHeader
.SectionAlignment
);
1083 /* Perform relocation fixups */
1084 Status
= LdrPEPerformRelocations(DriverBase
, *DriverSize
);
1085 if (!NT_SUCCESS(Status
))
1091 /* Perform import fixups */
1092 Status
= LdrPEFixupImports(DriverBase
== ModuleLoadBase
? &NtoskrnlModuleObject
: &HalModuleObject
);
1093 if (!NT_SUCCESS(Status
))
1098 /* Set the page protection for the virtual sections */
1099 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
1100 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1102 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1107 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1108 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
1109 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1111 if (Characteristics
& IMAGE_SCN_MEM_EXECUTE
)
1113 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1115 Protect
= PAGE_EXECUTE_READWRITE
;
1119 Protect
= PAGE_EXECUTE_READ
;
1122 else if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1124 Protect
= PAGE_READWRITE
;
1128 Protect
= PAGE_READONLY
;
1130 while ((ULONG_PTR
)PageAddress
< (ULONG_PTR
)BaseAddress
+ Length
)
1132 MmSetPageProtect(NULL
, PageAddress
, Protect
);
1133 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
1135 if (DriverBase
== ModuleLoadBase
&&
1136 Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
1138 /* For ntoskrnl, we must stop after the bss section */
1148 LdrPEFixupForward ( PCHAR ForwardName
)
1150 CHAR NameBuffer
[128];
1151 UNICODE_STRING ModuleName
;
1153 PMODULE_OBJECT ModuleObject
;
1155 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1157 strcpy(NameBuffer
, ForwardName
);
1158 p
= strchr(NameBuffer
, '.');
1166 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1168 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1170 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1171 RtlFreeUnicodeString(&ModuleName
);
1173 DPRINT("ModuleObject: %p\n", ModuleObject
);
1175 if (ModuleObject
== NULL
)
1177 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1180 return LdrPEGetExportByName(ModuleObject
->Base
, (PUCHAR
)(p
+1), 0xffff);
1184 LdrPEPerformRelocations (
1188 PIMAGE_NT_HEADERS NtHeaders
;
1189 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1190 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1192 PVOID Address
, MaxAddress
;
1200 NtHeaders
= RtlImageNtHeader(DriverBase
);
1202 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1204 return STATUS_UNSUCCESSFUL
;
1207 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1209 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1211 return STATUS_SUCCESS
;
1214 Delta
= (ULONG_PTR
)DriverBase
- NtHeaders
->OptionalHeader
.ImageBase
;
1215 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)DriverBase
+ RelocationDDir
->VirtualAddress
);
1216 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
1217 MaxAddress
= RVA(DriverBase
, DriverSize
);
1219 while (RelocationDir
< RelocationEnd
&&
1220 RelocationDir
->SizeOfBlock
> 0)
1222 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
1223 Address
= RVA(DriverBase
, RelocationDir
->VirtualAddress
);
1224 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1226 for (i
= 0; i
< Count
; i
++)
1228 Offset
= *TypeOffset
& 0xFFF;
1229 Type
= *TypeOffset
>> 12;
1230 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
1232 /* Don't relocate after the end of the loaded driver */
1233 if ((PVOID
)ShortPtr
>= MaxAddress
)
1239 * Don't relocate within the relocation section itself.
1240 * GCC/LD generates sometimes relocation records for the relecotion section.
1241 * This is a bug in GCC/LD.
1243 if ((ULONG_PTR
)ShortPtr
< (ULONG_PTR
)RelocationDir
||
1244 (ULONG_PTR
)ShortPtr
>= (ULONG_PTR
)RelocationEnd
)
1248 case IMAGE_REL_BASED_ABSOLUTE
:
1251 case IMAGE_REL_BASED_HIGH
:
1252 *ShortPtr
+= HIWORD(Delta
);
1255 case IMAGE_REL_BASED_LOW
:
1256 *ShortPtr
+= LOWORD(Delta
);
1259 case IMAGE_REL_BASED_HIGHLOW
:
1260 LongPtr
= (PULONG
)ShortPtr
;
1264 case IMAGE_REL_BASED_HIGHADJ
:
1265 case IMAGE_REL_BASED_MIPS_JMPADDR
:
1267 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
1268 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, *TypeOffset
);
1269 return STATUS_UNSUCCESSFUL
;
1274 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
1277 return STATUS_SUCCESS
;
1280 #define PATH_MAX 260
1284 LdrPEGetOrLoadModule (
1285 PMODULE_OBJECT Module
,
1287 PMODULE_OBJECT
* ImportedModule
)
1289 UNICODE_STRING DriverName
;
1290 UNICODE_STRING NameString
;
1291 WCHAR NameBuffer
[PATH_MAX
];
1292 NTSTATUS Status
= STATUS_SUCCESS
;
1294 if (0 == _stricmp(ImportedName
, "ntoskrnl") ||
1295 0 == _stricmp(ImportedName
, "ntoskrnl.exe"))
1297 *ImportedModule
= &NtoskrnlModuleObject
;
1298 return STATUS_SUCCESS
;
1301 if (0 == _stricmp(ImportedName
, "hal") ||
1302 0 == _stricmp(ImportedName
, "hal.dll"))
1304 *ImportedModule
= &HalModuleObject
;
1305 return STATUS_SUCCESS
;
1308 RtlCreateUnicodeStringFromAsciiz (&DriverName
, ImportedName
);
1309 DPRINT("Import module: %wZ\n", &DriverName
);
1311 *ImportedModule
= LdrGetModuleObject(&DriverName
);
1312 if (*ImportedModule
== NULL
)
1317 PathEnd
= wcsrchr(Module
->FullName
.Buffer
, L
'\\');
1318 if (NULL
!= PathEnd
)
1320 PathLength
= (PathEnd
- Module
->FullName
.Buffer
+ 1) * sizeof(WCHAR
);
1321 RtlCopyMemory(NameBuffer
, Module
->FullName
.Buffer
, PathLength
);
1322 RtlCopyMemory(NameBuffer
+ (PathLength
/ sizeof(WCHAR
)), DriverName
.Buffer
, DriverName
.Length
);
1323 NameString
.Buffer
= NameBuffer
;
1324 NameString
.MaximumLength
= NameString
.Length
= PathLength
+ DriverName
.Length
;
1326 /* NULL-terminate */
1327 NameString
.MaximumLength
++;
1328 NameBuffer
[NameString
.Length
/ sizeof(WCHAR
)] = 0;
1330 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1334 DPRINT("Module '%wZ' not loaded yet\n", &DriverName
);
1335 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
1336 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1337 RtlInitUnicodeString(&NameString
, NameBuffer
);
1338 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1340 if (!NT_SUCCESS(Status
))
1342 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
1343 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1344 RtlInitUnicodeString(&NameString
, NameBuffer
);
1345 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1346 if (!NT_SUCCESS(Status
))
1348 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName
, Status
);
1352 RtlFreeUnicodeString(&DriverName
);
1357 LdrPEGetExportByName (
1362 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1363 PDWORD
* ExFunctions
;
1365 USHORT
* ExOrdinals
;
1371 ULONG ExportDirSize
;
1373 DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1375 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData(BaseAddress
,
1377 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1379 if (ExportDir
== NULL
)
1381 DPRINT1("LdrPEGetExportByName(): no export directory!\n");
1386 /* The symbol names may be missing entirely */
1387 if (ExportDir
->AddressOfNames
== 0)
1389 DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
1394 * Get header pointers
1396 ExNames
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
1397 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
1398 ExFunctions
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
1401 * Check the hint first
1403 if (Hint
< ExportDir
->NumberOfNames
)
1405 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1406 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1408 Ordinal
= ExOrdinals
[Hint
];
1409 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1410 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1411 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1413 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1414 Function
= LdrPEFixupForward((PCHAR
)Function
);
1415 if (Function
== NULL
)
1417 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1421 if (Function
!= NULL
)
1429 * Try a binary search first
1432 maxn
= ExportDir
->NumberOfNames
- 1;
1433 while (minn
<= maxn
)
1438 mid
= (minn
+ maxn
) / 2;
1440 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1441 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1444 Ordinal
= ExOrdinals
[mid
];
1445 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1446 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1447 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1449 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1450 Function
= LdrPEFixupForward((PCHAR
)Function
);
1451 if (Function
== NULL
)
1453 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1457 if (Function
!= NULL
)
1462 else if (minn
== maxn
)
1464 DPRINT("LdrPEGetExportByName(): binary search failed\n");
1478 * Fall back on a linear search
1480 DPRINT("LdrPEGetExportByName(): Falling back on a linear search of export table\n");
1481 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++)
1483 ExName
= RVA(BaseAddress
, ExNames
[i
]);
1484 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1486 Ordinal
= ExOrdinals
[i
];
1487 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1488 DPRINT("%x %x %x\n", Function
, ExportDir
, ExportDir
+ ExportDirSize
);
1489 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1490 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1492 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1493 Function
= LdrPEFixupForward((PCHAR
)Function
);
1495 if (Function
== NULL
)
1502 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1507 LdrPEGetExportByOrdinal (
1511 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1512 ULONG ExportDirSize
;
1513 PDWORD
* ExFunctions
;
1516 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData (
1519 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1522 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1523 ExportDir
->AddressOfFunctions
);
1524 DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
1526 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
]));
1528 Function
= 0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1529 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1532 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1533 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1535 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1536 Function
= LdrPEFixupForward((PCHAR
)Function
);
1543 LdrPEProcessImportDirectoryEntry(
1545 PMODULE_OBJECT ImportedModule
,
1546 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1548 PVOID
* ImportAddressList
;
1549 PULONG FunctionNameList
;
1552 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1554 return STATUS_UNSUCCESSFUL
;
1557 /* Get the import address list. */
1558 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
1560 /* Get the list of functions to import. */
1561 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1563 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
1567 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
1570 /* Walk through function list and fixup addresses. */
1571 while (*FunctionNameList
!= 0L)
1573 if ((*FunctionNameList
) & 0x80000000)
1575 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1576 *ImportAddressList
= LdrPEGetExportByOrdinal(ImportedModule
->Base
, Ordinal
);
1577 if ((*ImportAddressList
) == NULL
)
1579 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullName
);
1580 return STATUS_UNSUCCESSFUL
;
1585 IMAGE_IMPORT_BY_NAME
*pe_name
;
1586 pe_name
= RVA(DriverBase
, *FunctionNameList
);
1587 *ImportAddressList
= LdrPEGetExportByName(ImportedModule
->Base
, pe_name
->Name
, pe_name
->Hint
);
1588 if ((*ImportAddressList
) == NULL
)
1590 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullName
);
1591 return STATUS_UNSUCCESSFUL
;
1594 ImportAddressList
++;
1597 return STATUS_SUCCESS
;
1601 LdrPEFixupImports ( PMODULE_OBJECT Module
)
1603 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1605 PMODULE_OBJECT ImportedModule
;
1608 /* Process each import module */
1609 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1610 RtlImageDirectoryEntryToData(Module
->Base
,
1612 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1614 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1615 while (ImportModuleDirectory
->Name
)
1617 if (Module
->Length
<= ImportModuleDirectory
->Name
)
1619 DPRINT1("Invalid import directory in %wZ\n", &Module
->FullName
);
1620 return STATUS_SECTION_NOT_IMAGE
;
1623 /* Check to make sure that import lib is kernel */
1624 ImportedName
= (PCHAR
) Module
->Base
+ ImportModuleDirectory
->Name
;
1626 Status
= LdrPEGetOrLoadModule(Module
, ImportedName
, &ImportedModule
);
1627 if (!NT_SUCCESS(Status
))
1632 Status
= LdrPEProcessImportDirectoryEntry(Module
->Base
, ImportedModule
, ImportModuleDirectory
);
1633 if (!NT_SUCCESS(Status
))
1638 ImportModuleDirectory
++;
1640 return STATUS_SUCCESS
;