[NTOSKRNL]

Check for old-style MZ executable in PeFmtCreateSection.
[NTVDM]
Fix bugs.
Implement MZ executable loading.


svn path=/branches/ntvdm/; revision=59328
This commit is contained in:
Aleksandar Andrejevic 2013-06-24 01:59:09 +00:00
parent 13a004a57d
commit ca06374c9f
5 changed files with 76 additions and 11 deletions

View file

@ -237,6 +237,10 @@ NTSTATUS NTAPI PeFmtCreateSection(IN CONST VOID * FileHeader,
if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic));
/* check if this is an old MZ executable */
if(pidhDosHeader->e_lfarlc < 0x40)
DIE(("Old-style MZ executable found, e_lfarlc is %d\n", pidhDosHeader->e_lfarlc));
/* not a Windows executable */
if(pidhDosHeader->e_lfanew <= 0)
DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew));

View file

@ -320,7 +320,10 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
LPSTR ProgramFilePath, Parameters[128];
CHAR CommandLineCopy[128];
INT ParamCount = 0;
WORD Segment, FileSize;
WORD i, Segment, FileSize, ExeSize;
PIMAGE_DOS_HEADER Header;
PDWORD RelocationTable;
PWORD RelocWord;
/* Save a copy of the command line */
strcpy(CommandLineCopy, CommandLine);
@ -366,8 +369,64 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
{
/* EXE file */
// TODO: NOT IMPLEMENTED
DisplayMessage(L"EXE files are not yet supported!");
/* Get the MZ header */
Header = (PIMAGE_DOS_HEADER)Address;
// TODO: Verify checksum and executable!
/* Get the base size of the file, in paragraphs (rounded up) */
ExeSize = (((Header->e_cp - 1) << 8) + Header->e_cblp + 0x0F) >> 4;
/* Loop from the maximum to the minimum number of extra paragraphs */
for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--)
{
/* Try to allocate that much memory */
Segment = DosAllocateMemory(ExeSize + (sizeof(DOS_PSP) >> 4) + i);
if (Segment != 0) break;
}
/* Check if at least the lowest allocation was successful */
if (Segment == 0) goto Cleanup;
/* Initialize the PSP */
DosInitializePsp(Segment,
CommandLine, ExeSize + (sizeof(DOS_PSP) >> 4) + i,
EnvBlock);
/* Copy the program to Segment:0100 */
RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress
+ TO_LINEAR(Segment, 0x100)),
Address + (Header->e_cparhdr << 4),
FileSize - (Header->e_cparhdr << 4));
/* Get the relocation table */
RelocationTable = (PDWORD)(Address + Header->e_lfarlc);
/* Perform relocations */
for (i = 0; i < Header->e_crlc; i++)
{
/* Get a pointer to the word that needs to be patched */
RelocWord = (PWORD)((ULONG_PTR)BaseAddress
+ TO_LINEAR(Segment + HIWORD(RelocationTable[i]),
0x100 + LOWORD(RelocationTable[i])));
/* Add the number of the EXE segment to it */
*RelocWord += Segment + (sizeof(DOS_PSP) >> 4);
}
/* Set the initial segment registers */
EmulatorSetRegister(EMULATOR_REG_DS, Segment);
EmulatorSetRegister(EMULATOR_REG_ES, Segment);
/* Set the stack to the location from the header */
EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss,
Header->e_sp);
/* Execute */
CurrentPsp = Segment;
EmulatorExecute(Segment + Header->e_cs, sizeof(DOS_PSP) + Header->e_ip);
Success = TRUE;
}
else
{

View file

@ -254,13 +254,13 @@ VOID EmulatorInterrupt(BYTE Number)
ULONG EmulatorGetRegister(ULONG Register)
{
if (Register < EMULATOR_REG_CS)
if (Register < EMULATOR_REG_ES)
{
return EmulatorContext.state->general_reg[Register].val;
}
else
{
return EmulatorContext.state->segment_reg[(Register >> 3) - 1].val;
return EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val;
}
}
@ -272,7 +272,7 @@ VOID EmulatorSetRegister(ULONG Register, ULONG Value)
}
else
{
EmulatorContext.state->segment_reg[(Register >> 3) - 1].val = Value;
EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val = Value;
}
}

View file

@ -42,6 +42,7 @@ BOOL WINAPI ConsoleCtrlHandler(DWORD ControlType)
{
/* Perform interrupt 0x23 */
EmulatorInterrupt(0x23);
break;
}
default:
{
@ -124,9 +125,12 @@ INT wmain(INT argc, WCHAR *argv[])
}
/* Continue CPU emulation */
for (i = 0; i < STEPS_PER_CYCLE; i++) EmulatorStep();
for (i = 0; (i < STEPS_PER_CYCLE) && VdmRunning; i++)
{
EmulatorStep();
Cycles++;
}
Cycles += STEPS_PER_CYCLE;
if ((CurrentTickCount - LastCyclePrintout) >= 1000)
{
DPRINT1("NTVDM: %d Instructions Per Second\n", Cycles);

View file

@ -102,12 +102,10 @@ typedef enum
EMULATOR_REG_DI,
EMULATOR_REG_SP,
EMULATOR_REG_BP,
EMULATOR_REG_ES,
EMULATOR_REG_CS,
EMULATOR_REG_SS,
EMULATOR_REG_DS,
EMULATOR_REG_ES,
EMULATOR_REG_FS,
EMULATOR_REG_GS
} EMULATOR_REGISTER;
#pragma pack(push, 1)