1 /* $Id: loader.c,v 1.60 2000/08/12 19:33:21 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/mmhal.h>
29 #include <internal/ob.h>
30 #include <internal/ps.h>
32 #include <internal/string.h>
35 #include <internal/debug.h>
38 /* FIXME: this should appear in a kernel header file */
39 NTSTATUS
IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry
);
41 /* MACROS ********************************************************************/
43 #define MODULE_ROOT_NAME L"\\Modules\\"
45 /* GLOBALS *******************************************************************/
47 LIST_ENTRY ModuleListHead
;
48 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
50 /* FORWARD DECLARATIONS ******************************************************/
52 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
);
53 NTSTATUS
LdrProcessDriver(PVOID ModuleLoadBase
);
55 PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename
);
56 PMODULE_OBJECT
LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
57 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
58 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
59 static NTSTATUS
LdrCreateModule(PVOID ObjectBody
,
62 POBJECT_ATTRIBUTES ObjectAttributes
);
64 /* PE Driver load support */
65 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
66 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
70 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
72 static PIMAGE_SECTION_HEADER
LdrPEGetEnclosingSectionHeader(DWORD RVA
,
73 PMODULE_OBJECT ModuleObject
);
75 /* FUNCTIONS *****************************************************************/
77 VOID
LdrInitModuleManagement(VOID
)
79 HANDLE DirHandle
, ModuleHandle
;
82 ANSI_STRING AnsiString
;
83 UNICODE_STRING ModuleName
;
84 OBJECT_ATTRIBUTES ObjectAttributes
;
85 PIMAGE_DOS_HEADER DosHeader
;
86 PMODULE_OBJECT ModuleObject
;
88 /* Register the process object type */
89 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
90 IoDriverObjectType
->TotalObjects
= 0;
91 IoDriverObjectType
->TotalHandles
= 0;
92 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
93 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
94 IoDriverObjectType
->PagedPoolCharge
= 0;
95 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(MODULE
);
96 IoDriverObjectType
->Dump
= NULL
;
97 IoDriverObjectType
->Open
= NULL
;
98 IoDriverObjectType
->Close
= NULL
;
99 IoDriverObjectType
->Delete
= NULL
;
100 IoDriverObjectType
->Parse
= NULL
;
101 IoDriverObjectType
->Security
= NULL
;
102 IoDriverObjectType
->QueryName
= NULL
;
103 IoDriverObjectType
->OkayToClose
= NULL
;
104 IoDriverObjectType
->Create
= LdrCreateModule
;
105 RtlInitAnsiString(&AnsiString
, "Module");
106 RtlAnsiStringToUnicodeString(&IoDriverObjectType
->TypeName
, &AnsiString
, TRUE
);
108 /* Create Modules object directory */
109 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
110 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
111 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
112 InitializeObjectAttributes(&ObjectAttributes
,
117 DPRINT("Create dir: %wZ\n", &ModuleName
);
118 Status
= ZwCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
119 assert(NT_SUCCESS(Status
));
121 /* Add module entry for NTOSKRNL */
122 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
123 wcscat(NameBuffer
, L
"ntoskrnl.exe");
124 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
125 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName
);
127 /* Initialize ObjectAttributes for ModuleObject */
128 InitializeObjectAttributes(&ObjectAttributes
,
134 /* Create module object */
136 ModuleObject
= ObCreateObject(&ModuleHandle
,
137 STANDARD_RIGHTS_REQUIRED
,
140 assert(ModuleObject
!= NULL
);
142 InitializeListHead(&ModuleListHead
);
144 /* Initialize ModuleObject data */
145 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
146 ModuleObject
->Flags
= MODULE_FLAG_PE
;
147 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
148 ModuleObject
->Name
= wcsdup(L
"ntoskrnl.exe");
149 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
150 ModuleObject
->Image
.PE
.FileHeader
=
151 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
152 DosHeader
->e_lfanew
+ sizeof(ULONG
));
153 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
154 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
155 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
156 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
157 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
158 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
159 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
160 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
162 /* FIXME: Add fake module entry for HAL */
167 * load the auto config drivers.
169 static VOID
LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName
)
171 WCHAR TmpFileName
[MAX_PATH
];
173 UNICODE_STRING DriverName
;
175 DbgPrint("Loading %S\n",RelativeDriverName
);
177 wcscpy(TmpFileName
, L
"\\SystemRoot\\system32\\drivers\\");
178 wcscat(TmpFileName
, RelativeDriverName
);
179 RtlInitUnicodeString (&DriverName
, TmpFileName
);
181 Status
= LdrLoadDriver(&DriverName
);
182 if (!NT_SUCCESS(Status
))
184 DbgPrint("driver load failed, status (%x)\n", Status
);
190 VOID
LdrLoadAutoConfigDrivers (VOID
)
195 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
200 LdrLoadAutoConfigDriver( L
"blue.sys" );
205 LdrLoadAutoConfigDriver(L
"vidport.sys");
210 LdrLoadAutoConfigDriver(L
"vgamp.sys");
213 * Minix filesystem driver
215 LdrLoadAutoConfigDriver(L
"minixfs.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 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
356 ModuleObject
= LdrProcessModule(ModuleLoadBase
, &ModuleName
);
359 ExFreePool(ModuleLoadBase
);
365 LdrProcessDriver(PVOID ModuleLoadBase
)
367 PMODULE_OBJECT ModuleObject
;
369 ModuleObject
= LdrProcessModule(ModuleLoadBase
, 0);
370 if (ModuleObject
== 0)
372 return STATUS_UNSUCCESSFUL
;
375 /* FIXME: should we dereference the ModuleObject here? */
377 return IoInitializeDriver(ModuleObject
->EntryPoint
);
381 LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
)
383 PIMAGE_DOS_HEADER PEDosHeader
;
385 /* If MZ header exists */
386 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
387 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
389 return LdrPEProcessModule(ModuleLoadBase
, ModuleName
);
395 static PMODULE_OBJECT
396 LdrOpenModule(PUNICODE_STRING Filename
)
399 WCHAR NameBuffer
[60];
400 UNICODE_STRING ModuleName
;
401 OBJECT_ATTRIBUTES ObjectAttributes
;
402 PMODULE_OBJECT ModuleObject
;
403 UNICODE_STRING RemainingPath
;
404 // PWSTR RemainingPath;
406 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
407 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
409 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
413 wcscat(NameBuffer
, Filename
->Buffer
);
415 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
416 InitializeObjectAttributes(&ObjectAttributes
,
422 Status
= ObFindObject(&ObjectAttributes
,
423 (PVOID
*) &ModuleObject
,
426 if (NT_SUCCESS(Status
) && (RemainingPath
.Buffer
== NULL
|| *(RemainingPath
.Buffer
) == 0))
428 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
429 RtlFreeUnicodeString (&RemainingPath
);
434 RtlFreeUnicodeString (&RemainingPath
);
440 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
444 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
446 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
454 /* ---------------------------------------------- PE Module support */
457 LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING pModuleName
)
459 unsigned int DriverSize
, Idx
, Idx2
;
460 ULONG RelocDelta
, NumRelocs
;
461 DWORD CurrentSize
, TotalRelocs
;
464 PIMAGE_DOS_HEADER PEDosHeader
;
465 PIMAGE_FILE_HEADER PEFileHeader
;
466 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
467 PIMAGE_SECTION_HEADER PESectionHeaders
;
468 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
469 PRELOCATION_DIRECTORY RelocDir
;
470 PRELOCATION_ENTRY RelocEntry
;
471 PMODULE_OBJECT LibraryModuleObject
;
473 PMODULE_OBJECT ModuleObject
;
474 PVOID
*ImportAddressList
;
475 PULONG FunctionNameList
;
476 PCHAR pName
, SymbolNameBuf
;
478 OBJECT_ATTRIBUTES ObjectAttributes
;
479 UNICODE_STRING ModuleName
;
480 WCHAR NameBuffer
[60];
482 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
484 /* Get header pointers */
485 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
486 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
487 PEDosHeader
->e_lfanew
);
488 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
489 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
490 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
491 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
492 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
493 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
494 sizeof(IMAGE_OPTIONAL_HEADER
));
497 /* Check file magic numbers */
498 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
500 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
503 if (PEDosHeader
->e_lfanew
== 0)
505 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
508 if (*PEMagic
!= IMAGE_PE_MAGIC
)
510 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
513 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
515 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
520 /* FIXME: if image is fixed-address load, then fail */
522 /* FIXME: check/verify OS version number */
524 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
525 PEOptionalHeader
->Magic
,
526 PEOptionalHeader
->MajorLinkerVersion
,
527 PEOptionalHeader
->MinorLinkerVersion
);
528 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
531 /* Determine the size of the module */
532 DriverSize
= PEOptionalHeader
->SizeOfImage
;
533 DPRINT("DriverSize %x\n",DriverSize
);
535 /* Allocate a virtual section for the module */
536 DriverBase
= MmAllocateSection(DriverSize
);
539 DbgPrint("Failed to allocate a virtual section for driver\n");
542 DbgPrint("DriverBase: %x\n", DriverBase
);
544 /* Copy headers over */
545 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
547 /* Copy image sections into virtual section */
548 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
550 // Copy current section into current offset of virtual section
551 if (PESectionHeaders
[Idx
].Characteristics
&
552 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
554 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
555 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
556 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
557 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
558 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
562 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
563 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
564 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
565 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
568 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
569 PEOptionalHeader
->SectionAlignment
);
572 // CurrentBase = (PVOID)((DWORD)CurrentBase +
573 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
574 // PEOptionalHeader->SectionAlignment));
577 /* Perform relocation fixups */
578 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
579 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
580 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
581 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
583 PEOptionalHeader
->ImageBase
,
585 DPRINT("RelocDir %x\n",RelocDir
);
586 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
588 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
590 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
591 PESectionHeaders
[Idx
].Name
,
592 PESectionHeaders
[Idx
].PointerToRawData
);
593 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
595 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
599 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
601 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
603 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
605 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
607 RelocDir->VirtualAddress,
609 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
610 sizeof(RELOCATION_DIRECTORY
));
611 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
617 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
618 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
619 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
621 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
624 Type ? "HIGHLOW" : "ABS",
626 (*RelocItem) + RelocDelta); */
629 (*RelocItem
) += RelocDelta
;
633 DbgPrint("Unknown relocation type %x\n",Type
);
637 TotalRelocs
+= RelocDir
->SizeOfBlock
;
638 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
639 RelocDir
->SizeOfBlock
);
640 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
643 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
644 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
646 /* Perform import fixups */
647 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
649 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
651 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
653 /* Process each import module */
654 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
655 ((DWORD
)DriverBase
+ PEOptionalHeader
->
656 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
657 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
658 while (ImportModuleDirectory
->dwRVAModuleName
)
660 /* Check to make sure that import lib is kernel */
661 pName
= (PCHAR
) DriverBase
+
662 ImportModuleDirectory
->dwRVAModuleName
;
663 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
664 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
666 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
668 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
670 NameBuffer
[Idx
+ Idx2
] = 0;
671 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
672 DPRINT("Import module: %wZ\n", &ModuleName
);
674 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
675 if (LibraryModuleObject
== 0)
677 DbgPrint("Unknown import module: %wZ\n", &ModuleName
);
679 /* Get the import address list */
680 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
681 ImportModuleDirectory
->dwRVAFunctionAddressList
);
683 /* Get the list of functions to import */
684 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
686 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
687 ImportModuleDirectory
->dwRVAFunctionNameList
);
691 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
692 ImportModuleDirectory
->dwRVAFunctionAddressList
);
694 /* Walk through function list and fixup addresses */
695 while (*FunctionNameList
!= 0L)
697 if ((*FunctionNameList
) & 0x80000000) // hint
702 Hint
= (*FunctionNameList
) & 0xffff;
706 pName
= (PCHAR
)((DWORD
)DriverBase
+
707 *FunctionNameList
+ 2);
708 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
710 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
712 /* Fixup the current import symbol */
713 if (LibraryModuleObject
!= NULL
)
715 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
721 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
727 ImportModuleDirectory
++;
730 ExFreePool(SymbolNameBuf
);
733 /* Create ModuleName string */
734 if (pModuleName
!= 0)
736 wcscpy(NameBuffer
, pModuleName
->Buffer
);
740 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
741 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
742 .VirtualAddress
!= 0)
744 ExportDirectory
= (PIMAGE_EXPORT_DIRECTORY
) (DriverBase
+
745 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
747 wcscat(NameBuffer
, DriverBase
+ ExportDirectory
->Name
);
753 sprintf(buf
, "%08X", (DWORD
) DriverBase
);
754 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
757 while ((NameBuffer
[Idx
+ Idx2
] = (WCHAR
) buf
[Idx2
]) != 0)
761 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
762 DbgPrint("Module name is: %wZ\n", &ModuleName
);
764 /* Initialize ObjectAttributes for ModuleObject */
765 InitializeObjectAttributes(&ObjectAttributes
,
771 /* Create module object */
773 ModuleObject
= ObCreateObject(&ModuleHandle
,
774 STANDARD_RIGHTS_REQUIRED
,
778 /* Initialize ModuleObject data */
779 ModuleObject
->Base
= DriverBase
;
780 ModuleObject
->Flags
= MODULE_FLAG_PE
;
781 InsertTailList(&ModuleListHead
, &ModuleObject
->ListEntry
);
782 ModuleObject
->Name
= wcsdup(NameBuffer
);
783 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
784 PEOptionalHeader
->AddressOfEntryPoint
);
785 ModuleObject
->Length
= DriverSize
;
786 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
788 ModuleObject
->Image
.PE
.FileHeader
=
789 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
791 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
792 ModuleObject
->Image
.PE
.OptionalHeader
=
793 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
794 sizeof(IMAGE_FILE_HEADER
));
795 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
796 ModuleObject
->Image
.PE
.SectionList
=
797 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
798 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
799 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
805 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
810 DWORD ExportsStartRVA
, ExportsEndRVA
;
813 PDWORD FunctionList
, NameList
;
814 PIMAGE_SECTION_HEADER SectionHeader
;
815 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
817 ExportsStartRVA
= ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
818 [IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
819 ExportsEndRVA
= ExportsStartRVA
+
820 ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
821 [IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
;
823 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
824 usually the .edata section, but doesn't have to be. */
825 SectionHeader
= LdrPEGetEnclosingSectionHeader(ExportsStartRVA
, ModuleObject
);
832 ExportDirectory
= MakePtr(PIMAGE_EXPORT_DIRECTORY
,
834 SectionHeader
->VirtualAddress
);
836 FunctionList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfFunctions
+ ModuleObject
->Base
);
837 NameList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfNames
+ ModuleObject
->Base
);
838 OrdinalList
= (PWORD
)((DWORD
)ExportDirectory
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
844 for (Idx
= 0; Idx
< ExportDirectory
->NumberOfNames
; Idx
++)
847 DPRINT(" Name:%s NameList[%d]:%s\n",
850 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
853 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
855 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
856 FunctionList
[OrdinalList
[Idx
]]);
863 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
864 FunctionList
[Hint
- ExportDirectory
->Base
]);
866 if (ExportAddress
== 0)
868 DbgPrint("Export not found for %d:%s\n", Hint
,
869 Name
!= NULL
? Name
: "(Ordinal)");
873 return ExportAddress
;
876 static PIMAGE_SECTION_HEADER
877 LdrPEGetEnclosingSectionHeader(DWORD RVA
,
878 PMODULE_OBJECT ModuleObject
)
880 PIMAGE_SECTION_HEADER SectionHeader
= SECHDROFFSET(ModuleObject
->Base
);
883 for (i
= 0; i
< ModuleObject
->Image
.PE
.FileHeader
->NumberOfSections
;
884 i
++, SectionHeader
++)
886 /* Is the RVA within this section? */
887 if ((RVA
>= SectionHeader
->VirtualAddress
) &&
888 (RVA
< (SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)))
890 return SectionHeader
;