1 /* $Id: loader.c,v 1.35 1999/10/24 17:07:57 rex 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
, PUNICODE_STRING ModuleName
);
56 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
57 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
58 static NTSTATUS
LdrCreateModule(PVOID ObjectBody
,
61 POBJECT_ATTRIBUTES ObjectAttributes
);
63 /* PE Driver load support */
64 static PMODULE_OBJECT
LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
);
65 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
69 static unsigned int LdrGetKernelSymbolAddr(char *Name
);
71 static PIMAGE_SECTION_HEADER
LdrPEGetEnclosingSectionHeader(DWORD RVA
,
72 PMODULE_OBJECT ModuleObject
);
74 /* FUNCTIONS *****************************************************************/
76 VOID
LdrInitModuleManagement(VOID
)
78 HANDLE DirHandle
, ModuleHandle
;
81 ANSI_STRING AnsiString
;
82 UNICODE_STRING ModuleName
;
83 OBJECT_ATTRIBUTES ObjectAttributes
;
84 PIMAGE_DOS_HEADER DosHeader
;
85 PMODULE_OBJECT ModuleObject
;
87 /* Register the process object type */
88 ObModuleType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
89 ObModuleType
->TotalObjects
= 0;
90 ObModuleType
->TotalHandles
= 0;
91 ObModuleType
->MaxObjects
= ULONG_MAX
;
92 ObModuleType
->MaxHandles
= ULONG_MAX
;
93 ObModuleType
->PagedPoolCharge
= 0;
94 ObModuleType
->NonpagedPoolCharge
= sizeof(MODULE
);
95 ObModuleType
->Dump
= NULL
;
96 ObModuleType
->Open
= NULL
;
97 ObModuleType
->Close
= NULL
;
98 ObModuleType
->Delete
= NULL
;
99 ObModuleType
->Parse
= NULL
;
100 ObModuleType
->Security
= NULL
;
101 ObModuleType
->QueryName
= NULL
;
102 ObModuleType
->OkayToClose
= NULL
;
103 ObModuleType
->Create
= LdrCreateModule
;
104 RtlInitAnsiString(&AnsiString
, "Module");
105 RtlAnsiStringToUnicodeString(&ObModuleType
->TypeName
, &AnsiString
, TRUE
);
107 /* Create Modules object directory */
108 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
109 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
110 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
111 ModuleName
.Buffer
= NameBuffer
;
112 InitializeObjectAttributes(&ObjectAttributes
,
117 DPRINT("Create dir: %W\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 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
125 ModuleName
.Buffer
= NameBuffer
;
126 DPRINT("Kernel's Module name is: %W\n", &ModuleName
);
128 /* Initialize ObjectAttributes for ModuleObject */
129 InitializeObjectAttributes(&ObjectAttributes
,
135 /* Create module object */
137 ModuleObject
= ObCreateObject(&ModuleHandle
,
138 STANDARD_RIGHTS_REQUIRED
,
141 assert(ModuleObject
!= NULL
);
143 /* Initialize ModuleObject data */
144 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
145 ModuleObject
->Flags
= MODULE_FLAG_PE
;
146 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
147 ModuleObject
->Image
.PE
.FileHeader
=
148 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
149 DosHeader
->e_lfanew
+ sizeof(ULONG
));
150 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
151 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
152 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
153 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
154 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
155 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
156 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
158 /* FIXME: Add fake module entry for HAL */
163 * load the auto config drivers.
167 LdrLoadAutoConfigDriver (
168 LPWSTR RelativeDriverName
171 WCHAR TmpFileName
[MAX_PATH
];
173 UNICODE_STRING DriverName
;
175 LdrGetSystemDirectory(
177 (MAX_PATH
* sizeof(WCHAR
))
193 DriverName
.MaximumLength
=
197 Status
= LdrLoadDriver(&DriverName
);
198 if (!NT_SUCCESS(Status
))
201 "driver load failed, status;%d(%x)\n",
205 DbgPrintErrorMessage(Status
);
211 LdrLoadAutoConfigDrivers (VOID
)
216 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
220 LdrLoadAutoConfigDriver( L
"blue.sys" );
224 LdrLoadAutoConfigDriver( L
"vidport.sys" );
226 * VGA Miniport driver
228 LdrLoadAutoConfigDriver( L
"vgamp.sys" );
233 LdrCreateModule(PVOID ObjectBody
,
236 POBJECT_ATTRIBUTES ObjectAttributes
)
238 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %w)\n",
242 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
244 return STATUS_UNSUCCESSFUL
;
246 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
248 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
251 return STATUS_SUCCESS
;
255 * FUNCTION: Loads a kernel driver
257 * FileName = Driver to load
262 LdrLoadDriver(PUNICODE_STRING Filename
)
264 PMODULE_OBJECT ModuleObject
;
266 ModuleObject
= LdrLoadModule(Filename
);
267 if (ModuleObject
== 0)
269 return STATUS_UNSUCCESSFUL
;
272 /* FIXME: should we dereference the ModuleObject here? */
274 return IoInitializeDriver(ModuleObject
->EntryPoint
);
278 LdrLoadModule(PUNICODE_STRING Filename
)
280 PVOID ModuleLoadBase
;
283 OBJECT_ATTRIBUTES ObjectAttributes
;
284 PMODULE_OBJECT ModuleObject
;
285 FILE_STANDARD_INFORMATION FileStdInfo
;
286 WCHAR NameBuffer
[60];
287 // PWSTR RemainingPath;
288 UNICODE_STRING ModuleName
;
290 /* Check for module already loaded */
291 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
296 DPRINT("Loading Module %W...\n", Filename
);
298 /* Open the Module */
299 InitializeObjectAttributes(&ObjectAttributes
,
305 Status
= ZwOpenFile(&FileHandle
,
310 if (!NT_SUCCESS(Status
))
312 DbgPrint("Could not open module file: %W\n", Filename
);
317 /* Get the size of the file */
318 Status
= ZwQueryInformationFile(FileHandle
,
322 FileStandardInformation
);
323 if (!NT_SUCCESS(Status
))
325 DbgPrint("Could not get file size\n");
330 /* Allocate nonpageable memory for driver */
331 ModuleLoadBase
= ExAllocatePool(NonPagedPool
,
332 FileStdInfo
.EndOfFile
.u
.LowPart
);
333 if (ModuleLoadBase
== NULL
)
335 DbgPrint("could not allocate memory for module");
340 /* Load driver into memory chunk */
341 Status
= ZwReadFile(FileHandle
,
344 FileStdInfo
.EndOfFile
.u
.LowPart
,
346 if (!NT_SUCCESS(Status
))
348 DbgPrint("could not read module file into memory");
349 ExFreePool(ModuleLoadBase
);
357 /* Build module object name */
358 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
359 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
361 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
365 wcscat(NameBuffer
, Filename
->Buffer
);
367 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
368 ModuleName
.Buffer
= NameBuffer
;
370 ModuleObject
= LdrProcessModule(ModuleLoadBase
, &ModuleName
);
373 ExFreePool(ModuleLoadBase
);
379 LdrProcessDriver(PVOID ModuleLoadBase
)
381 PMODULE_OBJECT ModuleObject
;
383 ModuleObject
= LdrProcessModule(ModuleLoadBase
, 0);
384 if (ModuleObject
== 0)
386 return STATUS_UNSUCCESSFUL
;
389 /* FIXME: should we dereference the ModuleObject here? */
391 return IoInitializeDriver(ModuleObject
->EntryPoint
);
395 LdrProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING ModuleName
)
397 PIMAGE_DOS_HEADER PEDosHeader
;
399 /* If MZ header exists */
400 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
401 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
403 return LdrPEProcessModule(ModuleLoadBase
, ModuleName
);
406 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
)
410 else /* Assume COFF format and load */
412 return LdrCOFFProcessModule(ModuleLoadBase
, ModuleName
);
419 static PMODULE_OBJECT
420 LdrOpenModule(PUNICODE_STRING Filename
)
423 WCHAR NameBuffer
[60];
424 UNICODE_STRING ModuleName
;
425 OBJECT_ATTRIBUTES ObjectAttributes
;
426 PMODULE_OBJECT ModuleObject
;
429 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
430 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
432 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
436 wcscat(NameBuffer
, Filename
->Buffer
);
438 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
439 ModuleName
.Buffer
= NameBuffer
;
440 InitializeObjectAttributes(&ObjectAttributes
,
445 Status
= ObFindObject(&ObjectAttributes
,
446 (PVOID
*) &ModuleObject
,
449 if (NT_SUCCESS(Status
) && (RemainingPath
== NULL
|| *RemainingPath
== 0))
451 DPRINT("Module %W at %p\n", Filename
, ModuleObject
);
460 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
464 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
466 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
474 /* ---------------------------------------------- PE Module support */
477 LdrPEProcessModule(PVOID ModuleLoadBase
, PUNICODE_STRING pModuleName
)
479 unsigned int DriverSize
, Idx
, Idx2
;
480 ULONG RelocDelta
, NumRelocs
;
481 DWORD CurrentSize
, TotalRelocs
;
482 PVOID DriverBase
, CurrentBase
;
484 PIMAGE_DOS_HEADER PEDosHeader
;
485 PIMAGE_FILE_HEADER PEFileHeader
;
486 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
487 PIMAGE_SECTION_HEADER PESectionHeaders
;
488 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
489 PRELOCATION_DIRECTORY RelocDir
;
490 PRELOCATION_ENTRY RelocEntry
;
491 PMODULE_OBJECT LibraryModuleObject
;
493 PMODULE_OBJECT ModuleObject
;
494 PVOID
*ImportAddressList
;
495 PULONG FunctionNameList
;
496 PCHAR pName
, SymbolNameBuf
;
498 OBJECT_ATTRIBUTES ObjectAttributes
;
499 UNICODE_STRING ModuleName
;
500 WCHAR NameBuffer
[60];
502 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
504 /* Get header pointers */
505 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
506 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
507 PEDosHeader
->e_lfanew
);
508 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
509 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
510 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
511 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
512 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
513 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
514 sizeof(IMAGE_OPTIONAL_HEADER
));
517 /* Check file magic numbers */
518 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
520 DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
523 if (PEDosHeader
->e_lfanew
== 0)
525 DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
528 if (*PEMagic
!= IMAGE_PE_MAGIC
)
530 DbgPrint("Incorrect PE magic: %08x\n", *PEMagic
);
533 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
535 DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
540 /* FIXME: if image is fixed-address load, then fail */
542 /* FIXME: check/verify OS version number */
544 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
545 PEOptionalHeader
->Magic
,
546 PEOptionalHeader
->MajorLinkerVersion
,
547 PEOptionalHeader
->MinorLinkerVersion
);
548 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
551 /* Determine the size of the module */
553 DriverSize
= PEOptionalHeader
->SizeOfImage
;
554 DPRINT("DriverSize %x\n",DriverSize
);
556 /* Allocate a virtual section for the module */
557 DriverBase
= MmAllocateSection(DriverSize
);
560 DbgPrint("Failed to allocate a virtual section for driver\n");
564 DPRINT("Module is at base %x\n",DriverBase
);
566 /* Copy image sections into virtual section */
567 memcpy(DriverBase
, ModuleLoadBase
, PESectionHeaders
[0].PointerToRawData
);
568 CurrentBase
= (PVOID
) ((DWORD
)DriverBase
+ PESectionHeaders
[0].PointerToRawData
);
570 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
572 /* Copy current section into current offset of virtual section */
573 if (PESectionHeaders
[Idx
].Characteristics
&
574 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
576 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
577 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
578 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
579 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
580 PESectionHeaders
[Idx
].SizeOfRawData
);
584 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
585 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
586 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
587 '\0', PESectionHeaders
[Idx
].SizeOfRawData
);
589 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
590 PEOptionalHeader
->SectionAlignment
);
591 CurrentBase
= (PVOID
)((DWORD
)CurrentBase
+
592 ROUND_UP(PESectionHeaders
[Idx
].SizeOfRawData
,
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
[
667 IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
669 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
671 SymbolNameBuf
= ExAllocatePool(NonPagedPool
, 512);
673 /* Process each import module */
674 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
675 ((DWORD
)DriverBase
+ PEOptionalHeader
->
676 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
677 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
678 while (ImportModuleDirectory
->dwRVAModuleName
)
680 /* Check to make sure that import lib is kernel */
681 pName
= (PCHAR
) DriverBase
+
682 ImportModuleDirectory
->dwRVAModuleName
;
683 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
684 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
686 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
688 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
690 NameBuffer
[Idx
+ Idx2
] = 0;
691 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
692 ModuleName
.Buffer
= NameBuffer
;
693 DPRINT("Import module: %W\n", &ModuleName
);
694 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
695 if (LibraryModuleObject
== 0)
697 DbgPrint("Unknown import module: %W\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
720 Hint
= (*FunctionNameList
) & 0xffff;
724 pName
= (PCHAR
)((DWORD
)DriverBase
+
725 *FunctionNameList
+ 2);
726 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
728 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
730 /* Fixup the current import symbol */
731 if (LibraryModuleObject
!= NULL
)
733 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
739 DbgPrint("Unresolved kernel symbol: %s\n", pName
);
744 ImportModuleDirectory
++;
747 ExFreePool(SymbolNameBuf
);
750 /* Create ModuleName string */
751 if (pModuleName
!= 0)
753 wcscpy(NameBuffer
, pModuleName
->Buffer
);
757 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
758 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
759 .VirtualAddress
!= 0)
761 ExportDirectory
= (PIMAGE_EXPORT_DIRECTORY
) (DriverBase
+
762 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
]
764 wcscat(NameBuffer
, DriverBase
+ ExportDirectory
->Name
);
770 sprintf(buf
, "%08X", (DWORD
) DriverBase
);
771 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++)
774 while ((NameBuffer
[Idx
+ Idx2
] = (WCHAR
) buf
[Idx2
]) != 0)
778 ModuleName
.Length
= ModuleName
.MaximumLength
= wcslen(NameBuffer
);
779 ModuleName
.Buffer
= NameBuffer
;
780 DbgPrint("Module name is: %W\n", &ModuleName
);
782 /* Initialize ObjectAttributes for ModuleObject */
783 InitializeObjectAttributes(&ObjectAttributes
,
789 /* Create module object */
791 ModuleObject
= ObCreateObject(&ModuleHandle
,
792 STANDARD_RIGHTS_REQUIRED
,
796 /* Initialize ModuleObject data */
797 ModuleObject
->Base
= DriverBase
;
798 ModuleObject
->Flags
= MODULE_FLAG_PE
;
799 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
800 PEOptionalHeader
->AddressOfEntryPoint
);
801 DPRINT("entrypoint at %x\n", ModuleObject
->EntryPoint
);
802 ModuleObject
->Image
.PE
.FileHeader
=
803 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+
804 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
805 DPRINT("FileHeader at %x\n", ModuleObject
->Image
.PE
.FileHeader
);
806 ModuleObject
->Image
.PE
.OptionalHeader
=
807 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+
808 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
809 DPRINT("OptionalHeader at %x\n", ModuleObject
->Image
.PE
.OptionalHeader
);
810 ModuleObject
->Image
.PE
.SectionList
=
811 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+
812 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
813 sizeof(IMAGE_OPTIONAL_HEADER
));
814 DPRINT("SectionList at %x\n", ModuleObject
->Image
.PE
.SectionList
);
820 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
825 DWORD ExportsStartRVA
, ExportsEndRVA
, Delta
;
828 PDWORD FunctionList
, NameList
;
829 PIMAGE_SECTION_HEADER SectionHeader
;
830 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
832 ExportsStartRVA
= ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
833 [IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
834 ExportsEndRVA
= ExportsStartRVA
+
835 ModuleObject
->Image
.PE
.OptionalHeader
->DataDirectory
836 [IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
;
837 /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
838 usually the .edata section, but doesn't have to be. */
839 SectionHeader
= LdrPEGetEnclosingSectionHeader(ExportsStartRVA
, ModuleObject
);
844 Delta
= (DWORD
)(SectionHeader
->VirtualAddress
-
845 SectionHeader
->PointerToRawData
);
846 ExportDirectory
= MakePtr(PIMAGE_EXPORT_DIRECTORY
,
848 ExportsStartRVA
- Delta
);
850 FunctionList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfFunctions
-
851 Delta
+ ModuleObject
->Base
);
852 NameList
= (PDWORD
)((DWORD
)ExportDirectory
->AddressOfNames
-
853 Delta
+ ModuleObject
->Base
);
854 OrdinalList
= (PWORD
)((DWORD
)ExportDirectory
->AddressOfNameOrdinals
-
855 Delta
+ ModuleObject
->Base
);
856 DPRINT("Delta:%08x\n", Delta
);
857 DPRINT("Func:%08x RVA:%08x Name:%08x RVA:%08x\nOrd:%08x RVA:%08x ",
858 FunctionList
, ExportDirectory
->AddressOfFunctions
,
859 NameList
, ExportDirectory
->AddressOfNames
,
860 OrdinalList
, ExportDirectory
->AddressOfNameOrdinals
);
861 DPRINT("NumNames:%d NumFuncs:%d\n", ExportDirectory
->NumberOfNames
,
862 ExportDirectory
->NumberOfFunctions
);
866 for (Idx
= 0; Idx
< ExportDirectory
->NumberOfNames
; Idx
++)
868 DPRINT(" Name:%s NameList[%d]:%s\n",
871 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
872 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
874 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
875 FunctionList
[OrdinalList
[Idx
]]);
882 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
883 FunctionList
[Hint
- ExportDirectory
->Base
]);
885 if (ExportAddress
== 0)
887 DbgPrint("Export not found for %d:%s\n", Hint
, Name
!= NULL
? Name
: "(Ordinal)");
890 return ExportAddress
;
893 static PIMAGE_SECTION_HEADER
894 LdrPEGetEnclosingSectionHeader(DWORD RVA
,
895 PMODULE_OBJECT ModuleObject
)
897 PIMAGE_SECTION_HEADER SectionHeader
= SECHDROFFSET(ModuleObject
->Base
);
900 for (i
= 0; i
< ModuleObject
->Image
.PE
.FileHeader
->NumberOfSections
;
901 i
++, SectionHeader
++)
903 /* Is the RVA within this section? */
904 if ((RVA
>= SectionHeader
->VirtualAddress
) &&
905 (RVA
< (SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)))
907 return SectionHeader
;