1 /* $Id: loader.c,v 1.71 2001/03/30 17:26:42 dwelch 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)
12 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
13 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
14 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
15 * JM 14/12/98 Built initial PE user module loader
16 * RJJ 06/03/99 Moved user PE loader into NTDLL
17 * JF 26/01/2000 Recoded some parts to retrieve export details correctly
18 * DW 27/06/00 Removed redundant header files
21 /* INCLUDES *****************************************************************/
24 #include <ddk/ntddk.h>
25 #include <internal/module.h>
26 #include <internal/ntoskrnl.h>
27 #include <internal/mm.h>
28 #include <internal/ob.h>
29 #include <internal/ps.h>
30 #include <internal/ldr.h>
31 #include <internal/pool.h>
34 #include <internal/debug.h>
37 /* FIXME: this should appear in a kernel header file */
38 NTSTATUS
IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry
);
40 /* MACROS ********************************************************************/
42 #define MODULE_ROOT_NAME L"\\Modules\\"
44 /* GLOBALS *******************************************************************/
46 LIST_ENTRY ModuleListHead
;
47 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
48 LIST_ENTRY ModuleTextListHead
;
49 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
50 /* STATIC MODULE_TEXT_SECTION HalTextSection; */
52 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
53 #define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
55 /* FORWARD DECLARATIONS ******************************************************/
57 PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename
);
58 PMODULE_OBJECT
LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
59 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
60 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
61 static NTSTATUS
LdrCreateModule(PVOID ObjectBody
,
64 POBJECT_ATTRIBUTES ObjectAttributes
);
65 static VOID
LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
66 PUNICODE_STRING FullName
);
68 /* PE Driver load support */
69 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING FileName
);
70 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
73 static PMODULE_OBJECT
LdrPEGetModuleObject(PUNICODE_STRING ModuleName
);
74 static PVOID
LdrPEFixupForward(PCHAR ForwardName
);
77 /* FUNCTIONS *****************************************************************/
82 PIMAGE_DOS_HEADER DosHeader
;
83 PIMAGE_FILE_HEADER FileHeader
;
84 PIMAGE_OPTIONAL_HEADER OptionalHeader
;
85 PIMAGE_SECTION_HEADER SectionList
;
87 InitializeListHead(&ModuleTextListHead
);
89 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
91 (PIMAGE_FILE_HEADER
) ((DWORD
)KERNEL_BASE
+
92 DosHeader
->e_lfanew
+ sizeof(ULONG
));
93 OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
94 ((DWORD
)FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
95 SectionList
= (PIMAGE_SECTION_HEADER
)
96 ((DWORD
)OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
97 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
98 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
99 SectionList
[0].VirtualAddress
;
100 NtoskrnlTextSection
.Name
= L
"ntoskrnl.exe";
101 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
104 VOID
LdrInitModuleManagement(VOID
)
106 HANDLE DirHandle
, ModuleHandle
;
108 WCHAR NameBuffer
[60];
109 UNICODE_STRING ModuleName
;
110 OBJECT_ATTRIBUTES ObjectAttributes
;
111 PIMAGE_DOS_HEADER DosHeader
;
112 PMODULE_OBJECT ModuleObject
;
114 /* Register the process object type */
115 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
116 IoDriverObjectType
->Tag
= TAG('D', 'R', 'V', 'T');
117 IoDriverObjectType
->TotalObjects
= 0;
118 IoDriverObjectType
->TotalHandles
= 0;
119 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
120 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
121 IoDriverObjectType
->PagedPoolCharge
= 0;
122 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(MODULE
);
123 IoDriverObjectType
->Dump
= NULL
;
124 IoDriverObjectType
->Open
= NULL
;
125 IoDriverObjectType
->Close
= NULL
;
126 IoDriverObjectType
->Delete
= NULL
;
127 IoDriverObjectType
->Parse
= NULL
;
128 IoDriverObjectType
->Security
= NULL
;
129 IoDriverObjectType
->QueryName
= NULL
;
130 IoDriverObjectType
->OkayToClose
= NULL
;
131 IoDriverObjectType
->Create
= LdrCreateModule
;
132 RtlInitUnicodeString(&IoDriverObjectType
->TypeName
, L
"Driver");
134 /* Create Modules object directory */
135 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
136 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
137 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
138 InitializeObjectAttributes(&ObjectAttributes
,
143 DPRINT("Create dir: %wZ\n", &ModuleName
);
144 Status
= NtCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
145 assert(NT_SUCCESS(Status
));
147 /* Add module entry for NTOSKRNL */
148 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
149 wcscat(NameBuffer
, L
"ntoskrnl.exe");
150 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
151 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName
);
153 /* Initialize ObjectAttributes for ModuleObject */
154 InitializeObjectAttributes(&ObjectAttributes
,
160 /* Create module object */
162 ModuleObject
= ObCreateObject(&ModuleHandle
,
163 STANDARD_RIGHTS_REQUIRED
,
166 assert(ModuleObject
!= NULL
);
168 InitializeListHead(&ModuleListHead
);
170 /* Initialize ModuleObject data */
171 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
172 ModuleObject
->Flags
= MODULE_FLAG_PE
;
173 InsertTailList(&ModuleListHead
,
174 &ModuleObject
->ListEntry
);
175 RtlCreateUnicodeString(&ModuleObject
->FullName
,
177 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
178 &ModuleObject
->FullName
);
180 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
181 ModuleObject
->Image
.PE
.FileHeader
=
182 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
183 DosHeader
->e_lfanew
+ sizeof(ULONG
));
184 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
185 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
186 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
187 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
188 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
189 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
190 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
191 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
193 /* FIXME: Add fake module entry for HAL */
198 * load the auto config drivers.
200 static VOID
LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName
)
202 WCHAR TmpFileName
[MAX_PATH
];
204 UNICODE_STRING DriverName
;
206 DbgPrint("Loading %S\n",RelativeDriverName
);
208 wcscpy(TmpFileName
, L
"\\SystemRoot\\system32\\drivers\\");
209 wcscat(TmpFileName
, RelativeDriverName
);
210 RtlInitUnicodeString (&DriverName
, TmpFileName
);
212 Status
= LdrLoadDriver(&DriverName
);
213 if (!NT_SUCCESS(Status
))
215 DbgPrint("driver load failed, status (%x)\n", Status
);
221 VOID
LdrLoadAutoConfigDrivers (VOID
)
226 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
231 LdrLoadAutoConfigDriver( L
"blue.sys" );
236 LdrLoadAutoConfigDriver(L
"vidport.sys");
241 LdrLoadAutoConfigDriver(L
"vgamp.sys");
244 * Minix filesystem driver
246 LdrLoadAutoConfigDriver(L
"minixfs.sys");
251 LdrCreateModule(PVOID ObjectBody
,
254 POBJECT_ATTRIBUTES ObjectAttributes
)
256 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
260 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
262 return STATUS_UNSUCCESSFUL
;
264 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
266 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
269 return STATUS_SUCCESS
;
273 * FUNCTION: Loads a kernel driver
275 * FileName = Driver to load
279 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
)
281 PMODULE_OBJECT ModuleObject
;
283 ModuleObject
= LdrLoadModule(Filename
);
284 if (ModuleObject
== 0)
286 return STATUS_UNSUCCESSFUL
;
289 /* FIXME: should we dereference the ModuleObject here? */
291 return IoInitializeDriver(ModuleObject
->EntryPoint
);
294 NTSTATUS
LdrLoadGdiDriver (PUNICODE_STRING DriverName
,
296 PVOID
*SectionPointer
,
298 PVOID
*ExportSectionPointer
)
300 PMODULE_OBJECT ModuleObject
;
302 ModuleObject
= LdrLoadModule(DriverName
);
303 if (ModuleObject
== 0)
305 return STATUS_UNSUCCESSFUL
;
309 *ImageAddress
= ModuleObject
->Base
;
311 // if (SectionPointer)
312 // *SectionPointer = ModuleObject->
315 *EntryPoint
= ModuleObject
->EntryPoint
;
317 // if (ExportSectionPointer)
318 // *ExportSectionPointer = ModuleObject->
320 return STATUS_SUCCESS
;
325 LdrLoadModule(PUNICODE_STRING Filename
)
327 PVOID ModuleLoadBase
;
330 OBJECT_ATTRIBUTES ObjectAttributes
;
331 PMODULE_OBJECT ModuleObject
;
332 FILE_STANDARD_INFORMATION FileStdInfo
;
334 /* Check for module already loaded */
335 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
340 DPRINT("Loading Module %wZ...\n", Filename
);
342 /* Open the Module */
343 InitializeObjectAttributes(&ObjectAttributes
,
349 Status
= NtOpenFile(&FileHandle
,
354 if (!NT_SUCCESS(Status
))
356 DbgPrint("Could not open module file: %wZ\n", Filename
);
361 /* Get the size of the file */
362 Status
= NtQueryInformationFile(FileHandle
,
366 FileStandardInformation
);
367 if (!NT_SUCCESS(Status
))
369 DbgPrint("Could not get file size\n");
374 /* Allocate nonpageable memory for driver */
375 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
376 FileStdInfo
.EndOfFile
.u
.LowPart
,
379 if (ModuleLoadBase
== NULL
)
381 DbgPrint("could not allocate memory for module");
386 /* Load driver into memory chunk */
387 Status
= NtReadFile(FileHandle
,
390 FileStdInfo
.EndOfFile
.u
.LowPart
,
392 if (!NT_SUCCESS(Status
))
394 DbgPrint("could not read module file into memory");
395 ExFreePool(ModuleLoadBase
);
403 ModuleObject
= LdrProcessModule(ModuleLoadBase
, Filename
);
406 ExFreePool(ModuleLoadBase
);
412 LdrProcessDriver(PVOID ModuleLoadBase
, PCHAR FileName
)
414 PMODULE_OBJECT ModuleObject
;
415 UNICODE_STRING ModuleName
;
417 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
419 ModuleObject
= LdrProcessModule(ModuleLoadBase
,
421 RtlFreeUnicodeString(&ModuleName
);
422 if (ModuleObject
== NULL
)
424 DPRINT1("Driver load was unsuccessful\n");
425 return(STATUS_UNSUCCESSFUL
);
428 /* FIXME: should we dereference the ModuleObject here? */
430 return(IoInitializeDriver(ModuleObject
->EntryPoint
));
434 LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
)
436 PIMAGE_DOS_HEADER PEDosHeader
;
438 /* If MZ header exists */
439 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
440 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
442 return LdrPEProcessModule(ModuleLoadBase
, ModuleName
);
445 DPRINT1("Module wasn't PE\n");
449 static PMODULE_OBJECT
450 LdrOpenModule(PUNICODE_STRING Filename
)
453 WCHAR NameBuffer
[60];
454 UNICODE_STRING ModuleName
;
455 OBJECT_ATTRIBUTES ObjectAttributes
;
456 PMODULE_OBJECT ModuleObject
;
457 UNICODE_STRING RemainingPath
;
459 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
460 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
462 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
466 wcscat(NameBuffer
, Filename
->Buffer
);
468 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
469 InitializeObjectAttributes(&ObjectAttributes
,
475 Status
= ObFindObject(&ObjectAttributes
,
476 (PVOID
*) &ModuleObject
,
480 if (NT_SUCCESS(Status
) && (RemainingPath
.Buffer
== NULL
|| *(RemainingPath
.Buffer
) == 0))
482 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
483 RtlFreeUnicodeString (&RemainingPath
);
488 RtlFreeUnicodeString (&RemainingPath
);
494 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
498 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
500 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
509 LdrpQueryModuleInformation(PVOID Buffer
,
513 PLIST_ENTRY current_entry
;
514 PMODULE_OBJECT current
;
515 ULONG ModuleCount
= 0;
516 PSYSTEM_MODULE_INFORMATION Smi
;
517 ANSI_STRING AnsiName
;
520 // KeAcquireSpinLock(&ModuleListLock,&oldlvl);
522 /* calculate required size */
523 current_entry
= ModuleListHead
.Flink
;
524 while (current_entry
!= (&ModuleListHead
))
527 current_entry
= current_entry
->Flink
;
530 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
531 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_ENTRY
);
535 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
536 return STATUS_INFO_LENGTH_MISMATCH
;
539 /* fill the buffer */
540 memset(Buffer
, '=', Size
);
542 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
543 Smi
->Count
= ModuleCount
;
546 current_entry
= ModuleListHead
.Flink
;
547 while (current_entry
!= (&ModuleListHead
))
549 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
551 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
552 Smi
->Module
[ModuleCount
].BaseAddress
= current
->Base
;
553 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
554 Smi
->Module
[ModuleCount
].Unknown3
= 0; /* Flags ??? */
555 Smi
->Module
[ModuleCount
].EntryIndex
= ModuleCount
;
558 AnsiName
.MaximumLength
= 256;
559 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].Name
;
560 RtlUnicodeStringToAnsiString(&AnsiName
,
564 p
= strrchr (AnsiName
.Buffer
, '\\');
567 Smi
->Module
[ModuleCount
].PathLength
= 0;
568 Smi
->Module
[ModuleCount
].NameLength
= strlen(AnsiName
.Buffer
);
573 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
574 Smi
->Module
[ModuleCount
].NameLength
= strlen(p
);
578 current_entry
= current_entry
->Flink
;
581 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
583 return STATUS_SUCCESS
;
588 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
589 PUNICODE_STRING FullName
)
595 DPRINT("LdrpBuildModuleBaseName()\n");
596 DPRINT("FullName %wZ\n", FullName
);
598 p
= wcsrchr(FullName
->Buffer
, '\\');
601 p
= FullName
->Buffer
;
610 RtlCreateUnicodeString(&Name
, p
);
620 RtlCreateUnicodeString(BaseName
, p
);
621 RtlFreeUnicodeString(&Name
);
625 /* ---------------------------------------------- PE Module support */
628 LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING FileName
)
630 unsigned int DriverSize
, Idx
, Idx2
;
631 ULONG RelocDelta
, NumRelocs
;
632 DWORD CurrentSize
, TotalRelocs
;
635 PIMAGE_DOS_HEADER PEDosHeader
;
636 PIMAGE_FILE_HEADER PEFileHeader
;
637 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
638 PIMAGE_SECTION_HEADER PESectionHeaders
;
639 PRELOCATION_DIRECTORY RelocDir
;
640 PRELOCATION_ENTRY RelocEntry
;
641 PMODULE_OBJECT LibraryModuleObject
;
643 PMODULE_OBJECT ModuleObject
;
644 PVOID
*ImportAddressList
;
645 PULONG FunctionNameList
;
646 PCHAR pName
, SymbolNameBuf
;
648 OBJECT_ATTRIBUTES ObjectAttributes
;
649 UNICODE_STRING ModuleName
;
650 WCHAR NameBuffer
[60];
651 MODULE_TEXT_SECTION
* ModuleTextSection
;
653 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
655 /* Get header pointers */
656 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
657 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
658 PEDosHeader
->e_lfanew
);
659 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
660 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
661 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
662 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
663 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
664 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
665 sizeof(IMAGE_OPTIONAL_HEADER
));
668 /* Check file magic numbers */
669 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
671 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
674 if (PEDosHeader
->e_lfanew
== 0)
676 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
679 if (*PEMagic
!= IMAGE_PE_MAGIC
)
681 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
684 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
686 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
691 /* FIXME: if image is fixed-address load, then fail */
693 /* FIXME: check/verify OS version number */
695 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
696 PEOptionalHeader
->Magic
,
697 PEOptionalHeader
->MajorLinkerVersion
,
698 PEOptionalHeader
->MinorLinkerVersion
);
699 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
702 /* Determine the size of the module */
703 DriverSize
= PEOptionalHeader
->SizeOfImage
;
704 DPRINT("DriverSize %x\n",DriverSize
);
706 /* Allocate a virtual section for the module */
707 DriverBase
= MmAllocateSection(DriverSize
);
710 DbgPrint("Failed to allocate a virtual section for driver\n");
713 DbgPrint("DriverBase: %x\n", DriverBase
);
715 /* Copy headers over */
716 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
718 /* Copy image sections into virtual section */
719 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
721 // Copy current section into current offset of virtual section
722 if (PESectionHeaders
[Idx
].Characteristics
&
723 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
725 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
726 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
727 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
728 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
729 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
733 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
734 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
735 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
736 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
739 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
740 PEOptionalHeader
->SectionAlignment
);
743 // CurrentBase = (PVOID)((DWORD)CurrentBase +
744 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
745 // PEOptionalHeader->SectionAlignment));
748 /* Perform relocation fixups */
749 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
750 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
751 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
752 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
754 PEOptionalHeader
->ImageBase
,
756 DPRINT("RelocDir %x\n",RelocDir
);
758 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
760 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
762 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
763 PESectionHeaders
[Idx
].Name
,
764 PESectionHeaders
[Idx
].PointerToRawData
);
765 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
767 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
772 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
773 CurrentSize
= PEOptionalHeader
->DataDirectory
774 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
776 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
778 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
780 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
782 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
784 RelocDir->VirtualAddress,
786 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
787 sizeof(RELOCATION_DIRECTORY
));
788 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
794 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
795 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
796 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
798 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
801 Type ? "HIGHLOW" : "ABS",
803 (*RelocItem) + RelocDelta); */
806 (*RelocItem
) += RelocDelta
;
810 DbgPrint("Unknown relocation type %x at %x\n",Type
, &Type
);
814 TotalRelocs
+= RelocDir
->SizeOfBlock
;
815 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
816 RelocDir
->SizeOfBlock
);
817 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
820 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
821 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
823 /* Perform import fixups */
824 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
826 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
828 SymbolNameBuf
= ExAllocatePoolWithTag(NonPagedPool
, 512, TAG_SYM_BUF
);
830 /* Process each import module */
831 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
832 ((DWORD
)DriverBase
+ PEOptionalHeader
->
833 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
834 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
835 while (ImportModuleDirectory
->dwRVAModuleName
)
837 /* Check to make sure that import lib is kernel */
838 pName
= (PCHAR
) DriverBase
+
839 ImportModuleDirectory
->dwRVAModuleName
;
840 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
841 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
843 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
845 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
847 NameBuffer
[Idx
+ Idx2
] = 0;
848 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
849 DPRINT("Import module: %wZ\n", &ModuleName
);
851 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
852 if (LibraryModuleObject
== 0)
854 DbgPrint("Unknown import module: %wZ\n", &ModuleName
);
856 /* Get the import address list */
857 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
858 ImportModuleDirectory
->dwRVAFunctionAddressList
);
860 /* Get the list of functions to import */
861 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
863 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
864 ImportModuleDirectory
->dwRVAFunctionNameList
);
868 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
869 ImportModuleDirectory
->dwRVAFunctionAddressList
);
871 /* Walk through function list and fixup addresses */
872 while (*FunctionNameList
!= 0L)
874 if ((*FunctionNameList
) & 0x80000000) // hint
879 Hint
= (*FunctionNameList
) & 0xffff;
883 pName
= (PCHAR
)((DWORD
)DriverBase
+
884 *FunctionNameList
+ 2);
885 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
887 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
889 /* Fixup the current import symbol */
890 if (LibraryModuleObject
!= NULL
)
892 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
898 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
904 ImportModuleDirectory
++;
907 ExFreePool(SymbolNameBuf
);
910 /* Create ModuleName string */
911 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
912 if (wcsrchr(FileName
->Buffer
, '\\') != 0)
914 wcscat(NameBuffer
, wcsrchr(FileName
->Buffer
, '\\') + 1);
918 wcscat(NameBuffer
, FileName
->Buffer
);
920 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
921 DbgPrint("Module name is: %wZ\n", &ModuleName
);
923 /* Initialize ObjectAttributes for ModuleObject */
924 InitializeObjectAttributes(&ObjectAttributes
,
930 /* Create module object */
932 ModuleObject
= ObCreateObject(&ModuleHandle
,
933 STANDARD_RIGHTS_REQUIRED
,
937 /* Initialize ModuleObject data */
938 ModuleObject
->Base
= DriverBase
;
939 ModuleObject
->Flags
= MODULE_FLAG_PE
;
940 InsertTailList(&ModuleListHead
,
941 &ModuleObject
->ListEntry
);
942 RtlCreateUnicodeString(&ModuleObject
->FullName
,
944 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
945 &ModuleObject
->FullName
);
947 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
948 PEOptionalHeader
->AddressOfEntryPoint
);
949 ModuleObject
->Length
= DriverSize
;
950 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
952 ModuleObject
->Image
.PE
.FileHeader
=
953 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
955 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
956 ModuleObject
->Image
.PE
.OptionalHeader
=
957 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
958 sizeof(IMAGE_FILE_HEADER
));
959 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
960 ModuleObject
->Image
.PE
.SectionList
=
961 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
962 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
963 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
965 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
966 sizeof(MODULE_TEXT_SECTION
));
967 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
968 ModuleTextSection
->Length
= DriverSize
;
969 ModuleTextSection
->Name
=
970 ExAllocatePool(NonPagedPool
,
971 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
972 wcscpy(ModuleTextSection
->Name
, NameBuffer
);
973 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
979 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
986 PDWORD FunctionList
, NameList
;
987 PIMAGE_EXPORT_DIRECTORY ExportDir
;
990 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
991 RtlImageDirectoryEntryToData(ModuleObject
->Base
,
993 IMAGE_DIRECTORY_ENTRY_EXPORT
,
995 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir
, ExportDirSize
);
996 if (ExportDir
== NULL
)
1002 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ModuleObject
->Base
);
1003 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ModuleObject
->Base
);
1004 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
1010 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
1013 DPRINT(" Name:%s NameList[%d]:%s\n",
1016 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
1019 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
1021 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
1022 FunctionList
[OrdinalList
[Idx
]]);
1023 if (((ULONG
)ExportAddress
>= (ULONG
)ExportDir
) &&
1024 ((ULONG
)ExportAddress
< (ULONG
)ExportDir
+ ExportDirSize
))
1026 DPRINT("Forward: %s\n", (PCHAR
)ExportAddress
);
1027 ExportAddress
= LdrPEFixupForward((PCHAR
)ExportAddress
);
1028 DPRINT("ExportAddress: %p\n", ExportAddress
);
1037 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
1038 FunctionList
[Hint
- ExportDir
->Base
]);
1041 if (ExportAddress
== 0)
1043 DbgPrint("Export not found for %d:%s\n",
1045 Name
!= NULL
? Name
: "(Ordinal)");
1049 return ExportAddress
;
1053 static PMODULE_OBJECT
1054 LdrPEGetModuleObject(PUNICODE_STRING ModuleName
)
1057 PMODULE_OBJECT Module
;
1059 DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
1062 Entry
= ModuleListHead
.Flink
;
1064 while (Entry
!= &ModuleListHead
)
1066 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
1068 DPRINT("Comparing %wZ and %wZ\n",
1072 if (!RtlCompareUnicodeString(&Module
->BaseName
, ModuleName
, TRUE
))
1074 DPRINT("Module %x\n", Module
);
1078 Entry
= Entry
->Flink
;
1081 DbgPrint("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName
);
1088 LdrPEFixupForward(PCHAR ForwardName
)
1090 CHAR NameBuffer
[128];
1091 UNICODE_STRING ModuleName
;
1093 PMODULE_OBJECT ModuleObject
;
1095 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
1097 strcpy(NameBuffer
, ForwardName
);
1098 p
= strchr(NameBuffer
, '.');
1106 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
1108 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1110 ModuleObject
= LdrPEGetModuleObject(&ModuleName
);
1111 RtlFreeUnicodeString(&ModuleName
);
1113 DPRINT("ModuleObject: %p\n", ModuleObject
);
1115 if (ModuleObject
== NULL
)
1117 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
1121 return LdrPEGetExportAddress(ModuleObject
, p
+1, 0);