2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/mm/sysldr.c
5 * PURPOSE: Contains the Kernel Loader (SYSLDR) for loading PE files.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 LIST_ENTRY PsLoadedModuleList
;
18 KSPIN_LOCK PsLoadedModuleSpinLock
;
19 PVOID PsNtosImageBase
;
21 /* FUNCTIONS *****************************************************************/
25 MiUpdateThunks(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
30 ULONG_PTR OldBaseTop
, Delta
;
31 PLDR_DATA_TABLE_ENTRY LdrEntry
;
32 PLIST_ENTRY NextEntry
;
34 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor
;
37 /* Calculate the top and delta */
38 OldBaseTop
= (ULONG_PTR
)OldBase
+ Size
- 1;
39 Delta
= (ULONG_PTR
)NewBase
- (ULONG_PTR
)OldBase
;
41 /* Loop the loader block */
42 for (NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
43 NextEntry
!= &LoaderBlock
->LoadOrderListHead
;
44 NextEntry
= NextEntry
->Flink
)
46 /* Get the loader entry */
47 LdrEntry
= CONTAINING_RECORD(NextEntry
,
51 /* Get the import table */
52 ImportDescriptor
= RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
54 IMAGE_DIRECTORY_ENTRY_IMPORT
,
56 if (!ImportDescriptor
) continue;
58 /* Make sure we have an IAT */
59 DPRINT("[Mm0]: Updating thunks in: %wZ\n", &LdrEntry
->BaseDllName
);
60 while ((ImportDescriptor
->Name
) &&
61 (ImportDescriptor
->OriginalFirstThunk
))
63 /* Get the image thunk */
64 ImageThunk
= (PVOID
)((ULONG_PTR
)LdrEntry
->DllBase
+
65 ImportDescriptor
->FirstThunk
);
68 /* Check if it's within this module */
69 if ((*ImageThunk
>= (ULONG_PTR
)OldBase
) && (*ImageThunk
<= OldBaseTop
))
72 DPRINT("[Mm0]: Updating IAT at: %p. Old Entry: %p. New Entry: %p.\n",
73 ImageThunk
, *ImageThunk
, *ImageThunk
+ Delta
);
77 /* Go to the next thunk */
81 /* Go to the next import */
89 MiSnapThunk(IN PVOID DllBase
,
91 IN PIMAGE_THUNK_DATA Name
,
92 IN PIMAGE_THUNK_DATA Address
,
93 IN PIMAGE_EXPORT_DIRECTORY ExportDirectory
,
95 IN BOOLEAN SnapForwarder
,
96 OUT PCHAR
*MissingApi
)
101 PUSHORT OrdinalTable
;
102 PIMAGE_IMPORT_BY_NAME NameImport
;
104 ULONG Low
= 0, Mid
= 0, High
;
107 PCHAR MissingForwarder
;
108 CHAR NameBuffer
[MAXIMUM_FILENAME_LENGTH
];
111 UNICODE_STRING ForwarderName
;
112 PLIST_ENTRY NextEntry
;
113 PLDR_DATA_TABLE_ENTRY LdrEntry
;
114 ULONG ForwardExportSize
;
115 PIMAGE_EXPORT_DIRECTORY ForwardExportDirectory
;
116 PIMAGE_IMPORT_BY_NAME ForwardName
;
118 IMAGE_THUNK_DATA ForwardThunk
;
121 /* Check if this is an ordinal */
122 IsOrdinal
= IMAGE_SNAP_BY_ORDINAL(Name
->u1
.Ordinal
);
123 if ((IsOrdinal
) && !(SnapForwarder
))
125 /* Get the ordinal number and set it as missing */
126 Ordinal
= (USHORT
)(IMAGE_ORDINAL(Name
->u1
.Ordinal
) -
127 ExportDirectory
->Base
);
128 *MissingApi
= (PCHAR
)(ULONG_PTR
)Ordinal
;
132 /* Get the VA if we don't have to snap */
133 if (!SnapForwarder
) Name
->u1
.AddressOfData
+= (ULONG_PTR
)ImageBase
;
134 NameImport
= (PIMAGE_IMPORT_BY_NAME
)Name
->u1
.AddressOfData
;
136 /* Copy the procedure name */
138 (PCHAR
)&NameImport
->Name
[0],
139 MAXIMUM_FILENAME_LENGTH
- 1);
141 /* Setup name tables */
142 DPRINT("Import name: %s\n", NameImport
->Name
);
143 NameTable
= (PULONG
)((ULONG_PTR
)DllBase
+
144 ExportDirectory
->AddressOfNames
);
145 OrdinalTable
= (PUSHORT
)((ULONG_PTR
)DllBase
+
146 ExportDirectory
->AddressOfNameOrdinals
);
148 /* Get the hint and check if it's valid */
149 Hint
= NameImport
->Hint
;
150 if ((Hint
< ExportDirectory
->NumberOfNames
) &&
151 !(strcmp((PCHAR
) NameImport
->Name
, (PCHAR
)DllBase
+ NameTable
[Hint
])))
153 /* We have a match, get the ordinal number from here */
154 Ordinal
= OrdinalTable
[Hint
];
158 /* Do a binary search */
159 High
= ExportDirectory
->NumberOfNames
- 1;
162 /* Get new middle value */
163 Mid
= (Low
+ High
) >> 1;
166 Ret
= strcmp((PCHAR
)NameImport
->Name
, (PCHAR
)DllBase
+ NameTable
[Mid
]);
184 /* Check if we couldn't find it */
185 if (High
< Low
) return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND
;
187 /* Otherwise, this is the ordinal */
188 Ordinal
= OrdinalTable
[Mid
];
192 /* Check if the ordinal is invalid */
193 if (Ordinal
>= ExportDirectory
->NumberOfFunctions
)
196 Status
= STATUS_DRIVER_ORDINAL_NOT_FOUND
;
200 /* In case the forwarder is missing */
201 MissingForwarder
= NameBuffer
;
203 /* Resolve the address and write it */
204 ExportTable
= (PULONG
)((ULONG_PTR
)DllBase
+
205 ExportDirectory
->AddressOfFunctions
);
206 Address
->u1
.Function
= (ULONG_PTR
)DllBase
+ ExportTable
[Ordinal
];
208 /* Assume success from now on */
209 Status
= STATUS_SUCCESS
;
211 /* Check if the function is actually a forwarder */
212 if ((Address
->u1
.Function
> (ULONG_PTR
)ExportDirectory
) &&
213 (Address
->u1
.Function
< ((ULONG_PTR
)ExportDirectory
+ ExportSize
)))
215 /* Now assume failure in case the forwarder doesn't exist */
216 Status
= STATUS_DRIVER_ENTRYPOINT_NOT_FOUND
;
218 /* Build the forwarder name */
219 DllName
.Buffer
= (PCHAR
)Address
->u1
.Function
;
220 DllName
.Length
= strchr(DllName
.Buffer
, '.') -
223 DllName
.MaximumLength
= DllName
.Length
;
226 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ForwarderName
,
230 /* We failed, just return an error */
234 /* Loop the module list */
235 NextEntry
= PsLoadedModuleList
.Flink
;
236 while (NextEntry
!= &PsLoadedModuleList
)
238 /* Get the loader entry */
239 LdrEntry
= CONTAINING_RECORD(NextEntry
,
240 LDR_DATA_TABLE_ENTRY
,
243 /* Check if it matches */
244 if (RtlPrefixString((PSTRING
)&ForwarderName
,
245 (PSTRING
)&LdrEntry
->BaseDllName
,
248 /* Get the forwarder export directory */
249 ForwardExportDirectory
=
250 RtlImageDirectoryEntryToData(LdrEntry
->DllBase
,
252 IMAGE_DIRECTORY_ENTRY_EXPORT
,
254 if (!ForwardExportDirectory
) break;
256 /* Allocate a name entry */
257 ForwardLength
= strlen(DllName
.Buffer
+ DllName
.Length
) +
259 ForwardName
= ExAllocatePoolWithTag(PagedPool
,
260 sizeof(*ForwardName
) +
263 if (!ForwardName
) break;
266 RtlCopyMemory(&ForwardName
->Name
[0],
267 DllName
.Buffer
+ DllName
.Length
,
269 ForwardName
->Hint
= 0;
271 /* Set the new address */
272 *(PULONG
)&ForwardThunk
.u1
.AddressOfData
= (ULONG
)ForwardName
;
274 /* Snap the forwarder */
275 Status
= MiSnapThunk(LdrEntry
->DllBase
,
279 ForwardExportDirectory
,
284 /* Free the forwarder name and set the thunk */
285 ExFreePool(ForwardName
);
286 Address
->u1
= ForwardThunk
.u1
;
290 /* Go to the next entry */
291 NextEntry
= NextEntry
->Flink
;
295 RtlFreeUnicodeString(&ForwarderName
);
305 MiResolveImageReferences(IN PVOID ImageBase
,
306 IN PUNICODE_STRING ImageFileDirectory
,
307 IN PUNICODE_STRING NamePrefix OPTIONAL
,
308 OUT PCHAR
*MissingApi
,
309 OUT PWCHAR
*MissingDriver
,
310 OUT PLOAD_IMPORTS
*LoadImports
)
312 PCHAR MissingApiBuffer
= *MissingApi
, ImportName
;
313 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor
, CurrentImport
;
314 ULONG ImportSize
, ImportCount
= 0, LoadedImportsSize
, ExportSize
;
315 PLOAD_IMPORTS LoadedImports
;
316 ULONG GdiLink
, NormalLink
, i
;
317 BOOLEAN ReferenceNeeded
, Loaded
;
318 ANSI_STRING TempString
;
319 UNICODE_STRING NameString
, DllName
;
320 PLDR_DATA_TABLE_ENTRY LdrEntry
= NULL
, DllEntry
, ImportEntry
= NULL
;
321 PVOID ImportBase
, DllBase
;
322 PLIST_ENTRY NextEntry
;
323 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
325 PIMAGE_THUNK_DATA OrigThunk
, FirstThunk
;
327 DPRINT("%s - ImageBase: %p. ImageFileDirectory: %wZ\n",
328 __FUNCTION__
, ImageBase
, ImageFileDirectory
);
330 /* Assume no imports */
331 *LoadImports
= (PVOID
)-2;
333 /* Get the import descriptor */
334 ImportDescriptor
= RtlImageDirectoryEntryToData(ImageBase
,
336 IMAGE_DIRECTORY_ENTRY_IMPORT
,
338 if (!ImportDescriptor
) return STATUS_SUCCESS
;
340 /* Loop all imports to count them */
341 for (CurrentImport
= ImportDescriptor
;
342 (CurrentImport
->Name
) && (CurrentImport
->OriginalFirstThunk
);
349 /* Make sure we have non-zero imports */
352 /* Calculate and allocate the list we'll need */
353 LoadedImportsSize
= ImportCount
* sizeof(PVOID
) + sizeof(SIZE_T
);
354 LoadedImports
= ExAllocatePoolWithTag(PagedPool
,
359 /* Zero it and set the count */
360 RtlZeroMemory(LoadedImports
, LoadedImportsSize
);
361 LoadedImports
->Count
= ImportCount
;
367 LoadedImports
= NULL
;
370 /* Reset the import count and loop descriptors again */
371 ImportCount
= GdiLink
= NormalLink
= 0;
372 while ((ImportDescriptor
->Name
) && (ImportDescriptor
->OriginalFirstThunk
))
375 ImportName
= (PCHAR
)((ULONG_PTR
)ImageBase
+ ImportDescriptor
->Name
);
377 /* Check if this is a GDI driver */
379 !(_strnicmp(ImportName
, "win32k", sizeof("win32k") - 1));
381 /* We can also allow dxapi */
382 NormalLink
= NormalLink
|
383 ((_strnicmp(ImportName
, "win32k", sizeof("win32k") - 1)) &&
384 (_strnicmp(ImportName
, "dxapi", sizeof("dxapi") - 1)));
386 /* Check if this is a valid GDI driver */
387 if ((GdiLink
) && (NormalLink
))
389 /* It's not, it's importing stuff it shouldn't be! */
390 DPRINT1("Invalid driver!\n");
391 //MiDereferenceImports(LoadedImports);
392 if (LoadedImports
) ExFreePool(LoadedImports
);
393 return STATUS_PROCEDURE_NOT_FOUND
;
396 /* Check if this is a "core" import, which doesn't get referenced */
397 if (!(_strnicmp(ImportName
, "ntoskrnl", sizeof("ntoskrnl") - 1)) ||
398 !(_strnicmp(ImportName
, "win32k", sizeof("win32k") - 1)) ||
399 !(_strnicmp(ImportName
, "hal", sizeof("hal") - 1)))
401 /* Don't reference this */
402 ReferenceNeeded
= FALSE
;
406 /* Reference these modules */
407 ReferenceNeeded
= TRUE
;
410 /* Now setup a unicode string for the import */
411 RtlInitAnsiString(&TempString
, ImportName
);
412 Status
= RtlAnsiStringToUnicodeString(&NameString
, &TempString
, TRUE
);
413 if (!NT_SUCCESS(Status
))
416 //MiDereferenceImports(LoadedImports);
417 if (LoadedImports
) ExFreePool(LoadedImports
);
421 /* We don't support name prefixes yet */
422 if (NamePrefix
) DPRINT1("Name Prefix not yet supported!\n");
424 /* Remember that we haven't loaded the import at this point */
429 /* Loop the driver list */
430 NextEntry
= PsLoadedModuleList
.Flink
;
431 while (NextEntry
!= &PsLoadedModuleList
)
433 /* Get the loader entry and compare the name */
434 LdrEntry
= CONTAINING_RECORD(NextEntry
,
435 LDR_DATA_TABLE_ENTRY
,
437 if (RtlEqualUnicodeString(&NameString
,
438 &LdrEntry
->BaseDllName
,
441 /* Get the base address */
442 ImportBase
= LdrEntry
->DllBase
;
444 /* Check if we haven't loaded yet, and we need references */
445 if (!(Loaded
) && (ReferenceNeeded
))
447 /* Make sure we're not already loading */
448 if (!(LdrEntry
->Flags
& LDRP_LOAD_IN_PROGRESS
))
450 /* Increase the load count */
451 LdrEntry
->LoadCount
++;
455 /* Done, break out */
459 /* Go to the next entry */
460 NextEntry
= NextEntry
->Flink
;
463 /* Check if we haven't loaded the import yet */
466 /* Setup the import DLL name */
467 DllName
.MaximumLength
= NameString
.Length
+
468 ImageFileDirectory
->Length
+
469 sizeof(UNICODE_NULL
);
470 DllName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
471 DllName
.MaximumLength
,
475 /* Setup the base length and copy it */
476 DllName
.Length
= ImageFileDirectory
->Length
;
477 RtlCopyMemory(DllName
.Buffer
,
478 ImageFileDirectory
->Buffer
,
479 ImageFileDirectory
->Length
);
481 /* Now add the import name and null-terminate it */
482 RtlAppendStringToString((PSTRING
)&DllName
,
483 (PSTRING
)&NameString
);
484 DllName
.Buffer
[(DllName
.MaximumLength
- 1) / 2] = UNICODE_NULL
;
487 Status
= MmLoadSystemImage(&DllName
,
493 if (NT_SUCCESS(Status
))
495 /* We can free the DLL Name */
496 ExFreePool(DllName
.Buffer
);
500 /* Fill out the information for the error */
501 DPRINT1("Failed to import: %S\n", DllName
.Buffer
);
502 *MissingDriver
= DllName
.Buffer
;
503 *(PULONG
)MissingDriver
|= 1;
509 /* We're out of resources */
510 Status
= STATUS_INSUFFICIENT_RESOURCES
;
513 /* Check if we're OK until now */
514 if (NT_SUCCESS(Status
))
516 /* We're now loaded */
520 ASSERT(DllBase
= DllEntry
->DllBase
);
522 /* Call the initialization routines */
524 Status
= MmCallDllInitialize(DllEntry
, &PsLoadedModuleList
);
525 if (!NT_SUCCESS(Status
))
527 /* We failed, unload the image */
528 MmUnloadSystemImage(DllEntry
);
535 /* Check if we failed by here */
536 if (!NT_SUCCESS(Status
))
538 /* Cleanup and return */
539 DPRINT1("Failed loading import\n");
540 RtlFreeUnicodeString(&NameString
);
541 //MiDereferenceImports(LoadedImports);
542 if (LoadedImports
) ExFreePool(LoadedImports
);
546 /* Loop again to make sure that everything is OK */
550 /* Check if we're support to reference this import */
551 if ((ReferenceNeeded
) && (LoadedImports
))
553 /* Make sure we're not already loading */
554 if (!(LdrEntry
->Flags
& LDRP_LOAD_IN_PROGRESS
))
557 LoadedImports
->Entry
[ImportCount
] = LdrEntry
;
562 /* Free the import name */
563 RtlFreeUnicodeString(&NameString
);
565 /* Set the missing driver name and get the export directory */
566 *MissingDriver
= LdrEntry
->BaseDllName
.Buffer
;
567 ExportDirectory
= RtlImageDirectoryEntryToData(ImportBase
,
569 IMAGE_DIRECTORY_ENTRY_EXPORT
,
571 if (!ExportDirectory
)
573 /* Cleanup and return */
574 DPRINT1("Invalid driver: %wZ\n", &LdrEntry
->BaseDllName
);
575 //MiDereferenceImports(LoadedImports);
576 if (LoadedImports
) ExFreePool(LoadedImports
);
577 return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND
;
580 /* Make sure we have an IAT */
581 if (ImportDescriptor
->OriginalFirstThunk
)
583 /* Get the first thunks */
584 OrigThunk
= (PVOID
)((ULONG_PTR
)ImageBase
+
585 ImportDescriptor
->OriginalFirstThunk
);
586 FirstThunk
= (PVOID
)((ULONG_PTR
)ImageBase
+
587 ImportDescriptor
->FirstThunk
);
590 while (OrigThunk
->u1
.AddressOfData
)
593 Status
= MiSnapThunk(ImportBase
,
601 if (!NT_SUCCESS(Status
))
603 /* Cleanup and return */
604 //MiDereferenceImports(LoadedImports);
605 if (LoadedImports
) ExFreePool(LoadedImports
);
609 /* Reset the buffer */
610 *MissingApi
= MissingApiBuffer
;
614 /* Go to the next import */
618 /* Check if we have an import list */
621 /* Reset the count again, and loop entries*/
623 for (i
= 0; i
< LoadedImports
->Count
; i
++)
625 if (LoadedImports
->Entry
[i
])
627 /* Got an entry, OR it with 1 in case it's the single entry */
628 ImportEntry
= (PVOID
)((ULONG_PTR
)LoadedImports
->Entry
[i
] | 1);
633 /* Check if we had no imports */
636 /* Free the list and set it to no imports */
637 ExFreePool(LoadedImports
);
638 LoadedImports
= (PVOID
)-2;
640 else if (ImportCount
== 1)
642 /* Just one entry, we can free the table and only use our entry */
643 ExFreePool(LoadedImports
);
644 LoadedImports
= (PLOAD_IMPORTS
)ImportEntry
;
646 else if (ImportCount
!= LoadedImports
->Count
)
648 /* FIXME: Can this happen? */
649 DPRINT1("Unhandled scenario\n");
653 /* Return the list */
654 *LoadImports
= LoadedImports
;
658 return STATUS_SUCCESS
;
663 MiReloadBootLoadedDrivers(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
665 PLIST_ENTRY NextEntry
;
667 PIMAGE_NT_HEADERS NtHeader
;
668 PLDR_DATA_TABLE_ENTRY LdrEntry
;
669 PIMAGE_FILE_HEADER FileHeader
;
671 PIMAGE_DATA_DIRECTORY DataDirectory
;
672 PVOID DllBase
, NewImageAddress
;
674 ULONG DriverSize
= 0, Size
;
675 PIMAGE_SECTION_HEADER Section
;
677 /* Loop driver list */
678 for (NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
679 NextEntry
!= &LoaderBlock
->LoadOrderListHead
;
680 NextEntry
= NextEntry
->Flink
)
682 /* Get the loader entry and NT header */
683 LdrEntry
= CONTAINING_RECORD(NextEntry
,
684 LDR_DATA_TABLE_ENTRY
,
686 NtHeader
= RtlImageNtHeader(LdrEntry
->DllBase
);
689 DPRINT("[Mm0]: Driver at: %p ending at: %p for module: %wZ\n",
691 (ULONG_PTR
)LdrEntry
->DllBase
+ LdrEntry
->SizeOfImage
,
692 &LdrEntry
->FullDllName
);
694 /* Skip kernel and HAL */
695 /* ROS HACK: Skip BOOTVID/KDCOM too */
697 if (i
<= 4) continue;
699 /* Skip non-drivers */
700 if (!NtHeader
) continue;
702 #if 1 // Disable for FreeLDR 2.5
703 /* Get header pointers */
704 Section
= IMAGE_FIRST_SECTION(NtHeader
);
706 /* Determine the size of the module */
707 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
709 /* Skip this section if we're not supposed to load it */
710 if (!(Section
[i
].Characteristics
& IMAGE_SCN_TYPE_NOLOAD
))
712 /* Add the size of this section into the total size */
713 Size
= Section
[i
].VirtualAddress
+ Section
[i
].Misc
.VirtualSize
;
714 DriverSize
= max(DriverSize
, Size
);
718 /* Round up the driver size to section alignment */
719 DriverSize
= ROUND_UP(DriverSize
, NtHeader
->OptionalHeader
.SectionAlignment
);
722 /* Get the file header and make sure we can relocate */
723 FileHeader
= &NtHeader
->FileHeader
;
724 if (FileHeader
->Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
) continue;
725 if (NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
<
726 IMAGE_DIRECTORY_ENTRY_BASERELOC
) continue;
728 /* Everything made sense until now, check the relocation section too */
729 DataDirectory
= &NtHeader
->OptionalHeader
.
730 DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
731 if (!DataDirectory
->VirtualAddress
)
733 /* We don't really have relocations */
738 /* Make sure the size is valid */
739 if ((DataDirectory
->VirtualAddress
+ DataDirectory
->Size
) >
740 LdrEntry
->SizeOfImage
)
742 /* They're not, skip */
746 /* We have relocations */
750 /* Remember the original address */
751 DllBase
= LdrEntry
->DllBase
;
753 /* Allocate a virtual section for the module */
754 NewImageAddress
= MmAllocateSection(DriverSize
, NULL
);
755 if (!NewImageAddress
)
757 /* Shouldn't happen */
758 DPRINT1("[Mm0]: Couldn't allocate driver section!\n");
763 DPRINT("[Mm0]: Copying from: %p to: %p\n", DllBase
, NewImageAddress
);
764 ASSERT(ExpInitializationPhase
== 0);
766 #if 0 // Enable for FreeLDR 2.5
767 /* Now copy the entire driver over */
768 RtlCopyMemory(NewImageAddress
, DllBase
, DriverSize
);
770 /* Copy headers over */
771 RtlCopyMemory(NewImageAddress
,
773 NtHeader
->OptionalHeader
.SizeOfHeaders
);
775 /* Copy image sections into virtual section */
776 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
778 /* Get the size of this section and check if it's valid and on-disk */
779 Size
= Section
[i
].VirtualAddress
+ Section
[i
].Misc
.VirtualSize
;
780 if ((Size
<= DriverSize
) && (Section
[i
].SizeOfRawData
))
782 /* Copy the data from the disk to the image */
783 RtlCopyMemory((PVOID
)((ULONG_PTR
)NewImageAddress
+
784 Section
[i
].VirtualAddress
),
785 (PVOID
)((ULONG_PTR
)DllBase
+
786 Section
[i
].PointerToRawData
),
787 Section
[i
].Misc
.VirtualSize
>
788 Section
[i
].SizeOfRawData
?
789 Section
[i
].SizeOfRawData
:
790 Section
[i
].Misc
.VirtualSize
);
796 ASSERT(*(PULONG
)NewImageAddress
== *(PULONG
)DllBase
);
798 /* Set the image base to the old address */
799 NtHeader
->OptionalHeader
.ImageBase
= (ULONG_PTR
)DllBase
;
801 /* Check if we had relocations */
804 /* Relocate the image */
805 Status
= LdrRelocateImageWithBias(NewImageAddress
,
809 STATUS_CONFLICTING_ADDRESSES
,
810 STATUS_INVALID_IMAGE_FORMAT
);
811 if (!NT_SUCCESS(Status
))
813 /* This shouldn't happen */
814 DPRINT1("Relocations failed!\n");
819 /* Update the loader entry */
820 LdrEntry
->DllBase
= NewImageAddress
;
822 /* Update the thunks */
823 DPRINT("[Mm0]: Updating thunks to: %wZ\n", &LdrEntry
->BaseDllName
);
824 MiUpdateThunks(LoaderBlock
,
827 LdrEntry
->SizeOfImage
);
829 /* Update the loader entry */
830 LdrEntry
->Flags
|= 0x01000000;
831 LdrEntry
->EntryPoint
= (PVOID
)((ULONG_PTR
)NewImageAddress
+
832 NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
833 LdrEntry
->SizeOfImage
= DriverSize
;
839 MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
841 PLDR_DATA_TABLE_ENTRY LdrEntry
, NewEntry
;
842 PLIST_ENTRY ListHead
, NextEntry
;
845 /* Setup the loaded module list and lock */
846 KeInitializeSpinLock(&PsLoadedModuleSpinLock
);
847 InitializeListHead(&PsLoadedModuleList
);
849 /* Get loop variables and the kernel entry */
850 ListHead
= &LoaderBlock
->LoadOrderListHead
;
851 NextEntry
= ListHead
->Flink
;
852 LdrEntry
= CONTAINING_RECORD(NextEntry
,
853 LDR_DATA_TABLE_ENTRY
,
855 PsNtosImageBase
= LdrEntry
->DllBase
;
857 /* Loop the loader block */
858 while (NextEntry
!= ListHead
)
860 /* Get the loader entry */
861 LdrEntry
= CONTAINING_RECORD(NextEntry
,
862 LDR_DATA_TABLE_ENTRY
,
865 /* FIXME: ROS HACK. Make sure this is a driver */
866 if (!RtlImageNtHeader(LdrEntry
->DllBase
))
868 /* Skip this entry */
869 NextEntry
= NextEntry
->Flink
;
873 /* Calculate the size we'll need and allocate a copy */
874 EntrySize
= sizeof(LDR_DATA_TABLE_ENTRY
) +
875 LdrEntry
->BaseDllName
.MaximumLength
+
876 sizeof(UNICODE_NULL
);
877 NewEntry
= ExAllocatePoolWithTag(NonPagedPool
, EntrySize
, TAG_LDR_WSTR
);
878 if (!NewEntry
) return FALSE
;
880 /* Copy the entry over */
881 *NewEntry
= *LdrEntry
;
883 /* Allocate the name */
884 NewEntry
->FullDllName
.Buffer
=
885 ExAllocatePoolWithTag(PagedPool
,
886 LdrEntry
->FullDllName
.MaximumLength
+
887 sizeof(UNICODE_NULL
),
889 if (!NewEntry
->FullDllName
.Buffer
) return FALSE
;
891 /* Set the base name */
892 NewEntry
->BaseDllName
.Buffer
= (PVOID
)(NewEntry
+ 1);
894 /* Copy the full and base name */
895 RtlCopyMemory(NewEntry
->FullDllName
.Buffer
,
896 LdrEntry
->FullDllName
.Buffer
,
897 LdrEntry
->FullDllName
.MaximumLength
);
898 RtlCopyMemory(NewEntry
->BaseDllName
.Buffer
,
899 LdrEntry
->BaseDllName
.Buffer
,
900 LdrEntry
->BaseDllName
.MaximumLength
);
902 /* Null-terminate the base name */
903 NewEntry
->BaseDllName
.Buffer
[NewEntry
->BaseDllName
.Length
/
904 sizeof(WCHAR
)] = UNICODE_NULL
;
906 /* Insert the entry into the list */
907 InsertTailList(&PsLoadedModuleList
, &NewEntry
->InLoadOrderLinks
);
908 NextEntry
= NextEntry
->Flink
;
911 /* Build the import lists for the boot drivers */
912 //MiBuildImportsForBootDrivers();