From af48f83e26b66436da46ae5c4785b7d69c14f0c4 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sat, 2 May 2015 18:51:03 +0000 Subject: [PATCH] [NTVDM] Save/restore the processor state when executing/terminating nested tasks. svn path=/trunk/; revision=67513 --- .../mvdm/ntvdm/dos/dos32krnl/process.c | 87 +++++++++++++++---- .../mvdm/ntvdm/dos/dos32krnl/process.h | 7 ++ 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c index 75b975a8b0c..76f0f6dd952 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c @@ -46,6 +46,56 @@ static inline VOID DosSetPspCommandLine(WORD Segment, LPCSTR CommandLine) RtlCopyMemory(PspBlock->CommandLine, CommandLine, DOS_CMDLINE_LENGTH); } +static inline VOID DosSaveState(VOID) +{ + PDOS_REGISTER_STATE State; + WORD StackPointer = getSP(); + + /* Allocate stack space for the registers */ + StackPointer -= sizeof(DOS_REGISTER_STATE); + State = SEG_OFF_TO_PTR(getSS(), StackPointer); + + /* Save */ + State->EAX = getEAX(); + State->ECX = getECX(); + State->EDX = getEDX(); + State->EBX = getEBX(); + State->ESP = getESP(); + State->EBP = getEBP(); + State->ESI = getESI(); + State->EDI = getEDI(); + State->DS = getDS(); + State->ES = getES(); + State->FS = getFS(); + State->GS = getGS(); + State->Flags = getEFLAGS(); +} + +static inline VOID DosRestoreState(VOID) +{ + PDOS_REGISTER_STATE State; + WORD StackPointer = getSP(); + + /* SS:SP points to the stack on the last entry to INT 21h */ + StackPointer -= (STACK_FLAGS + 1) * 2; /* Interrupt parameters */ + StackPointer -= sizeof(DOS_REGISTER_STATE); /* Pushed state structure */ + State = SEG_OFF_TO_PTR(getSS(), StackPointer); + + /* Restore */ + setEAX(State->EAX); + setECX(State->ECX); + setEDX(State->EDX); + setEBX(State->EBX); + setEBP(State->EBP); + setESI(State->ESI); + setEDI(State->EDI); + setDS(State->DS); + setES(State->ES); + setFS(State->FS); + setGS(State->GS); + setEFLAGS(State->Flags); +} + static WORD DosCopyEnvironmentBlock(LPCSTR Environment OPTIONAL, LPCSTR ProgramName) { @@ -432,6 +482,9 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, if (LoadType == DOS_LOAD_AND_EXECUTE) { + /* Save the program state */ + if (CurrentPsp != SYSTEM_PSP) DosSaveState(); + /* Set the initial segment registers */ setDS(Segment); setES(Segment); @@ -750,6 +803,9 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident) PDOS_MCB CurrentMcb; LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp); +#ifndef STANDALONE + VDM_COMMAND_INFO CommandInfo; +#endif DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X, KeepResident 0x%04X\n", Psp, @@ -818,29 +874,25 @@ Done: { ResetEvent(VdmTaskEvent); CpuUnsimulate(); + return; } } #ifndef STANDALONE - // FIXME: This is probably not the best way to do it - /* Check if this was a nested DOS task */ - if (CurrentPsp != SYSTEM_PSP) - { - VDM_COMMAND_INFO CommandInfo; - /* Decrement the re-entry count */ - CommandInfo.TaskId = SessionId; - CommandInfo.VDMState = VDM_DEC_REENTER_COUNT; - GetNextVDMCommand(&CommandInfo); + /* Decrement the re-entry count */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_DEC_REENTER_COUNT; + GetNextVDMCommand(&CommandInfo); - /* Clear the structure */ - RtlZeroMemory(&CommandInfo, sizeof(CommandInfo)); + /* Clear the structure */ + RtlZeroMemory(&CommandInfo, sizeof(CommandInfo)); + + /* Update the VDM state of the task */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_FLAG_DONT_WAIT; + GetNextVDMCommand(&CommandInfo); - /* Update the VDM state of the task */ - CommandInfo.TaskId = SessionId; - CommandInfo.VDMState = VDM_FLAG_DONT_WAIT; - GetNextVDMCommand(&CommandInfo); - } #endif /* Save the return code - Normal termination */ @@ -850,6 +902,9 @@ Done: setSS(HIWORD(SEGMENT_TO_PSP(CurrentPsp)->LastStack)); setSP(LOWORD(SEGMENT_TO_PSP(CurrentPsp)->LastStack)); + /* Restore the program state */ + DosRestoreState(); + /* Return control to the parent process */ CpuExecute(HIWORD(PspBlock->TerminateAddress), LOWORD(PspBlock->TerminateAddress)); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h index a9f5e7d0414..42744dc69c7 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h @@ -72,6 +72,13 @@ typedef struct _DOS_EXEC_PARAM_BLOCK }; } DOS_EXEC_PARAM_BLOCK, *PDOS_EXEC_PARAM_BLOCK; +typedef struct _DOS_REGISTER_STATE +{ + DWORD Flags; + WORD GS, FS, ES, DS; + DWORD EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX; +} DOS_REGISTER_STATE, *PDOS_REGISTER_STATE; + #pragma pack(pop) /* VARIABLES ******************************************************************/ -- 2.17.1