* Call RtlCreateUnicodeString() instead of RtlInitUnicodeString() when
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
1 /* $Id: loader.c,v 1.109 2002/06/12 14:05:03 chorns 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 RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer);
1107
1108 Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode);
1109 if (!NT_SUCCESS(Status))
1110 {
1111 IopFreeDeviceNode(DeviceNode);
1112 CPRINT("Driver load failed, status (%x)\n", Status);
1113 }
1114
1115 return(Status);
1116 }
1117
1118
1119 NTSTATUS
1120 LdrProcessModule(PVOID ModuleLoadBase,
1121 PUNICODE_STRING ModuleName,
1122 PMODULE_OBJECT *ModuleObject)
1123 {
1124 PIMAGE_DOS_HEADER PEDosHeader;
1125
1126 /* If MZ header exists */
1127 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1128 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
1129 {
1130 return LdrPEProcessModule(ModuleLoadBase,
1131 ModuleName,
1132 ModuleObject);
1133 }
1134
1135 CPRINT("Module wasn't PE\n");
1136 return STATUS_UNSUCCESSFUL;
1137 }
1138
1139
1140 PVOID
1141 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
1142 char *Name,
1143 unsigned short Hint)
1144 {
1145 if (ModuleObject->Flags & MODULE_FLAG_PE)
1146 {
1147 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
1148 }
1149 else
1150 {
1151 return 0;
1152 }
1153 }
1154
1155
1156 NTSTATUS
1157 LdrpQueryModuleInformation(PVOID Buffer,
1158 ULONG Size,
1159 PULONG ReqSize)
1160 {
1161 PLIST_ENTRY current_entry;
1162 PMODULE_OBJECT current;
1163 ULONG ModuleCount = 0;
1164 PSYSTEM_MODULE_INFORMATION Smi;
1165 ANSI_STRING AnsiName;
1166 PCHAR p;
1167 KIRQL Irql;
1168
1169 KeAcquireSpinLock(&ModuleListLock,&Irql);
1170
1171 /* calculate required size */
1172 current_entry = ModuleListHead.Flink;
1173 while (current_entry != (&ModuleListHead))
1174 {
1175 ModuleCount++;
1176 current_entry = current_entry->Flink;
1177 }
1178
1179 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
1180 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
1181
1182 if (Size < *ReqSize)
1183 {
1184 KeReleaseSpinLock(&ModuleListLock, Irql);
1185 return(STATUS_INFO_LENGTH_MISMATCH);
1186 }
1187
1188 /* fill the buffer */
1189 memset(Buffer, '=', Size);
1190
1191 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
1192 Smi->Count = ModuleCount;
1193
1194 ModuleCount = 0;
1195 current_entry = ModuleListHead.Flink;
1196 while (current_entry != (&ModuleListHead))
1197 {
1198 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
1199
1200 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
1201 Smi->Module[ModuleCount].BaseAddress = current->Base;
1202 Smi->Module[ModuleCount].Size = current->Length;
1203 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
1204 Smi->Module[ModuleCount].EntryIndex = ModuleCount;
1205
1206 AnsiName.Length = 0;
1207 AnsiName.MaximumLength = 256;
1208 AnsiName.Buffer = Smi->Module[ModuleCount].Name;
1209 RtlUnicodeStringToAnsiString(&AnsiName,
1210 &current->FullName,
1211 FALSE);
1212
1213 p = strrchr(AnsiName.Buffer, '\\');
1214 if (p == NULL)
1215 {
1216 Smi->Module[ModuleCount].PathLength = 0;
1217 Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
1218 }
1219 else
1220 {
1221 p++;
1222 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
1223 Smi->Module[ModuleCount].NameLength = strlen(p);
1224 }
1225
1226 ModuleCount++;
1227 current_entry = current_entry->Flink;
1228 }
1229
1230 KeReleaseSpinLock(&ModuleListLock, Irql);
1231
1232 return(STATUS_SUCCESS);
1233 }
1234
1235
1236 static VOID
1237 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
1238 PUNICODE_STRING FullName)
1239 {
1240 UNICODE_STRING Name;
1241 PWCHAR p;
1242 PWCHAR q;
1243
1244 DPRINT("LdrpBuildModuleBaseName()\n");
1245 DPRINT("FullName %wZ\n", FullName);
1246
1247 p = wcsrchr(FullName->Buffer, L'\\');
1248 if (p == NULL)
1249 {
1250 p = FullName->Buffer;
1251 }
1252 else
1253 {
1254 p++;
1255 }
1256
1257 DPRINT("p %S\n", p);
1258
1259 RtlCreateUnicodeString(&Name, p);
1260
1261 q = wcschr(Name.Buffer, L'.');
1262 if (q != NULL)
1263 {
1264 *q = (WCHAR)0;
1265 }
1266
1267 DPRINT("p %S\n", p);
1268
1269 RtlCreateUnicodeString(BaseName, Name.Buffer);
1270 RtlFreeUnicodeString(&Name);
1271 }
1272
1273
1274 static LONG
1275 LdrpCompareModuleNames(IN PUNICODE_STRING String1,
1276 IN PUNICODE_STRING String2)
1277 {
1278 ULONG len1, len2, i;
1279 PWCHAR s1, s2, p;
1280 WCHAR c1, c2;
1281
1282 if (String1 && String2)
1283 {
1284 /* Search String1 for last path component */
1285 len1 = String1->Length / sizeof(WCHAR);
1286 s1 = String1->Buffer;
1287 for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++)
1288 {
1289 if (*p == L'\\')
1290 {
1291 if (i == String1->Length - sizeof(WCHAR))
1292 {
1293 s1 = NULL;
1294 len1 = 0;
1295 }
1296 else
1297 {
1298 s1 = p + 1;
1299 len1 = (String1->Length - i) / sizeof(WCHAR);
1300 }
1301 }
1302 }
1303
1304 /* Search String2 for last path component */
1305 len2 = String2->Length / sizeof(WCHAR);
1306 s2 = String2->Buffer;
1307 for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++)
1308 {
1309 if (*p == L'\\')
1310 {
1311 if (i == String2->Length - sizeof(WCHAR))
1312 {
1313 s2 = NULL;
1314 len2 = 0;
1315 }
1316 else
1317 {
1318 s2 = p + 1;
1319 len2 = (String2->Length - i) / sizeof(WCHAR);
1320 }
1321 }
1322 }
1323
1324 /* Compare last path components */
1325 if (s1 && s2)
1326 {
1327 while (1)
1328 {
1329 c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0;
1330 c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0;
1331 if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0))
1332 return(0);
1333 if (!c1 || !c2 || c1 != c2)
1334 return(c1 - c2);
1335 }
1336 }
1337 }
1338
1339 return(0);
1340 }
1341
1342
1343 PMODULE_OBJECT
1344 LdrGetModuleObject(PUNICODE_STRING ModuleName)
1345 {
1346 PMODULE_OBJECT Module;
1347 PLIST_ENTRY Entry;
1348 KIRQL Irql;
1349
1350 DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName);
1351
1352 KeAcquireSpinLock(&ModuleListLock,&Irql);
1353
1354 Entry = ModuleListHead.Flink;
1355 while (Entry != &ModuleListHead)
1356 {
1357 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
1358
1359 DPRINT("Comparing %wZ and %wZ\n",
1360 &Module->BaseName,
1361 ModuleName);
1362
1363 if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName))
1364 {
1365 DPRINT("Module %wZ\n", &Module->BaseName);
1366 KeReleaseSpinLock(&ModuleListLock, Irql);
1367 return(Module);
1368 }
1369
1370 Entry = Entry->Flink;
1371 }
1372
1373 KeReleaseSpinLock(&ModuleListLock, Irql);
1374
1375 CPRINT("LdrpGetModuleObject: Failed to find dll %wZ\n", ModuleName);
1376
1377 return(NULL);
1378 }
1379
1380
1381 /* ---------------------------------------------- PE Module support */
1382
1383 static NTSTATUS
1384 LdrPEProcessModule(PVOID ModuleLoadBase,
1385 PUNICODE_STRING FileName,
1386 PMODULE_OBJECT *ModuleObject)
1387 {
1388 unsigned int DriverSize, Idx;
1389 ULONG RelocDelta, NumRelocs;
1390 DWORD CurrentSize, TotalRelocs;
1391 PVOID DriverBase;
1392 PULONG PEMagic;
1393 PIMAGE_DOS_HEADER PEDosHeader;
1394 PIMAGE_FILE_HEADER PEFileHeader;
1395 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1396 PIMAGE_SECTION_HEADER PESectionHeaders;
1397 PRELOCATION_DIRECTORY RelocDir;
1398 PRELOCATION_ENTRY RelocEntry;
1399 PMODULE_OBJECT LibraryModuleObject;
1400 PMODULE_OBJECT CreatedModuleObject;
1401 PVOID *ImportAddressList;
1402 PULONG FunctionNameList;
1403 PCHAR pName;
1404 WORD Hint;
1405 UNICODE_STRING ModuleName;
1406 WCHAR NameBuffer[60];
1407 MODULE_TEXT_SECTION* ModuleTextSection;
1408 NTSTATUS Status;
1409 KIRQL Irql;
1410
1411 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1412
1413 /* Get header pointers */
1414 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1415 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1416 PEDosHeader->e_lfanew);
1417 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1418 PEDosHeader->e_lfanew + sizeof(ULONG));
1419 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1420 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1421 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1422 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1423 sizeof(IMAGE_OPTIONAL_HEADER));
1424 CHECKPOINT;
1425
1426 /* Check file magic numbers */
1427 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1428 {
1429 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
1430 return STATUS_UNSUCCESSFUL;
1431 }
1432 if (PEDosHeader->e_lfanew == 0)
1433 {
1434 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
1435 return STATUS_UNSUCCESSFUL;
1436 }
1437 if (*PEMagic != IMAGE_PE_MAGIC)
1438 {
1439 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
1440 return STATUS_UNSUCCESSFUL;
1441 }
1442 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1443 {
1444 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
1445 return STATUS_UNSUCCESSFUL;
1446 }
1447 CHECKPOINT;
1448
1449 /* FIXME: if image is fixed-address load, then fail */
1450
1451 /* FIXME: check/verify OS version number */
1452
1453 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1454 PEOptionalHeader->Magic,
1455 PEOptionalHeader->MajorLinkerVersion,
1456 PEOptionalHeader->MinorLinkerVersion);
1457 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1458 CHECKPOINT;
1459
1460 /* Determine the size of the module */
1461 DriverSize = PEOptionalHeader->SizeOfImage;
1462 DPRINT("DriverSize %x\n",DriverSize);
1463
1464 /* Allocate a virtual section for the module */
1465 DriverBase = MmAllocateSection(DriverSize);
1466 if (DriverBase == 0)
1467 {
1468 CPRINT("Failed to allocate a virtual section for driver\n");
1469 return STATUS_UNSUCCESSFUL;
1470 }
1471 CPRINT("DriverBase: %x\n", DriverBase);
1472 CHECKPOINT;
1473 /* Copy headers over */
1474 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1475 CurrentSize = 0;
1476 /* Copy image sections into virtual section */
1477 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1478 {
1479 // Copy current section into current offset of virtual section
1480 if (PESectionHeaders[Idx].Characteristics &
1481 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1482 {
1483 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1484 PESectionHeaders[Idx].VirtualAddress + DriverBase);
1485 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1486 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1487 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1488 }
1489 else
1490 {
1491 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1492 PESectionHeaders[Idx].VirtualAddress + DriverBase);
1493 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1494 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
1495
1496 }
1497 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1498 PEOptionalHeader->SectionAlignment);
1499
1500
1501 // CurrentBase = (PVOID)((DWORD)CurrentBase +
1502 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
1503 // PEOptionalHeader->SectionAlignment));
1504 }
1505
1506 /* Perform relocation fixups */
1507 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
1508 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1509 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1510 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1511 DriverBase,
1512 PEOptionalHeader->ImageBase,
1513 RelocDelta);
1514 DPRINT("RelocDir %x\n",RelocDir);
1515 #if 1
1516 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1517 {
1518 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1519 {
1520 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1521 PESectionHeaders[Idx].Name,
1522 PESectionHeaders[Idx].PointerToRawData);
1523 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1524 ModuleLoadBase;
1525 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1526 break;
1527 }
1528 }
1529 #else
1530 RelocDir = RelocDir + (ULONG)DriverBase;
1531 CurrentSize = PEOptionalHeader->DataDirectory
1532 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1533 #endif
1534 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1535 TotalRelocs = 0;
1536 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1537 {
1538 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1539 sizeof(WORD);
1540 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1541 RelocDir,
1542 RelocDir->VirtualAddress,
1543 NumRelocs);*/
1544 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1545 sizeof(RELOCATION_DIRECTORY));
1546 for (Idx = 0; Idx < NumRelocs; Idx++)
1547 {
1548 ULONG Offset;
1549 ULONG Type;
1550 PDWORD RelocItem;
1551
1552 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1553 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1554 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1555 Offset);
1556 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1557 RelocItem,
1558 Type,
1559 Type ? "HIGHLOW" : "ABS",
1560 *RelocItem,
1561 (*RelocItem) + RelocDelta); */
1562 if (Type == 3)
1563 {
1564 (*RelocItem) += RelocDelta;
1565 }
1566 else if (Type != 0)
1567 {
1568 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1569 return STATUS_UNSUCCESSFUL;
1570 }
1571 }
1572 TotalRelocs += RelocDir->SizeOfBlock;
1573 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1574 RelocDir->SizeOfBlock);
1575 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1576 }
1577
1578 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1579 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1580 .VirtualAddress);
1581 /* Perform import fixups */
1582 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1583 {
1584 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1585
1586 /* Process each import module */
1587 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1588 ((DWORD)DriverBase + PEOptionalHeader->
1589 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1590 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1591 while (ImportModuleDirectory->dwRVAModuleName)
1592 {
1593 /* Check to make sure that import lib is kernel */
1594 pName = (PCHAR) DriverBase +
1595 ImportModuleDirectory->dwRVAModuleName;
1596
1597 RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName);
1598 DPRINT("Import module: %wZ\n", &ModuleName);
1599
1600 Status = LdrLoadModule(&ModuleName, &LibraryModuleObject);
1601 if (!NT_SUCCESS(Status))
1602 {
1603 CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status);
1604 }
1605 /* Get the import address list */
1606 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1607 ImportModuleDirectory->dwRVAFunctionAddressList);
1608
1609 /* Get the list of functions to import */
1610 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1611 {
1612 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1613 ImportModuleDirectory->dwRVAFunctionNameList);
1614 }
1615 else
1616 {
1617 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1618 ImportModuleDirectory->dwRVAFunctionAddressList);
1619 }
1620 /* Walk through function list and fixup addresses */
1621 while (*FunctionNameList != 0L)
1622 {
1623 if ((*FunctionNameList) & 0x80000000) // hint
1624 {
1625 pName = NULL;
1626
1627
1628 Hint = (*FunctionNameList) & 0xffff;
1629 }
1630 else // hint-name
1631 {
1632 pName = (PCHAR)((DWORD)DriverBase +
1633 *FunctionNameList + 2);
1634 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1635 }
1636 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1637
1638 /* Fixup the current import symbol */
1639 if (LibraryModuleObject != NULL)
1640 {
1641 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1642 pName,
1643 Hint);
1644 }
1645 else
1646 {
1647 CPRINT("Unresolved kernel symbol: %s\n", pName);
1648 return STATUS_UNSUCCESSFUL;
1649 }
1650 ImportAddressList++;
1651 FunctionNameList++;
1652 }
1653
1654 RtlFreeUnicodeString(&ModuleName);
1655
1656 ImportModuleDirectory++;
1657 }
1658 }
1659
1660 /* Create the module */
1661 CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT));
1662 if (CreatedModuleObject == NULL)
1663 {
1664 return(STATUS_INSUFFICIENT_RESOURCES);
1665 }
1666
1667 RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT));
1668
1669 /* Initialize ModuleObject data */
1670 CreatedModuleObject->Base = DriverBase;
1671 CreatedModuleObject->Flags = MODULE_FLAG_PE;
1672
1673 RtlCreateUnicodeString(&CreatedModuleObject->FullName,
1674 FileName->Buffer);
1675 LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName,
1676 &CreatedModuleObject->FullName);
1677
1678 CreatedModuleObject->EntryPoint = (PVOID)((DWORD)DriverBase +
1679 PEOptionalHeader->AddressOfEntryPoint);
1680 CreatedModuleObject->Length = DriverSize;
1681 DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
1682
1683 CreatedModuleObject->Image.PE.FileHeader =
1684 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1685
1686 DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader);
1687 CreatedModuleObject->Image.PE.OptionalHeader =
1688 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1689 sizeof(IMAGE_FILE_HEADER));
1690 DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader);
1691 CreatedModuleObject->Image.PE.SectionList =
1692 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1693 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1694 DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList);
1695
1696 /* Insert module */
1697 KeAcquireSpinLock(&ModuleListLock, &Irql);
1698 InsertTailList(&ModuleListHead,
1699 &CreatedModuleObject->ListEntry);
1700 KeReleaseSpinLock(&ModuleListLock, Irql);
1701
1702
1703 ModuleTextSection = ExAllocatePool(NonPagedPool,
1704 sizeof(MODULE_TEXT_SECTION));
1705 ModuleTextSection->Base = (ULONG)DriverBase;
1706 ModuleTextSection->Length = DriverSize;
1707 ModuleTextSection->SymbolsBase = NULL;
1708 ModuleTextSection->SymbolsLength = 0;
1709 ModuleTextSection->Name =
1710 ExAllocatePool(NonPagedPool,
1711 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
1712 wcscpy(ModuleTextSection->Name, NameBuffer);
1713 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1714
1715 CreatedModuleObject->TextSection = ModuleTextSection;
1716
1717 *ModuleObject = CreatedModuleObject;
1718
1719 DPRINT("Loading Module %wZ...\n", FileName);
1720
1721 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB))
1722 {
1723 DbgPrint("Module %wZ loaded at 0x%.08x.\n",
1724 FileName, CreatedModuleObject->Base);
1725 }
1726
1727 return STATUS_SUCCESS;
1728 }
1729
1730
1731 PVOID
1732 LdrSafePEProcessModule(PVOID ModuleLoadBase,
1733 PVOID DriverBase,
1734 PVOID ImportModuleBase,
1735 PULONG DriverSize)
1736 {
1737 unsigned int Idx;
1738 ULONG RelocDelta, NumRelocs;
1739 ULONG CurrentSize, TotalRelocs;
1740 PULONG PEMagic;
1741 PIMAGE_DOS_HEADER PEDosHeader;
1742 PIMAGE_FILE_HEADER PEFileHeader;
1743 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1744 PIMAGE_SECTION_HEADER PESectionHeaders;
1745 PRELOCATION_DIRECTORY RelocDir;
1746 PRELOCATION_ENTRY RelocEntry;
1747 PVOID *ImportAddressList;
1748 PULONG FunctionNameList;
1749 PCHAR pName;
1750 USHORT Hint;
1751
1752 ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1753
1754 /* Get header pointers */
1755 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1756 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1757 PEDosHeader->e_lfanew);
1758 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1759 PEDosHeader->e_lfanew + sizeof(ULONG));
1760 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1761 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1762 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1763 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1764 sizeof(IMAGE_OPTIONAL_HEADER));
1765 CHECKPOINT;
1766
1767 /* Check file magic numbers */
1768 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1769 {
1770 return 0;
1771 }
1772 if (PEDosHeader->e_lfanew == 0)
1773 {
1774 return 0;
1775 }
1776 if (*PEMagic != IMAGE_PE_MAGIC)
1777 {
1778 return 0;
1779 }
1780 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1781 {
1782 return 0;
1783 }
1784
1785 ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1786 PEOptionalHeader->Magic,
1787 PEOptionalHeader->MajorLinkerVersion,
1788 PEOptionalHeader->MinorLinkerVersion);
1789 ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1790
1791 /* Determine the size of the module */
1792 *DriverSize = PEOptionalHeader->SizeOfImage;
1793 ps("DriverSize %x\n",*DriverSize);
1794
1795 /* Copy headers over */
1796 if (DriverBase != ModuleLoadBase)
1797 {
1798 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1799 }
1800
1801 ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader);
1802 ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders);
1803 ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections);
1804
1805 /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same
1806 address as it is mapped */
1807 if (DriverBase != ModuleLoadBase)
1808 {
1809 CurrentSize = 0;
1810
1811 /* Copy image sections into virtual section */
1812 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1813 {
1814 // Copy current section into current offset of virtual section
1815 if (PESectionHeaders[Idx].Characteristics &
1816 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1817 {
1818 //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1819 //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1820 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1821 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1822 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ?
1823 PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1824 }
1825 else
1826 {
1827 ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n",
1828 PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase);
1829 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1830 '\0',
1831 PESectionHeaders[Idx].Misc.VirtualSize);
1832 }
1833 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1834 PEOptionalHeader->SectionAlignment);
1835 }
1836
1837 /* Perform relocation fixups */
1838 RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase;
1839 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1840 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1841 ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1842 DriverBase,
1843 PEOptionalHeader->ImageBase,
1844 RelocDelta);
1845 ps("RelocDir %x\n",RelocDir);
1846
1847 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1848 {
1849 if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir)
1850 {
1851 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1852 PESectionHeaders[Idx].Name,
1853 PESectionHeaders[Idx].PointerToRawData);
1854 RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase;
1855 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1856 break;
1857 }
1858 }
1859
1860 ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1861
1862 TotalRelocs = 0;
1863 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1864 {
1865 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1866 sizeof(USHORT);
1867 RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir +
1868 sizeof(RELOCATION_DIRECTORY));
1869 for (Idx = 0; Idx < NumRelocs; Idx++)
1870 {
1871 ULONG Offset;
1872 ULONG Type;
1873 PDWORD RelocItem;
1874
1875 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1876 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1877 RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset);
1878 if (Type == 3)
1879 {
1880 (*RelocItem) += RelocDelta;
1881 }
1882 else if (Type != 0)
1883 {
1884 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1885 return(0);
1886 }
1887 }
1888 TotalRelocs += RelocDir->SizeOfBlock;
1889 RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir +
1890 RelocDir->SizeOfBlock);
1891 }
1892
1893 ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1894 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1895 .VirtualAddress);
1896 }
1897
1898 /* Perform import fixups */
1899 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1900 {
1901 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1902
1903 /* Process each import module */
1904 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1905 ((ULONG)DriverBase + PEOptionalHeader->
1906 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1907
1908 ps("Processeing import directory at %p\n", ImportModuleDirectory);
1909
1910 /* Check to make sure that import lib is kernel */
1911 pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName;
1912
1913 ps("Import module: %s\n", pName);
1914
1915 /* Get the import address list */
1916 ImportAddressList = (PVOID *)((ULONG)DriverBase +
1917 ImportModuleDirectory->dwRVAFunctionAddressList);
1918
1919 ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n",
1920 ImportModuleDirectory->dwRVAFunctionAddressList);
1921 ps(" ImportAddressList: 0x%X\n", ImportAddressList);
1922
1923 /* Get the list of functions to import */
1924 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1925 {
1926 ps("Using function name list.\n");
1927
1928 FunctionNameList = (PULONG)((ULONG)DriverBase +
1929 ImportModuleDirectory->dwRVAFunctionNameList);
1930 }
1931 else
1932 {
1933 ps("Using function address list.\n");
1934
1935 FunctionNameList = (PULONG)((ULONG)DriverBase +
1936 ImportModuleDirectory->dwRVAFunctionAddressList);
1937 }
1938
1939 /* Walk through function list and fixup addresses */
1940 while (*FunctionNameList != 0L)
1941 {
1942 if ((*FunctionNameList) & 0x80000000)
1943 {
1944 /* Hint */
1945 pName = NULL;
1946 Hint = (*FunctionNameList) & 0xffff;
1947 }
1948 else
1949 {
1950 /* Hint name */
1951 pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2);
1952 Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList);
1953 }
1954 //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList);
1955
1956 *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase,
1957 pName,
1958 Hint);
1959
1960 ImportAddressList++;
1961 FunctionNameList++;
1962 }
1963 }
1964
1965 ps("Finished importing.\n");
1966
1967 return(0);
1968 }
1969
1970
1971 static PVOID
1972 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1973 PCHAR Name,
1974 USHORT Hint)
1975 {
1976 PIMAGE_EXPORT_DIRECTORY ExportDir;
1977 ULONG ExportDirSize;
1978 USHORT Idx;
1979 PVOID ExportAddress;
1980 PWORD OrdinalList;
1981 PDWORD FunctionList, NameList;
1982
1983 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1984 RtlImageDirectoryEntryToData(ModuleObject->Base,
1985 TRUE,
1986 IMAGE_DIRECTORY_ENTRY_EXPORT,
1987 &ExportDirSize);
1988 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1989 if (ExportDir == NULL)
1990 {
1991 return NULL;
1992 }
1993
1994 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1995 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1996 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1997
1998 ExportAddress = 0;
1999
2000 if (Name != NULL)
2001 {
2002 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
2003 {
2004 #if 0
2005 DPRINT(" Name:%s NameList[%d]:%s\n",
2006 Name,
2007 Idx,
2008 (DWORD) ModuleObject->Base + NameList[Idx]);
2009
2010 #endif
2011 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
2012 {
2013 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
2014 FunctionList[OrdinalList[Idx]]);
2015 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
2016 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
2017 {
2018 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
2019 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
2020 DPRINT("ExportAddress: %p\n", ExportAddress);
2021 }
2022
2023 break;
2024 }
2025 }
2026 }
2027 else /* use hint */
2028 {
2029 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
2030 FunctionList[Hint - ExportDir->Base]);
2031 }
2032
2033 if (ExportAddress == 0)
2034 {
2035 CPRINT("Export not found for %d:%s\n",
2036 Hint,
2037 Name != NULL ? Name : "(Ordinal)");
2038 KeBugCheck(0);
2039 }
2040
2041 return(ExportAddress);
2042 }
2043
2044
2045 static PVOID
2046 LdrSafePEGetExportAddress(PVOID ImportModuleBase,
2047 PCHAR Name,
2048 USHORT Hint)
2049 {
2050 USHORT Idx;
2051 PVOID ExportAddress;
2052 PWORD OrdinalList;
2053 PDWORD FunctionList, NameList;
2054 PIMAGE_EXPORT_DIRECTORY ExportDir;
2055 ULONG ExportDirSize;
2056
2057 static BOOLEAN EP = FALSE;
2058
2059 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
2060 RtlImageDirectoryEntryToData(ImportModuleBase,
2061 TRUE,
2062 IMAGE_DIRECTORY_ENTRY_EXPORT,
2063 &ExportDirSize);
2064
2065 if (!EP) {
2066 EP = TRUE;
2067 ps("ExportDir %x\n", ExportDir);
2068 }
2069
2070 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase);
2071 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase);
2072 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase);
2073
2074 ExportAddress = 0;
2075
2076 if (Name != NULL)
2077 {
2078 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
2079 {
2080 if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx])))
2081 {
2082 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
2083 FunctionList[OrdinalList[Idx]]);
2084 break;
2085 }
2086 }
2087 }
2088 else /* use hint */
2089 {
2090 ExportAddress = (PVOID) ((DWORD)ImportModuleBase +
2091
2092 FunctionList[Hint - ExportDir->Base]);
2093 }
2094
2095 if (ExportAddress == 0)
2096 {
2097 ps("Export not found for %d:%s\n",
2098 Hint,
2099 Name != NULL ? Name : "(Ordinal)");
2100 KeBugCheck(0);
2101 }
2102 return ExportAddress;
2103 }
2104
2105
2106 static PVOID
2107 LdrPEFixupForward(PCHAR ForwardName)
2108 {
2109 CHAR NameBuffer[128];
2110 UNICODE_STRING ModuleName;
2111 PCHAR p;
2112 PMODULE_OBJECT ModuleObject;
2113
2114 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
2115
2116 strcpy(NameBuffer, ForwardName);
2117 p = strchr(NameBuffer, '.');
2118 if (p == NULL)
2119 {
2120 return NULL;
2121 }
2122
2123 *p = 0;
2124
2125 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
2126
2127 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
2128 NameBuffer);
2129 ModuleObject = LdrGetModuleObject(&ModuleName);
2130 RtlFreeUnicodeString(&ModuleName);
2131
2132 DPRINT("ModuleObject: %p\n", ModuleObject);
2133
2134 if (ModuleObject == NULL)
2135 {
2136 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
2137 return NULL;
2138 }
2139
2140 return(LdrPEGetExportAddress(ModuleObject, p+1, 0));
2141 }
2142
2143 /* EOF */