1 /* $Id: loader.c,v 1.137 2003/10/15 17:04:39 navaraf 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 *****************************************************************/
28 #include <ddk/ntddk.h>
30 #include <internal/module.h>
31 #include <internal/ntoskrnl.h>
32 #include <internal/kd.h>
33 #include <internal/io.h>
34 #include <internal/mm.h>
35 #include <internal/ps.h>
36 #include <internal/ldr.h>
37 #include <internal/pool.h>
38 #include <internal/kd.h>
39 #include <ntos/minmax.h>
42 #include <internal/ntosdbg.h>
48 #include <internal/debug.h>
50 /* GLOBALS *******************************************************************/
52 LIST_ENTRY ModuleListHead
;
53 KSPIN_LOCK ModuleListLock
;
55 LIST_ENTRY ModuleTextListHead
;
56 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
57 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
60 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
62 /* FORWARD DECLARATIONS ******************************************************/
65 LdrProcessModule(PVOID ModuleLoadBase
,
66 PUNICODE_STRING ModuleName
,
67 PMODULE_OBJECT
*ModuleObject
);
70 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
75 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
76 PUNICODE_STRING FullName
);
79 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
80 IN PUNICODE_STRING String2
);
83 /* PE Driver load support */
84 static NTSTATUS
LdrPEProcessModule(PVOID ModuleLoadBase
,
85 PUNICODE_STRING FileName
,
86 PMODULE_OBJECT
*ModuleObject
);
88 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
93 LdrSafePEGetExportAddress(PVOID ImportModuleBase
,
98 LdrPEFixupForward(PCHAR ForwardName
);
101 /* FUNCTIONS *****************************************************************/
104 LdrInitDebug(PLOADER_MODULE Module
, PWCH Name
)
106 PLIST_ENTRY current_entry
;
107 MODULE_TEXT_SECTION
* current
;
109 current_entry
= ModuleTextListHead
.Flink
;
110 while (current_entry
!= &ModuleTextListHead
)
113 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
114 if (wcscmp(current
->Name
, Name
) == 0)
118 current_entry
= current_entry
->Flink
;
121 if (current_entry
== &ModuleTextListHead
)
130 PIMAGE_DOS_HEADER DosHeader
;
131 PIMAGE_FILE_HEADER FileHeader
;
132 PIMAGE_OPTIONAL_HEADER OptionalHeader
;
133 PIMAGE_SECTION_HEADER SectionList
;
135 InitializeListHead(&ModuleTextListHead
);
137 /* Setup ntoskrnl.exe text section */
138 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
140 (PIMAGE_FILE_HEADER
) ((DWORD
)KERNEL_BASE
+
141 DosHeader
->e_lfanew
+ sizeof(ULONG
));
142 OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
143 ((DWORD
)FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
144 SectionList
= (PIMAGE_SECTION_HEADER
)
145 ((DWORD
)OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
146 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
147 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
148 SectionList
[0].VirtualAddress
;
149 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
150 NtoskrnlTextSection
.OptionalHeader
= OptionalHeader
;
151 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
153 /* Setup hal.dll text section */
154 DosHeader
= (PIMAGE_DOS_HEADER
)LdrHalBase
;
156 (PIMAGE_FILE_HEADER
) ((DWORD
)LdrHalBase
+
157 DosHeader
->e_lfanew
+ sizeof(ULONG
));
158 OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
159 ((DWORD
)FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
160 SectionList
= (PIMAGE_SECTION_HEADER
)
161 ((DWORD
)OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
162 LdrHalTextSection
.Base
= LdrHalBase
;
163 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
164 SectionList
[0].VirtualAddress
;
165 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
166 LdrHalTextSection
.OptionalHeader
= OptionalHeader
;
167 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
169 /* Hook for KDB on initialization of the loader. */
170 KDB_LOADERINIT_HOOK(&NtoskrnlTextSection
, &LdrHalTextSection
);
175 LdrInitModuleManagement(VOID
)
177 PIMAGE_DOS_HEADER DosHeader
;
178 PMODULE_OBJECT ModuleObject
;
180 /* Initialize the module list and spinlock */
181 InitializeListHead(&ModuleListHead
);
182 KeInitializeSpinLock(&ModuleListLock
);
184 /* Create module object for NTOSKRNL */
185 ModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
186 assert(ModuleObject
!= NULL
);
187 RtlZeroMemory(ModuleObject
, sizeof(MODULE_OBJECT
));
189 /* Initialize ModuleObject data */
190 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
191 ModuleObject
->Flags
= MODULE_FLAG_PE
;
192 RtlCreateUnicodeString(&ModuleObject
->FullName
,
194 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
195 &ModuleObject
->FullName
);
197 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
198 ModuleObject
->Image
.PE
.FileHeader
=
199 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
200 DosHeader
->e_lfanew
+ sizeof(ULONG
));
201 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
202 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
203 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
204 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
205 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
206 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
207 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
208 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
209 ModuleObject
->TextSection
= &NtoskrnlTextSection
;
211 InsertTailList(&ModuleListHead
,
212 &ModuleObject
->ListEntry
);
214 /* Create module object for HAL */
215 ModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
216 assert(ModuleObject
!= NULL
);
217 RtlZeroMemory(ModuleObject
, sizeof(MODULE_OBJECT
));
219 /* Initialize ModuleObject data */
220 ModuleObject
->Base
= (PVOID
) LdrHalBase
;
221 ModuleObject
->Flags
= MODULE_FLAG_PE
;
223 RtlCreateUnicodeString(&ModuleObject
->FullName
,
225 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
226 &ModuleObject
->FullName
);
228 DosHeader
= (PIMAGE_DOS_HEADER
) LdrHalBase
;
229 ModuleObject
->Image
.PE
.FileHeader
=
230 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
231 DosHeader
->e_lfanew
+ sizeof(ULONG
));
232 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
233 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
234 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
235 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
236 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
237 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
238 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
239 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
240 ModuleObject
->TextSection
= &LdrHalTextSection
;
242 InsertTailList(&ModuleListHead
,
243 &ModuleObject
->ListEntry
);
247 LdrpLoadImage(PUNICODE_STRING DriverName
,
249 PVOID
*SectionPointer
,
251 PVOID
*ExportSectionPointer
)
253 PMODULE_OBJECT ModuleObject
;
256 ModuleObject
= LdrGetModuleObject(DriverName
);
257 if (ModuleObject
== NULL
)
259 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
260 if (!NT_SUCCESS(Status
))
267 *ModuleBase
= ModuleObject
->Base
;
269 // if (SectionPointer)
270 // *SectionPointer = ModuleObject->
273 *EntryPoint
= ModuleObject
->EntryPoint
;
275 // if (ExportSectionPointer)
276 // *ExportSectionPointer = ModuleObject->
278 return(STATUS_SUCCESS
);
283 LdrpUnloadImage(PVOID ModuleBase
)
285 return(STATUS_NOT_IMPLEMENTED
);
290 LdrpLoadAndCallImage(PUNICODE_STRING ModuleName
)
292 PDRIVER_INITIALIZE DriverEntry
;
293 PMODULE_OBJECT ModuleObject
;
296 ModuleObject
= LdrGetModuleObject(ModuleName
);
297 if (ModuleObject
!= NULL
)
299 return(STATUS_IMAGE_ALREADY_LOADED
);
302 Status
= LdrLoadModule(ModuleName
, &ModuleObject
);
303 if (!NT_SUCCESS(Status
))
308 DriverEntry
= (PDRIVER_INITIALIZE
)ModuleObject
->EntryPoint
;
310 Status
= DriverEntry(NULL
, NULL
);
311 if (!NT_SUCCESS(Status
))
313 LdrUnloadModule(ModuleObject
);
321 LdrLoadModule(PUNICODE_STRING Filename
,
322 PMODULE_OBJECT
*ModuleObject
)
324 PVOID ModuleLoadBase
;
327 OBJECT_ATTRIBUTES ObjectAttributes
;
328 PMODULE_OBJECT Module
;
329 FILE_STANDARD_INFORMATION FileStdInfo
;
330 IO_STATUS_BLOCK IoStatusBlock
;
332 *ModuleObject
= NULL
;
334 DPRINT("Loading Module %wZ...\n", Filename
);
336 /* Open the Module */
337 InitializeObjectAttributes(&ObjectAttributes
,
343 Status
= NtOpenFile(&FileHandle
,
348 FILE_SYNCHRONOUS_IO_NONALERT
);
350 if (!NT_SUCCESS(Status
))
352 CPRINT("Could not open module file: %wZ\n", Filename
);
357 /* Get the size of the file */
358 Status
= NtQueryInformationFile(FileHandle
,
362 FileStandardInformation
);
363 if (!NT_SUCCESS(Status
))
365 CPRINT("Could not get file size\n");
371 /* Allocate nonpageable memory for driver */
372 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
373 FileStdInfo
.EndOfFile
.u
.LowPart
,
375 if (ModuleLoadBase
== NULL
)
377 CPRINT("Could not allocate memory for module");
379 return(STATUS_INSUFFICIENT_RESOURCES
);
383 /* Load driver into memory chunk */
384 Status
= NtReadFile(FileHandle
,
388 FileStdInfo
.EndOfFile
.u
.LowPart
,
390 if (!NT_SUCCESS(Status
))
392 CPRINT("Could not read module file into memory");
393 ExFreePool(ModuleLoadBase
);
401 Status
= LdrProcessModule(ModuleLoadBase
,
404 if (!NT_SUCCESS(Status
))
406 CPRINT("Could not process module");
407 ExFreePool(ModuleLoadBase
);
412 ExFreePool(ModuleLoadBase
);
414 *ModuleObject
= Module
;
416 /* Hook for KDB on loading a driver. */
417 KDB_LOADDRIVER_HOOK(Filename
, Module
);
419 return(STATUS_SUCCESS
);
424 LdrUnloadModule(PMODULE_OBJECT ModuleObject
)
428 /* Remove the module from the module list */
429 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
430 RemoveEntryList(&ModuleObject
->ListEntry
);
431 KeReleaseSpinLock(&ModuleListLock
, Irql
);
433 /* Hook for KDB on unloading a driver. */
434 KDB_UNLOADDRIVER_HOOK(ModuleObject
);
436 /* Free text section */
437 if (ModuleObject
->TextSection
!= NULL
)
439 ExFreePool(ModuleObject
->TextSection
->Name
);
440 RemoveEntryList(&ModuleObject
->TextSection
->ListEntry
);
441 ExFreePool(ModuleObject
->TextSection
);
442 ModuleObject
->TextSection
= NULL
;
445 /* Free module section */
446 // MmFreeSection(ModuleObject->Base);
448 ExFreePool(ModuleObject
);
450 return(STATUS_SUCCESS
);
454 NTSTATUS INIT_FUNCTION
455 LdrInitializeBootStartDriver(PVOID ModuleLoadBase
,
459 PMODULE_OBJECT ModuleObject
;
460 UNICODE_STRING ModuleName
;
461 PDEVICE_NODE DeviceNode
;
464 WCHAR Buffer
[MAX_PATH
];
469 CHAR TextBuffer
[256];
472 HalQueryDisplayParameters(&x
, &y
, &cx
, &cy
);
473 RtlFillMemory(TextBuffer
, x
, ' ');
474 TextBuffer
[x
] = '\0';
475 HalSetDisplayParameters(0, y
-1);
476 HalDisplayString(TextBuffer
);
478 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
479 HalSetDisplayParameters(0, y
-1);
480 HalDisplayString(TextBuffer
);
481 HalSetDisplayParameters(cx
, cy
);
483 /* Split the filename into base name and extension */
484 FileExt
= strrchr(FileName
, '.');
486 Length
= FileExt
- FileName
;
488 Length
= strlen(FileName
);
490 if ((FileExt
!= NULL
) && (strcmp(FileExt
, ".sym") == 0))
492 KDB_SYMBOLFILE_HOOK(ModuleLoadBase
, FileName
, Length
);
493 return(STATUS_SUCCESS
);
495 else if ((FileExt
!= NULL
) && !(strcmp(FileExt
, ".sys") == 0))
497 CPRINT("Ignoring non-driver file %s\n", FileName
);
498 return STATUS_SUCCESS
;
501 /* Use IopRootDeviceNode for now */
502 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
503 if (!NT_SUCCESS(Status
))
505 CPRINT("Driver load failed, status (%x)\n", Status
);
509 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
511 Status
= LdrProcessModule(ModuleLoadBase
,
514 RtlFreeUnicodeString(&ModuleName
);
515 if (ModuleObject
== NULL
)
517 IopFreeDeviceNode(DeviceNode
);
518 CPRINT("Driver load failed, status (%x)\n", Status
);
519 return(STATUS_UNSUCCESSFUL
);
523 /* Get the service name from the module name */
524 Start
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'\\');
526 Start
= ModuleObject
->BaseName
.Buffer
;
530 Ext
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'.');
532 Length
= Ext
- Start
;
534 Length
= wcslen(Start
);
536 wcsncpy(Buffer
, Start
, Length
);
538 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, Buffer
);
540 Status
= IopInitializeDriver(ModuleObject
->EntryPoint
,
543 ModuleObject
->Length
,
545 if (!NT_SUCCESS(Status
))
547 IopFreeDeviceNode(DeviceNode
);
548 CPRINT("Driver load failed, status (%x)\n", Status
);
556 LdrProcessModule(PVOID ModuleLoadBase
,
557 PUNICODE_STRING ModuleName
,
558 PMODULE_OBJECT
*ModuleObject
)
560 PIMAGE_DOS_HEADER PEDosHeader
;
562 /* If MZ header exists */
563 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
564 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
566 return LdrPEProcessModule(ModuleLoadBase
,
571 CPRINT("Module wasn't PE\n");
572 return STATUS_UNSUCCESSFUL
;
577 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
581 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
583 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
593 LdrpQueryModuleInformation(PVOID Buffer
,
597 PLIST_ENTRY current_entry
;
598 PMODULE_OBJECT current
;
599 ULONG ModuleCount
= 0;
600 PSYSTEM_MODULE_INFORMATION Smi
;
601 ANSI_STRING AnsiName
;
605 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
607 /* calculate required size */
608 current_entry
= ModuleListHead
.Flink
;
609 while (current_entry
!= (&ModuleListHead
))
612 current_entry
= current_entry
->Flink
;
615 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
616 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_INFORMATION_ENTRY
);
620 KeReleaseSpinLock(&ModuleListLock
, Irql
);
621 return(STATUS_INFO_LENGTH_MISMATCH
);
624 /* fill the buffer */
625 memset(Buffer
, '=', Size
);
627 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
628 Smi
->Count
= ModuleCount
;
631 current_entry
= ModuleListHead
.Flink
;
632 while (current_entry
!= (&ModuleListHead
))
634 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
636 Smi
->Module
[ModuleCount
].Unknown1
= 0; /* Always 0 */
637 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
638 Smi
->Module
[ModuleCount
].Base
= current
->Base
;
639 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
640 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
641 Smi
->Module
[ModuleCount
].Index
= ModuleCount
;
642 Smi
->Module
[ModuleCount
].NameLength
= 0;
643 Smi
->Module
[ModuleCount
].LoadCount
= 0; /* FIXME */
646 AnsiName
.MaximumLength
= 256;
647 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].ImageName
;
648 RtlUnicodeStringToAnsiString(&AnsiName
,
652 p
= strrchr(AnsiName
.Buffer
, '\\');
655 Smi
->Module
[ModuleCount
].PathLength
= 0;
660 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
664 current_entry
= current_entry
->Flink
;
667 KeReleaseSpinLock(&ModuleListLock
, Irql
);
669 return(STATUS_SUCCESS
);
674 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
675 PUNICODE_STRING FullName
)
681 DPRINT("LdrpBuildModuleBaseName()\n");
682 DPRINT("FullName %wZ\n", FullName
);
684 p
= wcsrchr(FullName
->Buffer
, L
'\\');
687 p
= FullName
->Buffer
;
696 RtlCreateUnicodeString(&Name
, p
);
698 q
= wcschr(Name
.Buffer
, L
'.');
706 RtlCreateUnicodeString(BaseName
, Name
.Buffer
);
707 RtlFreeUnicodeString(&Name
);
712 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
713 IN PUNICODE_STRING String2
)
719 if (String1
&& String2
)
721 /* Search String1 for last path component */
722 len1
= String1
->Length
/ sizeof(WCHAR
);
723 s1
= String1
->Buffer
;
724 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
728 if (i
== String1
->Length
- sizeof(WCHAR
))
736 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
741 /* Search String2 for last path component */
742 len2
= String2
->Length
/ sizeof(WCHAR
);
743 s2
= String2
->Buffer
;
744 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
748 if (i
== String2
->Length
- sizeof(WCHAR
))
756 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
761 /* Compare last path components */
766 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
767 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
768 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
770 if (!c1
|| !c2
|| c1
!= c2
)
781 LdrGetModuleObject(PUNICODE_STRING ModuleName
)
783 PMODULE_OBJECT Module
;
787 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName
);
789 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
791 Entry
= ModuleListHead
.Flink
;
792 while (Entry
!= &ModuleListHead
)
794 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
796 DPRINT("Comparing %wZ and %wZ\n",
800 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
802 DPRINT("Module %wZ\n", &Module
->BaseName
);
803 KeReleaseSpinLock(&ModuleListLock
, Irql
);
807 Entry
= Entry
->Flink
;
810 KeReleaseSpinLock(&ModuleListLock
, Irql
);
812 DPRINT("Could not find module '%wZ'\n", ModuleName
);
818 /* ---------------------------------------------- PE Module support */
821 PageNeedsWriteAccess(PVOID PageStart
,
823 PIMAGE_FILE_HEADER PEFileHeader
,
824 PIMAGE_SECTION_HEADER PESectionHeaders
)
826 BOOL NeedsWriteAccess
;
828 ULONG Characteristics
;
832 NeedsWriteAccess
= FALSE
;
833 /* Set the protections for the various parts of the driver */
834 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
&& ! NeedsWriteAccess
; Idx
++)
836 Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
837 if (!(Characteristics
& IMAGE_SECTION_CHAR_CODE
) ||
838 (Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
||
839 Characteristics
& IMAGE_SECTION_CHAR_DATA
||
840 Characteristics
& IMAGE_SECTION_CHAR_BSS
))
843 max(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
844 PESectionHeaders
[Idx
].SizeOfRawData
);
845 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
;
846 NeedsWriteAccess
= BaseAddress
< PageStart
+ PAGE_SIZE
&&
847 PageStart
< (PVOID
)((PCHAR
) BaseAddress
+ Length
);
851 return(NeedsWriteAccess
);
855 LdrPEProcessModule(PVOID ModuleLoadBase
,
856 PUNICODE_STRING FileName
,
857 PMODULE_OBJECT
*ModuleObject
)
859 unsigned int DriverSize
, Idx
;
860 ULONG RelocDelta
, NumRelocs
;
861 DWORD CurrentSize
, TotalRelocs
;
864 PIMAGE_DOS_HEADER PEDosHeader
;
865 PIMAGE_FILE_HEADER PEFileHeader
;
866 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
867 PIMAGE_SECTION_HEADER PESectionHeaders
;
868 PRELOCATION_DIRECTORY RelocDir
;
869 PRELOCATION_ENTRY RelocEntry
;
870 PMODULE_OBJECT LibraryModuleObject
;
871 PMODULE_OBJECT CreatedModuleObject
;
872 PVOID
*ImportAddressList
;
873 PULONG FunctionNameList
;
876 UNICODE_STRING ModuleName
;
877 UNICODE_STRING NameString
;
878 WCHAR NameBuffer
[60];
879 MODULE_TEXT_SECTION
* ModuleTextSection
;
883 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
885 /* Get header pointers */
886 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
887 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
888 PEDosHeader
->e_lfanew
);
889 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
890 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
891 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
892 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
893 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
894 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
895 sizeof(IMAGE_OPTIONAL_HEADER
));
898 /* Check file magic numbers */
899 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
901 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
902 return STATUS_UNSUCCESSFUL
;
904 if (PEDosHeader
->e_lfanew
== 0)
906 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
907 return STATUS_UNSUCCESSFUL
;
909 if (*PEMagic
!= IMAGE_PE_MAGIC
)
911 CPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
912 return STATUS_UNSUCCESSFUL
;
914 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
916 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
917 return STATUS_UNSUCCESSFUL
;
921 /* FIXME: if image is fixed-address load, then fail */
923 /* FIXME: check/verify OS version number */
925 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
926 PEOptionalHeader
->Magic
,
927 PEOptionalHeader
->MajorLinkerVersion
,
928 PEOptionalHeader
->MinorLinkerVersion
);
929 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
932 /* Determine the size of the module */
933 DriverSize
= PEOptionalHeader
->SizeOfImage
;
934 DPRINT("DriverSize %x\n",DriverSize
);
936 /* Allocate a virtual section for the module */
937 DriverBase
= MmAllocateSection(DriverSize
);
940 CPRINT("Failed to allocate a virtual section for driver\n");
941 return STATUS_UNSUCCESSFUL
;
944 DbgPrint("DriverBase for %wZ: %x\n", FileName
, DriverBase
);
946 DbgPrint("DriverBase for %wZ", FileName
);
947 DbgPrint(": %x\n", DriverBase
);
950 /* Copy headers over */
951 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
953 /* Copy image sections into virtual section */
954 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
956 // Copy current section into current offset of virtual section
957 if (PESectionHeaders
[Idx
].Characteristics
&
958 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
960 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
961 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
962 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
963 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
964 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
965 ? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
969 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
970 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
971 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
972 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
975 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
976 PEOptionalHeader
->SectionAlignment
);
979 // CurrentBase = (PVOID)((DWORD)CurrentBase +
980 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
981 // PEOptionalHeader->SectionAlignment));
984 /* Perform relocation fixups */
985 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
986 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
987 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
988 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
990 PEOptionalHeader
->ImageBase
,
992 DPRINT("RelocDir %x\n",RelocDir
);
994 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
996 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
998 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
999 PESectionHeaders
[Idx
].Name
,
1000 PESectionHeaders
[Idx
].PointerToRawData
);
1001 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
1003 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1008 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
1009 CurrentSize
= PEOptionalHeader
->DataDirectory
1010 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
1012 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1014 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1016 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1018 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1020 RelocDir->VirtualAddress,
1022 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
1023 sizeof(RELOCATION_DIRECTORY
));
1024 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1030 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1031 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1032 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
1034 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1037 Type ? "HIGHLOW" : "ABS",
1039 (*RelocItem) + RelocDelta); */
1042 (*RelocItem
) += RelocDelta
;
1046 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1047 return STATUS_UNSUCCESSFUL
;
1050 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1051 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
1052 RelocDir
->SizeOfBlock
);
1053 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1056 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1057 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1059 /* Perform import fixups */
1060 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1062 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1064 /* Process each import module */
1065 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1066 ((DWORD
)DriverBase
+ PEOptionalHeader
->
1067 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1068 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1069 while (ImportModuleDirectory
->dwRVAModuleName
)
1071 /* Check to make sure that import lib is kernel */
1072 pName
= (PCHAR
) DriverBase
+
1073 ImportModuleDirectory
->dwRVAModuleName
;
1075 RtlCreateUnicodeStringFromAsciiz(&ModuleName
, pName
);
1076 DPRINT("Import module: %wZ\n", &ModuleName
);
1078 LibraryModuleObject
= LdrGetModuleObject(&ModuleName
);
1079 if (LibraryModuleObject
== NULL
)
1081 DPRINT("Module '%wZ' not loaded yet\n", &ModuleName
);
1082 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\drivers\\");
1083 wcscat(NameBuffer
, ModuleName
.Buffer
);
1084 RtlInitUnicodeString(&NameString
, NameBuffer
);
1085 Status
= LdrLoadModule(&NameString
, &LibraryModuleObject
);
1086 if (!NT_SUCCESS(Status
))
1088 wcscpy(NameBuffer
, L
"\\SystemRoot\\system32\\");
1089 wcscat(NameBuffer
, ModuleName
.Buffer
);
1090 RtlInitUnicodeString(&NameString
, NameBuffer
);
1091 Status
= LdrLoadModule(&NameString
, &LibraryModuleObject
);
1092 if (!NT_SUCCESS(Status
))
1094 DPRINT1("Unknown import module: %wZ (Status %lx)\n", &ModuleName
, Status
);
1099 /* Get the import address list */
1100 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
1101 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1103 /* Get the list of functions to import */
1104 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1106 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1107 ImportModuleDirectory
->dwRVAFunctionNameList
);
1111 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1112 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1114 /* Walk through function list and fixup addresses */
1115 while (*FunctionNameList
!= 0L)
1117 if ((*FunctionNameList
) & 0x80000000) // hint
1122 Hint
= (*FunctionNameList
) & 0xffff;
1126 pName
= (PCHAR
)((DWORD
)DriverBase
+
1127 *FunctionNameList
+ 2);
1128 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
1130 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
1132 /* Fixup the current import symbol */
1133 if (LibraryModuleObject
!= NULL
)
1135 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
1141 CPRINT("Unresolved kernel symbol: %s\n", pName
);
1142 return STATUS_UNSUCCESSFUL
;
1144 ImportAddressList
++;
1148 RtlFreeUnicodeString(&ModuleName
);
1150 ImportModuleDirectory
++;
1154 /* Set the protections for the various parts of the driver */
1155 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1157 ULONG Characteristics
= PESectionHeaders
[Idx
].Characteristics
;
1161 if (Characteristics
& IMAGE_SECTION_CHAR_CODE
&&
1162 !(Characteristics
& IMAGE_SECTION_CHAR_WRITABLE
||
1163 Characteristics
& IMAGE_SECTION_CHAR_DATA
||
1164 Characteristics
& IMAGE_SECTION_CHAR_BSS
))
1167 max(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1168 PESectionHeaders
[Idx
].SizeOfRawData
);
1169 BaseAddress
= PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
;
1170 PageAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
1171 if (! PageNeedsWriteAccess(PageAddress
, DriverBase
, PEFileHeader
, PESectionHeaders
))
1173 MmSetPageProtect(NULL
, PageAddress
, PAGE_READONLY
);
1175 PageAddress
= (PVOID
)((PCHAR
) PageAddress
+ PAGE_SIZE
);
1176 while ((PVOID
)((PCHAR
) PageAddress
+ PAGE_SIZE
) <
1177 (PVOID
)((PCHAR
) BaseAddress
+ Length
))
1179 MmSetPageProtect(NULL
, PageAddress
, PAGE_READONLY
);
1180 PageAddress
= (PVOID
)((PCHAR
) PageAddress
+ PAGE_SIZE
);
1182 if (PageAddress
< (PVOID
)((PCHAR
) BaseAddress
+ Length
) &&
1183 ! PageNeedsWriteAccess(PageAddress
, DriverBase
, PEFileHeader
, PESectionHeaders
))
1185 MmSetPageProtect(NULL
, PageAddress
, PAGE_READONLY
);
1190 /* Create the module */
1191 CreatedModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
1192 if (CreatedModuleObject
== NULL
)
1194 return(STATUS_INSUFFICIENT_RESOURCES
);
1197 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
1199 /* Initialize ModuleObject data */
1200 CreatedModuleObject
->Base
= DriverBase
;
1201 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
1203 RtlCreateUnicodeString(&CreatedModuleObject
->FullName
,
1205 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
1206 &CreatedModuleObject
->FullName
);
1208 CreatedModuleObject
->EntryPoint
=
1209 (PVOID
)((DWORD
)DriverBase
+
1210 PEOptionalHeader
->AddressOfEntryPoint
);
1211 CreatedModuleObject
->Length
= DriverSize
;
1212 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
1214 CreatedModuleObject
->Image
.PE
.FileHeader
=
1215 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1217 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
1218 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
1219 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1220 sizeof(IMAGE_FILE_HEADER
));
1221 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
1222 CreatedModuleObject
->Image
.PE
.SectionList
=
1223 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1224 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
1225 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
1228 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
1229 InsertTailList(&ModuleListHead
,
1230 &CreatedModuleObject
->ListEntry
);
1231 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1234 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
1235 sizeof(MODULE_TEXT_SECTION
));
1236 assert(ModuleTextSection
);
1237 RtlZeroMemory(ModuleTextSection
, sizeof(MODULE_TEXT_SECTION
));
1238 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
1239 ModuleTextSection
->Length
= DriverSize
;
1240 ModuleTextSection
->Name
= ExAllocatePool(NonPagedPool
,
1241 (wcslen(CreatedModuleObject
->BaseName
.Buffer
) + 1) * sizeof(WCHAR
));
1242 wcscpy(ModuleTextSection
->Name
, CreatedModuleObject
->BaseName
.Buffer
);
1243 ModuleTextSection
->OptionalHeader
=
1244 CreatedModuleObject
->Image
.PE
.OptionalHeader
;
1245 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
1247 CreatedModuleObject
->TextSection
= ModuleTextSection
;
1249 *ModuleObject
= CreatedModuleObject
;
1251 DPRINT("Loading Module %wZ...\n", FileName
);
1253 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_GDB
))
1255 DPRINT("Module %wZ loaded at 0x%.08x.\n",
1256 FileName
, CreatedModuleObject
->Base
);
1259 return STATUS_SUCCESS
;
1264 LdrSafePEProcessModule(PVOID ModuleLoadBase
,
1266 PVOID ImportModuleBase
,
1270 ULONG RelocDelta
, NumRelocs
;
1271 ULONG CurrentSize
, TotalRelocs
;
1273 PIMAGE_DOS_HEADER PEDosHeader
;
1274 PIMAGE_FILE_HEADER PEFileHeader
;
1275 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1276 PIMAGE_SECTION_HEADER PESectionHeaders
;
1277 PRELOCATION_DIRECTORY RelocDir
;
1278 PRELOCATION_ENTRY RelocEntry
;
1279 PVOID
*ImportAddressList
;
1280 PULONG FunctionNameList
;
1284 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1286 /* Get header pointers */
1287 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1288 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1289 PEDosHeader
->e_lfanew
);
1290 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1291 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1292 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1293 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1294 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1295 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1296 sizeof(IMAGE_OPTIONAL_HEADER
));
1299 /* Check file magic numbers */
1300 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1304 if (PEDosHeader
->e_lfanew
== 0)
1308 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1312 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1317 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1318 PEOptionalHeader
->Magic
,
1319 PEOptionalHeader
->MajorLinkerVersion
,
1320 PEOptionalHeader
->MinorLinkerVersion
);
1321 ps("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1323 /* Determine the size of the module */
1324 *DriverSize
= PEOptionalHeader
->SizeOfImage
;
1325 ps("DriverSize %x\n",*DriverSize
);
1327 /* Copy headers over */
1328 if (DriverBase
!= ModuleLoadBase
)
1330 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1333 ps("Hdr: 0x%X\n", (ULONG
)PEOptionalHeader
);
1334 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG
)PEOptionalHeader
->SizeOfHeaders
);
1335 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG
)PEFileHeader
->NumberOfSections
);
1337 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1338 address as it is mapped */
1339 if (DriverBase
!= ModuleLoadBase
)
1343 /* Copy image sections into virtual section */
1344 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1346 // Copy current section into current offset of virtual section
1347 if (PESectionHeaders
[Idx
].Characteristics
&
1348 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1350 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1351 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1352 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1353 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1354 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
?
1355 PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1359 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1360 PESectionHeaders
[Idx
].VirtualAddress
, PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1361 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1363 PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1365 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1366 PEOptionalHeader
->SectionAlignment
);
1369 /* Perform relocation fixups */
1370 RelocDelta
= (ULONG
) DriverBase
- PEOptionalHeader
->ImageBase
;
1371 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1372 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1373 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1375 PEOptionalHeader
->ImageBase
,
1377 ps("RelocDir %x\n",RelocDir
);
1379 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1381 if (PESectionHeaders
[Idx
].VirtualAddress
== (ULONG
)RelocDir
)
1383 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1384 PESectionHeaders
[Idx
].Name
,
1385 PESectionHeaders
[Idx
].PointerToRawData
);
1386 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+ ModuleLoadBase
;
1387 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1392 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1395 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1397 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1399 RelocEntry
= (PRELOCATION_ENTRY
)((ULONG
)RelocDir
+
1400 sizeof(RELOCATION_DIRECTORY
));
1401 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1407 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1408 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1409 RelocItem
= (PULONG
)(DriverBase
+ RelocDir
->VirtualAddress
+ Offset
);
1412 (*RelocItem
) += RelocDelta
;
1416 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1420 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1421 RelocDir
= (PRELOCATION_DIRECTORY
)((ULONG
)RelocDir
+
1422 RelocDir
->SizeOfBlock
);
1425 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1426 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1430 /* Perform import fixups */
1431 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1433 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1435 /* Process each import module */
1436 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1437 ((ULONG
)DriverBase
+ PEOptionalHeader
->
1438 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1440 ps("Processeing import directory at %p\n", ImportModuleDirectory
);
1442 /* Check to make sure that import lib is kernel */
1443 pName
= (PCHAR
)DriverBase
+ ImportModuleDirectory
->dwRVAModuleName
;
1445 ps("Import module: %s\n", pName
);
1447 /* Get the import address list */
1448 ImportAddressList
= (PVOID
*)((ULONG
)DriverBase
+
1449 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1451 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1452 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1453 ps(" ImportAddressList: 0x%X\n", ImportAddressList
);
1455 /* Get the list of functions to import */
1456 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1458 ps("Using function name list.\n");
1460 FunctionNameList
= (PULONG
)((ULONG
)DriverBase
+
1461 ImportModuleDirectory
->dwRVAFunctionNameList
);
1465 ps("Using function address list.\n");
1467 FunctionNameList
= (PULONG
)((ULONG
)DriverBase
+
1468 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1471 /* Walk through function list and fixup addresses */
1472 while (*FunctionNameList
!= 0L)
1474 if ((*FunctionNameList
) & 0x80000000)
1478 Hint
= (*FunctionNameList
) & 0xffff;
1483 pName
= (PCHAR
)((ULONG
)DriverBase
+ *FunctionNameList
+ 2);
1484 Hint
= *(PWORD
)((ULONG
)DriverBase
+ *FunctionNameList
);
1486 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1488 *ImportAddressList
= LdrSafePEGetExportAddress(ImportModuleBase
,
1492 ImportAddressList
++;
1497 ps("Finished importing.\n");
1504 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
1508 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1509 ULONG ExportDirSize
;
1511 PVOID ExportAddress
;
1513 PDWORD FunctionList
, NameList
;
1515 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1516 RtlImageDirectoryEntryToData(ModuleObject
->Base
,
1518 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1520 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir
, ExportDirSize
);
1521 if (ExportDir
== NULL
)
1526 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ModuleObject
->Base
);
1527 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ModuleObject
->Base
);
1528 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
1534 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
1537 DPRINT(" Name:%s NameList[%d]:%s\n",
1540 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
1543 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
1545 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
1546 FunctionList
[OrdinalList
[Idx
]]);
1547 if (((ULONG
)ExportAddress
>= (ULONG
)ExportDir
) &&
1548 ((ULONG
)ExportAddress
< (ULONG
)ExportDir
+ ExportDirSize
))
1550 DPRINT("Forward: %s\n", (PCHAR
)ExportAddress
);
1551 ExportAddress
= LdrPEFixupForward((PCHAR
)ExportAddress
);
1552 DPRINT("ExportAddress: %p\n", ExportAddress
);
1561 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
1562 FunctionList
[Hint
- ExportDir
->Base
]);
1565 if (ExportAddress
== NULL
)
1567 DbgPrint("Export not found for %d:%s\n",
1569 Name
!= NULL
? Name
: "(Ordinal)");
1573 return(ExportAddress
);
1578 LdrSafePEGetExportAddress(PVOID ImportModuleBase
,
1583 PVOID ExportAddress
;
1585 PDWORD FunctionList
, NameList
;
1586 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1587 ULONG ExportDirSize
;
1589 static BOOLEAN EP
= FALSE
;
1591 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1592 RtlImageDirectoryEntryToData(ImportModuleBase
,
1594 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1599 ps("ExportDir %x\n", ExportDir
);
1602 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ImportModuleBase
);
1603 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ImportModuleBase
);
1604 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ImportModuleBase
);
1610 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
1612 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ImportModuleBase
+ NameList
[Idx
])))
1614 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
1615 FunctionList
[OrdinalList
[Idx
]]);
1622 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
1624 FunctionList
[Hint
- ExportDir
->Base
]);
1627 if (ExportAddress
== 0)
1629 ps("Export not found for %d:%s\n",
1631 Name
!= NULL
? Name
: "(Ordinal)");
1634 return ExportAddress
;
1639 LdrPEFixupForward(PCHAR ForwardName
)
1641 CHAR NameBuffer
[128];
1642 UNICODE_STRING ModuleName
;
1644 PMODULE_OBJECT ModuleObject
;
1646 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1648 strcpy(NameBuffer
, ForwardName
);
1649 p
= strchr(NameBuffer
, '.');
1657 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1659 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1661 ModuleObject
= LdrGetModuleObject(&ModuleName
);
1662 RtlFreeUnicodeString(&ModuleName
);
1664 DPRINT("ModuleObject: %p\n", ModuleObject
);
1666 if (ModuleObject
== NULL
)
1668 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1672 return(LdrPEGetExportAddress(ModuleObject
, p
+1, 0));