mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 18:35:32 +00:00
- 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) svn path=/trunk/; revision=24402
This commit is contained in:
parent
76abbb4423
commit
602923e572
|
@ -36,7 +36,74 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
|
|||
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 @@ BOOLEAN
|
|||
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 *******************************************************/
|
||||
|
|
|
@ -458,7 +458,6 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue