4 extern BOOLEAN FrLdrBootType
;
6 ULONG_PTR NextModuleBase
= KERNEL_BASE_PHYS
;
7 PLOADER_MODULE CurrentModule
= NULL
;
17 extern BOOLEAN
FrLdrLoadDriver(PCHAR szFileName
, INT nPos
);
19 PVOID AnsiData
, OemData
, UnicodeData
, RegistryData
, KernelData
, HalData
, DriverData
[16];
20 ULONG RegistrySize
, AnsiSize
, OemSize
, UnicodeSize
, KernelSize
, HalSize
, DriverSize
[16];
23 /* MODULE MANAGEMENT **********************************************************/
27 LdrGetModuleObject(IN PCHAR ModuleName
)
31 for (i
= 0; i
< LoaderBlock
.ModsCount
; i
++)
33 if (strstr(_strupr((PCHAR
)reactos_modules
[i
].String
), _strupr(ModuleName
)))
35 return &reactos_modules
[i
];
44 LdrPEGetOrLoadModule(IN PCHAR ModuleName
,
45 IN PCHAR ImportedName
,
46 IN PLOADER_MODULE
* ImportedModule
)
48 NTSTATUS Status
= STATUS_SUCCESS
;
50 *ImportedModule
= LdrGetModuleObject(ImportedName
);
51 if (*ImportedModule
== NULL
)
53 if (!FrLdrLoadDriver(ImportedName
, 0))
55 return STATUS_UNSUCCESSFUL
;
59 return LdrPEGetOrLoadModule(ModuleName
, ImportedName
, ImportedModule
);
68 FrLdrLoadModule(PFILE ModuleImage
,
72 ULONG LocalModuleSize
;
73 PLOADER_MODULE ModuleData
;
77 /* Get current module data structure and module name string array */
78 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
80 /* Get only the Module Name */
83 TempName
= strchr(ModuleName
, '\\');
86 ModuleName
= TempName
+ 1;
90 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
93 LocalModuleSize
= FsGetFileSize(ModuleImage
);
95 /* Fill out Module Data Structure */
96 ModuleData
->ModStart
= NextModuleBase
;
97 ModuleData
->ModEnd
= NextModuleBase
+ LocalModuleSize
;
100 strcpy(NameBuffer
, ModuleName
);
101 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
103 /* NLS detection for NT Loader Block */
104 if (!_stricmp(NameBuffer
, "ansi.nls"))
106 AnsiData
= (PVOID
)NextModuleBase
;
107 AnsiSize
= LocalModuleSize
;
109 else if (!_stricmp(NameBuffer
, "oem.nls"))
111 OemData
= (PVOID
)NextModuleBase
;
112 OemSize
= LocalModuleSize
;
114 else if (!_stricmp(NameBuffer
, "casemap.nls"))
116 UnicodeData
= (PVOID
)NextModuleBase
;
117 UnicodeSize
= LocalModuleSize
;
119 else if (!(_stricmp(NameBuffer
, "system")) ||
120 !(_stricmp(NameBuffer
, "system.hiv")))
122 RegistryData
= (PVOID
)NextModuleBase
;
123 RegistrySize
= LocalModuleSize
;
126 /* Load the file image */
127 FsReadFile(ModuleImage
, LocalModuleSize
, NULL
, (PVOID
)NextModuleBase
);
129 /* Move to next memory block and increase Module Count */
130 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
131 LoaderBlock
.ModsCount
++;
132 // DbgPrint("NextBase, ImageSize, ModStart, ModEnd %p %p %p %p\n",
133 // NextModuleBase, LocalModuleSize, ModuleData->ModStart, ModuleData->ModEnd);
135 /* Return Module Size if required */
136 if (ModuleSize
!= NULL
) {
137 *ModuleSize
= LocalModuleSize
;
140 return(ModuleData
->ModStart
);
145 FrLdrCreateModule(LPCSTR ModuleName
)
147 PLOADER_MODULE ModuleData
;
150 /* Get current module data structure and module name string array */
151 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
152 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
154 /* Set up the structure */
155 ModuleData
->ModStart
= NextModuleBase
;
156 ModuleData
->ModEnd
= -1;
159 strcpy(NameBuffer
, ModuleName
);
160 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
162 /* Set the current Module */
163 CurrentModule
= ModuleData
;
165 /* Return Module Base Address */
166 return(ModuleData
->ModStart
);
171 FrLdrCloseModule(ULONG_PTR ModuleBase
,
174 PLOADER_MODULE ModuleData
= CurrentModule
;
176 /* Make sure a module is opened */
179 /* Make sure this is the right module and that it hasn't been closed */
180 if ((ModuleBase
== ModuleData
->ModStart
) && (ModuleData
->ModEnd
== MAXULONG_PTR
)) {
182 /* Close the Module */
183 ModuleData
->ModEnd
= ModuleData
->ModStart
+ ModuleSize
;
185 /* Set the next Module Base and increase the number of modules */
186 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
187 LoaderBlock
.ModsCount
++;
189 /* Close the currently opened module */
190 CurrentModule
= NULL
;
201 /* PE IMAGE LOADER ***********************************************************/
205 LdrPEFixupForward(IN PCHAR ForwardName
)
207 CHAR NameBuffer
[128];
209 PLOADER_MODULE ModuleObject
;
211 strcpy(NameBuffer
, ForwardName
);
212 p
= strchr(NameBuffer
, '.');
213 if (p
== NULL
) return NULL
;
216 ModuleObject
= LdrGetModuleObject(NameBuffer
);
219 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
223 return LdrPEGetExportByName((PVOID
)ModuleObject
->ModStart
, (PUCHAR
)(p
+ 1), 0xffff);
228 LdrPEGetExportByName(PVOID BaseAddress
,
232 PIMAGE_EXPORT_DIRECTORY ExportDir
;
239 LONG minn
, maxn
, mid
, res
;
242 /* HAL and NTOS use a virtual address, switch it to physical mode */
243 if ((ULONG_PTR
)BaseAddress
& KSEG0_BASE
)
245 BaseAddress
= RVA(BaseAddress
, -KSEG0_BASE
);
248 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
249 RtlImageDirectoryEntryToData(BaseAddress
,
251 IMAGE_DIRECTORY_ENTRY_EXPORT
,
255 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
259 /* The symbol names may be missing entirely */
260 if (!ExportDir
->AddressOfNames
)
262 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
267 * Get header pointers
269 ExNames
= (ULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
270 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
271 ExFunctions
= (ULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
274 * Check the hint first
276 if (Hint
< ExportDir
->NumberOfNames
)
278 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
279 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
281 Ordinal
= ExOrdinals
[Hint
];
282 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
283 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
284 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
286 Function
= LdrPEFixupForward((PCHAR
)Function
);
287 if (Function
== NULL
)
289 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function
);
294 if (Function
!= NULL
) return Function
;
302 maxn
= ExportDir
->NumberOfNames
- 1;
305 mid
= (minn
+ maxn
) / 2;
307 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
308 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
311 Ordinal
= ExOrdinals
[mid
];
312 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
313 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
314 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
316 Function
= LdrPEFixupForward((PCHAR
)Function
);
317 if (Function
== NULL
)
319 DbgPrint("1: failed to find %s\n", Function
);
323 if (Function
!= NULL
)
338 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
339 DbgPrint("2: failed to find %s\n",SymbolName
);
345 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
346 PLOADER_MODULE LoaderModule
,
347 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
349 PVOID
* ImportAddressList
;
350 PULONG_PTR FunctionNameList
;
352 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
354 return STATUS_UNSUCCESSFUL
;
357 /* Get the import address list. */
358 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
360 /* Get the list of functions to import. */
361 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
363 FunctionNameList
= (PULONG_PTR
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
367 FunctionNameList
= (PULONG_PTR
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
370 /* Walk through function list and fixup addresses. */
371 while (*FunctionNameList
!= 0L)
373 if ((*FunctionNameList
) & 0x80000000)
375 DbgPrint("Failed to import ordinal from %s\n", LoaderModule
->String
);
376 return STATUS_UNSUCCESSFUL
;
380 IMAGE_IMPORT_BY_NAME
*pe_name
;
381 pe_name
= RVA(DriverBase
, *FunctionNameList
);
382 *ImportAddressList
= LdrPEGetExportByName((PVOID
)LoaderModule
->ModStart
, pe_name
->Name
, pe_name
->Hint
);
384 /* Fixup the address to be virtual */
385 *ImportAddressList
= RVA(*ImportAddressList
, KSEG0_BASE
);
387 //DbgPrint("Looked for: %s and found: %p\n", pe_name->Name, *ImportAddressList);
388 if ((*ImportAddressList
) == NULL
)
390 DbgPrint("Failed to import %s from %s\n", pe_name
->Name
, LoaderModule
->String
);
391 return STATUS_UNSUCCESSFUL
;
397 return STATUS_SUCCESS
;
402 LdrPEFixupImports(IN PVOID DllBase
,
405 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
408 PLOADER_MODULE ImportedModule
;
411 /* Process each import module */
412 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
413 RtlImageDirectoryEntryToData(DllBase
,
415 IMAGE_DIRECTORY_ENTRY_IMPORT
,
417 while (ImportModuleDirectory
&& ImportModuleDirectory
->Name
)
419 /* Check to make sure that import lib is kernel */
420 ImportedName
= (PCHAR
) DllBase
+ ImportModuleDirectory
->Name
;
421 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
423 Status
= LdrPEGetOrLoadModule(DllName
, ImportedName
, &ImportedModule
);
424 if (!NT_SUCCESS(Status
)) return Status
;
426 Status
= LdrPEProcessImportDirectoryEntry(DllBase
, ImportedModule
, ImportModuleDirectory
);
427 if (!NT_SUCCESS(Status
)) return Status
;
429 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
430 ImportModuleDirectory
++;
433 return STATUS_SUCCESS
;
438 FrLdrReadAndMapImage(IN PFILE Image
,
442 PVOID ImageBase
, LoadBase
, ReadBuffer
;
443 ULONG ImageId
= LoaderBlock
.ModsCount
;
444 ULONG i
, Size
, ImageSize
, SizeOfHeaders
;
445 PIMAGE_NT_HEADERS NtHeader
;
446 PIMAGE_SECTION_HEADER Section
;
447 NTSTATUS Status
= STATUS_SUCCESS
;
448 PLOADER_MODULE pModule
;
450 /* Try to see, maybe it's loaded already */
451 if ((pModule
= LdrGetModuleObject(Name
)) != NULL
)
453 /* It's loaded, return LoadBase */
454 ImageBase
= (PVOID
)pModule
->ModStart
;
455 LoadBase
= RVA(ImageBase
, -KSEG0_BASE
);
459 /* Set the virtual (image) and physical (load) addresses */
460 LoadBase
= (PVOID
)NextModuleBase
;
461 ImageBase
= RVA(LoadBase
, KSEG0_BASE
);
463 /* Allocate a temporary buffer for the read */
464 ReadBuffer
= MmHeapAlloc(MM_PAGE_SIZE
);
468 DbgPrint("Failed to allocate a temporary buffer for the read\n");
472 /* Set the file pointer to zero */
473 FsSetFilePointer(Image
, 0);
475 /* Load first page of the file image */
476 if (!FsReadFile(Image
, MM_PAGE_SIZE
, NULL
, ReadBuffer
))
479 DbgPrint("Failed to read image: %s\n", Name
);
483 /* Get image headers */
484 NtHeader
= RtlImageNtHeader(ReadBuffer
);
487 DbgPrint("Failed to read image (bad PE signature) %s\n", Name
);
491 /* Allocate memory for the driver */
492 ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
493 LoadBase
= MmAllocateMemoryAtAddress(ImageSize
, LoadBase
, LoaderSystemCode
);
496 /* Copy headers over */
497 SizeOfHeaders
= NtHeader
->OptionalHeader
.SizeOfHeaders
;
498 if (SizeOfHeaders
< MM_PAGE_SIZE
)
500 RtlMoveMemory(LoadBase
, ReadBuffer
, SizeOfHeaders
);
504 RtlMoveMemory(LoadBase
, ReadBuffer
, MM_PAGE_SIZE
);
505 if (!FsReadFile(Image
, SizeOfHeaders
- MM_PAGE_SIZE
, NULL
,
506 (PVOID
)((ULONG_PTR
)LoadBase
+ MM_PAGE_SIZE
)))
508 DbgPrint("Failed to read image: %s\n", Name
);
513 /* Free the temporary buffer */
514 MmHeapFree(ReadBuffer
);
516 /* Get the first section */
517 NtHeader
= RtlImageNtHeader(LoadBase
);
518 Section
= IMAGE_FIRST_SECTION(NtHeader
);
520 /* Read image sections into virtual section */
521 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
523 /* Get the size of this section and check if it's valid */
524 Size
= Section
[i
].VirtualAddress
+ Section
[i
].Misc
.VirtualSize
;
525 if (Size
<= ImageSize
)
527 if (Section
[i
].SizeOfRawData
)
529 /* Copy the data from the disk to the image */
530 FsSetFilePointer(Image
, Section
[i
].PointerToRawData
);
531 if (!FsReadFile(Image
,
532 Section
[i
].Misc
.VirtualSize
>
533 Section
[i
].SizeOfRawData
?
534 Section
[i
].SizeOfRawData
:
535 Section
[i
].Misc
.VirtualSize
,
537 (PVOID
)((ULONG_PTR
)LoadBase
+
538 Section
[i
].VirtualAddress
)))
540 DbgPrint("Failed to read image: %s\n", Name
);
546 /* Clear the BSS area */
547 RtlZeroMemory((PVOID
)((ULONG_PTR
)LoadBase
+
548 Section
[i
].VirtualAddress
),
549 Section
[i
].Misc
.VirtualSize
);
554 DbgPrint("Section %s in %s doesn't fit: VA: %lx, Size: %lx\n",
555 Section
[i
].Name
, Name
, Section
[i
].VirtualAddress
,
556 Section
[i
].Misc
.VirtualSize
);
560 /* Calculate Difference between Real Base and Compiled Base*/
561 Status
= LdrRelocateImageWithBias(LoadBase
,
562 (ULONG_PTR
)ImageBase
-
567 STATUS_SUCCESS
, // allow stripped files
571 STATUS_UNSUCCESSFUL
);
572 if (!NT_SUCCESS(Status
))
575 DbgPrint("Failed to relocate image: %s\n", Name
);
579 /* Fill out Module Data Structure */
580 reactos_modules
[ImageId
].ModStart
= (ULONG_PTR
)ImageBase
;
581 reactos_modules
[ImageId
].ModEnd
= (ULONG_PTR
)ImageBase
+ ImageSize
;
582 strcpy(reactos_module_strings
[ImageId
], Name
);
583 reactos_modules
[ImageId
].String
= (ULONG_PTR
)reactos_module_strings
[ImageId
];
584 LoaderBlock
.ModsCount
++;
586 /* Detect kernel or HAL */
587 if (!_stricmp(Name
, "ntoskrnl.exe"))
589 KernelData
= (PVOID
)NextModuleBase
;
590 KernelSize
= ImageSize
;
592 else if (!_stricmp(Name
, "hal.dll"))
594 HalData
= (PVOID
)NextModuleBase
;
599 DriverName
[Drivers
] = reactos_module_strings
[ImageId
];
600 DriverData
[Drivers
] = (PVOID
)NextModuleBase
;
601 DriverSize
[Drivers
] = ImageSize
;
605 /* Increase the next Load Base */
606 NextModuleBase
= ROUND_UP(NextModuleBase
+ ImageSize
, PAGE_SIZE
);
608 /* Perform import fixups */
609 if (!NT_SUCCESS(LdrPEFixupImports(LoadBase
, Name
)))
611 /* Fixup failed, just don't include it in the list */
612 // NextModuleBase = OldNextModuleBase;
613 LoaderBlock
.ModsCount
= ImageId
;
617 /* Return the final mapped address */
623 FrLdrReMapImage(IN PVOID Base
,
626 PIMAGE_NT_HEADERS NtHeader
;
627 PIMAGE_SECTION_HEADER Section
;
628 ULONG i
, Size
, DriverSize
= 0;
630 /* Get the first section */
631 NtHeader
= RtlImageNtHeader(Base
);
632 Section
= IMAGE_FIRST_SECTION(NtHeader
);
634 /* Allocate memory for the driver */
635 DriverSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
636 LoadBase
= MmAllocateMemoryAtAddress(DriverSize
, LoadBase
, LoaderSystemCode
);
639 /* Copy headers over */
640 RtlMoveMemory(LoadBase
, Base
, NtHeader
->OptionalHeader
.SizeOfHeaders
);
642 /* Copy image sections into virtual section */
643 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
645 /* Get the size of this section and check if it's valid */
646 Size
= Section
[i
].VirtualAddress
+ Section
[i
].Misc
.VirtualSize
;
647 if (Size
<= DriverSize
)
649 if (Section
[i
].SizeOfRawData
)
651 /* Copy the data from the disk to the image */
652 RtlCopyMemory((PVOID
)((ULONG_PTR
)LoadBase
+
653 Section
[i
].VirtualAddress
),
654 (PVOID
)((ULONG_PTR
)Base
+
655 Section
[i
].PointerToRawData
),
656 Section
[i
].Misc
.VirtualSize
>
657 Section
[i
].SizeOfRawData
?
658 Section
[i
].SizeOfRawData
:
659 Section
[i
].Misc
.VirtualSize
);
663 /* Clear the BSS area */
664 RtlZeroMemory((PVOID
)((ULONG_PTR
)LoadBase
+
665 Section
[i
].VirtualAddress
),
666 Section
[i
].Misc
.VirtualSize
);
671 /* Return the size of the mapped driver */
677 FrLdrMapImage(IN PFILE Image
,
681 PVOID ImageBase
, LoadBase
, ReadBuffer
;
682 ULONG ImageId
= LoaderBlock
.ModsCount
;
684 NTSTATUS Status
= STATUS_SUCCESS
;
686 /* Try to see, maybe it's loaded already */
687 if (LdrGetModuleObject(Name
) != NULL
)
689 /* It's loaded, return NULL. It would be wise to return
690 correct LoadBase, but it seems to be ignored almost everywhere */
694 /* Set the virtual (image) and physical (load) addresses */
695 LoadBase
= (PVOID
)NextModuleBase
;
696 ImageBase
= RVA(LoadBase
, KSEG0_BASE
);
698 /* Save the Image Size */
699 ImageSize
= FsGetFileSize(Image
);
701 /* Set the file pointer to zero */
702 FsSetFilePointer(Image
, 0);
704 /* Allocate a temporary buffer for the read */
705 ReadBuffer
= MmHeapAlloc(ImageSize
);
709 DbgPrint("Failed to allocate a temporary buffer for the read\n");
713 /* Load the file image */
714 if (!FsReadFile(Image
, ImageSize
, NULL
, ReadBuffer
))
717 DbgPrint("Failed to read image: %s\n", Name
);
721 /* Map it into virtual memory */
722 ImageSize
= FrLdrReMapImage(ReadBuffer
, LoadBase
);
724 /* Free the temporary buffer */
725 MmHeapFree(ReadBuffer
);
727 /* Calculate Difference between Real Base and Compiled Base*/
728 Status
= LdrRelocateImageWithBias(LoadBase
,
729 (ULONG_PTR
)ImageBase
-
734 STATUS_UNSUCCESSFUL
);
735 if (!NT_SUCCESS(Status
))
738 DbgPrint("Failed to relocate image: %s\n", Name
);
742 /* Fill out Module Data Structure */
743 reactos_modules
[ImageId
].ModStart
= (ULONG_PTR
)ImageBase
;
744 reactos_modules
[ImageId
].ModEnd
= (ULONG_PTR
)ImageBase
+ ImageSize
;
745 strcpy(reactos_module_strings
[ImageId
], Name
);
746 reactos_modules
[ImageId
].String
= (ULONG_PTR
)reactos_module_strings
[ImageId
];
747 LoaderBlock
.ModsCount
++;
749 /* Detect kernel or HAL */
750 if (!_stricmp(Name
, "ntoskrnl.exe"))
752 KernelData
= (PVOID
)NextModuleBase
;
753 KernelSize
= ImageSize
;
755 else if (!_stricmp(Name
, "hal.dll"))
757 HalData
= (PVOID
)NextModuleBase
;
762 DriverName
[Drivers
] = reactos_module_strings
[ImageId
];
763 DriverData
[Drivers
] = (PVOID
)NextModuleBase
;
764 DriverSize
[Drivers
] = ImageSize
;
768 /* Increase the next Load Base */
769 NextModuleBase
= ROUND_UP(NextModuleBase
+ ImageSize
, PAGE_SIZE
);
771 /* Perform import fixups */
772 if (!NT_SUCCESS(LdrPEFixupImports(LoadBase
, Name
)))
774 /* Fixup failed, just don't include it in the list */
775 // NextModuleBase = OldNextModuleBase;
776 LoaderBlock
.ModsCount
= ImageId
;
780 /* Return the final mapped address */