1 /* $Id: loader.c,v 1.66 2001/01/18 16:55:00 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ldr/loader.c
6 * PURPOSE: Loaders for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
9 * Jason Filby (jasonfilby@yahoo.com)
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/mmhal.h>
29 #include <internal/ob.h>
30 #include <internal/ps.h>
31 #include <internal/ldr.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
;
49 /* FORWARD DECLARATIONS ******************************************************/
51 PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename
);
52 PMODULE_OBJECT
LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
53 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
54 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
55 static NTSTATUS
LdrCreateModule(PVOID ObjectBody
,
58 POBJECT_ATTRIBUTES ObjectAttributes
);
60 /* PE Driver load support */
61 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING FileName
);
62 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
66 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
68 static PIMAGE_SECTION_HEADER
LdrPEGetEnclosingSectionHeader(DWORD RVA
,
69 PMODULE_OBJECT ModuleObject
);
71 /* FUNCTIONS *****************************************************************/
73 VOID
LdrInitModuleManagement(VOID
)
75 HANDLE DirHandle
, ModuleHandle
;
78 UNICODE_STRING ModuleName
;
79 OBJECT_ATTRIBUTES ObjectAttributes
;
80 PIMAGE_DOS_HEADER DosHeader
;
81 PMODULE_OBJECT ModuleObject
;
83 /* Register the process object type */
84 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
85 IoDriverObjectType
->TotalObjects
= 0;
86 IoDriverObjectType
->TotalHandles
= 0;
87 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
88 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
89 IoDriverObjectType
->PagedPoolCharge
= 0;
90 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(MODULE
);
91 IoDriverObjectType
->Dump
= NULL
;
92 IoDriverObjectType
->Open
= NULL
;
93 IoDriverObjectType
->Close
= NULL
;
94 IoDriverObjectType
->Delete
= NULL
;
95 IoDriverObjectType
->Parse
= NULL
;
96 IoDriverObjectType
->Security
= NULL
;
97 IoDriverObjectType
->QueryName
= NULL
;
98 IoDriverObjectType
->OkayToClose
= NULL
;
99 IoDriverObjectType
->Create
= LdrCreateModule
;
100 RtlInitUnicodeString(&IoDriverObjectType
->TypeName
, L
"Driver");
102 /* Create Modules object directory */
103 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
104 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
105 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
106 InitializeObjectAttributes(&ObjectAttributes
,
111 DPRINT("Create dir: %wZ\n", &ModuleName
);
112 Status
= NtCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
113 assert(NT_SUCCESS(Status
));
115 /* Add module entry for NTOSKRNL */
116 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
117 wcscat(NameBuffer
, L
"ntoskrnl.exe");
118 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
119 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName
);
121 /* Initialize ObjectAttributes for ModuleObject */
122 InitializeObjectAttributes(&ObjectAttributes
,
128 /* Create module object */
130 ModuleObject
= ObCreateObject(&ModuleHandle
,
131 STANDARD_RIGHTS_REQUIRED
,
134 assert(ModuleObject
!= NULL
);
136 InitializeListHead(&ModuleListHead
);
138 /* Initialize ModuleObject data */
139 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
140 ModuleObject
->Flags
= MODULE_FLAG_PE
;
141 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
142 RtlCreateUnicodeString(&ModuleObject
->Name
,
144 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
145 ModuleObject
->Image
.PE
.FileHeader
=
146 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
147 DosHeader
->e_lfanew
+ sizeof(ULONG
));
148 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
149 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
150 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
151 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
152 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
153 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
154 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
155 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
157 /* FIXME: Add fake module entry for HAL */
162 * load the auto config drivers.
164 static VOID
LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName
)
166 WCHAR TmpFileName
[MAX_PATH
];
168 UNICODE_STRING DriverName
;
170 DbgPrint("Loading %S\n",RelativeDriverName
);
172 wcscpy(TmpFileName
, L
"\\SystemRoot\\system32\\drivers\\");
173 wcscat(TmpFileName
, RelativeDriverName
);
174 RtlInitUnicodeString (&DriverName
, TmpFileName
);
176 Status
= LdrLoadDriver(&DriverName
);
177 if (!NT_SUCCESS(Status
))
179 DbgPrint("driver load failed, status (%x)\n", Status
);
185 VOID
LdrLoadAutoConfigDrivers (VOID
)
190 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
195 LdrLoadAutoConfigDriver( L
"blue.sys" );
200 LdrLoadAutoConfigDriver(L
"vidport.sys");
205 LdrLoadAutoConfigDriver(L
"vgamp.sys");
208 * Minix filesystem driver
210 LdrLoadAutoConfigDriver(L
"minixfs.sys");
215 LdrCreateModule(PVOID ObjectBody
,
218 POBJECT_ATTRIBUTES ObjectAttributes
)
220 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
224 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
226 return STATUS_UNSUCCESSFUL
;
228 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
230 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
233 return STATUS_SUCCESS
;
237 * FUNCTION: Loads a kernel driver
239 * FileName = Driver to load
243 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
)
245 PMODULE_OBJECT ModuleObject
;
247 ModuleObject
= LdrLoadModule(Filename
);
248 if (ModuleObject
== 0)
250 return STATUS_UNSUCCESSFUL
;
253 /* FIXME: should we dereference the ModuleObject here? */
255 return IoInitializeDriver(ModuleObject
->EntryPoint
);
258 NTSTATUS
LdrLoadGdiDriver (PUNICODE_STRING DriverName
,
260 PVOID
*SectionPointer
,
262 PVOID
*ExportSectionPointer
)
264 PMODULE_OBJECT ModuleObject
;
266 ModuleObject
= LdrLoadModule(DriverName
);
267 if (ModuleObject
== 0)
269 return STATUS_UNSUCCESSFUL
;
273 *ImageAddress
= ModuleObject
->Base
;
275 // if (SectionPointer)
276 // *SectionPointer = ModuleObject->
279 *EntryPoint
= ModuleObject
->EntryPoint
;
281 // if (ExportSectionPointer)
282 // *ExportSectionPointer = ModuleObject->
284 return STATUS_SUCCESS
;
289 LdrLoadModule(PUNICODE_STRING Filename
)
291 PVOID ModuleLoadBase
;
294 OBJECT_ATTRIBUTES ObjectAttributes
;
295 PMODULE_OBJECT ModuleObject
;
296 FILE_STANDARD_INFORMATION FileStdInfo
;
298 /* Check for module already loaded */
299 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
304 DPRINT("Loading Module %wZ...\n", Filename
);
306 /* Open the Module */
307 InitializeObjectAttributes(&ObjectAttributes
,
313 Status
= NtOpenFile(&FileHandle
,
318 if (!NT_SUCCESS(Status
))
320 DbgPrint("Could not open module file: %wZ\n", Filename
);
325 /* Get the size of the file */
326 Status
= NtQueryInformationFile(FileHandle
,
330 FileStandardInformation
);
331 if (!NT_SUCCESS(Status
))
333 DbgPrint("Could not get file size\n");
338 /* Allocate nonpageable memory for driver */
339 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
340 FileStdInfo
.EndOfFile
.u
.LowPart
);
342 if (ModuleLoadBase
== NULL
)
344 DbgPrint("could not allocate memory for module");
349 /* Load driver into memory chunk */
350 Status
= NtReadFile(FileHandle
,
353 FileStdInfo
.EndOfFile
.u
.LowPart
,
355 if (!NT_SUCCESS(Status
))
357 DbgPrint("could not read module file into memory");
358 ExFreePool(ModuleLoadBase
);
366 ModuleObject
= LdrProcessModule(ModuleLoadBase
, Filename
);
369 ExFreePool(ModuleLoadBase
);
375 LdrProcessDriver(PVOID ModuleLoadBase
, PCHAR FileName
)
377 PMODULE_OBJECT ModuleObject
;
378 UNICODE_STRING ModuleName
;
380 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
382 ModuleObject
= LdrProcessModule(ModuleLoadBase
,
384 RtlFreeUnicodeString(&ModuleName
);
385 if (ModuleObject
== NULL
)
387 return STATUS_UNSUCCESSFUL
;
390 /* FIXME: should we dereference the ModuleObject here? */
392 return IoInitializeDriver(ModuleObject
->EntryPoint
);
396 LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
)
398 PIMAGE_DOS_HEADER PEDosHeader
;
400 /* If MZ header exists */
401 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
402 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
404 return LdrPEProcessModule(ModuleLoadBase
, ModuleName
);
410 static PMODULE_OBJECT
411 LdrOpenModule(PUNICODE_STRING Filename
)
414 WCHAR NameBuffer
[60];
415 UNICODE_STRING ModuleName
;
416 OBJECT_ATTRIBUTES ObjectAttributes
;
417 PMODULE_OBJECT ModuleObject
;
418 UNICODE_STRING RemainingPath
;
420 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
421 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
423 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
427 wcscat(NameBuffer
, Filename
->Buffer
);
429 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
430 InitializeObjectAttributes(&ObjectAttributes
,
436 Status
= ObFindObject(&ObjectAttributes
,
437 (PVOID
*) &ModuleObject
,
441 if (NT_SUCCESS(Status
) && (RemainingPath
.Buffer
== NULL
|| *(RemainingPath
.Buffer
) == 0))
443 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
444 RtlFreeUnicodeString (&RemainingPath
);
449 RtlFreeUnicodeString (&RemainingPath
);
455 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
459 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
461 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
470 LdrpQueryModuleInformation(PVOID Buffer
,
474 PLIST_ENTRY current_entry
;
475 PMODULE_OBJECT current
;
476 ULONG ModuleCount
= 0;
477 PSYSTEM_MODULE_INFORMATION Smi
;
478 ANSI_STRING AnsiName
;
481 // KeAcquireSpinLock(&ModuleListLock,&oldlvl);
483 /* calculate required size */
484 current_entry
= ModuleListHead
.Flink
;
485 while (current_entry
!= (&ModuleListHead
))
488 current_entry
= current_entry
->Flink
;
491 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
492 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_ENTRY
);
496 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
497 return STATUS_INFO_LENGTH_MISMATCH
;
500 /* fill the buffer */
501 memset(Buffer
, '=', Size
);
503 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
504 Smi
->Count
= ModuleCount
;
507 current_entry
= ModuleListHead
.Flink
;
508 while (current_entry
!= (&ModuleListHead
))
510 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
512 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
513 Smi
->Module
[ModuleCount
].BaseAddress
= current
->Base
;
514 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
515 Smi
->Module
[ModuleCount
].Unknown3
= 0; /* Flags ??? */
516 Smi
->Module
[ModuleCount
].EntryIndex
= ModuleCount
;
519 AnsiName
.MaximumLength
= 256;
520 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].Name
;
521 RtlUnicodeStringToAnsiString(&AnsiName
,
525 p
= strrchr (AnsiName
.Buffer
, '\\');
528 Smi
->Module
[ModuleCount
].PathLength
= 0;
529 Smi
->Module
[ModuleCount
].NameLength
= strlen(AnsiName
.Buffer
);
534 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
535 Smi
->Module
[ModuleCount
].NameLength
= strlen(p
);
539 current_entry
= current_entry
->Flink
;
542 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
544 return STATUS_SUCCESS
;
547 /* ---------------------------------------------- PE Module support */
550 LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING FileName
)
552 unsigned int DriverSize
, Idx
, Idx2
;
553 ULONG RelocDelta
, NumRelocs
;
554 DWORD CurrentSize
, TotalRelocs
;
557 PIMAGE_DOS_HEADER PEDosHeader
;
558 PIMAGE_FILE_HEADER PEFileHeader
;
559 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
560 PIMAGE_SECTION_HEADER PESectionHeaders
;
561 PRELOCATION_DIRECTORY RelocDir
;
562 PRELOCATION_ENTRY RelocEntry
;
563 PMODULE_OBJECT LibraryModuleObject
;
565 PMODULE_OBJECT ModuleObject
;
566 PVOID
*ImportAddressList
;
567 PULONG FunctionNameList
;
568 PCHAR pName
, SymbolNameBuf
;
570 OBJECT_ATTRIBUTES ObjectAttributes
;
571 UNICODE_STRING ModuleName
;
572 WCHAR NameBuffer
[60];
574 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
576 /* Get header pointers */
577 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
578 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
579 PEDosHeader
->e_lfanew
);
580 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
581 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
582 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
583 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
584 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
585 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
586 sizeof(IMAGE_OPTIONAL_HEADER
));
589 /* Check file magic numbers */
590 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
592 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
595 if (PEDosHeader
->e_lfanew
== 0)
597 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
600 if (*PEMagic
!= IMAGE_PE_MAGIC
)
602 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
605 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
607 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
612 /* FIXME: if image is fixed-address load, then fail */
614 /* FIXME: check/verify OS version number */
616 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
617 PEOptionalHeader
->Magic
,
618 PEOptionalHeader
->MajorLinkerVersion
,
619 PEOptionalHeader
->MinorLinkerVersion
);
620 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
623 /* Determine the size of the module */
624 DriverSize
= PEOptionalHeader
->SizeOfImage
;
625 DPRINT("DriverSize %x\n",DriverSize
);
627 /* Allocate a virtual section for the module */
628 DriverBase
= MmAllocateSection(DriverSize
);
631 DbgPrint("Failed to allocate a virtual section for driver\n");
634 DbgPrint("DriverBase: %x\n", DriverBase
);
636 /* Copy headers over */
637 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
639 /* Copy image sections into virtual section */
640 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
642 // Copy current section into current offset of virtual section
643 if (PESectionHeaders
[Idx
].Characteristics
&
644 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
646 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
647 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
648 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
649 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
650 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
654 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
655 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
656 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
657 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
660 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
661 PEOptionalHeader
->SectionAlignment
);
664 // CurrentBase = (PVOID)((DWORD)CurrentBase +
665 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
666 // PEOptionalHeader->SectionAlignment));
669 /* Perform relocation fixups */
670 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
671 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
672 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
673 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
675 PEOptionalHeader
->ImageBase
,
677 DPRINT("RelocDir %x\n",RelocDir
);
679 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
681 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
683 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
684 PESectionHeaders
[Idx
].Name
,
685 PESectionHeaders
[Idx
].PointerToRawData
);
686 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
688 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
693 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
694 CurrentSize
= PEOptionalHeader
->DataDirectory
695 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
697 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
699 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
701 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
703 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
705 RelocDir->VirtualAddress,
707 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
708 sizeof(RELOCATION_DIRECTORY
));
709 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
715 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
716 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
717 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
719 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
722 Type ? "HIGHLOW" : "ABS",
724 (*RelocItem) + RelocDelta); */
727 (*RelocItem
) += RelocDelta
;
731 DbgPrint("Unknown relocation type %x at %x\n",Type
, &Type
);
735 TotalRelocs
+= RelocDir
->SizeOfBlock
;
736 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
737 RelocDir
->SizeOfBlock
);
738 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
741 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
742 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
744 /* Perform import fixups */
745 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
747 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
749 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
751 /* Process each import module */
752 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
753 ((DWORD
)DriverBase
+ PEOptionalHeader
->
754 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
755 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
756 while (ImportModuleDirectory
->dwRVAModuleName
)
758 /* Check to make sure that import lib is kernel */
759 pName
= (PCHAR
) DriverBase
+
760 ImportModuleDirectory
->dwRVAModuleName
;
761 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
762 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
764 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
766 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
768 NameBuffer
[Idx
+ Idx2
] = 0;
769 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
770 DPRINT("Import module: %wZ\n", &ModuleName
);
772 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
773 if (LibraryModuleObject
== 0)
775 DbgPrint("Unknown import module: %wZ\n", &ModuleName
);
777 /* Get the import address list */
778 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
779 ImportModuleDirectory
->dwRVAFunctionAddressList
);
781 /* Get the list of functions to import */
782 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
784 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
785 ImportModuleDirectory
->dwRVAFunctionNameList
);
789 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
790 ImportModuleDirectory
->dwRVAFunctionAddressList
);
792 /* Walk through function list and fixup addresses */
793 while (*FunctionNameList
!= 0L)
795 if ((*FunctionNameList
) & 0x80000000) // hint
800 Hint
= (*FunctionNameList
) & 0xffff;
804 pName
= (PCHAR
)((DWORD
)DriverBase
+
805 *FunctionNameList
+ 2);
806 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
808 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
810 /* Fixup the current import symbol */
811 if (LibraryModuleObject
!= NULL
)
813 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
819 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
825 ImportModuleDirectory
++;
828 ExFreePool(SymbolNameBuf
);
831 /* Create ModuleName string */
832 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
833 if (wcsrchr(FileName
->Buffer
, '\\') != 0)
835 wcscat(NameBuffer
, wcsrchr(FileName
->Buffer
, '\\') + 1);
839 wcscat(NameBuffer
, FileName
->Buffer
);
841 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
842 DbgPrint("Module name is: %wZ\n", &ModuleName
);
844 /* Initialize ObjectAttributes for ModuleObject */
845 InitializeObjectAttributes(&ObjectAttributes
,
851 /* Create module object */
853 ModuleObject
= ObCreateObject(&ModuleHandle
,
854 STANDARD_RIGHTS_REQUIRED
,
858 /* Initialize ModuleObject data */
859 ModuleObject
->Base
= DriverBase
;
860 ModuleObject
->Flags
= MODULE_FLAG_PE
;
861 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
862 RtlCreateUnicodeString(&ModuleObject
->Name
, FileName
->Buffer
);
864 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
865 PEOptionalHeader
->AddressOfEntryPoint
);
866 ModuleObject
->Length
= DriverSize
;
867 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
869 ModuleObject
->Image
.PE
.FileHeader
=
870 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
872 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
873 ModuleObject
->Image
.PE
.OptionalHeader
=
874 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
875 sizeof(IMAGE_FILE_HEADER
));
876 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
877 ModuleObject
->Image
.PE
.SectionList
=
878 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
879 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
880 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
886 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
891 DWORD ExportsStartRVA
, ExportsEndRVA
;
894 PDWORD FunctionList
, NameList
;
895 PIMAGE_SECTION_HEADER SectionHeader
;
896 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
898 ExportsStartRVA
= ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
899 [IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
900 ExportsEndRVA
= ExportsStartRVA
+
901 ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
902 [IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
;
904 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
905 usually the .edata section, but doesn't have to be. */
906 SectionHeader
= LdrPEGetEnclosingSectionHeader(ExportsStartRVA
, ModuleObject
);
913 ExportDirectory
= MakePtr(PIMAGE_EXPORT_DIRECTORY
,
915 SectionHeader
->VirtualAddress
);
917 FunctionList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfFunctions
+ ModuleObject
->Base
);
918 NameList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfNames
+ ModuleObject
->Base
);
919 OrdinalList
= (PWORD
)((DWORD
)ExportDirectory
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
925 for (Idx
= 0; Idx
< ExportDirectory
->NumberOfNames
; Idx
++)
928 DPRINT(" Name:%s NameList[%d]:%s\n",
931 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
934 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
936 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
937 FunctionList
[OrdinalList
[Idx
]]);
944 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
945 FunctionList
[Hint
- ExportDirectory
->Base
]);
947 if (ExportAddress
== 0)
949 DbgPrint("Export not found for %d:%s\n", Hint
,
950 Name
!= NULL
? Name
: "(Ordinal)");
954 return ExportAddress
;
957 static PIMAGE_SECTION_HEADER
958 LdrPEGetEnclosingSectionHeader(DWORD RVA
,
959 PMODULE_OBJECT ModuleObject
)
961 PIMAGE_SECTION_HEADER SectionHeader
= SECHDROFFSET(ModuleObject
->Base
);
964 for (i
= 0; i
< ModuleObject
->Image
.PE
.FileHeader
->NumberOfSections
;
965 i
++, SectionHeader
++)
967 /* Is the RVA within this section? */
968 if ((RVA
>= SectionHeader
->VirtualAddress
) &&
969 (RVA
< (SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)))
971 return SectionHeader
;