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