Preparations for checked/free like builds (CPRINT == DbgPrint when DBG is defined).
[reactos.git] / reactos / ntoskrnl / ldr / loader.c
1 /* $Id: loader.c,v 1.77 2001/05/01 23:08:20 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 <internal/config.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 #define NDEBUG
39 #include <internal/debug.h>
40
41
42 /* MACROS ********************************************************************/
43
44 #define MODULE_ROOT_NAME L"\\Modules\\"
45
46 /* GLOBALS *******************************************************************/
47
48 LIST_ENTRY ModuleListHead;
49 POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
50 LIST_ENTRY ModuleTextListHead;
51 STATIC MODULE_TEXT_SECTION NtoskrnlTextSection;
52 /* STATIC MODULE_TEXT_SECTION HalTextSection; */
53
54 #define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M')
55 #define TAG_SYM_BUF TAG('S', 'Y', 'M', 'B')
56
57 /* FORWARD DECLARATIONS ******************************************************/
58
59 PMODULE_OBJECT LdrLoadModule(PUNICODE_STRING Filename);
60 PMODULE_OBJECT LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName);
61 PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject, char *Name, unsigned short Hint);
62 static PMODULE_OBJECT LdrOpenModule(PUNICODE_STRING Filename);
63 static NTSTATUS LdrCreateModule(PVOID ObjectBody,
64 PVOID Parent,
65 PWSTR RemainingPath,
66 POBJECT_ATTRIBUTES ObjectAttributes);
67 static VOID LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
68 PUNICODE_STRING FullName);
69
70 /* PE Driver load support */
71 static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName);
72 static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
73 char *Name,
74 unsigned short Hint);
75 static PMODULE_OBJECT LdrPEGetModuleObject(PUNICODE_STRING ModuleName);
76 static PVOID LdrPEFixupForward(PCHAR ForwardName);
77
78
79 /* FUNCTIONS *****************************************************************/
80
81 VOID
82 LdrInitDebug(PLOADER_MODULE Module, PWCH Name)
83 {
84 PLIST_ENTRY current_entry;
85 MODULE_TEXT_SECTION* current;
86
87 current_entry = ModuleTextListHead.Flink;
88 while (current_entry != &ModuleTextListHead)
89 {
90 current =
91 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
92 if (wcscmp(current->Name, Name) == 0)
93 {
94 break;
95 }
96 current_entry = current_entry->Flink;
97 }
98
99 if (current_entry == &ModuleTextListHead)
100 {
101 return;
102 }
103
104 current->SymbolsBase = (PVOID)Module->ModStart;
105 current->SymbolsLength = Module->ModEnd - Module->ModStart;
106 }
107
108 VOID
109 LdrInit1(VOID)
110 {
111 PIMAGE_DOS_HEADER DosHeader;
112 PIMAGE_FILE_HEADER FileHeader;
113 PIMAGE_OPTIONAL_HEADER OptionalHeader;
114 PIMAGE_SECTION_HEADER SectionList;
115
116 InitializeListHead(&ModuleTextListHead);
117
118 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
119 FileHeader =
120 (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE +
121 DosHeader->e_lfanew + sizeof(ULONG));
122 OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
123 ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER));
124 SectionList = (PIMAGE_SECTION_HEADER)
125 ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
126 NtoskrnlTextSection.Base = KERNEL_BASE;
127 NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize +
128 SectionList[0].VirtualAddress;
129 NtoskrnlTextSection.Name = L"ntoskrnl.exe";
130 NtoskrnlTextSection.SymbolsBase = NULL;
131 NtoskrnlTextSection.SymbolsLength = 0;
132 InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry);
133 }
134
135 VOID LdrInitModuleManagement(VOID)
136 {
137 HANDLE DirHandle, ModuleHandle;
138 NTSTATUS Status;
139 WCHAR NameBuffer[60];
140 UNICODE_STRING ModuleName;
141 OBJECT_ATTRIBUTES ObjectAttributes;
142 PIMAGE_DOS_HEADER DosHeader;
143 PMODULE_OBJECT ModuleObject;
144
145 /* Register the process object type */
146 IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
147 IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'T');
148 IoDriverObjectType->TotalObjects = 0;
149 IoDriverObjectType->TotalHandles = 0;
150 IoDriverObjectType->MaxObjects = ULONG_MAX;
151 IoDriverObjectType->MaxHandles = ULONG_MAX;
152 IoDriverObjectType->PagedPoolCharge = 0;
153 IoDriverObjectType->NonpagedPoolCharge = sizeof(MODULE);
154 IoDriverObjectType->Dump = NULL;
155 IoDriverObjectType->Open = NULL;
156 IoDriverObjectType->Close = NULL;
157 IoDriverObjectType->Delete = NULL;
158 IoDriverObjectType->Parse = NULL;
159 IoDriverObjectType->Security = NULL;
160 IoDriverObjectType->QueryName = NULL;
161 IoDriverObjectType->OkayToClose = NULL;
162 IoDriverObjectType->Create = LdrCreateModule;
163 RtlInitUnicodeString(&IoDriverObjectType->TypeName, L"Driver");
164
165 /* Create Modules object directory */
166 wcscpy(NameBuffer, MODULE_ROOT_NAME);
167 *(wcsrchr(NameBuffer, L'\\')) = 0;
168 RtlInitUnicodeString (&ModuleName, NameBuffer);
169 InitializeObjectAttributes(&ObjectAttributes,
170 &ModuleName,
171 0,
172 NULL,
173 NULL);
174 DPRINT("Create dir: %wZ\n", &ModuleName);
175 Status = NtCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
176 assert(NT_SUCCESS(Status));
177
178 /* Add module entry for NTOSKRNL */
179 wcscpy(NameBuffer, MODULE_ROOT_NAME);
180 wcscat(NameBuffer, L"ntoskrnl.exe");
181 RtlInitUnicodeString (&ModuleName, NameBuffer);
182 DPRINT("Kernel's Module name is: %wZ\n", &ModuleName);
183
184 /* Initialize ObjectAttributes for ModuleObject */
185 InitializeObjectAttributes(&ObjectAttributes,
186 &ModuleName,
187 0,
188 NULL,
189 NULL);
190
191 /* Create module object */
192 ModuleHandle = 0;
193 ModuleObject = ObCreateObject(&ModuleHandle,
194 STANDARD_RIGHTS_REQUIRED,
195 &ObjectAttributes,
196 IoDriverObjectType);
197 assert(ModuleObject != NULL);
198
199 InitializeListHead(&ModuleListHead);
200
201 /* Initialize ModuleObject data */
202 ModuleObject->Base = (PVOID) KERNEL_BASE;
203 ModuleObject->Flags = MODULE_FLAG_PE;
204 InsertTailList(&ModuleListHead,
205 &ModuleObject->ListEntry);
206 RtlCreateUnicodeString(&ModuleObject->FullName,
207 L"ntoskrnl.exe");
208 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
209 &ModuleObject->FullName);
210
211 DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
212 ModuleObject->Image.PE.FileHeader =
213 (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
214 DosHeader->e_lfanew + sizeof(ULONG));
215 ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
216 ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
217 ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
218 ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
219 ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
220 ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
221 DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
222 ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage;
223 ModuleObject->TextSection = &NtoskrnlTextSection;
224
225 /* FIXME: Add fake module entry for HAL */
226 }
227
228 /*
229 * load the auto config drivers.
230 */
231 static VOID LdrLoadAutoConfigDriver (LPWSTR RelativeDriverName)
232 {
233 WCHAR TmpFileName [MAX_PATH];
234 UNICODE_STRING DriverName;
235 PDEVICE_NODE DeviceNode;
236 NTSTATUS Status;
237
238 CPRINT("Loading %S\n",RelativeDriverName);
239
240 wcscpy(TmpFileName, L"\\SystemRoot\\system32\\drivers\\");
241 wcscat(TmpFileName, RelativeDriverName);
242 RtlInitUnicodeString (&DriverName, TmpFileName);
243
244 /* Use IopRootDeviceNode for now */
245 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
246 if (!NT_SUCCESS(Status))
247 {
248 return;
249 }
250
251 Status = LdrLoadDriver(&DriverName, DeviceNode, FALSE);
252 if (!NT_SUCCESS(Status))
253 {
254 IopFreeDeviceNode(DeviceNode);
255 DPRINT1("Driver load failed, status (%x)\n", Status);
256 }
257 }
258
259 #ifdef KDBG
260
261 BOOLEAN LdrpReadLine(PCHAR Line,
262 ULONG LineSize,
263 PVOID *Buffer,
264 PULONG Size)
265 {
266 CHAR ch;
267 PCHAR Block;
268 ULONG Count;
269
270 if (*Size == 0)
271 return FALSE;
272
273 ch = ' ';
274 Count = 0;
275 Block = *Buffer;
276 while ((*Size > 0) && (Count < LineSize) && ((ch = *Block) != (CHAR)13))
277 {
278 *Line = ch;
279 Line++;
280 Block++;
281 Count++;
282 *Size -= 1;
283 }
284 *Line = (CHAR)0;
285
286 if (ch == (CHAR)13)
287 {
288 Block++;
289 *Size -= 1;
290 }
291
292 if ((*Size > 0) && (*Block == (CHAR)10))
293 {
294 Block++;
295 *Size -= 1;
296 }
297
298 *Buffer = Block;
299
300 return TRUE;
301 }
302
303 ULONG HexL(PCHAR Buffer)
304 {
305 CHAR ch;
306 UINT i, j;
307 ULONG Value;
308
309 j = 32;
310 i = 0;
311 Value = 0;
312 while ((j > 0) && ((ch = Buffer[i]) != ' '))
313 {
314 j -= 4;
315 if ((ch >= '0') && (ch <= '9'))
316 Value |= ((ch - '0') << j);
317 if ((ch >= 'A') && (ch <= 'F'))
318 Value |= ((10 + (ch - 'A')) << j);
319 else
320 if ((ch >= 'a') && (ch <= 'f'))
321 Value |= ((10 + (ch - 'a')) << j);
322 i++;
323 }
324 return Value;
325 }
326
327 PSYMBOL LdrpParseLine(PCHAR Line,
328 PULONG TextBase,
329 PBOOLEAN TextBaseValid,
330 PULONG FileAlignment)
331 /*
332 Line format: [ADDRESS] <TYPE> <NAME>
333 TYPE:
334 U = ?
335 A = Image information
336 t = Symbol in text segment
337 T = Symbol in text segment
338 d = Symbol in data segment
339 D = Symbol in data segment
340 b = Symbol in BSS segment
341 B = Symbol in BSS segment
342 ? = Unknown segment or symbol in unknown segment
343 */
344 {
345 ANSI_STRING AnsiString;
346 CHAR Buffer[128];
347 PSYMBOL Symbol;
348 ULONG Address;
349 PCHAR Str;
350 CHAR Type;
351
352 if ((Line[0] == (CHAR)0) || (Line[0] == ' '))
353 return NULL;
354
355 Address = HexL(Line);
356
357 Line = strchr(Line, ' ');
358 if (Line == NULL)
359 return NULL;
360
361 Line++;
362 Type = *Line;
363
364 Line = strchr(Line, ' ');
365 if (Line == NULL)
366 return NULL;
367
368 Line++;
369 Str = strchr(Line, ' ');
370 if (Str == NULL)
371 strcpy((char*)&Buffer, Line);
372 else
373 strncpy((char*)&Buffer, Line, Str - Line);
374
375 if ((Type == 'A') && (strcmp((char*)&Buffer, "__file_alignment__")) == 0)
376 {
377 *FileAlignment = Address;
378 return NULL;
379 }
380
381 /* if ((Type == 'A') && (strcmp((char*)&Buffer, "__image_base__")) == 0)
382 {
383 *TextBase = Address;
384 *TextBaseValid = TRUE;
385 return NULL;
386 }*/
387
388 /* We only want symbols in the .text segment */
389 if ((Type != 't') && (Type != 'T'))
390 return NULL;
391
392 /* Discard other symbols we can't use */
393 if ((Buffer[0] != '_') || ((Buffer[0] == '_') && (Buffer[1] == '_')))
394 return NULL;
395
396 Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
397 if (!Symbol)
398 return NULL;
399
400 Symbol->Next = NULL;
401
402 Symbol->RelativeAddress = Address;
403
404 RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
405 RtlAnsiStringToUnicodeString(&Symbol->Name, &AnsiString, TRUE);
406
407 if (!(*TextBaseValid))
408 {
409 *TextBase = Address - *FileAlignment;
410 *TextBaseValid = TRUE;
411 }
412
413 return Symbol;
414 }
415
416 VOID LdrpLoadModuleSymbolsFromBuffer(
417 PMODULE_OBJECT ModuleObject,
418 PVOID Buffer,
419 ULONG Length)
420 /*
421 Symbols must be sorted by address, e.g.
422 "nm --numeric-sort module.sys > module.sym"
423 */
424 {
425 PSYMBOL Symbol, CurrentSymbol = NULL;
426 BOOLEAN TextBaseValid;
427 BOOLEAN Valid;
428 ULONG TextBase = 0;
429 ULONG FileAlignment = 0;
430 CHAR Line[256];
431 ULONG Tmp;
432
433 assert(ModuleObject);
434
435 if (ModuleObject->TextSection == NULL)
436 {
437 ModuleObject->TextSection = &NtoskrnlTextSection;
438 }
439
440 if (ModuleObject->TextSection->Symbols.SymbolCount > 0)
441 {
442 CPRINT("Symbols are already loaded for %wZ\n", &ModuleObject->BaseName);
443 return;
444 }
445
446 ModuleObject->TextSection->Symbols.SymbolCount = 0;
447 ModuleObject->TextSection->Symbols.Symbols = NULL;
448 TextBaseValid = FALSE;
449 Valid = FALSE;
450 while (LdrpReadLine((PCHAR)&Line, 256, &Buffer, &Length))
451 {
452 Symbol = LdrpParseLine((PCHAR)&Line, &Tmp, &Valid, &FileAlignment);
453
454 if ((Valid) && (!TextBaseValid))
455 {
456 TextBase = Tmp;
457 TextBaseValid = TRUE;
458 }
459
460 if (Symbol != NULL)
461 {
462 Symbol->RelativeAddress -= TextBase;
463
464 if (ModuleObject->TextSection->Symbols.Symbols == NULL)
465 ModuleObject->TextSection->Symbols.Symbols = Symbol;
466 else
467 CurrentSymbol->Next = Symbol;
468
469 CurrentSymbol = Symbol;
470
471 ModuleObject->TextSection->Symbols.SymbolCount++;
472 }
473 }
474 }
475
476 VOID LdrpLoadModuleSymbols(PMODULE_OBJECT ModuleObject)
477 {
478 FILE_STANDARD_INFORMATION FileStdInfo;
479 OBJECT_ATTRIBUTES ObjectAttributes;
480 WCHAR TmpFileName[MAX_PATH];
481 UNICODE_STRING Filename;
482 LPWSTR Start, Ext;
483 HANDLE FileHandle;
484 PVOID FileBuffer;
485 NTSTATUS Status;
486 ULONG Length;
487
488 /* Get the path to the symbol store */
489 wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
490
491 /* Get the symbol filename from the module name */
492 Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\');
493 if (Start == NULL)
494 Start = ModuleObject->BaseName.Buffer;
495 else
496 Start++;
497
498 Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.');
499 if (Ext != NULL)
500 Length = Ext - Start;
501 else
502 Length = wcslen(Start);
503
504 wcsncat(TmpFileName, Start, Length);
505 wcscat(TmpFileName, L".sym");
506 RtlInitUnicodeString(&Filename, TmpFileName);
507
508 /* Open the file */
509 InitializeObjectAttributes(&ObjectAttributes,
510 &Filename,
511 0,
512 NULL,
513 NULL);
514
515 Status = ZwOpenFile(&FileHandle,
516 FILE_ALL_ACCESS,
517 &ObjectAttributes,
518 NULL, 0, 0);
519 if (!NT_SUCCESS(Status))
520 {
521 DPRINT("Could not open symbol file: %wZ\n", &Filename);
522 return;
523 }
524
525 CPRINT("Loading symbols from %wZ...\n", &Filename);
526
527 /* Get the size of the file */
528 Status = ZwQueryInformationFile(FileHandle,
529 NULL,
530 &FileStdInfo,
531 sizeof(FileStdInfo),
532 FileStandardInformation);
533 if (!NT_SUCCESS(Status))
534 {
535 DPRINT("Could not get file size\n");
536 return;
537 }
538
539 /* Allocate nonpageable memory for symbol file */
540 FileBuffer = ExAllocatePool(NonPagedPool,
541 FileStdInfo.EndOfFile.u.LowPart);
542
543 if (FileBuffer == NULL)
544 {
545 DPRINT("Could not allocate memory for symbol file\n");
546 return;
547 }
548
549 /* Load file into memory chunk */
550 Status = ZwReadFile(FileHandle,
551 0, 0, 0, 0,
552 FileBuffer,
553 FileStdInfo.EndOfFile.u.LowPart,
554 0, 0);
555 if (!NT_SUCCESS(Status))
556 {
557 DPRINT("Could not read symbol file into memory\n");
558 ExFreePool(FileBuffer);
559 return;
560 }
561
562 ZwClose(FileHandle);
563
564 LdrpLoadModuleSymbolsFromBuffer(ModuleObject,
565 FileBuffer,
566 FileStdInfo.EndOfFile.u.LowPart);
567
568 ExFreePool(FileBuffer);
569 }
570
571 NTSTATUS LdrpFindModuleObject(
572 PUNICODE_STRING ModuleName,
573 PMODULE_OBJECT *ModuleObject)
574 {
575 NTSTATUS Status;
576 WCHAR NameBuffer[MAX_PATH];
577 UNICODE_STRING Name;
578 OBJECT_ATTRIBUTES ObjectAttributes;
579 UNICODE_STRING RemainingPath;
580
581 wcscpy(NameBuffer, MODULE_ROOT_NAME);
582 wcscat(NameBuffer, ModuleName->Buffer);
583 RtlInitUnicodeString(&Name, NameBuffer);
584
585 InitializeObjectAttributes(&ObjectAttributes,
586 &Name,
587 0,
588 NULL,
589 NULL);
590 Status = ObFindObject(&ObjectAttributes,
591 (PVOID*)ModuleObject,
592 &RemainingPath,
593 NULL);
594 if (!NT_SUCCESS(Status))
595 {
596 return Status;
597 }
598
599 if ((RemainingPath.Buffer != NULL) || (*ModuleObject == NULL))
600 {
601 RtlFreeUnicodeString(&RemainingPath);
602 return STATUS_UNSUCCESSFUL;
603 }
604
605 return STATUS_SUCCESS;
606 }
607
608 #endif /* KDBG */
609
610 VOID LdrLoadAutoConfigDrivers (VOID)
611 {
612
613 #ifdef KDBG
614
615 NTSTATUS Status;
616 UNICODE_STRING ModuleName;
617 PMODULE_OBJECT ModuleObject;
618
619 /* Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
620 is created after their module entries */
621
622 RtlInitUnicodeString(&ModuleName, L"ntoskrnl.exe");
623
624 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
625 if (NT_SUCCESS(Status)) {
626 LdrpLoadModuleSymbols(ModuleObject);
627 }
628
629 /* FIXME: Load symbols for hal.dll */
630
631 #endif /* KDBG */
632
633 /*
634 * Keyboard driver
635 */
636 LdrLoadAutoConfigDriver( L"keyboard.sys" );
637
638 /*
639 * Raw console driver
640 */
641 LdrLoadAutoConfigDriver( L"blue.sys" );
642
643 /*
644 *
645 */
646 LdrLoadAutoConfigDriver(L"vidport.sys");
647
648 /*
649 *
650 */
651 LdrLoadAutoConfigDriver(L"vgamp.sys");
652
653 /*
654 * Minix filesystem driver
655 */
656 LdrLoadAutoConfigDriver(L"minixfs.sys");
657
658 /*
659 * Networking
660 */
661 #if 0
662 /*
663 * NDIS library
664 */
665 LdrLoadAutoConfigDriver(L"ndis.sys");
666
667 /*
668 * Novell Eagle 2000 driver
669 */
670 LdrLoadAutoConfigDriver(L"ne2000.sys");
671
672 /*
673 * TCP/IP protocol driver
674 */
675 LdrLoadAutoConfigDriver(L"tcpip.sys");
676
677 /*
678 * TDI test driver
679 */
680 LdrLoadAutoConfigDriver(L"tditest.sys");
681
682 /*
683 * Ancillary Function Driver
684 */
685 LdrLoadAutoConfigDriver(L"afd.sys");
686 #endif
687 }
688
689
690 static NTSTATUS
691 LdrCreateModule(PVOID ObjectBody,
692 PVOID Parent,
693 PWSTR RemainingPath,
694 POBJECT_ATTRIBUTES ObjectAttributes)
695 {
696 DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
697 ObjectBody,
698 Parent,
699 RemainingPath);
700 if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
701 {
702 return STATUS_UNSUCCESSFUL;
703 }
704 if (Parent != NULL && RemainingPath != NULL)
705 {
706 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath + 1);
707 }
708
709 return STATUS_SUCCESS;
710 }
711
712 /*
713 * FUNCTION: Loads a kernel driver
714 * ARGUMENTS:
715 * FileName = Driver to load
716 * RETURNS: Status
717 */
718
719 NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename,
720 PDEVICE_NODE DeviceNode,
721 BOOLEAN BootDriversOnly)
722 {
723 PMODULE_OBJECT ModuleObject;
724 NTSTATUS Status;
725
726 ModuleObject = LdrLoadModule(Filename);
727 if (!ModuleObject)
728 {
729 return STATUS_UNSUCCESSFUL;
730 }
731
732 Status = IopInitializeDriver(ModuleObject->EntryPoint,
733 DeviceNode, BootDriversOnly);
734 if (!NT_SUCCESS(Status))
735 {
736 ObDereferenceObject(ModuleObject);
737 }
738
739 return Status;
740 }
741
742 NTSTATUS LdrLoadGdiDriver (PUNICODE_STRING DriverName,
743 PVOID *ImageAddress,
744 PVOID *SectionPointer,
745 PVOID *EntryPoint,
746 PVOID *ExportSectionPointer)
747 {
748 PMODULE_OBJECT ModuleObject;
749
750 ModuleObject = LdrLoadModule(DriverName);
751 if (ModuleObject == 0)
752 {
753 return STATUS_UNSUCCESSFUL;
754 }
755
756 if (ImageAddress)
757 *ImageAddress = ModuleObject->Base;
758
759 // if (SectionPointer)
760 // *SectionPointer = ModuleObject->
761
762 if (EntryPoint)
763 *EntryPoint = ModuleObject->EntryPoint;
764
765 // if (ExportSectionPointer)
766 // *ExportSectionPointer = ModuleObject->
767
768 return STATUS_SUCCESS;
769 }
770
771
772 PMODULE_OBJECT
773 LdrLoadModule(PUNICODE_STRING Filename)
774 {
775 PVOID ModuleLoadBase;
776 NTSTATUS Status;
777 HANDLE FileHandle;
778 OBJECT_ATTRIBUTES ObjectAttributes;
779 PMODULE_OBJECT ModuleObject;
780 FILE_STANDARD_INFORMATION FileStdInfo;
781
782 /* Check for module already loaded */
783 if ((ModuleObject = LdrOpenModule(Filename)) != NULL)
784 {
785 return ModuleObject;
786 }
787
788 DPRINT("Loading Module %wZ...\n", Filename);
789
790 /* Open the Module */
791 InitializeObjectAttributes(&ObjectAttributes,
792 Filename,
793 0,
794 NULL,
795 NULL);
796 CHECKPOINT;
797 Status = NtOpenFile(&FileHandle,
798 FILE_ALL_ACCESS,
799 &ObjectAttributes,
800 NULL, 0, 0);
801 CHECKPOINT;
802 if (!NT_SUCCESS(Status))
803 {
804 CPRINT("Could not open module file: %wZ\n", Filename);
805 return NULL;
806 }
807 CHECKPOINT;
808
809 /* Get the size of the file */
810 Status = NtQueryInformationFile(FileHandle,
811 NULL,
812 &FileStdInfo,
813 sizeof(FileStdInfo),
814 FileStandardInformation);
815 if (!NT_SUCCESS(Status))
816 {
817 CPRINT("Could not get file size\n");
818 return NULL;
819 }
820 CHECKPOINT;
821
822 /* Allocate nonpageable memory for driver */
823 ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool,
824 FileStdInfo.EndOfFile.u.LowPart,
825 TAG_DRIVER_MEM);
826
827 if (ModuleLoadBase == NULL)
828 {
829 CPRINT("Could not allocate memory for module");
830 return NULL;
831 }
832 CHECKPOINT;
833
834 /* Load driver into memory chunk */
835 Status = NtReadFile(FileHandle,
836 0, 0, 0, 0,
837 ModuleLoadBase,
838 FileStdInfo.EndOfFile.u.LowPart,
839 0, 0);
840 if (!NT_SUCCESS(Status))
841 {
842 CPRINT("Could not read module file into memory");
843 ExFreePool(ModuleLoadBase);
844 return NULL;
845 }
846 CHECKPOINT;
847
848 NtClose(FileHandle);
849
850 ModuleObject = LdrProcessModule(ModuleLoadBase, Filename);
851
852 /* Cleanup */
853 ExFreePool(ModuleLoadBase);
854
855 #ifdef KDBG
856
857 /* Load symbols for module if available */
858 LdrpLoadModuleSymbols(ModuleObject);
859
860 #endif /* KDBG */
861
862 return ModuleObject;
863 }
864
865 NTSTATUS
866 LdrProcessDriver(PVOID ModuleLoadBase, PCHAR FileName, ULONG ModuleLength)
867 {
868 PMODULE_OBJECT ModuleObject;
869 UNICODE_STRING ModuleName;
870 PDEVICE_NODE DeviceNode;
871 NTSTATUS Status;
872
873 #ifdef KDBG
874
875 CHAR TmpBaseName[MAX_PATH];
876 CHAR TmpFileName[MAX_PATH];
877 ANSI_STRING AnsiString;
878 ULONG Length;
879 PCHAR Ext;
880
881 /* Split the filename into base name and extension */
882 Ext = strrchr(FileName, '.');
883 if (Ext != NULL)
884 Length = Ext - FileName;
885 else
886 Length = strlen(FileName);
887
888 if ((Ext != NULL) && (strcmp(Ext, ".sym") == 0))
889 {
890 DPRINT("Module %s is a symbol file\n", FileName);
891
892 strncpy(TmpBaseName, FileName, Length);
893 TmpBaseName[Length] = '\0';
894
895 DPRINT("base: %s (Length %d)\n", TmpBaseName, Length);
896
897 strcpy(TmpFileName, TmpBaseName);
898 strcat(TmpFileName, ".sys");
899 RtlInitAnsiString(&AnsiString, TmpFileName);
900
901 DPRINT("dasdsad: %s\n", TmpFileName);
902
903 RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
904 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
905 RtlFreeUnicodeString(&ModuleName);
906 if (!NT_SUCCESS(Status))
907 {
908 strcpy(TmpFileName, TmpBaseName);
909 strcat(TmpFileName, ".exe");
910 RtlInitAnsiString(&AnsiString, TmpFileName);
911 RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
912 Status = LdrpFindModuleObject(&ModuleName, &ModuleObject);
913 RtlFreeUnicodeString(&ModuleName);
914 }
915 if (NT_SUCCESS(Status))
916 {
917 LdrpLoadModuleSymbolsFromBuffer(
918 ModuleObject,
919 ModuleLoadBase,
920 ModuleLength);
921 }
922 return(STATUS_SUCCESS);
923 }
924 else
925 {
926 DPRINT("Module %s is executable\n", FileName);
927 }
928 #endif /* KDBG */
929
930 /* Use IopRootDeviceNode for now */
931 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
932 if (!NT_SUCCESS(Status))
933 {
934 CPRINT("Driver load failed, status (%x)\n", Status);
935 return(Status);
936 }
937
938 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
939 FileName);
940 ModuleObject = LdrProcessModule(ModuleLoadBase,
941 &ModuleName);
942 RtlFreeUnicodeString(&ModuleName);
943 if (ModuleObject == NULL)
944 {
945 IopFreeDeviceNode(DeviceNode);
946 CPRINT("Driver load failed, status (%x)\n", Status);
947 return(STATUS_UNSUCCESSFUL);
948 }
949
950 Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE);
951 if (!NT_SUCCESS(Status))
952 {
953 IopFreeDeviceNode(DeviceNode);
954 CPRINT("Driver load failed, status (%x)\n", Status);
955 }
956
957 return(Status);
958 }
959
960 PMODULE_OBJECT
961 LdrProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING ModuleName)
962 {
963 PIMAGE_DOS_HEADER PEDosHeader;
964
965 /* If MZ header exists */
966 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
967 if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
968 {
969 return LdrPEProcessModule(ModuleLoadBase, ModuleName);
970 }
971
972 CPRINT("Module wasn't PE\n");
973 return 0;
974 }
975
976 static PMODULE_OBJECT
977 LdrOpenModule(PUNICODE_STRING Filename)
978 {
979 NTSTATUS Status;
980 WCHAR NameBuffer[60];
981 UNICODE_STRING ModuleName;
982 OBJECT_ATTRIBUTES ObjectAttributes;
983 PMODULE_OBJECT ModuleObject;
984 UNICODE_STRING RemainingPath;
985
986 wcscpy(NameBuffer, MODULE_ROOT_NAME);
987 if (wcsrchr(Filename->Buffer, '\\') != 0)
988 {
989 wcscat(NameBuffer, wcsrchr(Filename->Buffer, '\\') + 1);
990 }
991 else
992 {
993 wcscat(NameBuffer, Filename->Buffer);
994 }
995 RtlInitUnicodeString (&ModuleName, NameBuffer);
996 InitializeObjectAttributes(&ObjectAttributes,
997 &ModuleName,
998 0,
999 NULL,
1000 NULL);
1001
1002 Status = ObFindObject(&ObjectAttributes,
1003 (PVOID *) &ModuleObject,
1004 &RemainingPath,
1005 NULL);
1006 CHECKPOINT;
1007 if (NT_SUCCESS(Status) && (RemainingPath.Buffer == NULL || *(RemainingPath.Buffer) == 0))
1008 {
1009 DPRINT("Module %wZ at %p\n", Filename, ModuleObject);
1010 RtlFreeUnicodeString (&RemainingPath);
1011
1012 return ModuleObject;
1013 }
1014
1015 RtlFreeUnicodeString (&RemainingPath);
1016
1017 return NULL;
1018 }
1019
1020 PVOID
1021 LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
1022 char *Name,
1023 unsigned short Hint)
1024 {
1025 if (ModuleObject->Flags & MODULE_FLAG_PE)
1026 {
1027 return LdrPEGetExportAddress(ModuleObject, Name, Hint);
1028 }
1029 else
1030 {
1031 return 0;
1032 }
1033 }
1034
1035 NTSTATUS
1036 LdrpQueryModuleInformation(PVOID Buffer,
1037 ULONG Size,
1038 PULONG ReqSize)
1039 {
1040 PLIST_ENTRY current_entry;
1041 PMODULE_OBJECT current;
1042 ULONG ModuleCount = 0;
1043 PSYSTEM_MODULE_INFORMATION Smi;
1044 ANSI_STRING AnsiName;
1045 PCHAR p;
1046
1047 // KeAcquireSpinLock(&ModuleListLock,&oldlvl);
1048
1049 /* calculate required size */
1050 current_entry = ModuleListHead.Flink;
1051 while (current_entry != (&ModuleListHead))
1052 {
1053 ModuleCount++;
1054 current_entry = current_entry->Flink;
1055 }
1056
1057 *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+
1058 (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY);
1059
1060 if (Size < *ReqSize)
1061 {
1062 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1063 return STATUS_INFO_LENGTH_MISMATCH;
1064 }
1065
1066 /* fill the buffer */
1067 memset(Buffer, '=', Size);
1068
1069 Smi = (PSYSTEM_MODULE_INFORMATION)Buffer;
1070 Smi->Count = ModuleCount;
1071
1072 ModuleCount = 0;
1073 current_entry = ModuleListHead.Flink;
1074 while (current_entry != (&ModuleListHead))
1075 {
1076 current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry);
1077
1078 Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */
1079 Smi->Module[ModuleCount].BaseAddress = current->Base;
1080 Smi->Module[ModuleCount].Size = current->Length;
1081 Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */
1082 Smi->Module[ModuleCount].EntryIndex = ModuleCount;
1083
1084 AnsiName.Length = 0;
1085 AnsiName.MaximumLength = 256;
1086 AnsiName.Buffer = Smi->Module[ModuleCount].Name;
1087 RtlUnicodeStringToAnsiString(&AnsiName,
1088 &current->FullName,
1089 FALSE);
1090
1091 p = strrchr (AnsiName.Buffer, '\\');
1092 if (p == NULL)
1093 {
1094 Smi->Module[ModuleCount].PathLength = 0;
1095 Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer);
1096 }
1097 else
1098 {
1099 p++;
1100 Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer;
1101 Smi->Module[ModuleCount].NameLength = strlen(p);
1102 }
1103
1104 ModuleCount++;
1105 current_entry = current_entry->Flink;
1106 }
1107
1108 // KeReleaseSpinLock(&ModuleListLock,oldlvl);
1109
1110 return STATUS_SUCCESS;
1111 }
1112
1113
1114 static VOID
1115 LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,
1116 PUNICODE_STRING FullName)
1117 {
1118 UNICODE_STRING Name;
1119 PWCHAR p;
1120 PWCHAR q;
1121
1122 DPRINT("LdrpBuildModuleBaseName()\n");
1123 DPRINT("FullName %wZ\n", FullName);
1124
1125 p = wcsrchr(FullName->Buffer, '\\');
1126 if (p == NULL)
1127 {
1128 p = FullName->Buffer;
1129 }
1130 else
1131 {
1132 p++;
1133 }
1134
1135 DPRINT("p %S\n", p);
1136
1137 RtlCreateUnicodeString(&Name, p);
1138
1139 q = wcschr(p, '.');
1140 if (q != NULL)
1141 {
1142 *q = (WCHAR)0;
1143 }
1144
1145 DPRINT("p %S\n", p);
1146
1147 RtlCreateUnicodeString(BaseName, p);
1148 RtlFreeUnicodeString(&Name);
1149 }
1150
1151
1152 /* ---------------------------------------------- PE Module support */
1153
1154 PMODULE_OBJECT
1155 LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING FileName)
1156 {
1157 unsigned int DriverSize, Idx, Idx2;
1158 ULONG RelocDelta, NumRelocs;
1159 DWORD CurrentSize, TotalRelocs;
1160 PVOID DriverBase;
1161 PULONG PEMagic;
1162 PIMAGE_DOS_HEADER PEDosHeader;
1163 PIMAGE_FILE_HEADER PEFileHeader;
1164 PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
1165 PIMAGE_SECTION_HEADER PESectionHeaders;
1166 PRELOCATION_DIRECTORY RelocDir;
1167 PRELOCATION_ENTRY RelocEntry;
1168 PMODULE_OBJECT LibraryModuleObject;
1169 HANDLE ModuleHandle;
1170 PMODULE_OBJECT ModuleObject;
1171 PVOID *ImportAddressList;
1172 PULONG FunctionNameList;
1173 PCHAR pName, SymbolNameBuf;
1174 WORD Hint;
1175 OBJECT_ATTRIBUTES ObjectAttributes;
1176 UNICODE_STRING ModuleName;
1177 WCHAR NameBuffer[60];
1178 MODULE_TEXT_SECTION* ModuleTextSection;
1179
1180 DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
1181
1182 /* Get header pointers */
1183 PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
1184 PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
1185 PEDosHeader->e_lfanew);
1186 PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase +
1187 PEDosHeader->e_lfanew + sizeof(ULONG));
1188 PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
1189 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
1190 PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase +
1191 PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
1192 sizeof(IMAGE_OPTIONAL_HEADER));
1193 CHECKPOINT;
1194
1195 /* Check file magic numbers */
1196 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
1197 {
1198 CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
1199 return 0;
1200 }
1201 if (PEDosHeader->e_lfanew == 0)
1202 {
1203 CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
1204 return NULL;
1205 }
1206 if (*PEMagic != IMAGE_PE_MAGIC)
1207 {
1208 CPRINT("Incorrect PE magic: %08x\n", *PEMagic);
1209 return NULL;
1210 }
1211 if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
1212 {
1213 CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
1214 return NULL;
1215 }
1216 CHECKPOINT;
1217
1218 /* FIXME: if image is fixed-address load, then fail */
1219
1220 /* FIXME: check/verify OS version number */
1221
1222 DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
1223 PEOptionalHeader->Magic,
1224 PEOptionalHeader->MajorLinkerVersion,
1225 PEOptionalHeader->MinorLinkerVersion);
1226 DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
1227 CHECKPOINT;
1228
1229 /* Determine the size of the module */
1230 DriverSize = PEOptionalHeader->SizeOfImage;
1231 DPRINT("DriverSize %x\n",DriverSize);
1232
1233 /* Allocate a virtual section for the module */
1234 DriverBase = MmAllocateSection(DriverSize);
1235 if (DriverBase == 0)
1236 {
1237 CPRINT("Failed to allocate a virtual section for driver\n");
1238 return 0;
1239 }
1240 CPRINT("DriverBase: %x\n", DriverBase);
1241 CHECKPOINT;
1242 /* Copy headers over */
1243 memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders);
1244 CurrentSize = 0;
1245 /* Copy image sections into virtual section */
1246 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1247 {
1248 // Copy current section into current offset of virtual section
1249 if (PESectionHeaders[Idx].Characteristics &
1250 (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
1251 {
1252 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1253 PESectionHeaders[Idx].VirtualAddress + DriverBase);
1254 memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1255 (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
1256 PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize );
1257 }
1258 else
1259 {
1260 DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n",
1261 PESectionHeaders[Idx].VirtualAddress + DriverBase);
1262 memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
1263 '\0', PESectionHeaders[Idx].Misc.VirtualSize);
1264
1265 }
1266 CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize,
1267 PEOptionalHeader->SectionAlignment);
1268
1269
1270 // CurrentBase = (PVOID)((DWORD)CurrentBase +
1271 // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize,
1272 // PEOptionalHeader->SectionAlignment));
1273 }
1274
1275 /* Perform relocation fixups */
1276 RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase;
1277 RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[
1278 IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
1279 DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n",
1280 DriverBase,
1281 PEOptionalHeader->ImageBase,
1282 RelocDelta);
1283 DPRINT("RelocDir %x\n",RelocDir);
1284 #if 1
1285 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
1286 {
1287 if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir)
1288 {
1289 DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n",
1290 PESectionHeaders[Idx].Name,
1291 PESectionHeaders[Idx].PointerToRawData);
1292 RelocDir = PESectionHeaders[Idx].PointerToRawData +
1293 ModuleLoadBase;
1294 CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize;
1295 break;
1296 }
1297 }
1298 #else
1299 RelocDir = RelocDir + (ULONG)DriverBase;
1300 CurrentSize = PEOptionalHeader->DataDirectory
1301 [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1302 #endif
1303 DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize);
1304 TotalRelocs = 0;
1305 while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0)
1306 {
1307 NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
1308 sizeof(WORD);
1309 /* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n",
1310 RelocDir,
1311 RelocDir->VirtualAddress,
1312 NumRelocs);*/
1313 RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir +
1314 sizeof(RELOCATION_DIRECTORY));
1315 for (Idx = 0; Idx < NumRelocs; Idx++)
1316 {
1317 ULONG Offset;
1318 ULONG Type;
1319 PDWORD RelocItem;
1320
1321 Offset = RelocEntry[Idx].TypeOffset & 0xfff;
1322 Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf;
1323 RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress +
1324 Offset);
1325 /* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n",
1326 RelocItem,
1327 Type,
1328 Type ? "HIGHLOW" : "ABS",
1329 *RelocItem,
1330 (*RelocItem) + RelocDelta); */
1331 if (Type == 3)
1332 {
1333 (*RelocItem) += RelocDelta;
1334 }
1335 else if (Type != 0)
1336 {
1337 CPRINT("Unknown relocation type %x at %x\n",Type, &Type);
1338 return NULL;
1339 }
1340 }
1341 TotalRelocs += RelocDir->SizeOfBlock;
1342 RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir +
1343 RelocDir->SizeOfBlock);
1344 // DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize);
1345 }
1346
1347 DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n",
1348 PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
1349 .VirtualAddress);
1350 /* Perform import fixups */
1351 if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1352 {
1353 PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
1354
1355 SymbolNameBuf = ExAllocatePoolWithTag(NonPagedPool, 512, TAG_SYM_BUF);
1356
1357 /* Process each import module */
1358 ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1359 ((DWORD)DriverBase + PEOptionalHeader->
1360 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
1361 DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
1362 while (ImportModuleDirectory->dwRVAModuleName)
1363 {
1364 /* Check to make sure that import lib is kernel */
1365 pName = (PCHAR) DriverBase +
1366 ImportModuleDirectory->dwRVAModuleName;
1367 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1368 for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
1369 ;
1370 for (Idx2 = 0; pName[Idx2] != '\0'; Idx2++)
1371 {
1372 NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
1373 }
1374 NameBuffer[Idx + Idx2] = 0;
1375 RtlInitUnicodeString (&ModuleName, NameBuffer);
1376 DPRINT("Import module: %wZ\n", &ModuleName);
1377
1378 LibraryModuleObject = LdrLoadModule(&ModuleName);
1379 if (LibraryModuleObject == 0)
1380 {
1381 CPRINT("Unknown import module: %wZ\n", &ModuleName);
1382 }
1383 /* Get the import address list */
1384 ImportAddressList = (PVOID *) ((DWORD)DriverBase +
1385 ImportModuleDirectory->dwRVAFunctionAddressList);
1386
1387 /* Get the list of functions to import */
1388 if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
1389 {
1390 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1391 ImportModuleDirectory->dwRVAFunctionNameList);
1392 }
1393 else
1394 {
1395 FunctionNameList = (PULONG) ((DWORD)DriverBase +
1396 ImportModuleDirectory->dwRVAFunctionAddressList);
1397 }
1398 /* Walk through function list and fixup addresses */
1399 while (*FunctionNameList != 0L)
1400 {
1401 if ((*FunctionNameList) & 0x80000000) // hint
1402 {
1403 pName = NULL;
1404
1405
1406 Hint = (*FunctionNameList) & 0xffff;
1407 }
1408 else // hint-name
1409 {
1410 pName = (PCHAR)((DWORD)DriverBase +
1411 *FunctionNameList + 2);
1412 Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
1413 }
1414 DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
1415
1416 /* Fixup the current import symbol */
1417 if (LibraryModuleObject != NULL)
1418 {
1419 *ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
1420 pName,
1421 Hint);
1422 }
1423 else
1424 {
1425 CPRINT("Unresolved kernel symbol: %s\n", pName);
1426 return(NULL);
1427 }
1428 ImportAddressList++;
1429 FunctionNameList++;
1430 }
1431 ImportModuleDirectory++;
1432 }
1433
1434 ExFreePool(SymbolNameBuf);
1435 }
1436
1437 /* Create ModuleName string */
1438 wcscpy(NameBuffer, MODULE_ROOT_NAME);
1439 if (wcsrchr(FileName->Buffer, '\\') != 0)
1440 {
1441 wcscat(NameBuffer, wcsrchr(FileName->Buffer, '\\') + 1);
1442 }
1443 else
1444 {
1445 wcscat(NameBuffer, FileName->Buffer);
1446 }
1447 RtlInitUnicodeString (&ModuleName, NameBuffer);
1448 CPRINT("Module name is: %wZ\n", &ModuleName);
1449
1450 /* Initialize ObjectAttributes for ModuleObject */
1451 InitializeObjectAttributes(&ObjectAttributes,
1452 &ModuleName,
1453 0,
1454 NULL,
1455 NULL);
1456
1457 /* Create module object */
1458 ModuleHandle = 0;
1459 ModuleObject = ObCreateObject(&ModuleHandle,
1460 STANDARD_RIGHTS_REQUIRED,
1461 &ObjectAttributes,
1462 IoDriverObjectType);
1463
1464 /* Initialize ModuleObject data */
1465 ModuleObject->Base = DriverBase;
1466 ModuleObject->Flags = MODULE_FLAG_PE;
1467 InsertTailList(&ModuleListHead,
1468 &ModuleObject->ListEntry);
1469 RtlCreateUnicodeString(&ModuleObject->FullName,
1470 FileName->Buffer);
1471 LdrpBuildModuleBaseName(&ModuleObject->BaseName,
1472 &ModuleObject->FullName);
1473
1474 ModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase +
1475 PEOptionalHeader->AddressOfEntryPoint);
1476 ModuleObject->Length = DriverSize;
1477 DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
1478
1479 ModuleObject->Image.PE.FileHeader =
1480 (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG));
1481
1482 DPRINT("FileHeader at %x\n", ModuleObject->Image.PE.FileHeader);
1483 ModuleObject->Image.PE.OptionalHeader =
1484 (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1485 sizeof(IMAGE_FILE_HEADER));
1486 DPRINT("OptionalHeader at %x\n", ModuleObject->Image.PE.OptionalHeader);
1487 ModuleObject->Image.PE.SectionList =
1488 (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) +
1489 sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
1490 DPRINT("SectionList at %x\n", ModuleObject->Image.PE.SectionList);
1491
1492 ModuleTextSection = ExAllocatePool(NonPagedPool,
1493 sizeof(MODULE_TEXT_SECTION));
1494 ModuleTextSection->Base = (ULONG)DriverBase;
1495 ModuleTextSection->Length = DriverSize;
1496 ModuleTextSection->SymbolsBase = NULL;
1497 ModuleTextSection->SymbolsLength = 0;
1498 ModuleTextSection->Name =
1499 ExAllocatePool(NonPagedPool,
1500 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
1501 wcscpy(ModuleTextSection->Name, NameBuffer);
1502 InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry);
1503
1504 ModuleObject->TextSection = ModuleTextSection;
1505
1506 return ModuleObject;
1507 }
1508
1509 static PVOID
1510 LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
1511 char *Name,
1512 unsigned short Hint)
1513 {
1514 WORD Idx;
1515 PVOID ExportAddress;
1516 PWORD OrdinalList;
1517 PDWORD FunctionList, NameList;
1518 PIMAGE_EXPORT_DIRECTORY ExportDir;
1519 ULONG ExportDirSize;
1520
1521 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
1522 RtlImageDirectoryEntryToData(ModuleObject->Base,
1523 TRUE,
1524 IMAGE_DIRECTORY_ENTRY_EXPORT,
1525 &ExportDirSize);
1526 DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize);
1527 if (ExportDir == NULL)
1528 {
1529 return NULL;
1530 }
1531
1532 FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base);
1533 NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base);
1534 OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base);
1535
1536 ExportAddress = 0;
1537
1538 if (Name != NULL)
1539 {
1540 for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++)
1541 {
1542 #if 0
1543 DPRINT(" Name:%s NameList[%d]:%s\n",
1544 Name,
1545 Idx,
1546 (DWORD) ModuleObject->Base + NameList[Idx]);
1547
1548 #endif
1549 if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
1550 {
1551 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1552 FunctionList[OrdinalList[Idx]]);
1553 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
1554 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
1555 {
1556 DPRINT("Forward: %s\n", (PCHAR)ExportAddress);
1557 ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress);
1558 DPRINT("ExportAddress: %p\n", ExportAddress);
1559 }
1560
1561 break;
1562 }
1563 }
1564 }
1565 else /* use hint */
1566 {
1567 ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
1568 FunctionList[Hint - ExportDir->Base]);
1569 }
1570
1571 if (ExportAddress == 0)
1572 {
1573 CPRINT("Export not found for %d:%s\n",
1574 Hint,
1575 Name != NULL ? Name : "(Ordinal)");
1576 return NULL;
1577 }
1578
1579 return ExportAddress;
1580 }
1581
1582
1583 static PMODULE_OBJECT
1584 LdrPEGetModuleObject(PUNICODE_STRING ModuleName)
1585 {
1586 PLIST_ENTRY Entry;
1587 PMODULE_OBJECT Module;
1588
1589 DPRINT("LdrPEGetModuleObject (ModuleName %wZ)\n",
1590 ModuleName);
1591
1592 Entry = ModuleListHead.Flink;
1593
1594 while (Entry != &ModuleListHead)
1595 {
1596 Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry);
1597
1598 DPRINT("Comparing %wZ and %wZ\n",
1599 &Module->BaseName,
1600 ModuleName);
1601
1602 if (!RtlCompareUnicodeString(&Module->BaseName, ModuleName, TRUE))
1603 {
1604 DPRINT("Module %x\n", Module);
1605 return Module;
1606 }
1607
1608 Entry = Entry->Flink;
1609 }
1610
1611 CPRINT("LdrPEGetModuleObject: Failed to find dll %wZ\n", ModuleName);
1612
1613 return NULL;
1614 }
1615
1616
1617 static PVOID
1618 LdrPEFixupForward(PCHAR ForwardName)
1619 {
1620 CHAR NameBuffer[128];
1621 UNICODE_STRING ModuleName;
1622 PCHAR p;
1623 PMODULE_OBJECT ModuleObject;
1624
1625 DPRINT("LdrPEFixupForward (%s)\n", ForwardName);
1626
1627 strcpy(NameBuffer, ForwardName);
1628 p = strchr(NameBuffer, '.');
1629 if (p == NULL)
1630 {
1631 return NULL;
1632 }
1633
1634 *p = 0;
1635
1636 DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1);
1637
1638 RtlCreateUnicodeStringFromAsciiz(&ModuleName,
1639 NameBuffer);
1640 ModuleObject = LdrPEGetModuleObject(&ModuleName);
1641 RtlFreeUnicodeString(&ModuleName);
1642
1643 DPRINT("ModuleObject: %p\n", ModuleObject);
1644
1645 if (ModuleObject == NULL)
1646 {
1647 CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
1648 return NULL;
1649 }
1650
1651 return LdrPEGetExportAddress(ModuleObject, p+1, 0);
1652 }
1653
1654 /* EOF */