1 /* $Id: loader.c,v 1.87 2001/08/26 17:27:44 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ldr/loader.c
6 * PURPOSE: Loaders for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
9 * Jason Filby (jasonfilby@yahoo.com)
10 * Casper S. Hornstrup (chorns@users.sourceforge.net)
13 * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
14 * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
15 * RJJ 10/12/98 Rolled in David's code to load COFF drivers
16 * JM 14/12/98 Built initial PE user module loader
17 * RJJ 06/03/99 Moved user PE loader into NTDLL
18 * JF 26/01/2000 Recoded some parts to retrieve export details correctly
19 * DW 27/06/2000 Removed redundant header files
20 * CSH 11/04/2001 Added automatic loading of module symbols if they exist
24 /* INCLUDES *****************************************************************/
27 #include <ddk/ntddk.h>
28 #include <internal/config.h>
29 #include <internal/module.h>
30 #include <internal/ntoskrnl.h>
31 #include <internal/io.h>
32 #include <internal/mm.h>
33 #include <internal/ob.h>
34 #include <internal/ps.h>
35 #include <internal/ldr.h>
36 #include <internal/pool.h>
39 #include <internal/ntosdbg.h>
45 #include <internal/debug.h>
47 /* MACROS ********************************************************************/
49 #define KERNEL_MODULE_NAME L"ntoskrnl.exe"
50 #define HAL_MODULE_NAME L"hal.dll"
51 #define MODULE_ROOT_NAME L"\\Modules\\"
52 #define FILESYSTEM_ROOT_NAME L"\\FileSystem\\"
54 /* GLOBALS *******************************************************************/
56 LIST_ENTRY ModuleListHead
;
57 POBJECT_TYPE EXPORTED IoDriverObjectType
= NULL
;
58 LIST_ENTRY ModuleTextListHead
;
59 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
60 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
63 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
64 #define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
66 /* FORWARD DECLARATIONS ******************************************************/
68 PMODULE_OBJECT
LdrLoadModule(PUNICODE_STRING Filename
);
69 NTSTATUS
LdrProcessModule(PVOID ModuleLoadBase
,
70 PUNICODE_STRING ModuleName
,
71 PMODULE_OBJECT
*ModuleObject
);
72 PVOID
LdrGetExportAddress(PMODULE_OBJECT ModuleObject
, char *Name
, unsigned short Hint
);
73 static PMODULE_OBJECT
LdrOpenModule(PUNICODE_STRING Filename
);
74 static NTSTATUS STDCALL
75 LdrCreateModule(PVOID ObjectBody
,
78 POBJECT_ATTRIBUTES ObjectAttributes
);
79 static VOID
LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
80 PUNICODE_STRING FullName
);
82 /* PE Driver load support */
83 static NTSTATUS
LdrPEProcessModule(PVOID ModuleLoadBase
,
84 PUNICODE_STRING FileName
,
85 PMODULE_OBJECT
*ModuleObject
);
86 static PVOID
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
89 static PMODULE_OBJECT
LdrPEGetModuleObject(PUNICODE_STRING ModuleName
);
90 static PVOID
LdrPEFixupForward(PCHAR ForwardName
);
93 LdrSafePEGetExportAddress(
94 PVOID ImportModuleBase
,
99 /* FUNCTIONS *****************************************************************/
102 LdrInitDebug(PLOADER_MODULE Module
, PWCH Name
)
104 PLIST_ENTRY current_entry
;
105 MODULE_TEXT_SECTION
* current
;
107 current_entry
= ModuleTextListHead
.Flink
;
108 while (current_entry
!= &ModuleTextListHead
)
111 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
112 if (wcscmp(current
->Name
, Name
) == 0)
116 current_entry
= current_entry
->Flink
;
119 if (current_entry
== &ModuleTextListHead
)
124 current
->SymbolsBase
= (PVOID
)Module
->ModStart
;
125 current
->SymbolsLength
= Module
->ModEnd
- Module
->ModStart
;
131 PIMAGE_DOS_HEADER DosHeader
;
132 PIMAGE_FILE_HEADER FileHeader
;
133 PIMAGE_OPTIONAL_HEADER OptionalHeader
;
134 PIMAGE_SECTION_HEADER SectionList
;
136 InitializeListHead(&ModuleTextListHead
);
138 /* Setup ntoskrnl.exe text section */
139 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
141 (PIMAGE_FILE_HEADER
) ((DWORD
)KERNEL_BASE
+
142 DosHeader
->e_lfanew
+ sizeof(ULONG
));
143 OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
144 ((DWORD
)FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
145 SectionList
= (PIMAGE_SECTION_HEADER
)
146 ((DWORD
)OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
147 NtoskrnlTextSection
.Base
= KERNEL_BASE
;
148 NtoskrnlTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
149 SectionList
[0].VirtualAddress
;
150 NtoskrnlTextSection
.Name
= KERNEL_MODULE_NAME
;
151 NtoskrnlTextSection
.SymbolsBase
= NULL
;
152 NtoskrnlTextSection
.SymbolsLength
= 0;
153 InsertTailList(&ModuleTextListHead
, &NtoskrnlTextSection
.ListEntry
);
155 /* Setup hal.dll text section */
156 DosHeader
= (PIMAGE_DOS_HEADER
)LdrHalBase
;
158 (PIMAGE_FILE_HEADER
) ((DWORD
)LdrHalBase
+
159 DosHeader
->e_lfanew
+ sizeof(ULONG
));
160 OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
161 ((DWORD
)FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
162 SectionList
= (PIMAGE_SECTION_HEADER
)
163 ((DWORD
)OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
164 LdrHalTextSection
.Base
= LdrHalBase
;
165 LdrHalTextSection
.Length
= SectionList
[0].Misc
.VirtualSize
+
166 SectionList
[0].VirtualAddress
;
167 LdrHalTextSection
.Name
= HAL_MODULE_NAME
;
168 LdrHalTextSection
.SymbolsBase
= NULL
;
169 LdrHalTextSection
.SymbolsLength
= 0;
170 InsertTailList(&ModuleTextListHead
, &LdrHalTextSection
.ListEntry
);
173 VOID
LdrInitModuleManagement(VOID
)
175 HANDLE DirHandle
, ModuleHandle
;
177 WCHAR NameBuffer
[60];
178 UNICODE_STRING ModuleName
;
179 OBJECT_ATTRIBUTES ObjectAttributes
;
180 PIMAGE_DOS_HEADER DosHeader
;
181 PMODULE_OBJECT ModuleObject
;
183 /* Register the process object type */
184 IoDriverObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
185 IoDriverObjectType
->Tag
= TAG('D', 'R', 'V', 'T');
186 IoDriverObjectType
->TotalObjects
= 0;
187 IoDriverObjectType
->TotalHandles
= 0;
188 IoDriverObjectType
->MaxObjects
= ULONG_MAX
;
189 IoDriverObjectType
->MaxHandles
= ULONG_MAX
;
190 IoDriverObjectType
->PagedPoolCharge
= 0;
191 IoDriverObjectType
->NonpagedPoolCharge
= sizeof(MODULE
);
192 IoDriverObjectType
->Dump
= NULL
;
193 IoDriverObjectType
->Open
= NULL
;
194 IoDriverObjectType
->Close
= NULL
;
195 IoDriverObjectType
->Delete
= NULL
;
196 IoDriverObjectType
->Parse
= NULL
;
197 IoDriverObjectType
->Security
= NULL
;
198 IoDriverObjectType
->QueryName
= NULL
;
199 IoDriverObjectType
->OkayToClose
= NULL
;
200 IoDriverObjectType
->Create
= LdrCreateModule
;
201 RtlInitUnicodeString(&IoDriverObjectType
->TypeName
, L
"Driver");
203 /* Create Modules object directory */
204 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
205 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
206 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
207 InitializeObjectAttributes(&ObjectAttributes
,
212 DPRINT("Create dir: %wZ\n", &ModuleName
);
213 Status
= NtCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
214 assert(NT_SUCCESS(Status
));
216 /* Create FileSystem object directory */
217 wcscpy(NameBuffer
, FILESYSTEM_ROOT_NAME
);
218 *(wcsrchr(NameBuffer
, L
'\\')) = 0;
219 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
220 InitializeObjectAttributes(&ObjectAttributes
,
225 DPRINT("Create dir: %wZ\n", &ModuleName
);
226 Status
= NtCreateDirectoryObject(&DirHandle
, 0, &ObjectAttributes
);
227 assert(NT_SUCCESS(Status
));
229 /* Add module entry for NTOSKRNL */
230 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
231 wcscat(NameBuffer
, KERNEL_MODULE_NAME
);
232 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
233 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName
);
235 /* Initialize ObjectAttributes for ModuleObject */
236 InitializeObjectAttributes(&ObjectAttributes
,
242 /* Create module object */
244 Status
= ObCreateObject(&ModuleHandle
,
245 STANDARD_RIGHTS_REQUIRED
,
248 (PVOID
*)&ModuleObject
);
249 assert(NT_SUCCESS(Status
));
251 InitializeListHead(&ModuleListHead
);
253 /* Initialize ModuleObject data */
254 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
255 ModuleObject
->Flags
= MODULE_FLAG_PE
;
256 InsertTailList(&ModuleListHead
,
257 &ModuleObject
->ListEntry
);
258 RtlCreateUnicodeString(&ModuleObject
->FullName
,
260 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
261 &ModuleObject
->FullName
);
263 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
264 ModuleObject
->Image
.PE
.FileHeader
=
265 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
266 DosHeader
->e_lfanew
+ sizeof(ULONG
));
267 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
268 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
269 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
270 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
271 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
272 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
273 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
274 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
275 ModuleObject
->TextSection
= &NtoskrnlTextSection
;
277 /* Add module entry for HAL */
278 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
279 wcscat(NameBuffer
, HAL_MODULE_NAME
);
280 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
281 DPRINT("HAL's Module name is: %wZ\n", &ModuleName
);
283 /* Initialize ObjectAttributes for ModuleObject */
284 InitializeObjectAttributes(&ObjectAttributes
,
290 /* Create module object */
292 Status
= ObCreateObject(&ModuleHandle
,
293 STANDARD_RIGHTS_REQUIRED
,
296 (PVOID
*)&ModuleObject
);
297 assert(NT_SUCCESS(Status
));
299 /* Initialize ModuleObject data */
300 ModuleObject
->Base
= (PVOID
) LdrHalBase
;
301 ModuleObject
->Flags
= MODULE_FLAG_PE
;
302 InsertTailList(&ModuleListHead
,
303 &ModuleObject
->ListEntry
);
304 RtlCreateUnicodeString(&ModuleObject
->FullName
,
306 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
307 &ModuleObject
->FullName
);
309 DosHeader
= (PIMAGE_DOS_HEADER
) LdrHalBase
;
310 ModuleObject
->Image
.PE
.FileHeader
=
311 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
312 DosHeader
->e_lfanew
+ sizeof(ULONG
));
313 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
314 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
315 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
316 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
317 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
318 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
319 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
320 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
321 ModuleObject
->TextSection
= &LdrHalTextSection
;
325 * load the auto config drivers.
327 static VOID
LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName
)
329 WCHAR TmpFileName
[MAX_PATH
];
330 UNICODE_STRING DriverName
;
331 PDEVICE_NODE DeviceNode
;
334 CPRINT("Loading %S\n",RelativeDriverName
);
336 wcscpy(TmpFileName
, L
"\\SystemRoot\\system32\\drivers\\");
337 wcscat(TmpFileName
, RelativeDriverName
);
338 RtlInitUnicodeString (&DriverName
, TmpFileName
);
340 /* Use IopRootDeviceNode for now */
341 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
342 if (!NT_SUCCESS(Status
))
347 Status
= LdrLoadDriver(&DriverName
, DeviceNode
, FALSE
);
348 if (!NT_SUCCESS(Status
))
350 IopFreeDeviceNode(DeviceNode
);
351 DPRINT1("Driver load failed, status (%x)\n", Status
);
357 BOOLEAN
LdrpReadLine(PCHAR Line
,
372 while ((*Size
> 0) && (Count
< LineSize
) && ((ch
= *Block
) != (CHAR
)13))
388 if ((*Size
> 0) && (*Block
== (CHAR
)10))
399 ULONG
HexL(PCHAR Buffer
)
408 while ((j
> 0) && ((ch
= Buffer
[i
]) != ' '))
411 if ((ch
>= '0') && (ch
<= '9'))
412 Value
|= ((ch
- '0') << j
);
413 if ((ch
>= 'A') && (ch
<= 'F'))
414 Value
|= ((10 + (ch
- 'A')) << j
);
416 if ((ch
>= 'a') && (ch
<= 'f'))
417 Value
|= ((10 + (ch
- 'a')) << j
);
423 PSYMBOL
LdrpParseLine(PCHAR Line
,
425 PBOOLEAN TextBaseValid
,
428 Line format: [ADDRESS] <TYPE> <NAME>
431 A = Image information
432 t = Symbol in text segment
433 T = Symbol in text segment
434 d = Symbol in data segment
435 D = Symbol in data segment
436 b = Symbol in BSS segment
437 B = Symbol in BSS segment
438 ? = Unknown segment or symbol in unknown segment
441 ANSI_STRING AnsiString
;
448 if ((Line
[0] == (CHAR
)0) || (Line
[0] == ' '))
451 Address
= HexL(Line
);
453 Line
= strchr(Line
, ' ');
460 Line
= strchr(Line
, ' ');
465 Str
= strchr(Line
, ' ');
467 strcpy((char*)&Buffer
, Line
);
469 strncpy((char*)&Buffer
, Line
, Str
- Line
);
471 if ((Type
== 'A') && (strcmp((char*)&Buffer
, "__section_alignment__")) == 0)
473 *Alignment
= Address
;
477 /* We only want symbols in the .text segment */
478 if ((Type
!= 't') && (Type
!= 'T'))
481 /* Discard other symbols we can't use */
482 if ((Buffer
[0] != '_') || ((Buffer
[0] == '_') && (Buffer
[1] == '_')))
485 Symbol
= ExAllocatePool(NonPagedPool
, sizeof(SYMBOL
));
491 Symbol
->RelativeAddress
= Address
;
493 RtlInitAnsiString(&AnsiString
, (PCSZ
)&Buffer
);
494 RtlAnsiStringToUnicodeString(&Symbol
->Name
, &AnsiString
, TRUE
);
496 if (!(*TextBaseValid
))
498 *TextBase
= Address
- *Alignment
;
499 *TextBaseValid
= TRUE
;
505 VOID
LdrpLoadModuleSymbolsFromBuffer(
506 PMODULE_OBJECT ModuleObject
,
510 Symbols must be sorted by address, e.g.
511 "nm --numeric-sort module.sys > module.sym"
514 PSYMBOL Symbol
, CurrentSymbol
= NULL
;
515 BOOLEAN TextBaseValid
;
522 assert(ModuleObject
);
524 if (ModuleObject
->TextSection
== NULL
)
526 ModuleObject
->TextSection
= &NtoskrnlTextSection
;
529 if (ModuleObject
->TextSection
->Symbols
.SymbolCount
> 0)
531 CPRINT("Symbols are already loaded for %wZ\n", &ModuleObject
->BaseName
);
535 ModuleObject
->TextSection
->Symbols
.SymbolCount
= 0;
536 ModuleObject
->TextSection
->Symbols
.Symbols
= NULL
;
537 TextBaseValid
= FALSE
;
539 while (LdrpReadLine((PCHAR
)&Line
, 256, &Buffer
, &Length
))
541 Symbol
= LdrpParseLine((PCHAR
)&Line
, &Tmp
, &Valid
, &Alignment
);
543 if ((Valid
) && (!TextBaseValid
))
546 TextBaseValid
= TRUE
;
551 Symbol
->RelativeAddress
-= TextBase
;
553 if (ModuleObject
->TextSection
->Symbols
.Symbols
== NULL
)
554 ModuleObject
->TextSection
->Symbols
.Symbols
= Symbol
;
556 CurrentSymbol
->Next
= Symbol
;
558 CurrentSymbol
= Symbol
;
560 ModuleObject
->TextSection
->Symbols
.SymbolCount
++;
565 VOID
LdrpLoadUserModuleSymbolsFromBuffer(
566 PLDR_MODULE ModuleObject
,
570 Symbols must be sorted by address, e.g.
571 "nm --numeric-sort module.dll > module.sym"
574 PSYMBOL Symbol
, CurrentSymbol
= NULL
;
575 BOOLEAN TextBaseValid
;
582 if (ModuleObject
->Symbols
.SymbolCount
> 0)
584 DPRINT("Symbols are already loaded for %wZ\n", &ModuleObject
->BaseDllName
);
588 ModuleObject
->Symbols
.SymbolCount
= 0;
589 ModuleObject
->Symbols
.Symbols
= NULL
;
590 TextBaseValid
= FALSE
;
592 while (LdrpReadLine((PCHAR
)&Line
, 256, &Buffer
, &Length
))
594 Symbol
= LdrpParseLine((PCHAR
)&Line
, &Tmp
, &Valid
, &Alignment
);
596 if ((Valid
) && (!TextBaseValid
))
599 TextBaseValid
= TRUE
;
604 Symbol
->RelativeAddress
-= TextBase
;
606 if (ModuleObject
->Symbols
.Symbols
== NULL
)
607 ModuleObject
->Symbols
.Symbols
= Symbol
;
609 CurrentSymbol
->Next
= Symbol
;
611 CurrentSymbol
= Symbol
;
613 ModuleObject
->Symbols
.SymbolCount
++;
619 LdrpLoadModuleSymbols(PMODULE_OBJECT ModuleObject
)
621 FILE_STANDARD_INFORMATION FileStdInfo
;
622 OBJECT_ATTRIBUTES ObjectAttributes
;
623 WCHAR TmpFileName
[MAX_PATH
];
624 UNICODE_STRING Filename
;
630 IO_STATUS_BLOCK IoStatusBlock
;
632 /* Get the path to the symbol store */
633 wcscpy(TmpFileName
, L
"\\SystemRoot\\symbols\\");
635 /* Get the symbol filename from the module name */
636 Start
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'\\');
638 Start
= ModuleObject
->BaseName
.Buffer
;
642 Ext
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'.');
644 Length
= Ext
- Start
;
646 Length
= wcslen(Start
);
648 wcsncat(TmpFileName
, Start
, Length
);
649 wcscat(TmpFileName
, L
".sym");
650 RtlInitUnicodeString(&Filename
, TmpFileName
);
653 InitializeObjectAttributes(&ObjectAttributes
,
659 Status
= ZwOpenFile(&FileHandle
,
665 if (!NT_SUCCESS(Status
))
667 DPRINT("Could not open symbol file: %wZ\n", &Filename
);
671 CPRINT("Loading symbols from %wZ...\n", &Filename
);
673 /* Get the size of the file */
674 Status
= ZwQueryInformationFile(FileHandle
,
678 FileStandardInformation
);
679 if (!NT_SUCCESS(Status
))
681 DPRINT("Could not get file size\n");
685 /* Allocate nonpageable memory for symbol file */
686 FileBuffer
= ExAllocatePool(NonPagedPool
,
687 FileStdInfo
.EndOfFile
.u
.LowPart
);
689 if (FileBuffer
== NULL
)
691 DPRINT("Could not allocate memory for symbol file\n");
695 /* Load file into memory chunk */
696 Status
= ZwReadFile(FileHandle
,
700 FileStdInfo
.EndOfFile
.u
.LowPart
,
702 if (!NT_SUCCESS(Status
))
704 DPRINT("Could not read symbol file into memory\n");
705 ExFreePool(FileBuffer
);
711 LdrpLoadModuleSymbolsFromBuffer(ModuleObject
,
713 FileStdInfo
.EndOfFile
.u
.LowPart
);
715 ExFreePool(FileBuffer
);
718 VOID
LdrLoadUserModuleSymbols(PLDR_MODULE ModuleObject
)
720 FILE_STANDARD_INFORMATION FileStdInfo
;
721 OBJECT_ATTRIBUTES ObjectAttributes
;
722 WCHAR TmpFileName
[MAX_PATH
];
723 UNICODE_STRING Filename
;
729 IO_STATUS_BLOCK IoStatusBlock
;
731 /* Get the path to the symbol store */
732 wcscpy(TmpFileName
, L
"\\SystemRoot\\symbols\\");
734 /* Get the symbol filename from the module name */
735 Start
= wcsrchr(ModuleObject
->BaseDllName
.Buffer
, L
'\\');
737 Start
= ModuleObject
->BaseDllName
.Buffer
;
741 Ext
= wcsrchr(ModuleObject
->BaseDllName
.Buffer
, L
'.');
743 Length
= Ext
- Start
;
745 Length
= wcslen(Start
);
747 wcsncat(TmpFileName
, Start
, Length
);
748 wcscat(TmpFileName
, L
".sym");
749 RtlInitUnicodeString(&Filename
, TmpFileName
);
752 InitializeObjectAttributes(&ObjectAttributes
,
758 Status
= ZwOpenFile(&FileHandle
,
764 if (!NT_SUCCESS(Status
))
766 DPRINT("Could not open symbol file: %wZ\n", &Filename
);
770 DbgPrint("Loading symbols from %wZ...\n", &Filename
);
772 /* Get the size of the file */
773 Status
= ZwQueryInformationFile(FileHandle
,
777 FileStandardInformation
);
778 if (!NT_SUCCESS(Status
))
780 DPRINT("Could not get file size\n");
784 /* Allocate nonpageable memory for symbol file */
785 FileBuffer
= ExAllocatePool(NonPagedPool
,
786 FileStdInfo
.EndOfFile
.u
.LowPart
);
788 if (FileBuffer
== NULL
)
790 DPRINT("Could not allocate memory for symbol file\n");
794 /* Load file into memory chunk */
795 Status
= ZwReadFile(FileHandle
,
799 FileStdInfo
.EndOfFile
.u
.LowPart
,
801 if (!NT_SUCCESS(Status
))
803 DPRINT("Could not read symbol file into memory\n");
804 ExFreePool(FileBuffer
);
810 LdrpLoadUserModuleSymbolsFromBuffer(ModuleObject
,
812 FileStdInfo
.EndOfFile
.u
.LowPart
);
814 ExFreePool(FileBuffer
);
817 NTSTATUS
LdrpFindModuleObject(
818 PUNICODE_STRING ModuleName
,
819 PMODULE_OBJECT
*ModuleObject
)
822 WCHAR NameBuffer
[MAX_PATH
];
824 OBJECT_ATTRIBUTES ObjectAttributes
;
825 UNICODE_STRING RemainingPath
;
827 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
828 wcscat(NameBuffer
, ModuleName
->Buffer
);
829 RtlInitUnicodeString(&Name
, NameBuffer
);
831 InitializeObjectAttributes(&ObjectAttributes
,
836 Status
= ObFindObject(&ObjectAttributes
,
837 (PVOID
*)ModuleObject
,
840 if (!NT_SUCCESS(Status
))
845 if ((RemainingPath
.Buffer
!= NULL
) || (*ModuleObject
== NULL
))
847 RtlFreeUnicodeString(&RemainingPath
);
848 return STATUS_UNSUCCESSFUL
;
851 return STATUS_SUCCESS
;
856 VOID
LdrLoadAutoConfigDrivers (VOID
)
862 UNICODE_STRING ModuleName
;
863 PMODULE_OBJECT ModuleObject
;
865 /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
866 is created after their module entries */
868 RtlInitUnicodeString(&ModuleName
, KERNEL_MODULE_NAME
);
869 Status
= LdrpFindModuleObject(&ModuleName
, &ModuleObject
);
870 if (NT_SUCCESS(Status
))
872 LdrpLoadModuleSymbols(ModuleObject
);
875 RtlInitUnicodeString(&ModuleName
, HAL_MODULE_NAME
);
876 Status
= LdrpFindModuleObject(&ModuleName
, &ModuleObject
);
877 if (NT_SUCCESS(Status
))
879 LdrpLoadModuleSymbols(ModuleObject
);
886 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
891 LdrLoadAutoConfigDriver( L
"blue.sys" );
896 LdrLoadAutoConfigDriver(L
"vidport.sys");
901 LdrLoadAutoConfigDriver(L
"vgamp.sys");
904 * Minix filesystem driver
906 LdrLoadAutoConfigDriver(L
"minixfs.sys");
909 * Mailslot filesystem driver
911 LdrLoadAutoConfigDriver(L
"msfs.sys");
914 * Named pipe filesystem driver
916 LdrLoadAutoConfigDriver(L
"npfs.sys");
921 // LdrLoadAutoConfigDriver(L"l8042prt.sys");
922 LdrLoadAutoConfigDriver(L
"psaux.sys");
923 LdrLoadAutoConfigDriver(L
"mouclass.sys");
932 LdrLoadAutoConfigDriver(L
"ndis.sys");
935 * Novell Eagle 2000 driver
937 //LdrLoadAutoConfigDriver(L"ne2000.sys");
940 * TCP/IP protocol driver
942 LdrLoadAutoConfigDriver(L
"tcpip.sys");
947 //LdrLoadAutoConfigDriver(L"tditest.sys");
950 * Ancillary Function Driver
952 LdrLoadAutoConfigDriver(L
"afd.sys");
957 static NTSTATUS STDCALL
958 LdrCreateModule(PVOID ObjectBody
,
961 POBJECT_ATTRIBUTES ObjectAttributes
)
963 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
967 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
969 return STATUS_UNSUCCESSFUL
;
971 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
973 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
976 return STATUS_SUCCESS
;
980 * FUNCTION: Loads a kernel driver
982 * FileName = Driver to load
986 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
,
987 PDEVICE_NODE DeviceNode
,
988 BOOLEAN BootDriversOnly
)
990 PMODULE_OBJECT ModuleObject
;
993 ModuleObject
= LdrLoadModule(Filename
);
996 return STATUS_UNSUCCESSFUL
;
999 Status
= IopInitializeDriver(ModuleObject
->EntryPoint
,
1000 DeviceNode
, Filename
, BootDriversOnly
);
1001 if (!NT_SUCCESS(Status
))
1003 ObDereferenceObject(ModuleObject
);
1009 NTSTATUS
LdrLoadGdiDriver (PUNICODE_STRING DriverName
,
1010 PVOID
*ImageAddress
,
1011 PVOID
*SectionPointer
,
1013 PVOID
*ExportSectionPointer
)
1015 PMODULE_OBJECT ModuleObject
;
1017 ModuleObject
= LdrLoadModule(DriverName
);
1018 if (ModuleObject
== 0)
1020 return STATUS_UNSUCCESSFUL
;
1024 *ImageAddress
= ModuleObject
->Base
;
1026 // if (SectionPointer)
1027 // *SectionPointer = ModuleObject->
1030 *EntryPoint
= ModuleObject
->EntryPoint
;
1032 // if (ExportSectionPointer)
1033 // *ExportSectionPointer = ModuleObject->
1035 return STATUS_SUCCESS
;
1040 LdrLoadModule(PUNICODE_STRING Filename
)
1042 PVOID ModuleLoadBase
;
1045 OBJECT_ATTRIBUTES ObjectAttributes
;
1046 PMODULE_OBJECT ModuleObject
;
1047 FILE_STANDARD_INFORMATION FileStdInfo
;
1048 IO_STATUS_BLOCK IoStatusBlock
;
1050 /* Check for module already loaded */
1051 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
1053 return ModuleObject
;
1056 DPRINT("Loading Module %wZ...\n", Filename
);
1058 /* Open the Module */
1059 InitializeObjectAttributes(&ObjectAttributes
,
1065 Status
= NtOpenFile(&FileHandle
,
1072 if (!NT_SUCCESS(Status
))
1074 CPRINT("Could not open module file: %wZ\n", Filename
);
1079 /* Get the size of the file */
1080 Status
= NtQueryInformationFile(FileHandle
,
1083 sizeof(FileStdInfo
),
1084 FileStandardInformation
);
1085 if (!NT_SUCCESS(Status
))
1087 CPRINT("Could not get file size\n");
1092 /* Allocate nonpageable memory for driver */
1093 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
1094 FileStdInfo
.EndOfFile
.u
.LowPart
,
1097 if (ModuleLoadBase
== NULL
)
1099 CPRINT("Could not allocate memory for module");
1104 /* Load driver into memory chunk */
1105 Status
= NtReadFile(FileHandle
,
1109 FileStdInfo
.EndOfFile
.u
.LowPart
,
1111 if (!NT_SUCCESS(Status
))
1113 CPRINT("Could not read module file into memory");
1114 ExFreePool(ModuleLoadBase
);
1119 NtClose(FileHandle
);
1121 Status
= LdrProcessModule(ModuleLoadBase
,
1124 if (!NT_SUCCESS(Status
))
1126 CPRINT("Could not process module");
1127 ExFreePool(ModuleLoadBase
);
1132 ExFreePool(ModuleLoadBase
);
1136 /* Load symbols for module if available */
1137 LdrpLoadModuleSymbols(ModuleObject
);
1141 return ModuleObject
;
1145 LdrProcessDriver(PVOID ModuleLoadBase
, PCHAR FileName
, ULONG ModuleLength
)
1147 PMODULE_OBJECT ModuleObject
;
1148 UNICODE_STRING ModuleName
;
1149 PDEVICE_NODE DeviceNode
;
1154 CHAR TmpBaseName
[MAX_PATH
];
1155 CHAR TmpFileName
[MAX_PATH
];
1156 ANSI_STRING AnsiString
;
1160 /* Split the filename into base name and extension */
1161 Ext
= strrchr(FileName
, '.');
1163 Length
= Ext
- FileName
;
1165 Length
= strlen(FileName
);
1167 if ((Ext
!= NULL
) && (strcmp(Ext
, ".sym") == 0))
1169 DPRINT("Module %s is a symbol file\n", FileName
);
1171 strncpy(TmpBaseName
, FileName
, Length
);
1172 TmpBaseName
[Length
] = '\0';
1174 DPRINT("base: %s (Length %d)\n", TmpBaseName
, Length
);
1176 strcpy(TmpFileName
, TmpBaseName
);
1177 strcat(TmpFileName
, ".sys");
1178 RtlInitAnsiString(&AnsiString
, TmpFileName
);
1180 DPRINT("dasdsad: %s\n", TmpFileName
);
1182 RtlAnsiStringToUnicodeString(&ModuleName
, &AnsiString
, TRUE
);
1183 Status
= LdrpFindModuleObject(&ModuleName
, &ModuleObject
);
1184 RtlFreeUnicodeString(&ModuleName
);
1185 if (!NT_SUCCESS(Status
))
1187 strcpy(TmpFileName
, TmpBaseName
);
1188 strcat(TmpFileName
, ".exe");
1189 RtlInitAnsiString(&AnsiString
, TmpFileName
);
1190 RtlAnsiStringToUnicodeString(&ModuleName
, &AnsiString
, TRUE
);
1191 Status
= LdrpFindModuleObject(&ModuleName
, &ModuleObject
);
1192 RtlFreeUnicodeString(&ModuleName
);
1194 if (NT_SUCCESS(Status
))
1196 LdrpLoadModuleSymbolsFromBuffer(
1201 return(STATUS_SUCCESS
);
1205 DPRINT("Module %s is executable\n", FileName
);
1209 /* Use IopRootDeviceNode for now */
1210 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1211 if (!NT_SUCCESS(Status
))
1213 CPRINT("Driver load failed, status (%x)\n", Status
);
1217 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1219 Status
= LdrProcessModule(ModuleLoadBase
,
1222 RtlFreeUnicodeString(&ModuleName
);
1223 if (ModuleObject
== NULL
)
1225 IopFreeDeviceNode(DeviceNode
);
1226 CPRINT("Driver load failed, status (%x)\n", Status
);
1227 return(STATUS_UNSUCCESSFUL
);
1230 Status
= IopInitializeDriver(ModuleObject
->EntryPoint
, DeviceNode
, NULL
, FALSE
);
1231 if (!NT_SUCCESS(Status
))
1233 IopFreeDeviceNode(DeviceNode
);
1234 CPRINT("Driver load failed, status (%x)\n", Status
);
1241 LdrProcessModule(PVOID ModuleLoadBase
,
1242 PUNICODE_STRING ModuleName
,
1243 PMODULE_OBJECT
*ModuleObject
)
1245 PIMAGE_DOS_HEADER PEDosHeader
;
1247 /* If MZ header exists */
1248 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1249 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
1251 return LdrPEProcessModule(ModuleLoadBase
,
1256 CPRINT("Module wasn't PE\n");
1257 return STATUS_UNSUCCESSFUL
;
1260 static PMODULE_OBJECT
1261 LdrOpenModule(PUNICODE_STRING Filename
)
1264 WCHAR NameBuffer
[60];
1265 UNICODE_STRING ModuleName
;
1266 OBJECT_ATTRIBUTES ObjectAttributes
;
1267 PMODULE_OBJECT ModuleObject
;
1268 UNICODE_STRING RemainingPath
;
1270 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1271 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
1273 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
1277 wcscat(NameBuffer
, Filename
->Buffer
);
1279 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1280 InitializeObjectAttributes(&ObjectAttributes
,
1282 OBJ_CASE_INSENSITIVE
,
1286 Status
= ObFindObject(&ObjectAttributes
,
1287 (PVOID
*) &ModuleObject
,
1291 if (NT_SUCCESS(Status
) && (RemainingPath
.Buffer
== NULL
|| *(RemainingPath
.Buffer
) == 0))
1293 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
1294 RtlFreeUnicodeString (&RemainingPath
);
1296 return ModuleObject
;
1299 RtlFreeUnicodeString (&RemainingPath
);
1305 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
1307 unsigned short Hint
)
1309 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
1311 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
1320 LdrpQueryModuleInformation(PVOID Buffer
,
1324 PLIST_ENTRY current_entry
;
1325 PMODULE_OBJECT current
;
1326 ULONG ModuleCount
= 0;
1327 PSYSTEM_MODULE_INFORMATION Smi
;
1328 ANSI_STRING AnsiName
;
1331 // KeAcquireSpinLock(&ModuleListLock,&oldlvl);
1333 /* calculate required size */
1334 current_entry
= ModuleListHead
.Flink
;
1335 while (current_entry
!= (&ModuleListHead
))
1338 current_entry
= current_entry
->Flink
;
1341 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
1342 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_ENTRY
);
1344 if (Size
< *ReqSize
)
1346 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1347 return STATUS_INFO_LENGTH_MISMATCH
;
1350 /* fill the buffer */
1351 memset(Buffer
, '=', Size
);
1353 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
1354 Smi
->Count
= ModuleCount
;
1357 current_entry
= ModuleListHead
.Flink
;
1358 while (current_entry
!= (&ModuleListHead
))
1360 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
1362 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
1363 Smi
->Module
[ModuleCount
].BaseAddress
= current
->Base
;
1364 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
1365 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
1366 Smi
->Module
[ModuleCount
].EntryIndex
= ModuleCount
;
1368 AnsiName
.Length
= 0;
1369 AnsiName
.MaximumLength
= 256;
1370 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].Name
;
1371 RtlUnicodeStringToAnsiString(&AnsiName
,
1375 p
= strrchr (AnsiName
.Buffer
, '\\');
1378 Smi
->Module
[ModuleCount
].PathLength
= 0;
1379 Smi
->Module
[ModuleCount
].NameLength
= strlen(AnsiName
.Buffer
);
1384 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
1385 Smi
->Module
[ModuleCount
].NameLength
= strlen(p
);
1389 current_entry
= current_entry
->Flink
;
1392 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1394 return STATUS_SUCCESS
;
1399 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
1400 PUNICODE_STRING FullName
)
1402 UNICODE_STRING Name
;
1406 DPRINT("LdrpBuildModuleBaseName()\n");
1407 DPRINT("FullName %wZ\n", FullName
);
1409 p
= wcsrchr(FullName
->Buffer
, '\\');
1412 p
= FullName
->Buffer
;
1419 DPRINT("p %S\n", p
);
1421 RtlCreateUnicodeString(&Name
, p
);
1429 DPRINT("p %S\n", p
);
1431 RtlCreateUnicodeString(BaseName
, p
);
1432 RtlFreeUnicodeString(&Name
);
1436 /* ---------------------------------------------- PE Module support */
1439 LdrPEProcessModule(PVOID ModuleLoadBase
,
1440 PUNICODE_STRING FileName
,
1441 PMODULE_OBJECT
*ModuleObject
)
1443 unsigned int DriverSize
, Idx
, Idx2
;
1444 ULONG RelocDelta
, NumRelocs
;
1445 DWORD CurrentSize
, TotalRelocs
;
1448 PIMAGE_DOS_HEADER PEDosHeader
;
1449 PIMAGE_FILE_HEADER PEFileHeader
;
1450 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1451 PIMAGE_SECTION_HEADER PESectionHeaders
;
1452 PRELOCATION_DIRECTORY RelocDir
;
1453 PRELOCATION_ENTRY RelocEntry
;
1454 PMODULE_OBJECT LibraryModuleObject
;
1455 HANDLE ModuleHandle
;
1456 PMODULE_OBJECT CreatedModuleObject
;
1457 PVOID
*ImportAddressList
;
1458 PULONG FunctionNameList
;
1461 OBJECT_ATTRIBUTES ObjectAttributes
;
1462 UNICODE_STRING ModuleName
;
1463 WCHAR NameBuffer
[60];
1464 MODULE_TEXT_SECTION
* ModuleTextSection
;
1467 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1469 /* Get header pointers */
1470 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1471 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1472 PEDosHeader
->e_lfanew
);
1473 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1474 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1475 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1476 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1477 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1478 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1479 sizeof(IMAGE_OPTIONAL_HEADER
));
1482 /* Check file magic numbers */
1483 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1485 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
1486 return STATUS_UNSUCCESSFUL
;
1488 if (PEDosHeader
->e_lfanew
== 0)
1490 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
1491 return STATUS_UNSUCCESSFUL
;
1493 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1495 CPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
1496 return STATUS_UNSUCCESSFUL
;
1498 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1500 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
1501 return STATUS_UNSUCCESSFUL
;
1505 /* FIXME: if image is fixed-address load, then fail */
1507 /* FIXME: check/verify OS version number */
1509 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1510 PEOptionalHeader
->Magic
,
1511 PEOptionalHeader
->MajorLinkerVersion
,
1512 PEOptionalHeader
->MinorLinkerVersion
);
1513 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1516 /* Determine the size of the module */
1517 DriverSize
= PEOptionalHeader
->SizeOfImage
;
1518 DPRINT("DriverSize %x\n",DriverSize
);
1520 /* Allocate a virtual section for the module */
1521 DriverBase
= MmAllocateSection(DriverSize
);
1522 if (DriverBase
== 0)
1524 CPRINT("Failed to allocate a virtual section for driver\n");
1525 return STATUS_UNSUCCESSFUL
;
1527 CPRINT("DriverBase: %x\n", DriverBase
);
1529 /* Copy headers over */
1530 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1532 /* Copy image sections into virtual section */
1533 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1535 // Copy current section into current offset of virtual section
1536 if (PESectionHeaders
[Idx
].Characteristics
&
1537 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1539 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1540 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1541 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1542 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1543 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1547 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1548 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1549 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1550 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1553 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1554 PEOptionalHeader
->SectionAlignment
);
1557 // CurrentBase = (PVOID)((DWORD)CurrentBase +
1558 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
1559 // PEOptionalHeader->SectionAlignment));
1562 /* Perform relocation fixups */
1563 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
1564 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1565 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1566 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1568 PEOptionalHeader
->ImageBase
,
1570 DPRINT("RelocDir %x\n",RelocDir
);
1572 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1574 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
1576 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1577 PESectionHeaders
[Idx
].Name
,
1578 PESectionHeaders
[Idx
].PointerToRawData
);
1579 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
1581 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1586 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
1587 CurrentSize
= PEOptionalHeader
->DataDirectory
1588 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
1590 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1592 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1594 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1596 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1598 RelocDir->VirtualAddress,
1600 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
1601 sizeof(RELOCATION_DIRECTORY
));
1602 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1608 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1609 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1610 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
1612 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1615 Type ? "HIGHLOW" : "ABS",
1617 (*RelocItem) + RelocDelta); */
1620 (*RelocItem
) += RelocDelta
;
1624 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1625 return STATUS_UNSUCCESSFUL
;
1628 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1629 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
1630 RelocDir
->SizeOfBlock
);
1631 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1634 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1635 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1637 /* Perform import fixups */
1638 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1640 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1642 /* Process each import module */
1643 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1644 ((DWORD
)DriverBase
+ PEOptionalHeader
->
1645 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1646 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1647 while (ImportModuleDirectory
->dwRVAModuleName
)
1649 /* Check to make sure that import lib is kernel */
1650 pName
= (PCHAR
) DriverBase
+
1651 ImportModuleDirectory
->dwRVAModuleName
;
1652 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1654 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++);
1655 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
1657 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
1659 NameBuffer
[Idx
+ Idx2
] = 0;
1661 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1662 DPRINT("Import module: %wZ\n", &ModuleName
);
1664 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
1665 if (LibraryModuleObject
== 0)
1667 CPRINT("Unknown import module: %wZ\n", &ModuleName
);
1669 /* Get the import address list */
1670 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
1671 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1673 /* Get the list of functions to import */
1674 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1676 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1677 ImportModuleDirectory
->dwRVAFunctionNameList
);
1681 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1682 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1684 /* Walk through function list and fixup addresses */
1685 while (*FunctionNameList
!= 0L)
1687 if ((*FunctionNameList
) & 0x80000000) // hint
1692 Hint
= (*FunctionNameList
) & 0xffff;
1696 pName
= (PCHAR
)((DWORD
)DriverBase
+
1697 *FunctionNameList
+ 2);
1698 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
1700 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
1702 /* Fixup the current import symbol */
1703 if (LibraryModuleObject
!= NULL
)
1705 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
1711 CPRINT("Unresolved kernel symbol: %s\n", pName
);
1712 return STATUS_UNSUCCESSFUL
;
1714 ImportAddressList
++;
1717 ImportModuleDirectory
++;
1721 /* Create ModuleName string */
1722 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1723 if (wcsrchr(FileName
->Buffer
, '\\') != 0)
1725 wcscat(NameBuffer
, wcsrchr(FileName
->Buffer
, '\\') + 1);
1729 wcscat(NameBuffer
, FileName
->Buffer
);
1731 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1732 CPRINT("Module name is: %wZ\n", &ModuleName
);
1734 /* Initialize ObjectAttributes for ModuleObject */
1735 InitializeObjectAttributes(&ObjectAttributes
,
1741 /* Create module object */
1743 Status
= ObCreateObject(&ModuleHandle
,
1744 STANDARD_RIGHTS_REQUIRED
,
1747 (PVOID
*)&CreatedModuleObject
);
1748 if (!NT_SUCCESS(Status
))
1753 /* Initialize ModuleObject data */
1754 CreatedModuleObject
->Base
= DriverBase
;
1755 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
1756 InsertTailList(&ModuleListHead
,
1757 &CreatedModuleObject
->ListEntry
);
1758 RtlCreateUnicodeString(&CreatedModuleObject
->FullName
,
1760 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
1761 &CreatedModuleObject
->FullName
);
1763 CreatedModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
1764 PEOptionalHeader
->AddressOfEntryPoint
);
1765 CreatedModuleObject
->Length
= DriverSize
;
1766 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
1768 CreatedModuleObject
->Image
.PE
.FileHeader
=
1769 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1771 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
1772 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
1773 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1774 sizeof(IMAGE_FILE_HEADER
));
1775 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
1776 CreatedModuleObject
->Image
.PE
.SectionList
=
1777 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1778 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
1779 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
1781 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
1782 sizeof(MODULE_TEXT_SECTION
));
1783 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
1784 ModuleTextSection
->Length
= DriverSize
;
1785 ModuleTextSection
->SymbolsBase
= NULL
;
1786 ModuleTextSection
->SymbolsLength
= 0;
1787 ModuleTextSection
->Name
=
1788 ExAllocatePool(NonPagedPool
,
1789 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
1790 wcscpy(ModuleTextSection
->Name
, NameBuffer
);
1791 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
1793 CreatedModuleObject
->TextSection
= ModuleTextSection
;
1795 *ModuleObject
= CreatedModuleObject
;
1797 return STATUS_SUCCESS
;
1800 PVOID
LdrSafePEProcessModule(
1801 PVOID ModuleLoadBase
,
1803 PVOID ImportModuleBase
,
1806 unsigned int Idx
, Idx2
;
1807 ULONG RelocDelta
, NumRelocs
;
1808 DWORD CurrentSize
, TotalRelocs
;
1810 PIMAGE_DOS_HEADER PEDosHeader
;
1811 PIMAGE_FILE_HEADER PEFileHeader
;
1812 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1813 PIMAGE_SECTION_HEADER PESectionHeaders
;
1814 PRELOCATION_DIRECTORY RelocDir
;
1815 PRELOCATION_ENTRY RelocEntry
;
1816 PVOID
*ImportAddressList
;
1817 PULONG FunctionNameList
;
1820 UNICODE_STRING ModuleName
;
1821 WCHAR NameBuffer
[60];
1823 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1825 /* Get header pointers */
1826 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1827 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1828 PEDosHeader
->e_lfanew
);
1829 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1830 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1831 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1832 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1833 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1834 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1835 sizeof(IMAGE_OPTIONAL_HEADER
));
1838 /* Check file magic numbers */
1839 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1843 if (PEDosHeader
->e_lfanew
== 0)
1847 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1851 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1856 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1857 PEOptionalHeader
->Magic
,
1858 PEOptionalHeader
->MajorLinkerVersion
,
1859 PEOptionalHeader
->MinorLinkerVersion
);
1860 ps("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1862 /* Determine the size of the module */
1863 *DriverSize
= PEOptionalHeader
->SizeOfImage
;
1864 ps("DriverSize %x\n",*DriverSize
);
1866 /* Copy headers over */
1867 if (DriverBase
!= ModuleLoadBase
)
1869 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1872 ps("Hdr: 0x%X\n", (ULONG
)PEOptionalHeader
);
1873 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG
)PEOptionalHeader
->SizeOfHeaders
);
1874 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG
)PEFileHeader
->NumberOfSections
);
1876 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1877 address as it is mapped */
1878 if (DriverBase
!= ModuleLoadBase
)
1882 /* Copy image sections into virtual section */
1883 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1885 // Copy current section into current offset of virtual section
1886 if (PESectionHeaders
[Idx
].Characteristics
&
1887 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1889 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1890 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1891 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1892 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1893 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
?
1894 PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1898 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1899 PESectionHeaders
[Idx
].VirtualAddress
, PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1900 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1901 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1904 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1905 PEOptionalHeader
->SectionAlignment
);
1908 /* Perform relocation fixups */
1909 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
1910 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1911 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1912 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1914 PEOptionalHeader
->ImageBase
,
1916 ps("RelocDir %x\n",RelocDir
);
1918 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1920 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
1922 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1923 PESectionHeaders
[Idx
].Name
,
1924 PESectionHeaders
[Idx
].PointerToRawData
);
1925 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+ ModuleLoadBase
;
1926 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1931 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1934 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1936 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1938 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
1939 sizeof(RELOCATION_DIRECTORY
));
1940 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1946 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1947 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1948 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
1952 (*RelocItem
) += RelocDelta
;
1956 DbgPrint("Unknown relocation type %x at %x\n",Type
, &Type
);
1960 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1961 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
1962 RelocDir
->SizeOfBlock
);
1965 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1966 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1970 /* Perform import fixups */
1971 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1973 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1975 /* Process each import module */
1976 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1977 ((DWORD
)DriverBase
+ PEOptionalHeader
->
1978 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1980 ps("Processeing import directory at %p\n", ImportModuleDirectory
);
1983 /* Check to make sure that import lib is kernel */
1984 pName
= (PCHAR
) DriverBase
+
1985 ImportModuleDirectory
->dwRVAModuleName
;
1986 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1987 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++);
1988 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
1990 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
1992 NameBuffer
[Idx
+ Idx2
] = 0;
1993 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1996 ps("Import module: %wZ\n", &ModuleName
);
1998 /* Get the import address list */
1999 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
2000 ImportModuleDirectory
->dwRVAFunctionAddressList
);
2002 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
2003 ImportModuleDirectory
->dwRVAFunctionAddressList
);
2004 ps(" ImportAddressList: 0x%X\n", ImportAddressList
);
2006 /* Get the list of functions to import */
2007 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
2010 ps("Using function name list.\n");
2012 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
2013 ImportModuleDirectory
->dwRVAFunctionNameList
);
2018 ps("Using function address list.\n");
2020 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
2021 ImportModuleDirectory
->dwRVAFunctionAddressList
);
2024 /* Walk through function list and fixup addresses */
2025 while (*FunctionNameList
!= 0L)
2027 if ((*FunctionNameList
) & 0x80000000) // hint
2031 Hint
= (*FunctionNameList
) & 0xffff;
2035 pName
= (PCHAR
)((DWORD
)DriverBase
+
2036 *FunctionNameList
+ 2);
2037 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
2039 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
2041 *ImportAddressList
= LdrSafePEGetExportAddress(
2046 ImportAddressList
++;
2049 ImportModuleDirectory
++;
2053 ps("Finished importing.\n");
2059 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
2061 unsigned short Hint
)
2064 PVOID ExportAddress
;
2066 PDWORD FunctionList
, NameList
;
2067 PIMAGE_EXPORT_DIRECTORY ExportDir
;
2068 ULONG ExportDirSize
;
2070 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
2071 RtlImageDirectoryEntryToData(ModuleObject
->Base
,
2073 IMAGE_DIRECTORY_ENTRY_EXPORT
,
2075 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir
, ExportDirSize
);
2076 if (ExportDir
== NULL
)
2081 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ModuleObject
->Base
);
2082 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ModuleObject
->Base
);
2083 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
2089 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
2092 DPRINT(" Name:%s NameList[%d]:%s\n",
2095 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
2098 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
2100 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
2101 FunctionList
[OrdinalList
[Idx
]]);
2102 if (((ULONG
)ExportAddress
>= (ULONG
)ExportDir
) &&
2103 ((ULONG
)ExportAddress
< (ULONG
)ExportDir
+ ExportDirSize
))
2105 DPRINT("Forward: %s\n", (PCHAR
)ExportAddress
);
2106 ExportAddress
= LdrPEFixupForward((PCHAR
)ExportAddress
);
2107 DPRINT("ExportAddress: %p\n", ExportAddress
);
2116 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
2117 FunctionList
[Hint
- ExportDir
->Base
]);
2120 if (ExportAddress
== 0)
2122 CPRINT("Export not found for %d:%s\n",
2124 Name
!= NULL
? Name
: "(Ordinal)");
2128 return ExportAddress
;
2132 LdrSafePEGetExportAddress(
2133 PVOID ImportModuleBase
,
2135 unsigned short Hint
)
2138 PVOID ExportAddress
;
2140 PDWORD FunctionList
, NameList
;
2141 PIMAGE_EXPORT_DIRECTORY ExportDir
;
2142 ULONG ExportDirSize
;
2144 static BOOLEAN EP
= FALSE
;
2146 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
2147 RtlImageDirectoryEntryToData(ImportModuleBase
,
2149 IMAGE_DIRECTORY_ENTRY_EXPORT
,
2154 ps("ExportDir %x\n", ExportDir
);
2157 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ImportModuleBase
);
2158 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ImportModuleBase
);
2159 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ImportModuleBase
);
2165 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
2167 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ImportModuleBase
+ NameList
[Idx
])))
2169 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
2170 FunctionList
[OrdinalList
[Idx
]]);
2177 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
2178 FunctionList
[Hint
- ExportDir
->Base
]);
2181 if (ExportAddress
== 0)
2183 ps("Export not found for %d:%s\n",
2185 Name
!= NULL
? Name
: "(Ordinal)");
2188 return ExportAddress
;
2192 static PMODULE_OBJECT
2193 LdrPEGetModuleObject(PUNICODE_STRING ModuleName
)
2196 PMODULE_OBJECT Module
;
2198 DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
2201 Entry
= ModuleListHead
.Flink
;
2203 while (Entry
!= &ModuleListHead
)
2205 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
2207 DPRINT("Comparing %wZ and %wZ\n",
2211 if (!RtlCompareUnicodeString(&Module
->BaseName
, ModuleName
, TRUE
))
2213 DPRINT("Module %x\n", Module
);
2217 Entry
= Entry
->Flink
;
2220 CPRINT("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName
);
2227 LdrPEFixupForward(PCHAR ForwardName
)
2229 CHAR NameBuffer
[128];
2230 UNICODE_STRING ModuleName
;
2232 PMODULE_OBJECT ModuleObject
;
2234 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
2236 strcpy(NameBuffer
, ForwardName
);
2237 p
= strchr(NameBuffer
, '.');
2245 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
2247 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
2249 ModuleObject
= LdrPEGetModuleObject(&ModuleName
);
2250 RtlFreeUnicodeString(&ModuleName
);
2252 DPRINT("ModuleObject: %p\n", ModuleObject
);
2254 if (ModuleObject
== NULL
)
2256 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
2260 return LdrPEGetExportAddress(ModuleObject
, p
+1, 0);