[ros-diffs] [fireball] 24402: - 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)

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Oct 4 23:36:57 CEST 2006


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/windows/peloader.c?rev=24402&r1=24401&r2=24402&view=diff
==============================================================================
--- 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/windows/winldr.c?rev=24402&r1=24401&r2=24402&view=diff
==============================================================================
--- 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;




More information about the Ros-diffs mailing list