Author: fireball
Date: Thu Oct 5 01:36:56 2006
New Revision: 24402
URL:
http://svn.reactos.org/svn/reactos?rev=24402&view=rev
Log:
- Fix warning in winldr.c
- Implement WinLdrAllocateDataTableEntry() used for allocating and initializing the DTE
- Implement WinLdrLoadImage(), which uses LdrRelocateImageWithBias() from RTL, calling it
with loader name "FLx86" (RTL should treat it differently -- ROS/WinLdr-specific
behavior)
Modified:
trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
trunk/reactos/boot/freeldr/freeldr/windows/winldr.c
Modified: trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/peloader.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/peloader.c Thu Oct 5 01:36:56 2006
@@ -36,7 +36,74 @@
IN PVOID BasePA,
OUT PLDR_DATA_TABLE_ENTRY *NewEntry)
{
- return FALSE;
+ PVOID BaseVA = PaToVa(BasePA);
+ PWSTR Buffer;
+ PLDR_DATA_TABLE_ENTRY DataTableEntry;
+ PIMAGE_NT_HEADERS NtHeaders;
+ USHORT Length;
+
+ /* Allocate memory for a data table entry, zero-initialize it */
+ DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmAllocateMemory(sizeof(LDR_DATA_TABLE_ENTRY));
+ if (DataTableEntry == NULL)
+ return FALSE;
+ RtlZeroMemory(DataTableEntry, sizeof(LDR_DATA_TABLE_ENTRY));
+
+ /* Get NT headers from the image */
+ NtHeaders = RtlImageNtHeader(BasePA);
+
+ /* Initialize corresponding fields of DTE based on NT headers value */
+ DataTableEntry->DllBase = BaseVA;
+ DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
+ DataTableEntry->EntryPoint = (PVOID)((ULONG)BaseVA +
+ NtHeaders->OptionalHeader.AddressOfEntryPoint);
+ DataTableEntry->SectionPointer = 0;
+ DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
+
+ /* Initialize BaseDllName field (UNICODE_STRING) from the Ansi BaseDllName
+ by simple conversion - copying each character */
+ Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR));
+ Buffer = (PWSTR)MmAllocateMemory(Length);
+ if (Buffer == NULL)
+ return FALSE;
+ RtlZeroMemory(Buffer, Length);
+
+ DataTableEntry->BaseDllName.Length = Length;
+ DataTableEntry->BaseDllName.MaximumLength = Length;
+ DataTableEntry->BaseDllName.Buffer = PaToVa(Buffer);
+ while (*BaseDllName != 0)
+ {
+ *Buffer++ = *BaseDllName++;
+ }
+
+ /* Initialize FullDllName field (UNICODE_STRING) from the Ansi FullDllName
+ using the same method */
+ Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR));
+ Buffer = (PWSTR)MmAllocateMemory(Length);
+ if (Buffer == NULL)
+ return FALSE;
+ RtlZeroMemory(Buffer, Length);
+
+ DataTableEntry->FullDllName.Length = Length;
+ DataTableEntry->FullDllName.MaximumLength = Length;
+ DataTableEntry->FullDllName.Buffer = PaToVa(Buffer);
+ while (*FullDllName != 0)
+ {
+ *Buffer++ = *FullDllName++;
+ }
+
+ /* Initialize what's left - LoadCount which is 1, and set Flags so that
+ we know this entry is processed */
+ DataTableEntry->Flags = LDRP_ENTRY_PROCESSED;
+ DataTableEntry->LoadCount = 1;
+
+ /* Insert this DTE to a list in the LPB */
+ InsertTailList(&WinLdrBlock->LoadOrderListHead,
&DataTableEntry->InLoadOrderLinks);
+
+ /* Save pointer to a newly allocated and initialized entry */
+ *NewEntry = DataTableEntry;
+
+ /* Return success */
+ return TRUE;
}
/* WinLdrLoadImage loads the specified image from the file (it doesn't
@@ -49,7 +116,176 @@
WinLdrLoadImage(IN PCHAR FileName,
OUT PVOID *ImageBasePA)
{
- return FALSE;
+ PFILE FileHandle;
+ PVOID PhysicalBase;
+ PVOID VirtualBase = NULL;
+ UCHAR HeadersBuffer[SECTOR_SIZE * 2];
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_SECTION_HEADER SectionHeader;
+ ULONG VirtualSize, SizeOfRawData, NumberOfSections;
+ BOOLEAN Status;
+ ULONG i, BytesRead;
+
+ //Print(L"Loading %s... ", FileName);
+
+ /* Open the image file */
+ FileHandle = FsOpenFile(FileName);
+
+ if (FileHandle == NULL)
+ {
+ //Print(L"Can not open the file %s\n",FileName);
+ UiMessageBox("Can not open the file");
+ return FALSE;
+ }
+
+ /* Load the first 2 sectors of the image so we can read the PE header */
+ Status = FsReadFile(FileHandle, SECTOR_SIZE * 2, NULL, HeadersBuffer);
+ if (!Status)
+ {
+ //Print(L"Error reading from file %s\n", FileName);
+ UiMessageBox("Error reading from file");
+ FsCloseFile(FileHandle);
+ return FALSE;
+ }
+
+ /* Now read the MZ header to get the offset to the PE Header */
+ NtHeaders = RtlImageNtHeader(HeadersBuffer);
+
+ if (!NtHeaders)
+ {
+ //Print(L"Error - no NT header found in %s\n", FileName);
+ UiMessageBox("Error - no NT header found");
+ FsCloseFile(FileHandle);
+ return FALSE;
+ }
+
+ /* Ensure this is executable image */
+ if (((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ==
0))
+ {
+ //Print(L"Not an executable image %s\n", FileName);
+ UiMessageBox("Not an executable image");
+ FsCloseFile(FileHandle);
+ return FALSE;
+ }
+
+ /* Store number of sections to read and a pointer to the first section */
+ NumberOfSections = NtHeaders->FileHeader.NumberOfSections;
+ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
+
+ /* Try to allocate this memory, if fails - allocate somewhere else */
+ PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage,
+ (PVOID)NtHeaders->OptionalHeader.ImageBase);
+
+ if (PhysicalBase == NULL)
+ {
+ /* It's ok, we don't panic - let's allocate again at any other
"low" place */
+ MmChangeAllocationPolicy(FALSE);
+ PhysicalBase = MmAllocateMemory(NtHeaders->OptionalHeader.SizeOfImage);
+ MmChangeAllocationPolicy(TRUE);
+
+ if (PhysicalBase == NULL)
+ {
+ //Print(L"Failed to alloc pages for image %s\n", FileName);
+ UiMessageBox("Failed to alloc pages for image");
+ FsCloseFile(FileHandle);
+ return FALSE;
+ }
+ }
+
+ /* This is the real image base - in form of a virtual address */
+ VirtualBase = PaToVa(PhysicalBase);
+
+ DbgPrint((DPRINT_WINDOWS, "Base PA: 0x%X, VA: 0x%X\n", PhysicalBase,
VirtualBase));
+
+ /* Set to 0 position and fully load the file image */
+ FsSetFilePointer(FileHandle, 0);
+
+ Status = FsReadFile(FileHandle, NtHeaders->OptionalHeader.SizeOfHeaders, NULL,
PhysicalBase);
+
+ if (!Status)
+ {
+ //Print(L"Error reading headers %s\n", FileName);
+ UiMessageBox("Error reading headers");
+ FsCloseFile(FileHandle);
+ return FALSE;
+ }
+
+ /* Reload the NT Header */
+ NtHeaders = RtlImageNtHeader(PhysicalBase);
+
+ /* Load the first section */
+ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
+
+ /* Fill output parameters */
+ *ImageBasePA = PhysicalBase;
+
+ /* Walk through each section and read it (check/fix any possible
+ bad situations, if they arise) */
+ for (i = 0; i < NumberOfSections; i++)
+ {
+ VirtualSize = SectionHeader->Misc.VirtualSize;
+ SizeOfRawData = SectionHeader->SizeOfRawData;
+
+ /* Handle a case when VirtualSize equals 0 */
+ if (VirtualSize == 0)
+ VirtualSize = SizeOfRawData;
+
+ /* If PointerToRawData is 0, then force its size to be also 0 */
+ if (SectionHeader->PointerToRawData == 0)
+ {
+ SizeOfRawData = 0;
+ }
+ else
+ {
+ /* Cut the loaded size to the VirtualSize extents */
+ if (SizeOfRawData > VirtualSize)
+ SizeOfRawData = VirtualSize;
+ }
+
+ /* Actually read the section (if its size is not 0) */
+ if (SizeOfRawData != 0)
+ {
+ /* Seek to the correct position */
+ FsSetFilePointer(FileHandle, SectionHeader->PointerToRawData);
+
+ DbgPrint((DPRINT_WINDOWS, "SH->VA: 0x%X\n",
SectionHeader->VirtualAddress));
+
+ /* Read this section from the file, size = SizeOfRawData */
+ Status = FsReadFile(FileHandle, SizeOfRawData, &BytesRead, (PUCHAR)PhysicalBase +
SectionHeader->VirtualAddress);
+
+ if (!Status && (BytesRead == 0))
+ break;
+ }
+
+ /* Size of data is less than the virtual size - fill up the remainder with zeroes */
+ if (SizeOfRawData < VirtualSize)
+ RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase +
SizeOfRawData), VirtualSize - SizeOfRawData);
+
+ SectionHeader++;
+ }
+
+ /* We are done with the file - close it */
+ FsCloseFile(FileHandle);
+
+ /* If loading failed - return right now */
+ if (!Status)
+ return FALSE;
+
+
+ /* Relocate the image, if it needs it */
+ if (NtHeaders->OptionalHeader.ImageBase != (ULONG)VirtualBase)
+ {
+ DbgPrint((DPRINT_WINDOWS, "Relocating %p -> %p\n",
+ NtHeaders->OptionalHeader.ImageBase, VirtualBase));
+ Status = (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase,
+ 0,
+ "FLx86",
+ TRUE,
+ 3,
+ FALSE);
+ }
+
+ return Status;
}
/* PRIVATE FUNCTIONS *******************************************************/
Modified: trunk/reactos/boot/freeldr/freeldr/windows/winldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/winldr.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/winldr.c Thu Oct 5 01:36:56 2006
@@ -458,7 +458,6 @@
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
KERNEL_ENTRY_POINT KiSystemStartup;
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE;
- PIMAGE_NT_HEADERS NtosHeader;
// Mm-related things
PVOID GdtIdt;
ULONG PcrBasePage=0;