mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 15:02:59 +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
2 changed files with 238 additions and 3 deletions
|
@ -36,7 +36,74 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
|
||||||
IN PVOID BasePA,
|
IN PVOID BasePA,
|
||||||
OUT PLDR_DATA_TABLE_ENTRY *NewEntry)
|
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
|
/* WinLdrLoadImage loads the specified image from the file (it doesn't
|
||||||
|
@ -49,7 +116,176 @@ BOOLEAN
|
||||||
WinLdrLoadImage(IN PCHAR FileName,
|
WinLdrLoadImage(IN PCHAR FileName,
|
||||||
OUT PVOID *ImageBasePA)
|
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 *******************************************************/
|
/* PRIVATE FUNCTIONS *******************************************************/
|
||||||
|
|
|
@ -458,7 +458,6 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
|
||||||
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
|
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
|
||||||
KERNEL_ENTRY_POINT KiSystemStartup;
|
KERNEL_ENTRY_POINT KiSystemStartup;
|
||||||
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE;
|
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE;
|
||||||
PIMAGE_NT_HEADERS NtosHeader;
|
|
||||||
// Mm-related things
|
// Mm-related things
|
||||||
PVOID GdtIdt;
|
PVOID GdtIdt;
|
||||||
ULONG PcrBasePage=0;
|
ULONG PcrBasePage=0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue