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