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