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 #if defined (ALLOC_PRAGMA)
38 #pragma alloc_text(INIT, LdrInit1)
39 #pragma alloc_text(INIT, LdrInitModuleManagement)
40 #pragma alloc_text(INIT, LdrSafePEProcessModule)
43 /* GLOBALS *******************************************************************/
45 LIST_ENTRY ModuleListHead
;
46 KSPIN_LOCK ModuleListLock
;
47 LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject
;
48 LDR_DATA_TABLE_ENTRY HalModuleObject
;
52 /* FORWARD DECLARATIONS ******************************************************/
57 PUNICODE_STRING ModuleName
,
58 PLDR_DATA_TABLE_ENTRY
*ModuleObject
);
61 LdrpBuildModuleBaseName (
62 PUNICODE_STRING BaseName
,
63 PUNICODE_STRING FullName
);
66 LdrpCompareModuleNames (
67 IN PUNICODE_STRING String1
,
68 IN PUNICODE_STRING String2
);
71 /* PE Driver load support */
75 PUNICODE_STRING FileName
,
76 PLDR_DATA_TABLE_ENTRY
*ModuleObject
);
79 LdrPEGetExportByName (
85 LdrPEFixupForward ( PCHAR ForwardName
);
88 LdrPEPerformRelocations (
93 LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module
);
95 /* FUNCTIONS *****************************************************************/
99 LdrInitDebug ( PLOADER_MODULE Module
, PWCH Name
)
108 /* Hook for KDB on initialization of the loader. */
109 KDB_LOADERINIT_HOOK(&NtoskrnlModuleObject
, &HalModuleObject
);
115 LdrInitModuleManagement ( VOID
)
117 PIMAGE_NT_HEADERS NtHeader
;
119 /* Initialize the module list and spinlock */
120 InitializeListHead(&ModuleListHead
);
121 KeInitializeSpinLock(&ModuleListLock
);
123 /* Initialize ModuleObject for NTOSKRNL */
124 RtlZeroMemory(&NtoskrnlModuleObject
, sizeof(LDR_DATA_TABLE_ENTRY
));
125 NtoskrnlModuleObject
.DllBase
= (PVOID
) KERNEL_BASE
;
126 RtlInitUnicodeString(&NtoskrnlModuleObject
.FullDllName
, KERNEL_MODULE_NAME
);
127 LdrpBuildModuleBaseName(&NtoskrnlModuleObject
.BaseDllName
, &NtoskrnlModuleObject
.FullDllName
);
129 NtHeader
= RtlImageNtHeader((PVOID
)KERNEL_BASE
);
130 NtoskrnlModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) NtoskrnlModuleObject
.DllBase
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
131 DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject
, NtoskrnlModuleObject
.EntryPoint
);
132 NtoskrnlModuleObject
.SizeOfImage
= NtHeader
->OptionalHeader
.SizeOfImage
;
134 InsertTailList(&ModuleListHead
, &NtoskrnlModuleObject
.InLoadOrderModuleList
);
136 /* Initialize ModuleObject for HAL */
137 RtlZeroMemory(&HalModuleObject
, sizeof(LDR_DATA_TABLE_ENTRY
));
138 HalModuleObject
.DllBase
= (PVOID
) LdrHalBase
;
140 RtlInitUnicodeString(&HalModuleObject
.FullDllName
, HAL_MODULE_NAME
);
141 LdrpBuildModuleBaseName(&HalModuleObject
.BaseDllName
, &HalModuleObject
.FullDllName
);
143 NtHeader
= RtlImageNtHeader((PVOID
)LdrHalBase
);
144 HalModuleObject
.EntryPoint
= (PVOID
) ((ULONG_PTR
) HalModuleObject
.DllBase
+ NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
145 DPRINT("ModuleObject:%08x entrypoint at %x\n", &HalModuleObject
, HalModuleObject
.EntryPoint
);
146 HalModuleObject
.SizeOfImage
= NtHeader
->OptionalHeader
.SizeOfImage
;
148 InsertTailList(&ModuleListHead
, &HalModuleObject
.InLoadOrderModuleList
);
154 PUNICODE_STRING DriverName
,
156 PVOID
*SectionPointer
,
158 PVOID
*ExportSectionPointer
)
160 PLDR_DATA_TABLE_ENTRY ModuleObject
;
163 ModuleObject
= LdrGetModuleObject(DriverName
);
164 if (ModuleObject
== NULL
)
166 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
167 if (!NT_SUCCESS(Status
))
174 *ModuleBase
= ModuleObject
->DllBase
;
177 *SectionPointer
= ModuleObject
;
180 *EntryPoint
= ModuleObject
->EntryPoint
;
182 //if (ExportSectionPointer)
183 // *ExportSectionPointer = ModuleObject->
185 return(STATUS_SUCCESS
);
191 LdrpUnloadImage ( PVOID ModuleBase
)
193 return(STATUS_NOT_IMPLEMENTED
);
199 LdrpLoadAndCallImage ( PUNICODE_STRING ModuleName
)
201 PDRIVER_INITIALIZE DriverEntry
;
202 PLDR_DATA_TABLE_ENTRY ModuleObject
;
203 DRIVER_OBJECT DriverObject
;
206 ModuleObject
= LdrGetModuleObject(ModuleName
);
207 if (ModuleObject
!= NULL
)
209 return(STATUS_IMAGE_ALREADY_LOADED
);
212 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
213 if (!NT_SUCCESS(Status
))
218 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
220 RtlZeroMemory(&DriverObject
, sizeof(DriverObject
));
221 // DriverObject.DriverStart = ModuleObject->DllBase;
223 Status
= DriverEntry(&DriverObject
, NULL
);
224 if (!NT_SUCCESS(Status
))
226 LdrUnloadModule(ModuleObject
);
236 PUNICODE_STRING Filename
,
237 PLDR_DATA_TABLE_ENTRY
*ModuleObject
)
239 PVOID ModuleLoadBase
;
242 OBJECT_ATTRIBUTES ObjectAttributes
;
243 PLDR_DATA_TABLE_ENTRY Module
;
244 FILE_STANDARD_INFORMATION FileStdInfo
;
245 IO_STATUS_BLOCK IoStatusBlock
;
247 *ModuleObject
= NULL
;
249 DPRINT("Loading Module %wZ...\n", Filename
);
251 /* Open the Module */
252 InitializeObjectAttributes(&ObjectAttributes
,
254 OBJ_CASE_INSENSITIVE
,
258 Status
= ZwOpenFile(&FileHandle
,
263 FILE_SYNCHRONOUS_IO_NONALERT
);
265 if (!NT_SUCCESS(Status
))
267 CPRINT("Could not open module file: %wZ (Status 0x%08lx)\n", Filename
, Status
);
272 /* Get the size of the file */
273 Status
= ZwQueryInformationFile(FileHandle
,
277 FileStandardInformation
);
278 if (!NT_SUCCESS(Status
))
280 CPRINT("Could not get file size\n");
286 /* Allocate nonpageable memory for driver */
287 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
288 FileStdInfo
.EndOfFile
.u
.LowPart
,
290 if (ModuleLoadBase
== NULL
)
292 CPRINT("Could not allocate memory for module");
294 return(STATUS_INSUFFICIENT_RESOURCES
);
298 /* Load driver into memory chunk */
299 Status
= ZwReadFile(FileHandle
,
303 FileStdInfo
.EndOfFile
.u
.LowPart
,
305 if (!NT_SUCCESS(Status
))
307 CPRINT("Could not read module file into memory");
308 ExFreePool(ModuleLoadBase
);
316 Status
= LdrProcessModule(ModuleLoadBase
,
319 if (!NT_SUCCESS(Status
))
321 CPRINT("Could not process module\n");
322 ExFreePool(ModuleLoadBase
);
327 ExFreePool(ModuleLoadBase
);
329 *ModuleObject
= Module
;
331 /* Hook for KDB on loading a driver. */
332 KDB_LOADDRIVER_HOOK(Filename
, Module
);
334 return(STATUS_SUCCESS
);
340 LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject
)
344 /* Remove the module from the module list */
345 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
346 RemoveEntryList(&ModuleObject
->InLoadOrderModuleList
);
347 KeReleaseSpinLock(&ModuleListLock
, Irql
);
349 /* Hook for KDB on unloading a driver. */
350 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
352 /* Free module section */
353 // MmFreeSection(ModuleObject->DllBase);
355 ExFreePool(ModuleObject
->FullDllName
.Buffer
);
356 ExFreePool(ModuleObject
);
358 return(STATUS_SUCCESS
);
364 PVOID ModuleLoadBase
,
365 PUNICODE_STRING ModuleName
,
366 PLDR_DATA_TABLE_ENTRY
*ModuleObject
)
368 PIMAGE_DOS_HEADER PEDosHeader
;
370 /* If MZ header exists */
371 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
372 if (PEDosHeader
->e_magic
== IMAGE_DOS_SIGNATURE
&& PEDosHeader
->e_lfanew
!= 0L)
374 return LdrPEProcessModule(ModuleLoadBase
,
379 CPRINT("Module wasn't PE\n");
380 return STATUS_UNSUCCESSFUL
;
385 LdrpQueryModuleInformation (
390 PLIST_ENTRY current_entry
;
391 PLDR_DATA_TABLE_ENTRY current
;
392 ULONG ModuleCount
= 0;
393 PSYSTEM_MODULE_INFORMATION Smi
;
394 ANSI_STRING AnsiName
;
397 PUNICODE_STRING UnicodeName
;
398 ULONG tmpBufferSize
= 0;
399 PWCHAR tmpNameBuffer
;
401 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
403 /* calculate required size */
404 current_entry
= ModuleListHead
.Flink
;
405 while (current_entry
!= (&ModuleListHead
))
408 current
= CONTAINING_RECORD(current_entry
,LDR_DATA_TABLE_ENTRY
,InLoadOrderModuleList
);
409 tmpBufferSize
+= current
->FullDllName
.Length
+ sizeof(WCHAR
) + sizeof(UNICODE_STRING
);
410 current_entry
= current_entry
->Flink
;
413 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
414 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
418 KeReleaseSpinLock(&ModuleListLock
, Irql
);
419 return(STATUS_INFO_LENGTH_MISMATCH
);
422 /* allocate a temp buffer to store the module names */
423 UnicodeName
= ExAllocatePool(NonPagedPool
, tmpBufferSize
);
424 if (UnicodeName
== NULL
)
426 KeReleaseSpinLock(&ModuleListLock
, Irql
);
427 return STATUS_INSUFFICIENT_RESOURCES
;
429 tmpNameBuffer
= (PWCHAR
)((ULONG_PTR
)UnicodeName
+ ModuleCount
* sizeof(UNICODE_STRING
));
431 /* fill the buffer */
432 memset(Buffer
, '=', Size
);
434 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
435 Smi
->Count
= ModuleCount
;
438 current_entry
= ModuleListHead
.Flink
;
439 while (current_entry
!= (&ModuleListHead
))
441 current
= CONTAINING_RECORD(current_entry
,LDR_DATA_TABLE_ENTRY
,InLoadOrderModuleList
);
443 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
444 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
445 Smi
->Module
[ModuleCount
].Base
= current
->DllBase
;
446 Smi
->Module
[ModuleCount
].Size
= current
->SizeOfImage
;
447 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
448 Smi
->Module
[ModuleCount
].Index
= (USHORT
)ModuleCount
;
449 Smi
->Module
[ModuleCount
].NameLength
= 0;
450 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
451 UnicodeName
[ModuleCount
].Buffer
= tmpNameBuffer
;
452 UnicodeName
[ModuleCount
].MaximumLength
= current
->FullDllName
.Length
+ sizeof(WCHAR
);
453 tmpNameBuffer
+= UnicodeName
[ModuleCount
].MaximumLength
/ sizeof(WCHAR
);
454 RtlCopyUnicodeString(&UnicodeName
[ModuleCount
], ¤t
->FullDllName
);
457 current_entry
= current_entry
->Flink
;
460 KeReleaseSpinLock(&ModuleListLock
, Irql
);
462 for (ModuleCount
= 0; ModuleCount
< Smi
->Count
; ModuleCount
++)
465 AnsiName
.MaximumLength
= 255;
466 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
467 RtlUnicodeStringToAnsiString(&AnsiName
, &UnicodeName
[ModuleCount
], FALSE
);
468 AnsiName
.Buffer
[AnsiName
.Length
] = 0;
469 Smi
->Module
[ModuleCount
].NameLength
= AnsiName
.Length
;
471 p
= strrchr(AnsiName
.Buffer
, '\\');
474 Smi
->Module
[ModuleCount
].PathLength
= 0;
479 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
483 ExFreePool(UnicodeName
);
485 return(STATUS_SUCCESS
);
490 LdrpBuildModuleBaseName (
491 PUNICODE_STRING BaseName
,
492 PUNICODE_STRING FullName
)
496 DPRINT("LdrpBuildModuleBaseName()\n");
497 DPRINT("FullName %wZ\n", FullName
);
499 p
= wcsrchr(FullName
->Buffer
, L
'\\');
502 p
= FullName
->Buffer
;
511 RtlInitUnicodeString(BaseName
, p
);
516 LdrpCompareModuleNames (
517 IN PUNICODE_STRING String1
,
518 IN PUNICODE_STRING String2
)
524 if (String1
&& String2
)
526 /* Search String1 for last path component */
527 len1
= String1
->Length
/ sizeof(WCHAR
);
528 s1
= String1
->Buffer
;
529 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
533 if (i
== String1
->Length
- sizeof(WCHAR
))
541 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
546 /* Search String2 for last path component */
547 len2
= String2
->Length
/ sizeof(WCHAR
);
548 s2
= String2
->Buffer
;
549 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
553 if (i
== String2
->Length
- sizeof(WCHAR
))
561 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
566 /* Compare last path components */
571 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
572 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
573 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
575 if (!c1
|| !c2
|| c1
!= c2
)
584 PLDR_DATA_TABLE_ENTRY
586 LdrGetModuleObject ( PUNICODE_STRING ModuleName
)
588 PLDR_DATA_TABLE_ENTRY Module
;
592 DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName
);
594 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
596 Entry
= ModuleListHead
.Flink
;
597 while (Entry
!= &ModuleListHead
)
599 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
601 DPRINT("Comparing %wZ and %wZ\n",
602 &Module
->BaseDllName
,
605 if (!LdrpCompareModuleNames(&Module
->BaseDllName
, ModuleName
))
607 DPRINT("Module %wZ\n", &Module
->BaseDllName
);
608 KeReleaseSpinLock(&ModuleListLock
, Irql
);
612 Entry
= Entry
->Flink
;
615 KeReleaseSpinLock(&ModuleListLock
, Irql
);
617 DPRINT("Could not find module '%wZ'\n", ModuleName
);
623 /* ---------------------------------------------- PE Module support */
626 LdrLookupPageProtection (
629 PIMAGE_FILE_HEADER PEFileHeader
,
630 PIMAGE_SECTION_HEADER PESectionHeaders
)
632 BOOLEAN Write
= FALSE
;
633 BOOLEAN Execute
= FALSE
;
634 ULONG Characteristics
;
639 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& (!Write
|| !Execute
); Idx
++)
641 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
642 if (!(Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
644 Length
= max(PESectionHeaders
[Idx
].Misc
.VirtualSize
, PESectionHeaders
[Idx
].SizeOfRawData
);
645 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
646 if (BaseAddress
< (PVOID
)((ULONG_PTR
)PageStart
+ PAGE_SIZE
) &&
647 PageStart
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
))
649 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
653 if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
660 if (Write
&& Execute
)
662 return PAGE_EXECUTE_READWRITE
;
666 return PAGE_EXECUTE_READ
;
670 return PAGE_READWRITE
;
674 return PAGE_READONLY
;
680 PVOID ModuleLoadBase
,
681 PUNICODE_STRING FileName
,
682 PLDR_DATA_TABLE_ENTRY
*ModuleObject
)
684 unsigned int DriverSize
, Idx
;
687 PIMAGE_DOS_HEADER PEDosHeader
;
688 PIMAGE_NT_HEADERS PENtHeaders
;
689 PIMAGE_SECTION_HEADER PESectionHeaders
;
690 PLDR_DATA_TABLE_ENTRY CreatedModuleObject
;
694 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
696 /* Get header pointers */
697 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
698 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
699 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
702 /* Check file magic numbers */
703 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
705 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
706 return STATUS_UNSUCCESSFUL
;
708 if (PEDosHeader
->e_lfanew
== 0)
710 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
711 return STATUS_UNSUCCESSFUL
;
713 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
715 CPRINT("Incorrect PE magic: %08x\n", PENtHeaders
->Signature
);
716 return STATUS_UNSUCCESSFUL
;
718 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
720 CPRINT("Incorrect Architechture: %04x\n", PENtHeaders
->FileHeader
.Machine
);
721 return STATUS_UNSUCCESSFUL
;
725 /* FIXME: if image is fixed-address load, then fail */
727 /* FIXME: check/verify OS version number */
729 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
730 PENtHeaders
->OptionalHeader
.Magic
,
731 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
732 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
733 DPRINT("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
735 /* Determine the size of the module */
737 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
739 if (!(PESectionHeaders
[Idx
].Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
741 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
742 DriverSize
= max(DriverSize
, CurrentSize
);
745 DriverSize
= ROUND_UP(DriverSize
, PENtHeaders
->OptionalHeader
.SectionAlignment
);
746 DPRINT("DriverSize %x, SizeOfImage %x\n",DriverSize
, PENtHeaders
->OptionalHeader
.SizeOfImage
);
748 /* Allocate a virtual section for the module */
750 DriverBase
= MmAllocateSection(DriverSize
, DriverBase
);
753 CPRINT("Failed to allocate a virtual section for driver\n");
754 return STATUS_UNSUCCESSFUL
;
756 DPRINT("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
758 /* Copy headers over */
759 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
761 /* Copy image sections into virtual section */
762 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
764 CurrentSize
= PESectionHeaders
[Idx
].VirtualAddress
+ PESectionHeaders
[Idx
].Misc
.VirtualSize
;
765 /* Copy current section into current offset of virtual section */
766 if (CurrentSize
<= DriverSize
&&
767 PESectionHeaders
[Idx
].SizeOfRawData
)
769 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
770 PESectionHeaders
[Idx
].VirtualAddress
+ (ULONG_PTR
)DriverBase
);
771 memcpy((PVOID
)((ULONG_PTR
)DriverBase
+ PESectionHeaders
[Idx
].VirtualAddress
),
772 (PVOID
)((ULONG_PTR
)ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
773 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
774 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
778 /* Perform relocation fixups */
779 Status
= LdrPEPerformRelocations(DriverBase
, DriverSize
);
780 if (!NT_SUCCESS(Status
))
782 // MmFreeSection(DriverBase);
786 /* Create the module */
787 CreatedModuleObject
= ExAllocatePoolWithTag (
788 NonPagedPool
, sizeof(LDR_DATA_TABLE_ENTRY
), TAG_MODULE_OBJECT
);
789 if (CreatedModuleObject
== NULL
)
791 // MmFreeSection(DriverBase);
792 return STATUS_INSUFFICIENT_RESOURCES
;
795 RtlZeroMemory(CreatedModuleObject
, sizeof(LDR_DATA_TABLE_ENTRY
));
797 /* Initialize ModuleObject data */
798 CreatedModuleObject
->DllBase
= DriverBase
;
800 CreatedModuleObject
->FullDllName
.Length
= 0;
801 CreatedModuleObject
->FullDllName
.MaximumLength
= FileName
->Length
+ sizeof(UNICODE_NULL
);
802 CreatedModuleObject
->FullDllName
.Buffer
=
803 ExAllocatePoolWithTag(PagedPool
, CreatedModuleObject
->FullDllName
.MaximumLength
, TAG_LDR_WSTR
);
804 if (CreatedModuleObject
->FullDllName
.Buffer
== NULL
)
806 ExFreePool(CreatedModuleObject
);
807 // MmFreeSection(DriverBase);
808 return STATUS_INSUFFICIENT_RESOURCES
;
811 RtlCopyUnicodeString(&CreatedModuleObject
->FullDllName
, FileName
);
812 CreatedModuleObject
->FullDllName
.Buffer
[FileName
->Length
/ sizeof(WCHAR
)] = 0;
813 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseDllName
,
814 &CreatedModuleObject
->FullDllName
);
816 CreatedModuleObject
->EntryPoint
=
817 (PVOID
)((ULONG_PTR
)DriverBase
+
818 PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
819 CreatedModuleObject
->SizeOfImage
= DriverSize
;
820 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
822 /* Perform import fixups */
823 Status
= LdrPEFixupImports(CreatedModuleObject
);
824 if (!NT_SUCCESS(Status
))
826 // MmFreeSection(DriverBase);
827 ExFreePool(CreatedModuleObject
->FullDllName
.Buffer
);
828 ExFreePool(CreatedModuleObject
);
832 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
833 /* Set the protections for the various parts of the driver */
834 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
836 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
841 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
842 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
843 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
845 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
849 * This driver modifies a string in the first page of the text section while initialising.
851 if (0 == _wcsicmp(L
"fireport.sys", FileName
->Buffer
))
853 Protect
= PAGE_EXECUTE_READWRITE
;
856 if (PageAddress
< RVA(DriverBase
, DriverSize
))
858 MmSetPageProtect(NULL
, PageAddress
, Protect
);
861 if (Characteristics
& IMAGE_SCN_CNT_CODE
)
863 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
865 Protect
= PAGE_EXECUTE_READWRITE
;
869 Protect
= PAGE_EXECUTE_READ
;
872 else if (Characteristics
& (IMAGE_SCN_MEM_WRITE
|IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
874 Protect
= PAGE_READWRITE
;
878 Protect
= PAGE_READONLY
;
880 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
881 while ((ULONG_PTR
)PageAddress
+ PAGE_SIZE
< (ULONG_PTR
)BaseAddress
+ Length
)
883 if (PageAddress
< RVA(DriverBase
, DriverSize
))
885 MmSetPageProtect(NULL
, PageAddress
, Protect
);
887 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
889 if (PageAddress
< (PVOID
)((ULONG_PTR
)BaseAddress
+ Length
) &&
890 PageAddress
< RVA(DriverBase
, DriverSize
))
892 Protect
= LdrLookupPageProtection(PageAddress
, DriverBase
, &PENtHeaders
->FileHeader
, PESectionHeaders
);
893 MmSetPageProtect(NULL
, PageAddress
, Protect
);
898 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
899 InsertTailList(&ModuleListHead
,
900 &CreatedModuleObject
->InLoadOrderModuleList
);
901 KeReleaseSpinLock(&ModuleListLock
, Irql
);
903 *ModuleObject
= CreatedModuleObject
;
905 DPRINT("Loading Module %wZ...\n", FileName
);
907 DPRINT("Module %wZ loaded at 0x%.08x.\n",
908 FileName
, CreatedModuleObject
->DllBase
);
910 return STATUS_SUCCESS
;
917 LdrSafePEProcessModule (
918 PVOID ModuleLoadBase
,
920 PVOID ImportModuleBase
,
925 PIMAGE_DOS_HEADER PEDosHeader
;
926 PIMAGE_NT_HEADERS PENtHeaders
;
927 PIMAGE_SECTION_HEADER PESectionHeaders
;
930 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
932 /* Get header pointers */
933 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
934 PENtHeaders
= RtlImageNtHeader(ModuleLoadBase
);
935 PESectionHeaders
= IMAGE_FIRST_SECTION(PENtHeaders
);
938 /* Check file magic numbers */
939 if (PEDosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
943 if (PEDosHeader
->e_lfanew
== 0)
947 if (PENtHeaders
->Signature
!= IMAGE_NT_SIGNATURE
)
951 if (PENtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
956 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
957 PENtHeaders
->OptionalHeader
.Magic
,
958 PENtHeaders
->OptionalHeader
.MajorLinkerVersion
,
959 PENtHeaders
->OptionalHeader
.MinorLinkerVersion
);
960 ps("Entry Point:%08lx\n", PENtHeaders
->OptionalHeader
.AddressOfEntryPoint
);
962 /* Determine the size of the module */
963 *DriverSize
= PENtHeaders
->OptionalHeader
.SizeOfImage
;
964 ps("DriverSize %x\n",*DriverSize
);
966 /* Copy headers over */
967 if (DriverBase
!= ModuleLoadBase
)
969 memcpy(DriverBase
, ModuleLoadBase
, PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
972 ps("Hdr: 0x%X\n", PENtHeaders
);
973 ps("Hdr->SizeOfHeaders: 0x%X\n", PENtHeaders
->OptionalHeader
.SizeOfHeaders
);
974 ps("FileHdr->NumberOfSections: 0x%X\n", PENtHeaders
->FileHeader
.NumberOfSections
);
976 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
977 address as it is mapped */
978 if (DriverBase
!= ModuleLoadBase
)
982 /* Copy image sections into virtual section */
983 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
985 PIMAGE_SECTION_HEADER Section
= &PESectionHeaders
[Idx
];
986 // Copy current section into current offset of virtual section
987 if (Section
->SizeOfRawData
)
989 // ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
990 // PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
991 memcpy(Section
->VirtualAddress
+ (char*)DriverBase
,
992 Section
->PointerToRawData
+ (char*)ModuleLoadBase
,
993 Section
->Misc
.VirtualSize
> Section
->SizeOfRawData
? Section
->SizeOfRawData
: Section
->Misc
.VirtualSize
);
995 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
)
997 memset(Section
->VirtualAddress
+ Section
->SizeOfRawData
+ (char*)DriverBase
,
999 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
1001 CurrentSize
+= ROUND_UP(Section
->Misc
.VirtualSize
,
1002 PENtHeaders
->OptionalHeader
.SectionAlignment
);
1005 /* Perform relocation fixups */
1006 Status
= LdrPEPerformRelocations(DriverBase
, *DriverSize
);
1007 if (!NT_SUCCESS(Status
))
1013 /* Perform import fixups */
1014 Status
= LdrPEFixupImports(DriverBase
== ModuleLoadBase
? &NtoskrnlModuleObject
: &HalModuleObject
);
1015 if (!NT_SUCCESS(Status
))
1020 /* Set the page protection for the virtual sections */
1021 MmSetPageProtect(NULL
, DriverBase
, PAGE_READONLY
);
1022 for (Idx
= 0; Idx
< PENtHeaders
->FileHeader
.NumberOfSections
; Idx
++)
1024 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1029 Length
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1030 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ (char*)DriverBase
;
1031 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1033 if (Characteristics
& IMAGE_SCN_MEM_EXECUTE
)
1035 if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1037 Protect
= PAGE_EXECUTE_READWRITE
;
1041 Protect
= PAGE_EXECUTE_READ
;
1044 else if (Characteristics
& IMAGE_SCN_MEM_WRITE
)
1046 Protect
= PAGE_READWRITE
;
1050 Protect
= PAGE_READONLY
;
1052 while ((ULONG_PTR
)PageAddress
< (ULONG_PTR
)BaseAddress
+ Length
)
1054 MmSetPageProtect(NULL
, PageAddress
, Protect
);
1055 PageAddress
= (PVOID
)((ULONG_PTR
)PageAddress
+ PAGE_SIZE
);
1057 if (DriverBase
== ModuleLoadBase
&&
1058 Characteristics
& IMAGE_SCN_CNT_UNINITIALIZED_DATA
)
1060 /* For ntoskrnl, we must stop after the bss section */
1070 LdrPEFixupForward ( PCHAR ForwardName
)
1072 CHAR NameBuffer
[128];
1073 UNICODE_STRING ModuleName
;
1075 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1077 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1079 strcpy(NameBuffer
, ForwardName
);
1080 p
= strchr(NameBuffer
, '.');
1088 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1090 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1092 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1093 RtlFreeUnicodeString(&ModuleName
);
1095 DPRINT("ModuleObject: %p\n", ModuleObject
);
1097 if (ModuleObject
== NULL
)
1099 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1102 return LdrPEGetExportByName(ModuleObject
->DllBase
, (PUCHAR
)(p
+1), 0xffff);
1106 LdrPEPerformRelocations (
1110 PIMAGE_NT_HEADERS NtHeaders
;
1111 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1112 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1114 PVOID Address
, MaxAddress
;
1122 NtHeaders
= RtlImageNtHeader(DriverBase
);
1124 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1126 return STATUS_UNSUCCESSFUL
;
1129 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1131 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1133 return STATUS_SUCCESS
;
1136 Delta
= (ULONG_PTR
)DriverBase
- NtHeaders
->OptionalHeader
.ImageBase
;
1137 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)DriverBase
+ RelocationDDir
->VirtualAddress
);
1138 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
1139 MaxAddress
= RVA(DriverBase
, DriverSize
);
1141 while (RelocationDir
< RelocationEnd
&&
1142 RelocationDir
->SizeOfBlock
> 0)
1144 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
1145 Address
= RVA(DriverBase
, RelocationDir
->VirtualAddress
);
1146 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1148 for (i
= 0; i
< Count
; i
++)
1150 Offset
= *TypeOffset
& 0xFFF;
1151 Type
= *TypeOffset
>> 12;
1152 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
1154 /* Don't relocate after the end of the loaded driver */
1155 if ((PVOID
)ShortPtr
>= MaxAddress
)
1161 * Don't relocate within the relocation section itself.
1162 * GCC/LD generates sometimes relocation records for the relocation section.
1163 * This is a bug in GCC/LD.
1165 if ((ULONG_PTR
)ShortPtr
< (ULONG_PTR
)RelocationDir
||
1166 (ULONG_PTR
)ShortPtr
>= (ULONG_PTR
)RelocationEnd
)
1170 case IMAGE_REL_BASED_ABSOLUTE
:
1173 case IMAGE_REL_BASED_HIGH
:
1174 *ShortPtr
+= HIWORD(Delta
);
1177 case IMAGE_REL_BASED_LOW
:
1178 *ShortPtr
+= LOWORD(Delta
);
1181 case IMAGE_REL_BASED_HIGHLOW
:
1182 LongPtr
= (PULONG
)ShortPtr
;
1186 case IMAGE_REL_BASED_HIGHADJ
:
1187 case IMAGE_REL_BASED_MIPS_JMPADDR
:
1189 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
1190 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, *TypeOffset
);
1191 return STATUS_UNSUCCESSFUL
;
1196 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
1199 return STATUS_SUCCESS
;
1202 #define PATH_MAX 260
1206 LdrPEGetOrLoadModule (
1207 PLDR_DATA_TABLE_ENTRY Module
,
1209 PLDR_DATA_TABLE_ENTRY
* ImportedModule
)
1211 UNICODE_STRING DriverName
;
1212 UNICODE_STRING NameString
;
1213 WCHAR NameBuffer
[PATH_MAX
];
1214 NTSTATUS Status
= STATUS_SUCCESS
;
1216 if (0 == _stricmp(ImportedName
, "ntoskrnl") ||
1217 0 == _stricmp(ImportedName
, "ntoskrnl.exe"))
1219 *ImportedModule
= &NtoskrnlModuleObject
;
1220 return STATUS_SUCCESS
;
1223 if (0 == _stricmp(ImportedName
, "hal") ||
1224 0 == _stricmp(ImportedName
, "hal.dll"))
1226 *ImportedModule
= &HalModuleObject
;
1227 return STATUS_SUCCESS
;
1230 RtlCreateUnicodeStringFromAsciiz (&DriverName
, ImportedName
);
1231 DPRINT("Import module: %wZ\n", &DriverName
);
1233 *ImportedModule
= LdrGetModuleObject(&DriverName
);
1234 if (*ImportedModule
== NULL
)
1239 PathEnd
= wcsrchr(Module
->FullDllName
.Buffer
, L
'\\');
1240 if (NULL
!= PathEnd
)
1242 PathLength
= (PathEnd
- Module
->FullDllName
.Buffer
+ 1) * sizeof(WCHAR
);
1243 RtlCopyMemory(NameBuffer
, Module
->FullDllName
.Buffer
, PathLength
);
1244 RtlCopyMemory(NameBuffer
+ (PathLength
/ sizeof(WCHAR
)), DriverName
.Buffer
, DriverName
.Length
);
1245 NameString
.Buffer
= NameBuffer
;
1246 NameString
.MaximumLength
= NameString
.Length
= PathLength
+ DriverName
.Length
;
1248 /* NULL-terminate */
1249 NameString
.MaximumLength
++;
1250 NameBuffer
[NameString
.Length
/ sizeof(WCHAR
)] = 0;
1252 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1256 DPRINT("Module '%wZ' not loaded yet\n", &DriverName
);
1257 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
1258 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1259 RtlInitUnicodeString(&NameString
, NameBuffer
);
1260 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1262 if (!NT_SUCCESS(Status
))
1264 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
1265 wcsncat(NameBuffer
, DriverName
.Buffer
, DriverName
.Length
/ sizeof(WCHAR
));
1266 RtlInitUnicodeString(&NameString
, NameBuffer
);
1267 Status
= LdrLoadModule(&NameString
, ImportedModule
);
1268 if (!NT_SUCCESS(Status
))
1270 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName
, Status
);
1274 RtlFreeUnicodeString(&DriverName
);
1279 LdrPEGetExportByName (
1284 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1285 PDWORD
* ExFunctions
;
1287 USHORT
* ExOrdinals
;
1291 LONG minn
, maxn
, mid
, res
;
1292 ULONG ExportDirSize
;
1294 DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1296 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData(BaseAddress
,
1298 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1300 if (ExportDir
== NULL
)
1302 DPRINT1("LdrPEGetExportByName(): no export directory!\n");
1307 /* The symbol names may be missing entirely */
1308 if (ExportDir
->AddressOfNames
== 0)
1310 DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n");
1315 * Get header pointers
1317 ExNames
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
1318 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
1319 ExFunctions
= (PDWORD
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
1322 * Check the hint first
1324 if (Hint
< ExportDir
->NumberOfNames
)
1326 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1327 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1329 Ordinal
= ExOrdinals
[Hint
];
1330 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1331 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1332 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1334 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1335 Function
= LdrPEFixupForward((PCHAR
)Function
);
1336 if (Function
== NULL
)
1338 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1342 if (Function
!= NULL
)
1353 maxn
= ExportDir
->NumberOfNames
- 1;
1354 while (minn
<= maxn
)
1356 mid
= (minn
+ maxn
) / 2;
1358 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1359 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1362 Ordinal
= ExOrdinals
[mid
];
1363 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1364 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
1365 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
1367 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1368 Function
= LdrPEFixupForward((PCHAR
)Function
);
1369 if (Function
== NULL
)
1371 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1375 if (Function
!= NULL
)
1390 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1391 DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName
);
1396 LdrPEGetExportByOrdinal (
1400 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1401 ULONG ExportDirSize
;
1402 PDWORD
* ExFunctions
;
1405 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)RtlImageDirectoryEntryToData (
1408 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1411 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1412 ExportDir
->AddressOfFunctions
);
1413 DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n",
1415 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
]));
1417 Function
= 0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1418 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1421 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1422 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
))
1424 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1425 Function
= LdrPEFixupForward((PCHAR
)Function
);
1432 LdrPEProcessImportDirectoryEntry(
1434 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1435 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1437 PVOID
* ImportAddressList
;
1438 PULONG FunctionNameList
;
1441 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1443 return STATUS_UNSUCCESSFUL
;
1446 /* Get the import address list. */
1447 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
1449 /* Get the list of functions to import. */
1450 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1452 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
1456 FunctionNameList
= (PULONG
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
1459 /* Walk through function list and fixup addresses. */
1460 while (*FunctionNameList
!= 0L)
1462 if ((*FunctionNameList
) & 0x80000000)
1464 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1465 *ImportAddressList
= LdrPEGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1466 if ((*ImportAddressList
) == NULL
)
1468 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1469 return STATUS_UNSUCCESSFUL
;
1474 IMAGE_IMPORT_BY_NAME
*pe_name
;
1475 pe_name
= RVA(DriverBase
, *FunctionNameList
);
1476 *ImportAddressList
= LdrPEGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1477 if ((*ImportAddressList
) == NULL
)
1479 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1480 return STATUS_UNSUCCESSFUL
;
1483 ImportAddressList
++;
1486 return STATUS_SUCCESS
;
1490 LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module
)
1492 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1494 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1498 /* Process each import module */
1499 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1500 RtlImageDirectoryEntryToData(Module
->DllBase
,
1502 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1504 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1505 while (ImportModuleDirectory
->Name
)
1507 if (Module
->SizeOfImage
<= ImportModuleDirectory
->Name
)
1509 DPRINT1("Invalid import directory in %wZ\n", &Module
->FullDllName
);
1510 return STATUS_SECTION_NOT_IMAGE
;
1513 /* Check to make sure that import lib is kernel */
1514 ImportedName
= (PCHAR
) Module
->DllBase
+ ImportModuleDirectory
->Name
;
1516 Status
= LdrPEGetOrLoadModule(Module
, ImportedName
, &ImportedModule
);
1517 if (!NT_SUCCESS(Status
))
1522 Status
= LdrPEProcessImportDirectoryEntry(Module
->DllBase
, ImportedModule
, ImportModuleDirectory
);
1523 if (!NT_SUCCESS(Status
))
1528 ImportModuleDirectory
++;
1530 return STATUS_SUCCESS
;