1 /* $Id: loader.c,v 1.43 2000/01/26 21:10:16 jfilby 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>
32 #include <internal/symbol.h>
35 #include <internal/debug.h>
40 /* FIXME: this should appear in a kernel header file */
41 NTSTATUS
IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry
);
43 /* MACROS ********************************************************************/
45 #define MODULE_ROOT_NAME L"\\Modules\\"
47 /* GLOBALS *******************************************************************/
49 LIST_ENTRY ModuleListHead
;
50 POBJECT_TYPE ObModuleType
= NULL
;
52 /* FORWARD DECLARATIONS ******************************************************/
54 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
);
55 NTSTATUS
LdrProcessDriver(PVOID ModuleLoadBase
);
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
);
66 /* PE Driver load support */
67 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
68 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
72 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
74 static PIMAGE_SECTION_HEADER
LdrPEGetEnclosingSectionHeader(DWORD RVA
,
75 PMODULE_OBJECT ModuleObject
);
77 /* FUNCTIONS *****************************************************************/
79 VOID
LdrInitModuleManagement(VOID
)
81 HANDLE DirHandle
, ModuleHandle
;
84 ANSI_STRING AnsiString
;
85 UNICODE_STRING ModuleName
;
86 OBJECT_ATTRIBUTES ObjectAttributes
;
87 PIMAGE_DOS_HEADER DosHeader
;
88 PMODULE_OBJECT ModuleObject
;
90 /* Register the process object type */
91 ObModuleType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
92 ObModuleType
->TotalObjects
= 0;
93 ObModuleType
->TotalHandles
= 0;
94 ObModuleType
->MaxObjects
= ULONG_MAX
;
95 ObModuleType
->MaxHandles
= ULONG_MAX
;
96 ObModuleType
->PagedPoolCharge
= 0;
97 ObModuleType
->NonpagedPoolCharge
= sizeof(MODULE
);
98 ObModuleType
->Dump
= NULL
;
99 ObModuleType
->Open
= NULL
;
100 ObModuleType
->Close
= NULL
;
101 ObModuleType
->Delete
= NULL
;
102 ObModuleType
->Parse
= NULL
;
103 ObModuleType
->Security
= NULL
;
104 ObModuleType
->QueryName
= NULL
;
105 ObModuleType
->OkayToClose
= NULL
;
106 ObModuleType
->Create
= LdrCreateModule
;
107 RtlInitAnsiString(&AnsiString
, "Module");
108 RtlAnsiStringToUnicodeString(&ObModuleType
->TypeName
, &AnsiString
, TRUE
);
110 /* Create Modules object directory */
111 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
112 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
113 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
114 ModuleName
.Buffer
= NameBuffer
;
115 InitializeObjectAttributes(&ObjectAttributes
,
120 DPRINT("Create dir: %wZ\n", &ModuleName
);
121 Status
= ZwCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
122 assert(NT_SUCCESS(Status
));
124 /* Add module entry for NTOSKRNL */
125 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
126 wcscat(NameBuffer
, L
"ntoskrnl.exe");
127 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
128 ModuleName
.Buffer
= NameBuffer
;
129 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName
);
131 /* Initialize ObjectAttributes for ModuleObject */
132 InitializeObjectAttributes(&ObjectAttributes
,
138 /* Create module object */
140 ModuleObject
= ObCreateObject(&ModuleHandle
,
141 STANDARD_RIGHTS_REQUIRED
,
144 assert(ModuleObject
!= NULL
);
146 InitializeListHead(&ModuleListHead
);
148 /* Initialize ModuleObject data */
149 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
150 ModuleObject
->Flags
= MODULE_FLAG_PE
;
151 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
152 ModuleObject
->Name
= wcsdup(L
"ntoskrnl.exe");
153 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
154 ModuleObject
->Image
.PE
.FileHeader
=
155 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
156 DosHeader
->e_lfanew
+ sizeof(ULONG
));
157 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
158 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
159 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
160 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
161 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
162 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
163 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
164 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
166 /* FIXME: Add fake module entry for HAL */
171 * load the auto config drivers.
173 static VOID
LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName
)
175 WCHAR TmpFileName
[MAX_PATH
];
177 UNICODE_STRING DriverName
;
179 DbgPrint("Loading %w\n",RelativeDriverName
);
181 LdrGetSystemDirectory(TmpFileName
, (MAX_PATH
* sizeof(WCHAR
)));
182 wcscat(TmpFileName
, L
"\\drivers\\");
183 wcscat(TmpFileName
, RelativeDriverName
);
185 DriverName
.Buffer
= TmpFileName
;
186 DriverName
.Length
= wcslen(TmpFileName
) * sizeof (WCHAR
);
187 DriverName
.MaximumLength
= DriverName
.Length
+ sizeof(WCHAR
);
190 Status
= LdrLoadDriver(&DriverName
);
191 if (!NT_SUCCESS(Status
))
193 DbgPrint("driver load failed, status;%d(%x)\n", Status
, Status
);
194 DbgPrintErrorMessage(Status
);
201 LdrLoadAutoConfigDrivers (VOID
)
206 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
210 LdrLoadAutoConfigDriver( L
"blue.sys" );
214 LdrLoadAutoConfigDriver( L
"vidport.sys" );
216 * VGA Miniport driver
218 LdrLoadAutoConfigDriver( L
"vgamp.sys" );
223 LdrCreateModule(PVOID ObjectBody
,
226 POBJECT_ATTRIBUTES ObjectAttributes
)
228 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
232 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
234 return STATUS_UNSUCCESSFUL
;
236 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
238 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
241 return STATUS_SUCCESS
;
245 * FUNCTION: Loads a kernel driver
247 * FileName = Driver to load
252 LdrLoadDriver(PUNICODE_STRING Filename
)
254 PMODULE_OBJECT ModuleObject
;
256 ModuleObject
= LdrLoadModule(Filename
);
257 if (ModuleObject
== 0)
259 return STATUS_UNSUCCESSFUL
;
262 /* FIXME: should we dereference the ModuleObject here? */
264 return IoInitializeDriver(ModuleObject
->EntryPoint
);
268 LdrLoadModule(PUNICODE_STRING Filename
)
270 PVOID ModuleLoadBase
;
273 OBJECT_ATTRIBUTES ObjectAttributes
;
274 PMODULE_OBJECT ModuleObject
;
275 FILE_STANDARD_INFORMATION FileStdInfo
;
276 WCHAR NameBuffer
[60];
277 // PWSTR RemainingPath;
278 UNICODE_STRING ModuleName
;
280 /* Check for module already loaded */
281 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
286 DPRINT("Loading Module %wZ...\n", Filename
);
288 /* Open the Module */
289 InitializeObjectAttributes(&ObjectAttributes
,
295 Status
= ZwOpenFile(&FileHandle
,
300 if (!NT_SUCCESS(Status
))
302 DbgPrint("Could not open module file: %wZ\n", Filename
);
307 /* Get the size of the file */
308 Status
= ZwQueryInformationFile(FileHandle
,
312 FileStandardInformation
);
313 if (!NT_SUCCESS(Status
))
315 DbgPrint("Could not get file size\n");
320 /* Allocate nonpageable memory for driver */
321 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
322 FileStdInfo
.EndOfFile
.u
.LowPart
);
324 if (ModuleLoadBase
== NULL
)
326 DbgPrint("could not allocate memory for module");
331 /* Load driver into memory chunk */
332 Status
= ZwReadFile(FileHandle
,
335 FileStdInfo
.EndOfFile
.u
.LowPart
,
337 if (!NT_SUCCESS(Status
))
339 DbgPrint("could not read module file into memory");
340 ExFreePool(ModuleLoadBase
);
348 /* Build module object name */
349 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
350 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
352 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
356 wcscat(NameBuffer
, Filename
->Buffer
);
358 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
359 ModuleName
.Buffer
= NameBuffer
;
362 ModuleObject
= LdrProcessModule(ModuleLoadBase
, &ModuleName
);
365 ExFreePool(ModuleLoadBase
);
371 LdrProcessDriver(PVOID ModuleLoadBase
)
373 PMODULE_OBJECT ModuleObject
;
375 ModuleObject
= LdrProcessModule(ModuleLoadBase
, 0);
376 if (ModuleObject
== 0)
378 return STATUS_UNSUCCESSFUL
;
381 /* FIXME: should we dereference the ModuleObject here? */
383 return IoInitializeDriver(ModuleObject
->EntryPoint
);
387 LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
)
389 PIMAGE_DOS_HEADER PEDosHeader
;
391 /* If MZ header exists */
392 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
393 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
395 return LdrPEProcessModule(ModuleLoadBase
, ModuleName
);
398 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
)
402 else /* Assume COFF format and load */
404 return LdrCOFFProcessModule(ModuleLoadBase
, ModuleName
);
411 static PMODULE_OBJECT
412 LdrOpenModule(PUNICODE_STRING Filename
)
415 WCHAR NameBuffer
[60];
416 UNICODE_STRING ModuleName
;
417 OBJECT_ATTRIBUTES ObjectAttributes
;
418 PMODULE_OBJECT ModuleObject
;
421 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
422 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
424 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
428 wcscat(NameBuffer
, Filename
->Buffer
);
430 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
431 ModuleName
.Buffer
= NameBuffer
;
432 InitializeObjectAttributes(&ObjectAttributes
,
437 Status
= ObFindObject(&ObjectAttributes
,
438 (PVOID
*) &ModuleObject
,
441 if (NT_SUCCESS(Status
) && (RemainingPath
== NULL
|| *RemainingPath
== 0))
443 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
452 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
456 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
458 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
466 /* ---------------------------------------------- PE Module support */
471 LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING pModuleName
)
473 unsigned int DriverSize
, Idx
, Idx2
;
474 ULONG RelocDelta
, NumRelocs
;
475 DWORD CurrentSize
, TotalRelocs
;
478 PIMAGE_DOS_HEADER PEDosHeader
;
479 PIMAGE_FILE_HEADER PEFileHeader
;
480 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
481 PIMAGE_SECTION_HEADER PESectionHeaders
;
482 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
483 PRELOCATION_DIRECTORY RelocDir
;
484 PRELOCATION_ENTRY RelocEntry
;
485 PMODULE_OBJECT LibraryModuleObject
;
487 PMODULE_OBJECT ModuleObject
;
488 PVOID
*ImportAddressList
;
489 PULONG FunctionNameList
;
490 PCHAR pName
, SymbolNameBuf
;
492 OBJECT_ATTRIBUTES ObjectAttributes
;
493 UNICODE_STRING ModuleName
;
494 WCHAR NameBuffer
[60];
496 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
498 /* Get header pointers */
499 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
500 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
501 PEDosHeader
->e_lfanew
);
502 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
503 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
504 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
505 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
506 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
507 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
508 sizeof(IMAGE_OPTIONAL_HEADER
));
511 /* Check file magic numbers */
512 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
514 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
517 if (PEDosHeader
->e_lfanew
== 0)
519 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
522 if (*PEMagic
!= IMAGE_PE_MAGIC
)
524 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
527 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
529 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
534 /* FIXME: if image is fixed-address load, then fail */
536 /* FIXME: check/verify OS version number */
538 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
539 PEOptionalHeader
->Magic
,
540 PEOptionalHeader
->MajorLinkerVersion
,
541 PEOptionalHeader
->MinorLinkerVersion
);
542 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
545 /* Determine the size of the module */
547 DriverSize
= PEOptionalHeader
->SizeOfImage
;
548 DPRINT("DriverSize %x\n",DriverSize
);
550 /* Allocate a virtual section for the module */
551 DriverBase
= MmAllocateSection(DriverSize
);
554 DbgPrint("Failed to allocate a virtual section for driver\n");
558 DPRINT1("Module is at base %x\n",DriverBase
);
560 /* Copy image sections into virtual section */
561 memcpy(DriverBase
, ModuleLoadBase
, PESectionHeaders
[0].PointerToRawData
);
562 // CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
565 memcpy(DriverBase
, ModuleLoadBase
, DriverSize
);
567 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
569 // Copy current section into current offset of virtual section
570 if (PESectionHeaders
[Idx
].Characteristics
&
571 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
573 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
574 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
575 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
576 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
577 PESectionHeaders
[Idx
].Misc
.VirtualSize
);
581 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
582 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
583 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
584 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
587 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
588 PEOptionalHeader
->SectionAlignment
);
591 // CurrentBase = (PVOID)((DWORD)CurrentBase +
592 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
593 // PEOptionalHeader->SectionAlignment));
596 /* Perform relocation fixups */
597 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
598 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
599 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
600 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
602 PEOptionalHeader
->ImageBase
,
604 DPRINT("RelocDir %x\n",RelocDir
);
605 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
607 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
609 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
610 PESectionHeaders
[Idx
].Name
,
611 PESectionHeaders
[Idx
].PointerToRawData
);
612 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
614 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
618 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
620 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
622 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
624 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
626 RelocDir->VirtualAddress,
628 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
629 sizeof(RELOCATION_DIRECTORY
));
630 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
636 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
637 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
638 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
640 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
643 Type ? "HIGHLOW" : "ABS",
645 (*RelocItem) + RelocDelta); */
648 (*RelocItem
) += RelocDelta
;
652 DbgPrint("Unknown relocation type %x\n",Type
);
656 TotalRelocs
+= RelocDir
->SizeOfBlock
;
657 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
658 RelocDir
->SizeOfBlock
);
659 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
662 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
663 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
665 /* Perform import fixups */
666 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
668 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
670 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
672 /* Process each import module */
673 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
674 ((DWORD
)DriverBase
+ PEOptionalHeader
->
675 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
676 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
677 while (ImportModuleDirectory
->dwRVAModuleName
)
679 /* Check to make sure that import lib is kernel */
680 pName
= (PCHAR
) DriverBase
+
681 ImportModuleDirectory
->dwRVAModuleName
;
682 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
683 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
685 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
687 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
689 NameBuffer
[Idx
+ Idx2
] = 0;
690 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
691 ModuleName
.Buffer
= NameBuffer
;
692 DPRINT("Import module: %wZ\n", &ModuleName
);
694 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
695 if (LibraryModuleObject
== 0)
697 DbgPrint("Unknown import module: %wZ\n", &ModuleName
);
699 /* Get the import address list */
700 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
701 ImportModuleDirectory
->dwRVAFunctionAddressList
);
703 /* Get the list of functions to import */
704 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
706 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
707 ImportModuleDirectory
->dwRVAFunctionNameList
);
711 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
712 ImportModuleDirectory
->dwRVAFunctionAddressList
);
714 /* Walk through function list and fixup addresses */
715 while (*FunctionNameList
!= 0L)
717 if ((*FunctionNameList
) & 0x80000000) // hint
722 Hint
= (*FunctionNameList
) & 0xffff;
726 pName
= (PCHAR
)((DWORD
)DriverBase
+
727 *FunctionNameList
+ 2);
728 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
730 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
732 /* Fixup the current import symbol */
733 if (LibraryModuleObject
!= NULL
)
735 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
741 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
746 ImportModuleDirectory
++;
749 ExFreePool(SymbolNameBuf
);
752 /* Create ModuleName string */
753 if (pModuleName
!= 0)
755 wcscpy(NameBuffer
, pModuleName
->Buffer
);
759 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
760 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
761 .VirtualAddress
!= 0)
763 ExportDirectory
= (PIMAGE_EXPORT_DIRECTORY
) (DriverBase
+
764 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
766 wcscat(NameBuffer
, DriverBase
+ ExportDirectory
->Name
);
772 sprintf(buf
, "%08X", (DWORD
) DriverBase
);
773 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
776 while ((NameBuffer
[Idx
+ Idx2
] = (WCHAR
) buf
[Idx2
]) != 0)
780 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
781 ModuleName
.Buffer
= NameBuffer
;
782 DbgPrint("Module name is: %wZ\n", &ModuleName
);
784 /* Initialize ObjectAttributes for ModuleObject */
785 InitializeObjectAttributes(&ObjectAttributes
,
791 /* Create module object */
793 ModuleObject
= ObCreateObject(&ModuleHandle
,
794 STANDARD_RIGHTS_REQUIRED
,
798 /* Initialize ModuleObject data */
799 ModuleObject
->Base
= DriverBase
;
800 ModuleObject
->Flags
= MODULE_FLAG_PE
;
801 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
802 ModuleObject
->Name
= wcsdup(NameBuffer
);
803 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
804 PEOptionalHeader
->AddressOfEntryPoint
);
805 ModuleObject
->Length
= DriverSize
;
806 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
808 ModuleObject
->Image
.PE
.FileHeader
=
809 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
811 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
812 ModuleObject
->Image
.PE
.OptionalHeader
=
813 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
814 sizeof(IMAGE_FILE_HEADER
));
815 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
816 ModuleObject
->Image
.PE
.SectionList
=
817 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
818 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
819 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
825 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
830 DWORD ExportsStartRVA
, ExportsEndRVA
;
833 PDWORD FunctionList
, NameList
;
834 PIMAGE_SECTION_HEADER SectionHeader
;
835 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
837 ExportsStartRVA
= ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
838 [IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
839 ExportsEndRVA
= ExportsStartRVA
+
840 ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
841 [IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
;
843 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
844 usually the .edata section, but doesn't have to be. */
845 SectionHeader
= LdrPEGetEnclosingSectionHeader(ExportsStartRVA
, ModuleObject
);
852 ExportDirectory
= MakePtr(PIMAGE_EXPORT_DIRECTORY
,
854 SectionHeader
->VirtualAddress
);
856 FunctionList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfFunctions
+ ModuleObject
->Base
);
857 NameList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfNames
+ ModuleObject
->Base
);
858 OrdinalList
= (PWORD
)((DWORD
)ExportDirectory
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
864 for (Idx
= 0; Idx
< ExportDirectory
->NumberOfNames
; Idx
++)
867 DPRINT(" Name:%s NameList[%d]:%s\n",
870 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
873 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
875 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
876 FunctionList
[OrdinalList
[Idx
]]);
883 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
884 FunctionList
[Hint
- ExportDirectory
->Base
]);
886 if (ExportAddress
== 0)
888 DbgPrint("Export not found for %d:%s\n", Hint
, Name
!= NULL
? Name
: "(Ordinal)");
893 return ExportAddress
;
896 static PIMAGE_SECTION_HEADER
897 LdrPEGetEnclosingSectionHeader(DWORD RVA
,
898 PMODULE_OBJECT ModuleObject
)
900 PIMAGE_SECTION_HEADER SectionHeader
= SECHDROFFSET(ModuleObject
->Base
);
903 for (i
= 0; i
< ModuleObject
->Image
.PE
.FileHeader
->NumberOfSections
;
904 i
++, SectionHeader
++)
906 /* Is the RVA within this section? */
907 if ((RVA
>= SectionHeader
->VirtualAddress
) &&
908 (RVA
< (SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)))
910 return SectionHeader
;