b2ce0ca561845b6cbebb66f5fc572d01f2d979a7
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
1 /* $Id: loader.c,v 1.87 2001/08/26 17:27:44 ekohl Exp $
2 *
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)
11 * UPDATE HISTORY:
12 * DW 22/05/98 Created
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
21 */
22
23
24 /* INCLUDES *****************************************************************/
25
26 #include <limits.h>
27 #include <ddk/ntddk.h>
28 #include <internal/config.h>
29 #include <internal/module.h>
30 #include <internal/ntoskrnl.h>
31 #include <internal/io.h>
32 #include <internal/mm.h>
33 #include <internal/ob.h>
34 #include <internal/ps.h>
35 #include <internal/ldr.h>
36 #include <internal/pool.h>
37
38 #ifdef HALDBG
39 #include <internal/ntosdbg.h>
40 #else
41 #define ps(args...)
42 #endif
43
44 #define NDEBUG
45 #include <internal/debug.h>
46
47 /* MACROS ********************************************************************/
48
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\\"
53
54 /* GLOBALS *******************************************************************/
55
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;
61 ULONG_PTR LdrHalBase;
62
63 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
64 #define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
65
66 /* FORWARD DECLARATIONS ******************************************************/
67
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,
76 PVOID Parent,
77 PWSTR RemainingPath,
78 POBJECT_ATTRIBUTES ObjectAttributes);
79 static VOID LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
80 PUNICODE_STRING FullName);
81
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,
87 char *Name,
88 unsigned short Hint);
89 static PMODULE_OBJECT LdrPEGetModuleObject(PUNICODE_STRING ModuleName);
90 static PVOID LdrPEFixupForward(PCHAR ForwardName);
91
92 static PVOID
93 LdrSafePEGetExportAddress(
94 PVOID ImportModuleBase,
95 char *Name,
96 unsigned short Hint);
97
98
99 /* FUNCTIONS *****************************************************************/
100
101 VOID
102 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
103 {
104 PLIST_ENTRY current_entry;
105 MODULE_TEXT_SECTION* current;
106
107 current_entry = ModuleTextListHead.Flink;
108 while (current_entry != &ModuleTextListHead)
109 {
110 current =
111 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
112 if (wcscmp(current->Name, Name) == 0)
113 {
114 break;
115 }
116 current_entry = current_entry->Flink;
117 }
118
119 if (current_entry == &ModuleTextListHead)
120 {
121 return;
122 }
123
124 current->SymbolsBase = (PVOID)Module->ModStart;
125 current->SymbolsLength = Module->ModEnd - Module->ModStart;
126 }
127
128 VOID
129 LdrInit1(VOID)
130 {
131 PIMAGE_DOS_HEADER DosHeader;
132 PIMAGE_FILE_HEADER FileHeader;
133 PIMAGE_OPTIONAL_HEADER OptionalHeader;
134 PIMAGE_SECTION_HEADER SectionList;
135
136 InitializeListHead(&ModuleTextListHead);
137
138 /* Setup ntoskrnl.exe text section */
139 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
140 FileHeader =
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);
154
155 /* Setup hal.dll text section */
156 DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase;
157 FileHeader =
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);
171 }
172
173 VOID LdrInitModuleManagement(VOID)
174 {
175 HANDLE DirHandle, ModuleHandle;
176 NTSTATUS Status;
177 WCHAR NameBuffer[60];
178 UNICODE_STRING ModuleName;
179 OBJECT_ATTRIBUTES ObjectAttributes;
180 PIMAGE_DOS_HEADER DosHeader;
181 PMODULE_OBJECT ModuleObject;
182
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");
202
203 /* Create Modules object directory */
204 wcscpy(NameBuffer, MODULE_ROOT_NAME);
205 *(wcsrchr(NameBuffer, L'\\')) = 0;
206 RtlInitUnicodeString (&ModuleName, NameBuffer);
207 InitializeObjectAttributes(&ObjectAttributes,
208 &ModuleName,
209 0,
210 NULL,
211 NULL);
212 DPRINT("Create dir: %wZ\n", &ModuleName);
213 Status = NtCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
214 assert(NT_SUCCESS(Status));
215
216 /* Create FileSystem object directory */
217 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
218 *(wcsrchr(NameBuffer, L'\\')) = 0;
219 RtlInitUnicodeString (&ModuleName, NameBuffer);
220 InitializeObjectAttributes(&ObjectAttributes,
221 &ModuleName,
222 0,
223 NULL,
224 NULL);
225 DPRINT("Create dir: %wZ\n", &ModuleName);
226 Status = NtCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
227 assert(NT_SUCCESS(Status));
228
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);
234
235 /* Initialize ObjectAttributes for ModuleObject */
236 InitializeObjectAttributes(&ObjectAttributes,
237 &ModuleName,
238 0,
239 NULL,
240 NULL);
241
242 /* Create module object */
243 ModuleHandle = 0;
244 Status = ObCreateObject(&ModuleHandle,
245 STANDARD_RIGHTS_REQUIRED,
246 &ObjectAttributes,
247 IoDriverObjectType,
248 (PVOID*)&ModuleObject);
249 assert(NT_SUCCESS(Status));
250
251 InitializeListHead(&ModuleListHead);
252
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,
259 KERNEL_MODULE_NAME);
260 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
261 &ModuleObject->FullName);
262
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;
276
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);
282
283 /* Initialize ObjectAttributes for ModuleObject */
284 InitializeObjectAttributes(&ObjectAttributes,
285 &ModuleName,
286 0,
287 NULL,
288 NULL);
289
290 /* Create module object */
291 ModuleHandle = 0;
292 Status = ObCreateObject(&ModuleHandle,
293 STANDARD_RIGHTS_REQUIRED,
294 &ObjectAttributes,
295 IoDriverObjectType,
296 (PVOID*)&ModuleObject);
297 assert(NT_SUCCESS(Status));
298
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,
305 HAL_MODULE_NAME);
306 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
307 &ModuleObject->FullName);
308
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;
322 }
323
324 /*
325 * load the auto config drivers.
326 */
327 static VOID LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName)
328 {
329 WCHAR TmpFileName [MAX_PATH];
330 UNICODE_STRING DriverName;
331 PDEVICE_NODE DeviceNode;
332 NTSTATUS Status;
333
334 CPRINT("Loading %S\n",RelativeDriverName);
335
336 wcscpy(TmpFileName, L"\\SystemRoot\\system32\\drivers\\");
337 wcscat(TmpFileName, RelativeDriverName);
338 RtlInitUnicodeString (&DriverName, TmpFileName);
339
340 /* Use IopRootDeviceNode for now */
341 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
342 if (!NT_SUCCESS(Status))
343 {
344 return;
345 }
346
347 Status = LdrLoadDriver(&DriverName, DeviceNode, FALSE);
348 if (!NT_SUCCESS(Status))
349 {
350 IopFreeDeviceNode(DeviceNode);
351 DPRINT1("Driver load failed, status (%x)\n", Status);
352 }
353 }
354
355 #ifdef KDBG
356
357 BOOLEAN LdrpReadLine(PCHAR Line,
358 ULONG LineSize,
359 PVOID *Buffer,
360 PULONG Size)
361 {
362 CHAR ch;
363 PCHAR Block;
364 ULONG Count;
365
366 if (*Size == 0)
367 return FALSE;
368
369 ch = ' ';
370 Count = 0;
371 Block = *Buffer;
372 while ((*Size > 0) && (Count < LineSize) && ((ch = *Block) != (CHAR)13))
373 {
374 *Line = ch;
375 Line++;
376 Block++;
377 Count++;
378 *Size -= 1;
379 }
380 *Line = (CHAR)0;
381
382 if (ch == (CHAR)13)
383 {
384 Block++;
385 *Size -= 1;
386 }
387
388 if ((*Size > 0) && (*Block == (CHAR)10))
389 {
390 Block++;
391 *Size -= 1;
392 }
393
394 *Buffer = Block;
395
396 return TRUE;
397 }
398
399 ULONG HexL(PCHAR Buffer)
400 {
401 CHAR ch;
402 UINT i, j;
403 ULONG Value;
404
405 j = 32;
406 i = 0;
407 Value = 0;
408 while ((j > 0) && ((ch = Buffer[i]) != ' '))
409 {
410 j -= 4;
411 if ((ch >= '0') && (ch <= '9'))
412 Value |= ((ch - '0') << j);
413 if ((ch >= 'A') && (ch <= 'F'))
414 Value |= ((10 + (ch - 'A')) << j);
415 else
416 if ((ch >= 'a') && (ch <= 'f'))
417 Value |= ((10 + (ch - 'a')) << j);
418 i++;
419 }
420 return Value;
421 }
422
423 PSYMBOL LdrpParseLine(PCHAR Line,
424 PULONG TextBase,
425 PBOOLEAN TextBaseValid,
426 PULONG Alignment)
427 /*
428 Line format: [ADDRESS] <TYPE> <NAME>
429 TYPE:
430 U = ?
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
439 */
440 {
441 ANSI_STRING AnsiString;
442 CHAR Buffer[128];
443 PSYMBOL Symbol;
444 ULONG Address;
445 PCHAR Str;
446 CHAR Type;
447
448 if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
449 return NULL;
450
451 Address = HexL(Line);
452
453 Line = strchr(Line, ' ');
454 if (Line == NULL)
455 return NULL;
456
457 Line++;
458 Type = *Line;
459
460 Line = strchr(Line, ' ');
461 if (Line == NULL)
462 return NULL;
463
464 Line++;
465 Str = strchr(Line, ' ');
466 if (Str == NULL)
467 strcpy((char*)&Buffer, Line);
468 else
469 strncpy((char*)&Buffer, Line, Str - Line);
470
471 if ((Type == 'A') && (strcmp((char*)&Buffer, "__section_alignment__")) == 0)
472 {
473 *Alignment = Address;
474 return NULL;
475 }
476
477 /* We only want symbols in the .text segment */
478 if ((Type != 't') && (Type != 'T'))
479 return NULL;
480
481 /* Discard other symbols we can't use */
482 if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
483 return NULL;
484
485 Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
486 if (!Symbol)
487 return NULL;
488
489 Symbol->Next = NULL;
490
491 Symbol->RelativeAddress = Address;
492
493 RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
494 RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
495
496 if (!(*TextBaseValid))
497 {
498 *TextBase = Address - *Alignment;
499 *TextBaseValid = TRUE;
500 }
501
502 return Symbol;
503 }
504
505 VOID LdrpLoadModuleSymbolsFromBuffer(
506 PMODULE_OBJECT ModuleObject,
507 PVOID Buffer,
508 ULONG Length)
509 /*
510 Symbols must be sorted by address, e.g.
511 "nm --numeric-sort module.sys > module.sym"
512 */
513 {
514 PSYMBOL Symbol, CurrentSymbol = NULL;
515 BOOLEAN TextBaseValid;
516 BOOLEAN Valid;
517 ULONG TextBase = 0;
518 ULONG Alignment = 0;
519 CHAR Line[256];
520 ULONG Tmp;
521
522 assert(ModuleObject);
523
524 if (ModuleObject->TextSection == NULL)
525 {
526 ModuleObject->TextSection = &NtoskrnlTextSection;
527 }
528
529 if (ModuleObject->TextSection->Symbols.SymbolCount > 0)
530 {
531 CPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseName);
532 return;
533 }
534
535 ModuleObject->TextSection->Symbols.SymbolCount = 0;
536 ModuleObject->TextSection->Symbols.Symbols = NULL;
537 TextBaseValid = FALSE;
538 Valid = FALSE;
539 while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
540 {
541 Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &Alignment);
542
543 if ((Valid) && (!TextBaseValid))
544 {
545 TextBase = Tmp;
546 TextBaseValid = TRUE;
547 }
548
549 if (Symbol != NULL)
550 {
551 Symbol->RelativeAddress -= TextBase;
552
553 if (ModuleObject->TextSection->Symbols.Symbols == NULL)
554 ModuleObject->TextSection->Symbols.Symbols = Symbol;
555 else
556 CurrentSymbol->Next = Symbol;
557
558 CurrentSymbol = Symbol;
559
560 ModuleObject->TextSection->Symbols.SymbolCount++;
561 }
562 }
563 }
564
565 VOID LdrpLoadUserModuleSymbolsFromBuffer(
566 PLDR_MODULE ModuleObject,
567 PVOID Buffer,
568 ULONG Length)
569 /*
570 Symbols must be sorted by address, e.g.
571 "nm --numeric-sort module.dll > module.sym"
572 */
573 {
574 PSYMBOL Symbol, CurrentSymbol = NULL;
575 BOOLEAN TextBaseValid;
576 BOOLEAN Valid;
577 ULONG TextBase = 0;
578 ULONG Alignment = 0;
579 CHAR Line[256];
580 ULONG Tmp;
581
582 if (ModuleObject->Symbols.SymbolCount > 0)
583 {
584 DPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseDllName);
585 return;
586 }
587
588 ModuleObject->Symbols.SymbolCount = 0;
589 ModuleObject->Symbols.Symbols = NULL;
590 TextBaseValid = FALSE;
591 Valid = FALSE;
592 while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
593 {
594 Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &Alignment);
595
596 if ((Valid) && (!TextBaseValid))
597 {
598 TextBase = Tmp;
599 TextBaseValid = TRUE;
600 }
601
602 if (Symbol != NULL)
603 {
604 Symbol->RelativeAddress -= TextBase;
605
606 if (ModuleObject->Symbols.Symbols == NULL)
607 ModuleObject->Symbols.Symbols = Symbol;
608 else
609 CurrentSymbol->Next = Symbol;
610
611 CurrentSymbol = Symbol;
612
613 ModuleObject->Symbols.SymbolCount++;
614 }
615 }
616 }
617
618 VOID
619 LdrpLoadModuleSymbols(PMODULE_OBJECT ModuleObject)
620 {
621 FILE_STANDARD_INFORMATION FileStdInfo;
622 OBJECT_ATTRIBUTES ObjectAttributes;
623 WCHAR TmpFileName[MAX_PATH];
624 UNICODE_STRING Filename;
625 LPWSTR Start, Ext;
626 HANDLE FileHandle;
627 PVOID FileBuffer;
628 NTSTATUS Status;
629 ULONG Length;
630 IO_STATUS_BLOCK IoStatusBlock;
631
632 /* Get the path to the symbol store */
633 wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
634
635 /* Get the symbol filename from the module name */
636 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
637 if (Start == NULL)
638 Start = ModuleObject->BaseName.Buffer;
639 else
640 Start++;
641
642 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
643 if (Ext != NULL)
644 Length = Ext - Start;
645 else
646 Length = wcslen(Start);
647
648 wcsncat(TmpFileName, Start, Length);
649 wcscat(TmpFileName, L".sym");
650 RtlInitUnicodeString(&Filename, TmpFileName);
651
652 /* Open the file */
653 InitializeObjectAttributes(&ObjectAttributes,
654 &Filename,
655 0,
656 NULL,
657 NULL);
658
659 Status = ZwOpenFile(&FileHandle,
660 FILE_ALL_ACCESS,
661 &ObjectAttributes,
662 &IoStatusBlock,
663 0,
664 0);
665 if (!NT_SUCCESS(Status))
666 {
667 DPRINT("Could not open symbol file: %wZ\n", &Filename);
668 return;
669 }
670
671 CPRINT("Loading symbols from %wZ...\n", &Filename);
672
673 /* Get the size of the file */
674 Status = ZwQueryInformationFile(FileHandle,
675 &IoStatusBlock,
676 &FileStdInfo,
677 sizeof(FileStdInfo),
678 FileStandardInformation);
679 if (!NT_SUCCESS(Status))
680 {
681 DPRINT("Could not get file size\n");
682 return;
683 }
684
685 /* Allocate nonpageable memory for symbol file */
686 FileBuffer = ExAllocatePool(NonPagedPool,
687 FileStdInfo.EndOfFile.u.LowPart);
688
689 if (FileBuffer == NULL)
690 {
691 DPRINT("Could not allocate memory for symbol file\n");
692 return;
693 }
694
695 /* Load file into memory chunk */
696 Status = ZwReadFile(FileHandle,
697 0, 0, 0,
698 &IoStatusBlock,
699 FileBuffer,
700 FileStdInfo.EndOfFile.u.LowPart,
701 0, 0);
702 if (!NT_SUCCESS(Status))
703 {
704 DPRINT("Could not read symbol file into memory\n");
705 ExFreePool(FileBuffer);
706 return;
707 }
708
709 ZwClose(FileHandle);
710
711 LdrpLoadModuleSymbolsFromBuffer(ModuleObject,
712 FileBuffer,
713 FileStdInfo.EndOfFile.u.LowPart);
714
715 ExFreePool(FileBuffer);
716 }
717
718 VOID LdrLoadUserModuleSymbols(PLDR_MODULE ModuleObject)
719 {
720 FILE_STANDARD_INFORMATION FileStdInfo;
721 OBJECT_ATTRIBUTES ObjectAttributes;
722 WCHAR TmpFileName[MAX_PATH];
723 UNICODE_STRING Filename;
724 LPWSTR Start, Ext;
725 HANDLE FileHandle;
726 PVOID FileBuffer;
727 NTSTATUS Status;
728 ULONG Length;
729 IO_STATUS_BLOCK IoStatusBlock;
730
731 /* Get the path to the symbol store */
732 wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
733
734 /* Get the symbol filename from the module name */
735 Start = wcsrchr(ModuleObject->BaseDllName.Buffer, L'\\');
736 if (Start == NULL)
737 Start = ModuleObject->BaseDllName.Buffer;
738 else
739 Start++;
740
741 Ext = wcsrchr(ModuleObject->BaseDllName.Buffer, L'.');
742 if (Ext != NULL)
743 Length = Ext - Start;
744 else
745 Length = wcslen(Start);
746
747 wcsncat(TmpFileName, Start, Length);
748 wcscat(TmpFileName, L".sym");
749 RtlInitUnicodeString(&Filename, TmpFileName);
750
751 /* Open the file */
752 InitializeObjectAttributes(&ObjectAttributes,
753 &Filename,
754 0,
755 NULL,
756 NULL);
757
758 Status = ZwOpenFile(&FileHandle,
759 FILE_ALL_ACCESS,
760 &ObjectAttributes,
761 &IoStatusBlock,
762 0,
763 0);
764 if (!NT_SUCCESS(Status))
765 {
766 DPRINT("Could not open symbol file: %wZ\n", &Filename);
767 return;
768 }
769
770 DbgPrint("Loading symbols from %wZ...\n", &Filename);
771
772 /* Get the size of the file */
773 Status = ZwQueryInformationFile(FileHandle,
774 &IoStatusBlock,
775 &FileStdInfo,
776 sizeof(FileStdInfo),
777 FileStandardInformation);
778 if (!NT_SUCCESS(Status))
779 {
780 DPRINT("Could not get file size\n");
781 return;
782 }
783
784 /* Allocate nonpageable memory for symbol file */
785 FileBuffer = ExAllocatePool(NonPagedPool,
786 FileStdInfo.EndOfFile.u.LowPart);
787
788 if (FileBuffer == NULL)
789 {
790 DPRINT("Could not allocate memory for symbol file\n");
791 return;
792 }
793
794 /* Load file into memory chunk */
795 Status = ZwReadFile(FileHandle,
796 0, 0, 0,
797 &IoStatusBlock,
798 FileBuffer,
799 FileStdInfo.EndOfFile.u.LowPart,
800 0, 0);
801 if (!NT_SUCCESS(Status))
802 {
803 DPRINT("Could not read symbol file into memory\n");
804 ExFreePool(FileBuffer);
805 return;
806 }
807
808 ZwClose(FileHandle);
809
810 LdrpLoadUserModuleSymbolsFromBuffer(ModuleObject,
811 FileBuffer,
812 FileStdInfo.EndOfFile.u.LowPart);
813
814 ExFreePool(FileBuffer);
815 }
816
817 NTSTATUS LdrpFindModuleObject(
818 PUNICODE_STRING ModuleName,
819 PMODULE_OBJECT *ModuleObject)
820 {
821 NTSTATUS Status;
822 WCHAR NameBuffer[MAX_PATH];
823 UNICODE_STRING Name;
824 OBJECT_ATTRIBUTES ObjectAttributes;
825 UNICODE_STRING RemainingPath;
826
827 wcscpy(NameBuffer, MODULE_ROOT_NAME);
828 wcscat(NameBuffer, ModuleName->Buffer);
829 RtlInitUnicodeString(&Name, NameBuffer);
830
831 InitializeObjectAttributes(&ObjectAttributes,
832 &Name,
833 0,
834 NULL,
835 NULL);
836 Status = ObFindObject(&ObjectAttributes,
837 (PVOID*)ModuleObject,
838 &RemainingPath,
839 NULL);
840 if (!NT_SUCCESS(Status))
841 {
842 return Status;
843 }
844
845 if ((RemainingPath.Buffer != NULL) || (*ModuleObject == NULL))
846 {
847 RtlFreeUnicodeString(&RemainingPath);
848 return STATUS_UNSUCCESSFUL;
849 }
850
851 return STATUS_SUCCESS;
852 }
853
854 #endif /* KDBG */
855
856 VOID LdrLoadAutoConfigDrivers (VOID)
857 {
858
859 #ifdef KDBG
860
861 NTSTATUS Status;
862 UNICODE_STRING ModuleName;
863 PMODULE_OBJECT ModuleObject;
864
865 /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
866 is created after their module entries */
867
868 RtlInitUnicodeString(&ModuleName, KERNEL_MODULE_NAME);
869 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
870 if (NT_SUCCESS(Status))
871 {
872 LdrpLoadModuleSymbols(ModuleObject);
873 }
874
875 RtlInitUnicodeString(&ModuleName, HAL_MODULE_NAME);
876 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
877 if (NT_SUCCESS(Status))
878 {
879 LdrpLoadModuleSymbols(ModuleObject);
880 }
881 #endif /* KDBG */
882
883 /*
884 * Keyboard driver
885 */
886 LdrLoadAutoConfigDriver( L"keyboard.sys" );
887
888 /*
889 * Raw console driver
890 */
891 LdrLoadAutoConfigDriver( L"blue.sys" );
892
893 /*
894 *
895 */
896 LdrLoadAutoConfigDriver(L"vidport.sys");
897
898 /*
899 *
900 */
901 LdrLoadAutoConfigDriver(L"vgamp.sys");
902 #if 0
903 /*
904 * Minix filesystem driver
905 */
906 LdrLoadAutoConfigDriver(L"minixfs.sys");
907
908 /*
909 * Mailslot filesystem driver
910 */
911 LdrLoadAutoConfigDriver(L"msfs.sys");
912
913 /*
914 * Named pipe filesystem driver
915 */
916 LdrLoadAutoConfigDriver(L"npfs.sys");
917 #endif
918 /*
919 * Mouse drivers
920 */
921 // LdrLoadAutoConfigDriver(L"l8042prt.sys");
922 LdrLoadAutoConfigDriver(L"psaux.sys");
923 LdrLoadAutoConfigDriver(L"mouclass.sys");
924
925 /*
926 * Networking
927 */
928 #if 1
929 /*
930 * NDIS library
931 */
932 LdrLoadAutoConfigDriver(L"ndis.sys");
933
934 /*
935 * Novell Eagle 2000 driver
936 */
937 //LdrLoadAutoConfigDriver(L"ne2000.sys");
938
939 /*
940 * TCP/IP protocol driver
941 */
942 LdrLoadAutoConfigDriver(L"tcpip.sys");
943
944 /*
945 * TDI test driver
946 */
947 //LdrLoadAutoConfigDriver(L"tditest.sys");
948
949 /*
950 * Ancillary Function Driver
951 */
952 LdrLoadAutoConfigDriver(L"afd.sys");
953 #endif
954 }
955
956
957 static NTSTATUS STDCALL
958 LdrCreateModule(PVOID ObjectBody,
959 PVOID Parent,
960 PWSTR RemainingPath,
961 POBJECT_ATTRIBUTES ObjectAttributes)
962 {
963 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
964 ObjectBody,
965 Parent,
966 RemainingPath);
967 if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
968 {
969 return STATUS_UNSUCCESSFUL;
970 }
971 if (Parent != NULL && RemainingPath != NULL)
972 {
973 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath + 1);
974 }
975
976 return STATUS_SUCCESS;
977 }
978
979 /*
980 * FUNCTION: Loads a kernel driver
981 * ARGUMENTS:
982 * FileName = Driver to load
983 * RETURNS: Status
984 */
985
986 NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename,
987 PDEVICE_NODE DeviceNode,
988 BOOLEAN BootDriversOnly)
989 {
990 PMODULE_OBJECT ModuleObject;
991 NTSTATUS Status;
992
993 ModuleObject = LdrLoadModule(Filename);
994 if (!ModuleObject)
995 {
996 return STATUS_UNSUCCESSFUL;
997 }
998
999 Status = IopInitializeDriver(ModuleObject->EntryPoint,
1000 DeviceNode, Filename, BootDriversOnly);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 ObDereferenceObject(ModuleObject);
1004 }
1005
1006 return Status;
1007 }
1008
1009 NTSTATUS LdrLoadGdiDriver (PUNICODE_STRING DriverName,
1010 PVOID *ImageAddress,
1011 PVOID *SectionPointer,
1012 PVOID *EntryPoint,
1013 PVOID *ExportSectionPointer)
1014 {
1015 PMODULE_OBJECT ModuleObject;
1016
1017 ModuleObject = LdrLoadModule(DriverName);
1018 if (ModuleObject == 0)
1019 {
1020 return STATUS_UNSUCCESSFUL;
1021 }
1022
1023 if (ImageAddress)
1024 *ImageAddress = ModuleObject->Base;
1025
1026 // if (SectionPointer)
1027 // *SectionPointer = ModuleObject->
1028
1029 if (EntryPoint)
1030 *EntryPoint = ModuleObject->EntryPoint;
1031
1032 // if (ExportSectionPointer)
1033 // *ExportSectionPointer = ModuleObject->
1034
1035 return STATUS_SUCCESS;
1036 }
1037
1038
1039 PMODULE_OBJECT
1040 LdrLoadModule(PUNICODE_STRING Filename)
1041 {
1042 PVOID ModuleLoadBase;
1043 NTSTATUS Status;
1044 HANDLE FileHandle;
1045 OBJECT_ATTRIBUTES ObjectAttributes;
1046 PMODULE_OBJECT ModuleObject;
1047 FILE_STANDARD_INFORMATION FileStdInfo;
1048 IO_STATUS_BLOCK IoStatusBlock;
1049
1050 /* Check for module already loaded */
1051 if ((ModuleObject = LdrOpenModule(Filename)) != NULL)
1052 {
1053 return ModuleObject;
1054 }
1055
1056 DPRINT("Loading Module %wZ...\n", Filename);
1057
1058 /* Open the Module */
1059 InitializeObjectAttributes(&ObjectAttributes,
1060 Filename,
1061 0,
1062 NULL,
1063 NULL);
1064 CHECKPOINT;
1065 Status = NtOpenFile(&FileHandle,
1066 FILE_ALL_ACCESS,
1067 &ObjectAttributes,
1068 &IoStatusBlock,
1069 0,
1070 0);
1071 CHECKPOINT;
1072 if (!NT_SUCCESS(Status))
1073 {
1074 CPRINT("Could not open module file: %wZ\n", Filename);
1075 return NULL;
1076 }
1077 CHECKPOINT;
1078
1079 /* Get the size of the file */
1080 Status = NtQueryInformationFile(FileHandle,
1081 &IoStatusBlock,
1082 &FileStdInfo,
1083 sizeof(FileStdInfo),
1084 FileStandardInformation);
1085 if (!NT_SUCCESS(Status))
1086 {
1087 CPRINT("Could not get file size\n");
1088 return NULL;
1089 }
1090 CHECKPOINT;
1091
1092 /* Allocate nonpageable memory for driver */
1093 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
1094 FileStdInfo.EndOfFile.u.LowPart,
1095 TAG_DRIVER_MEM);
1096
1097 if (ModuleLoadBase == NULL)
1098 {
1099 CPRINT("Could not allocate memory for module");
1100 return NULL;
1101 }
1102 CHECKPOINT;
1103
1104 /* Load driver into memory chunk */
1105 Status = NtReadFile(FileHandle,
1106 0, 0, 0,
1107 &IoStatusBlock,
1108 ModuleLoadBase,
1109 FileStdInfo.EndOfFile.u.LowPart,
1110 0, 0);
1111 if (!NT_SUCCESS(Status))
1112 {
1113 CPRINT("Could not read module file into memory");
1114 ExFreePool(ModuleLoadBase);
1115 return NULL;
1116 }
1117 CHECKPOINT;
1118
1119 NtClose(FileHandle);
1120
1121 Status = LdrProcessModule(ModuleLoadBase,
1122 Filename,
1123 &ModuleObject);
1124 if (!NT_SUCCESS(Status))
1125 {
1126 CPRINT("Could not process module");
1127 ExFreePool(ModuleLoadBase);
1128 return NULL;
1129 }
1130
1131 /* Cleanup */
1132 ExFreePool(ModuleLoadBase);
1133
1134 #ifdef KDBG
1135
1136 /* Load symbols for module if available */
1137 LdrpLoadModuleSymbols(ModuleObject);
1138
1139 #endif /* KDBG */
1140
1141 return ModuleObject;
1142 }
1143
1144 NTSTATUS
1145 LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName, ULONG ModuleLength)
1146 {
1147 PMODULE_OBJECT ModuleObject;
1148 UNICODE_STRING ModuleName;
1149 PDEVICE_NODE DeviceNode;
1150 NTSTATUS Status;
1151
1152 #ifdef KDBG
1153
1154 CHAR TmpBaseName[MAX_PATH];
1155 CHAR TmpFileName[MAX_PATH];
1156 ANSI_STRING AnsiString;
1157 ULONG Length;
1158 PCHAR Ext;
1159
1160 /* Split the filename into base name and extension */
1161 Ext = strrchr(FileName, '.');
1162 if (Ext != NULL)
1163 Length = Ext - FileName;
1164 else
1165 Length = strlen(FileName);
1166
1167 if ((Ext != NULL) && (strcmp(Ext, ".sym") == 0))
1168 {
1169 DPRINT("Module %s is a symbol file\n", FileName);
1170
1171 strncpy(TmpBaseName, FileName, Length);
1172 TmpBaseName[Length] = '\0';
1173
1174 DPRINT("base: %s (Length %d)\n", TmpBaseName, Length);
1175
1176 strcpy(TmpFileName, TmpBaseName);
1177 strcat(TmpFileName, ".sys");
1178 RtlInitAnsiString(&AnsiString, TmpFileName);
1179
1180 DPRINT("dasdsad: %s\n", TmpFileName);
1181
1182 RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
1183 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
1184 RtlFreeUnicodeString(&ModuleName);
1185 if (!NT_SUCCESS(Status))
1186 {
1187 strcpy(TmpFileName, TmpBaseName);
1188 strcat(TmpFileName, ".exe");
1189 RtlInitAnsiString(&AnsiString, TmpFileName);
1190 RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
1191 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
1192 RtlFreeUnicodeString(&ModuleName);
1193 }
1194 if (NT_SUCCESS(Status))
1195 {
1196 LdrpLoadModuleSymbolsFromBuffer(
1197 ModuleObject,
1198 ModuleLoadBase,
1199 ModuleLength);
1200 }
1201 return(STATUS_SUCCESS);
1202 }
1203 else
1204 {
1205 DPRINT("Module %s is executable\n", FileName);
1206 }
1207 #endif /* KDBG */
1208
1209 /* Use IopRootDeviceNode for now */
1210 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
1211 if (!NT_SUCCESS(Status))
1212 {
1213 CPRINT("Driver load failed, status (%x)\n", Status);
1214 return(Status);
1215 }
1216
1217 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1218 FileName);
1219 Status = LdrProcessModule(ModuleLoadBase,
1220 &ModuleName,
1221 &ModuleObject);
1222 RtlFreeUnicodeString(&ModuleName);
1223 if (ModuleObject == NULL)
1224 {
1225 IopFreeDeviceNode(DeviceNode);
1226 CPRINT("Driver load failed, status (%x)\n", Status);
1227 return(STATUS_UNSUCCESSFUL);
1228 }
1229
1230 Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, NULL, FALSE);
1231 if (!NT_SUCCESS(Status))
1232 {
1233 IopFreeDeviceNode(DeviceNode);
1234 CPRINT("Driver load failed, status (%x)\n", Status);
1235 }
1236
1237 return(Status);
1238 }
1239
1240 NTSTATUS
1241 LdrProcessModule(PVOID ModuleLoadBase,
1242 PUNICODE_STRING ModuleName,
1243 PMODULE_OBJECT *ModuleObject)
1244 {
1245 PIMAGE_DOS_HEADER PEDosHeader;
1246
1247 /* If MZ header exists */
1248 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1249 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
1250 {
1251 return LdrPEProcessModule(ModuleLoadBase,
1252 ModuleName,
1253 ModuleObject);
1254 }
1255
1256 CPRINT("Module wasn't PE\n");
1257 return STATUS_UNSUCCESSFUL;
1258 }
1259
1260 static PMODULE_OBJECT
1261 LdrOpenModule(PUNICODE_STRING Filename)
1262 {
1263 NTSTATUS Status;
1264 WCHAR NameBuffer[60];
1265 UNICODE_STRING ModuleName;
1266 OBJECT_ATTRIBUTES ObjectAttributes;
1267 PMODULE_OBJECT ModuleObject;
1268 UNICODE_STRING RemainingPath;
1269
1270 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1271 if (wcsrchr(Filename->Buffer, '\\') != 0)
1272 {
1273 wcscat(NameBuffer, wcsrchr(Filename->Buffer, '\\') + 1);
1274 }
1275 else
1276 {
1277 wcscat(NameBuffer, Filename->Buffer);
1278 }
1279 RtlInitUnicodeString (&ModuleName, NameBuffer);
1280 InitializeObjectAttributes(&ObjectAttributes,
1281 &ModuleName,
1282 OBJ_CASE_INSENSITIVE,
1283 NULL,
1284 NULL);
1285
1286 Status = ObFindObject(&ObjectAttributes,
1287 (PVOID *) &ModuleObject,
1288 &RemainingPath,
1289 NULL);
1290 CHECKPOINT;
1291 if (NT_SUCCESS(Status) && (RemainingPath.Buffer == NULL || *(RemainingPath.Buffer) == 0))
1292 {
1293 DPRINT("Module %wZ at %p\n", Filename, ModuleObject);
1294 RtlFreeUnicodeString (&RemainingPath);
1295
1296 return ModuleObject;
1297 }
1298
1299 RtlFreeUnicodeString (&RemainingPath);
1300
1301 return NULL;
1302 }
1303
1304 PVOID
1305 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
1306 char *Name,
1307 unsigned short Hint)
1308 {
1309 if (ModuleObject->Flags & MODULE_FLAG_PE)
1310 {
1311 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
1312 }
1313 else
1314 {
1315 return 0;
1316 }
1317 }
1318
1319 NTSTATUS
1320 LdrpQueryModuleInformation(PVOID Buffer,
1321 ULONG Size,
1322 PULONG ReqSize)
1323 {
1324 PLIST_ENTRY current_entry;
1325 PMODULE_OBJECT current;
1326 ULONG ModuleCount = 0;
1327 PSYSTEM_MODULE_INFORMATION Smi;
1328 ANSI_STRING AnsiName;
1329 PCHAR p;
1330
1331 // KeAcquireSpinLock(&ModuleListLock,&oldlvl);
1332
1333 /* calculate required size */
1334 current_entry = ModuleListHead.Flink;
1335 while (current_entry != (&ModuleListHead))
1336 {
1337 ModuleCount++;
1338 current_entry = current_entry->Flink;
1339 }
1340
1341 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
1342 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
1343
1344 if (Size < *ReqSize)
1345 {
1346 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1347 return STATUS_INFO_LENGTH_MISMATCH;
1348 }
1349
1350 /* fill the buffer */
1351 memset(Buffer, '=', Size);
1352
1353 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
1354 Smi->Count = ModuleCount;
1355
1356 ModuleCount = 0;
1357 current_entry = ModuleListHead.Flink;
1358 while (current_entry != (&ModuleListHead))
1359 {
1360 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
1361
1362 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
1363 Smi->Module[ModuleCount].BaseAddress = current->Base;
1364 Smi->Module[ModuleCount].Size = current->Length;
1365 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
1366 Smi->Module[ModuleCount].EntryIndex = ModuleCount;
1367
1368 AnsiName.Length = 0;
1369 AnsiName.MaximumLength = 256;
1370 AnsiName.Buffer = Smi->Module[ModuleCount].Name;
1371 RtlUnicodeStringToAnsiString(&AnsiName,
1372 &current->FullName,
1373 FALSE);
1374
1375 p = strrchr (AnsiName.Buffer, '\\');
1376 if (p == NULL)
1377 {
1378 Smi->Module[ModuleCount].PathLength = 0;
1379 Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
1380 }
1381 else
1382 {
1383 p++;
1384 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
1385 Smi->Module[ModuleCount].NameLength = strlen(p);
1386 }
1387
1388 ModuleCount++;
1389 current_entry = current_entry->Flink;
1390 }
1391
1392 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1393
1394 return STATUS_SUCCESS;
1395 }
1396
1397
1398 static VOID
1399 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
1400 PUNICODE_STRING FullName)
1401 {
1402 UNICODE_STRING Name;
1403 PWCHAR p;
1404 PWCHAR q;
1405
1406 DPRINT("LdrpBuildModuleBaseName()\n");
1407 DPRINT("FullName %wZ\n", FullName);
1408
1409 p = wcsrchr(FullName->Buffer, '\\');
1410 if (p == NULL)
1411 {
1412 p = FullName->Buffer;
1413 }
1414 else
1415 {
1416 p++;
1417 }
1418
1419 DPRINT("p %S\n", p);
1420
1421 RtlCreateUnicodeString(&Name, p);
1422
1423 q = wcschr(p, '.');
1424 if (q != NULL)
1425 {
1426 *q = (WCHAR)0;
1427 }
1428
1429 DPRINT("p %S\n", p);
1430
1431 RtlCreateUnicodeString(BaseName, p);
1432 RtlFreeUnicodeString(&Name);
1433 }
1434
1435
1436 /* ---------------------------------------------- PE Module support */
1437
1438 static NTSTATUS
1439 LdrPEProcessModule(PVOID ModuleLoadBase,
1440 PUNICODE_STRING FileName,
1441 PMODULE_OBJECT *ModuleObject)
1442 {
1443 unsigned int DriverSize, Idx, Idx2;
1444 ULONG RelocDelta, NumRelocs;
1445 DWORD CurrentSize, TotalRelocs;
1446 PVOID DriverBase;
1447 PULONG PEMagic;
1448 PIMAGE_DOS_HEADER PEDosHeader;
1449 PIMAGE_FILE_HEADER PEFileHeader;
1450 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1451 PIMAGE_SECTION_HEADER PESectionHeaders;
1452 PRELOCATION_DIRECTORY RelocDir;
1453 PRELOCATION_ENTRY RelocEntry;
1454 PMODULE_OBJECT LibraryModuleObject;
1455 HANDLE ModuleHandle;
1456 PMODULE_OBJECT CreatedModuleObject;
1457 PVOID *ImportAddressList;
1458 PULONG FunctionNameList;
1459 PCHAR pName;
1460 WORD Hint;
1461 OBJECT_ATTRIBUTES ObjectAttributes;
1462 UNICODE_STRING ModuleName;
1463 WCHAR NameBuffer[60];
1464 MODULE_TEXT_SECTION* ModuleTextSection;
1465 NTSTATUS Status;
1466
1467 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1468
1469 /* Get header pointers */
1470 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1471 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1472 PEDosHeader->e_lfanew);
1473 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1474 PEDosHeader->e_lfanew + sizeof(ULONG));
1475 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1476 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1477 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1478 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1479 sizeof(IMAGE_OPTIONAL_HEADER));
1480 CHECKPOINT;
1481
1482 /* Check file magic numbers */
1483 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1484 {
1485 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
1486 return STATUS_UNSUCCESSFUL;
1487 }
1488 if (PEDosHeader->e_lfanew == 0)
1489 {
1490 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
1491 return STATUS_UNSUCCESSFUL;
1492 }
1493 if (*PEMagic != IMAGE_PE_MAGIC)
1494 {
1495 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
1496 return STATUS_UNSUCCESSFUL;
1497 }
1498 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1499 {
1500 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
1501 return STATUS_UNSUCCESSFUL;
1502 }
1503 CHECKPOINT;
1504
1505 /* FIXME: if image is fixed-address load, then fail */
1506
1507 /* FIXME: check/verify OS version number */
1508
1509 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1510 PEOptionalHeader->Magic,
1511 PEOptionalHeader->MajorLinkerVersion,
1512 PEOptionalHeader->MinorLinkerVersion);
1513 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1514 CHECKPOINT;
1515
1516 /* Determine the size of the module */
1517 DriverSize = PEOptionalHeader->SizeOfImage;
1518 DPRINT("DriverSize %x\n",DriverSize);
1519
1520 /* Allocate a virtual section for the module */
1521 DriverBase = MmAllocateSection(DriverSize);
1522 if (DriverBase == 0)
1523 {
1524 CPRINT("Failed to allocate a virtual section for driver\n");
1525 return STATUS_UNSUCCESSFUL;
1526 }
1527 CPRINT("DriverBase: %x\n", DriverBase);
1528 CHECKPOINT;
1529 /* Copy headers over */
1530 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1531 CurrentSize = 0;
1532 /* Copy image sections into virtual section */
1533 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1534 {
1535 // Copy current section into current offset of virtual section
1536 if (PESectionHeaders[Idx].Characteristics &
1537 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1538 {
1539 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1540 PESectionHeaders[Idx].VirtualAddress + DriverBase);
1541 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1542 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1543 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1544 }
1545 else
1546 {
1547 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1548 PESectionHeaders[Idx].VirtualAddress + DriverBase);
1549 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1550 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
1551
1552 }
1553 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1554 PEOptionalHeader->SectionAlignment);
1555
1556
1557 // CurrentBase = (PVOID)((DWORD)CurrentBase +
1558 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
1559 // PEOptionalHeader->SectionAlignment));
1560 }
1561
1562 /* Perform relocation fixups */
1563 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
1564 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1565 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1566 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1567 DriverBase,
1568 PEOptionalHeader->ImageBase,
1569 RelocDelta);
1570 DPRINT("RelocDir %x\n",RelocDir);
1571 #if 1
1572 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1573 {
1574 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1575 {
1576 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1577 PESectionHeaders[Idx].Name,
1578 PESectionHeaders[Idx].PointerToRawData);
1579 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1580 ModuleLoadBase;
1581 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1582 break;
1583 }
1584 }
1585 #else
1586 RelocDir = RelocDir + (ULONG)DriverBase;
1587 CurrentSize = PEOptionalHeader->DataDirectory
1588 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1589 #endif
1590 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1591 TotalRelocs = 0;
1592 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1593 {
1594 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1595 sizeof(WORD);
1596 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1597 RelocDir,
1598 RelocDir->VirtualAddress,
1599 NumRelocs);*/
1600 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1601 sizeof(RELOCATION_DIRECTORY));
1602 for (Idx = 0; Idx < NumRelocs; Idx++)
1603 {
1604 ULONG Offset;
1605 ULONG Type;
1606 PDWORD RelocItem;
1607
1608 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1609 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1610 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1611 Offset);
1612 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1613 RelocItem,
1614 Type,
1615 Type ? "HIGHLOW" : "ABS",
1616 *RelocItem,
1617 (*RelocItem) + RelocDelta); */
1618 if (Type == 3)
1619 {
1620 (*RelocItem) += RelocDelta;
1621 }
1622 else if (Type != 0)
1623 {
1624 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1625 return STATUS_UNSUCCESSFUL;
1626 }
1627 }
1628 TotalRelocs += RelocDir->SizeOfBlock;
1629 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1630 RelocDir->SizeOfBlock);
1631 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1632 }
1633
1634 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1635 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1636 .VirtualAddress);
1637 /* Perform import fixups */
1638 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1639 {
1640 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1641
1642 /* Process each import module */
1643 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1644 ((DWORD)DriverBase + PEOptionalHeader->
1645 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1646 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1647 while (ImportModuleDirectory->dwRVAModuleName)
1648 {
1649 /* Check to make sure that import lib is kernel */
1650 pName = (PCHAR) DriverBase +
1651 ImportModuleDirectory->dwRVAModuleName;
1652 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1653
1654 for (Idx = 0; NameBuffer[Idx] != 0; Idx++);
1655 for (Idx2 = 0; pName[Idx2] != '\0'; Idx2++)
1656 {
1657 NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
1658 }
1659 NameBuffer[Idx + Idx2] = 0;
1660
1661 RtlInitUnicodeString (&ModuleName, NameBuffer);
1662 DPRINT("Import module: %wZ\n", &ModuleName);
1663
1664 LibraryModuleObject = LdrLoadModule(&ModuleName);
1665 if (LibraryModuleObject == 0)
1666 {
1667 CPRINT("Unknown import module: %wZ\n", &ModuleName);
1668 }
1669 /* Get the import address list */
1670 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1671 ImportModuleDirectory->dwRVAFunctionAddressList);
1672
1673 /* Get the list of functions to import */
1674 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1675 {
1676 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1677 ImportModuleDirectory->dwRVAFunctionNameList);
1678 }
1679 else
1680 {
1681 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1682 ImportModuleDirectory->dwRVAFunctionAddressList);
1683 }
1684 /* Walk through function list and fixup addresses */
1685 while (*FunctionNameList != 0L)
1686 {
1687 if ((*FunctionNameList) & 0x80000000) // hint
1688 {
1689 pName = NULL;
1690
1691
1692 Hint = (*FunctionNameList) & 0xffff;
1693 }
1694 else // hint-name
1695 {
1696 pName = (PCHAR)((DWORD)DriverBase +
1697 *FunctionNameList + 2);
1698 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1699 }
1700 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1701
1702 /* Fixup the current import symbol */
1703 if (LibraryModuleObject != NULL)
1704 {
1705 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1706 pName,
1707 Hint);
1708 }
1709 else
1710 {
1711 CPRINT("Unresolved kernel symbol: %s\n", pName);
1712 return STATUS_UNSUCCESSFUL;
1713 }
1714 ImportAddressList++;
1715 FunctionNameList++;
1716 }
1717 ImportModuleDirectory++;
1718 }
1719 }
1720
1721 /* Create ModuleName string */
1722 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1723 if (wcsrchr(FileName->Buffer, '\\') != 0)
1724 {
1725 wcscat(NameBuffer, wcsrchr(FileName->Buffer, '\\') + 1);
1726 }
1727 else
1728 {
1729 wcscat(NameBuffer, FileName->Buffer);
1730 }
1731 RtlInitUnicodeString (&ModuleName, NameBuffer);
1732 CPRINT("Module name is: %wZ\n", &ModuleName);
1733
1734 /* Initialize ObjectAttributes for ModuleObject */
1735 InitializeObjectAttributes(&ObjectAttributes,
1736 &ModuleName,
1737 0,
1738 NULL,
1739 NULL);
1740
1741 /* Create module object */
1742 ModuleHandle = 0;
1743 Status = ObCreateObject(&ModuleHandle,
1744 STANDARD_RIGHTS_REQUIRED,
1745 &ObjectAttributes,
1746 IoDriverObjectType,
1747 (PVOID*)&CreatedModuleObject);
1748 if (!NT_SUCCESS(Status))
1749 {
1750 return(Status);
1751 }
1752
1753 /* Initialize ModuleObject data */
1754 CreatedModuleObject->Base = DriverBase;
1755 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1756 InsertTailList(&ModuleListHead,
1757 &CreatedModuleObject->ListEntry);
1758 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1759 FileName->Buffer);
1760 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1761 &CreatedModuleObject->FullName);
1762
1763 CreatedModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase +
1764 PEOptionalHeader->AddressOfEntryPoint);
1765 CreatedModuleObject->Length = DriverSize;
1766 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1767
1768 CreatedModuleObject->Image.PE.FileHeader =
1769 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1770
1771 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1772 CreatedModuleObject->Image.PE.OptionalHeader =
1773 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1774 sizeof(IMAGE_FILE_HEADER));
1775 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1776 CreatedModuleObject->Image.PE.SectionList =
1777 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1778 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1779 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1780
1781 ModuleTextSection = ExAllocatePool(NonPagedPool,
1782 sizeof(MODULE_TEXT_SECTION));
1783 ModuleTextSection->Base = (ULONG)DriverBase;
1784 ModuleTextSection->Length = DriverSize;
1785 ModuleTextSection->SymbolsBase = NULL;
1786 ModuleTextSection->SymbolsLength = 0;
1787 ModuleTextSection->Name =
1788 ExAllocatePool(NonPagedPool,
1789 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
1790 wcscpy(ModuleTextSection->Name, NameBuffer);
1791 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1792
1793 CreatedModuleObject->TextSection = ModuleTextSection;
1794
1795 *ModuleObject = CreatedModuleObject;
1796
1797 return STATUS_SUCCESS;
1798 }
1799
1800 PVOID LdrSafePEProcessModule(
1801 PVOID ModuleLoadBase,
1802 PVOID DriverBase,
1803 PVOID ImportModuleBase,
1804 PULONG DriverSize)
1805 {
1806 unsigned int Idx, Idx2;
1807 ULONG RelocDelta, NumRelocs;
1808 DWORD CurrentSize, TotalRelocs;
1809 PULONG PEMagic;
1810 PIMAGE_DOS_HEADER PEDosHeader;
1811 PIMAGE_FILE_HEADER PEFileHeader;
1812 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1813 PIMAGE_SECTION_HEADER PESectionHeaders;
1814 PRELOCATION_DIRECTORY RelocDir;
1815 PRELOCATION_ENTRY RelocEntry;
1816 PVOID *ImportAddressList;
1817 PULONG FunctionNameList;
1818 PCHAR pName;
1819 WORD Hint;
1820 UNICODE_STRING ModuleName;
1821 WCHAR NameBuffer[60];
1822
1823 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1824
1825 /* Get header pointers */
1826 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1827 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1828 PEDosHeader->e_lfanew);
1829 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1830 PEDosHeader->e_lfanew + sizeof(ULONG));
1831 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1832 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1833 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1834 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1835 sizeof(IMAGE_OPTIONAL_HEADER));
1836 CHECKPOINT;
1837
1838 /* Check file magic numbers */
1839 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1840 {
1841 return 0;
1842 }
1843 if (PEDosHeader->e_lfanew == 0)
1844 {
1845 return 0;
1846 }
1847 if (*PEMagic != IMAGE_PE_MAGIC)
1848 {
1849 return 0;
1850 }
1851 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1852 {
1853 return 0;
1854 }
1855
1856 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1857 PEOptionalHeader->Magic,
1858 PEOptionalHeader->MajorLinkerVersion,
1859 PEOptionalHeader->MinorLinkerVersion);
1860 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1861
1862 /* Determine the size of the module */
1863 *DriverSize = PEOptionalHeader->SizeOfImage;
1864 ps("DriverSize %x\n",*DriverSize);
1865
1866 /* Copy headers over */
1867 if (DriverBase != ModuleLoadBase)
1868 {
1869 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1870 }
1871
1872 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1873 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1874 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1875
1876 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1877 address as it is mapped */
1878 if (DriverBase != ModuleLoadBase)
1879 {
1880 CurrentSize = 0;
1881
1882 /* Copy image sections into virtual section */
1883 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1884 {
1885 // Copy current section into current offset of virtual section
1886 if (PESectionHeaders[Idx].Characteristics &
1887 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1888 {
1889 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1890 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1891 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1892 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1893 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1894 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1895 }
1896 else
1897 {
1898 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1899 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1900 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1901 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
1902
1903 }
1904 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1905 PEOptionalHeader->SectionAlignment);
1906 }
1907
1908 /* Perform relocation fixups */
1909 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
1910 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1911 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1912 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1913 DriverBase,
1914 PEOptionalHeader->ImageBase,
1915 RelocDelta);
1916 ps("RelocDir %x\n",RelocDir);
1917
1918 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1919 {
1920 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1921 {
1922 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1923 PESectionHeaders[Idx].Name,
1924 PESectionHeaders[Idx].PointerToRawData);
1925 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1926 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1927 break;
1928 }
1929 }
1930
1931 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1932
1933 TotalRelocs = 0;
1934 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1935 {
1936 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1937 sizeof(WORD);
1938 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1939 sizeof(RELOCATION_DIRECTORY));
1940 for (Idx = 0; Idx < NumRelocs; Idx++)
1941 {
1942 ULONG Offset;
1943 ULONG Type;
1944 PDWORD RelocItem;
1945
1946 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1947 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1948 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1949 Offset);
1950 if (Type == 3)
1951 {
1952 (*RelocItem) += RelocDelta;
1953 }
1954 else if (Type != 0)
1955 {
1956 DbgPrint("Unknown relocation type %x at %x\n",Type, &Type);
1957 return 0;
1958 }
1959 }
1960 TotalRelocs += RelocDir->SizeOfBlock;
1961 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1962 RelocDir->SizeOfBlock);
1963 }
1964
1965 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1966 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1967 .VirtualAddress);
1968 }
1969
1970 /* Perform import fixups */
1971 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1972 {
1973 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1974
1975 /* Process each import module */
1976 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1977 ((DWORD)DriverBase + PEOptionalHeader->
1978 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1979
1980 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1981
1982 {
1983 /* Check to make sure that import lib is kernel */
1984 pName = (PCHAR) DriverBase +
1985 ImportModuleDirectory->dwRVAModuleName;
1986 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1987 for (Idx = 0; NameBuffer[Idx] != 0; Idx++);
1988 for (Idx2 = 0; pName[Idx2] != '\0'; Idx2++)
1989 {
1990 NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
1991 }
1992 NameBuffer[Idx + Idx2] = 0;
1993 RtlInitUnicodeString (&ModuleName, NameBuffer);
1994
1995
1996 ps("Import module: %wZ\n", &ModuleName);
1997
1998 /* Get the import address list */
1999 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
2000 ImportModuleDirectory->dwRVAFunctionAddressList);
2001
2002 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
2003 ImportModuleDirectory->dwRVAFunctionAddressList);
2004 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
2005
2006 /* Get the list of functions to import */
2007 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
2008 {
2009
2010 ps("Using function name list.\n");
2011
2012 FunctionNameList = (PULONG) ((DWORD)DriverBase +
2013 ImportModuleDirectory->dwRVAFunctionNameList);
2014 }
2015 else
2016 {
2017
2018 ps("Using function address list.\n");
2019
2020 FunctionNameList = (PULONG) ((DWORD)DriverBase +
2021 ImportModuleDirectory->dwRVAFunctionAddressList);
2022 }
2023
2024 /* Walk through function list and fixup addresses */
2025 while (*FunctionNameList != 0L)
2026 {
2027 if ((*FunctionNameList) & 0x80000000) // hint
2028 {
2029 pName = NULL;
2030
2031 Hint = (*FunctionNameList) & 0xffff;
2032 }
2033 else // hint-name
2034 {
2035 pName = (PCHAR)((DWORD)DriverBase +
2036 *FunctionNameList + 2);
2037 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
2038 }
2039 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
2040
2041 *ImportAddressList = LdrSafePEGetExportAddress(
2042 ImportModuleBase,
2043 pName,
2044 Hint);
2045
2046 ImportAddressList++;
2047 FunctionNameList++;
2048 }
2049 ImportModuleDirectory++;
2050 }
2051 }
2052
2053 ps("Finished importing.\n");
2054
2055 return 0;
2056 }
2057
2058 static PVOID
2059 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
2060 char *Name,
2061 unsigned short Hint)
2062 {
2063 WORD Idx;
2064 PVOID ExportAddress;
2065 PWORD OrdinalList;
2066 PDWORD FunctionList, NameList;
2067 PIMAGE_EXPORT_DIRECTORY ExportDir;
2068 ULONG ExportDirSize;
2069
2070 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
2071 RtlImageDirectoryEntryToData(ModuleObject->Base,
2072 TRUE,
2073 IMAGE_DIRECTORY_ENTRY_EXPORT,
2074 &ExportDirSize);
2075 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
2076 if (ExportDir == NULL)
2077 {
2078 return NULL;
2079 }
2080
2081 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
2082 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
2083 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
2084
2085 ExportAddress = 0;
2086
2087 if (Name != NULL)
2088 {
2089 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
2090 {
2091 #if 0
2092 DPRINT(" Name:%s NameList[%d]:%s\n",
2093 Name,
2094 Idx,
2095 (DWORD) ModuleObject->Base + NameList[Idx]);
2096
2097 #endif
2098 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
2099 {
2100 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
2101 FunctionList[OrdinalList[Idx]]);
2102 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
2103 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
2104 {
2105 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
2106 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
2107 DPRINT("ExportAddress: %p\n", ExportAddress);
2108 }
2109
2110 break;
2111 }
2112 }
2113 }
2114 else /* use hint */
2115 {
2116 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
2117 FunctionList[Hint - ExportDir->Base]);
2118 }
2119
2120 if (ExportAddress == 0)
2121 {
2122 CPRINT("Export not found for %d:%s\n",
2123 Hint,
2124 Name != NULL ? Name : "(Ordinal)");
2125 KeBugCheck(0);
2126 }
2127
2128 return ExportAddress;
2129 }
2130
2131 static PVOID
2132 LdrSafePEGetExportAddress(
2133 PVOID ImportModuleBase,
2134 char *Name,
2135 unsigned short Hint)
2136 {
2137 WORD Idx;
2138 PVOID ExportAddress;
2139 PWORD OrdinalList;
2140 PDWORD FunctionList, NameList;
2141 PIMAGE_EXPORT_DIRECTORY ExportDir;
2142 ULONG ExportDirSize;
2143
2144 static BOOLEAN EP = FALSE;
2145
2146 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
2147 RtlImageDirectoryEntryToData(ImportModuleBase,
2148 TRUE,
2149 IMAGE_DIRECTORY_ENTRY_EXPORT,
2150 &ExportDirSize);
2151
2152 if (!EP) {
2153 EP = TRUE;
2154 ps("ExportDir %x\n", ExportDir);
2155 }
2156
2157 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
2158 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
2159 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
2160
2161 ExportAddress = 0;
2162
2163 if (Name != NULL)
2164 {
2165 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
2166 {
2167 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
2168 {
2169 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
2170 FunctionList[OrdinalList[Idx]]);
2171 break;
2172 }
2173 }
2174 }
2175 else /* use hint */
2176 {
2177 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
2178 FunctionList[Hint - ExportDir->Base]);
2179 }
2180
2181 if (ExportAddress == 0)
2182 {
2183 ps("Export not found for %d:%s\n",
2184 Hint,
2185 Name != NULL ? Name : "(Ordinal)");
2186 for (;;);
2187 }
2188 return ExportAddress;
2189 }
2190
2191
2192 static PMODULE_OBJECT
2193 LdrPEGetModuleObject(PUNICODE_STRING ModuleName)
2194 {
2195 PLIST_ENTRY Entry;
2196 PMODULE_OBJECT Module;
2197
2198 DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
2199 ModuleName);
2200
2201 Entry = ModuleListHead.Flink;
2202
2203 while (Entry != &ModuleListHead)
2204 {
2205 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
2206
2207 DPRINT("Comparing %wZ and %wZ\n",
2208 &Module->BaseName,
2209 ModuleName);
2210
2211 if (!RtlCompareUnicodeString(&Module->BaseName, ModuleName, TRUE))
2212 {
2213 DPRINT("Module %x\n", Module);
2214 return Module;
2215 }
2216
2217 Entry = Entry->Flink;
2218 }
2219
2220 CPRINT("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName);
2221
2222 return NULL;
2223 }
2224
2225
2226 static PVOID
2227 LdrPEFixupForward(PCHAR ForwardName)
2228 {
2229 CHAR NameBuffer[128];
2230 UNICODE_STRING ModuleName;
2231 PCHAR p;
2232 PMODULE_OBJECT ModuleObject;
2233
2234 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
2235
2236 strcpy(NameBuffer, ForwardName);
2237 p = strchr(NameBuffer, '.');
2238 if (p == NULL)
2239 {
2240 return NULL;
2241 }
2242
2243 *p = 0;
2244
2245 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
2246
2247 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
2248 NameBuffer);
2249 ModuleObject = LdrPEGetModuleObject(&ModuleName);
2250 RtlFreeUnicodeString(&ModuleName);
2251
2252 DPRINT("ModuleObject: %p\n", ModuleObject);
2253
2254 if (ModuleObject == NULL)
2255 {
2256 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
2257 return NULL;
2258 }
2259
2260 return LdrPEGetExportAddress(ModuleObject, p+1, 0);
2261 }
2262
2263 /* EOF */