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