5 extern BOOLEAN FrLdrBootType
;
7 ULONG_PTR NextModuleBase
= KERNEL_BASE_PHYS
;
8 PLOADER_MODULE CurrentModule
= NULL
;
18 extern BOOLEAN
FrLdrLoadDriver(PCHAR szFileName
, INT nPos
);
20 PVOID AnsiData
, OemData
, UnicodeData
, RegistryData
, KernelData
, HalData
, DriverData
[16];
21 ULONG RegistrySize
, AnsiSize
, OemSize
, UnicodeSize
, KernelSize
, HalSize
, DriverSize
[16];
24 /* MODULE MANAGEMENT **********************************************************/
28 LdrGetModuleObject(IN PCHAR ModuleName
)
32 for (i
= 0; i
< LoaderBlock
.ModsCount
; i
++)
34 if (strstr(_strupr((PCHAR
)reactos_modules
[i
].String
), _strupr(ModuleName
)))
36 return &reactos_modules
[i
];
45 LdrPEGetOrLoadModule(IN PCHAR ModuleName
,
46 IN PCHAR ImportedName
,
47 IN PLOADER_MODULE
* ImportedModule
)
49 NTSTATUS Status
= STATUS_SUCCESS
;
51 *ImportedModule
= LdrGetModuleObject(ImportedName
);
52 if (*ImportedModule
== NULL
)
54 if (!FrLdrLoadDriver(ImportedName
, 0))
56 return STATUS_UNSUCCESSFUL
;
60 return LdrPEGetOrLoadModule(ModuleName
, ImportedName
, ImportedModule
);
69 FrLdrLoadModule(PFILE ModuleImage
,
73 ULONG LocalModuleSize
;
74 PLOADER_MODULE ModuleData
;
78 /* Get current module data structure and module name string array */
79 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
81 /* Get only the Module Name */
84 TempName
= strchr(ModuleName
, '\\');
87 ModuleName
= TempName
+ 1;
91 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
94 LocalModuleSize
= FsGetFileSize(ModuleImage
);
96 /* Fill out Module Data Structure */
97 ModuleData
->ModStart
= NextModuleBase
;
98 ModuleData
->ModEnd
= NextModuleBase
+ LocalModuleSize
;
101 strcpy(NameBuffer
, ModuleName
);
102 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
104 /* NLS detection for NT Loader Block */
105 if (!_stricmp(NameBuffer
, "ansi.nls"))
107 AnsiData
= (PVOID
)NextModuleBase
;
108 AnsiSize
= LocalModuleSize
;
110 else if (!_stricmp(NameBuffer
, "oem.nls"))
112 OemData
= (PVOID
)NextModuleBase
;
113 OemSize
= LocalModuleSize
;
115 else if (!_stricmp(NameBuffer
, "casemap.nls"))
117 UnicodeData
= (PVOID
)NextModuleBase
;
118 UnicodeSize
= LocalModuleSize
;
120 else if (!(_stricmp(NameBuffer
, "system")) ||
121 !(_stricmp(NameBuffer
, "system.hiv")))
123 RegistryData
= (PVOID
)NextModuleBase
;
124 RegistrySize
= LocalModuleSize
;
127 /* Load the file image */
128 FsReadFile(ModuleImage
, LocalModuleSize
, NULL
, (PVOID
)NextModuleBase
);
130 /* Move to next memory block and increase Module Count */
131 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
132 LoaderBlock
.ModsCount
++;
133 // DbgPrint("NextBase, ImageSize, ModStart, ModEnd %p %p %p %p\n",
134 // NextModuleBase, LocalModuleSize, ModuleData->ModStart, ModuleData->ModEnd);
136 /* Return Module Size if required */
137 if (ModuleSize
!= NULL
) {
138 *ModuleSize
= LocalModuleSize
;
141 return(ModuleData
->ModStart
);
146 FrLdrCreateModule(LPCSTR ModuleName
)
148 PLOADER_MODULE ModuleData
;
151 /* Get current module data structure and module name string array */
152 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
153 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
155 /* Set up the structure */
156 ModuleData
->ModStart
= NextModuleBase
;
157 ModuleData
->ModEnd
= -1;
160 strcpy(NameBuffer
, ModuleName
);
161 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
163 /* Set the current Module */
164 CurrentModule
= ModuleData
;
166 /* Return Module Base Address */
167 return(ModuleData
->ModStart
);
172 FrLdrCloseModule(ULONG_PTR ModuleBase
,
175 PLOADER_MODULE ModuleData
= CurrentModule
;
177 /* Make sure a module is opened */
180 /* Make sure this is the right module and that it hasn't been closed */
181 if ((ModuleBase
== ModuleData
->ModStart
) && (ModuleData
->ModEnd
== MAXULONG_PTR
)) {
183 /* Close the Module */
184 ModuleData
->ModEnd
= ModuleData
->ModStart
+ ModuleSize
;
186 /* Set the next Module Base and increase the number of modules */
187 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
188 LoaderBlock
.ModsCount
++;
190 /* Close the currently opened module */
191 CurrentModule
= NULL
;
202 /* PE IMAGE LOADER ***********************************************************/
206 LdrPEFixupForward(IN PCHAR ForwardName
)
208 CHAR NameBuffer
[128];
210 PLOADER_MODULE ModuleObject
;
212 strcpy(NameBuffer
, ForwardName
);
213 p
= strchr(NameBuffer
, '.');
214 if (p
== NULL
) return NULL
;
217 ModuleObject
= LdrGetModuleObject(NameBuffer
);
220 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer
);
224 return LdrPEGetExportByName((PVOID
)ModuleObject
->ModStart
, (PUCHAR
)(p
+ 1), 0xffff);
229 LdrPEGetExportByName(PVOID BaseAddress
,
233 PIMAGE_EXPORT_DIRECTORY ExportDir
;
240 LONG minn
, maxn
, mid
, res
;
243 /* HAL and NTOS use a virtual address, switch it to physical mode */
244 if ((ULONG_PTR
)BaseAddress
& KSEG0_BASE
)
246 BaseAddress
= RVA(BaseAddress
, -KSEG0_BASE
);
249 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
250 RtlImageDirectoryEntryToData(BaseAddress
,
252 IMAGE_DIRECTORY_ENTRY_EXPORT
,
256 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
260 /* The symbol names may be missing entirely */
261 if (!ExportDir
->AddressOfNames
)
263 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
268 * Get header pointers
270 ExNames
= (ULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfNames
);
271 ExOrdinals
= (USHORT
*)RVA(BaseAddress
, ExportDir
->AddressOfNameOrdinals
);
272 ExFunctions
= (ULONG
*)RVA(BaseAddress
, ExportDir
->AddressOfFunctions
);
275 * Check the hint first
277 if (Hint
< ExportDir
->NumberOfNames
)
279 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
280 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
282 Ordinal
= ExOrdinals
[Hint
];
283 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
284 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
285 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
287 Function
= LdrPEFixupForward((PCHAR
)Function
);
288 if (Function
== NULL
)
290 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function
);
295 if (Function
!= NULL
) return Function
;
303 maxn
= ExportDir
->NumberOfNames
- 1;
306 mid
= (minn
+ maxn
) / 2;
308 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
309 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
312 Ordinal
= ExOrdinals
[mid
];
313 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
314 if ((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
&&
315 (ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ ExportDirSize
)
317 Function
= LdrPEFixupForward((PCHAR
)Function
);
318 if (Function
== NULL
)
320 DbgPrint("1: failed to find %s\n", Function
);
324 if (Function
!= NULL
)
339 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
340 DbgPrint("2: failed to find %s\n",SymbolName
);
346 LdrPEProcessImportDirectoryEntry(PVOID DriverBase
,
347 PLOADER_MODULE LoaderModule
,
348 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
350 PVOID
* ImportAddressList
;
351 PULONG_PTR FunctionNameList
;
353 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
355 return STATUS_UNSUCCESSFUL
;
358 /* Get the import address list. */
359 ImportAddressList
= (PVOID
*)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
361 /* Get the list of functions to import. */
362 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
364 FunctionNameList
= (PULONG_PTR
)RVA(DriverBase
, ImportModuleDirectory
->OriginalFirstThunk
);
368 FunctionNameList
= (PULONG_PTR
)RVA(DriverBase
, ImportModuleDirectory
->FirstThunk
);
371 /* Walk through function list and fixup addresses. */
372 while (*FunctionNameList
!= 0L)
374 if ((*FunctionNameList
) & 0x80000000)
376 DbgPrint("Failed to import ordinal from %s\n", LoaderModule
->String
);
377 return STATUS_UNSUCCESSFUL
;
381 IMAGE_IMPORT_BY_NAME
*pe_name
;
382 pe_name
= RVA(DriverBase
, *FunctionNameList
);
383 *ImportAddressList
= LdrPEGetExportByName((PVOID
)LoaderModule
->ModStart
, pe_name
->Name
, pe_name
->Hint
);
385 /* Fixup the address to be virtual */
386 *ImportAddressList
= RVA(*ImportAddressList
, KSEG0_BASE
);
388 //DbgPrint("Looked for: %s and found: %p\n", pe_name->Name, *ImportAddressList);
389 if ((*ImportAddressList
) == NULL
)
391 DbgPrint("Failed to import %s from %s\n", pe_name
->Name
, LoaderModule
->String
);
392 return STATUS_UNSUCCESSFUL
;
398 return STATUS_SUCCESS
;
403 LdrPEFixupImports(IN PVOID DllBase
,
406 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
409 PLOADER_MODULE ImportedModule
;
412 /* Process each import module */
413 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
414 RtlImageDirectoryEntryToData(DllBase
,
416 IMAGE_DIRECTORY_ENTRY_IMPORT
,
418 while (ImportModuleDirectory
&& ImportModuleDirectory
->Name
)
420 /* Check to make sure that import lib is kernel */
421 ImportedName
= (PCHAR
) DllBase
+ ImportModuleDirectory
->Name
;
422 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
424 Status
= LdrPEGetOrLoadModule(DllName
, ImportedName
, &ImportedModule
);
425 if (!NT_SUCCESS(Status
)) return Status
;
427 Status
= LdrPEProcessImportDirectoryEntry(DllBase
, ImportedModule
, ImportModuleDirectory
);
428 if (!NT_SUCCESS(Status
)) return Status
;
430 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
431 ImportModuleDirectory
++;
434 return STATUS_SUCCESS
;
439 FrLdrReadAndMapImage(IN PFILE Image
,
443 PVOID ImageBase
, LoadBase
, ReadBuffer
;
444 ULONG ImageId
= LoaderBlock
.ModsCount
;
445 ULONG i
, Size
, ImageSize
, SizeOfHeaders
;
446 PIMAGE_NT_HEADERS NtHeader
;
447 PIMAGE_SECTION_HEADER Section
;
448 NTSTATUS Status
= STATUS_SUCCESS
;
449 PLOADER_MODULE pModule
;
451 /* Try to see, maybe it's loaded already */
452 if ((pModule
= LdrGetModuleObject(Name
)) != NULL
)
454 /* It's loaded, return LoadBase */
455 ImageBase
= (PVOID
)pModule
->ModStart
;
456 LoadBase
= RVA(ImageBase
, -KSEG0_BASE
);
460 /* Set the virtual (image) and physical (load) addresses */
461 LoadBase
= (PVOID
)NextModuleBase
;
462 ImageBase
= RVA(LoadBase
, KSEG0_BASE
);
464 /* Allocate a temporary buffer for the read */
465 ReadBuffer
= MmHeapAlloc(MM_PAGE_SIZE
);
469 DbgPrint("Failed to allocate a temporary buffer for the read\n");
473 /* Set the file pointer to zero */
474 FsSetFilePointer(Image
, 0);
476 /* Load first page of the file image */
477 if (!FsReadFile(Image
, MM_PAGE_SIZE
, NULL
, ReadBuffer
))
480 DbgPrint("Failed to read image: %s\n", Name
);
484 /* Get image headers */
485 NtHeader
= RtlImageNtHeader(ReadBuffer
);
488 DbgPrint("Failed to read image (bad PE signature) %s\n", Name
);
492 /* Allocate memory for the driver */
493 ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
494 LoadBase
= MmAllocateMemoryAtAddress(ImageSize
, LoadBase
, LoaderSystemCode
);
497 /* Copy headers over */
498 SizeOfHeaders
= NtHeader
->OptionalHeader
.SizeOfHeaders
;
499 if (SizeOfHeaders
< MM_PAGE_SIZE
)
501 RtlMoveMemory(LoadBase
, ReadBuffer
, SizeOfHeaders
);
505 RtlMoveMemory(LoadBase
, ReadBuffer
, MM_PAGE_SIZE
);
506 if (!FsReadFile(Image
, SizeOfHeaders
- MM_PAGE_SIZE
, NULL
,
507 (PVOID
)((ULONG_PTR
)LoadBase
+ MM_PAGE_SIZE
)))
509 DbgPrint("Failed to read image: %s\n", Name
);
514 /* Free the temporary buffer */
515 MmHeapFree(ReadBuffer
);
517 /* Get the first section */
518 NtHeader
= RtlImageNtHeader(LoadBase
);
519 Section
= IMAGE_FIRST_SECTION(NtHeader
);
521 /* Read image sections into virtual section */
522 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
524 /* Get the size of this section and check if it's valid */
525 Size
= Section
[i
].VirtualAddress
+ Section
[i
].Misc
.VirtualSize
;
526 if (Size
<= ImageSize
)
528 if (Section
[i
].SizeOfRawData
)
530 /* Copy the data from the disk to the image */
531 FsSetFilePointer(Image
, Section
[i
].PointerToRawData
);
532 if (!FsReadFile(Image
,
533 Section
[i
].Misc
.VirtualSize
>
534 Section
[i
].SizeOfRawData
?
535 Section
[i
].SizeOfRawData
:
536 Section
[i
].Misc
.VirtualSize
,
538 (PVOID
)((ULONG_PTR
)LoadBase
+
539 Section
[i
].VirtualAddress
)))
541 DbgPrint("Failed to read image: %s\n", Name
);
547 /* Clear the BSS area */
548 RtlZeroMemory((PVOID
)((ULONG_PTR
)LoadBase
+
549 Section
[i
].VirtualAddress
),
550 Section
[i
].Misc
.VirtualSize
);
555 DbgPrint("Section %s in %s doesn't fit: VA: %lx, Size: %lx\n",
556 Section
[i
].Name
, Name
, Section
[i
].VirtualAddress
,
557 Section
[i
].Misc
.VirtualSize
);
561 /* Calculate Difference between Real Base and Compiled Base*/
562 Status
= LdrRelocateImageWithBias(LoadBase
,
563 (ULONG_PTR
)ImageBase
-
568 STATUS_SUCCESS
, // allow stripped files
572 STATUS_UNSUCCESSFUL
);
573 if (!NT_SUCCESS(Status
))
576 DbgPrint("Failed to relocate image: %s\n", Name
);
580 /* Fill out Module Data Structure */
581 reactos_modules
[ImageId
].ModStart
= (ULONG_PTR
)ImageBase
;
582 reactos_modules
[ImageId
].ModEnd
= (ULONG_PTR
)ImageBase
+ ImageSize
;
583 strcpy(reactos_module_strings
[ImageId
], Name
);
584 reactos_modules
[ImageId
].String
= (ULONG_PTR
)reactos_module_strings
[ImageId
];
585 LoaderBlock
.ModsCount
++;
587 /* Detect kernel or HAL */
588 if (!_stricmp(Name
, "ntoskrnl.exe"))
590 KernelData
= (PVOID
)NextModuleBase
;
591 KernelSize
= ImageSize
;
593 else if (!_stricmp(Name
, "hal.dll"))
595 HalData
= (PVOID
)NextModuleBase
;
600 DriverName
[Drivers
] = reactos_module_strings
[ImageId
];
601 DriverData
[Drivers
] = (PVOID
)NextModuleBase
;
602 DriverSize
[Drivers
] = ImageSize
;
606 /* Increase the next Load Base */
607 NextModuleBase
= ROUND_UP(NextModuleBase
+ ImageSize
, PAGE_SIZE
);
609 /* Perform import fixups */
610 if (!NT_SUCCESS(LdrPEFixupImports(LoadBase
, Name
)))
612 /* Fixup failed, just don't include it in the list */
613 // NextModuleBase = OldNextModuleBase;
614 LoaderBlock
.ModsCount
= ImageId
;
618 /* Return the final mapped address */
624 FrLdrReMapImage(IN PVOID Base
,
627 PIMAGE_NT_HEADERS NtHeader
;
628 PIMAGE_SECTION_HEADER Section
;
629 ULONG i
, Size
, DriverSize
= 0;
631 /* Get the first section */
632 NtHeader
= RtlImageNtHeader(Base
);
633 Section
= IMAGE_FIRST_SECTION(NtHeader
);
635 /* Allocate memory for the driver */
636 DriverSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
637 LoadBase
= MmAllocateMemoryAtAddress(DriverSize
, LoadBase
, LoaderSystemCode
);
640 /* Copy headers over */
641 RtlMoveMemory(LoadBase
, Base
, NtHeader
->OptionalHeader
.SizeOfHeaders
);
643 /* Copy image sections into virtual section */
644 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
646 /* Get the size of this section and check if it's valid */
647 Size
= Section
[i
].VirtualAddress
+ Section
[i
].Misc
.VirtualSize
;
648 if (Size
<= DriverSize
)
650 if (Section
[i
].SizeOfRawData
)
652 /* Copy the data from the disk to the image */
653 RtlCopyMemory((PVOID
)((ULONG_PTR
)LoadBase
+
654 Section
[i
].VirtualAddress
),
655 (PVOID
)((ULONG_PTR
)Base
+
656 Section
[i
].PointerToRawData
),
657 Section
[i
].Misc
.VirtualSize
>
658 Section
[i
].SizeOfRawData
?
659 Section
[i
].SizeOfRawData
:
660 Section
[i
].Misc
.VirtualSize
);
664 /* Clear the BSS area */
665 RtlZeroMemory((PVOID
)((ULONG_PTR
)LoadBase
+
666 Section
[i
].VirtualAddress
),
667 Section
[i
].Misc
.VirtualSize
);
672 /* Return the size of the mapped driver */
678 FrLdrMapImage(IN PFILE Image
,
682 PVOID ImageBase
, LoadBase
, ReadBuffer
;
683 ULONG ImageId
= LoaderBlock
.ModsCount
;
685 NTSTATUS Status
= STATUS_SUCCESS
;
687 /* Try to see, maybe it's loaded already */
688 if (LdrGetModuleObject(Name
) != NULL
)
690 /* It's loaded, return NULL. It would be wise to return
691 correct LoadBase, but it seems to be ignored almost everywhere */
695 /* Set the virtual (image) and physical (load) addresses */
696 LoadBase
= (PVOID
)NextModuleBase
;
697 ImageBase
= RVA(LoadBase
, KSEG0_BASE
);
699 /* Save the Image Size */
700 ImageSize
= FsGetFileSize(Image
);
702 /* Set the file pointer to zero */
703 FsSetFilePointer(Image
, 0);
705 /* Allocate a temporary buffer for the read */
706 ReadBuffer
= MmHeapAlloc(ImageSize
);
710 DbgPrint("Failed to allocate a temporary buffer for the read\n");
714 /* Load the file image */
715 if (!FsReadFile(Image
, ImageSize
, NULL
, ReadBuffer
))
718 DbgPrint("Failed to read image: %s\n", Name
);
722 /* Map it into virtual memory */
723 ImageSize
= FrLdrReMapImage(ReadBuffer
, LoadBase
);
725 /* Free the temporary buffer */
726 MmHeapFree(ReadBuffer
);
728 /* Calculate Difference between Real Base and Compiled Base*/
729 Status
= LdrRelocateImageWithBias(LoadBase
,
730 (ULONG_PTR
)ImageBase
-
735 STATUS_UNSUCCESSFUL
);
736 if (!NT_SUCCESS(Status
))
739 DbgPrint("Failed to relocate image: %s\n", Name
);
743 /* Fill out Module Data Structure */
744 reactos_modules
[ImageId
].ModStart
= (ULONG_PTR
)ImageBase
;
745 reactos_modules
[ImageId
].ModEnd
= (ULONG_PTR
)ImageBase
+ ImageSize
;
746 strcpy(reactos_module_strings
[ImageId
], Name
);
747 reactos_modules
[ImageId
].String
= (ULONG_PTR
)reactos_module_strings
[ImageId
];
748 LoaderBlock
.ModsCount
++;
750 /* Detect kernel or HAL */
751 if (!_stricmp(Name
, "ntoskrnl.exe"))
753 KernelData
= (PVOID
)NextModuleBase
;
754 KernelSize
= ImageSize
;
756 else if (!_stricmp(Name
, "hal.dll"))
758 HalData
= (PVOID
)NextModuleBase
;
763 DriverName
[Drivers
] = reactos_module_strings
[ImageId
];
764 DriverData
[Drivers
] = (PVOID
)NextModuleBase
;
765 DriverSize
[Drivers
] = ImageSize
;
769 /* Increase the next Load Base */
770 NextModuleBase
= ROUND_UP(NextModuleBase
+ ImageSize
, PAGE_SIZE
);
772 /* Perform import fixups */
773 if (!NT_SUCCESS(LdrPEFixupImports(LoadBase
, Name
)))
775 /* Fixup failed, just don't include it in the list */
776 // NextModuleBase = OldNextModuleBase;
777 LoaderBlock
.ModsCount
= ImageId
;
781 /* Return the final mapped address */