Author: aandrejevic Date: Sat May 2 18:51:03 2015 New Revision: 67513
URL: http://svn.reactos.org/svn/reactos?rev=67513&view=rev Log: [NTVDM] Save/restore the processor state when executing/terminating nested tasks.
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c [iso-8859-1] Sat May 2 18:51:03 2015 @@ -44,6 +44,56 @@ PspBlock->CommandLineSize = min(*(PBYTE)CommandLine, DOS_CMDLINE_LENGTH); 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, @@ -432,6 +482,9 @@
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 @@ 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 @@ { 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); - - /* 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); - } + + /* Decrement the re-entry count */ + CommandInfo.TaskId = SessionId; + CommandInfo.VDMState = VDM_DEC_REENTER_COUNT; + GetNextVDMCommand(&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); + #endif
/* Save the return code - Normal termination */ @@ -850,6 +902,9 @@ 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));
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/d... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.h [iso-8859-1] Sat May 2 18:51:03 2015 @@ -72,6 +72,13 @@ }; } 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 ******************************************************************/