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