Author: aandrejevic
Date: Thu May  1 23:52:36 2014
New Revision: 63098

URL: http://svn.reactos.org/svn/reactos?rev=63098&view=rev
Log:
[BASESRV][KERNEL32][NTVDM]
Make our BaseSrvGetNextVDMCommand and GetNextVDMCommand a bit more 
Windows-compatible,
and modify NTVDM accordingly.


Modified:
    branches/ntvdm/dll/win32/kernel32/client/vdm.c
    branches/ntvdm/include/reactos/subsys/win/vdm.h
    branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c
    branches/ntvdm/subsystems/ntvdm/ntvdm.c
    branches/ntvdm/subsystems/win/basesrv/vdm.c

Modified: branches/ntvdm/dll/win32/kernel32/client/vdm.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ntvdm/dll/win32/kernel32/client/vdm.c?rev=63098&r1=63097&r2=63098&view=diff
==============================================================================
--- branches/ntvdm/dll/win32/kernel32/client/vdm.c      [iso-8859-1] (original)
+++ branches/ntvdm/dll/win32/kernel32/client/vdm.c      [iso-8859-1] Thu May  1 
23:52:36 2014
@@ -1281,6 +1281,10 @@
                         BaseSetLastNTError(Status);
                         goto Cleanup;
                     }
+
+                    /* Set the retry flag and clear the exit code */
+                    GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
+                    GetNextVdmCommand->ExitCode = 0;
                 }
             }
             while (GetNextVdmCommand->WaitObjectForVDM != NULL);

Modified: branches/ntvdm/include/reactos/subsys/win/vdm.h
URL: 
http://svn.reactos.org/svn/reactos/branches/ntvdm/include/reactos/subsys/win/vdm.h?rev=63098&r1=63097&r2=63098&view=diff
==============================================================================
--- branches/ntvdm/include/reactos/subsys/win/vdm.h     [iso-8859-1] (original)
+++ branches/ntvdm/include/reactos/subsys/win/vdm.h     [iso-8859-1] Thu May  1 
23:52:36 2014
@@ -48,11 +48,22 @@
 #define VDM_READY           0x04
 
 //
-// VDM Magic Values
+// VDM Flags
 //
+#define VDM_FLAG_FIRST_TASK     0x01
 #define VDM_FLAG_WOW            0x02
+#define VDM_FLAG_DOS            0x04
+#define VDM_FLAG_RETRY          0x08
 #define VDM_INC_REENTER_COUNT   0x10
 #define VDM_DEC_REENTER_COUNT   0x20
+#define VDM_FLAG_NESTED_TASK    0x40
+#define VDM_FLAG_DONT_WAIT      0x80
+#define VDM_GET_FIRST_COMMAND   0x100
+#define VDM_GET_ENVIRONMENT     0x400
+#define VDM_FLAG_SEPARATE_WOW   0x800
+#define VDM_LIST_WOW_PROCESSES  0x1000
+#define VDM_LIST_WOW_TASKS      0x4000
+#define VDM_ADD_WOW_TASK        0x8000
 
 typedef struct
 {

Modified: branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c?rev=63098&r1=63097&r2=63098&view=diff
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Thu May  1 
23:52:36 2014
@@ -1336,7 +1336,7 @@
             ZeroMemory(&CommandInfo, sizeof(CommandInfo));
 
             /* Initialize the structure members */
-            CommandInfo.VDMState = VDM_NOT_READY;
+            CommandInfo.VDMState = VDM_FLAG_NESTED_TASK | VDM_FLAG_DONT_WAIT;
             CommandInfo.CmdLine = CmdLine;
             CommandInfo.CmdLen = sizeof(CmdLine);
             CommandInfo.AppName = AppName;
@@ -1399,6 +1399,7 @@
     PDOS_MCB CurrentMcb;
     LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
     PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp);
+    VDM_COMMAND_INFO CommandInfo;
 
     DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n",
            Psp,
@@ -1443,6 +1444,22 @@
     {
         CurrentPsp = PspBlock->ParentPsp;
         if (CurrentPsp == SYSTEM_PSP) VdmRunning = FALSE;
+    }
+
+    // FIXME: This is probably not the best way to do it
+    /* Check if this was a nested DOS task */
+    if (VdmRunning)
+    {
+        /* Decrement the re-entry count */
+        CommandInfo.VDMState = VDM_DEC_REENTER_COUNT;
+        GetNextVDMCommand(&CommandInfo);
+
+        /* Clear the structure */
+        ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+
+        /* Update the VDM state of the task */
+        CommandInfo.VDMState = VDM_FLAG_DONT_WAIT;
+        GetNextVDMCommand(&CommandInfo);
     }
 
     /* Save the return code - Normal termination */

Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?rev=63098&r1=63097&r2=63098&view=diff
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ntvdm.c     [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ntvdm.c     [iso-8859-1] Thu May  1 
23:52:36 2014
@@ -390,6 +390,7 @@
 
 DWORD WINAPI CommandThreadProc(LPVOID Parameter)
 {
+    BOOLEAN First = TRUE;
     DWORD Result;
     VDM_COMMAND_INFO CommandInfo;
     CHAR CmdLine[MAX_PATH];
@@ -407,7 +408,7 @@
         ZeroMemory(&CommandInfo, sizeof(CommandInfo));
 
         /* Initialize the structure members */
-        CommandInfo.VDMState = VDM_NOT_LOADED;
+        CommandInfo.VDMState = VDM_FLAG_DOS;
         CommandInfo.CmdLine = CmdLine;
         CommandInfo.CmdLen = sizeof(CmdLine);
         CommandInfo.AppName = AppName;
@@ -421,6 +422,12 @@
         CommandInfo.Env = Env;
         CommandInfo.EnvLen = sizeof(Env);
 
+        if (First)
+        {
+            CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
+            First = FALSE;
+        }
+
         /* Wait for the next available VDM */
         if (!GetNextVDMCommand(&CommandInfo)) break;
 

Modified: branches/ntvdm/subsystems/win/basesrv/vdm.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/win/basesrv/vdm.c?rev=63098&r1=63097&r2=63098&view=diff
==============================================================================
--- branches/ntvdm/subsystems/win/basesrv/vdm.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/win/basesrv/vdm.c [iso-8859-1] Thu May  1 
23:52:36 2014
@@ -905,21 +905,58 @@
         GetNextVdmCommandRequest->iTask = ConsoleRecord->SessionId;
         GetNextVdmCommandRequest->WaitObjectForVDM = NULL;
 
-        if (!(GetNextVdmCommandRequest->VDMState & VDM_NOT_READY))
-        {
+        if (GetNextVdmCommandRequest->VDMState & VDM_GET_FIRST_COMMAND)
+        {
+            /* Check if the DOS record list is empty */
+            if (ConsoleRecord->DosListHead.Flink == 
&ConsoleRecord->DosListHead)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Cleanup;
+            }
+
+            /* Get the first DOS record */
+            DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, 
VDM_DOS_RECORD, Entry);
+
+            /* Make sure its command information is still there */
+            if (DosRecord->CommandInfo == NULL)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Cleanup;
+            }
+
+            /* Fill the command information */
+            Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, 
GetNextVdmCommandRequest);
+            goto Cleanup;
+        }
+
+        /* Check if we should set the state of a running DOS record to ready */
+        if (!(GetNextVdmCommandRequest->VDMState
+            & (VDM_FLAG_FIRST_TASK | VDM_FLAG_RETRY | VDM_FLAG_NESTED_TASK)))
+        {
+            /* Search for a DOS record that is currently running */
             for (i = ConsoleRecord->DosListHead.Flink; i != 
&ConsoleRecord->DosListHead; i = i->Flink)
             {
                 DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry);
-                if (DosRecord->State == VDM_NOT_READY)
-                {
-                    /* If NTVDM is asking for a new command, it means these 
are done */
-                    DosRecord->State = VDM_READY; 
-
-                    NtSetEvent(DosRecord->ServerEvent, NULL);
-                    NtClose(DosRecord->ServerEvent);
-                    DosRecord->ServerEvent = NULL;
-                }
-            }
+                if (DosRecord->State == VDM_NOT_READY) break;
+            }
+
+            /* Check if we found any */
+            if (i == &ConsoleRecord->DosListHead)
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                goto Cleanup;
+            }
+
+            /* Set the exit code */
+            DosRecord->ExitCode = GetNextVdmCommandRequest->ExitCode;
+
+            /* Update the VDM state */
+            DosRecord->State = VDM_READY; 
+
+            /* Notify all waiting threads that the task is finished */
+            NtSetEvent(DosRecord->ServerEvent, NULL);
+            NtClose(DosRecord->ServerEvent);
+            DosRecord->ServerEvent = NULL;
         }
 
         /* Search for a DOS record that isn't loaded yet */
@@ -931,16 +968,40 @@
 
         if (i != &ConsoleRecord->DosListHead)
         {
-            /* Fill the command information */
-            Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, 
GetNextVdmCommandRequest);
-            if (!NT_SUCCESS(Status)) goto Cleanup;
-
-            /* Free the command information, it's no longer needed */
-            BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
-            DosRecord->CommandInfo = NULL;
-
-            /* Update the VDM state */
-            DosRecord->State = VDM_NOT_READY;
+            /* DOS tasks which haven't been loaded yet should have a command 
info structure */
+            ASSERT(DosRecord->CommandInfo != NULL);
+
+            /* Check if the caller only wants environment data */
+            if (GetNextVdmCommandRequest->VDMState & VDM_GET_ENVIRONMENT)
+            {
+                if (GetNextVdmCommandRequest->EnvLen < 
DosRecord->CommandInfo->EnvLen)
+                {
+                    /* Not enough space was reserved */
+                    GetNextVdmCommandRequest->EnvLen = 
DosRecord->CommandInfo->EnvLen;
+                    Status = STATUS_BUFFER_OVERFLOW;
+                    goto Cleanup;
+                }
+
+                /* Copy the environment data */
+                RtlMoveMemory(GetNextVdmCommandRequest->Env,
+                              DosRecord->CommandInfo->Env,
+                              DosRecord->CommandInfo->EnvLen);
+
+                /* Return the actual size to the caller */
+                GetNextVdmCommandRequest->EnvLen = 
DosRecord->CommandInfo->EnvLen;
+            }
+            else
+            {
+                /* Fill the command information */
+                Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, 
GetNextVdmCommandRequest);
+
+                /* Free the command information, it's no longer needed */
+                BaseSrvFreeVDMInfo(DosRecord->CommandInfo);
+                DosRecord->CommandInfo = NULL;
+
+                /* Update the VDM state */
+                GetNextVdmCommandRequest->VDMState = DosRecord->State = 
VDM_NOT_READY;
+            }
 
             Status = STATUS_SUCCESS;
             goto Cleanup;
@@ -954,21 +1015,25 @@
     }
 
     /* There is no command yet */
-    if (ConsoleRecord->ServerEvent)
-    {
-        /* Reset the event */
-        NtResetEvent(ConsoleRecord->ServerEvent, NULL);
-    }
-    else
-    {
-        /* Create a pair of wait handles */
-        Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent,
-                                              &ConsoleRecord->ClientEvent);
-        if (!NT_SUCCESS(Status)) goto Cleanup;
-    }
-
-    /* Return the client event handle */
-    GetNextVdmCommandRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent;
+    if ((GetNextVdmCommandRequest->VDMState & (VDM_FLAG_DONT_WAIT | 
VDM_FLAG_RETRY))
+        != (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY))
+    {
+        if (ConsoleRecord->ServerEvent)
+        {
+            /* Reset the event */
+            NtResetEvent(ConsoleRecord->ServerEvent, NULL);
+        }
+        else
+        {
+            /* Create a pair of wait handles */
+            Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent,
+                                                  &ConsoleRecord->ClientEvent);
+            if (!NT_SUCCESS(Status)) goto Cleanup;
+        }
+
+        /* Return the client event handle */
+        GetNextVdmCommandRequest->WaitObjectForVDM = 
ConsoleRecord->ClientEvent;
+    }
 
 Cleanup:
     /* Leave the critical section */


Reply via email to