1 /* $Id: loader.c,v 1.92 2001/12/02 23:37:25 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ldr/loader.c
6 * PURPOSE: Loaders for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
9 * Jason Filby (jasonfilby@yahoo.com)
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>
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
);
820 NTSTATUS
LdrFindModuleObject(
821 PUNICODE_STRING ModuleName
,
822 PMODULE_OBJECT
*ModuleObject
)
825 WCHAR NameBuffer
[MAX_PATH
];
827 OBJECT_ATTRIBUTES ObjectAttributes
;
828 UNICODE_STRING RemainingPath
;
830 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
831 wcscat(NameBuffer
, ModuleName
->Buffer
);
832 RtlInitUnicodeString(&Name
, NameBuffer
);
834 InitializeObjectAttributes(&ObjectAttributes
,
839 Status
= ObFindObject(&ObjectAttributes
,
840 (PVOID
*)ModuleObject
,
843 if (!NT_SUCCESS(Status
))
848 if ((RemainingPath
.Buffer
!= NULL
) || (*ModuleObject
== NULL
))
850 RtlFreeUnicodeString(&RemainingPath
);
851 return STATUS_UNSUCCESSFUL
;
854 return STATUS_SUCCESS
;
857 VOID
LdrLoadAutoConfigDrivers (VOID
)
863 UNICODE_STRING ModuleName
;
864 PMODULE_OBJECT ModuleObject
;
866 /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
867 is created after their module entries */
869 RtlInitUnicodeString(&ModuleName
, KERNEL_MODULE_NAME
);
870 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
871 if (NT_SUCCESS(Status
))
873 LdrpLoadModuleSymbols(ModuleObject
);
876 RtlInitUnicodeString(&ModuleName
, HAL_MODULE_NAME
);
877 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
878 if (NT_SUCCESS(Status
))
880 LdrpLoadModuleSymbols(ModuleObject
);
888 //LdrLoadAutoConfigDriver( L"pci.sys" );
893 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
898 LdrLoadAutoConfigDriver( L
"blue.sys" );
903 LdrLoadAutoConfigDriver(L
"vidport.sys");
908 LdrLoadAutoConfigDriver(L
"vgamp.sys");
911 * Minix filesystem driver
913 LdrLoadAutoConfigDriver(L
"minixfs.sys");
916 * Mailslot filesystem driver
918 LdrLoadAutoConfigDriver(L
"msfs.sys");
921 * Named pipe filesystem driver
923 LdrLoadAutoConfigDriver(L
"npfs.sys");
928 // LdrLoadAutoConfigDriver(L"l8042prt.sys");
929 LdrLoadAutoConfigDriver(L
"psaux.sys");
930 LdrLoadAutoConfigDriver(L
"mouclass.sys");
939 LdrLoadAutoConfigDriver(L
"ndis.sys");
942 * Novell Eagle 2000 driver
944 //LdrLoadAutoConfigDriver(L"ne2000.sys");
947 * TCP/IP protocol driver
949 LdrLoadAutoConfigDriver(L
"tcpip.sys");
954 //LdrLoadAutoConfigDriver(L"tditest.sys");
957 * Ancillary Function Driver
959 LdrLoadAutoConfigDriver(L
"afd.sys");
964 static NTSTATUS STDCALL
965 LdrCreateModule(PVOID ObjectBody
,
968 POBJECT_ATTRIBUTES ObjectAttributes
)
970 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
974 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
976 return STATUS_UNSUCCESSFUL
;
978 if (Parent
!= NULL
&& RemainingPath
!= NULL
)
980 ObAddEntryDirectory(Parent
, ObjectBody
, RemainingPath
+ 1);
983 return STATUS_SUCCESS
;
987 * FUNCTION: Loads a kernel driver
989 * FileName = Driver to load
993 NTSTATUS
LdrLoadDriver(PUNICODE_STRING Filename
,
994 PDEVICE_NODE DeviceNode
,
995 BOOLEAN BootDriversOnly
)
997 PMODULE_OBJECT ModuleObject
;
998 WCHAR Buffer
[MAX_PATH
];
1004 ModuleObject
= LdrLoadModule(Filename
);
1007 return STATUS_UNSUCCESSFUL
;
1010 /* Set a service name for the device node */
1012 /* Get the service name from the module name */
1013 Start
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'\\');
1015 Start
= ModuleObject
->BaseName
.Buffer
;
1019 Ext
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'.');
1021 Length
= Ext
- Start
;
1023 Length
= wcslen(Start
);
1025 wcsncpy(Buffer
, Start
, Length
);
1026 RtlInitUnicodeString(&DeviceNode
->ServiceName
, Buffer
);
1029 Status
= IopInitializeDriver(ModuleObject
->EntryPoint
, DeviceNode
);
1030 if (!NT_SUCCESS(Status
))
1032 ObDereferenceObject(ModuleObject
);
1038 NTSTATUS
LdrLoadGdiDriver (PUNICODE_STRING DriverName
,
1039 PVOID
*ImageAddress
,
1040 PVOID
*SectionPointer
,
1042 PVOID
*ExportSectionPointer
)
1044 PMODULE_OBJECT ModuleObject
;
1046 ModuleObject
= LdrLoadModule(DriverName
);
1047 if (ModuleObject
== 0)
1049 return STATUS_UNSUCCESSFUL
;
1053 *ImageAddress
= ModuleObject
->Base
;
1055 // if (SectionPointer)
1056 // *SectionPointer = ModuleObject->
1059 *EntryPoint
= ModuleObject
->EntryPoint
;
1061 // if (ExportSectionPointer)
1062 // *ExportSectionPointer = ModuleObject->
1064 return STATUS_SUCCESS
;
1069 LdrLoadModule(PUNICODE_STRING Filename
)
1071 PVOID ModuleLoadBase
;
1074 OBJECT_ATTRIBUTES ObjectAttributes
;
1075 PMODULE_OBJECT ModuleObject
;
1076 FILE_STANDARD_INFORMATION FileStdInfo
;
1077 IO_STATUS_BLOCK IoStatusBlock
;
1079 /* Check for module already loaded */
1080 if ((ModuleObject
= LdrOpenModule(Filename
)) != NULL
)
1082 return ModuleObject
;
1085 DPRINT("Loading Module %wZ...\n", Filename
);
1087 /* Open the Module */
1088 InitializeObjectAttributes(&ObjectAttributes
,
1094 Status
= NtOpenFile(&FileHandle
,
1101 if (!NT_SUCCESS(Status
))
1103 CPRINT("Could not open module file: %wZ\n", Filename
);
1108 /* Get the size of the file */
1109 Status
= NtQueryInformationFile(FileHandle
,
1112 sizeof(FileStdInfo
),
1113 FileStandardInformation
);
1114 if (!NT_SUCCESS(Status
))
1116 CPRINT("Could not get file size\n");
1121 /* Allocate nonpageable memory for driver */
1122 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
1123 FileStdInfo
.EndOfFile
.u
.LowPart
,
1126 if (ModuleLoadBase
== NULL
)
1128 CPRINT("Could not allocate memory for module");
1133 /* Load driver into memory chunk */
1134 Status
= NtReadFile(FileHandle
,
1138 FileStdInfo
.EndOfFile
.u
.LowPart
,
1140 if (!NT_SUCCESS(Status
))
1142 CPRINT("Could not read module file into memory");
1143 ExFreePool(ModuleLoadBase
);
1148 NtClose(FileHandle
);
1150 Status
= LdrProcessModule(ModuleLoadBase
,
1153 if (!NT_SUCCESS(Status
))
1155 CPRINT("Could not process module");
1156 ExFreePool(ModuleLoadBase
);
1161 ExFreePool(ModuleLoadBase
);
1165 /* Load symbols for module if available */
1166 LdrpLoadModuleSymbols(ModuleObject
);
1170 return ModuleObject
;
1174 LdrProcessDriver(PVOID ModuleLoadBase
, PCHAR FileName
, ULONG ModuleLength
)
1176 PMODULE_OBJECT ModuleObject
;
1177 UNICODE_STRING ModuleName
;
1178 PDEVICE_NODE DeviceNode
;
1183 CHAR TmpBaseName
[MAX_PATH
];
1184 CHAR TmpFileName
[MAX_PATH
];
1185 ANSI_STRING AnsiString
;
1189 /* Split the filename into base name and extension */
1190 Ext
= strrchr(FileName
, '.');
1192 Length
= Ext
- FileName
;
1194 Length
= strlen(FileName
);
1196 if ((Ext
!= NULL
) && (strcmp(Ext
, ".sym") == 0))
1198 DPRINT("Module %s is a symbol file\n", FileName
);
1200 strncpy(TmpBaseName
, FileName
, Length
);
1201 TmpBaseName
[Length
] = '\0';
1203 DPRINT("base: %s (Length %d)\n", TmpBaseName
, Length
);
1205 strcpy(TmpFileName
, TmpBaseName
);
1206 strcat(TmpFileName
, ".sys");
1207 RtlInitAnsiString(&AnsiString
, TmpFileName
);
1209 DPRINT("dasdsad: %s\n", TmpFileName
);
1211 RtlAnsiStringToUnicodeString(&ModuleName
, &AnsiString
, TRUE
);
1212 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
1213 RtlFreeUnicodeString(&ModuleName
);
1214 if (!NT_SUCCESS(Status
))
1216 strcpy(TmpFileName
, TmpBaseName
);
1217 strcat(TmpFileName
, ".exe");
1218 RtlInitAnsiString(&AnsiString
, TmpFileName
);
1219 RtlAnsiStringToUnicodeString(&ModuleName
, &AnsiString
, TRUE
);
1220 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
1221 RtlFreeUnicodeString(&ModuleName
);
1223 if (NT_SUCCESS(Status
))
1225 LdrpLoadModuleSymbolsFromBuffer(
1230 return(STATUS_SUCCESS
);
1234 DPRINT("Module %s is executable\n", FileName
);
1238 /* Use IopRootDeviceNode for now */
1239 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1240 if (!NT_SUCCESS(Status
))
1242 CPRINT("Driver load failed, status (%x)\n", Status
);
1246 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1248 Status
= LdrProcessModule(ModuleLoadBase
,
1251 RtlFreeUnicodeString(&ModuleName
);
1252 if (ModuleObject
== NULL
)
1254 IopFreeDeviceNode(DeviceNode
);
1255 CPRINT("Driver load failed, status (%x)\n", Status
);
1256 return(STATUS_UNSUCCESSFUL
);
1259 Status
= IopInitializeDriver(ModuleObject
->EntryPoint
, DeviceNode
);
1260 if (!NT_SUCCESS(Status
))
1262 IopFreeDeviceNode(DeviceNode
);
1263 CPRINT("Driver load failed, status (%x)\n", Status
);
1270 LdrProcessModule(PVOID ModuleLoadBase
,
1271 PUNICODE_STRING ModuleName
,
1272 PMODULE_OBJECT
*ModuleObject
)
1274 PIMAGE_DOS_HEADER PEDosHeader
;
1276 /* If MZ header exists */
1277 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1278 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
1280 return LdrPEProcessModule(ModuleLoadBase
,
1285 CPRINT("Module wasn't PE\n");
1286 return STATUS_UNSUCCESSFUL
;
1289 static PMODULE_OBJECT
1290 LdrOpenModule(PUNICODE_STRING Filename
)
1293 WCHAR NameBuffer
[60];
1294 UNICODE_STRING ModuleName
;
1295 OBJECT_ATTRIBUTES ObjectAttributes
;
1296 PMODULE_OBJECT ModuleObject
;
1297 UNICODE_STRING RemainingPath
;
1299 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1300 if (wcsrchr(Filename
->Buffer
, '\\') != 0)
1302 wcscat(NameBuffer
, wcsrchr(Filename
->Buffer
, '\\') + 1);
1306 wcscat(NameBuffer
, Filename
->Buffer
);
1308 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1309 InitializeObjectAttributes(&ObjectAttributes
,
1311 OBJ_CASE_INSENSITIVE
,
1315 Status
= ObFindObject(&ObjectAttributes
,
1316 (PVOID
*) &ModuleObject
,
1320 if (NT_SUCCESS(Status
) && (RemainingPath
.Buffer
== NULL
|| *(RemainingPath
.Buffer
) == 0))
1322 DPRINT("Module %wZ at %p\n", Filename
, ModuleObject
);
1323 RtlFreeUnicodeString (&RemainingPath
);
1325 return ModuleObject
;
1328 RtlFreeUnicodeString (&RemainingPath
);
1334 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
1336 unsigned short Hint
)
1338 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
1340 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
1349 LdrpQueryModuleInformation(PVOID Buffer
,
1353 PLIST_ENTRY current_entry
;
1354 PMODULE_OBJECT current
;
1355 ULONG ModuleCount
= 0;
1356 PSYSTEM_MODULE_INFORMATION Smi
;
1357 ANSI_STRING AnsiName
;
1360 // KeAcquireSpinLock(&ModuleListLock,&oldlvl);
1362 /* calculate required size */
1363 current_entry
= ModuleListHead
.Flink
;
1364 while (current_entry
!= (&ModuleListHead
))
1367 current_entry
= current_entry
->Flink
;
1370 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
1371 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_ENTRY
);
1373 if (Size
< *ReqSize
)
1375 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1376 return STATUS_INFO_LENGTH_MISMATCH
;
1379 /* fill the buffer */
1380 memset(Buffer
, '=', Size
);
1382 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
1383 Smi
->Count
= ModuleCount
;
1386 current_entry
= ModuleListHead
.Flink
;
1387 while (current_entry
!= (&ModuleListHead
))
1389 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
1391 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
1392 Smi
->Module
[ModuleCount
].BaseAddress
= current
->Base
;
1393 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
1394 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
1395 Smi
->Module
[ModuleCount
].EntryIndex
= ModuleCount
;
1397 AnsiName
.Length
= 0;
1398 AnsiName
.MaximumLength
= 256;
1399 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].Name
;
1400 RtlUnicodeStringToAnsiString(&AnsiName
,
1404 p
= strrchr (AnsiName
.Buffer
, '\\');
1407 Smi
->Module
[ModuleCount
].PathLength
= 0;
1408 Smi
->Module
[ModuleCount
].NameLength
= strlen(AnsiName
.Buffer
);
1413 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
1414 Smi
->Module
[ModuleCount
].NameLength
= strlen(p
);
1418 current_entry
= current_entry
->Flink
;
1421 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1423 return STATUS_SUCCESS
;
1428 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
1429 PUNICODE_STRING FullName
)
1431 UNICODE_STRING Name
;
1435 DPRINT("LdrpBuildModuleBaseName()\n");
1436 DPRINT("FullName %wZ\n", FullName
);
1438 p
= wcsrchr(FullName
->Buffer
, '\\');
1441 p
= FullName
->Buffer
;
1448 DPRINT("p %S\n", p
);
1450 RtlCreateUnicodeString(&Name
, p
);
1458 DPRINT("p %S\n", p
);
1460 RtlCreateUnicodeString(BaseName
, p
);
1461 RtlFreeUnicodeString(&Name
);
1465 /* ---------------------------------------------- PE Module support */
1468 LdrPEProcessModule(PVOID ModuleLoadBase
,
1469 PUNICODE_STRING FileName
,
1470 PMODULE_OBJECT
*ModuleObject
)
1472 unsigned int DriverSize
, Idx
, Idx2
;
1473 ULONG RelocDelta
, NumRelocs
;
1474 DWORD CurrentSize
, TotalRelocs
;
1477 PIMAGE_DOS_HEADER PEDosHeader
;
1478 PIMAGE_FILE_HEADER PEFileHeader
;
1479 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1480 PIMAGE_SECTION_HEADER PESectionHeaders
;
1481 PRELOCATION_DIRECTORY RelocDir
;
1482 PRELOCATION_ENTRY RelocEntry
;
1483 PMODULE_OBJECT LibraryModuleObject
;
1484 HANDLE ModuleHandle
;
1485 PMODULE_OBJECT CreatedModuleObject
;
1486 PVOID
*ImportAddressList
;
1487 PULONG FunctionNameList
;
1490 OBJECT_ATTRIBUTES ObjectAttributes
;
1491 UNICODE_STRING ModuleName
;
1492 WCHAR NameBuffer
[60];
1493 MODULE_TEXT_SECTION
* ModuleTextSection
;
1496 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1498 /* Get header pointers */
1499 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1500 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1501 PEDosHeader
->e_lfanew
);
1502 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1503 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1504 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1505 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1506 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1507 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1508 sizeof(IMAGE_OPTIONAL_HEADER
));
1511 /* Check file magic numbers */
1512 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1514 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
1515 return STATUS_UNSUCCESSFUL
;
1517 if (PEDosHeader
->e_lfanew
== 0)
1519 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
1520 return STATUS_UNSUCCESSFUL
;
1522 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1524 CPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
1525 return STATUS_UNSUCCESSFUL
;
1527 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1529 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
1530 return STATUS_UNSUCCESSFUL
;
1534 /* FIXME: if image is fixed-address load, then fail */
1536 /* FIXME: check/verify OS version number */
1538 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1539 PEOptionalHeader
->Magic
,
1540 PEOptionalHeader
->MajorLinkerVersion
,
1541 PEOptionalHeader
->MinorLinkerVersion
);
1542 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1545 /* Determine the size of the module */
1546 DriverSize
= PEOptionalHeader
->SizeOfImage
;
1547 DPRINT("DriverSize %x\n",DriverSize
);
1549 /* Allocate a virtual section for the module */
1550 DriverBase
= MmAllocateSection(DriverSize
);
1551 if (DriverBase
== 0)
1553 CPRINT("Failed to allocate a virtual section for driver\n");
1554 return STATUS_UNSUCCESSFUL
;
1556 CPRINT("DriverBase: %x\n", DriverBase
);
1558 /* Copy headers over */
1559 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1561 /* Copy image sections into virtual section */
1562 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1564 // Copy current section into current offset of virtual section
1565 if (PESectionHeaders
[Idx
].Characteristics
&
1566 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1568 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1569 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1570 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1571 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1572 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1576 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1577 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1578 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1579 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1582 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1583 PEOptionalHeader
->SectionAlignment
);
1586 // CurrentBase = (PVOID)((DWORD)CurrentBase +
1587 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
1588 // PEOptionalHeader->SectionAlignment));
1591 /* Perform relocation fixups */
1592 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
1593 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1594 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1595 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1597 PEOptionalHeader
->ImageBase
,
1599 DPRINT("RelocDir %x\n",RelocDir
);
1601 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1603 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
1605 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1606 PESectionHeaders
[Idx
].Name
,
1607 PESectionHeaders
[Idx
].PointerToRawData
);
1608 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
1610 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1615 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
1616 CurrentSize
= PEOptionalHeader
->DataDirectory
1617 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
1619 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1621 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1623 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1625 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1627 RelocDir->VirtualAddress,
1629 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
1630 sizeof(RELOCATION_DIRECTORY
));
1631 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1637 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1638 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1639 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
1641 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1644 Type ? "HIGHLOW" : "ABS",
1646 (*RelocItem) + RelocDelta); */
1649 (*RelocItem
) += RelocDelta
;
1653 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1654 return STATUS_UNSUCCESSFUL
;
1657 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1658 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
1659 RelocDir
->SizeOfBlock
);
1660 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1663 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1664 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1666 /* Perform import fixups */
1667 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1669 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1671 /* Process each import module */
1672 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1673 ((DWORD
)DriverBase
+ PEOptionalHeader
->
1674 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1675 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1676 while (ImportModuleDirectory
->dwRVAModuleName
)
1678 /* Check to make sure that import lib is kernel */
1679 pName
= (PCHAR
) DriverBase
+
1680 ImportModuleDirectory
->dwRVAModuleName
;
1681 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1683 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++);
1684 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
1686 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
1688 NameBuffer
[Idx
+ Idx2
] = 0;
1690 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1691 DPRINT("Import module: %wZ\n", &ModuleName
);
1693 LibraryModuleObject
= LdrLoadModule(&ModuleName
);
1694 if (LibraryModuleObject
== 0)
1696 CPRINT("Unknown import module: %wZ\n", &ModuleName
);
1698 /* Get the import address list */
1699 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
1700 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1702 /* Get the list of functions to import */
1703 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1705 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1706 ImportModuleDirectory
->dwRVAFunctionNameList
);
1710 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1711 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1713 /* Walk through function list and fixup addresses */
1714 while (*FunctionNameList
!= 0L)
1716 if ((*FunctionNameList
) & 0x80000000) // hint
1721 Hint
= (*FunctionNameList
) & 0xffff;
1725 pName
= (PCHAR
)((DWORD
)DriverBase
+
1726 *FunctionNameList
+ 2);
1727 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
1729 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
1731 /* Fixup the current import symbol */
1732 if (LibraryModuleObject
!= NULL
)
1734 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
1740 CPRINT("Unresolved kernel symbol: %s\n", pName
);
1741 return STATUS_UNSUCCESSFUL
;
1743 ImportAddressList
++;
1746 ImportModuleDirectory
++;
1750 /* Create ModuleName string */
1751 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
1752 if (wcsrchr(FileName
->Buffer
, '\\') != 0)
1754 wcscat(NameBuffer
, wcsrchr(FileName
->Buffer
, '\\') + 1);
1758 wcscat(NameBuffer
, FileName
->Buffer
);
1760 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
1761 CPRINT("Module name is: %wZ\n", &ModuleName
);
1763 /* Initialize ObjectAttributes for ModuleObject */
1764 InitializeObjectAttributes(&ObjectAttributes
,
1770 /* Create module object */
1772 Status
= ObCreateObject(&ModuleHandle
,
1773 STANDARD_RIGHTS_REQUIRED
,
1776 (PVOID
*)&CreatedModuleObject
);
1777 if (!NT_SUCCESS(Status
))
1782 /* Initialize ModuleObject data */
1783 CreatedModuleObject
->Base
= DriverBase
;
1784 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
1785 InsertTailList(&ModuleListHead
,
1786 &CreatedModuleObject
->ListEntry
);
1787 RtlCreateUnicodeString(&CreatedModuleObject
->FullName
,
1789 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
1790 &CreatedModuleObject
->FullName
);
1792 CreatedModuleObject
->EntryPoint
= (PVOID
) ((DWORD
)DriverBase
+
1793 PEOptionalHeader
->AddressOfEntryPoint
);
1794 CreatedModuleObject
->Length
= DriverSize
;
1795 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
1797 CreatedModuleObject
->Image
.PE
.FileHeader
=
1798 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1800 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
1801 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
1802 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1803 sizeof(IMAGE_FILE_HEADER
));
1804 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
1805 CreatedModuleObject
->Image
.PE
.SectionList
=
1806 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1807 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
1808 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
1810 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
1811 sizeof(MODULE_TEXT_SECTION
));
1812 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
1813 ModuleTextSection
->Length
= DriverSize
;
1814 ModuleTextSection
->SymbolsBase
= NULL
;
1815 ModuleTextSection
->SymbolsLength
= 0;
1816 ModuleTextSection
->Name
=
1817 ExAllocatePool(NonPagedPool
,
1818 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
1819 wcscpy(ModuleTextSection
->Name
, NameBuffer
);
1820 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
1822 CreatedModuleObject
->TextSection
= ModuleTextSection
;
1824 *ModuleObject
= CreatedModuleObject
;
1826 return STATUS_SUCCESS
;
1829 PVOID
LdrSafePEProcessModule(
1830 PVOID ModuleLoadBase
,
1832 PVOID ImportModuleBase
,
1835 unsigned int Idx
, Idx2
;
1836 ULONG RelocDelta
, NumRelocs
;
1837 DWORD CurrentSize
, TotalRelocs
;
1839 PIMAGE_DOS_HEADER PEDosHeader
;
1840 PIMAGE_FILE_HEADER PEFileHeader
;
1841 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1842 PIMAGE_SECTION_HEADER PESectionHeaders
;
1843 PRELOCATION_DIRECTORY RelocDir
;
1844 PRELOCATION_ENTRY RelocEntry
;
1845 PVOID
*ImportAddressList
;
1846 PULONG FunctionNameList
;
1849 UNICODE_STRING ModuleName
;
1850 WCHAR NameBuffer
[60];
1852 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1854 /* Get header pointers */
1855 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1856 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1857 PEDosHeader
->e_lfanew
);
1858 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1859 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1860 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1861 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1862 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1863 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1864 sizeof(IMAGE_OPTIONAL_HEADER
));
1867 /* Check file magic numbers */
1868 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1872 if (PEDosHeader
->e_lfanew
== 0)
1876 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1880 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1885 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1886 PEOptionalHeader
->Magic
,
1887 PEOptionalHeader
->MajorLinkerVersion
,
1888 PEOptionalHeader
->MinorLinkerVersion
);
1889 ps("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1891 /* Determine the size of the module */
1892 *DriverSize
= PEOptionalHeader
->SizeOfImage
;
1893 ps("DriverSize %x\n",*DriverSize
);
1895 /* Copy headers over */
1896 if (DriverBase
!= ModuleLoadBase
)
1898 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1901 ps("Hdr: 0x%X\n", (ULONG
)PEOptionalHeader
);
1902 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG
)PEOptionalHeader
->SizeOfHeaders
);
1903 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG
)PEFileHeader
->NumberOfSections
);
1905 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1906 address as it is mapped */
1907 if (DriverBase
!= ModuleLoadBase
)
1911 /* Copy image sections into virtual section */
1912 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1914 // Copy current section into current offset of virtual section
1915 if (PESectionHeaders
[Idx
].Characteristics
&
1916 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1918 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1919 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1920 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1921 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1922 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
?
1923 PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1927 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1928 PESectionHeaders
[Idx
].VirtualAddress
, PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1929 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1930 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1933 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1934 PEOptionalHeader
->SectionAlignment
);
1937 /* Perform relocation fixups */
1938 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
1939 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1940 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1941 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1943 PEOptionalHeader
->ImageBase
,
1945 ps("RelocDir %x\n",RelocDir
);
1947 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1949 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
1951 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1952 PESectionHeaders
[Idx
].Name
,
1953 PESectionHeaders
[Idx
].PointerToRawData
);
1954 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+ ModuleLoadBase
;
1955 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1960 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1963 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1965 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1967 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
1968 sizeof(RELOCATION_DIRECTORY
));
1969 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1975 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1976 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1977 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
1981 (*RelocItem
) += RelocDelta
;
1985 DbgPrint("Unknown relocation type %x at %x\n",Type
, &Type
);
1989 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1990 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
1991 RelocDir
->SizeOfBlock
);
1994 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1995 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1999 /* Perform import fixups */
2000 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
2002 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
2004 /* Process each import module */
2005 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
2006 ((DWORD
)DriverBase
+ PEOptionalHeader
->
2007 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
2009 ps("Processeing import directory at %p\n", ImportModuleDirectory
);
2012 /* Check to make sure that import lib is kernel */
2013 pName
= (PCHAR
) DriverBase
+
2014 ImportModuleDirectory
->dwRVAModuleName
;
2015 wcscpy(NameBuffer
, MODULE_ROOT_NAME
);
2016 for (Idx
= 0; NameBuffer
[Idx
] != 0; Idx
++);
2017 for (Idx2
= 0; pName
[Idx2
] != '\0'; Idx2
++)
2019 NameBuffer
[Idx
+ Idx2
] = (WCHAR
) pName
[Idx2
];
2021 NameBuffer
[Idx
+ Idx2
] = 0;
2022 RtlInitUnicodeString (&ModuleName
, NameBuffer
);
2025 ps("Import module: %wZ\n", &ModuleName
);
2027 /* Get the import address list */
2028 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
2029 ImportModuleDirectory
->dwRVAFunctionAddressList
);
2031 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
2032 ImportModuleDirectory
->dwRVAFunctionAddressList
);
2033 ps(" ImportAddressList: 0x%X\n", ImportAddressList
);
2035 /* Get the list of functions to import */
2036 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
2039 ps("Using function name list.\n");
2041 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
2042 ImportModuleDirectory
->dwRVAFunctionNameList
);
2047 ps("Using function address list.\n");
2049 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
2050 ImportModuleDirectory
->dwRVAFunctionAddressList
);
2053 /* Walk through function list and fixup addresses */
2054 while (*FunctionNameList
!= 0L)
2056 if ((*FunctionNameList
) & 0x80000000) // hint
2060 Hint
= (*FunctionNameList
) & 0xffff;
2064 pName
= (PCHAR
)((DWORD
)DriverBase
+
2065 *FunctionNameList
+ 2);
2066 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
2068 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
2070 *ImportAddressList
= LdrSafePEGetExportAddress(
2075 ImportAddressList
++;
2078 ImportModuleDirectory
++;
2082 ps("Finished importing.\n");
2088 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
2090 unsigned short Hint
)
2093 PVOID ExportAddress
;
2095 PDWORD FunctionList
, NameList
;
2096 PIMAGE_EXPORT_DIRECTORY ExportDir
;
2097 ULONG ExportDirSize
;
2099 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
2100 RtlImageDirectoryEntryToData(ModuleObject
->Base
,
2102 IMAGE_DIRECTORY_ENTRY_EXPORT
,
2104 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir
, ExportDirSize
);
2105 if (ExportDir
== NULL
)
2110 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ModuleObject
->Base
);
2111 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ModuleObject
->Base
);
2112 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
2118 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
2121 DPRINT(" Name:%s NameList[%d]:%s\n",
2124 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
2127 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
2129 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
2130 FunctionList
[OrdinalList
[Idx
]]);
2131 if (((ULONG
)ExportAddress
>= (ULONG
)ExportDir
) &&
2132 ((ULONG
)ExportAddress
< (ULONG
)ExportDir
+ ExportDirSize
))
2134 DPRINT("Forward: %s\n", (PCHAR
)ExportAddress
);
2135 ExportAddress
= LdrPEFixupForward((PCHAR
)ExportAddress
);
2136 DPRINT("ExportAddress: %p\n", ExportAddress
);
2145 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
2146 FunctionList
[Hint
- ExportDir
->Base
]);
2149 if (ExportAddress
== 0)
2151 CPRINT("Export not found for %d:%s\n",
2153 Name
!= NULL
? Name
: "(Ordinal)");
2157 return ExportAddress
;
2161 LdrSafePEGetExportAddress(
2162 PVOID ImportModuleBase
,
2164 unsigned short Hint
)
2167 PVOID ExportAddress
;
2169 PDWORD FunctionList
, NameList
;
2170 PIMAGE_EXPORT_DIRECTORY ExportDir
;
2171 ULONG ExportDirSize
;
2173 static BOOLEAN EP
= FALSE
;
2175 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
2176 RtlImageDirectoryEntryToData(ImportModuleBase
,
2178 IMAGE_DIRECTORY_ENTRY_EXPORT
,
2183 ps("ExportDir %x\n", ExportDir
);
2186 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ImportModuleBase
);
2187 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ImportModuleBase
);
2188 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ImportModuleBase
);
2194 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
2196 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ImportModuleBase
+ NameList
[Idx
])))
2198 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
2199 FunctionList
[OrdinalList
[Idx
]]);
2206 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
2207 FunctionList
[Hint
- ExportDir
->Base
]);
2210 if (ExportAddress
== 0)
2212 ps("Export not found for %d:%s\n",
2214 Name
!= NULL
? Name
: "(Ordinal)");
2217 return ExportAddress
;
2221 static PMODULE_OBJECT
2222 LdrPEGetModuleObject(PUNICODE_STRING ModuleName
)
2225 PMODULE_OBJECT Module
;
2227 DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
2230 Entry
= ModuleListHead
.Flink
;
2232 while (Entry
!= &ModuleListHead
)
2234 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
2236 DPRINT("Comparing %wZ and %wZ\n",
2240 if (!RtlCompareUnicodeString(&Module
->BaseName
, ModuleName
, TRUE
))
2242 DPRINT("Module %x\n", Module
);
2246 Entry
= Entry
->Flink
;
2249 CPRINT("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName
);
2256 LdrPEFixupForward(PCHAR ForwardName
)
2258 CHAR NameBuffer
[128];
2259 UNICODE_STRING ModuleName
;
2261 PMODULE_OBJECT ModuleObject
;
2263 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
2265 strcpy(NameBuffer
, ForwardName
);
2266 p
= strchr(NameBuffer
, '.');
2274 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
2276 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
2278 ModuleObject
= LdrPEGetModuleObject(&ModuleName
);
2279 RtlFreeUnicodeString(&ModuleName
);
2281 DPRINT("ModuleObject: %p\n", ModuleObject
);
2283 if (ModuleObject
== NULL
)
2285 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
2289 return LdrPEGetExportAddress(ModuleObject
, p
+1, 0);