1 /* $Id: loader.c,v 1.47 2000/02/25 00:32:04 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
20 /* INCLUDES *****************************************************************/
22 #include <ddk/ntddk.h>
23 #include <internal/i386/segment.h>
24 #include <internal/linkage.h>
25 #include <internal/module.h>
26 #include <internal/ntoskrnl.h>
27 #include <internal/mmhal.h>
28 #include <internal/ob.h>
29 #include <internal/ps.h>
31 #include <internal/string.h>
34 #include <internal/debug.h>
39 /* FIXME: this should appear in a kernel header file */
40 NTSTATUS
IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry
);
42 /* MACROS ********************************************************************/
44 #define MODULE_ROOT_NAME L"\\Modules\\"
46 /* GLOBALS *******************************************************************/
48 LIST_ENTRY ModuleListHead
;
49 POBJECT_TYPE ObModuleType
= NULL
;
51 /* FORWARD DECLARATIONS ******************************************************/
53 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
);
54 NTSTATUS
LdrProcessDriver(PVOID ModuleLoadBase
);
56 PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename
);
57 PMODULE_OBJECT
LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
58 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
59 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
60 static NTSTATUS
LdrCreateModule(PVOID ObjectBody
,
63 POBJECT_ATTRIBUTES ObjectAttributes
);
65 /* PE Driver load support */
66 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
67 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
71 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
73 static PIMAGE_SECTION_HEADER
LdrPEGetEnclosingSectionHeader(DWORD RVA
,
74 PMODULE_OBJECT ModuleObject
);
76 /* FUNCTIONS *****************************************************************/
78 VOID
LdrInitModuleManagement(VOID
)
80 HANDLE DirHandle
, ModuleHandle
;
83 ANSI_STRING AnsiString
;
84 UNICODE_STRING ModuleName
;
85 OBJECT_ATTRIBUTES ObjectAttributes
;
86 PIMAGE_DOS_HEADER DosHeader
;
87 PMODULE_OBJECT ModuleObject
;
89 /* Register the process object type */
90 ObModuleType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
91 ObModuleType
->TotalObjects
= 0;
92 ObModuleType
->TotalHandles
= 0;
93 ObModuleType
->MaxObjects
= ULONG_MAX
;
94 ObModuleType
->MaxHandles
= ULONG_MAX
;
95 ObModuleType
->PagedPoolCharge
= 0;
96 ObModuleType
->NonpagedPoolCharge
= sizeof(MODULE
);
97 ObModuleType
->Dump
= NULL
;
98 ObModuleType
->Open
= NULL
;
99 ObModuleType
->Close
= NULL
;
100 ObModuleType
->Delete
= NULL
;
101 ObModuleType
->Parse
= NULL
;
102 ObModuleType
->Security
= NULL
;
103 ObModuleType
->QueryName
= NULL
;
104 ObModuleType
->OkayToClose
= NULL
;
105 ObModuleType
->Create
= LdrCreateModule
;
106 RtlInitAnsiString(&AnsiString
, "Module");
107 RtlAnsiStringToUnicodeString(&ObModuleType
->TypeName
, &AnsiString
, TRUE
);
109 /* Create Modules object directory */
110 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
111 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
112 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
113 ModuleName
.Buffer
= NameBuffer
;
114 InitializeObjectAttributes(&ObjectAttributes
,
119 DPRINT("Create dir: %wZ\n", &ModuleName
);
120 Status
= ZwCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
121 assert(NT_SUCCESS(Status
));
123 /* Add module entry for NTOSKRNL */
124 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
125 wcscat(NameBuffer
, L
"ntoskrnl.exe");
126 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
127 ModuleName
.Buffer
= NameBuffer
;
128 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName
);
130 /* Initialize ObjectAttributes for ModuleObject */
131 InitializeObjectAttributes(&ObjectAttributes
,
137 /* Create module object */
139 ModuleObject
= ObCreateObject(&ModuleHandle
,
140 STANDARD_RIGHTS_REQUIRED
,
143 assert(ModuleObject
!= NULL
);
145 InitializeListHead(&ModuleListHead
);
147 /* Initialize ModuleObject data */
148 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
149 ModuleObject
->Flags
= MODULE_FLAG_PE
;
150 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
151 ModuleObject
->Name
= wcsdup(L
"ntoskrnl.exe");
152 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
153 ModuleObject
->Image
.PE
.FileHeader
=
154 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
155 DosHeader
->e_lfanew
+ sizeof(ULONG
));
156 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
157 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
158 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
159 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
160 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
161 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
162 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
163 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
165 /* FIXME: Add fake module entry for HAL */
170 * load the auto config drivers.
172 static VOID
LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName
)
174 WCHAR TmpFileName
[MAX_PATH
];
176 UNICODE_STRING DriverName
;
178 DbgPrint("Loading %S\n",RelativeDriverName
);
180 LdrGetSystemDirectory(TmpFileName
, (MAX_PATH
* sizeof(WCHAR
)));
181 wcscat(TmpFileName
, L
"\\drivers\\");
182 wcscat(TmpFileName
, RelativeDriverName
);
184 DriverName
.Buffer
= TmpFileName
;
185 DriverName
.Length
= wcslen(TmpFileName
) * sizeof (WCHAR
);
186 DriverName
.MaximumLength
= DriverName
.Length
+ sizeof(WCHAR
);
189 Status
= LdrLoadDriver(&DriverName
);
190 if (!NT_SUCCESS(Status
))
192 DbgPrint("driver load failed, status (%x)\n", Status
);
198 VOID
LdrLoadAutoConfigDrivers (VOID
)
203 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
207 LdrLoadAutoConfigDriver( L
"blue.sys" );
211 LdrLoadAutoConfigDriver( L
"vidport.sys" );
213 * VGA Miniport driver
215 LdrLoadAutoConfigDriver( L
"vgamp.sys" );
220 LdrCreateModule(PVOID ObjectBody
,
223 POBJECT_ATTRIBUTES ObjectAttributes
)
225 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
229 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
231 return STATUS_UNSUCCESSFUL
;
233 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
235 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
238 return STATUS_SUCCESS
;
242 * FUNCTION: Loads a kernel driver
244 * FileName = Driver to load
248 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
)
250 PMODULE_OBJECT ModuleObject
;
252 ModuleObject
= LdrLoadModule(Filename
);
253 if (ModuleObject
== 0)
255 return STATUS_UNSUCCESSFUL
;
258 /* FIXME: should we dereference the ModuleObject here? */
260 return IoInitializeDriver(ModuleObject
->EntryPoint
);
264 LdrLoadModule(PUNICODE_STRING Filename
)
266 PVOID ModuleLoadBase
;
269 OBJECT_ATTRIBUTES ObjectAttributes
;
270 PMODULE_OBJECT ModuleObject
;
271 FILE_STANDARD_INFORMATION FileStdInfo
;
272 WCHAR NameBuffer
[60];
273 // PWSTR RemainingPath;
274 UNICODE_STRING ModuleName
;
276 /* Check for module already loaded */
277 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
282 DPRINT("Loading Module %wZ...\n", Filename
);
284 /* Open the Module */
285 InitializeObjectAttributes(&ObjectAttributes
,
291 Status
= ZwOpenFile(&FileHandle
,
296 if (!NT_SUCCESS(Status
))
298 DbgPrint("Could not open module file: %wZ\n", Filename
);
303 /* Get the size of the file */
304 Status
= ZwQueryInformationFile(FileHandle
,
308 FileStandardInformation
);
309 if (!NT_SUCCESS(Status
))
311 DbgPrint("Could not get file size\n");
316 /* Allocate nonpageable memory for driver */
317 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
318 FileStdInfo
.EndOfFile
.u
.LowPart
);
320 if (ModuleLoadBase
== NULL
)
322 DbgPrint("could not allocate memory for module");
327 /* Load driver into memory chunk */
328 Status
= ZwReadFile(FileHandle
,
331 FileStdInfo
.EndOfFile
.u
.LowPart
,
333 if (!NT_SUCCESS(Status
))
335 DbgPrint("could not read module file into memory");
336 ExFreePool(ModuleLoadBase
);
344 /* Build module object name */
345 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
346 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
348 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
352 wcscat(NameBuffer
, Filename
->Buffer
);
354 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
355 ModuleName
.Buffer
= NameBuffer
;
358 ModuleObject
= LdrProcessModule(ModuleLoadBase
, &ModuleName
);
361 ExFreePool(ModuleLoadBase
);
367 LdrProcessDriver(PVOID ModuleLoadBase
)
369 PMODULE_OBJECT ModuleObject
;
371 ModuleObject
= LdrProcessModule(ModuleLoadBase
, 0);
372 if (ModuleObject
== 0)
374 return STATUS_UNSUCCESSFUL
;
377 /* FIXME: should we dereference the ModuleObject here? */
379 return IoInitializeDriver(ModuleObject
->EntryPoint
);
383 LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
)
385 PIMAGE_DOS_HEADER PEDosHeader
;
387 /* If MZ header exists */
388 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
389 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
391 return LdrPEProcessModule(ModuleLoadBase
, ModuleName
);
394 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
)
398 else /* Assume COFF format and load */
400 return LdrCOFFProcessModule(ModuleLoadBase
, ModuleName
);
407 static PMODULE_OBJECT
408 LdrOpenModule(PUNICODE_STRING Filename
)
411 WCHAR NameBuffer
[60];
412 UNICODE_STRING ModuleName
;
413 OBJECT_ATTRIBUTES ObjectAttributes
;
414 PMODULE_OBJECT ModuleObject
;
417 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
418 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
420 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
424 wcscat(NameBuffer
, Filename
->Buffer
);
426 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
427 ModuleName
.Buffer
= NameBuffer
;
428 InitializeObjectAttributes(&ObjectAttributes
,
433 Status
= ObFindObject(&ObjectAttributes
,
434 (PVOID
*) &ModuleObject
,
437 if (NT_SUCCESS(Status
) && (RemainingPath
== NULL
|| *RemainingPath
== 0))
439 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
448 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
452 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
454 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
462 /* ---------------------------------------------- PE Module support */
467 LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING pModuleName
)
469 unsigned int DriverSize
, Idx
, Idx2
;
470 ULONG RelocDelta
, NumRelocs
;
471 DWORD CurrentSize
, TotalRelocs
;
474 PIMAGE_DOS_HEADER PEDosHeader
;
475 PIMAGE_FILE_HEADER PEFileHeader
;
476 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
477 PIMAGE_SECTION_HEADER PESectionHeaders
;
478 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
479 PRELOCATION_DIRECTORY RelocDir
;
480 PRELOCATION_ENTRY RelocEntry
;
481 PMODULE_OBJECT LibraryModuleObject
;
483 PMODULE_OBJECT ModuleObject
;
484 PVOID
*ImportAddressList
;
485 PULONG FunctionNameList
;
486 PCHAR pName
, SymbolNameBuf
;
488 OBJECT_ATTRIBUTES ObjectAttributes
;
489 UNICODE_STRING ModuleName
;
490 WCHAR NameBuffer
[60];
492 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
494 /* Get header pointers */
495 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
496 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
497 PEDosHeader
->e_lfanew
);
498 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
499 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
500 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
501 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
502 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
503 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
504 sizeof(IMAGE_OPTIONAL_HEADER
));
507 /* Check file magic numbers */
508 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
510 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
513 if (PEDosHeader
->e_lfanew
== 0)
515 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
518 if (*PEMagic
!= IMAGE_PE_MAGIC
)
520 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
523 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
525 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
530 /* FIXME: if image is fixed-address load, then fail */
532 /* FIXME: check/verify OS version number */
534 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
535 PEOptionalHeader
->Magic
,
536 PEOptionalHeader
->MajorLinkerVersion
,
537 PEOptionalHeader
->MinorLinkerVersion
);
538 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
541 /* Determine the size of the module */
543 DriverSize
= PEOptionalHeader
->SizeOfImage
;
544 DPRINT("DriverSize %x\n",DriverSize
);
546 /* Allocate a virtual section for the module */
547 DriverBase
= MmAllocateSection(DriverSize
);
550 DbgPrint("Failed to allocate a virtual section for driver\n");
554 /* Copy headers over */
555 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
557 /* Copy image sections into virtual section */
558 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
560 // Copy current section into current offset of virtual section
561 if (PESectionHeaders
[Idx
].Characteristics
&
562 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
564 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
565 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
566 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
567 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
568 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
572 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
573 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
574 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
575 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
578 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
579 PEOptionalHeader
->SectionAlignment
);
582 // CurrentBase = (PVOID)((DWORD)CurrentBase +
583 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
584 // PEOptionalHeader->SectionAlignment));
587 /* Perform relocation fixups */
588 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
589 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
590 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
591 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
593 PEOptionalHeader
->ImageBase
,
595 DPRINT("RelocDir %x\n",RelocDir
);
596 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
598 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
600 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
601 PESectionHeaders
[Idx
].Name
,
602 PESectionHeaders
[Idx
].PointerToRawData
);
603 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
605 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
609 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
611 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
613 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
615 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
617 RelocDir->VirtualAddress,
619 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
620 sizeof(RELOCATION_DIRECTORY
));
621 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
627 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
628 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
629 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
631 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
634 Type ? "HIGHLOW" : "ABS",
636 (*RelocItem) + RelocDelta); */
639 (*RelocItem
) += RelocDelta
;
643 DbgPrint("Unknown relocation type %x\n",Type
);
647 TotalRelocs
+= RelocDir
->SizeOfBlock
;
648 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
649 RelocDir
->SizeOfBlock
);
650 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
653 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
654 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
656 /* Perform import fixups */
657 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
659 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
661 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
663 /* Process each import module */
664 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
665 ((DWORD
)DriverBase
+ PEOptionalHeader
->
666 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
667 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
668 while (ImportModuleDirectory
->dwRVAModuleName
)
670 /* Check to make sure that import lib is kernel */
671 pName
= (PCHAR
) DriverBase
+
672 ImportModuleDirectory
->dwRVAModuleName
;
673 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
674 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
676 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
678 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
680 NameBuffer
[Idx
+ Idx2
] = 0;
681 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
682 ModuleName
.Buffer
= NameBuffer
;
683 DPRINT("Import module: %wZ\n", &ModuleName
);
685 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
686 if (LibraryModuleObject
== 0)
688 DbgPrint("Unknown import module: %wZ\n", &ModuleName
);
690 /* Get the import address list */
691 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
692 ImportModuleDirectory
->dwRVAFunctionAddressList
);
694 /* Get the list of functions to import */
695 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
697 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
698 ImportModuleDirectory
->dwRVAFunctionNameList
);
702 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
703 ImportModuleDirectory
->dwRVAFunctionAddressList
);
705 /* Walk through function list and fixup addresses */
706 while (*FunctionNameList
!= 0L)
708 if ((*FunctionNameList
) & 0x80000000) // hint
713 Hint
= (*FunctionNameList
) & 0xffff;
717 pName
= (PCHAR
)((DWORD
)DriverBase
+
718 *FunctionNameList
+ 2);
719 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
721 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
723 /* Fixup the current import symbol */
724 if (LibraryModuleObject
!= NULL
)
726 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
732 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
737 ImportModuleDirectory
++;
740 ExFreePool(SymbolNameBuf
);
743 /* Create ModuleName string */
744 if (pModuleName
!= 0)
746 wcscpy(NameBuffer
, pModuleName
->Buffer
);
750 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
751 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
752 .VirtualAddress
!= 0)
754 ExportDirectory
= (PIMAGE_EXPORT_DIRECTORY
) (DriverBase
+
755 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
757 wcscat(NameBuffer
, DriverBase
+ ExportDirectory
->Name
);
763 sprintf(buf
, "%08X", (DWORD
) DriverBase
);
764 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
767 while ((NameBuffer
[Idx
+ Idx2
] = (WCHAR
) buf
[Idx2
]) != 0)
771 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
772 ModuleName
.Buffer
= NameBuffer
;
773 DbgPrint("Module name is: %wZ\n", &ModuleName
);
775 /* Initialize ObjectAttributes for ModuleObject */
776 InitializeObjectAttributes(&ObjectAttributes
,
782 /* Create module object */
784 ModuleObject
= ObCreateObject(&ModuleHandle
,
785 STANDARD_RIGHTS_REQUIRED
,
789 /* Initialize ModuleObject data */
790 ModuleObject
->Base
= DriverBase
;
791 ModuleObject
->Flags
= MODULE_FLAG_PE
;
792 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
793 ModuleObject
->Name
= wcsdup(NameBuffer
);
794 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
795 PEOptionalHeader
->AddressOfEntryPoint
);
796 ModuleObject
->Length
= DriverSize
;
797 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
799 ModuleObject
->Image
.PE
.FileHeader
=
800 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
802 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
803 ModuleObject
->Image
.PE
.OptionalHeader
=
804 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
805 sizeof(IMAGE_FILE_HEADER
));
806 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
807 ModuleObject
->Image
.PE
.SectionList
=
808 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
809 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
810 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
816 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
821 DWORD ExportsStartRVA
, ExportsEndRVA
;
824 PDWORD FunctionList
, NameList
;
825 PIMAGE_SECTION_HEADER SectionHeader
;
826 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
828 ExportsStartRVA
= ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
829 [IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
830 ExportsEndRVA
= ExportsStartRVA
+
831 ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
832 [IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
;
834 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
835 usually the .edata section, but doesn't have to be. */
836 SectionHeader
= LdrPEGetEnclosingSectionHeader(ExportsStartRVA
, ModuleObject
);
843 ExportDirectory
= MakePtr(PIMAGE_EXPORT_DIRECTORY
,
845 SectionHeader
->VirtualAddress
);
847 FunctionList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfFunctions
+ ModuleObject
->Base
);
848 NameList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfNames
+ ModuleObject
->Base
);
849 OrdinalList
= (PWORD
)((DWORD
)ExportDirectory
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
855 for (Idx
= 0; Idx
< ExportDirectory
->NumberOfNames
; Idx
++)
858 DPRINT(" Name:%s NameList[%d]:%s\n",
861 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
864 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
866 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
867 FunctionList
[OrdinalList
[Idx
]]);
874 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
875 FunctionList
[Hint
- ExportDirectory
->Base
]);
877 if (ExportAddress
== 0)
879 DbgPrint("Export not found for %d:%s\n", Hint
, Name
!= NULL
? Name
: "(Ordinal)");
884 return ExportAddress
;
887 static PIMAGE_SECTION_HEADER
888 LdrPEGetEnclosingSectionHeader(DWORD RVA
,
889 PMODULE_OBJECT ModuleObject
)
891 PIMAGE_SECTION_HEADER SectionHeader
= SECHDROFFSET(ModuleObject
->Base
);
894 for (i
= 0; i
< ModuleObject
->Image
.PE
.FileHeader
->NumberOfSections
;
895 i
++, SectionHeader
++)
897 /* Is the RVA within this section? */
898 if ((RVA
>= SectionHeader
->VirtualAddress
) &&
899 (RVA
< (SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)))
901 return SectionHeader
;