[NTVDM]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 2 May 2015 02:59:21 +0000 (02:59 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 2 May 2015 02:59:21 +0000 (02:59 +0000)
Implement INT 27h (Terminate and Stay Resident).
Keep track of the last entry SS:SP in the INT 21h handler.
Restore the stack in DosTerminateProcess.
The number of bytes to keep resident applies only to the block which holds the PSP,
other blocks are not freed.

svn path=/trunk/; revision=67507

reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c

index 54d8b53..3b3c673 100644 (file)
@@ -178,6 +178,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
 
     (*InDos)++;
 
+    /* Save the value of SS:SP on entry in the PSP */
+    SEGMENT_TO_PSP(CurrentPsp)->LastStack =
+    MAKELONG(getSP() + (STACK_FLAGS + 1) * 2, getSS());
+
     /* Check the value in the AH register */
     switch (getAH())
     {
@@ -1817,6 +1821,11 @@ VOID WINAPI DosBreakInterrupt(LPWORD Stack)
     Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
 }
 
+VOID WINAPI DosInt27h(LPWORD Stack)
+{
+    DosTerminateProcess(getCS(), 0, (getDX() + 0x0F) >> 4);
+}
+
 VOID WINAPI DosFastConOut(LPWORD Stack)
 {
     /*
@@ -2002,6 +2011,7 @@ BOOLEAN DosKRNLInitialize(VOID)
 //  RegisterDosInt32(0x22, DosInt22h        ); // Termination
     RegisterDosInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
 //  RegisterDosInt32(0x24, DosInt24h        ); // Critical Error
+    RegisterDosInt32(0x27, DosInt27h        ); // Terminate and Stay Resident
     RegisterDosInt32(0x29, DosFastConOut    ); // DOS 2+ Fast Console Output
     RegisterDosInt32(0x2F, DosInt2Fh        );
 
index 70919b8..75b975a 100644 (file)
@@ -780,23 +780,20 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident)
         /* Check if this block was allocated by the process */
         if (CurrentMcb->OwnerPsp == Psp)
         {
-            if (KeepResident == 0)
+            if (KeepResident)
             {
-                /* Free this entire block */
-                DosFreeMemory(McbSegment + 1);
-            }
-            else if (KeepResident < CurrentMcb->Size)
-            {
-                /* Reduce the size of the block */
-                DosResizeMemory(McbSegment + 1, KeepResident, NULL);
-
-                /* No further paragraphs need to stay resident */
-                KeepResident = 0;
+                /* Check if this is the PSP block and we should reduce its size */
+                if (McbSegment == Psp && KeepResident < CurrentMcb->Size)
+                {
+                    /* Reduce the size of the block */
+                    DosResizeMemory(McbSegment + 1, KeepResident, NULL);
+                    break;
+                }
             }
             else
             {
-                /* Just reduce the amount of paragraphs we need to keep resident */
-                KeepResident -= CurrentMcb->Size;
+                /* Free this entire block */
+                DosFreeMemory(McbSegment + 1);
             }
         }
 
@@ -849,6 +846,10 @@ Done:
     /* Save the return code - Normal termination */
     DosErrorLevel = MAKEWORD(ReturnCode, 0x00);
 
+    /* Restore the old stack */
+    setSS(HIWORD(SEGMENT_TO_PSP(CurrentPsp)->LastStack));
+    setSP(LOWORD(SEGMENT_TO_PSP(CurrentPsp)->LastStack));
+
     /* Return control to the parent process */
     CpuExecute(HIWORD(PspBlock->TerminateAddress),
                LOWORD(PspBlock->TerminateAddress));