Author: aandrejevic Date: Wed Apr 29 03:18:02 2015 New Revision: 67478
URL: http://svn.reactos.org/svn/reactos?rev=67478&view=rev Log: [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...
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Wed Apr 29 03:18:02 2015 @@ -292,12 +292,13 @@ WORD Segment = 0; WORD EnvBlock = 0; WORD MaxAllocSize; - DWORD i, FileSize, ExeSize; + WORD ExeSegment; + DWORD i, FileSize, BaseSize, TotalSize; PIMAGE_DOS_HEADER Header; PDWORD RelocationTable; PWORD RelocWord; LPSTR CmdLinePtr = (LPSTR)CommandLine; - BYTE OldStrategy = DosAllocStrategy; + BOOLEAN LoadHigh = FALSE;
DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n", LoadType, @@ -372,45 +373,46 @@ Header = (PIMAGE_DOS_HEADER)Address;
/* 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 */ - ExeSize += sizeof(DOS_PSP) >> 4; + TotalSize += sizeof(DOS_PSP) >> 4;
/* Add the maximum size that should be allocated */ - ExeSize += Header->e_maxalloc; + TotalSize += Header->e_maxalloc; + + if (Header->e_minalloc == 0 && Header->e_maxalloc == 0) + { + /* This program should be loaded high */ + LoadHigh = TRUE; + TotalSize = 0xFFFF; + }
/* Make sure it does not pass 0xFFFF */ - if (ExeSize > 0xFFFF) ExeSize = 0xFFFF; - - if (Header->e_minalloc == 0 && Header->e_maxalloc == 0) - { - /* This program should be loaded high */ - DosAllocStrategy = DOS_ALLOC_LAST_FIT; - } + if (TotalSize > 0xFFFF) TotalSize = 0xFFFF;
/* Try to allocate that much memory */ - Segment = DosAllocateMemory((WORD)ExeSize, &MaxAllocSize); + Segment = DosAllocateMemory((WORD)TotalSize, &MaxAllocSize);
if (Segment == 0) { /* 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; goto Cleanup; }
/* Allocate that minimum amount */ - ExeSize = MaxAllocSize; - Segment = DosAllocateMemory((WORD)ExeSize, NULL); + TotalSize = MaxAllocSize; + Segment = DosAllocateMemory((WORD)TotalSize, NULL); ASSERT(Segment != 0); }
/* Initialize the PSP */ DosInitializePsp(Segment, CommandLine, - (WORD)ExeSize, + (WORD)TotalSize, EnvBlock, ReturnAddress);
@@ -418,11 +420,14 @@ DosChangeMemoryOwner(Segment, Segment); DosChangeMemoryOwner(EnvBlock, Segment);
- /* Copy the program to Segment:0100 */ - RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100), + /* Find the EXE segment */ + 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), - min(FileSize - (Header->e_cparhdr << 4), - (ExeSize << 4) - sizeof(DOS_PSP))); + min(FileSize - (Header->e_cparhdr << 4), BaseSize << 4));
/* Get the relocation table */ RelocationTable = (PDWORD)(Address + Header->e_lfarlc); @@ -431,11 +436,11 @@ for (i = 0; i < Header->e_crlc; i++) { /* Get a pointer to the word that needs to be patched */ - RelocWord = (PWORD)SEG_OFF_TO_PTR(Segment + HIWORD(RelocationTable[i]), - 0x100 + LOWORD(RelocationTable[i])); + RelocWord = (PWORD)SEG_OFF_TO_PTR(ExeSegment + HIWORD(RelocationTable[i]), + LOWORD(RelocationTable[i]));
/* Add the number of the EXE segment to it */ - *RelocWord += Segment + (sizeof(DOS_PSP) >> 4); + *RelocWord += ExeSegment; }
if (LoadType == DOS_LOAD_AND_EXECUTE) @@ -445,14 +450,13 @@ setES(Segment);
/* 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);
/* Execute */ CurrentPsp = Segment; DiskTransferArea = MAKELONG(0x80, Segment); - CpuExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4), - Header->e_ip); + CpuExecute(ExeSegment + Header->e_cs, Header->e_ip); } } else @@ -523,9 +527,6 @@ if (EnvBlock) DosFreeMemory(EnvBlock); if (Segment) DosFreeMemory(Segment); } - - /* Restore the old allocation strategy */ - DosAllocStrategy = OldStrategy;
/* Unmap the file*/ if (Address != NULL) UnmapViewOfFile(Address);