merge trunk head (37902)
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / imageldr.c
1 #include <freeldr.h>
2 #include <debug.h>
3 #undef DbgPrint
4
5 extern BOOLEAN FrLdrBootType;
6
7 ULONG_PTR NextModuleBase = KERNEL_BASE_PHYS;
8 PLOADER_MODULE CurrentModule = NULL;
9
10 PVOID
11 NTAPI
12 LdrPEGetExportByName(
13 IN PVOID BaseAddress,
14 IN PUCHAR SymbolName,
15 IN USHORT Hint
16 );
17
18 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
19 ULONG Drivers;
20 PVOID AnsiData, OemData, UnicodeData, RegistryData, KernelData, HalData, DriverData[16];
21 ULONG RegistrySize, AnsiSize, OemSize, UnicodeSize, KernelSize, HalSize, DriverSize[16];
22 PCHAR DriverName[16];
23
24 /* MODULE MANAGEMENT **********************************************************/
25
26 PLOADER_MODULE
27 NTAPI
28 LdrGetModuleObject(IN PCHAR ModuleName)
29 {
30 ULONG i;
31
32 for (i = 0; i < LoaderBlock.ModsCount; i++)
33 {
34 if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName)))
35 {
36 return &reactos_modules[i];
37 }
38 }
39
40 return NULL;
41 }
42
43 NTSTATUS
44 NTAPI
45 LdrPEGetOrLoadModule(IN PCHAR ModuleName,
46 IN PCHAR ImportedName,
47 IN PLOADER_MODULE* ImportedModule)
48 {
49 NTSTATUS Status = STATUS_SUCCESS;
50
51 *ImportedModule = LdrGetModuleObject(ImportedName);
52 if (*ImportedModule == NULL)
53 {
54 if (!FrLdrLoadDriver(ImportedName, 0))
55 {
56 return STATUS_UNSUCCESSFUL;
57 }
58 else
59 {
60 return LdrPEGetOrLoadModule(ModuleName, ImportedName, ImportedModule);
61 }
62 }
63
64 return Status;
65 }
66
67 ULONG_PTR
68 NTAPI
69 FrLdrLoadModule(FILE *ModuleImage,
70 LPCSTR ModuleName,
71 PULONG ModuleSize)
72 {
73 ULONG LocalModuleSize;
74 PLOADER_MODULE ModuleData;
75 LPSTR NameBuffer;
76 LPSTR TempName;
77
78 /* Get current module data structure and module name string array */
79 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
80
81 /* Get only the Module Name */
82 do {
83
84 TempName = strchr(ModuleName, '\\');
85
86 if(TempName) {
87 ModuleName = TempName + 1;
88 }
89
90 } while(TempName);
91 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
92
93 /* Get Module Size */
94 LocalModuleSize = FsGetFileSize(ModuleImage);
95
96 /* Fill out Module Data Structure */
97 ModuleData->ModStart = NextModuleBase;
98 ModuleData->ModEnd = NextModuleBase + LocalModuleSize;
99
100 /* Save name */
101 strcpy(NameBuffer, ModuleName);
102 ModuleData->String = (ULONG_PTR)NameBuffer;
103
104 /* NLS detection for NT Loader Block */
105 if (!_stricmp(NameBuffer, "ansi.nls"))
106 {
107 AnsiData = (PVOID)NextModuleBase;
108 AnsiSize = LocalModuleSize;
109 }
110 else if (!_stricmp(NameBuffer, "oem.nls"))
111 {
112 OemData = (PVOID)NextModuleBase;
113 OemSize = LocalModuleSize;
114 }
115 else if (!_stricmp(NameBuffer, "casemap.nls"))
116 {
117 UnicodeData = (PVOID)NextModuleBase;
118 UnicodeSize = LocalModuleSize;
119 }
120 else if (!(_stricmp(NameBuffer, "system")) ||
121 !(_stricmp(NameBuffer, "system.hiv")))
122 {
123 RegistryData = (PVOID)NextModuleBase;
124 RegistrySize = LocalModuleSize;
125 }
126
127 /* Load the file image */
128 FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
129
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);
135
136 /* Return Module Size if required */
137 if (ModuleSize != NULL) {
138 *ModuleSize = LocalModuleSize;
139 }
140
141 return(ModuleData->ModStart);
142 }
143
144 ULONG_PTR
145 NTAPI
146 FrLdrCreateModule(LPCSTR ModuleName)
147 {
148 PLOADER_MODULE ModuleData;
149 LPSTR NameBuffer;
150
151 /* Get current module data structure and module name string array */
152 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
153 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
154
155 /* Set up the structure */
156 ModuleData->ModStart = NextModuleBase;
157 ModuleData->ModEnd = -1;
158
159 /* Copy the name */
160 strcpy(NameBuffer, ModuleName);
161 ModuleData->String = (ULONG_PTR)NameBuffer;
162
163 /* Set the current Module */
164 CurrentModule = ModuleData;
165
166 /* Return Module Base Address */
167 return(ModuleData->ModStart);
168 }
169
170 BOOLEAN
171 NTAPI
172 FrLdrCloseModule(ULONG_PTR ModuleBase,
173 ULONG ModuleSize)
174 {
175 PLOADER_MODULE ModuleData = CurrentModule;
176
177 /* Make sure a module is opened */
178 if (ModuleData) {
179
180 /* Make sure this is the right module and that it hasn't been closed */
181 if ((ModuleBase == ModuleData->ModStart) && (ModuleData->ModEnd == (ULONG_PTR)-1)) {
182
183 /* Close the Module */
184 ModuleData->ModEnd = ModuleData->ModStart + ModuleSize;
185
186 /* Set the next Module Base and increase the number of modules */
187 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
188 LoaderBlock.ModsCount++;
189
190 /* Close the currently opened module */
191 CurrentModule = NULL;
192
193 /* Success */
194 return(TRUE);
195 }
196 }
197
198 /* Failure path */
199 return(FALSE);
200 }
201
202 /* PE IMAGE LOADER ***********************************************************/
203
204 PVOID
205 NTAPI
206 LdrPEFixupForward(IN PCHAR ForwardName)
207 {
208 CHAR NameBuffer[128];
209 PCHAR p;
210 PLOADER_MODULE ModuleObject;
211
212 strcpy(NameBuffer, ForwardName);
213 p = strchr(NameBuffer, '.');
214 if (p == NULL) return NULL;
215 *p = 0;
216
217 ModuleObject = LdrGetModuleObject(NameBuffer);
218 if (!ModuleObject)
219 {
220 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
221 return NULL;
222 }
223
224 return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff);
225 }
226
227 PVOID
228 NTAPI
229 LdrPEGetExportByName(PVOID BaseAddress,
230 PUCHAR SymbolName,
231 USHORT Hint)
232 {
233 PIMAGE_EXPORT_DIRECTORY ExportDir;
234 ULONG * ExFunctions;
235 ULONG * ExNames;
236 USHORT * ExOrdinals;
237 PVOID ExName;
238 ULONG Ordinal;
239 PVOID Function;
240 LONG minn, maxn, mid, res;
241 ULONG ExportDirSize;
242
243 /* HAL and NTOS use a virtual address, switch it to physical mode */
244 if ((ULONG_PTR)BaseAddress & KSEG0_BASE)
245 {
246 BaseAddress = RVA(BaseAddress, -KSEG0_BASE);
247 }
248
249 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
250 RtlImageDirectoryEntryToData(BaseAddress,
251 TRUE,
252 IMAGE_DIRECTORY_ENTRY_EXPORT,
253 &ExportDirSize);
254 if (!ExportDir)
255 {
256 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
257 return NULL;
258 }
259
260 /* The symbol names may be missing entirely */
261 if (!ExportDir->AddressOfNames)
262 {
263 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
264 return NULL;
265 }
266
267 /*
268 * Get header pointers
269 */
270 ExNames = (ULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
271 ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
272 ExFunctions = (ULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
273
274 /*
275 * Check the hint first
276 */
277 if (Hint < ExportDir->NumberOfNames)
278 {
279 ExName = RVA(BaseAddress, ExNames[Hint]);
280 if (strcmp(ExName, (PCHAR)SymbolName) == 0)
281 {
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)
286 {
287 Function = LdrPEFixupForward((PCHAR)Function);
288 if (Function == NULL)
289 {
290 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
291 }
292 return Function;
293 }
294
295 if (Function != NULL) return Function;
296 }
297 }
298
299 /*
300 * Binary search
301 */
302 minn = 0;
303 maxn = ExportDir->NumberOfNames - 1;
304 while (minn <= maxn)
305 {
306 mid = (minn + maxn) / 2;
307
308 ExName = RVA(BaseAddress, ExNames[mid]);
309 res = strcmp(ExName, (PCHAR)SymbolName);
310 if (res == 0)
311 {
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)
316 {
317 Function = LdrPEFixupForward((PCHAR)Function);
318 if (Function == NULL)
319 {
320 DbgPrint("1: failed to find %s\n", Function);
321 }
322 return Function;
323 }
324 if (Function != NULL)
325 {
326 return Function;
327 }
328 }
329 else if (res > 0)
330 {
331 maxn = mid - 1;
332 }
333 else
334 {
335 minn = mid + 1;
336 }
337 }
338
339 ExName = RVA(BaseAddress, ExNames[mid]);
340 DbgPrint("2: failed to find %s\n",SymbolName);
341 return (PVOID)NULL;
342 }
343
344 NTSTATUS
345 NTAPI
346 LdrPEProcessImportDirectoryEntry(PVOID DriverBase,
347 PLOADER_MODULE LoaderModule,
348 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
349 {
350 PVOID* ImportAddressList;
351 PULONG_PTR FunctionNameList;
352
353 if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
354 {
355 return STATUS_UNSUCCESSFUL;
356 }
357
358 /* Get the import address list. */
359 ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
360
361 /* Get the list of functions to import. */
362 if (ImportModuleDirectory->OriginalFirstThunk != 0)
363 {
364 FunctionNameList = (PULONG_PTR)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
365 }
366 else
367 {
368 FunctionNameList = (PULONG_PTR)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
369 }
370
371 /* Walk through function list and fixup addresses. */
372 while (*FunctionNameList != 0L)
373 {
374 if ((*FunctionNameList) & 0x80000000)
375 {
376 DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String);
377 return STATUS_UNSUCCESSFUL;
378 }
379 else
380 {
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);
384
385 /* Fixup the address to be virtual */
386 *ImportAddressList = RVA(*ImportAddressList, KSEG0_BASE);
387
388 //DbgPrint("Looked for: %s and found: %p\n", pe_name->Name, *ImportAddressList);
389 if ((*ImportAddressList) == NULL)
390 {
391 DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String);
392 return STATUS_UNSUCCESSFUL;
393 }
394 }
395 ImportAddressList++;
396 FunctionNameList++;
397 }
398 return STATUS_SUCCESS;
399 }
400
401 NTSTATUS
402 NTAPI
403 LdrPEFixupImports(IN PVOID DllBase,
404 IN PCHAR DllName)
405 {
406 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
407 PCHAR ImportedName;
408 NTSTATUS Status;
409 PLOADER_MODULE ImportedModule;
410 ULONG Size;
411
412 /* Process each import module */
413 ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
414 RtlImageDirectoryEntryToData(DllBase,
415 TRUE,
416 IMAGE_DIRECTORY_ENTRY_IMPORT,
417 &Size);
418 while (ImportModuleDirectory && ImportModuleDirectory->Name)
419 {
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);
423
424 Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule);
425 if (!NT_SUCCESS(Status)) return Status;
426
427 Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory);
428 if (!NT_SUCCESS(Status)) return Status;
429
430 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
431 ImportModuleDirectory++;
432 }
433
434 return STATUS_SUCCESS;
435 }
436
437 PVOID
438 NTAPI
439 FrLdrReadAndMapImage(IN FILE *Image,
440 IN PCHAR Name,
441 IN ULONG ImageType)
442 {
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
450 /* Try to see, maybe it's loaded already */
451 if (LdrGetModuleObject(Name) != NULL)
452 {
453 /* It's loaded, return NULL. It would be wise to return
454 correct LoadBase, but it seems to be ignored almost everywhere */
455 return NULL;
456 }
457
458 /* Set the virtual (image) and physical (load) addresses */
459 LoadBase = (PVOID)NextModuleBase;
460 ImageBase = RVA(LoadBase, KSEG0_BASE);
461
462 /* Allocate a temporary buffer for the read */
463 ReadBuffer = MmHeapAlloc(MM_PAGE_SIZE);
464 if (!ReadBuffer)
465 {
466 /* Fail */
467 DbgPrint("Failed to allocate a temporary buffer for the read\n");
468 return NULL;
469 }
470
471 /* Set the file pointer to zero */
472 FsSetFilePointer(Image, 0);
473
474 /* Load first page of the file image */
475 if (!FsReadFile(Image, MM_PAGE_SIZE, NULL, ReadBuffer))
476 {
477 /* Fail */
478 DbgPrint("Failed to read image: %s\n", Name);
479 return NULL;
480 }
481
482 /* Get image headers */
483 NtHeader = RtlImageNtHeader(ReadBuffer);
484
485 /* Allocate memory for the driver */
486 ImageSize = NtHeader->OptionalHeader.SizeOfImage;
487 LoadBase = MmAllocateMemoryAtAddress(ImageSize, LoadBase, LoaderSystemCode);
488 ASSERT(LoadBase);
489
490 /* Copy headers over */
491 SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders;
492 if (SizeOfHeaders < MM_PAGE_SIZE)
493 {
494 RtlMoveMemory(LoadBase, ReadBuffer, SizeOfHeaders);
495 }
496 else
497 {
498 RtlMoveMemory(LoadBase, ReadBuffer, MM_PAGE_SIZE);
499 if (!FsReadFile(Image, SizeOfHeaders - MM_PAGE_SIZE, NULL,
500 (PVOID)((ULONG_PTR)LoadBase + MM_PAGE_SIZE)))
501 {
502 DbgPrint("Failed to read image: %s\n", Name);
503 return NULL;
504 }
505 }
506
507 /* Free the temporary buffer */
508 MmHeapFree(ReadBuffer);
509
510 /* Get the first section */
511 NtHeader = RtlImageNtHeader(LoadBase);
512 Section = IMAGE_FIRST_SECTION(NtHeader);
513
514 /* Read image sections into virtual section */
515 for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
516 {
517 /* Get the size of this section and check if it's valid */
518 Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
519 if (Size <= ImageSize)
520 {
521 if (Section[i].SizeOfRawData)
522 {
523 /* Copy the data from the disk to the image */
524 FsSetFilePointer(Image, Section[i].PointerToRawData);
525 if (!FsReadFile(Image,
526 Section[i].Misc.VirtualSize >
527 Section[i].SizeOfRawData ?
528 Section[i].SizeOfRawData :
529 Section[i].Misc.VirtualSize,
530 NULL,
531 (PVOID)((ULONG_PTR)LoadBase +
532 Section[i].VirtualAddress)))
533 {
534 DbgPrint("Failed to read image: %s\n", Name);
535 return NULL;
536 }
537 }
538 else
539 {
540 /* Clear the BSS area */
541 RtlZeroMemory((PVOID)((ULONG_PTR)LoadBase +
542 Section[i].VirtualAddress),
543 Section[i].Misc.VirtualSize);
544 }
545 }
546 else
547 {
548 DbgPrint("Section %s in %s doesn't fit: VA: %lx, Size: %lx\n",
549 Section[i].Name, Name, Section[i].VirtualAddress,
550 Section[i].Misc.VirtualSize);
551 }
552 }
553
554 /* Calculate Difference between Real Base and Compiled Base*/
555 Status = LdrRelocateImageWithBias(LoadBase,
556 (ULONG_PTR)ImageBase -
557 (ULONG_PTR)LoadBase,
558 "FreeLdr",
559 STATUS_SUCCESS,
560 #ifdef _M_AMD64
561 STATUS_SUCCESS, // allow stripped files
562 #else
563 STATUS_UNSUCCESSFUL,
564 #endif
565 STATUS_UNSUCCESSFUL);
566 if (!NT_SUCCESS(Status))
567 {
568 /* Fail */
569 DbgPrint("Failed to relocate image: %s\n", Name);
570 return NULL;
571 }
572
573 /* Fill out Module Data Structure */
574 reactos_modules[ImageId].ModStart = (ULONG_PTR)ImageBase;
575 reactos_modules[ImageId].ModEnd = (ULONG_PTR)ImageBase + ImageSize;
576 strcpy(reactos_module_strings[ImageId], Name);
577 reactos_modules[ImageId].String = (ULONG_PTR)reactos_module_strings[ImageId];
578 LoaderBlock.ModsCount++;
579
580 /* Detect kernel or HAL */
581 if (!_stricmp(Name, "ntoskrnl.exe"))
582 {
583 KernelData = (PVOID)NextModuleBase;
584 KernelSize = ImageSize;
585 }
586 else if (!_stricmp(Name, "hal.dll"))
587 {
588 HalData = (PVOID)NextModuleBase;
589 HalSize = ImageSize;
590 }
591 else
592 {
593 DriverName[Drivers] = reactos_module_strings[ImageId];
594 DriverData[Drivers] = (PVOID)NextModuleBase;
595 DriverSize[Drivers] = ImageSize;
596 Drivers++;
597 }
598
599 /* Increase the next Load Base */
600 NextModuleBase = ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE);
601
602 /* Perform import fixups */
603 if (!NT_SUCCESS(LdrPEFixupImports(LoadBase, Name)))
604 {
605 /* Fixup failed, just don't include it in the list */
606 // NextModuleBase = OldNextModuleBase;
607 LoaderBlock.ModsCount = ImageId;
608 return NULL;
609 }
610
611 /* Return the final mapped address */
612 return LoadBase;
613 }
614
615 ULONG
616 NTAPI
617 FrLdrReMapImage(IN PVOID Base,
618 IN PVOID LoadBase)
619 {
620 PIMAGE_NT_HEADERS NtHeader;
621 PIMAGE_SECTION_HEADER Section;
622 ULONG i, Size, DriverSize = 0;
623
624 /* Get the first section */
625 NtHeader = RtlImageNtHeader(Base);
626 Section = IMAGE_FIRST_SECTION(NtHeader);
627
628 /* Allocate memory for the driver */
629 DriverSize = NtHeader->OptionalHeader.SizeOfImage;
630 LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase, LoaderSystemCode);
631 ASSERT(LoadBase);
632
633 /* Copy headers over */
634 RtlMoveMemory(LoadBase, Base, NtHeader->OptionalHeader.SizeOfHeaders);
635
636 /* Copy image sections into virtual section */
637 for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
638 {
639 /* Get the size of this section and check if it's valid */
640 Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
641 if (Size <= DriverSize)
642 {
643 if (Section[i].SizeOfRawData)
644 {
645 /* Copy the data from the disk to the image */
646 RtlCopyMemory((PVOID)((ULONG_PTR)LoadBase +
647 Section[i].VirtualAddress),
648 (PVOID)((ULONG_PTR)Base +
649 Section[i].PointerToRawData),
650 Section[i].Misc.VirtualSize >
651 Section[i].SizeOfRawData ?
652 Section[i].SizeOfRawData :
653 Section[i].Misc.VirtualSize);
654 }
655 else
656 {
657 /* Clear the BSS area */
658 RtlZeroMemory((PVOID)((ULONG_PTR)LoadBase +
659 Section[i].VirtualAddress),
660 Section[i].Misc.VirtualSize);
661 }
662 }
663 }
664
665 /* Return the size of the mapped driver */
666 return DriverSize;
667 }
668
669 PVOID
670 NTAPI
671 FrLdrMapImage(IN FILE *Image,
672 IN PCHAR Name,
673 IN ULONG ImageType)
674 {
675 PVOID ImageBase, LoadBase, ReadBuffer;
676 ULONG ImageId = LoaderBlock.ModsCount;
677 ULONG ImageSize;
678 NTSTATUS Status = STATUS_SUCCESS;
679
680 /* Try to see, maybe it's loaded already */
681 if (LdrGetModuleObject(Name) != NULL)
682 {
683 /* It's loaded, return NULL. It would be wise to return
684 correct LoadBase, but it seems to be ignored almost everywhere */
685 return NULL;
686 }
687
688 /* Set the virtual (image) and physical (load) addresses */
689 LoadBase = (PVOID)NextModuleBase;
690 ImageBase = RVA(LoadBase, KSEG0_BASE);
691
692 /* Save the Image Size */
693 ImageSize = FsGetFileSize(Image);
694
695 /* Set the file pointer to zero */
696 FsSetFilePointer(Image, 0);
697
698 /* Allocate a temporary buffer for the read */
699 ReadBuffer = MmHeapAlloc(ImageSize);
700 if (!ReadBuffer)
701 {
702 /* Fail */
703 DbgPrint("Failed to allocate a temporary buffer for the read\n");
704 return NULL;
705 }
706
707 /* Load the file image */
708 if (!FsReadFile(Image, ImageSize, NULL, ReadBuffer))
709 {
710 /* Fail */
711 DbgPrint("Failed to read image: %s\n", Name);
712 return NULL;
713 }
714
715 /* Map it into virtual memory */
716 ImageSize = FrLdrReMapImage(ReadBuffer, LoadBase);
717
718 /* Free the temporary buffer */
719 MmHeapFree(ReadBuffer);
720
721 /* Calculate Difference between Real Base and Compiled Base*/
722 Status = LdrRelocateImageWithBias(LoadBase,
723 (ULONG_PTR)ImageBase -
724 (ULONG_PTR)LoadBase,
725 "FreeLdr",
726 STATUS_SUCCESS,
727 STATUS_UNSUCCESSFUL,
728 STATUS_UNSUCCESSFUL);
729 if (!NT_SUCCESS(Status))
730 {
731 /* Fail */
732 DbgPrint("Failed to relocate image: %s\n", Name);
733 return NULL;
734 }
735
736 /* Fill out Module Data Structure */
737 reactos_modules[ImageId].ModStart = (ULONG_PTR)ImageBase;
738 reactos_modules[ImageId].ModEnd = (ULONG_PTR)ImageBase + ImageSize;
739 strcpy(reactos_module_strings[ImageId], Name);
740 reactos_modules[ImageId].String = (ULONG_PTR)reactos_module_strings[ImageId];
741 LoaderBlock.ModsCount++;
742
743 /* Detect kernel or HAL */
744 if (!_stricmp(Name, "ntoskrnl.exe"))
745 {
746 KernelData = (PVOID)NextModuleBase;
747 KernelSize = ImageSize;
748 }
749 else if (!_stricmp(Name, "hal.dll"))
750 {
751 HalData = (PVOID)NextModuleBase;
752 HalSize = ImageSize;
753 }
754 else
755 {
756 DriverName[Drivers] = reactos_module_strings[ImageId];
757 DriverData[Drivers] = (PVOID)NextModuleBase;
758 DriverSize[Drivers] = ImageSize;
759 Drivers++;
760 }
761
762 /* Increase the next Load Base */
763 NextModuleBase = ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE);
764
765 /* Perform import fixups */
766 if (!NT_SUCCESS(LdrPEFixupImports(LoadBase, Name)))
767 {
768 /* Fixup failed, just don't include it in the list */
769 // NextModuleBase = OldNextModuleBase;
770 LoaderBlock.ModsCount = ImageId;
771 return NULL;
772 }
773
774 /* Return the final mapped address */
775 return LoadBase;
776 }
777
778 /* EOF */