1 /* $Id: loader.c,v 1.32 1999/10/07 23:36:24 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)
11 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
12 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
13 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
14 * JM 14/12/98 Built initial PE user module loader
15 * RJJ 06/03/99 Moved user PE loader into NTDLL
18 /* INCLUDES *****************************************************************/
20 #include <ddk/ntddk.h>
21 #include <internal/i386/segment.h>
22 #include <internal/linkage.h>
23 #include <internal/module.h>
24 #include <internal/ntoskrnl.h>
25 #include <internal/mmhal.h>
26 #include <internal/ob.h>
27 #include <internal/ps.h>
29 #include <internal/string.h>
30 #include <internal/symbol.h>
33 #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 POBJECT_TYPE ObModuleType
= NULL
;
49 /* FORWARD DECLARATIONS ******************************************************/
51 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
);
52 NTSTATUS
LdrProcessDriver(PVOID ModuleLoadBase
);
54 PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename
);
55 PMODULE_OBJECT
LdrProcessModule(PVOID ModuleLoadBase
);
56 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
57 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
58 static PIMAGE_SECTION_HEADER
LdrPEGetEnclosingSectionHeader(DWORD RVA
,
59 PMODULE_OBJECT ModuleObject
);
60 static NTSTATUS
LdrCreateModule(PVOID ObjectBody
,
63 POBJECT_ATTRIBUTES ObjectAttributes
);
65 /* PE Driver load support */
66 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
);
67 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
70 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
73 /* FUNCTIONS *****************************************************************/
75 VOID
LdrInitModuleManagement(VOID
)
77 HANDLE DirHandle
, ModuleHandle
;
80 ANSI_STRING AnsiString
;
81 UNICODE_STRING ModuleName
;
82 OBJECT_ATTRIBUTES ObjectAttributes
;
83 PIMAGE_DOS_HEADER DosHeader
;
84 PMODULE_OBJECT ModuleObject
;
86 /* Register the process object type */
87 ObModuleType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
88 ObModuleType
->TotalObjects
= 0;
89 ObModuleType
->TotalHandles
= 0;
90 ObModuleType
->MaxObjects
= ULONG_MAX
;
91 ObModuleType
->MaxHandles
= ULONG_MAX
;
92 ObModuleType
->PagedPoolCharge
= 0;
93 ObModuleType
->NonpagedPoolCharge
= sizeof(MODULE
);
94 ObModuleType
->Dump
= NULL
;
95 ObModuleType
->Open
= NULL
;
96 ObModuleType
->Close
= NULL
;
97 ObModuleType
->Delete
= NULL
;
98 ObModuleType
->Parse
= NULL
;
99 ObModuleType
->Security
= NULL
;
100 ObModuleType
->QueryName
= NULL
;
101 ObModuleType
->OkayToClose
= NULL
;
102 ObModuleType
->Create
= LdrCreateModule
;
103 RtlInitAnsiString(&AnsiString
, "Module");
104 RtlAnsiStringToUnicodeString(&ObModuleType
->TypeName
, &AnsiString
, TRUE
);
106 /* Create Modules object directory */
107 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
108 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
109 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
110 ModuleName
.Buffer
= NameBuffer
;
111 InitializeObjectAttributes(&ObjectAttributes
,
116 DPRINT("Create dir: %W\n", &ModuleName
);
117 Status
= ZwCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
118 assert(NT_SUCCESS(Status
));
120 /* Add module entry for NTOSKRNL */
121 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
122 wcscat(NameBuffer
, L
"ntoskrnl.exe");
123 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
124 ModuleName
.Buffer
= NameBuffer
;
125 DPRINT("Kernel's Module name is: %W\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 /* Initialize ModuleObject data */
143 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
144 ModuleObject
->Flags
= MODULE_FLAG_PE
;
145 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
146 ModuleObject
->Image
.PE
.FileHeader
=
147 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
148 DosHeader
->e_lfanew
+ sizeof(ULONG
));
149 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
150 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
151 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
152 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
153 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
154 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
155 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
157 /* FIXME: Add fake module entry for HAL */
162 * load the auto config drivers.
166 LdrLoadAutoConfigDriver (
167 LPWSTR RelativeDriverName
170 WCHAR TmpFileName
[MAX_PATH
];
172 UNICODE_STRING DriverName
;
176 (MAX_PATH
* sizeof(WCHAR
))
192 DriverName
.MaximumLength
=
196 Status
= LdrLoadDriver(&DriverName
);
197 if (!NT_SUCCESS(Status
))
200 "driver load failed, status;%d(%x)\n",
204 DbgPrintErrorMessage(Status
);
210 LdrLoadAutoConfigDrivers (VOID
)
215 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
219 LdrLoadAutoConfigDriver( L
"blue.sys" );
224 LdrCreateModule(PVOID ObjectBody
,
227 POBJECT_ATTRIBUTES ObjectAttributes
)
229 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %w)\n",
233 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
235 return STATUS_UNSUCCESSFUL
;
237 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
239 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
242 return STATUS_SUCCESS
;
246 * FUNCTION: Loads a kernel driver
248 * FileName = Driver to load
253 LdrLoadDriver(PUNICODE_STRING Filename
)
255 PMODULE_OBJECT ModuleObject
;
257 ModuleObject
= LdrLoadModule(Filename
);
258 if (ModuleObject
== 0)
260 return STATUS_UNSUCCESSFUL
;
263 /* FIXME: should we dereference the ModuleObject here? */
265 return IoInitializeDriver(ModuleObject
->EntryPoint
);
269 LdrLoadModule(PUNICODE_STRING Filename
)
271 PVOID ModuleLoadBase
;
274 OBJECT_ATTRIBUTES ObjectAttributes
;
275 PMODULE_OBJECT ModuleObject
;
276 FILE_STANDARD_INFORMATION FileStdInfo
;
277 WCHAR NameBuffer
[60];
279 UNICODE_STRING ModuleName
;
281 /* Check for module already loaded */
282 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
287 DPRINT("Loading Module %W...\n", Filename
);
289 /* Open the Module */
290 InitializeObjectAttributes(&ObjectAttributes
,
296 Status
= ZwOpenFile(&FileHandle
,
301 if (!NT_SUCCESS(Status
))
303 DbgPrint("Could not open module file: %W\n", Filename
);
308 /* Get the size of the file */
309 Status
= ZwQueryInformationFile(FileHandle
,
313 FileStandardInformation
);
314 if (!NT_SUCCESS(Status
))
316 DbgPrint("Could not get file size\n");
321 /* Allocate nonpageable memory for driver */
322 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
323 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 ModuleObject
= LdrProcessModule(ModuleLoadBase
);
351 ExFreePool(ModuleLoadBase
);
357 LdrProcessDriver(PVOID ModuleLoadBase
)
359 PMODULE_OBJECT ModuleObject
;
361 ModuleObject
= LdrProcessModule(ModuleLoadBase
);
362 if (ModuleObject
== 0)
364 return STATUS_UNSUCCESSFUL
;
367 /* FIXME: should we dereference the ModuleObject here? */
369 return IoInitializeDriver(ModuleObject
->EntryPoint
);
373 LdrProcessModule(PVOID ModuleLoadBase
)
375 PIMAGE_DOS_HEADER PEDosHeader
;
377 /* If MZ header exists */
378 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
379 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
381 return LdrPEProcessModule(ModuleLoadBase
);
384 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
)
388 else /* Assume COFF format and load */
390 return LdrCOFFProcessModule(ModuleLoadBase
);
397 static PMODULE_OBJECT
398 LdrOpenModule(PUNICODE_STRING Filename
)
401 WCHAR NameBuffer
[60];
402 UNICODE_STRING ModuleName
;
403 OBJECT_ATTRIBUTES ObjectAttributes
;
404 PMODULE_OBJECT ModuleObject
;
407 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
408 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
410 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
414 wcscat(NameBuffer
, Filename
->Buffer
);
416 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
417 ModuleName
.Buffer
= NameBuffer
;
418 InitializeObjectAttributes(&ObjectAttributes
,
423 Status
= ObFindObject(&ObjectAttributes
,
424 (PVOID
*) &ModuleObject
,
427 if (NT_SUCCESS(Status
) && (RemainingPath
== NULL
|| *RemainingPath
== 0))
429 DPRINT("Module %W at %p\n", Filename
, ModuleObject
);
438 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
442 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
444 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
452 /* ---------------------------------------------- PE Module support */
455 LdrPEProcessModule(PVOID ModuleLoadBase
)
457 unsigned int DriverSize
, Idx
, Idx2
;
458 ULONG RelocDelta
, NumRelocs
;
459 DWORD CurrentSize
, TotalRelocs
;
460 PVOID DriverBase
, CurrentBase
;
462 PIMAGE_DOS_HEADER PEDosHeader
;
463 PIMAGE_FILE_HEADER PEFileHeader
;
464 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
465 PIMAGE_SECTION_HEADER PESectionHeaders
;
466 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
467 PRELOCATION_DIRECTORY RelocDir
;
468 PRELOCATION_ENTRY RelocEntry
;
469 PMODULE_OBJECT LibraryModuleObject
;
471 PMODULE_OBJECT ModuleObject
;
472 PVOID
*ImportAddressList
;
473 PULONG FunctionNameList
;
474 PCHAR pName
, SymbolNameBuf
;
476 OBJECT_ATTRIBUTES ObjectAttributes
;
477 UNICODE_STRING ModuleName
;
478 WCHAR NameBuffer
[60];
480 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
482 /* Get header pointers */
483 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
484 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
485 PEDosHeader
->e_lfanew
);
486 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
487 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
488 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
489 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
490 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
491 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
492 sizeof(IMAGE_OPTIONAL_HEADER
));
495 /* Check file magic numbers */
496 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
498 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
501 if (PEDosHeader
->e_lfanew
== 0)
503 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
506 if (*PEMagic
!= IMAGE_PE_MAGIC
)
508 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
511 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
513 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
518 /* FIXME: if image is fixed-address load, then fail */
520 /* FIXME: check/verify OS version number */
522 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
523 PEOptionalHeader
->Magic
,
524 PEOptionalHeader
->MajorLinkerVersion
,
525 PEOptionalHeader
->MinorLinkerVersion
);
526 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
529 /* Determine the size of the module */
531 DriverSize
= PEOptionalHeader
->SizeOfImage
;
532 DPRINT("DriverSize %x\n",DriverSize
);
534 /* Allocate a virtual section for the module */
535 DriverBase
= MmAllocateSection(DriverSize
);
538 DbgPrint("Failed to allocate a virtual section for driver\n");
542 DPRINT("Module is at base %x\n",DriverBase
);
544 /* Copy image sections into virtual section */
545 memcpy(DriverBase
, ModuleLoadBase
, PESectionHeaders
[0].PointerToRawData
);
546 CurrentBase
= (PVOID
) ((DWORD
)DriverBase
+ PESectionHeaders
[0].PointerToRawData
);
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
].SizeOfRawData
);
562 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
563 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
564 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
565 '\0', PESectionHeaders
[Idx
].SizeOfRawData
);
567 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
568 PEOptionalHeader
->SectionAlignment
);
569 CurrentBase
= (PVOID
)((DWORD
)CurrentBase
+
570 ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
571 PEOptionalHeader
->SectionAlignment
));
574 /* Perform relocation fixups */
575 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
576 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
577 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
578 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
580 PEOptionalHeader
->ImageBase
,
582 DPRINT("RelocDir %x\n",RelocDir
);
583 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
585 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
587 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
588 PESectionHeaders
[Idx
].Name
,
589 PESectionHeaders
[Idx
].PointerToRawData
);
590 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
592 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
596 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
598 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
600 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
602 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
604 RelocDir->VirtualAddress,
606 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
607 sizeof(RELOCATION_DIRECTORY
));
608 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
614 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
615 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
616 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
618 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
621 Type ? "HIGHLOW" : "ABS",
623 (*RelocItem) + RelocDelta); */
626 (*RelocItem
) += RelocDelta
;
630 DbgPrint("Unknown relocation type %x\n",Type
);
634 TotalRelocs
+= RelocDir
->SizeOfBlock
;
635 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
636 RelocDir
->SizeOfBlock
);
637 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
640 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
641 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
643 /* Perform import fixups */
644 if (PEOptionalHeader
->DataDirectory
[
645 IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
647 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
649 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
651 /* Process each import module */
652 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
653 ((DWORD
)DriverBase
+ PEOptionalHeader
->
654 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
655 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
656 while (ImportModuleDirectory
->dwRVAModuleName
)
658 /* Check to make sure that import lib is kernel */
659 pName
= (PCHAR
) DriverBase
+
660 ImportModuleDirectory
->dwRVAModuleName
;
661 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
662 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
664 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
666 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
668 NameBuffer
[Idx
+ Idx2
] = 0;
669 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
670 ModuleName
.Buffer
= NameBuffer
;
671 DPRINT("Import module: %W\n", &ModuleName
);
672 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
673 if (LibraryModuleObject
== 0)
675 DbgPrint("Unknown import module: %W\n", &ModuleName
);
677 /* Get the import address list */
678 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
679 ImportModuleDirectory
->dwRVAFunctionAddressList
);
681 /* Get the list of functions to import */
682 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
684 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
685 ImportModuleDirectory
->dwRVAFunctionNameList
);
689 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
690 ImportModuleDirectory
->dwRVAFunctionAddressList
);
692 /* Walk through function list and fixup addresses */
693 while (*FunctionNameList
!= 0L)
695 if ((*FunctionNameList
) & 0x80000000) // hint
698 Hint
= (*FunctionNameList
) & 0xffff;
702 pName
= (PCHAR
)((DWORD
)DriverBase
+
703 *FunctionNameList
+ 2);
704 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
706 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
708 /* Fixup the current import symbol */
709 if (LibraryModuleObject
!= NULL
)
711 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
717 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
722 ImportModuleDirectory
++;
725 ExFreePool(SymbolNameBuf
);
728 /* Create ModuleName string */
729 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
730 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
731 .VirtualAddress
!= 0)
733 ExportDirectory
= (PIMAGE_EXPORT_DIRECTORY
) (DriverBase
+
734 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
736 wcscat(NameBuffer
, DriverBase
+ ExportDirectory
->Name
);
742 sprintf(buf
, "%08X", (DWORD
) DriverBase
);
743 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
746 while ((NameBuffer
[Idx
+ Idx2
] = (WCHAR
) buf
[Idx2
]) != 0)
749 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
750 ModuleName
.Buffer
= NameBuffer
;
751 DPRINT("Module name is: %W\n", &ModuleName
);
753 /* Initialize ObjectAttributes for ModuleObject */
754 InitializeObjectAttributes(&ObjectAttributes
,
760 /* Create module object */
762 ModuleObject
= ObCreateObject(&ModuleHandle
,
763 STANDARD_RIGHTS_REQUIRED
,
767 /* Initialize ModuleObject data */
768 ModuleObject
->Base
= DriverBase
;
769 ModuleObject
->Flags
= MODULE_FLAG_PE
;
770 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
771 PEOptionalHeader
->AddressOfEntryPoint
);
772 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
773 ModuleObject
->Image
.PE
.FileHeader
=
774 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+
775 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
776 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
777 ModuleObject
->Image
.PE
.OptionalHeader
=
778 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+
779 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
780 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
781 ModuleObject
->Image
.PE
.SectionList
=
782 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+
783 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
784 sizeof(IMAGE_OPTIONAL_HEADER
));
785 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
791 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
796 DWORD ExportsStartRVA
, ExportsEndRVA
, Delta
;
799 PDWORD FunctionList
, NameList
;
800 PIMAGE_SECTION_HEADER SectionHeader
;
801 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
803 ExportsStartRVA
= ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
804 [IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
805 ExportsEndRVA
= ExportsStartRVA
+
806 ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
807 [IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
;
808 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
809 usually the .edata section, but doesn't have to be. */
810 SectionHeader
= LdrPEGetEnclosingSectionHeader(ExportsStartRVA
, ModuleObject
);
815 Delta
= (DWORD
)(SectionHeader
->VirtualAddress
-
816 SectionHeader
->PointerToRawData
);
817 ExportDirectory
= MakePtr(PIMAGE_EXPORT_DIRECTORY
,
819 ExportsStartRVA
- Delta
);
821 FunctionList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfFunctions
-
822 Delta
+ ModuleObject
->Base
);
823 NameList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfNames
-
824 Delta
+ ModuleObject
->Base
);
825 OrdinalList
= (PWORD
)((DWORD
)ExportDirectory
->AddressOfNameOrdinals
-
826 Delta
+ ModuleObject
->Base
);
827 DPRINT("Delta:%08x\n", Delta
);
828 DPRINT("Func:%08x RVA:%08x Name:%08x RVA:%08x\nOrd:%08x RVA:%08x ",
829 FunctionList
, ExportDirectory
->AddressOfFunctions
,
830 NameList
, ExportDirectory
->AddressOfNames
,
831 OrdinalList
, ExportDirectory
->AddressOfNameOrdinals
);
832 DPRINT("NumNames:%d NumFuncs:%d\n", ExportDirectory
->NumberOfNames
,
833 ExportDirectory
->NumberOfFunctions
);
837 for (Idx
= 0; Idx
< ExportDirectory
->NumberOfNames
; Idx
++)
839 DPRINT(" Name:%s NameList[%d]:%s\n",
842 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
843 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
845 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
846 FunctionList
[OrdinalList
[Idx
]]);
853 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
854 FunctionList
[Hint
- ExportDirectory
->Base
]);
856 if (ExportAddress
== 0)
858 DbgPrint("Export not found for %d:%s\n", Hint
, Name
!= NULL
? Name
: "(Ordinal)");
861 return ExportAddress
;
864 static PIMAGE_SECTION_HEADER
865 LdrPEGetEnclosingSectionHeader(DWORD RVA
,
866 PMODULE_OBJECT ModuleObject
)
868 PIMAGE_SECTION_HEADER SectionHeader
= SECHDROFFSET(ModuleObject
->Base
);
871 for (i
= 0; i
< ModuleObject
->Image
.PE
.FileHeader
->NumberOfSections
;
872 i
++, SectionHeader
++)
874 /* Is the RVA within this section? */
875 if ((RVA
>= SectionHeader
->VirtualAddress
) &&
876 (RVA
< (SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)))
878 return SectionHeader
;