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') /* drvm */
45 #define TAG_MODULE_OBJECT TAG('k', 'l', 'm', 'o') /* klmo - kernel ldr module object */
46 #define TAG_LDR_WSTR TAG('k', 'l', 'w', 's') /* klws - kernel ldr wide string */
47 #define TAG_MODULE_TEXT_SECTION TAG('k', 'l', 'm', 't') /* klmt - kernel ldr module text */
50 #define HIWORD(X) ((WORD) (((DWORD) (X) >> 16) & 0xFFFF))
53 #define LOWORD(X) ((WORD) (X))
56 /* FORWARD DECLARATIONS ******************************************************/
61 PUNICODE_STRING ModuleName
,
62 PMODULE_OBJECT
*ModuleObject
);
65 LdrpBuildModuleBaseName (
66 PUNICODE_STRING BaseName
,
67 PUNICODE_STRING FullName
);
70 LdrpCompareModuleNames (
71 IN PUNICODE_STRING String1
,
72 IN PUNICODE_STRING String2
);
75 /* PE Driver load support */
79 PUNICODE_STRING FileName
,
80 PMODULE_OBJECT
*ModuleObject
);
83 LdrPEGetExportByName (
89 LdrPEFixupForward ( PCHAR ForwardName
);
92 LdrPEPerformRelocations (
97 LdrPEFixupImports ( PMODULE_OBJECT Module
);
99 /* FUNCTIONS *****************************************************************/
102 LdrInitDebug ( PLOADER_MODULE Module
, PWCH Name
)
104 PLIST_ENTRY current_entry
;
105 MODULE_TEXT_SECTION
* current
;
107 current_entry
= ModuleTextListHead
.Flink
;
108 while (current_entry
!= &ModuleTextListHead
)
111 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
112 if (wcscmp(current
->Name
, Name
) == 0)
116 current_entry
= current_entry
->Flink
;
119 if (current_entry
== &ModuleTextListHead
)
128 PIMAGE_NT_HEADERS NtHeader
;
129 PIMAGE_SECTION_HEADER SectionList
;
131 InitializeListHead(&ModuleTextListHead
);
133 /* Setup ntoskrnl.exe text section */
135 * This isn't the base of the text segment, but the start of the
136 * full image (in memory)
137 * Also, the Length field isn't set to the length of the segment,
138 * but is more like the offset, from the image base, to the end
141 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
142 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
143 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
144 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
145 + SectionList
[0].VirtualAddress
;
146 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
147 NtoskrnlTextSection
.OptionalHeader
= OPTHDROFFSET(KERNEL_BASE
);
148 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
150 /* Setup hal.dll text section */
151 /* Same comment as above applies */
152 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
153 SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
154 LdrHalTextSection
.Base
= LdrHalBase
;
155 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
156 + SectionList
[0].VirtualAddress
;
157 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
158 LdrHalTextSection
.OptionalHeader
= OPTHDROFFSET(LdrHalBase
);
159 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
161 /* Hook for KDB on initialization of the loader. */
162 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection
, &LdrHalTextSection
);
166 LdrInitModuleManagement ( VOID
)
168 PIMAGE_NT_HEADERS NtHeader
;
170 /* Initialize the module list and spinlock */
171 InitializeListHead(&ModuleListHead
);
172 KeInitializeSpinLock(&ModuleListLock
);
174 /* Initialize ModuleObject for NTOSKRNL */
175 RtlZeroMemory(&NtoskrnlModuleObject
, sizeof(MODULE_OBJECT
));
176 NtoskrnlModuleObject
.Base
= (PVOID
) KERNEL_BASE
;
177 NtoskrnlModuleObject
.Flags
= MODULE_FLAG_PE
;
178 RtlInitUnicodeString(&NtoskrnlModuleObject
.FullName
, KERNEL_MODULE_NAME
);
179 LdrpBuildModuleBaseName(&NtoskrnlModuleObject
.BaseName
, &NtoskrnlModuleObject
.FullName
);
181 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
182 NtoskrnlModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
183 NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
184 NtoskrnlModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
185 NtoskrnlModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) NtoskrnlModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
186 DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject
, NtoskrnlModuleObject
.EntryPoint
);
187 NtoskrnlModuleObject
.Length
= NtoskrnlModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
188 NtoskrnlModuleObject
.TextSection
= &NtoskrnlTextSection
;
190 InsertTailList(&ModuleListHead
,
191 &NtoskrnlModuleObject
.ListEntry
);
193 /* Initialize ModuleObject for HAL */
194 RtlZeroMemory(&HalModuleObject
, sizeof(MODULE_OBJECT
));
195 HalModuleObject
.Base
= (PVOID
) LdrHalBase
;
196 HalModuleObject
.Flags
= MODULE_FLAG_PE
;
198 RtlInitUnicodeString(&HalModuleObject
.FullName
, HAL_MODULE_NAME
);
199 LdrpBuildModuleBaseName(&HalModuleObject
.BaseName
, &HalModuleObject
.FullName
);
201 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
202 HalModuleObject
.Image
.PE
.FileHeader
= &NtHeader
->FileHeader
;
203 HalModuleObject
.Image
.PE
.OptionalHeader
= &NtHeader
->OptionalHeader
;
204 HalModuleObject
.Image
.PE
.SectionList
= IMAGE_FIRST_SECTION(NtHeader
);
205 HalModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) HalModuleObject
.Base
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
206 DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject
, HalModuleObject
.EntryPoint
);
207 HalModuleObject
.Length
= HalModuleObject
.Image
.PE
.OptionalHeader
->SizeOfImage
;
208 HalModuleObject
.TextSection
= &LdrHalTextSection
;
210 InsertTailList(&ModuleListHead
,
211 &HalModuleObject
.ListEntry
);
216 PUNICODE_STRING DriverName
,
218 PVOID
*SectionPointer
,
220 PVOID
*ExportSectionPointer
)
222 PMODULE_OBJECT ModuleObject
;
225 ModuleObject
= LdrGetModuleObject(DriverName
);
226 if (ModuleObject
== NULL
)
228 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
229 if (!NT_SUCCESS(Status
))
236 *ModuleBase
= ModuleObject
->Base
;
238 //if (SectionPointer)
239 // *SectionPointer = ModuleObject->
242 *EntryPoint
= ModuleObject
->EntryPoint
;
244 //if (ExportSectionPointer)
245 // *ExportSectionPointer = ModuleObject->
247 return(STATUS_SUCCESS
);
252 LdrpUnloadImage ( PVOID ModuleBase
)
254 return(STATUS_NOT_IMPLEMENTED
);
259 LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName
)
261 PDRIVER_INITIALIZE DriverEntry
;
262 PMODULE_OBJECT ModuleObject
;
265 ModuleObject
= LdrGetModuleObject(ModuleName
);
266 if (ModuleObject
!= NULL
)
268 return(STATUS_IMAGE_ALREADY_LOADED
);
271 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
272 if (!NT_SUCCESS(Status
))
277 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
279 Status
= DriverEntry(NULL
, NULL
);
280 if (!NT_SUCCESS(Status
))
282 LdrUnloadModule(ModuleObject
);
291 PUNICODE_STRING Filename
,
292 PMODULE_OBJECT
*ModuleObject
)
294 PVOID ModuleLoadBase
;
297 OBJECT_ATTRIBUTES ObjectAttributes
;
298 PMODULE_OBJECT Module
;
299 FILE_STANDARD_INFORMATION FileStdInfo
;
300 IO_STATUS_BLOCK IoStatusBlock
;
302 *ModuleObject
= NULL
;
304 DPRINT("Loading Module %wZ...\n", Filename
);
306 /* Open the Module */
307 InitializeObjectAttributes(&ObjectAttributes
,
309 OBJ_CASE_INSENSITIVE
,
313 Status
= ZwOpenFile(&FileHandle
,
318 FILE_SYNCHRONOUS_IO_NONALERT
);
320 if (!NT_SUCCESS(Status
))
322 CPRINT("Could not open module file: %wZ\n", Filename
);
327 /* Get the size of the file */
328 Status
= ZwQueryInformationFile(FileHandle
,
332 FileStandardInformation
);
333 if (!NT_SUCCESS(Status
))
335 CPRINT("Could not get file size\n");
341 /* Allocate nonpageable memory for driver */
342 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
343 FileStdInfo
.EndOfFile
.u
.LowPart
,
345 if (ModuleLoadBase
== NULL
)
347 CPRINT("Could not allocate memory for module");
349 return(STATUS_INSUFFICIENT_RESOURCES
);
353 /* Load driver into memory chunk */
354 Status
= ZwReadFile(FileHandle
,
358 FileStdInfo
.EndOfFile
.u
.LowPart
,
360 if (!NT_SUCCESS(Status
))
362 CPRINT("Could not read module file into memory");
363 ExFreePool(ModuleLoadBase
);
371 Status
= LdrProcessModule(ModuleLoadBase
,
374 if (!NT_SUCCESS(Status
))
376 CPRINT("Could not process module\n");
377 ExFreePool(ModuleLoadBase
);
382 ExFreePool(ModuleLoadBase
);
384 *ModuleObject
= Module
;
386 /* Hook for KDB on loading a driver. */
387 KDB_LOADDRIVER_HOOK(Filename
, Module
);
389 return(STATUS_SUCCESS
);
394 LdrUnloadModule ( PMODULE_OBJECT ModuleObject
)
398 /* Remove the module from the module list */
399 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
400 RemoveEntryList(&ModuleObject
->ListEntry
);
401 KeReleaseSpinLock(&ModuleListLock
, Irql
);
403 /* Hook for KDB on unloading a driver. */
404 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
406 /* Free text section */
407 if (ModuleObject
->TextSection
!= NULL
)
409 ExFreePool(ModuleObject
->TextSection
->Name
);
410 RemoveEntryList(&ModuleObject
->TextSection
->ListEntry
);
411 ExFreePool(ModuleObject
->TextSection
);
412 ModuleObject
->TextSection
= NULL
;
415 /* Free module section */
416 // MmFreeSection(ModuleObject->Base);
418 ExFreePool(ModuleObject
->FullName
.Buffer
);
419 ExFreePool(ModuleObject
);
421 return(STATUS_SUCCESS
);
427 PVOID ModuleLoadBase
,
428 PUNICODE_STRING ModuleName
,
429 PMODULE_OBJECT
*ModuleObject
)
431 PIMAGE_DOS_HEADER PEDosHeader
;
433 /* If MZ header exists */
434 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
435 if (PEDosHeader
->e_magic
== IMAGE_DOS_SIGNATURE
&& PEDosHeader
->e_lfanew
!= 0L)
437 return LdrPEProcessModule(ModuleLoadBase
,
442 CPRINT("Module wasn't PE\n");
443 return STATUS_UNSUCCESSFUL
;
447 LdrpQueryModuleInformation (
452 PLIST_ENTRY current_entry
;
453 PMODULE_OBJECT current
;
454 ULONG ModuleCount
= 0;
455 PSYSTEM_MODULE_INFORMATION Smi
;
456 ANSI_STRING AnsiName
;
460 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
462 /* calculate required size */
463 current_entry
= ModuleListHead
.Flink
;
464 while (current_entry
!= (&ModuleListHead
))
467 current_entry
= current_entry
->Flink
;
470 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
471 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
475 KeReleaseSpinLock(&ModuleListLock
, Irql
);
476 return(STATUS_INFO_LENGTH_MISMATCH
);
479 /* fill the buffer */
480 memset(Buffer
, '=', Size
);
482 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
483 Smi
->Count
= ModuleCount
;
486 current_entry
= ModuleListHead
.Flink
;
487 while (current_entry
!= (&ModuleListHead
))
489 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
491 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
492 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
493 Smi
->Module
[ModuleCount
].Base
= current
->Base
;
494 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
495 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
496 Smi
->Module
[ModuleCount
].Index
= (USHORT
)ModuleCount
;
497 Smi
->Module
[ModuleCount
].NameLength
= 0;
498 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
501 AnsiName
.MaximumLength
= 256;
502 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
503 RtlUnicodeStringToAnsiString(&AnsiName
,
507 p
= strrchr(AnsiName
.Buffer
, '\\');
510 Smi
->Module
[ModuleCount
].PathLength
= 0;
515 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
519 current_entry
= current_entry
->Flink
;
522 KeReleaseSpinLock(&ModuleListLock
, Irql
);
524 return(STATUS_SUCCESS
);
529 LdrpBuildModuleBaseName (
530 PUNICODE_STRING BaseName
,
531 PUNICODE_STRING FullName
)
535 DPRINT("LdrpBuildModuleBaseName()\n");
536 DPRINT("FullName %wZ\n", FullName
);
538 p
= wcsrchr(FullName
->Buffer
, L
'\\');
541 p
= FullName
->Buffer
;
550 RtlInitUnicodeString(BaseName
, p
);
555 LdrpCompareModuleNames (
556 IN PUNICODE_STRING String1
,
557 IN PUNICODE_STRING String2
)
563 if (String1
&& String2
)
565 /* Search String1 for last path component */
566 len1
= String1
->Length
/ sizeof(WCHAR
);
567 s1
= String1
->Buffer
;
568 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
572 if (i
== String1
->Length
- sizeof(WCHAR
))
580 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
585 /* Search String2 for last path component */
586 len2
= String2
->Length
/ sizeof(WCHAR
);
587 s2
= String2
->Buffer
;
588 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
592 if (i
== String2
->Length
- sizeof(WCHAR
))
600 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
605 /* Compare last path components */
610 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
611 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
612 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
614 if (!c1
|| !c2
|| c1
!= c2
)
624 LdrGetModuleObject ( PUNICODE_STRING ModuleName
)
626 PMODULE_OBJECT Module
;
630 DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName
);
632 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
634 Entry
= ModuleListHead
.Flink
;
635 while (Entry
!= &ModuleListHead
)
637 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
639 DPRINT("Comparing %wZ and %wZ\n",
643 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
645 DPRINT("Module %wZ\n", &Module
->BaseName
);
646 KeReleaseSpinLock(&ModuleListLock
, Irql
);
650 Entry
= Entry
->Flink
;
653 KeReleaseSpinLock(&ModuleListLock
, Irql
);
655 DPRINT("Could not find module '%wZ'\n", ModuleName
);
661 /* ---------------------------------------------- PE Module support */
664 LdrLookupPageProtection (
667 PIMAGE_FILE_HEADER PEFileHeader
,
668 PIMAGE_SECTION_HEADER PESectionHeaders
)
670 BOOLEAN Write
= FALSE
;
671 BOOLEAN Execute
= FALSE
;
672 ULONG Characteristics
;
677 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& (!Write
|| !Execute
); Idx
++)
679 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
680 if (!(Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
682 Length
= max(PESectionHeaders
[Idx
].Misc
.VirtualSize
, PESectionHeaders
[Idx
].SizeOfRawData
);
683 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
684 if (BaseAddress
< (PVOID
)((ULONG_PTR
)PageStart
+ PAGE_SIZE
) &&
685 PageStart
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
))
687 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
691 if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
698 if (Write
&& Execute
)
700 return PAGE_EXECUTE_READWRITE
;
704 return PAGE_EXECUTE_READ
;
708 return PAGE_READWRITE
;
712 return PAGE_READONLY
;
718 PVOID ModuleLoadBase
,
719 PUNICODE_STRING FileName
,
720 PMODULE_OBJECT
*ModuleObject
)
722 unsigned int DriverSize
, Idx
;
725 PIMAGE_DOS_HEADER PEDosHeader
;
726 PIMAGE_NT_HEADERS PENtHeaders
;
727 PIMAGE_SECTION_HEADER PESectionHeaders
;
728 PMODULE_OBJECT CreatedModuleObject
;
729 MODULE_TEXT_SECTION
* ModuleTextSection
;
733 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
735 /* Get header pointers */
736 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
737 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
738 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
741 /* Check file magic numbers */
742 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
744 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
745 return STATUS_UNSUCCESSFUL
;
747 if (PEDosHeader
->e_lfanew
== 0)
749 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
750 return STATUS_UNSUCCESSFUL
;
752 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
754 CPRINT("Incorrect PE magic: %08x\n", PENtHeaders
->Signature
);
755 return STATUS_UNSUCCESSFUL
;
757 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
759 CPRINT("Incorrect Architechture: %04x\n", PENtHeaders
->FileHeader
.Machine
);
760 return STATUS_UNSUCCESSFUL
;
764 /* FIXME: if image is fixed-address load, then fail */
766 /* FIXME: check/verify OS version number */
768 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
769 PENtHeaders
->OptionalHeader
.Magic
,
770 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
771 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
772 DPRINT("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
774 /* Determine the size of the module */
776 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
778 if (!(PESectionHeaders
[Idx
].Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
780 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
781 DriverSize
= max(DriverSize
, CurrentSize
);
784 DriverSize
= ROUND_UP(DriverSize
, PENtHeaders
->OptionalHeader
.SectionAlignment
);
785 DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize
, PENtHeaders
->OptionalHeader
.SizeOfImage
);
787 /* Allocate a virtual section for the module */
789 DriverBase
= MmAllocateSection(DriverSize
, DriverBase
);
792 CPRINT("Failed to allocate a virtual section for driver\n");
793 return STATUS_UNSUCCESSFUL
;
795 DbgPrint("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
797 /* Copy headers over */
798 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
800 /* Copy image sections into virtual section */
801 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
803 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
804 /* Copy current section into current offset of virtual section */
805 if (CurrentSize
<= DriverSize
&&
806 PESectionHeaders
[Idx
].SizeOfRawData
)
808 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
809 PESectionHeaders
[Idx
].VirtualAddress
+ (ULONG_PTR
)DriverBase
);
810 memcpy((PVOID
)((ULONG_PTR
)DriverBase
+ PESectionHeaders
[Idx
].VirtualAddress
),
811 (PVOID
)((ULONG_PTR
)ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
812 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
813 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
817 /* Perform relocation fixups */
818 Status
= LdrPEPerformRelocations(DriverBase
, DriverSize
);
819 if (!NT_SUCCESS(Status
))
821 // MmFreeSection(DriverBase);
825 /* Create the module */
826 CreatedModuleObject
= ExAllocatePoolWithTag (
827 NonPagedPool
, sizeof(MODULE_OBJECT
), TAG_MODULE_OBJECT
);
828 if (CreatedModuleObject
== NULL
)
830 // MmFreeSection(DriverBase);
831 return STATUS_INSUFFICIENT_RESOURCES
;
834 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
836 /* Initialize ModuleObject data */
837 CreatedModuleObject
->Base
= DriverBase
;
838 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
840 CreatedModuleObject
->FullName
.Length
= 0;
841 CreatedModuleObject
->FullName
.MaximumLength
= FileName
->Length
+ sizeof(UNICODE_NULL
);
842 CreatedModuleObject
->FullName
.Buffer
=
843 ExAllocatePoolWithTag(PagedPool
, CreatedModuleObject
->FullName
.MaximumLength
, TAG_LDR_WSTR
);
844 if (CreatedModuleObject
->FullName
.Buffer
== NULL
)
846 ExFreePool(CreatedModuleObject
);
847 // MmFreeSection(DriverBase);
848 return STATUS_INSUFFICIENT_RESOURCES
;
851 RtlCopyUnicodeString(&CreatedModuleObject
->FullName
, FileName
);
852 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
853 &CreatedModuleObject
->FullName
);
855 CreatedModuleObject
->EntryPoint
=
856 (PVOID
)((ULONG_PTR
)DriverBase
+
857 PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
858 CreatedModuleObject
->Length
= DriverSize
;
859 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
861 CreatedModuleObject
->Image
.PE
.FileHeader
=
862 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
864 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
865 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
866 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
867 sizeof(IMAGE_FILE_HEADER
));
868 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
869 CreatedModuleObject
->Image
.PE
.SectionList
=
870 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
871 sizeof(IMAGE_FILE_HEADER
) + CreatedModuleObject
->Image
.PE
.FileHeader
->SizeOfOptionalHeader
);
872 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
874 /* Perform import fixups */
875 Status
= LdrPEFixupImports(CreatedModuleObject
);
876 if (!NT_SUCCESS(Status
))
878 // MmFreeSection(DriverBase);
879 ExFreePool(CreatedModuleObject
->FullName
.Buffer
);
880 ExFreePool(CreatedModuleObject
);
884 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
885 /* Set the protections for the various parts of the driver */
886 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
888 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
893 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
894 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
895 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
897 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
901 * This driver modifies a string in the first page of the text section while initialising.
903 if (0 == _wcsicmp(L
"fireport.sys", FileName
->Buffer
))
905 Protect
= PAGE_EXECUTE_READWRITE
;
908 if (PageAddress
< DriverBase
+ DriverSize
)
910 MmSetPageProtect(NULL
, PageAddress
, Protect
);
913 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
915 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
917 Protect
= PAGE_EXECUTE_READWRITE
;
921 Protect
= PAGE_EXECUTE_READ
;
924 else if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
926 Protect
= PAGE_READWRITE
;
930 Protect
= PAGE_READONLY
;
932 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
933 while ((ULONG_PTR
)PageAddress
+ PAGE_SIZE
< (ULONG_PTR
)BaseAddress
+ Length
)
935 if (PageAddress
< DriverBase
+ DriverSize
)
937 MmSetPageProtect(NULL
, PageAddress
, Protect
);
939 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
941 if (PageAddress
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
) &&
942 PageAddress
< DriverBase
+ DriverSize
)
944 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
945 MmSetPageProtect(NULL
, PageAddress
, Protect
);
950 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
951 InsertTailList(&ModuleListHead
,
952 &CreatedModuleObject
->ListEntry
);
953 KeReleaseSpinLock(&ModuleListLock
, Irql
);
956 ModuleTextSection
= ExAllocatePoolWithTag (
958 sizeof(MODULE_TEXT_SECTION
),
959 TAG_MODULE_TEXT_SECTION
);
960 ASSERT(ModuleTextSection
);
961 RtlZeroMemory(ModuleTextSection
, sizeof(MODULE_TEXT_SECTION
));
962 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
963 ModuleTextSection
->Length
= DriverSize
;
964 ModuleTextSection
->Name
= ExAllocatePoolWithTag (
966 (CreatedModuleObject
->BaseName
.Length
+ 1) * sizeof(WCHAR
),
968 RtlCopyMemory(ModuleTextSection
->Name
,
969 CreatedModuleObject
->BaseName
.Buffer
,
970 CreatedModuleObject
->BaseName
.Length
);
971 ModuleTextSection
->Name
[CreatedModuleObject
->BaseName
.Length
/ sizeof(WCHAR
)] = 0;
972 ModuleTextSection
->OptionalHeader
=
973 CreatedModuleObject
->Image
.PE
.OptionalHeader
;
974 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
976 CreatedModuleObject
->TextSection
= ModuleTextSection
;
978 *ModuleObject
= CreatedModuleObject
;
980 DPRINT("Loading Module %wZ...\n", FileName
);
982 if (KdDebuggerEnabled
&& (KdDebugState
& KD_DEBUG_GDB
))
984 DPRINT("Module %wZ loaded at 0x%.08x.\n",
985 FileName
, CreatedModuleObject
->Base
);
988 return STATUS_SUCCESS
;
993 LdrSafePEProcessModule (
994 PVOID ModuleLoadBase
,
996 PVOID ImportModuleBase
,
1001 PIMAGE_DOS_HEADER PEDosHeader
;
1002 PIMAGE_NT_HEADERS PENtHeaders
;
1003 PIMAGE_SECTION_HEADER PESectionHeaders
;
1006 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1008 /* Get header pointers */
1009 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1010 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
1011 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
1014 /* Check file magic numbers */
1015 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
1019 if (PEDosHeader
->e_lfanew
== 0)
1023 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
1027 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
1032 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1033 PENtHeaders
->OptionalHeader
.Magic
,
1034 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
1035 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
1036 ps("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1038 /* Determine the size of the module */
1039 *DriverSize
= PENtHeaders
->OptionalHeader
.SizeOfImage
;
1040 ps("DriverSize %x\n",*DriverSize
);
1042 /* Copy headers over */
1043 if (DriverBase
!= ModuleLoadBase
)
1045 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1048 ps("Hdr: 0x%X\n", PENtHeaders
);
1049 ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
1050 ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders
->FileHeader
.NumberOfSections
);
1052 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1053 address as it is mapped */
1054 if (DriverBase
!= ModuleLoadBase
)
1058 /* Copy image sections into virtual section */
1059 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1061 PIMAGE_SECTION_HEADER Section
= &PESectionHeaders
[Idx
];
1062 // Copy current section into current offset of virtual section
1063 if (Section
->SizeOfRawData
)
1065 // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1066 // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1067 memcpy(Section
->VirtualAddress
+ (char*)DriverBase
,
1068 Section
->PointerToRawData
+ (char*)ModuleLoadBase
,
1069 Section
->Misc
.VirtualSize
> Section
->SizeOfRawData
? Section
->SizeOfRawData
: Section
->Misc
.VirtualSize
);
1071 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
)
1073 memset(Section
->VirtualAddress
+ Section
->SizeOfRawData
+ (char*)DriverBase
,
1075 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
1077 CurrentSize
+= ROUND_UP(Section
->Misc
.VirtualSize
,
1078 PENtHeaders
->OptionalHeader
.SectionAlignment
);
1081 /* Perform relocation fixups */
1082 Status
= LdrPEPerformRelocations(DriverBase
, *DriverSize
);
1083 if (!NT_SUCCESS(Status
))
1089 /* Perform import fixups */
1090 Status
= LdrPEFixupImports(DriverBase
== ModuleLoadBase
? &NtoskrnlModuleObject
: &HalModuleObject
);
1091 if (!NT_SUCCESS(Status
))
1096 /* Set the page protection for the virtual sections */
1097 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
1098 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1100 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1105 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1106 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
1107 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1109 if (Characteristics
& IMAGE_SCN_MEM_EXECUTE
)
1111 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1113 Protect
= PAGE_EXECUTE_READWRITE
;
1117 Protect
= PAGE_EXECUTE_READ
;
1120 else if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1122 Protect
= PAGE_READWRITE
;
1126 Protect
= PAGE_READONLY
;
1128 while ((ULONG_PTR
)PageAddress
< (ULONG_PTR
)BaseAddress
+ Length
)
1130 MmSetPageProtect(NULL
, PageAddress
, Protect
);
1131 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
1133 if (DriverBase
== ModuleLoadBase
&&
1134 Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
1136 /* For ntoskrnl, we must stop after the bss section */
1146 LdrPEFixupForward ( PCHAR ForwardName
)
1148 CHAR NameBuffer
[128];
1149 UNICODE_STRING ModuleName
;
1151 PMODULE_OBJECT ModuleObject
;
1153 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1155 strcpy(NameBuffer
, ForwardName
);
1156 p
= strchr(NameBuffer
, '.');
1164 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1166 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1168 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1169 RtlFreeUnicodeString(&ModuleName
);
1171 DPRINT("ModuleObject: %p\n", ModuleObject
);
1173 if (ModuleObject
== NULL
)
1175 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1178 return LdrPEGetExportByName(ModuleObject
->Base
, (PUCHAR
)(p
+1), 0xffff);
1182 LdrPEPerformRelocations (
1186 PIMAGE_NT_HEADERS NtHeaders
;
1187 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1188 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1190 PVOID Address
, MaxAddress
;
1198 NtHeaders
= RtlImageNtHeader(DriverBase
);
1200 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1202 return STATUS_UNSUCCESSFUL
;
1205 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1207 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1209 return STATUS_SUCCESS
;
1212 Delta
= (ULONG_PTR
)DriverBase
- NtHeaders
->OptionalHeader
.ImageBase
;
1213 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)DriverBase
+ RelocationDDir
->VirtualAddress
);
1214 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
1215 MaxAddress
= DriverBase
+ DriverSize
;
1217 while (RelocationDir
< RelocationEnd
&&
1218 RelocationDir
->SizeOfBlock
> 0)
1220 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
1221 Address
= DriverBase
+ RelocationDir
->VirtualAddress
;
1222 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1224 for (i
= 0; i
< Count
; i
++)
1226 Offset
= *TypeOffset
& 0xFFF;
1227 Type
= *TypeOffset
>> 12;
1228 ShortPtr
= (PUSHORT
)(Address
+ Offset
);
1230 /* Don't relocate after the end of the loaded driver */
1231 if ((PVOID
)ShortPtr
>= MaxAddress
)
1237 * Don't relocate within the relocation section itself.
1238 * GCC/LD generates sometimes relocation records for the relecotion section.
1239 * This is a bug in GCC/LD.
1241 if ((ULONG_PTR
)ShortPtr
< (ULONG_PTR
)RelocationDir
||
1242 (ULONG_PTR
)ShortPtr
>= (ULONG_PTR
)RelocationEnd
)
1246 case IMAGE_REL_BASED_ABSOLUTE
:
1249 case IMAGE_REL_BASED_HIGH
:
1250 *ShortPtr
+= HIWORD(Delta
);
1253 case IMAGE_REL_BASED_LOW
:
1254 *ShortPtr
+= LOWORD(Delta
);
1257 case IMAGE_REL_BASED_HIGHLOW
:
1258 LongPtr
= (PULONG
)ShortPtr
;
1262 case IMAGE_REL_BASED_HIGHADJ
:
1263 case IMAGE_REL_BASED_MIPS_JMPADDR
:
1265 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
1266 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, *TypeOffset
);
1267 return STATUS_UNSUCCESSFUL
;
1272 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
1275 return STATUS_SUCCESS
;
1279 LdrPEGetOrLoadModule (
1280 PMODULE_OBJECT Module
,
1282 PMODULE_OBJECT
* ImportedModule
)
1284 UNICODE_STRING DriverName
;
1285 UNICODE_STRING NameString
;
1286 WCHAR NameBuffer
[PATH_MAX
];
1287 NTSTATUS Status
= STATUS_SUCCESS
;
1289 if (0 == _stricmp(ImportedName
, "ntoskrnl") ||
1290 0 == _stricmp(ImportedName
, "ntoskrnl.exe"))
1292 *ImportedModule
= &NtoskrnlModuleObject
;
1293 return STATUS_SUCCESS
;
1296 if (0 == _stricmp(ImportedName
, "hal") ||
1297 0 == _stricmp(ImportedName
, "hal.dll"))
1299 *ImportedModule
= &HalModuleObject
;
1300 return STATUS_SUCCESS
;
1303 RtlCreateUnicodeStringFromAsciiz (&DriverName
, ImportedName
);
1304 DPRINT("Import module: %wZ\n", &DriverName
);
1306 *ImportedModule
= LdrGetModuleObject(&DriverName
);
1307 if (*ImportedModule
== NULL
)
1312 PathEnd
= wcsrchr(Module
->FullName
.Buffer
, L
'\\');
1313 if (NULL
!= PathEnd
)
1315 PathLength
= (PathEnd
- Module
->FullName
.Buffer
+ 1) * sizeof(WCHAR
);
1316 RtlCopyMemory(NameBuffer
, Module
->FullName
.Buffer
, PathLength
);
1317 RtlCopyMemory(NameBuffer
+ (PathLength
/ sizeof(WCHAR
)), DriverName
.Buffer
, DriverName
.Length
);
1318 NameString
.Buffer
= NameBuffer
;
1319 NameString
.MaximumLength
= NameString
.Length
= PathLength
+ DriverName
.Length
;
1321 /* NULL-terminate */
1322 NameString
.MaximumLength
++;
1323 NameBuffer
[NameString
.Length
/ sizeof(WCHAR
)] = 0;
1325 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1329 DPRINT("Module '%wZ' not loaded yet\n", &DriverName
);
1330 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
1331 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1332 RtlInitUnicodeString(&NameString
, NameBuffer
);
1333 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1335 if (!NT_SUCCESS(Status
))
1337 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
1338 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1339 RtlInitUnicodeString(&NameString
, NameBuffer
);
1340 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1341 if (!NT_SUCCESS(Status
))
1343 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName
, Status
);
1347 RtlFreeUnicodeString(&DriverName
);
1352 LdrPEGetExportByName (
1357 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1358 PDWORD
* ExFunctions
;
1360 USHORT
* ExOrdinals
;
1366 ULONG ExportDirSize
;
1368 DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1370 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData(BaseAddress
,
1372 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1374 if (ExportDir
== NULL
)
1376 DPRINT1("LdrPEGetExportByName(): no export directory!\n");
1381 /* The symbol names may be missing entirely */
1382 if (ExportDir
->AddressOfNames
== 0)
1384 DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
1389 * Get header pointers
1391 ExNames
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
1392 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
1393 ExFunctions
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
1396 * Check the hint first
1398 if (Hint
< ExportDir
->NumberOfNames
)
1400 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1401 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1403 Ordinal
= ExOrdinals
[Hint
];
1404 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1405 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1406 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1408 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1409 Function
= LdrPEFixupForward((PCHAR
)Function
);
1410 if (Function
== NULL
)
1412 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1416 if (Function
!= NULL
)
1424 * Try a binary search first
1427 maxn
= ExportDir
->NumberOfNames
- 1;
1428 while (minn
<= maxn
)
1433 mid
= (minn
+ maxn
) / 2;
1435 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1436 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1439 Ordinal
= ExOrdinals
[mid
];
1440 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1441 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1442 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1444 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1445 Function
= LdrPEFixupForward((PCHAR
)Function
);
1446 if (Function
== NULL
)
1448 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1452 if (Function
!= NULL
)
1457 else if (minn
== maxn
)
1459 DPRINT("LdrPEGetExportByName(): binary search failed\n");
1473 * Fall back on a linear search
1475 DPRINT("LdrPEGetExportByName(): Falling back on a linear search of export table\n");
1476 for (i
= 0; i
< ExportDir
->NumberOfNames
; i
++)
1478 ExName
= RVA(BaseAddress
, ExNames
[i
]);
1479 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1481 Ordinal
= ExOrdinals
[i
];
1482 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1483 DPRINT("%x %x %x\n", Function
, ExportDir
, ExportDir
+ ExportDirSize
);
1484 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1485 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1487 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1488 Function
= LdrPEFixupForward((PCHAR
)Function
);
1490 if (Function
== NULL
)
1497 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1502 LdrPEGetExportByOrdinal (
1506 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1507 ULONG ExportDirSize
;
1508 PDWORD
* ExFunctions
;
1511 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData (
1514 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1517 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1518 ExportDir
->AddressOfFunctions
);
1519 DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
1521 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
]));
1523 Function
= 0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1524 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1527 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1528 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1530 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1531 Function
= LdrPEFixupForward((PCHAR
)Function
);
1538 LdrPEProcessImportDirectoryEntry(
1540 PMODULE_OBJECT ImportedModule
,
1541 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1543 PVOID
* ImportAddressList
;
1544 PULONG FunctionNameList
;
1547 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1549 return STATUS_UNSUCCESSFUL
;
1552 /* Get the import address list. */
1553 ImportAddressList
= (PVOID
*)(DriverBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1555 /* Get the list of functions to import. */
1556 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1558 FunctionNameList
= (PULONG
) (DriverBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1562 FunctionNameList
= (PULONG
)(DriverBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1565 /* Walk through function list and fixup addresses. */
1566 while (*FunctionNameList
!= 0L)
1568 if ((*FunctionNameList
) & 0x80000000)
1570 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1571 *ImportAddressList
= LdrPEGetExportByOrdinal(ImportedModule
->Base
, Ordinal
);
1572 if ((*ImportAddressList
) == NULL
)
1574 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullName
);
1575 return STATUS_UNSUCCESSFUL
;
1580 IMAGE_IMPORT_BY_NAME
*pe_name
;
1581 pe_name
= RVA(DriverBase
, *FunctionNameList
);
1582 *ImportAddressList
= LdrPEGetExportByName(ImportedModule
->Base
, pe_name
->Name
, pe_name
->Hint
);
1583 if ((*ImportAddressList
) == NULL
)
1585 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullName
);
1586 return STATUS_UNSUCCESSFUL
;
1589 ImportAddressList
++;
1592 return STATUS_SUCCESS
;
1596 LdrPEFixupImports ( PMODULE_OBJECT Module
)
1598 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1600 PMODULE_OBJECT ImportedModule
;
1603 /* Process each import module */
1604 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1605 RtlImageDirectoryEntryToData(Module
->Base
,
1607 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1609 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1610 while (ImportModuleDirectory
->Name
)
1612 if (Module
->Length
<= ImportModuleDirectory
->Name
)
1614 DPRINT1("Invalid import directory in %wZ\n", &Module
->FullName
);
1615 return STATUS_SECTION_NOT_IMAGE
;
1618 /* Check to make sure that import lib is kernel */
1619 ImportedName
= (PCHAR
) Module
->Base
+ ImportModuleDirectory
->Name
;
1621 Status
= LdrPEGetOrLoadModule(Module
, ImportedName
, &ImportedModule
);
1622 if (!NT_SUCCESS(Status
))
1627 Status
= LdrPEProcessImportDirectoryEntry(Module
->Base
, ImportedModule
, ImportModuleDirectory
);
1628 if (!NT_SUCCESS(Status
))
1633 ImportModuleDirectory
++;
1635 return STATUS_SUCCESS
;