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;