mirror of
https://github.com/reactos/reactos.git
synced 2024-08-01 09:01:13 +00:00
[NTVDM]
The fix in r67477 was incorrect. When loading an executable high, we need to allocate all of the memory and copy the program itself to the highest part of it. I know it sounds illogical but that's how it works... svn path=/trunk/; revision=67478
This commit is contained in:
parent
294468d4e7
commit
5891e0a021
|
@ -292,12 +292,13 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
WORD Segment = 0;
|
WORD Segment = 0;
|
||||||
WORD EnvBlock = 0;
|
WORD EnvBlock = 0;
|
||||||
WORD MaxAllocSize;
|
WORD MaxAllocSize;
|
||||||
DWORD i, FileSize, ExeSize;
|
WORD ExeSegment;
|
||||||
|
DWORD i, FileSize, BaseSize, TotalSize;
|
||||||
PIMAGE_DOS_HEADER Header;
|
PIMAGE_DOS_HEADER Header;
|
||||||
PDWORD RelocationTable;
|
PDWORD RelocationTable;
|
||||||
PWORD RelocWord;
|
PWORD RelocWord;
|
||||||
LPSTR CmdLinePtr = (LPSTR)CommandLine;
|
LPSTR CmdLinePtr = (LPSTR)CommandLine;
|
||||||
BYTE OldStrategy = DosAllocStrategy;
|
BOOLEAN LoadHigh = FALSE;
|
||||||
|
|
||||||
DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n",
|
DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n",
|
||||||
LoadType,
|
LoadType,
|
||||||
|
@ -372,45 +373,46 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
Header = (PIMAGE_DOS_HEADER)Address;
|
Header = (PIMAGE_DOS_HEADER)Address;
|
||||||
|
|
||||||
/* Get the base size of the file, in paragraphs (rounded up) */
|
/* Get the base size of the file, in paragraphs (rounded up) */
|
||||||
ExeSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4;
|
BaseSize = TotalSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4;
|
||||||
|
|
||||||
/* Add the PSP size, in paragraphs */
|
/* Add the PSP size, in paragraphs */
|
||||||
ExeSize += sizeof(DOS_PSP) >> 4;
|
TotalSize += sizeof(DOS_PSP) >> 4;
|
||||||
|
|
||||||
/* Add the maximum size that should be allocated */
|
/* Add the maximum size that should be allocated */
|
||||||
ExeSize += Header->e_maxalloc;
|
TotalSize += Header->e_maxalloc;
|
||||||
|
|
||||||
/* Make sure it does not pass 0xFFFF */
|
|
||||||
if (ExeSize > 0xFFFF) ExeSize = 0xFFFF;
|
|
||||||
|
|
||||||
if (Header->e_minalloc == 0 && Header->e_maxalloc == 0)
|
if (Header->e_minalloc == 0 && Header->e_maxalloc == 0)
|
||||||
{
|
{
|
||||||
/* This program should be loaded high */
|
/* This program should be loaded high */
|
||||||
DosAllocStrategy = DOS_ALLOC_LAST_FIT;
|
LoadHigh = TRUE;
|
||||||
|
TotalSize = 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure it does not pass 0xFFFF */
|
||||||
|
if (TotalSize > 0xFFFF) TotalSize = 0xFFFF;
|
||||||
|
|
||||||
/* Try to allocate that much memory */
|
/* Try to allocate that much memory */
|
||||||
Segment = DosAllocateMemory((WORD)ExeSize, &MaxAllocSize);
|
Segment = DosAllocateMemory((WORD)TotalSize, &MaxAllocSize);
|
||||||
|
|
||||||
if (Segment == 0)
|
if (Segment == 0)
|
||||||
{
|
{
|
||||||
/* Check if there's at least enough memory for the minimum size */
|
/* Check if there's at least enough memory for the minimum size */
|
||||||
if (MaxAllocSize < (ExeSize - Header->e_maxalloc + Header->e_minalloc))
|
if (MaxAllocSize < (BaseSize + (sizeof(DOS_PSP) >> 4) + Header->e_minalloc))
|
||||||
{
|
{
|
||||||
Result = DosLastError;
|
Result = DosLastError;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate that minimum amount */
|
/* Allocate that minimum amount */
|
||||||
ExeSize = MaxAllocSize;
|
TotalSize = MaxAllocSize;
|
||||||
Segment = DosAllocateMemory((WORD)ExeSize, NULL);
|
Segment = DosAllocateMemory((WORD)TotalSize, NULL);
|
||||||
ASSERT(Segment != 0);
|
ASSERT(Segment != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the PSP */
|
/* Initialize the PSP */
|
||||||
DosInitializePsp(Segment,
|
DosInitializePsp(Segment,
|
||||||
CommandLine,
|
CommandLine,
|
||||||
(WORD)ExeSize,
|
(WORD)TotalSize,
|
||||||
EnvBlock,
|
EnvBlock,
|
||||||
ReturnAddress);
|
ReturnAddress);
|
||||||
|
|
||||||
|
@ -418,11 +420,14 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
DosChangeMemoryOwner(Segment, Segment);
|
DosChangeMemoryOwner(Segment, Segment);
|
||||||
DosChangeMemoryOwner(EnvBlock, Segment);
|
DosChangeMemoryOwner(EnvBlock, Segment);
|
||||||
|
|
||||||
/* Copy the program to Segment:0100 */
|
/* Find the EXE segment */
|
||||||
RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100),
|
if (!LoadHigh) ExeSegment = Segment + (sizeof(DOS_PSP) >> 4);
|
||||||
|
else ExeSegment = Segment + TotalSize - BaseSize;
|
||||||
|
|
||||||
|
/* Copy the program to the code segment */
|
||||||
|
RtlCopyMemory(SEG_OFF_TO_PTR(ExeSegment, 0),
|
||||||
Address + (Header->e_cparhdr << 4),
|
Address + (Header->e_cparhdr << 4),
|
||||||
min(FileSize - (Header->e_cparhdr << 4),
|
min(FileSize - (Header->e_cparhdr << 4), BaseSize << 4));
|
||||||
(ExeSize << 4) - sizeof(DOS_PSP)));
|
|
||||||
|
|
||||||
/* Get the relocation table */
|
/* Get the relocation table */
|
||||||
RelocationTable = (PDWORD)(Address + Header->e_lfarlc);
|
RelocationTable = (PDWORD)(Address + Header->e_lfarlc);
|
||||||
|
@ -431,11 +436,11 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
for (i = 0; i < Header->e_crlc; i++)
|
for (i = 0; i < Header->e_crlc; i++)
|
||||||
{
|
{
|
||||||
/* Get a pointer to the word that needs to be patched */
|
/* Get a pointer to the word that needs to be patched */
|
||||||
RelocWord = (PWORD)SEG_OFF_TO_PTR(Segment + HIWORD(RelocationTable[i]),
|
RelocWord = (PWORD)SEG_OFF_TO_PTR(ExeSegment + HIWORD(RelocationTable[i]),
|
||||||
0x100 + LOWORD(RelocationTable[i]));
|
LOWORD(RelocationTable[i]));
|
||||||
|
|
||||||
/* Add the number of the EXE segment to it */
|
/* Add the number of the EXE segment to it */
|
||||||
*RelocWord += Segment + (sizeof(DOS_PSP) >> 4);
|
*RelocWord += ExeSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoadType == DOS_LOAD_AND_EXECUTE)
|
if (LoadType == DOS_LOAD_AND_EXECUTE)
|
||||||
|
@ -445,14 +450,13 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
setES(Segment);
|
setES(Segment);
|
||||||
|
|
||||||
/* Set the stack to the location from the header */
|
/* Set the stack to the location from the header */
|
||||||
setSS(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss);
|
setSS(ExeSegment + Header->e_ss);
|
||||||
setSP(Header->e_sp);
|
setSP(Header->e_sp);
|
||||||
|
|
||||||
/* Execute */
|
/* Execute */
|
||||||
CurrentPsp = Segment;
|
CurrentPsp = Segment;
|
||||||
DiskTransferArea = MAKELONG(0x80, Segment);
|
DiskTransferArea = MAKELONG(0x80, Segment);
|
||||||
CpuExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4),
|
CpuExecute(ExeSegment + Header->e_cs, Header->e_ip);
|
||||||
Header->e_ip);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -524,9 +528,6 @@ Cleanup:
|
||||||
if (Segment) DosFreeMemory(Segment);
|
if (Segment) DosFreeMemory(Segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the old allocation strategy */
|
|
||||||
DosAllocStrategy = OldStrategy;
|
|
||||||
|
|
||||||
/* Unmap the file*/
|
/* Unmap the file*/
|
||||||
if (Address != NULL) UnmapViewOfFile(Address);
|
if (Address != NULL) UnmapViewOfFile(Address);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue