1 /* $Id: loader.c,v 1.109 2002/06/12 14:05:03 chorns 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/kd.h>
32 #include <internal/io.h>
33 #include <internal/mm.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 /* GLOBALS *******************************************************************/
49 LIST_ENTRY ModuleListHead
;
50 KSPIN_LOCK ModuleListLock
;
52 LIST_ENTRY ModuleTextListHead
;
53 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection
;
54 STATIC MODULE_TEXT_SECTION LdrHalTextSection
;
57 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
58 #define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
60 /* FORWARD DECLARATIONS ******************************************************/
63 LdrProcessModule(PVOID ModuleLoadBase
,
64 PUNICODE_STRING ModuleName
,
65 PMODULE_OBJECT
*ModuleObject
);
68 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
73 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
74 PUNICODE_STRING FullName
);
77 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
78 IN PUNICODE_STRING String2
);
81 /* PE Driver load support */
82 static NTSTATUS
LdrPEProcessModule(PVOID ModuleLoadBase
,
83 PUNICODE_STRING FileName
,
84 PMODULE_OBJECT
*ModuleObject
);
86 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
91 LdrSafePEGetExportAddress(PVOID ImportModuleBase
,
96 LdrPEFixupForward(PCHAR ForwardName
);
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
);
175 LdrInitModuleManagement(VOID
)
177 PIMAGE_DOS_HEADER DosHeader
;
178 PMODULE_OBJECT ModuleObject
;
180 /* Initialize the module list and spinlock */
181 InitializeListHead(&ModuleListHead
);
182 KeInitializeSpinLock(&ModuleListLock
);
184 /* Create module object for NTOSKRNL */
185 ModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
186 assert(ModuleObject
!= NULL
);
187 RtlZeroMemory(ModuleObject
, sizeof(MODULE_OBJECT
));
189 /* Initialize ModuleObject data */
190 ModuleObject
->Base
= (PVOID
) KERNEL_BASE
;
191 ModuleObject
->Flags
= MODULE_FLAG_PE
;
192 RtlCreateUnicodeString(&ModuleObject
->FullName
,
194 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
195 &ModuleObject
->FullName
);
197 DosHeader
= (PIMAGE_DOS_HEADER
) KERNEL_BASE
;
198 ModuleObject
->Image
.PE
.FileHeader
=
199 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
200 DosHeader
->e_lfanew
+ sizeof(ULONG
));
201 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
202 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
203 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
204 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
205 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
206 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
207 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
208 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
209 ModuleObject
->TextSection
= &NtoskrnlTextSection
;
211 InsertTailList(&ModuleListHead
,
212 &ModuleObject
->ListEntry
);
214 /* Create module object for HAL */
215 ModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
216 assert(ModuleObject
!= NULL
);
217 RtlZeroMemory(ModuleObject
, sizeof(MODULE_OBJECT
));
219 /* Initialize ModuleObject data */
220 ModuleObject
->Base
= (PVOID
) LdrHalBase
;
221 ModuleObject
->Flags
= MODULE_FLAG_PE
;
223 RtlCreateUnicodeString(&ModuleObject
->FullName
,
225 LdrpBuildModuleBaseName(&ModuleObject
->BaseName
,
226 &ModuleObject
->FullName
);
228 DosHeader
= (PIMAGE_DOS_HEADER
) LdrHalBase
;
229 ModuleObject
->Image
.PE
.FileHeader
=
230 (PIMAGE_FILE_HEADER
) ((DWORD
) ModuleObject
->Base
+
231 DosHeader
->e_lfanew
+ sizeof(ULONG
));
232 ModuleObject
->Image
.PE
.OptionalHeader
= (PIMAGE_OPTIONAL_HEADER
)
233 ((DWORD
)ModuleObject
->Image
.PE
.FileHeader
+ sizeof(IMAGE_FILE_HEADER
));
234 ModuleObject
->Image
.PE
.SectionList
= (PIMAGE_SECTION_HEADER
)
235 ((DWORD
)ModuleObject
->Image
.PE
.OptionalHeader
+ sizeof(IMAGE_OPTIONAL_HEADER
));
236 ModuleObject
->EntryPoint
= (PVOID
) ((DWORD
) ModuleObject
->Base
+
237 ModuleObject
->Image
.PE
.OptionalHeader
->AddressOfEntryPoint
);
238 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject
, ModuleObject
->EntryPoint
);
239 ModuleObject
->Length
= ModuleObject
->Image
.PE
.OptionalHeader
->SizeOfImage
;
240 ModuleObject
->TextSection
= &LdrHalTextSection
;
242 InsertTailList(&ModuleListHead
,
243 &ModuleObject
->ListEntry
);
248 * load the auto config drivers.
251 LdrLoadAutoConfigDriver(LPWSTR RelativeDriverName
)
253 WCHAR TmpFileName
[MAX_PATH
];
255 UNICODE_STRING DriverName
;
258 HalQueryDisplayParameters(&x
, &y
, &cx
, &cy
);
259 RtlFillMemory(Buffer
, x
, ' ');
261 HalSetDisplayParameters(0, y
-1);
262 HalDisplayString(Buffer
);
264 sprintf(Buffer
, "Loading %S...\n",RelativeDriverName
);
265 HalSetDisplayParameters(0, y
-1);
266 HalDisplayString(Buffer
);
267 HalSetDisplayParameters(cx
, cy
);
268 //CPRINT("Loading %S\n",RelativeDriverName);
270 wcscpy(TmpFileName
, L
"\\SystemRoot\\system32\\drivers\\");
271 wcscat(TmpFileName
, RelativeDriverName
);
272 RtlInitUnicodeString (&DriverName
, TmpFileName
);
274 NtLoadDriver(&DriverName
);
279 BOOLEAN
LdrpReadLine(PCHAR Line
,
294 while ((*Size
> 0) && (Count
< LineSize
) && ((ch
= *Block
) != (CHAR
)13))
310 if ((*Size
> 0) && (*Block
== (CHAR
)10))
321 ULONG
HexL(PCHAR Buffer
)
330 while ((j
> 0) && ((ch
= Buffer
[i
]) != ' '))
333 if ((ch
>= '0') && (ch
<= '9'))
334 Value
|= ((ch
- '0') << j
);
335 if ((ch
>= 'A') && (ch
<= 'F'))
336 Value
|= ((10 + (ch
- 'A')) << j
);
338 if ((ch
>= 'a') && (ch
<= 'f'))
339 Value
|= ((10 + (ch
- 'a')) << j
);
345 PSYMBOL
LdrpParseLine(PCHAR Line
,
347 PBOOLEAN TextBaseValid
,
350 Line format: [ADDRESS] <TYPE> <NAME>
353 A = Image information
354 t = Symbol in text segment
355 T = Symbol in text segment
356 d = Symbol in data segment
357 D = Symbol in data segment
358 b = Symbol in BSS segment
359 B = Symbol in BSS segment
360 ? = Unknown segment or symbol in unknown segment
363 ANSI_STRING AnsiString
;
370 if ((Line
[0] == (CHAR
)0) || (Line
[0] == ' '))
373 Address
= HexL(Line
);
375 Line
= strchr(Line
, ' ');
382 Line
= strchr(Line
, ' ');
387 Str
= strchr(Line
, ' ');
389 strcpy((char*)&Buffer
, Line
);
391 strncpy((char*)&Buffer
, Line
, Str
- Line
);
393 if ((Type
== 'A') && (strcmp((char*)&Buffer
, "__section_alignment__")) == 0)
395 *Alignment
= Address
;
399 /* We only want symbols in the .text segment */
400 if ((Type
!= 't') && (Type
!= 'T'))
403 /* Discard other symbols we can't use */
404 if ((Buffer
[0] != '_') || ((Buffer
[0] == '_') && (Buffer
[1] == '_')))
407 Symbol
= ExAllocatePool(NonPagedPool
, sizeof(SYMBOL
));
413 Symbol
->RelativeAddress
= Address
;
415 RtlInitAnsiString(&AnsiString
, (PCSZ
)&Buffer
);
416 RtlAnsiStringToUnicodeString(&Symbol
->Name
, &AnsiString
, TRUE
);
418 if (!(*TextBaseValid
))
420 *TextBase
= Address
- *Alignment
;
421 *TextBaseValid
= TRUE
;
427 VOID
LdrpLoadModuleSymbolsFromBuffer(
428 PMODULE_OBJECT ModuleObject
,
432 Symbols must be sorted by address, e.g.
433 "nm --numeric-sort module.sys > module.sym"
436 PSYMBOL Symbol
, CurrentSymbol
= NULL
;
437 BOOLEAN TextBaseValid
;
444 assert(ModuleObject
);
446 if (ModuleObject
->TextSection
== NULL
)
448 ModuleObject
->TextSection
= &NtoskrnlTextSection
;
451 if (ModuleObject
->TextSection
->Symbols
.SymbolCount
> 0)
453 CPRINT("Symbols are already loaded for %wZ\n", &ModuleObject
->BaseName
);
457 ModuleObject
->TextSection
->Symbols
.SymbolCount
= 0;
458 ModuleObject
->TextSection
->Symbols
.Symbols
= NULL
;
459 TextBaseValid
= FALSE
;
461 while (LdrpReadLine((PCHAR
)&Line
, 256, &Buffer
, &Length
))
463 Symbol
= LdrpParseLine((PCHAR
)&Line
, &Tmp
, &Valid
, &Alignment
);
465 if ((Valid
) && (!TextBaseValid
))
468 TextBaseValid
= TRUE
;
473 Symbol
->RelativeAddress
-= TextBase
;
475 if (ModuleObject
->TextSection
->Symbols
.Symbols
== NULL
)
476 ModuleObject
->TextSection
->Symbols
.Symbols
= Symbol
;
478 CurrentSymbol
->Next
= Symbol
;
480 CurrentSymbol
= Symbol
;
482 ModuleObject
->TextSection
->Symbols
.SymbolCount
++;
487 VOID
LdrpLoadUserModuleSymbolsFromBuffer(
488 PLDR_MODULE ModuleObject
,
492 Symbols must be sorted by address, e.g.
493 "nm --numeric-sort module.dll > module.sym"
496 PSYMBOL Symbol
, CurrentSymbol
= NULL
;
497 BOOLEAN TextBaseValid
;
504 if (ModuleObject
->Symbols
.SymbolCount
> 0)
506 DPRINT("Symbols are already loaded for %wZ\n", &ModuleObject
->BaseDllName
);
510 ModuleObject
->Symbols
.SymbolCount
= 0;
511 ModuleObject
->Symbols
.Symbols
= NULL
;
512 TextBaseValid
= FALSE
;
514 while (LdrpReadLine((PCHAR
)&Line
, 256, &Buffer
, &Length
))
516 Symbol
= LdrpParseLine((PCHAR
)&Line
, &Tmp
, &Valid
, &Alignment
);
518 if ((Valid
) && (!TextBaseValid
))
521 TextBaseValid
= TRUE
;
526 Symbol
->RelativeAddress
-= TextBase
;
528 if (ModuleObject
->Symbols
.Symbols
== NULL
)
529 ModuleObject
->Symbols
.Symbols
= Symbol
;
531 CurrentSymbol
->Next
= Symbol
;
533 CurrentSymbol
= Symbol
;
535 ModuleObject
->Symbols
.SymbolCount
++;
541 LdrpLoadModuleSymbols(PMODULE_OBJECT ModuleObject
)
543 FILE_STANDARD_INFORMATION FileStdInfo
;
544 OBJECT_ATTRIBUTES ObjectAttributes
;
545 WCHAR TmpFileName
[MAX_PATH
];
546 UNICODE_STRING Filename
;
552 IO_STATUS_BLOCK IoStatusBlock
;
554 ModuleObject
->TextSection
->Symbols
.SymbolCount
= 0;
555 ModuleObject
->TextSection
->Symbols
.Symbols
= NULL
;
557 /* Get the path to the symbol store */
558 wcscpy(TmpFileName
, L
"\\SystemRoot\\symbols\\");
560 /* Get the symbol filename from the module name */
561 Start
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'\\');
563 Start
= ModuleObject
->BaseName
.Buffer
;
567 Ext
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'.');
569 Length
= Ext
- Start
;
571 Length
= wcslen(Start
);
573 wcsncat(TmpFileName
, Start
, Length
);
574 wcscat(TmpFileName
, L
".sym");
575 RtlInitUnicodeString(&Filename
, TmpFileName
);
578 InitializeObjectAttributes(&ObjectAttributes
,
584 Status
= ZwOpenFile(&FileHandle
,
590 if (!NT_SUCCESS(Status
))
592 DPRINT("Could not open symbol file: %wZ\n", &Filename
);
596 CPRINT("Loading symbols from %wZ...\n", &Filename
);
598 /* Get the size of the file */
599 Status
= ZwQueryInformationFile(FileHandle
,
603 FileStandardInformation
);
604 if (!NT_SUCCESS(Status
))
606 DPRINT("Could not get file size\n");
610 /* Allocate nonpageable memory for symbol file */
611 FileBuffer
= ExAllocatePool(NonPagedPool
,
612 FileStdInfo
.EndOfFile
.u
.LowPart
);
614 if (FileBuffer
== NULL
)
616 DPRINT("Could not allocate memory for symbol file\n");
620 /* Load file into memory chunk */
621 Status
= ZwReadFile(FileHandle
,
625 FileStdInfo
.EndOfFile
.u
.LowPart
,
627 if (!NT_SUCCESS(Status
))
629 DPRINT("Could not read symbol file into memory\n");
630 ExFreePool(FileBuffer
);
636 LdrpLoadModuleSymbolsFromBuffer(ModuleObject
,
638 FileStdInfo
.EndOfFile
.u
.LowPart
);
640 ExFreePool(FileBuffer
);
643 VOID
LdrLoadUserModuleSymbols(PLDR_MODULE ModuleObject
)
645 FILE_STANDARD_INFORMATION FileStdInfo
;
646 OBJECT_ATTRIBUTES ObjectAttributes
;
647 WCHAR TmpFileName
[MAX_PATH
];
648 UNICODE_STRING Filename
;
654 IO_STATUS_BLOCK IoStatusBlock
;
656 ModuleObject
->Symbols
.SymbolCount
= 0;
657 ModuleObject
->Symbols
.Symbols
= NULL
;
659 /* Get the path to the symbol store */
660 wcscpy(TmpFileName
, L
"\\SystemRoot\\symbols\\");
662 /* Get the symbol filename from the module name */
663 Start
= wcsrchr(ModuleObject
->BaseDllName
.Buffer
, L
'\\');
665 Start
= ModuleObject
->BaseDllName
.Buffer
;
669 Ext
= wcsrchr(ModuleObject
->BaseDllName
.Buffer
, L
'.');
671 Length
= Ext
- Start
;
673 Length
= wcslen(Start
);
675 wcsncat(TmpFileName
, Start
, Length
);
676 wcscat(TmpFileName
, L
".sym");
677 RtlInitUnicodeString(&Filename
, TmpFileName
);
680 InitializeObjectAttributes(&ObjectAttributes
,
686 Status
= ZwOpenFile(&FileHandle
,
692 if (!NT_SUCCESS(Status
))
694 DPRINT("Could not open symbol file: %wZ\n", &Filename
);
698 CPRINT("Loading symbols from %wZ...\n", &Filename
);
700 /* Get the size of the file */
701 Status
= ZwQueryInformationFile(FileHandle
,
705 FileStandardInformation
);
706 if (!NT_SUCCESS(Status
))
708 DPRINT("Could not get file size\n");
712 /* Allocate nonpageable memory for symbol file */
713 FileBuffer
= ExAllocatePool(NonPagedPool
,
714 FileStdInfo
.EndOfFile
.u
.LowPart
);
716 if (FileBuffer
== NULL
)
718 DPRINT("Could not allocate memory for symbol file\n");
722 /* Load file into memory chunk */
723 Status
= ZwReadFile(FileHandle
,
727 FileStdInfo
.EndOfFile
.u
.LowPart
,
729 if (!NT_SUCCESS(Status
))
731 DPRINT("Could not read symbol file into memory\n");
732 ExFreePool(FileBuffer
);
738 LdrpLoadUserModuleSymbolsFromBuffer(ModuleObject
,
740 FileStdInfo
.EndOfFile
.u
.LowPart
);
742 ExFreePool(FileBuffer
);
747 VOID
LdrLoadAutoConfigDrivers (VOID
)
752 UNICODE_STRING ModuleName
;
753 PMODULE_OBJECT ModuleObject
;
755 /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
756 is created after their module entries */
758 RtlInitUnicodeString(&ModuleName
, KERNEL_MODULE_NAME
);
759 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
760 if (NT_SUCCESS(Status
))
762 LdrpLoadModuleSymbols(ModuleObject
);
765 RtlInitUnicodeString(&ModuleName
, HAL_MODULE_NAME
);
766 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
767 if (NT_SUCCESS(Status
))
769 LdrpLoadModuleSymbols(ModuleObject
);
777 //LdrLoadAutoConfigDriver( L"pci.sys" );
782 LdrLoadAutoConfigDriver( L
"keyboard.sys" );
784 if ((KdDebuggerEnabled
) && (KdDebugState
& KD_DEBUG_PICE
))
787 * Private ICE debugger
789 LdrLoadAutoConfigDriver( L
"pice.sys" );
795 LdrLoadAutoConfigDriver( L
"blue.sys" );
800 LdrLoadAutoConfigDriver(L
"vidport.sys");
804 * Minix filesystem driver
806 LdrLoadAutoConfigDriver(L
"minixfs.sys");
809 * Mailslot filesystem driver
811 LdrLoadAutoConfigDriver(L
"msfs.sys");
814 * Named pipe filesystem driver
816 LdrLoadAutoConfigDriver(L
"npfs.sys");
821 // LdrLoadAutoConfigDriver(L"l8042prt.sys");
822 LdrLoadAutoConfigDriver(L
"psaux.sys");
823 LdrLoadAutoConfigDriver(L
"mouclass.sys");
832 LdrLoadAutoConfigDriver(L
"ndis.sys");
838 LdrLoadGdiDriver(PUNICODE_STRING DriverName
,
840 PVOID
*SectionPointer
,
842 PVOID
*ExportSectionPointer
)
844 PMODULE_OBJECT ModuleObject
;
847 Status
= LdrLoadModule(DriverName
, &ModuleObject
);
848 if (!NT_SUCCESS(Status
))
854 *ImageAddress
= ModuleObject
->Base
;
856 // if (SectionPointer)
857 // *SectionPointer = ModuleObject->
860 *EntryPoint
= ModuleObject
->EntryPoint
;
862 // if (ExportSectionPointer)
863 // *ExportSectionPointer = ModuleObject->
865 return(STATUS_SUCCESS
);
870 LdrLoadModule(PUNICODE_STRING Filename
,
871 PMODULE_OBJECT
*ModuleObject
)
873 PVOID ModuleLoadBase
;
876 OBJECT_ATTRIBUTES ObjectAttributes
;
877 PMODULE_OBJECT Module
;
878 FILE_STANDARD_INFORMATION FileStdInfo
;
879 IO_STATUS_BLOCK IoStatusBlock
;
881 *ModuleObject
= NULL
;
883 /* Check for module already loaded */
884 Module
= LdrGetModuleObject(Filename
);
887 *ModuleObject
= Module
;
888 return(STATUS_SUCCESS
);
891 DPRINT("Loading Module %wZ...\n", Filename
);
893 /* Open the Module */
894 InitializeObjectAttributes(&ObjectAttributes
,
900 Status
= NtOpenFile(&FileHandle
,
907 if (!NT_SUCCESS(Status
))
909 CPRINT("Could not open module file: %wZ\n", Filename
);
914 /* Get the size of the file */
915 Status
= NtQueryInformationFile(FileHandle
,
919 FileStandardInformation
);
920 if (!NT_SUCCESS(Status
))
922 CPRINT("Could not get file size\n");
928 /* Allocate nonpageable memory for driver */
929 ModuleLoadBase
= ExAllocatePoolWithTag(NonPagedPool
,
930 FileStdInfo
.EndOfFile
.u
.LowPart
,
932 if (ModuleLoadBase
== NULL
)
934 CPRINT("Could not allocate memory for module");
936 return(STATUS_INSUFFICIENT_RESOURCES
);
940 /* Load driver into memory chunk */
941 Status
= NtReadFile(FileHandle
,
945 FileStdInfo
.EndOfFile
.u
.LowPart
,
947 if (!NT_SUCCESS(Status
))
949 CPRINT("Could not read module file into memory");
950 ExFreePool(ModuleLoadBase
);
958 Status
= LdrProcessModule(ModuleLoadBase
,
961 if (!NT_SUCCESS(Status
))
963 CPRINT("Could not process module");
964 ExFreePool(ModuleLoadBase
);
969 ExFreePool(ModuleLoadBase
);
973 /* Load symbols for module if available */
974 LdrpLoadModuleSymbols(Module
);
978 *ModuleObject
= Module
;
980 return(STATUS_SUCCESS
);
985 LdrInitializeBootStartDriver(PVOID ModuleLoadBase
,
989 PMODULE_OBJECT ModuleObject
;
990 UNICODE_STRING ModuleName
;
991 PDEVICE_NODE DeviceNode
;
994 WCHAR Buffer
[MAX_PATH
];
999 CHAR TextBuffer
[256];
1003 CHAR TmpBaseName
[MAX_PATH
];
1004 CHAR TmpFileName
[MAX_PATH
];
1005 ANSI_STRING AnsiString
;
1010 HalQueryDisplayParameters(&x
, &y
, &cx
, &cy
);
1011 RtlFillMemory(TextBuffer
, x
, ' ');
1012 TextBuffer
[x
] = '\0';
1013 HalSetDisplayParameters(0, y
-1);
1014 HalDisplayString(TextBuffer
);
1016 sprintf(TextBuffer
, "Initializing %s...\n", FileName
);
1017 HalSetDisplayParameters(0, y
-1);
1018 HalDisplayString(TextBuffer
);
1019 HalSetDisplayParameters(cx
, cy
);
1022 /* Split the filename into base name and extension */
1023 Ext
= strrchr(FileName
, '.');
1025 Length
= Ext
- FileName
;
1027 Length
= strlen(FileName
);
1029 if ((Ext
!= NULL
) && (strcmp(Ext
, ".sym") == 0))
1031 DPRINT("Module %s is a symbol file\n", FileName
);
1033 strncpy(TmpBaseName
, FileName
, Length
);
1034 TmpBaseName
[Length
] = '\0';
1036 DPRINT("base: %s (Length %d)\n", TmpBaseName
, Length
);
1038 strcpy(TmpFileName
, TmpBaseName
);
1039 strcat(TmpFileName
, ".sys");
1040 RtlInitAnsiString(&AnsiString
, TmpFileName
);
1042 DPRINT("dasdsad: %s\n", TmpFileName
);
1044 RtlAnsiStringToUnicodeString(&ModuleName
, &AnsiString
, TRUE
);
1045 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
1046 RtlFreeUnicodeString(&ModuleName
);
1047 if (!NT_SUCCESS(Status
))
1049 strcpy(TmpFileName
, TmpBaseName
);
1050 strcat(TmpFileName
, ".exe");
1051 RtlInitAnsiString(&AnsiString
, TmpFileName
);
1052 RtlAnsiStringToUnicodeString(&ModuleName
, &AnsiString
, TRUE
);
1053 Status
= LdrFindModuleObject(&ModuleName
, &ModuleObject
);
1054 RtlFreeUnicodeString(&ModuleName
);
1056 if (NT_SUCCESS(Status
))
1058 LdrpLoadModuleSymbolsFromBuffer(ModuleObject
,
1062 return(STATUS_SUCCESS
);
1066 DPRINT("Module %s is executable\n", FileName
);
1070 /* Use IopRootDeviceNode for now */
1071 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
1072 if (!NT_SUCCESS(Status
))
1074 CPRINT("Driver load failed, status (%x)\n", Status
);
1078 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
1080 Status
= LdrProcessModule(ModuleLoadBase
,
1083 RtlFreeUnicodeString(&ModuleName
);
1084 if (ModuleObject
== NULL
)
1086 IopFreeDeviceNode(DeviceNode
);
1087 CPRINT("Driver load failed, status (%x)\n", Status
);
1088 return(STATUS_UNSUCCESSFUL
);
1092 /* Get the service name from the module name */
1093 Start
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'\\');
1095 Start
= ModuleObject
->BaseName
.Buffer
;
1099 Ext
= wcsrchr(ModuleObject
->BaseName
.Buffer
, L
'.');
1101 Length
= Ext
- Start
;
1103 Length
= wcslen(Start
);
1105 wcsncpy(Buffer
, Start
, Length
);
1106 RtlCreateUnicodeString(&DeviceNode
->ServiceName
, Buffer
);
1108 Status
= IopInitializeDriver(ModuleObject
->EntryPoint
, DeviceNode
);
1109 if (!NT_SUCCESS(Status
))
1111 IopFreeDeviceNode(DeviceNode
);
1112 CPRINT("Driver load failed, status (%x)\n", Status
);
1120 LdrProcessModule(PVOID ModuleLoadBase
,
1121 PUNICODE_STRING ModuleName
,
1122 PMODULE_OBJECT
*ModuleObject
)
1124 PIMAGE_DOS_HEADER PEDosHeader
;
1126 /* If MZ header exists */
1127 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1128 if (PEDosHeader
->e_magic
== IMAGE_DOS_MAGIC
&& PEDosHeader
->e_lfanew
!= 0L)
1130 return LdrPEProcessModule(ModuleLoadBase
,
1135 CPRINT("Module wasn't PE\n");
1136 return STATUS_UNSUCCESSFUL
;
1141 LdrGetExportAddress(PMODULE_OBJECT ModuleObject
,
1143 unsigned short Hint
)
1145 if (ModuleObject
->Flags
& MODULE_FLAG_PE
)
1147 return LdrPEGetExportAddress(ModuleObject
, Name
, Hint
);
1157 LdrpQueryModuleInformation(PVOID Buffer
,
1161 PLIST_ENTRY current_entry
;
1162 PMODULE_OBJECT current
;
1163 ULONG ModuleCount
= 0;
1164 PSYSTEM_MODULE_INFORMATION Smi
;
1165 ANSI_STRING AnsiName
;
1169 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
1171 /* calculate required size */
1172 current_entry
= ModuleListHead
.Flink
;
1173 while (current_entry
!= (&ModuleListHead
))
1176 current_entry
= current_entry
->Flink
;
1179 *ReqSize
= sizeof(SYSTEM_MODULE_INFORMATION
)+
1180 (ModuleCount
- 1) * sizeof(SYSTEM_MODULE_ENTRY
);
1182 if (Size
< *ReqSize
)
1184 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1185 return(STATUS_INFO_LENGTH_MISMATCH
);
1188 /* fill the buffer */
1189 memset(Buffer
, '=', Size
);
1191 Smi
= (PSYSTEM_MODULE_INFORMATION
)Buffer
;
1192 Smi
->Count
= ModuleCount
;
1195 current_entry
= ModuleListHead
.Flink
;
1196 while (current_entry
!= (&ModuleListHead
))
1198 current
= CONTAINING_RECORD(current_entry
,MODULE_OBJECT
,ListEntry
);
1200 Smi
->Module
[ModuleCount
].Unknown2
= 0; /* Always 0 */
1201 Smi
->Module
[ModuleCount
].BaseAddress
= current
->Base
;
1202 Smi
->Module
[ModuleCount
].Size
= current
->Length
;
1203 Smi
->Module
[ModuleCount
].Flags
= 0; /* Flags ??? (GN) */
1204 Smi
->Module
[ModuleCount
].EntryIndex
= ModuleCount
;
1206 AnsiName
.Length
= 0;
1207 AnsiName
.MaximumLength
= 256;
1208 AnsiName
.Buffer
= Smi
->Module
[ModuleCount
].Name
;
1209 RtlUnicodeStringToAnsiString(&AnsiName
,
1213 p
= strrchr(AnsiName
.Buffer
, '\\');
1216 Smi
->Module
[ModuleCount
].PathLength
= 0;
1217 Smi
->Module
[ModuleCount
].NameLength
= strlen(AnsiName
.Buffer
);
1222 Smi
->Module
[ModuleCount
].PathLength
= p
- AnsiName
.Buffer
;
1223 Smi
->Module
[ModuleCount
].NameLength
= strlen(p
);
1227 current_entry
= current_entry
->Flink
;
1230 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1232 return(STATUS_SUCCESS
);
1237 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName
,
1238 PUNICODE_STRING FullName
)
1240 UNICODE_STRING Name
;
1244 DPRINT("LdrpBuildModuleBaseName()\n");
1245 DPRINT("FullName %wZ\n", FullName
);
1247 p
= wcsrchr(FullName
->Buffer
, L
'\\');
1250 p
= FullName
->Buffer
;
1257 DPRINT("p %S\n", p
);
1259 RtlCreateUnicodeString(&Name
, p
);
1261 q
= wcschr(Name
.Buffer
, L
'.');
1267 DPRINT("p %S\n", p
);
1269 RtlCreateUnicodeString(BaseName
, Name
.Buffer
);
1270 RtlFreeUnicodeString(&Name
);
1275 LdrpCompareModuleNames(IN PUNICODE_STRING String1
,
1276 IN PUNICODE_STRING String2
)
1278 ULONG len1
, len2
, i
;
1282 if (String1
&& String2
)
1284 /* Search String1 for last path component */
1285 len1
= String1
->Length
/ sizeof(WCHAR
);
1286 s1
= String1
->Buffer
;
1287 for (i
= 0, p
= String1
->Buffer
; i
< String1
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
1291 if (i
== String1
->Length
- sizeof(WCHAR
))
1299 len1
= (String1
->Length
- i
) / sizeof(WCHAR
);
1304 /* Search String2 for last path component */
1305 len2
= String2
->Length
/ sizeof(WCHAR
);
1306 s2
= String2
->Buffer
;
1307 for (i
= 0, p
= String2
->Buffer
; i
< String2
->Length
; i
= i
+ sizeof(WCHAR
), p
++)
1311 if (i
== String2
->Length
- sizeof(WCHAR
))
1319 len2
= (String2
->Length
- i
) / sizeof(WCHAR
);
1324 /* Compare last path components */
1329 c1
= len1
-- ? RtlUpcaseUnicodeChar (*s1
++) : 0;
1330 c2
= len2
-- ? RtlUpcaseUnicodeChar (*s2
++) : 0;
1331 if ((c1
== 0 && c2
== L
'.') || (c1
== L
'.' && c2
== 0))
1333 if (!c1
|| !c2
|| c1
!= c2
)
1344 LdrGetModuleObject(PUNICODE_STRING ModuleName
)
1346 PMODULE_OBJECT Module
;
1350 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName
);
1352 KeAcquireSpinLock(&ModuleListLock
,&Irql
);
1354 Entry
= ModuleListHead
.Flink
;
1355 while (Entry
!= &ModuleListHead
)
1357 Module
= CONTAINING_RECORD(Entry
, MODULE_OBJECT
, ListEntry
);
1359 DPRINT("Comparing %wZ and %wZ\n",
1363 if (!LdrpCompareModuleNames(&Module
->BaseName
, ModuleName
))
1365 DPRINT("Module %wZ\n", &Module
->BaseName
);
1366 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1370 Entry
= Entry
->Flink
;
1373 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1375 CPRINT("LdrpGetModuleObject: Failed to find dll %wZ\n", ModuleName
);
1381 /* ---------------------------------------------- PE Module support */
1384 LdrPEProcessModule(PVOID ModuleLoadBase
,
1385 PUNICODE_STRING FileName
,
1386 PMODULE_OBJECT
*ModuleObject
)
1388 unsigned int DriverSize
, Idx
;
1389 ULONG RelocDelta
, NumRelocs
;
1390 DWORD CurrentSize
, TotalRelocs
;
1393 PIMAGE_DOS_HEADER PEDosHeader
;
1394 PIMAGE_FILE_HEADER PEFileHeader
;
1395 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1396 PIMAGE_SECTION_HEADER PESectionHeaders
;
1397 PRELOCATION_DIRECTORY RelocDir
;
1398 PRELOCATION_ENTRY RelocEntry
;
1399 PMODULE_OBJECT LibraryModuleObject
;
1400 PMODULE_OBJECT CreatedModuleObject
;
1401 PVOID
*ImportAddressList
;
1402 PULONG FunctionNameList
;
1405 UNICODE_STRING ModuleName
;
1406 WCHAR NameBuffer
[60];
1407 MODULE_TEXT_SECTION
* ModuleTextSection
;
1411 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1413 /* Get header pointers */
1414 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1415 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1416 PEDosHeader
->e_lfanew
);
1417 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1418 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1419 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1420 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1421 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1422 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1423 sizeof(IMAGE_OPTIONAL_HEADER
));
1426 /* Check file magic numbers */
1427 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1429 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader
->e_magic
);
1430 return STATUS_UNSUCCESSFUL
;
1432 if (PEDosHeader
->e_lfanew
== 0)
1434 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader
->e_lfanew
);
1435 return STATUS_UNSUCCESSFUL
;
1437 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1439 CPRINT("Incorrect PE magic: %08x\n", *PEMagic
);
1440 return STATUS_UNSUCCESSFUL
;
1442 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1444 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader
->Machine
);
1445 return STATUS_UNSUCCESSFUL
;
1449 /* FIXME: if image is fixed-address load, then fail */
1451 /* FIXME: check/verify OS version number */
1453 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1454 PEOptionalHeader
->Magic
,
1455 PEOptionalHeader
->MajorLinkerVersion
,
1456 PEOptionalHeader
->MinorLinkerVersion
);
1457 DPRINT("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1460 /* Determine the size of the module */
1461 DriverSize
= PEOptionalHeader
->SizeOfImage
;
1462 DPRINT("DriverSize %x\n",DriverSize
);
1464 /* Allocate a virtual section for the module */
1465 DriverBase
= MmAllocateSection(DriverSize
);
1466 if (DriverBase
== 0)
1468 CPRINT("Failed to allocate a virtual section for driver\n");
1469 return STATUS_UNSUCCESSFUL
;
1471 CPRINT("DriverBase: %x\n", DriverBase
);
1473 /* Copy headers over */
1474 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1476 /* Copy image sections into virtual section */
1477 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1479 // Copy current section into current offset of virtual section
1480 if (PESectionHeaders
[Idx
].Characteristics
&
1481 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1483 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1484 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1485 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1486 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1487 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
? PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1491 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1492 PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1493 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1494 '\0', PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1497 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1498 PEOptionalHeader
->SectionAlignment
);
1501 // CurrentBase = (PVOID)((DWORD)CurrentBase +
1502 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
1503 // PEOptionalHeader->SectionAlignment));
1506 /* Perform relocation fixups */
1507 RelocDelta
= (DWORD
) DriverBase
- PEOptionalHeader
->ImageBase
;
1508 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1509 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1510 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1512 PEOptionalHeader
->ImageBase
,
1514 DPRINT("RelocDir %x\n",RelocDir
);
1516 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1518 if (PESectionHeaders
[Idx
].VirtualAddress
== (DWORD
)RelocDir
)
1520 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1521 PESectionHeaders
[Idx
].Name
,
1522 PESectionHeaders
[Idx
].PointerToRawData
);
1523 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+
1525 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1530 RelocDir
= RelocDir
+ (ULONG
)DriverBase
;
1531 CurrentSize
= PEOptionalHeader
->DataDirectory
1532 [IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
;
1534 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1536 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1538 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1540 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1542 RelocDir->VirtualAddress,
1544 RelocEntry
= (PRELOCATION_ENTRY
) ((DWORD
)RelocDir
+
1545 sizeof(RELOCATION_DIRECTORY
));
1546 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1552 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1553 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1554 RelocItem
= (PDWORD
)(DriverBase
+ RelocDir
->VirtualAddress
+
1556 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1559 Type ? "HIGHLOW" : "ABS",
1561 (*RelocItem) + RelocDelta); */
1564 (*RelocItem
) += RelocDelta
;
1568 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1569 return STATUS_UNSUCCESSFUL
;
1572 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1573 RelocDir
= (PRELOCATION_DIRECTORY
)((DWORD
)RelocDir
+
1574 RelocDir
->SizeOfBlock
);
1575 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1578 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1579 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1581 /* Perform import fixups */
1582 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1584 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1586 /* Process each import module */
1587 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1588 ((DWORD
)DriverBase
+ PEOptionalHeader
->
1589 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1590 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory
);
1591 while (ImportModuleDirectory
->dwRVAModuleName
)
1593 /* Check to make sure that import lib is kernel */
1594 pName
= (PCHAR
) DriverBase
+
1595 ImportModuleDirectory
->dwRVAModuleName
;
1597 RtlCreateUnicodeStringFromAsciiz(&ModuleName
, pName
);
1598 DPRINT("Import module: %wZ\n", &ModuleName
);
1600 Status
= LdrLoadModule(&ModuleName
, &LibraryModuleObject
);
1601 if (!NT_SUCCESS(Status
))
1603 CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName
, Status
);
1605 /* Get the import address list */
1606 ImportAddressList
= (PVOID
*) ((DWORD
)DriverBase
+
1607 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1609 /* Get the list of functions to import */
1610 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1612 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1613 ImportModuleDirectory
->dwRVAFunctionNameList
);
1617 FunctionNameList
= (PULONG
) ((DWORD
)DriverBase
+
1618 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1620 /* Walk through function list and fixup addresses */
1621 while (*FunctionNameList
!= 0L)
1623 if ((*FunctionNameList
) & 0x80000000) // hint
1628 Hint
= (*FunctionNameList
) & 0xffff;
1632 pName
= (PCHAR
)((DWORD
)DriverBase
+
1633 *FunctionNameList
+ 2);
1634 Hint
= *(PWORD
)((DWORD
)DriverBase
+ *FunctionNameList
);
1636 DPRINT(" Hint:%04x Name:%s\n", Hint
, pName
);
1638 /* Fixup the current import symbol */
1639 if (LibraryModuleObject
!= NULL
)
1641 *ImportAddressList
= LdrGetExportAddress(LibraryModuleObject
,
1647 CPRINT("Unresolved kernel symbol: %s\n", pName
);
1648 return STATUS_UNSUCCESSFUL
;
1650 ImportAddressList
++;
1654 RtlFreeUnicodeString(&ModuleName
);
1656 ImportModuleDirectory
++;
1660 /* Create the module */
1661 CreatedModuleObject
= ExAllocatePool(NonPagedPool
, sizeof(MODULE_OBJECT
));
1662 if (CreatedModuleObject
== NULL
)
1664 return(STATUS_INSUFFICIENT_RESOURCES
);
1667 RtlZeroMemory(CreatedModuleObject
, sizeof(MODULE_OBJECT
));
1669 /* Initialize ModuleObject data */
1670 CreatedModuleObject
->Base
= DriverBase
;
1671 CreatedModuleObject
->Flags
= MODULE_FLAG_PE
;
1673 RtlCreateUnicodeString(&CreatedModuleObject
->FullName
,
1675 LdrpBuildModuleBaseName(&CreatedModuleObject
->BaseName
,
1676 &CreatedModuleObject
->FullName
);
1678 CreatedModuleObject
->EntryPoint
= (PVOID
)((DWORD
)DriverBase
+
1679 PEOptionalHeader
->AddressOfEntryPoint
);
1680 CreatedModuleObject
->Length
= DriverSize
;
1681 DPRINT("EntryPoint at %x\n", CreatedModuleObject
->EntryPoint
);
1683 CreatedModuleObject
->Image
.PE
.FileHeader
=
1684 (PIMAGE_FILE_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1686 DPRINT("FileHeader at %x\n", CreatedModuleObject
->Image
.PE
.FileHeader
);
1687 CreatedModuleObject
->Image
.PE
.OptionalHeader
=
1688 (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1689 sizeof(IMAGE_FILE_HEADER
));
1690 DPRINT("OptionalHeader at %x\n", CreatedModuleObject
->Image
.PE
.OptionalHeader
);
1691 CreatedModuleObject
->Image
.PE
.SectionList
=
1692 (PIMAGE_SECTION_HEADER
) ((unsigned int) DriverBase
+ PEDosHeader
->e_lfanew
+ sizeof(ULONG
) +
1693 sizeof(IMAGE_FILE_HEADER
) + sizeof(IMAGE_OPTIONAL_HEADER
));
1694 DPRINT("SectionList at %x\n", CreatedModuleObject
->Image
.PE
.SectionList
);
1697 KeAcquireSpinLock(&ModuleListLock
, &Irql
);
1698 InsertTailList(&ModuleListHead
,
1699 &CreatedModuleObject
->ListEntry
);
1700 KeReleaseSpinLock(&ModuleListLock
, Irql
);
1703 ModuleTextSection
= ExAllocatePool(NonPagedPool
,
1704 sizeof(MODULE_TEXT_SECTION
));
1705 ModuleTextSection
->Base
= (ULONG
)DriverBase
;
1706 ModuleTextSection
->Length
= DriverSize
;
1707 ModuleTextSection
->SymbolsBase
= NULL
;
1708 ModuleTextSection
->SymbolsLength
= 0;
1709 ModuleTextSection
->Name
=
1710 ExAllocatePool(NonPagedPool
,
1711 (wcslen(NameBuffer
) + 1) * sizeof(WCHAR
));
1712 wcscpy(ModuleTextSection
->Name
, NameBuffer
);
1713 InsertTailList(&ModuleTextListHead
, &ModuleTextSection
->ListEntry
);
1715 CreatedModuleObject
->TextSection
= ModuleTextSection
;
1717 *ModuleObject
= CreatedModuleObject
;
1719 DPRINT("Loading Module %wZ...\n", FileName
);
1721 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_GDB
))
1723 DbgPrint("Module %wZ loaded at 0x%.08x.\n",
1724 FileName
, CreatedModuleObject
->Base
);
1727 return STATUS_SUCCESS
;
1732 LdrSafePEProcessModule(PVOID ModuleLoadBase
,
1734 PVOID ImportModuleBase
,
1738 ULONG RelocDelta
, NumRelocs
;
1739 ULONG CurrentSize
, TotalRelocs
;
1741 PIMAGE_DOS_HEADER PEDosHeader
;
1742 PIMAGE_FILE_HEADER PEFileHeader
;
1743 PIMAGE_OPTIONAL_HEADER PEOptionalHeader
;
1744 PIMAGE_SECTION_HEADER PESectionHeaders
;
1745 PRELOCATION_DIRECTORY RelocDir
;
1746 PRELOCATION_ENTRY RelocEntry
;
1747 PVOID
*ImportAddressList
;
1748 PULONG FunctionNameList
;
1752 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase
);
1754 /* Get header pointers */
1755 PEDosHeader
= (PIMAGE_DOS_HEADER
) ModuleLoadBase
;
1756 PEMagic
= (PULONG
) ((unsigned int) ModuleLoadBase
+
1757 PEDosHeader
->e_lfanew
);
1758 PEFileHeader
= (PIMAGE_FILE_HEADER
) ((unsigned int) ModuleLoadBase
+
1759 PEDosHeader
->e_lfanew
+ sizeof(ULONG
));
1760 PEOptionalHeader
= (PIMAGE_OPTIONAL_HEADER
) ((unsigned int) ModuleLoadBase
+
1761 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
));
1762 PESectionHeaders
= (PIMAGE_SECTION_HEADER
) ((unsigned int) ModuleLoadBase
+
1763 PEDosHeader
->e_lfanew
+ sizeof(ULONG
) + sizeof(IMAGE_FILE_HEADER
) +
1764 sizeof(IMAGE_OPTIONAL_HEADER
));
1767 /* Check file magic numbers */
1768 if (PEDosHeader
->e_magic
!= IMAGE_DOS_MAGIC
)
1772 if (PEDosHeader
->e_lfanew
== 0)
1776 if (*PEMagic
!= IMAGE_PE_MAGIC
)
1780 if (PEFileHeader
->Machine
!= IMAGE_FILE_MACHINE_I386
)
1785 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1786 PEOptionalHeader
->Magic
,
1787 PEOptionalHeader
->MajorLinkerVersion
,
1788 PEOptionalHeader
->MinorLinkerVersion
);
1789 ps("Entry Point:%08lx\n", PEOptionalHeader
->AddressOfEntryPoint
);
1791 /* Determine the size of the module */
1792 *DriverSize
= PEOptionalHeader
->SizeOfImage
;
1793 ps("DriverSize %x\n",*DriverSize
);
1795 /* Copy headers over */
1796 if (DriverBase
!= ModuleLoadBase
)
1798 memcpy(DriverBase
, ModuleLoadBase
, PEOptionalHeader
->SizeOfHeaders
);
1801 ps("Hdr: 0x%X\n", (ULONG
)PEOptionalHeader
);
1802 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG
)PEOptionalHeader
->SizeOfHeaders
);
1803 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG
)PEFileHeader
->NumberOfSections
);
1805 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1806 address as it is mapped */
1807 if (DriverBase
!= ModuleLoadBase
)
1811 /* Copy image sections into virtual section */
1812 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1814 // Copy current section into current offset of virtual section
1815 if (PESectionHeaders
[Idx
].Characteristics
&
1816 (IMAGE_SECTION_CHAR_CODE
| IMAGE_SECTION_CHAR_DATA
))
1818 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1819 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1820 memcpy(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1821 (PVOID
)(ModuleLoadBase
+ PESectionHeaders
[Idx
].PointerToRawData
),
1822 PESectionHeaders
[Idx
].Misc
.VirtualSize
> PESectionHeaders
[Idx
].SizeOfRawData
?
1823 PESectionHeaders
[Idx
].SizeOfRawData
: PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1827 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1828 PESectionHeaders
[Idx
].VirtualAddress
, PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
);
1829 memset(PESectionHeaders
[Idx
].VirtualAddress
+ DriverBase
,
1831 PESectionHeaders
[Idx
].Misc
.VirtualSize
);
1833 CurrentSize
+= ROUND_UP(PESectionHeaders
[Idx
].Misc
.VirtualSize
,
1834 PEOptionalHeader
->SectionAlignment
);
1837 /* Perform relocation fixups */
1838 RelocDelta
= (ULONG
) DriverBase
- PEOptionalHeader
->ImageBase
;
1839 RelocDir
= (PRELOCATION_DIRECTORY
)(PEOptionalHeader
->DataDirectory
[
1840 IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
);
1841 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1843 PEOptionalHeader
->ImageBase
,
1845 ps("RelocDir %x\n",RelocDir
);
1847 for (Idx
= 0; Idx
< PEFileHeader
->NumberOfSections
; Idx
++)
1849 if (PESectionHeaders
[Idx
].VirtualAddress
== (ULONG
)RelocDir
)
1851 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1852 PESectionHeaders
[Idx
].Name
,
1853 PESectionHeaders
[Idx
].PointerToRawData
);
1854 RelocDir
= PESectionHeaders
[Idx
].PointerToRawData
+ ModuleLoadBase
;
1855 CurrentSize
= PESectionHeaders
[Idx
].Misc
.VirtualSize
;
1860 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir
, CurrentSize
);
1863 while (TotalRelocs
< CurrentSize
&& RelocDir
->SizeOfBlock
!= 0)
1865 NumRelocs
= (RelocDir
->SizeOfBlock
- sizeof(RELOCATION_DIRECTORY
)) /
1867 RelocEntry
= (PRELOCATION_ENTRY
)((ULONG
)RelocDir
+
1868 sizeof(RELOCATION_DIRECTORY
));
1869 for (Idx
= 0; Idx
< NumRelocs
; Idx
++)
1875 Offset
= RelocEntry
[Idx
].TypeOffset
& 0xfff;
1876 Type
= (RelocEntry
[Idx
].TypeOffset
>> 12) & 0xf;
1877 RelocItem
= (PULONG
)(DriverBase
+ RelocDir
->VirtualAddress
+ Offset
);
1880 (*RelocItem
) += RelocDelta
;
1884 CPRINT("Unknown relocation type %x at %x\n",Type
, &Type
);
1888 TotalRelocs
+= RelocDir
->SizeOfBlock
;
1889 RelocDir
= (PRELOCATION_DIRECTORY
)((ULONG
)RelocDir
+
1890 RelocDir
->SizeOfBlock
);
1893 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1894 PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
]
1898 /* Perform import fixups */
1899 if (PEOptionalHeader
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
)
1901 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory
;
1903 /* Process each import module */
1904 ImportModuleDirectory
= (PIMAGE_IMPORT_MODULE_DIRECTORY
)
1905 ((ULONG
)DriverBase
+ PEOptionalHeader
->
1906 DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
);
1908 ps("Processeing import directory at %p\n", ImportModuleDirectory
);
1910 /* Check to make sure that import lib is kernel */
1911 pName
= (PCHAR
)DriverBase
+ ImportModuleDirectory
->dwRVAModuleName
;
1913 ps("Import module: %s\n", pName
);
1915 /* Get the import address list */
1916 ImportAddressList
= (PVOID
*)((ULONG
)DriverBase
+
1917 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1919 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1920 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1921 ps(" ImportAddressList: 0x%X\n", ImportAddressList
);
1923 /* Get the list of functions to import */
1924 if (ImportModuleDirectory
->dwRVAFunctionNameList
!= 0)
1926 ps("Using function name list.\n");
1928 FunctionNameList
= (PULONG
)((ULONG
)DriverBase
+
1929 ImportModuleDirectory
->dwRVAFunctionNameList
);
1933 ps("Using function address list.\n");
1935 FunctionNameList
= (PULONG
)((ULONG
)DriverBase
+
1936 ImportModuleDirectory
->dwRVAFunctionAddressList
);
1939 /* Walk through function list and fixup addresses */
1940 while (*FunctionNameList
!= 0L)
1942 if ((*FunctionNameList
) & 0x80000000)
1946 Hint
= (*FunctionNameList
) & 0xffff;
1951 pName
= (PCHAR
)((ULONG
)DriverBase
+ *FunctionNameList
+ 2);
1952 Hint
= *(PWORD
)((ULONG
)DriverBase
+ *FunctionNameList
);
1954 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1956 *ImportAddressList
= LdrSafePEGetExportAddress(ImportModuleBase
,
1960 ImportAddressList
++;
1965 ps("Finished importing.\n");
1972 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject
,
1976 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1977 ULONG ExportDirSize
;
1979 PVOID ExportAddress
;
1981 PDWORD FunctionList
, NameList
;
1983 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1984 RtlImageDirectoryEntryToData(ModuleObject
->Base
,
1986 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1988 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir
, ExportDirSize
);
1989 if (ExportDir
== NULL
)
1994 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ModuleObject
->Base
);
1995 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ModuleObject
->Base
);
1996 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ModuleObject
->Base
);
2002 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
2005 DPRINT(" Name:%s NameList[%d]:%s\n",
2008 (DWORD
) ModuleObject
->Base
+ NameList
[Idx
]);
2011 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ModuleObject
->Base
+ NameList
[Idx
])))
2013 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
2014 FunctionList
[OrdinalList
[Idx
]]);
2015 if (((ULONG
)ExportAddress
>= (ULONG
)ExportDir
) &&
2016 ((ULONG
)ExportAddress
< (ULONG
)ExportDir
+ ExportDirSize
))
2018 DPRINT("Forward: %s\n", (PCHAR
)ExportAddress
);
2019 ExportAddress
= LdrPEFixupForward((PCHAR
)ExportAddress
);
2020 DPRINT("ExportAddress: %p\n", ExportAddress
);
2029 ExportAddress
= (PVOID
) ((DWORD
)ModuleObject
->Base
+
2030 FunctionList
[Hint
- ExportDir
->Base
]);
2033 if (ExportAddress
== 0)
2035 CPRINT("Export not found for %d:%s\n",
2037 Name
!= NULL
? Name
: "(Ordinal)");
2041 return(ExportAddress
);
2046 LdrSafePEGetExportAddress(PVOID ImportModuleBase
,
2051 PVOID ExportAddress
;
2053 PDWORD FunctionList
, NameList
;
2054 PIMAGE_EXPORT_DIRECTORY ExportDir
;
2055 ULONG ExportDirSize
;
2057 static BOOLEAN EP
= FALSE
;
2059 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
2060 RtlImageDirectoryEntryToData(ImportModuleBase
,
2062 IMAGE_DIRECTORY_ENTRY_EXPORT
,
2067 ps("ExportDir %x\n", ExportDir
);
2070 FunctionList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfFunctions
+ ImportModuleBase
);
2071 NameList
= (PDWORD
)((DWORD
)ExportDir
->AddressOfNames
+ ImportModuleBase
);
2072 OrdinalList
= (PWORD
)((DWORD
)ExportDir
->AddressOfNameOrdinals
+ ImportModuleBase
);
2078 for (Idx
= 0; Idx
< ExportDir
->NumberOfNames
; Idx
++)
2080 if (!strcmp(Name
, (PCHAR
) ((DWORD
)ImportModuleBase
+ NameList
[Idx
])))
2082 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
2083 FunctionList
[OrdinalList
[Idx
]]);
2090 ExportAddress
= (PVOID
) ((DWORD
)ImportModuleBase
+
2092 FunctionList
[Hint
- ExportDir
->Base
]);
2095 if (ExportAddress
== 0)
2097 ps("Export not found for %d:%s\n",
2099 Name
!= NULL
? Name
: "(Ordinal)");
2102 return ExportAddress
;
2107 LdrPEFixupForward(PCHAR ForwardName
)
2109 CHAR NameBuffer
[128];
2110 UNICODE_STRING ModuleName
;
2112 PMODULE_OBJECT ModuleObject
;
2114 DPRINT("LdrPEFixupForward (%s)\n", ForwardName
);
2116 strcpy(NameBuffer
, ForwardName
);
2117 p
= strchr(NameBuffer
, '.');
2125 DPRINT("Driver: %s Function: %s\n", NameBuffer
, p
+1);
2127 RtlCreateUnicodeStringFromAsciiz(&ModuleName
,
2129 ModuleObject
= LdrGetModuleObject(&ModuleName
);
2130 RtlFreeUnicodeString(&ModuleName
);
2132 DPRINT("ModuleObject: %p\n", ModuleObject
);
2134 if (ModuleObject
== NULL
)
2136 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
2140 return(LdrPEGetExportAddress(ModuleObject
, p
+1, 0));