[NTVDM]: Fix (again) command-line parsing in DosCreateProcess.
[reactos.git] / reactos / subsystems / mvdm / ntvdm / dos / dem.c
index f6de163..19a37af 100644 (file)
@@ -19,6 +19,8 @@
 #include "utils.h"
 
 #include "dem.h"
+#include "dos/dos32krnl/device.h"
+#include "dos/dos32krnl/process.h"
 #include "cpu/bop.h"
 
 #include "bios/bios.h"
 
 /**/extern BYTE CurrentDrive;/**/
 
-/* DEFINES ********************************************************************/
-
-/* BOP Identifiers */
-#define BOP_LOAD_DOS    0x2B    // DOS Loading and Initializing BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
-#define BOP_START_DOS   0x2C    // DOS Starting BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
-#define BOP_DOS         0x50    // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
-#define BOP_CMD         0x54    // DOS Command Interpreter BOP (for COMMAND.COM)
-
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static VOID WINAPI DosSystemBop(LPWORD Stack)
@@ -89,6 +83,20 @@ Quit:
             break;
         }
 
+        /* Call 32-bit Driver Strategy Routine */
+        case BOP_DRV_STRATEGY:
+        {
+            DeviceStrategyBop();
+            break;
+        }
+
+        /* Call 32-bit Driver Interrupt Routine */
+        case BOP_DRV_INTERRUPT:
+        {
+            DeviceInterruptBop();
+            break;
+        }
+
         default:
         {
             DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
@@ -108,29 +116,33 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
     {
         case 0x08:  // Launch external command
         {
-#define CMDLINE_LENGTH  1024
-
             BOOL Result;
             DWORD dwExitCode;
 
             LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI());
-            LPSTR CmdPtr  = Command;
-            CHAR CommandLine[CMDLINE_LENGTH] = "";
+            CHAR CmdLine[sizeof("cmd.exe /c ") + DOS_CMDLINE_LENGTH + 1] = "";
+            LPSTR CmdLinePtr;
+            ULONG CmdLineLen;
             STARTUPINFOA StartupInfo;
             PROCESS_INFORMATION ProcessInformation;
 
-            /* NULL-terminate the command line by removing the return carriage character */
-            while (*CmdPtr && *CmdPtr != '\r') CmdPtr++;
-            *CmdPtr = '\0';
-
-            DPRINT1("CMD Run Command '%s'\n", Command);
-
             /* Spawn a user-defined 32-bit command preprocessor */
 
-            /* Build the command line */
             // FIXME: Use COMSPEC env var!!
-            strcpy(CommandLine, "cmd.exe /c ");
-            strcat(CommandLine, Command);
+            CmdLinePtr = CmdLine;
+            strcpy(CmdLinePtr, "cmd.exe /c ");
+            CmdLinePtr += strlen(CmdLinePtr);
+
+            /* Build a Win32-compatible command-line */
+            CmdLineLen = min(strlen(Command), sizeof(CmdLine) - strlen(CmdLinePtr) - 1);
+            RtlCopyMemory(CmdLinePtr, Command, CmdLineLen);
+            CmdLinePtr[CmdLineLen] = '\0';
+
+            /* Remove any trailing return carriage character and NULL-terminate the command line */
+            while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr != '\n') CmdLinePtr++;
+            *CmdLinePtr = '\0';
+
+            DPRINT1("CMD Run Command '%s' ('%s')\n", Command, CmdLine);
 
             RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
             RtlZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
@@ -140,7 +152,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
             VidBiosDetachFromConsole();
 
             Result = CreateProcessA(NULL,
-                                    CommandLine,
+                                    CmdLine,
                                     NULL,
                                     NULL,
                                     TRUE,
@@ -151,7 +163,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
                                     &ProcessInformation);
             if (Result)
             {
-                DPRINT1("Command '%s' launched successfully\n", Command);
+                DPRINT1("Command '%s' ('%s') launched successfully\n", Command, CmdLine);
 
                 /* Wait for process termination */
                 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
@@ -165,7 +177,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
             }
             else
             {
-                DPRINT1("Failed when launched command '%s'\n");
+                DPRINT1("Failed when launched command '%s' ('%s')\n", Command, CmdLine);
                 dwExitCode = GetLastError();
             }
 
@@ -202,7 +214,7 @@ CommandThreadProc(LPVOID Parameter)
     PVOID Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
 
     UNREFERENCED_PARAMETER(Parameter);
-    ASSERT(Env != NULL);
+    ASSERT(Env);
 
     do
     {
@@ -237,6 +249,7 @@ Command:
                 CommandInfo.Env = Env = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
 
                 /* Repeat the request */
+                CommandInfo.VDMState |= VDM_FLAG_RETRY;
                 goto Command;
             }
 
@@ -244,7 +257,6 @@ Command:
         }
 
         /* Start the process from the command line */
-        DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
         Result = DosStartProcess(AppName, CmdLine, Env);
         if (Result != ERROR_SUCCESS)
         {
@@ -262,6 +274,14 @@ Command:
 }
 #endif
 
+/* PUBLIC VARIABLES ***********************************************************/
+
+#ifndef STANDALONE
+BOOLEAN AcceptCommands = TRUE;
+HANDLE CommandThread = NULL;
+ULONG SessionId = 0;
+#endif
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 //
@@ -410,6 +430,8 @@ static VOID WINAPI DosStart(LPWORD Stack)
     DWORD Result;
     CHAR ApplicationName[MAX_PATH];
     CHAR CommandLine[DOS_CMDLINE_LENGTH];
+#else
+    INT i;
 #endif
 
     DPRINT("DosStart\n");
@@ -425,6 +447,19 @@ static VOID WINAPI DosStart(LPWORD Stack)
 
 #ifndef STANDALONE
 
+    /* Parse the command line arguments */
+    for (i = 1; i < NtVdmArgc; i++)
+    {
+        if (wcsncmp(NtVdmArgv[i], L"-i", 2) == 0)
+        {
+            /* This is the session ID */
+            SessionId = wcstoul(NtVdmArgv[i] + 2, NULL, 10);
+
+            /* The VDM hasn't been started from a console, so quit when the task is done */
+            AcceptCommands = FALSE;
+        }
+    }
+
     /* Create the GetNextVDMCommand thread */
     CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
     if (CommandThread == NULL)
@@ -457,9 +492,7 @@ static VOID WINAPI DosStart(LPWORD Stack)
     }
 
     /* Start the process from the command line */
-    DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
-    Result = DosStartProcess(ApplicationName,
-                             CommandLine,
+    Result = DosStartProcess(ApplicationName, CommandLine,
                              SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0));
     if (Result != ERROR_SUCCESS)
     {