1 /* $Id: loader.c,v 1.150 2004/10/26 10:56:38 ekohl 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
;
46 STATIC MODULE_OBJECT NtoskrnlModuleObject
;
47 STATIC MODULE_OBJECT HalModuleObject
;
49 LIST_ENTRY ModuleTextListHead
;
50 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
51 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
54 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
57 #define HIWORD(X) ((WORD) (((DWORD) (X) >> 16) & 0xFFFF))
60 #define LOWORD(X) ((WORD) (X))
63 /* FORWARD DECLARATIONS ******************************************************/
66 LdrProcessModule(PVOID ModuleLoadBase
,
67 PUNICODE_STRING ModuleName
,
68 PMODULE_OBJECT
*ModuleObject
);
71 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
72 PUNICODE_STRING FullName
);
75 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
76 IN PUNICODE_STRING String2
);
79 /* PE Driver load support */
80 static NTSTATUS
LdrPEProcessModule(PVOID ModuleLoadBase
,
81 PUNICODE_STRING FileName
,
82 PMODULE_OBJECT
*ModuleObject
);
84 LdrPEGetExportByName(PVOID BaseAddress
,
89 LdrPEFixupForward(PCHAR ForwardName
);
92 LdrPEPerformRelocations(PVOID DriverBase
,
96 LdrPEFixupImports(PMODULE_OBJECT Module
);
98 /* FUNCTIONS *****************************************************************/
101 LdrInitDebug(PLOADER_MODULE Module
, PWCH Name
)
103 PLIST_ENTRY current_entry
;
104 MODULE_TEXT_SECTION
* current
;
106 current_entry
= ModuleTextListHead
.Flink
;
107 while (current_entry
!= &ModuleTextListHead
)
110 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
111 if (wcscmp(current
->Name
, Name
) == 0)
115 current_entry
= current_entry
->Flink
;
118 if (current_entry
== &ModuleTextListHead
)
127 PIMAGE_NT_HEADERS NtHeader
;
128 PIMAGE_SECTION_HEADER SectionList
;
130 InitializeListHead(&ModuleTextListHead
);
132 /* Setup ntoskrnl.exe text section */
134 * This isn't the base of the text segment, but the start of the
135 * full image (in memory)
136 * Also, the Length field isn't set to the length of the segment,
137 * but is more like the offset, from the image base, to the end
140 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
141 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
142 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
143 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
144 SectionList
[0].VirtualAddress
;
145 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
146 NtoskrnlTextSection
.OptionalHeader
= OPTHDROFFSET(KERNEL_BASE
);
147 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
149 /* Setup hal.dll text section */
150 /* Same comment as above applies */
151 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
152 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
153 LdrHalTextSection
.Base
= LdrHalBase
;
154 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
155 SectionList
[0].VirtualAddress
;
156 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
157 LdrHalTextSection
.OptionalHeader
= OPTHDROFFSET(LdrHalBase
);
158 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
160 /* Hook for KDB on initialization of the loader. */
161 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection
, &LdrHalTextSection
);
165 LdrInitModuleManagement(VOID
)
167 PIMAGE_NT_HEADERS NtHeader
;
169 /* Initialize the module list and spinlock */
170 InitializeListHead(&ModuleListHead
);
171 KeInitializeSpinLock(&ModuleListLock
);
173 /* Initialize ModuleObject for NTOSKRNL */
174 RtlZeroMemory(&NtoskrnlModuleObject
, sizeof(MODULE_OBJECT
));
175 NtoskrnlModuleObject
.Base
= (PVOID
) KERNEL_BASE
;
176 NtoskrnlModuleObject
.Flags
= MODULE_FLAG_PE
;
177 RtlInitUnicodeString(&NtoskrnlModuleObject
.FullName
, KERNEL_MODULE_NAME
);
178 LdrpBuildModuleBaseName(&NtoskrnlModuleObject
.BaseName
, &NtoskrnlModuleObject
.FullName
);
180 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
181 NtoskrnlModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
182 NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
183 NtoskrnlModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
184 NtoskrnlModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) NtoskrnlModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
185 DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject
, NtoskrnlModuleObject
.EntryPoint
);
186 NtoskrnlModuleObject
.Length
= NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
187 NtoskrnlModuleObject
.TextSection
= &NtoskrnlTextSection
;
189 InsertTailList(&ModuleListHead
,
190 &NtoskrnlModuleObject
.ListEntry
);
192 /* Initialize ModuleObject for HAL */
193 RtlZeroMemory(&HalModuleObject
, sizeof(MODULE_OBJECT
));
194 HalModuleObject
.Base
= (PVOID
) LdrHalBase
;
195 HalModuleObject
.Flags
= MODULE_FLAG_PE
;
197 RtlInitUnicodeString(&HalModuleObject
.FullName
, HAL_MODULE_NAME
);
198 LdrpBuildModuleBaseName(&HalModuleObject
.BaseName
, &HalModuleObject
.FullName
);
200 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
201 HalModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
202 HalModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
203 HalModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
204 HalModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) HalModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
205 DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject
, HalModuleObject
.EntryPoint
);
206 HalModuleObject
.Length
= HalModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
207 HalModuleObject
.TextSection
= &LdrHalTextSection
;
209 InsertTailList(&ModuleListHead
,
210 &HalModuleObject
.ListEntry
);
214 LdrpLoadImage(PUNICODE_STRING DriverName
,
216 PVOID
*SectionPointer
,
218 PVOID
*ExportSectionPointer
)
220 PMODULE_OBJECT ModuleObject
;
223 ModuleObject
= LdrGetModuleObject(DriverName
);
224 if (ModuleObject
== NULL
)
226 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
227 if (!NT_SUCCESS(Status
))
234 *ModuleBase
= ModuleObject
->Base
;
236 // if (SectionPointer)
237 // *SectionPointer = ModuleObject->
240 *EntryPoint
= ModuleObject
->EntryPoint
;
242 // if (ExportSectionPointer)
243 // *ExportSectionPointer = ModuleObject->
245 return(STATUS_SUCCESS
);
250 LdrpUnloadImage(PVOID ModuleBase
)
252 return(STATUS_NOT_IMPLEMENTED
);
257 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName
)
259 PDRIVER_INITIALIZE DriverEntry
;
260 PMODULE_OBJECT ModuleObject
;
263 ModuleObject
= LdrGetModuleObject(ModuleName
);
264 if (ModuleObject
!= NULL
)
266 return(STATUS_IMAGE_ALREADY_LOADED
);
269 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
270 if (!NT_SUCCESS(Status
))
275 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
277 Status
= DriverEntry(NULL
, NULL
);
278 if (!NT_SUCCESS(Status
))
280 LdrUnloadModule(ModuleObject
);
288 LdrLoadModule(PUNICODE_STRING Filename
,
289 PMODULE_OBJECT
*ModuleObject
)
291 PVOID ModuleLoadBase
;
294 OBJECT_ATTRIBUTES ObjectAttributes
;
295 PMODULE_OBJECT Module
;
296 FILE_STANDARD_INFORMATION FileStdInfo
;
297 IO_STATUS_BLOCK IoStatusBlock
;
299 *ModuleObject
= NULL
;
301 DPRINT("Loading Module %wZ...\n", Filename
);
303 /* Open the Module */
304 InitializeObjectAttributes(&ObjectAttributes
,
306 OBJ_CASE_INSENSITIVE
,
310 Status
= NtOpenFile(&FileHandle
,
315 FILE_SYNCHRONOUS_IO_NONALERT
);
317 if (!NT_SUCCESS(Status
))
319 CPRINT("Could not open module file: %wZ\n", Filename
);
324 /* Get the size of the file */
325 Status
= NtQueryInformationFile(FileHandle
,
329 FileStandardInformation
);
330 if (!NT_SUCCESS(Status
))
332 CPRINT("Could not get file size\n");
338 /* Allocate nonpageable memory for driver */
339 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
340 FileStdInfo
.EndOfFile
.u
.LowPart
,
342 if (ModuleLoadBase
== NULL
)
344 CPRINT("Could not allocate memory for module");
346 return(STATUS_INSUFFICIENT_RESOURCES
);
350 /* Load driver into memory chunk */
351 Status
= NtReadFile(FileHandle
,
355 FileStdInfo
.EndOfFile
.u
.LowPart
,
357 if (!NT_SUCCESS(Status
))
359 CPRINT("Could not read module file into memory");
360 ExFreePool(ModuleLoadBase
);
368 Status
= LdrProcessModule(ModuleLoadBase
,
371 if (!NT_SUCCESS(Status
))
373 CPRINT("Could not process module\n");
374 ExFreePool(ModuleLoadBase
);
379 ExFreePool(ModuleLoadBase
);
381 *ModuleObject
= Module
;
383 /* Hook for KDB on loading a driver. */
384 KDB_LOADDRIVER_HOOK(Filename
, Module
);
386 return(STATUS_SUCCESS
);
391 LdrUnloadModule(PMODULE_OBJECT ModuleObject
)
395 /* Remove the module from the module list */
396 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
397 RemoveEntryList(&ModuleObject
->ListEntry
);
398 KeReleaseSpinLock(&ModuleListLock
, Irql
);
400 /* Hook for KDB on unloading a driver. */
401 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
403 /* Free text section */
404 if (ModuleObject
->TextSection
!= NULL
)
406 ExFreePool(ModuleObject
->TextSection
->Name
);
407 RemoveEntryList(&ModuleObject
->TextSection
->ListEntry
);
408 ExFreePool(ModuleObject
->TextSection
);
409 ModuleObject
->TextSection
= NULL
;
412 /* Free module section */
413 // MmFreeSection(ModuleObject->Base);
415 ExFreePool(ModuleObject
->FullName
.Buffer
);
416 ExFreePool(ModuleObject
);
418 return(STATUS_SUCCESS
);
423 LdrProcessModule(PVOID ModuleLoadBase
,
424 PUNICODE_STRING ModuleName
,
425 PMODULE_OBJECT
*ModuleObject
)
427 PIMAGE_DOS_HEADER PEDosHeader
;
429 /* If MZ header exists */
430 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
431 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
433 return LdrPEProcessModule(ModuleLoadBase
,
438 CPRINT("Module wasn't PE\n");
439 return STATUS_UNSUCCESSFUL
;
443 LdrpQueryModuleInformation(PVOID Buffer
,
447 PLIST_ENTRY current_entry
;
448 PMODULE_OBJECT current
;
449 ULONG ModuleCount
= 0;
450 PSYSTEM_MODULE_INFORMATION Smi
;
451 ANSI_STRING AnsiName
;
455 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
457 /* calculate required size */
458 current_entry
= ModuleListHead
.Flink
;
459 while (current_entry
!= (&ModuleListHead
))
462 current_entry
= current_entry
->Flink
;
465 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
466 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
470 KeReleaseSpinLock(&ModuleListLock
, Irql
);
471 return(STATUS_INFO_LENGTH_MISMATCH
);
474 /* fill the buffer */
475 memset(Buffer
, '=', Size
);
477 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
478 Smi
->Count
= ModuleCount
;
481 current_entry
= ModuleListHead
.Flink
;
482 while (current_entry
!= (&ModuleListHead
))
484 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
486 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
487 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
488 Smi
->Module
[ModuleCount
].Base
= current
->Base
;
489 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
490 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
491 Smi
->Module
[ModuleCount
].Index
= (USHORT
)ModuleCount
;
492 Smi
->Module
[ModuleCount
].NameLength
= 0;
493 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
496 AnsiName
.MaximumLength
= 256;
497 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
498 RtlUnicodeStringToAnsiString(&AnsiName
,
502 p
= strrchr(AnsiName
.Buffer
, '\\');
505 Smi
->Module
[ModuleCount
].PathLength
= 0;
510 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
514 current_entry
= current_entry
->Flink
;
517 KeReleaseSpinLock(&ModuleListLock
, Irql
);
519 return(STATUS_SUCCESS
);
524 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
525 PUNICODE_STRING FullName
)
529 DPRINT("LdrpBuildModuleBaseName()\n");
530 DPRINT("FullName %wZ\n", FullName
);
532 p
= wcsrchr(FullName
->Buffer
, L
'\\');
535 p
= FullName
->Buffer
;
544 RtlInitUnicodeString(BaseName
, p
);
549 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
550 IN PUNICODE_STRING String2
)
556 if (String1
&& String2
)
558 /* Search String1 for last path component */
559 len1
= String1
->Length
/ sizeof(WCHAR
);
560 s1
= String1
->Buffer
;
561 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
565 if (i
== String1
->Length
- sizeof(WCHAR
))
573 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
578 /* Search String2 for last path component */
579 len2
= String2
->Length
/ sizeof(WCHAR
);
580 s2
= String2
->Buffer
;
581 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
585 if (i
== String2
->Length
- sizeof(WCHAR
))
593 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
598 /* Compare last path components */
603 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
604 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
605 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
607 if (!c1
|| !c2
|| c1
!= c2
)
617 LdrGetModuleObject(PUNICODE_STRING ModuleName
)
619 PMODULE_OBJECT Module
;
623 DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName
);
625 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
627 Entry
= ModuleListHead
.Flink
;
628 while (Entry
!= &ModuleListHead
)
630 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
632 DPRINT("Comparing %wZ and %wZ\n",
636 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
638 DPRINT("Module %wZ\n", &Module
->BaseName
);
639 KeReleaseSpinLock(&ModuleListLock
, Irql
);
643 Entry
= Entry
->Flink
;
646 KeReleaseSpinLock(&ModuleListLock
, Irql
);
648 DPRINT("Could not find module '%wZ'\n", ModuleName
);
654 /* ---------------------------------------------- PE Module support */
657 LdrLookupPageProtection(PVOID PageStart
,
659 PIMAGE_FILE_HEADER PEFileHeader
,
660 PIMAGE_SECTION_HEADER PESectionHeaders
)
662 BOOLEAN Write
= FALSE
;
663 BOOLEAN Execute
= FALSE
;
664 ULONG Characteristics
;
669 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& (!Write
|| !Execute
); Idx
++)
671 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
672 if (!(Characteristics
& IMAGE_SECTION_NOLOAD
))
674 Length
= max(PESectionHeaders
[Idx
].Misc
.VirtualSize
, PESectionHeaders
[Idx
].SizeOfRawData
);
675 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
676 if (BaseAddress
< (PVOID
)((ULONG_PTR
)PageStart
+ PAGE_SIZE
) &&
677 PageStart
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
))
679 if (Characteristics
& IMAGE_SECTION_CHAR_CODE
)
683 if (Characteristics
& (IMAGE_SECTION_CHAR_WRITABLE
|IMAGE_SECTION_CHAR_BSS
))
690 if (Write
&& Execute
)
692 return PAGE_EXECUTE_READWRITE
;
696 return PAGE_EXECUTE_READ
;
700 return PAGE_READWRITE
;
704 return PAGE_READONLY
;
709 LdrPEProcessModule(PVOID ModuleLoadBase
,
710 PUNICODE_STRING FileName
,
711 PMODULE_OBJECT
*ModuleObject
)
713 unsigned int DriverSize
, Idx
;
716 PIMAGE_DOS_HEADER PEDosHeader
;
717 PIMAGE_NT_HEADERS PENtHeaders
;
718 PIMAGE_SECTION_HEADER PESectionHeaders
;
719 PMODULE_OBJECT CreatedModuleObject
;
720 MODULE_TEXT_SECTION
* ModuleTextSection
;
724 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
726 /* Get header pointers */
727 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
728 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
729 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
732 /* Check file magic numbers */
733 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
735 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
736 return STATUS_UNSUCCESSFUL
;
738 if (PEDosHeader
->e_lfanew
== 0)
740 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
741 return STATUS_UNSUCCESSFUL
;
743 if (PENtHeaders
->Signature
!= IMAGE_PE_MAGIC
)
745 CPRINT("Incorrect PE magic: %08x\n", PENtHeaders
->Signature
);
746 return STATUS_UNSUCCESSFUL
;
748 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
750 CPRINT("Incorrect Architechture: %04x\n", PENtHeaders
->FileHeader
.Machine
);
751 return STATUS_UNSUCCESSFUL
;
755 /* FIXME: if image is fixed-address load, then fail */
757 /* FIXME: check/verify OS version number */
759 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
760 PENtHeaders
->OptionalHeader
.Magic
,
761 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
762 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
763 DPRINT("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
765 /* Determine the size of the module */
767 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
769 if (!(PESectionHeaders
[Idx
].Characteristics
& IMAGE_SECTION_NOLOAD
))
771 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
772 DriverSize
= max(DriverSize
, CurrentSize
);
775 DriverSize
= ROUND_UP(DriverSize
, PENtHeaders
->OptionalHeader
.SectionAlignment
);
776 DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize
, PENtHeaders
->OptionalHeader
.SizeOfImage
);
778 /* Allocate a virtual section for the module */
780 DriverBase
= MmAllocateSection(DriverSize
, DriverBase
);
783 CPRINT("Failed to allocate a virtual section for driver\n");
784 return STATUS_UNSUCCESSFUL
;
786 DbgPrint("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
788 /* Copy headers over */
789 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
791 /* Copy image sections into virtual section */
792 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
794 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
795 /* Copy current section into current offset of virtual section */
796 if (CurrentSize
<= DriverSize
&&
797 PESectionHeaders
[Idx
].SizeOfRawData
)
799 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
800 PESectionHeaders
[Idx
].VirtualAddress
+ (ULONG_PTR
)DriverBase
);
801 memcpy((PVOID
)((ULONG_PTR
)DriverBase
+ PESectionHeaders
[Idx
].VirtualAddress
),
802 (PVOID
)((ULONG_PTR
)ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
803 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
804 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
808 /* Perform relocation fixups */
809 Status
= LdrPEPerformRelocations(DriverBase
, DriverSize
);
810 if (!NT_SUCCESS(Status
))
812 // MmFreeSection(DriverBase);
816 /* Create the module */
817 CreatedModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
818 if (CreatedModuleObject
== NULL
)
820 // MmFreeSection(DriverBase);
821 return STATUS_INSUFFICIENT_RESOURCES
;
824 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
826 /* Initialize ModuleObject data */
827 CreatedModuleObject
->Base
= DriverBase
;
828 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
830 CreatedModuleObject
->FullName
.Length
= 0;
831 CreatedModuleObject
->FullName
.MaximumLength
= FileName
->Length
+ sizeof(UNICODE_NULL
);
832 CreatedModuleObject
->FullName
.Buffer
= ExAllocatePool(PagedPool
, CreatedModuleObject
->FullName
.MaximumLength
);
833 if (CreatedModuleObject
->FullName
.Buffer
== NULL
)
835 ExFreePool(CreatedModuleObject
);
836 // MmFreeSection(DriverBase);
837 return STATUS_INSUFFICIENT_RESOURCES
;
840 RtlCopyUnicodeString(&CreatedModuleObject
->FullName
, FileName
);
841 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
842 &CreatedModuleObject
->FullName
);
844 CreatedModuleObject
->EntryPoint
=
845 (PVOID
)((ULONG_PTR
)DriverBase
+
846 PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
847 CreatedModuleObject
->Length
= DriverSize
;
848 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
850 CreatedModuleObject
->Image
.PE
.FileHeader
=
851 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
853 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
854 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
855 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
856 sizeof(IMAGE_FILE_HEADER
));
857 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
858 CreatedModuleObject
->Image
.PE
.SectionList
=
859 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
860 sizeof(IMAGE_FILE_HEADER
) + CreatedModuleObject
->Image
.PE
.FileHeader
->SizeOfOptionalHeader
);
861 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
863 /* Perform import fixups */
864 Status
= LdrPEFixupImports(CreatedModuleObject
);
865 if (!NT_SUCCESS(Status
))
867 // MmFreeSection(DriverBase);
868 ExFreePool(CreatedModuleObject
->FullName
.Buffer
);
869 ExFreePool(CreatedModuleObject
);
873 /* Set the protections for the various parts of the driver */
874 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
876 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
881 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
882 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
883 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
885 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
889 * This driver modifies a string in the first page of the text section while initialising.
891 if (0 == _wcsicmp(L
"fireport.sys", FileName
->Buffer
))
893 Protect
= PAGE_EXECUTE_READWRITE
;
896 if (PageAddress
< DriverBase
+ DriverSize
)
898 MmSetPageProtect(NULL
, PageAddress
, Protect
);
901 if (Characteristics
& IMAGE_SECTION_CHAR_CODE
)
903 if (Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
)
905 Protect
= PAGE_EXECUTE_READWRITE
;
909 Protect
= PAGE_EXECUTE_READ
;
912 else if (Characteristics
& (IMAGE_SECTION_CHAR_WRITABLE
|IMAGE_SECTION_CHAR_BSS
))
914 Protect
= PAGE_READWRITE
;
918 Protect
= PAGE_READONLY
;
920 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
921 while ((ULONG_PTR
)PageAddress
+ PAGE_SIZE
< (ULONG_PTR
)BaseAddress
+ Length
)
923 if (PageAddress
< DriverBase
+ DriverSize
)
925 MmSetPageProtect(NULL
, PageAddress
, Protect
);
927 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
929 if (PageAddress
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
) &&
930 PageAddress
< DriverBase
+ DriverSize
)
932 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
933 MmSetPageProtect(NULL
, PageAddress
, Protect
);
938 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
939 InsertTailList(&ModuleListHead
,
940 &CreatedModuleObject
->ListEntry
);
941 KeReleaseSpinLock(&ModuleListLock
, Irql
);
944 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
945 sizeof(MODULE_TEXT_SECTION
));
946 ASSERT(ModuleTextSection
);
947 RtlZeroMemory(ModuleTextSection
, sizeof(MODULE_TEXT_SECTION
));
948 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
949 ModuleTextSection
->Length
= DriverSize
;
950 ModuleTextSection
->Name
= ExAllocatePool(NonPagedPool
,
951 (CreatedModuleObject
->BaseName
.Length
+ 1) * sizeof(WCHAR
));
952 RtlCopyMemory(ModuleTextSection
->Name
,
953 CreatedModuleObject
->BaseName
.Buffer
,
954 CreatedModuleObject
->BaseName
.Length
);
955 ModuleTextSection
->Name
[CreatedModuleObject
->BaseName
.Length
/ sizeof(WCHAR
)] = 0;
956 ModuleTextSection
->OptionalHeader
=
957 CreatedModuleObject
->Image
.PE
.OptionalHeader
;
958 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
960 CreatedModuleObject
->TextSection
= ModuleTextSection
;
962 *ModuleObject
= CreatedModuleObject
;
964 DPRINT("Loading Module %wZ...\n", FileName
);
966 if (KdDebuggerEnabled
&& (KdDebugState
& KD_DEBUG_GDB
))
968 DPRINT("Module %wZ loaded at 0x%.08x.\n",
969 FileName
, CreatedModuleObject
->Base
);
972 return STATUS_SUCCESS
;
977 LdrSafePEProcessModule(PVOID ModuleLoadBase
,
979 PVOID ImportModuleBase
,
984 PIMAGE_DOS_HEADER PEDosHeader
;
985 PIMAGE_NT_HEADERS PENtHeaders
;
986 PIMAGE_SECTION_HEADER PESectionHeaders
;
989 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
991 /* Get header pointers */
992 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
993 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
994 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
997 /* Check file magic numbers */
998 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1002 if (PEDosHeader
->e_lfanew
== 0)
1006 if (PENtHeaders
->Signature
!= IMAGE_PE_MAGIC
)
1010 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
1015 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1016 PENtHeaders
->OptionalHeader
.Magic
,
1017 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
1018 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
1019 ps("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1021 /* Determine the size of the module */
1022 *DriverSize
= PENtHeaders
->OptionalHeader
.SizeOfImage
;
1023 ps("DriverSize %x\n",*DriverSize
);
1025 /* Copy headers over */
1026 if (DriverBase
!= ModuleLoadBase
)
1028 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1031 ps("Hdr: 0x%X\n", PENtHeaders
);
1032 ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1033 ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders
->FileHeader
.NumberOfSections
);
1035 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1036 address as it is mapped */
1037 if (DriverBase
!= ModuleLoadBase
)
1041 /* Copy image sections into virtual section */
1042 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1044 PIMAGE_SECTION_HEADER Section
= &PESectionHeaders
[Idx
];
1045 // Copy current section into current offset of virtual section
1046 if (Section
->SizeOfRawData
)
1048 // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1049 // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1050 memcpy(Section
->VirtualAddress
+ (char*)DriverBase
,
1051 Section
->PointerToRawData
+ (char*)ModuleLoadBase
,
1052 Section
->Misc
.VirtualSize
> Section
->SizeOfRawData
? Section
->SizeOfRawData
: Section
->Misc
.VirtualSize
);
1054 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
)
1056 memset(Section
->VirtualAddress
+ Section
->SizeOfRawData
+ (char*)DriverBase
,
1058 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
1060 CurrentSize
+= ROUND_UP(Section
->Misc
.VirtualSize
,
1061 PENtHeaders
->OptionalHeader
.SectionAlignment
);
1064 /* Perform relocation fixups */
1065 Status
= LdrPEPerformRelocations(DriverBase
, *DriverSize
);
1066 if (!NT_SUCCESS(Status
))
1072 /* Perform import fixups */
1073 Status
= LdrPEFixupImports(DriverBase
== ModuleLoadBase
? &NtoskrnlModuleObject
: &HalModuleObject
);
1074 if (!NT_SUCCESS(Status
))
1079 /* Set the page protection for the virtual sections */
1080 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1082 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1087 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1088 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
1089 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1091 if (Characteristics
& IMAGE_SECTION_CHAR_EXECUTABLE
)
1093 if (Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
)
1095 Protect
= PAGE_EXECUTE_READWRITE
;
1099 Protect
= PAGE_EXECUTE_READ
;
1102 else if (Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
)
1104 Protect
= PAGE_READWRITE
;
1108 Protect
= PAGE_READONLY
;
1110 while ((ULONG_PTR
)PageAddress
< (ULONG_PTR
)BaseAddress
+ Length
)
1112 MmSetPageProtect(NULL
, PageAddress
, Protect
);
1113 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
1115 if (DriverBase
== ModuleLoadBase
&&
1116 Characteristics
& IMAGE_SECTION_CHAR_BSS
)
1118 /* For ntoskrnl, we must stop after the bss section */
1128 LdrPEFixupForward(PCHAR ForwardName
)
1130 CHAR NameBuffer
[128];
1131 UNICODE_STRING ModuleName
;
1133 PMODULE_OBJECT ModuleObject
;
1135 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1137 strcpy(NameBuffer
, ForwardName
);
1138 p
= strchr(NameBuffer
, '.');
1146 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1148 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1150 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1151 RtlFreeUnicodeString(&ModuleName
);
1153 DPRINT("ModuleObject: %p\n", ModuleObject
);
1155 if (ModuleObject
== NULL
)
1157 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1160 return LdrPEGetExportByName(ModuleObject
->Base
, p
+1, 0xffff);
1164 LdrPEPerformRelocations(PVOID DriverBase
,
1167 PIMAGE_NT_HEADERS NtHeaders
;
1168 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1169 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1171 PVOID Address
, MaxAddress
;
1179 NtHeaders
= RtlImageNtHeader(DriverBase
);
1181 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1183 return STATUS_UNSUCCESSFUL
;
1186 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1188 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1190 return STATUS_SUCCESS
;
1193 Delta
= (ULONG_PTR
)DriverBase
- NtHeaders
->OptionalHeader
.ImageBase
;
1194 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)DriverBase
+ RelocationDDir
->VirtualAddress
);
1195 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
1196 MaxAddress
= DriverBase
+ DriverSize
;
1198 while (RelocationDir
< RelocationEnd
&&
1199 RelocationDir
->SizeOfBlock
> 0)
1201 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
1202 Address
= DriverBase
+ RelocationDir
->VirtualAddress
;
1203 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1205 for (i
= 0; i
< Count
; i
++)
1207 Offset
= *TypeOffset
& 0xFFF;
1208 Type
= *TypeOffset
>> 12;
1209 ShortPtr
= (PUSHORT
)(Address
+ Offset
);
1211 /* Don't relocate after the end of the loaded driver */
1212 if ((PVOID
)ShortPtr
>= MaxAddress
)
1218 * Don't relocate within the relocation section itself.
1219 * GCC/LD generates sometimes relocation records for the relecotion section.
1220 * This is a bug in GCC/LD.
1222 if ((ULONG_PTR
)ShortPtr
< (ULONG_PTR
)RelocationDir
||
1223 (ULONG_PTR
)ShortPtr
>= (ULONG_PTR
)RelocationEnd
)
1227 case IMAGE_REL_BASED_ABSOLUTE
:
1230 case IMAGE_REL_BASED_HIGH
:
1231 *ShortPtr
+= HIWORD(Delta
);
1234 case IMAGE_REL_BASED_LOW
:
1235 *ShortPtr
+= LOWORD(Delta
);
1238 case IMAGE_REL_BASED_HIGHLOW
:
1239 LongPtr
= (PULONG
)ShortPtr
;
1243 case IMAGE_REL_BASED_HIGHADJ
:
1244 case IMAGE_REL_BASED_MIPS_JMPADDR
:
1246 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
1247 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, *TypeOffset
);
1248 return STATUS_UNSUCCESSFUL
;
1253 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
1256 return STATUS_SUCCESS
;
1260 LdrPEGetOrLoadModule(PMODULE_OBJECT Module
,
1262 PMODULE_OBJECT
* ImportedModule
)
1264 UNICODE_STRING DriverName
;
1265 UNICODE_STRING NameString
;
1266 WCHAR NameBuffer
[PATH_MAX
];
1267 NTSTATUS Status
= STATUS_SUCCESS
;
1269 if (0 == _stricmp(ImportedName
, "ntoskrnl") ||
1270 0 == _stricmp(ImportedName
, "ntoskrnl.exe"))
1272 *ImportedModule
= &NtoskrnlModuleObject
;
1273 return STATUS_SUCCESS
;
1276 if (0 == _stricmp(ImportedName
, "hal") ||
1277 0 == _stricmp(ImportedName
, "hal.dll"))
1279 *ImportedModule
= &HalModuleObject
;
1280 return STATUS_SUCCESS
;
1283 RtlCreateUnicodeStringFromAsciiz (&DriverName
, ImportedName
);
1284 DPRINT("Import module: %wZ\n", &DriverName
);
1286 *ImportedModule
= LdrGetModuleObject(&DriverName
);
1287 if (*ImportedModule
== NULL
)
1292 PathEnd
= wcsrchr(Module
->FullName
.Buffer
, L
'\\');
1293 if (NULL
!= PathEnd
)
1295 PathLength
= (PathEnd
- Module
->FullName
.Buffer
+ 1) * sizeof(WCHAR
);
1296 RtlCopyMemory(NameBuffer
, Module
->FullName
.Buffer
, PathLength
);
1297 RtlCopyMemory(NameBuffer
+ (PathLength
/ sizeof(WCHAR
)), DriverName
.Buffer
, DriverName
.Length
);
1298 NameString
.Buffer
= NameBuffer
;
1299 NameString
.MaximumLength
= NameString
.Length
= PathLength
+ DriverName
.Length
;
1301 /* NULL-terminate */
1302 NameString
.MaximumLength
++;
1303 NameBuffer
[NameString
.Length
/ sizeof(WCHAR
)] = 0;
1305 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1309 DPRINT("Module '%wZ' not loaded yet\n", &DriverName
);
1310 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
1311 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1312 RtlInitUnicodeString(&NameString
, NameBuffer
);
1313 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1315 if (!NT_SUCCESS(Status
))
1317 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
1318 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1319 RtlInitUnicodeString(&NameString
, NameBuffer
);
1320 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1321 if (!NT_SUCCESS(Status
))
1323 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName
, Status
);
1327 RtlFreeUnicodeString(&DriverName
);
1332 LdrPEGetExportByName(PVOID BaseAddress
,
1336 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1337 PDWORD
* ExFunctions
;
1339 USHORT
* ExOrdinals
;
1345 ULONG ExportDirSize
;
1347 DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1349 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData(BaseAddress
,
1351 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1353 if (ExportDir
== NULL
)
1355 DPRINT1("LdrPEGetExportByName(): no export directory!\n");
1360 /* The symbol names may be missing entirely */
1361 if (ExportDir
->AddressOfNames
== 0)
1363 DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
1368 * Get header pointers
1370 ExNames
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
1371 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
1372 ExFunctions
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
1375 * Check the hint first
1377 if (Hint
< ExportDir
->NumberOfNames
)
1379 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1380 if (strcmp(ExName
, SymbolName
) == 0)
1382 Ordinal
= ExOrdinals
[Hint
];
1383 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1384 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1385 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1387 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1388 Function
= LdrPEFixupForward((PCHAR
)Function
);
1389 if (Function
== NULL
)
1391 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1395 if (Function
!= NULL
)
1403 * Try a binary search first
1406 maxn
= ExportDir
->NumberOfNames
- 1;
1407 while (minn
<= maxn
)
1412 mid
= (minn
+ maxn
) / 2;
1414 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1415 res
= strcmp(ExName
, SymbolName
);
1418 Ordinal
= ExOrdinals
[mid
];
1419 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1420 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1421 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1423 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1424 Function
= LdrPEFixupForward((PCHAR
)Function
);
1425 if (Function
== NULL
)
1427 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1431 if (Function
!= NULL
)
1436 else if (minn
== maxn
)
1438 DPRINT("LdrPEGetExportByName(): binary search failed\n");
1452 * Fall back on a linear search
1454 DPRINT("LdrPEGetExportByName(): Falling back on a linear search of export table\n");
1455 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++)
1457 ExName
= RVA(BaseAddress
, ExNames
[i
]);
1458 if (strcmp(ExName
,SymbolName
) == 0)
1460 Ordinal
= ExOrdinals
[i
];
1461 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1462 DPRINT("%x %x %x\n", Function
, ExportDir
, ExportDir
+ ExportDirSize
);
1463 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1464 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1466 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1467 Function
= LdrPEFixupForward((PCHAR
)Function
);
1469 if (Function
== NULL
)
1476 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1481 LdrPEGetExportByOrdinal (PVOID BaseAddress
,
1484 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1485 ULONG ExportDirSize
;
1486 PDWORD
* ExFunctions
;
1489 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData (BaseAddress
,
1491 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1494 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1495 ExportDir
->AddressOfFunctions
);
1496 DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
1498 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
]));
1500 Function
= 0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1501 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1504 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1505 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1507 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1508 Function
= LdrPEFixupForward((PCHAR
)Function
);
1515 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
1516 PMODULE_OBJECT ImportedModule
,
1517 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
)
1519 PVOID
* ImportAddressList
;
1520 PULONG FunctionNameList
;
1523 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->dwRVAModuleName
== 0)
1525 return STATUS_UNSUCCESSFUL
;
1528 /* Get the import address list. */
1529 ImportAddressList
= (PVOID
*)(DriverBase
+ ImportModuleDirectory
->dwRVAFunctionAddressList
);
1531 /* Get the list of functions to import. */
1532 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1534 FunctionNameList
= (PULONG
) (DriverBase
+ ImportModuleDirectory
->dwRVAFunctionNameList
);
1538 FunctionNameList
= (PULONG
)(DriverBase
+ ImportModuleDirectory
->dwRVAFunctionAddressList
);
1541 /* Walk through function list and fixup addresses. */
1542 while (*FunctionNameList
!= 0L)
1544 if ((*FunctionNameList
) & 0x80000000)
1546 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1547 *ImportAddressList
= LdrPEGetExportByOrdinal(ImportedModule
->Base
, Ordinal
);
1548 if ((*ImportAddressList
) == NULL
)
1550 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullName
);
1551 return STATUS_UNSUCCESSFUL
;
1556 IMAGE_IMPORT_BY_NAME
*pe_name
;
1557 pe_name
= RVA(DriverBase
, *FunctionNameList
);
1558 *ImportAddressList
= LdrPEGetExportByName(ImportedModule
->Base
, pe_name
->Name
, pe_name
->Hint
);
1559 if ((*ImportAddressList
) == NULL
)
1561 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullName
);
1562 return STATUS_UNSUCCESSFUL
;
1565 ImportAddressList
++;
1568 return STATUS_SUCCESS
;
1572 LdrPEFixupImports(PMODULE_OBJECT Module
)
1574 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1576 PMODULE_OBJECT ImportedModule
;
1579 /* Process each import module */
1580 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1581 RtlImageDirectoryEntryToData(Module
->Base
,
1583 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1585 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1586 while (ImportModuleDirectory
->dwRVAModuleName
)
1588 /* Check to make sure that import lib is kernel */
1589 ImportedName
= (PCHAR
) Module
->Base
+ ImportModuleDirectory
->dwRVAModuleName
;
1591 Status
= LdrPEGetOrLoadModule(Module
, ImportedName
, &ImportedModule
);
1592 if (!NT_SUCCESS(Status
))
1597 Status
= LdrPEProcessImportDirectoryEntry(Module
->Base
, ImportedModule
, ImportModuleDirectory
);
1598 if (!NT_SUCCESS(Status
))
1603 ImportModuleDirectory
++;
1605 return STATUS_SUCCESS
;