[NTVDM]: Fix (again) command-line parsing in DosCreateProcess.
[reactos.git] / reactos / subsystems / mvdm / ntvdm / dos / dem.c
index a1adf9e..19a37af 100644 (file)
@@ -116,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));
@@ -148,7 +152,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
             VidBiosDetachFromConsole();
 
             Result = CreateProcessA(NULL,
-                                    CommandLine,
+                                    CmdLine,
                                     NULL,
                                     NULL,
                                     TRUE,
@@ -159,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);
@@ -173,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();
             }
 
@@ -210,7 +214,7 @@ CommandThreadProc(LPVOID Parameter)
     PVOID Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
 
     UNREFERENCED_PARAMETER(Parameter);
-    ASSERT(Env != NULL);
+    ASSERT(Env);
 
     do
     {
@@ -253,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)
         {
@@ -271,6 +274,14 @@ Command:
 }
 #endif
 
+/* PUBLIC VARIABLES ***********************************************************/
+
+#ifndef STANDALONE
+BOOLEAN AcceptCommands = TRUE;
+HANDLE CommandThread = NULL;
+ULONG SessionId = 0;
+#endif
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 //
@@ -419,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");
@@ -434,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)
@@ -466,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)
     {