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