Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 55519)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 55531)
@@ -1065,15 +1065,15 @@
  * @param  pszArgv0         First argument (argv0), either original or modified version.  Optional.
  * @param  papszArgs        Original argv command line from the host, starting at argv[1].
+ * @param  fFlags           The process creation flags pass to us from the host.
  * @param  ppapszArgv       Pointer to a pointer with the new argv command line.
  *                          Needs to be freed with RTGetOptArgvFree.
  */
-static int gstcntlProcessAllocateArgv(const char *pszArgv0,
-                                      const char * const *papszArgs,
-                                      bool fExpandArgs, char ***ppapszArgv)
+static int gstcntlProcessAllocateArgv(const char *pszArgv0, const char * const *papszArgs, uint32_t fFlags,
+                                      char ***ppapszArgv)
 {
     AssertPtrReturn(ppapszArgv, VERR_INVALID_POINTER);
 
-    VBoxServiceVerbose(3, "GstCntlProcessPrepareArgv: pszArgv0=%p, papszArgs=%p, fExpandArgs=%RTbool, ppapszArgv=%p\n",
-                       pszArgv0, papszArgs, fExpandArgs, ppapszArgv);
+    VBoxServiceVerbose(3, "GstCntlProcessPrepareArgv: pszArgv0=%p, papszArgs=%p, fFlags=%#x, ppapszArgv=%p\n",
+                       pszArgv0, papszArgs, fFlags, ppapszArgv);
 
     int rc = VINF_SUCCESS;
@@ -1096,15 +1096,39 @@
 #endif
 
-    size_t i = 0; /* Keep the argument counter in scope for cleaning up on failure. */
-
-    rc = RTStrDupEx(&papszNewArgv[0], pszArgv0);
+
+    /* HACK ALERT! Since we still don't allow the user to really specify the first
+                   argument separately from the executable image, we have to fudge
+                   a little in the unquoted argument case to deal with executables
+                   containing spaces. */
+    /** @todo Fix the stupid host/guest protocol so the user can do this for us! */
+    if (   !(fFlags & EXECUTEPROCESSFLAG_UNQUOTED_ARGS)
+        || !strpbrk(pszArgv0, " \t\n\r")
+        || pszArgv0[0] == '"')
+        rc = RTStrDupEx(&papszNewArgv[0], pszArgv0);
+    else
+    {
+        size_t cchArgv0 = strlen(pszArgv0);
+        rc = RTStrAllocEx(&papszNewArgv[0], 1 + cchArgv0 + 1 + 1);
+        if (RT_SUCCESS(rc))
+        {
+            char *pszDst = papszNewArgv[0];
+            *pszDst++ = '"';
+            memcpy(pszDst, pszArgv0, cchArgv0);
+            pszDst += cchArgv0;
+            *pszDst++ = '"';
+            *pszDst   = '\0';
+        }
+    }
     if (RT_SUCCESS(rc))
     {
-        for (; i < cArgs; i++)
+        size_t i;
+        for (i = 0; i < cArgs; i++)
         {
             char *pszArg;
 #if 0 /* Arguments expansion -- untested. */
-            if (fExpandArgs)
-            {
+            if (fFlags & EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS)
+            {
+/** @todo r=bird: If you want this, we need a generic implementation, preferably in RTEnv or somewhere like that.  The marking
+ * up of the variables must be the same on all platforms.  */
                 /* According to MSDN the limit on older Windows version is 32K, whereas
                  * Vista+ there are no limits anymore. We still stick to 4K. */
@@ -1136,14 +1160,12 @@
 
             *ppapszArgv = papszNewArgv;
-        }
-    }
-
-    if (RT_FAILURE(rc))
-    {
-        for (i; i > 0; i--)
+            return VINF_SUCCESS;
+        }
+
+        /* Failed, bail out. */
+        for (; i > 0; i--)
             RTStrFree(papszNewArgv[i]);
-        RTMemFree(papszNewArgv);
-    }
-
+    }
+    RTMemFree(papszNewArgv);
     return rc;
 }
@@ -1239,7 +1261,4 @@
     char szExecExp[RTPATH_MAX];
 
-    /* Do we need to expand environment variables in arguments? */
-    bool fExpandArgs = (fFlags & EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS) ? true  : false;
-
 #ifdef RT_OS_WINDOWS
     /*
@@ -1295,6 +1314,5 @@
         {
             char **papszArgsExp;
-            rc = gstcntlProcessAllocateArgv(szSysprepCmd /* argv0 */, papszArgs,
-                                            fExpandArgs, &papszArgsExp);
+            rc = gstcntlProcessAllocateArgv(szSysprepCmd /* argv0 */, papszArgs, fFlags, &papszArgsExp);
             if (RT_SUCCESS(rc))
             {
@@ -1336,7 +1354,9 @@
     {
         char **papszArgsExp;
+        /** @todo r-bird: pszExec != argv[0]! When are you going to get that?!? How many
+         * times does this need to be pointed out?  HOST/GUEST INTERFACE IS MISDESIGNED! */
         rc = gstcntlProcessAllocateArgv(pszExec /* Always use the unmodified executable name as argv0. */,
                                         papszArgs /* Append the rest of the argument vector (if any). */,
-                                        fExpandArgs, &papszArgsExp);
+                                        fFlags, &papszArgsExp);
         if (RT_FAILURE(rc))
         {
@@ -1353,4 +1373,6 @@
                 if (fFlags & EXECUTEPROCESSFLAG_NO_PROFILE)
                     uProcFlags |= RTPROC_FLAGS_NO_PROFILE;
+                if (fFlags & EXECUTEPROCESSFLAG_UNQUOTED_ARGS)
+                    uProcFlags |= RTPROC_FLAGS_UNQUOTED_ARGS;
             }
 
@@ -1591,5 +1613,6 @@
                                 bool fNeedsImpersonation = !(pProcess->pSession->uFlags & VBOXSERVICECTRLSESSION_FLAG_FORK);
 
-                                rc = gstcntlProcessCreateProcess(pProcess->StartupInfo.szCmd, papszArgs, hEnv, pProcess->StartupInfo.uFlags,
+                                rc = gstcntlProcessCreateProcess(pProcess->StartupInfo.szCmd, papszArgs, hEnv,
+                                                                 pProcess->StartupInfo.uFlags,
                                                                  phStdIn, phStdOut, phStdErr,
                                                                  fNeedsImpersonation ? pProcess->StartupInfo.szUser : NULL,
