Index: trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp	(revision 84214)
+++ trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp	(revision 84215)
@@ -36,4 +36,5 @@
 #include <VBox/err.h>
 #include <VBox/log.h>
+#include <VBox/GuestHost/GuestControl.h>
 #include <VBox/HostServices/GuestControlSvc.h>
 
@@ -718,25 +719,160 @@
 }
 
+/**
+ * Initializes a session startup info, extended version.
+ *
+ * @returns VBox status code.
+ * @param   pStartupInfo        Session startup info to initializes.
+ * @param   cbUser              Size (in bytes) to use for the user name buffer.
+ * @param   cbPassword          Size (in bytes) to use for the password buffer.
+ * @param   cbDomain            Size (in bytes) to use for the domain name buffer.
+ */
+VBGLR3DECL(int)  VbglR3GuestCtrlSessionStartupInfoInitEx(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo,
+                                                         size_t cbUser, size_t cbPassword, size_t cbDomain)
+{
+    AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
+
+    RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
+
+#define ALLOC_STR(a_Str, a_cb) \
+    if ((a_cb) > 0) \
+    { \
+        pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
+        AssertPtrBreak(pStartupInfo->psz##a_Str); \
+        pStartupInfo->cb##a_Str  = (uint32_t)a_cb; \
+    }
+
+    do
+    {
+        ALLOC_STR(User,     cbUser);
+        ALLOC_STR(Password, cbPassword);
+        ALLOC_STR(Domain,   cbDomain);
+
+        return VINF_SUCCESS;
+
+    } while (0);
+
+#undef ALLOC_STR
+
+    VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
+    return VERR_NO_MEMORY;
+}
+
+/**
+ * Initializes a session startup info.
+ *
+ * @returns VBox status code.
+ * @param   pStartupInfo        Session startup info to initializes.
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInit(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
+{
+    return VbglR3GuestCtrlSessionStartupInfoInitEx(pStartupInfo,
+                                                   GUESTPROCESS_MAX_USER_LEN, GUESTPROCESS_MAX_PASSWORD_LEN,
+                                                   GUESTPROCESS_MAX_DOMAIN_LEN);
+}
+
+/**
+ * Destroys a session startup info.
+ *
+ * @param   pStartupInfo        Session startup info to destroy.
+ */
+VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoDestroy(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
+{
+    if (!pStartupInfo)
+        return;
+
+    RTStrFree(pStartupInfo->pszUser);
+    RTStrFree(pStartupInfo->pszPassword);
+    RTStrFree(pStartupInfo->pszDomain);
+
+    RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
+}
+
+/**
+ * Free's a session startup info.
+ *
+ * @param   pStartupInfo        Session startup info to free.
+ *                              The pointer will not be valid anymore after return.
+ */
+VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoFree(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
+{
+    if (!pStartupInfo)
+        return;
+
+    VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
+
+    RTMemFree(pStartupInfo);
+    pStartupInfo = NULL;
+}
+
+/**
+ * Duplicates a session startup info.
+ *
+ * @returns Duplicated session startup info on success, or NULL on error.
+ * @param   pStartupInfo        Session startup info to duplicate.
+ */
+VBGLR3DECL(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO) VbglR3GuestCtrlSessionStartupInfoDup(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
+{
+    AssertPtrReturn(pStartupInfo, NULL);
+
+    PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)
+                                                                RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
+    if (pStartupInfoDup)
+    {
+        do
+        {
+            pStartupInfoDup->pszUser     = NULL;
+            pStartupInfoDup->pszPassword = NULL;
+            pStartupInfoDup->pszDomain   = NULL;
+
+#define DUP_STR(a_Str) \
+    if (pStartupInfo->cb##a_Str) \
+    { \
+        pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
+        AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
+        pStartupInfoDup->cb##a_Str  = strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
+    }
+            DUP_STR(User);
+            DUP_STR(Password);
+            DUP_STR(Domain);
+
+#undef DUP_STR
+
+            return pStartupInfoDup;
+
+        } while (0); /* To use break macros above. */
+
+        VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfoDup);
+    }
+
+    return NULL;
+}
 
 /**
  * Retrieves a HOST_SESSION_CREATE message.
- */
-VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
-                                              uint32_t *puProtocol,
-                                              char     *pszUser,     uint32_t  cbUser,
-                                              char     *pszPassword, uint32_t  cbPassword,
-                                              char     *pszDomain,   uint32_t  cbDomain,
-                                              uint32_t *pfFlags,     uint32_t *pidSession)
+ *
+ * @returns VBox status code.
+ * @param   pCtx                Guest control command context to use.
+ * @param   ppStartupInfo       Where to store the allocated session startup info.
+ *                              Needs to be free'd by VbglR3GuestCtrlSessionStartupInfoFree().
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLSESSIONSTARTUPINFO *ppStartupInfo)
 {
     AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     AssertReturn(pCtx->uNumParms == 6, VERR_INVALID_PARAMETER);
-
-    AssertPtrReturn(puProtocol, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszPassword, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszDomain, VERR_INVALID_POINTER);
-    AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
-
-    int rc;
+    AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
+
+    PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo
+        = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
+    if (!pStartupInfo)
+        return VERR_NO_MEMORY;
+
+    int rc = VbglR3GuestCtrlSessionStartupInfoInit(pStartupInfo);
+    if (RT_FAILURE(rc))
+    {
+        VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
+        return rc;
+    }
+
     do
     {
@@ -745,7 +881,7 @@
         VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CREATE);
         VbglHGCMParmUInt32Set(&Msg.protocol, 0);
-        VbglHGCMParmPtrSet(&Msg.username, pszUser, cbUser);
-        VbglHGCMParmPtrSet(&Msg.password, pszPassword, cbPassword);
-        VbglHGCMParmPtrSet(&Msg.domain, pszDomain, cbDomain);
+        VbglHGCMParmPtrSet(&Msg.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
+        VbglHGCMParmPtrSet(&Msg.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
+        VbglHGCMParmPtrSet(&Msg.domain, pStartupInfo->pszDomain, pStartupInfo->cbDomain);
         VbglHGCMParmUInt32Set(&Msg.flags, 0);
 
@@ -754,12 +890,20 @@
         {
             Msg.context.GetUInt32(&pCtx->uContextID);
-            Msg.protocol.GetUInt32(puProtocol);
-            Msg.flags.GetUInt32(pfFlags);
-
-            if (pidSession)
-                *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
+            Msg.protocol.GetUInt32(&pStartupInfo->uProtocol);
+            Msg.flags.GetUInt32(&pStartupInfo->fFlags);
+
+            pStartupInfo->uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
         }
 
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
+
+    if (RT_SUCCESS(rc))
+    {
+        *ppStartupInfo = pStartupInfo;
+    }
+    else
+        VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
+
+    LogFlowFuncLeaveRC(rc);
     return rc;
 }
@@ -882,33 +1026,196 @@
 }
 
+/**
+ * Initializes a process startup info, extended version.
+ *
+ * @returns VBox status code.
+ * @param   pStartupInfo        Process startup info to initializes.
+ * @param   cbCmd               Size (in bytes) to use for the command buffer.
+ * @param   cbUser              Size (in bytes) to use for the user name buffer.
+ * @param   cbPassword          Size (in bytes) to use for the password buffer.
+ * @param   cbDomain            Size (in bytes) to use for the domain buffer.
+ * @param   cbArgs              Size (in bytes) to use for the arguments buffer.
+ * @param   cbEnv               Size (in bytes) to use for the environment buffer.
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
+                                                     size_t cbCmd,
+                                                     size_t cbUser, size_t cbPassword, size_t cbDomain,
+                                                     size_t cbArgs, size_t cbEnv)
+{
+    AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
+    AssertReturn(cbCmd,           VERR_INVALID_PARAMETER);
+    AssertReturn(cbUser,          VERR_INVALID_PARAMETER);
+    AssertReturn(cbPassword,      VERR_INVALID_PARAMETER);
+    AssertReturn(cbDomain,        VERR_INVALID_PARAMETER);
+    AssertReturn(cbArgs,          VERR_INVALID_PARAMETER);
+    AssertReturn(cbEnv,           VERR_INVALID_PARAMETER);
+
+    RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
+
+#define ALLOC_STR(a_Str, a_cb) \
+    if ((a_cb) > 0) \
+    { \
+        pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
+        AssertPtrBreak(pStartupInfo->psz##a_Str); \
+        pStartupInfo->cb##a_Str  = (uint32_t)a_cb; \
+    }
+
+    do
+    {
+        ALLOC_STR(Cmd,      cbCmd);
+        ALLOC_STR(Args,     cbArgs);
+        ALLOC_STR(Env,      cbEnv);
+        ALLOC_STR(User,     cbUser);
+        ALLOC_STR(Password, cbPassword);
+        ALLOC_STR(Domain,   cbDomain);
+
+        return VINF_SUCCESS;
+
+    } while (0);
+
+#undef ALLOC_STR
+
+    VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
+    return VERR_NO_MEMORY;
+}
+
+/**
+ * Initializes a process startup info with default values.
+ *
+ * @param   pStartupInfo        Process startup info to initializes.
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
+{
+    return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
+                                                GUESTPROCESS_MAX_CMD_LEN,
+                                                GUESTPROCESS_MAX_USER_LEN,  GUESTPROCESS_MAX_PASSWORD_LEN,
+                                                GUESTPROCESS_MAX_DOMAIN_LEN,
+                                                GUESTPROCESS_MAX_ARGS_LEN, GUESTPROCESS_MAX_ENV_LEN);
+}
+
+/**
+ * Destroys a process startup info.
+ *
+ * @param   pStartupInfo        Process startup info to destroy.
+ */
+VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
+{
+    if (!pStartupInfo)
+        return;
+
+    RTStrFree(pStartupInfo->pszCmd);
+    RTStrFree(pStartupInfo->pszArgs);
+    RTStrFree(pStartupInfo->pszEnv);
+    RTStrFree(pStartupInfo->pszUser);
+    RTStrFree(pStartupInfo->pszPassword);
+    RTStrFree(pStartupInfo->pszDomain);
+
+    RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
+}
+
+/**
+ * Free's a process startup info.
+ *
+ * @param   pStartupInfo        Process startup info to free.
+ *                              The pointer will not be valid anymore after return.
+ */
+VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
+{
+    if (!pStartupInfo)
+        return;
+
+    VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
+
+    RTMemFree(pStartupInfo);
+    pStartupInfo = NULL;
+}
+
+/**
+ * Duplicates a process startup info.
+ *
+ * @returns Duplicated process startup info on success, or NULL on error.
+ * @param   pStartupInfo        Process startup info to duplicate.
+ */
+VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
+{
+    AssertPtrReturn(pStartupInfo, NULL);
+
+    PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)
+                                                            RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
+    if (pStartupInfoDup)
+    {
+        do
+        {
+            pStartupInfoDup->pszCmd      = NULL;
+            pStartupInfoDup->pszArgs     = NULL;
+            pStartupInfoDup->pszEnv      = NULL;
+            pStartupInfoDup->pszUser     = NULL;
+            pStartupInfoDup->pszPassword = NULL;
+            pStartupInfoDup->pszDomain   = NULL;
+
+#define DUP_STR(a_Str) \
+    if (pStartupInfo->cb##a_Str) \
+    { \
+        pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
+        AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
+        pStartupInfoDup->cb##a_Str  = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
+    }
+
+#define DUP_MEM(a_Str) \
+    if (pStartupInfo->cb##a_Str) \
+    { \
+        pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
+        AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
+        pStartupInfoDup->cb##a_Str  = (uint32_t)pStartupInfo->cb##a_Str; \
+    }
+
+            DUP_STR(Cmd);
+            DUP_MEM(Args);
+            DUP_MEM(Env);
+            DUP_STR(User);
+            DUP_STR(Password);
+            DUP_STR(Domain);
+
+#undef DUP_STR
+#undef DUP_MEM
+
+            return pStartupInfoDup;
+
+        } while (0); /* To use break macros above. */
+
+        VbglR3GuestCtrlProcStartupInfoFree(pStartupInfoDup);
+    }
+
+    return NULL;
+}
 
 /**
  * Retrieves a HOST_EXEC_CMD message.
  *
- * @todo Move the parameters in an own struct!
- */
-VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX    pCtx,
-                                            char     *pszCmd,         uint32_t  cbCmd,
-                                            uint32_t *pfFlags,
-                                            char     *pszArgs,        uint32_t  cbArgs,     uint32_t *pcArgs,
-                                            char     *pszEnv,         uint32_t *pcbEnv,     uint32_t *pcEnvVars,
-                                            char     *pszUser,        uint32_t  cbUser,
-                                            char     *pszPassword,    uint32_t  cbPassword,
-                                            uint32_t *puTimeoutMS,
-                                            uint32_t *puPriority,
-                                            uint64_t *puAffinity,     uint32_t  cbAffinity, uint32_t *pcAffinity)
-{
-    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
-
-    AssertPtrReturn(pszCmd, VERR_INVALID_POINTER);
-    AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszArgs, VERR_INVALID_POINTER);
-    AssertPtrReturn(pcArgs, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszEnv, VERR_INVALID_POINTER);
-    AssertPtrReturn(pcbEnv, VERR_INVALID_POINTER);
-    AssertPtrReturn(pcEnvVars, VERR_INVALID_POINTER);
-    AssertPtrReturn(puTimeoutMS, VERR_INVALID_POINTER);
-
-    int rc;
+ * @returns VBox status code.
+ * @param   pCtx                Guest control command context to use.
+ * @param   ppStartupInfo       Where to store the allocated session startup info.
+ *                              Needs to be free'd by VbglR3GuestCtrlProcStartupInfoFree().
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo)
+{
+    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
+    AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
+
+    PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo
+        = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
+    if (!pStartupInfo)
+        return VERR_NO_MEMORY;
+
+    int rc = VbglR3GuestCtrlProcStartupInfoInit(pStartupInfo);
+    if (RT_FAILURE(rc))
+    {
+        VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
+        return rc;
+    }
+
+    unsigned cRetries = 0;
+    unsigned cGrowthFactor = 2;
+
     do
     {
@@ -916,54 +1223,75 @@
         VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
         VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_CMD);
-        VbglHGCMParmPtrSet(&Msg.cmd, pszCmd, cbCmd);
+        VbglHGCMParmPtrSet(&Msg.cmd, pStartupInfo->pszCmd, pStartupInfo->cbCmd);
         VbglHGCMParmUInt32Set(&Msg.flags, 0);
         VbglHGCMParmUInt32Set(&Msg.num_args, 0);
-        VbglHGCMParmPtrSet(&Msg.args, pszArgs, cbArgs);
+        VbglHGCMParmPtrSet(&Msg.args, pStartupInfo->pszArgs, pStartupInfo->cbArgs);
         VbglHGCMParmUInt32Set(&Msg.num_env, 0);
         VbglHGCMParmUInt32Set(&Msg.cb_env, 0);
-        VbglHGCMParmPtrSet(&Msg.env, pszEnv, *pcbEnv);
+        VbglHGCMParmPtrSet(&Msg.env, pStartupInfo->pszEnv, pStartupInfo->cbEnv);
         if (pCtx->uProtocol < 2)
         {
-            AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
-            AssertReturn(cbUser, VERR_INVALID_PARAMETER);
-            AssertPtrReturn(pszPassword, VERR_INVALID_POINTER);
-            AssertReturn(pszPassword, VERR_INVALID_PARAMETER);
-
-            VbglHGCMParmPtrSet(&Msg.u.v1.username, pszUser, cbUser);
-            VbglHGCMParmPtrSet(&Msg.u.v1.password, pszPassword, cbPassword);
+            VbglHGCMParmPtrSet(&Msg.u.v1.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
+            VbglHGCMParmPtrSet(&Msg.u.v1.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
             VbglHGCMParmUInt32Set(&Msg.u.v1.timeout, 0);
         }
         else
         {
-            AssertPtrReturn(puAffinity, VERR_INVALID_POINTER);
-            AssertReturn(cbAffinity, VERR_INVALID_PARAMETER);
-
             VbglHGCMParmUInt32Set(&Msg.u.v2.timeout, 0);
             VbglHGCMParmUInt32Set(&Msg.u.v2.priority, 0);
             VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
-            VbglHGCMParmPtrSet(&Msg.u.v2.affinity, puAffinity, cbAffinity);
+            VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
         }
 
         rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
-        if (RT_SUCCESS(rc))
+        if (RT_FAILURE(rc))
+        {
+            if (   rc == VERR_BUFFER_OVERFLOW
+                && cRetries++ < 4)
+            {
+#define GROW_STR(a_Str, a_cbMax) \
+        pStartupInfo->psz##a_Str = (char *)RTMemRealloc(pStartupInfo->psz##a_Str, \
+           RT_MAX(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax)); \
+        AssertPtrBreakStmt(pStartupInfo->psz##a_Str, VERR_NO_MEMORY); \
+        pStartupInfo->cb##a_Str  = RT_MAX(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax);
+
+                GROW_STR(Cmd , GUESTPROCESS_MAX_CMD_LEN);
+                GROW_STR(Args, GUESTPROCESS_MAX_ARGS_LEN);
+                GROW_STR(Env,  GUESTPROCESS_MAX_ENV_LEN);
+
+#undef GROW_STR
+                cGrowthFactor *= cGrowthFactor;
+            }
+            else
+                break;
+        }
+        else
         {
             Msg.context.GetUInt32(&pCtx->uContextID);
-            Msg.flags.GetUInt32(pfFlags);
-            Msg.num_args.GetUInt32(pcArgs);
-            Msg.num_env.GetUInt32(pcEnvVars);
-            Msg.cb_env.GetUInt32(pcbEnv);
+            Msg.flags.GetUInt32(&pStartupInfo->fFlags);
+            Msg.num_args.GetUInt32(&pStartupInfo->cArgs);
+            Msg.num_env.GetUInt32(&pStartupInfo->cEnvVars);
+            Msg.cb_env.GetUInt32(&pStartupInfo->cbEnv);
             if (pCtx->uProtocol < 2)
-                Msg.u.v1.timeout.GetUInt32(puTimeoutMS);
+                Msg.u.v1.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
             else
             {
-                Msg.u.v2.timeout.GetUInt32(puTimeoutMS);
-                Msg.u.v2.priority.GetUInt32(puPriority);
-                Msg.u.v2.num_affinity.GetUInt32(pcAffinity);
+                Msg.u.v2.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
+                Msg.u.v2.priority.GetUInt32(&pStartupInfo->uPriority);
+                Msg.u.v2.num_affinity.GetUInt32(&pStartupInfo->cAffinity);
             }
         }
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
-    return rc;
-}
-
+
+    if (RT_SUCCESS(rc))
+    {
+        *ppStartupInfo = pStartupInfo;
+    }
+    else
+        VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
 
 /**
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 84214)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 84215)
@@ -415,15 +415,6 @@
      * Retrieve the message parameters.
      */
-    VBOXSERVICECTRLSESSIONSTARTUPINFO startupInfo;
-    int rc = VgsvcGstCtrlSessionStartupInfoInit(&startupInfo);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = VbglR3GuestCtrlSessionGetOpen(pHostCtx,
-                                       &startupInfo.uProtocol,
-                                       startupInfo.pszUser,     startupInfo.cbUser,
-                                       startupInfo.pszPassword, startupInfo.cbPassword,
-                                       startupInfo.pszDomain,   startupInfo.cbDomain,
-                                       &startupInfo.fFlags,    &startupInfo.uSessionID);
+    PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo;
+    int rc = VbglR3GuestCtrlSessionGetOpen(pHostCtx, &pStartupInfo);
     if (RT_SUCCESS(rc))
     {
@@ -431,16 +422,16 @@
          * Flat out refuse to work with protocol v1 hosts.
          */
-        if (startupInfo.uProtocol == 2)
-        {
-            pHostCtx->uProtocol = startupInfo.uProtocol;
+        if (pStartupInfo->uProtocol == 2)
+        {
+            pHostCtx->uProtocol = pStartupInfo->uProtocol;
             VGSvcVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n", pHostCtx->uClientID, pHostCtx->uProtocol);
 
 /** @todo Someone explain why this code isn't in this file too?  v1 support? */
-            rc = VGSvcGstCtrlSessionThreadCreate(&g_lstControlSessionThreads, &startupInfo, NULL /* ppSessionThread */);
+            rc = VGSvcGstCtrlSessionThreadCreate(&g_lstControlSessionThreads, pStartupInfo, NULL /* ppSessionThread */);
             /* Report failures to the host (successes are taken care of by the session thread). */
         }
         else
         {
-            VGSvcError("The host wants to use protocol v%u, we only support v2!\n", startupInfo.uProtocol);
+            VGSvcError("The host wants to use protocol v%u, we only support v2!\n", pStartupInfo->uProtocol);
             rc = VERR_VERSION_MISMATCH;
         }
@@ -458,5 +449,6 @@
     }
 
-    VgsvcGstCtrlSessionStartupInfoDestroy(&startupInfo);
+    VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
+    pStartupInfo = NULL;
 
     VGSvcVerbose(3, "Opening a new guest session returned rc=%Rrc\n", rc);
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h	(revision 84214)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h	(revision 84215)
@@ -74,29 +74,4 @@
 typedef VBOXSERVICECTRLFILE *PVBOXSERVICECTRLFILE;
 
-typedef struct VBOXSERVICECTRLSESSIONSTARTUPINFO
-{
-    /** The session's protocol version to use. */
-    uint32_t                        uProtocol;
-    /** The session's ID. */
-    uint32_t                        uSessionID;
-    /** User name (account) to start the guest session under. */
-    char                           *pszUser;
-    /** Size (in bytes) of allocated pszUser. */
-    uint32_t                        cbUser;
-    /** Password of specified user name (account). */
-    char                           *pszPassword;
-    /** Size (in bytes) of allocated pszPassword. */
-    uint32_t                        cbPassword;
-    /** Domain of the user account. */
-    char                           *pszDomain;
-    /** Size (in bytes) of allocated pszDomain. */
-    uint32_t                        cbDomain;
-    /** Session creation flags.
-     *  @sa VBOXSERVICECTRLSESSIONSTARTUPFLAG_* flags. */
-    uint32_t                        fFlags;
-} VBOXSERVICECTRLSESSIONSTARTUPINFO;
-/** Pointer to thread data. */
-typedef VBOXSERVICECTRLSESSIONSTARTUPINFO *PVBOXSERVICECTRLSESSIONSTARTUPINFO;
-
 /**
  * Structure for a guest session thread to
@@ -110,5 +85,5 @@
     RTLISTNODE                      Node;
     /** The sessions's startup info. */
-    PVBOXSERVICECTRLSESSIONSTARTUPINFO
+    PVBGLR3GUESTCTRLSESSIONSTARTUPINFO
                                     pStartupInfo;
     /** Critical section for thread-safe use. */
@@ -185,5 +160,5 @@
 {
     /* The session's startup information. */
-    VBOXSERVICECTRLSESSIONSTARTUPINFO
+    VBGLR3GUESTCTRLSESSIONSTARTUPINFO
                                     StartupInfo;
     /** List of active guest process threads
@@ -207,55 +182,4 @@
 /** Pointer to guest session. */
 typedef VBOXSERVICECTRLSESSION *PVBOXSERVICECTRLSESSION;
-
-/**
- * Structure holding information for starting a guest
- * process.
- */
-typedef struct VBOXSERVICECTRLPROCSTARTUPINFO
-{
-    /** Full qualified path of process to start (without arguments).
-     *  Note: This is *not* argv[0]! */
-    char *pszCmd;
-    /** Size (in bytes) of allocated pszCmd. */
-    uint32_t cbCmd;
-    /** Process execution flags. @sa */
-    uint32_t fFlags;
-    /** Command line arguments. */
-    char *pszArgs;
-    /** Size (in bytes) of allocated pszArgs. */
-    uint32_t cbArgs;
-    /** Number of arguments specified in pszArgs. */
-    uint32_t cArgs;
-    /** String of environment variables ("FOO=BAR") to pass to the process
-      * to start. */
-    char *pszEnv;
-    /** Size (in bytes) of environment variables block. */
-    uint32_t cbEnv;
-    /** Number of environment variables specified in pszEnv. */
-    uint32_t cEnvVars;
-    /** User name (account) to start the process under. */
-    char *pszUser;
-    /** Size (in bytes) of allocated pszUser. */
-    uint32_t cbUser;
-    /** Password of specified user name (account). */
-    char *pszPassword;
-    /** Size (in bytes) of allocated pszPassword. */
-    uint32_t cbPassword;
-    /** Domain to be used for authenticating the specified user name (account). */
-    char *pszDomain;
-    /** Size (in bytes) of allocated pszDomain. */
-    uint32_t cbDomain;
-    /** Time limit (in ms) of the process' life time. */
-    uint32_t uTimeLimitMS;
-    /** Process priority. */
-    uint32_t uPriority;
-    /** Process affinity. At the moment we support
-     *  up to 4 * 64 = 256 CPUs. */
-    uint64_t uAffinity[4];
-    /** Number of used process affinity blocks. */
-    uint32_t uNumAffinity;
-} VBOXSERVICECTRLPROCSTARTUPINFO;
-/** Pointer to a guest process block. */
-typedef VBOXSERVICECTRLPROCSTARTUPINFO *PVBOXSERVICECTRLPROCSTARTUPINFO;
 
 /**
@@ -287,5 +211,5 @@
     RTCRITSECT                      CritSect;
     /** Process startup information. */
-    PVBOXSERVICECTRLPROCSTARTUPINFO
+    PVBGLR3GUESTCTRLPROCSTARTUPINFO
                                     pStartupInfo;
     /** The process' PID assigned by the guest OS. */
@@ -328,5 +252,5 @@
 /** @name Guest session thread handling.
  * @{ */
-extern int                      VGSvcGstCtrlSessionThreadCreate(PRTLISTANCHOR pList, const PVBOXSERVICECTRLSESSIONSTARTUPINFO pSessionStartupInfo, PVBOXSERVICECTRLSESSIONTHREAD *ppSessionThread);
+extern int                      VGSvcGstCtrlSessionThreadCreate(PRTLISTANCHOR pList, const PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pSessionStartupInfo, PVBOXSERVICECTRLSESSIONTHREAD *ppSessionThread);
 extern int                      VGSvcGstCtrlSessionThreadDestroy(PVBOXSERVICECTRLSESSIONTHREAD pSession, uint32_t uFlags);
 extern int                      VGSvcGstCtrlSessionThreadDestroyAll(PRTLISTANCHOR pList, uint32_t uFlags);
@@ -336,8 +260,4 @@
 /** @name Per-session functions.
  * @{ */
-extern int                      VgsvcGstCtrlSessionStartupInfoInit(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo);
-extern int                      VgsvcGstCtrlSessionStartupInfoInitEx(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo, size_t cbUser, size_t cbPassword, size_t cbDomain);
-extern void                     VgsvcGstCtrlSessionStartupInfoDestroy(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo);
-
 extern PVBOXSERVICECTRLPROCESS  VGSvcGstCtrlSessionRetainProcess(PVBOXSERVICECTRLSESSION pSession, uint32_t uPID);
 extern int                      VGSvcGstCtrlSessionClose(PVBOXSERVICECTRLSESSION pSession);
@@ -352,9 +272,4 @@
 /** @name Per-guest process functions.
  * @{ */
-extern int                      VgsvcGstCtrlProcessStartupInfoInit(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo);
-extern int                      VgsvcGstCtrlProcessStartupInfoInitEx(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo, size_t cbCmd, size_t cbUser, size_t cbPassword, size_t cbDomain, size_t cbArgs, size_t cbEnv);
-extern void                     VgsvcGstCtrlProcessStartupInfoDestroy(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo);
-extern void                     VgsvcGstCtrlProcessStartupInfoFree(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo);
-
 extern int                      VGSvcGstCtrlProcessFree(PVBOXSERVICECTRLPROCESS pProcess);
 extern int                      VGSvcGstCtrlProcessHandleInput(PVBOXSERVICECTRLPROCESS pProcess, PVBGLR3GUESTCTRLCMDCTX pHostCtx, bool fPendingClose, void *pvBuf, uint32_t cbBuf);
@@ -362,5 +277,5 @@
 extern int                      VGSvcGstCtrlProcessHandleTerm(PVBOXSERVICECTRLPROCESS pProcess);
 extern void                     VGSvcGstCtrlProcessRelease(PVBOXSERVICECTRLPROCESS pProcess);
-extern int                      VGSvcGstCtrlProcessStart(const PVBOXSERVICECTRLSESSION pSession, const PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo, uint32_t uContext);
+extern int                      VGSvcGstCtrlProcessStart(const PVBOXSERVICECTRLSESSION pSession, const PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo, uint32_t uContext);
 extern int                      VGSvcGstCtrlProcessStop(PVBOXSERVICECTRLPROCESS pProcess);
 extern int                      VGSvcGstCtrlProcessWait(const PVBOXSERVICECTRLPROCESS pProcess, RTMSINTERVAL msTimeout, int *pRc);
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 84214)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 84215)
@@ -61,167 +61,4 @@
 
 
-/**
- * Initializes a process startup info, extended version.
- *
- * @returns VBox status code.
- * @param   pStartupInfo        Process startup info to initializes.
- * @param   cbCmd               Size (in bytes) to use for the command buffer.
- * @param   cbUser              Size (in bytes) to use for the user name buffer.
- * @param   cbPassword          Size (in bytes) to use for the password buffer.
- * @param   cbDomain            Size (in bytes) to use for the domain buffer.
- * @param   cbArgs              Size (in bytes) to use for the arguments buffer.
- * @param   cbEnv               Size (in bytes) to use for the environment buffer.
- */
-int VgsvcGstCtrlProcessStartupInfoInitEx(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo,
-                                         size_t cbCmd,
-                                         size_t cbUser, size_t cbPassword, size_t cbDomain,
-                                         size_t cbArgs, size_t cbEnv)
-{
-    AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
-    AssertReturn(cbCmd,           VERR_INVALID_PARAMETER);
-    AssertReturn(cbUser,          VERR_INVALID_PARAMETER);
-    AssertReturn(cbPassword,      VERR_INVALID_PARAMETER);
-    AssertReturn(cbDomain,        VERR_INVALID_PARAMETER);
-    AssertReturn(cbArgs,          VERR_INVALID_PARAMETER);
-    AssertReturn(cbEnv,           VERR_INVALID_PARAMETER);
-
-    RT_BZERO(pStartupInfo, sizeof(VBOXSERVICECTRLPROCSTARTUPINFO));
-
-#define ALLOC_STR(a_Str, a_cb) \
-    if ((a_cb) > 0) \
-    { \
-        pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
-        AssertPtrBreak(pStartupInfo->psz##a_Str); \
-        pStartupInfo->cb##a_Str  = (uint32_t)a_cb; \
-    }
-
-    do
-    {
-        ALLOC_STR(Cmd,      cbCmd);
-        ALLOC_STR(Args,     cbArgs);
-        ALLOC_STR(Env,      cbEnv);
-        ALLOC_STR(User,     cbUser);
-        ALLOC_STR(Password, cbPassword);
-        ALLOC_STR(Domain,   cbDomain);
-
-        return VINF_SUCCESS;
-
-    } while (0);
-
-#undef ALLOC_STR
-
-    VgsvcGstCtrlProcessStartupInfoDestroy(pStartupInfo);
-    return VERR_NO_MEMORY;
-}
-
-/**
- * Initializes a process startup info with default values.
- *
- * @param   pStartupInfo        Process startup info to initializes.
- */
-int VgsvcGstCtrlProcessStartupInfoInit(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo)
-{
-    return VgsvcGstCtrlProcessStartupInfoInitEx(pStartupInfo,
-                                                GUESTPROCESS_MAX_CMD_LEN,
-                                                GUESTPROCESS_MAX_USER_LEN,  GUESTPROCESS_MAX_PASSWORD_LEN,
-                                                GUESTPROCESS_MAX_DOMAIN_LEN,
-                                                GUESTPROCESS_MAX_ARGS_LEN, GUESTPROCESS_MAX_ENV_LEN);
-}
-
-/**
- * Destroys a process startup info.
- *
- * @param   pStartupInfo        Process startup info to destroy.
- */
-void VgsvcGstCtrlProcessStartupInfoDestroy(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo)
-{
-    if (!pStartupInfo)
-        return;
-
-    RTStrFree(pStartupInfo->pszCmd);
-    RTStrFree(pStartupInfo->pszArgs);
-    RTStrFree(pStartupInfo->pszEnv);
-    RTStrFree(pStartupInfo->pszUser);
-    RTStrFree(pStartupInfo->pszPassword);
-    RTStrFree(pStartupInfo->pszDomain);
-
-    RT_BZERO(pStartupInfo, sizeof(VBOXSERVICECTRLPROCSTARTUPINFO));
-}
-
-/**
- * Free's a process startup info.
- *
- * @param   pStartupInfo        Process startup info to free.
- *                              The pointer will not be valid anymore after return.
- */
-void VgsvcGstCtrlProcessStartupInfoFree(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo)
-{
-    if (!pStartupInfo)
-        return;
-
-    VgsvcGstCtrlProcessStartupInfoDestroy(pStartupInfo);
-
-    RTMemFree(pStartupInfo);
-    pStartupInfo = NULL;
-}
-
-/**
- * Duplicates a process startup info.
- *
- * @returns Duplicated process startup info on success, or NULL on error.
- * @param   pStartupInfo        Process startup info to duplicate.
- */
-static PVBOXSERVICECTRLPROCSTARTUPINFO vgsvcGstCtrlProcessStartupInfoDup(PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo)
-{
-    AssertPtrReturn(pStartupInfo, NULL);
-
-    PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfoDup = (PVBOXSERVICECTRLPROCSTARTUPINFO)
-                                                            RTMemDup(pStartupInfo, sizeof(VBOXSERVICECTRLPROCSTARTUPINFO));
-    if (pStartupInfoDup)
-    {
-        do
-        {
-            pStartupInfoDup->pszCmd      = NULL;
-            pStartupInfoDup->pszArgs     = NULL;
-            pStartupInfoDup->pszEnv      = NULL;
-            pStartupInfoDup->pszUser     = NULL;
-            pStartupInfoDup->pszPassword = NULL;
-            pStartupInfoDup->pszDomain   = NULL;
-
-#define DUP_STR(a_Str) \
-    if (pStartupInfo->cb##a_Str) \
-    { \
-        pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
-        AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
-        pStartupInfoDup->cb##a_Str  = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
-    }
-
-#define DUP_MEM(a_Str) \
-    if (pStartupInfo->cb##a_Str) \
-    { \
-        pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
-        AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
-        pStartupInfoDup->cb##a_Str  = (uint32_t)pStartupInfo->cb##a_Str; \
-    }
-
-            DUP_STR(Cmd);
-            DUP_MEM(Args);
-            DUP_MEM(Env);
-            DUP_STR(User);
-            DUP_STR(Password);
-            DUP_STR(Domain);
-
-#undef DUP_STR
-#undef DUP_MEM
-
-            return pStartupInfoDup;
-
-        } while (0); /* To use break macros above. */
-
-        VgsvcGstCtrlProcessStartupInfoFree(pStartupInfoDup);
-    }
-
-    return NULL;
-}
 
 /**
@@ -236,5 +73,5 @@
 static int vgsvcGstCtrlProcessInit(PVBOXSERVICECTRLPROCESS pProcess,
                                    const PVBOXSERVICECTRLSESSION pSession,
-                                   const PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo,
+                                   const PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
                                    uint32_t u32ContextID)
 {
@@ -282,5 +119,5 @@
 
     /* Duplicate startup info. */
-    pProcess->pStartupInfo = vgsvcGstCtrlProcessStartupInfoDup(pStartupInfo);
+    pProcess->pStartupInfo = VbglR3GuestCtrlProcStartupInfoDup(pStartupInfo);
     AssertPtrReturn(pProcess->pStartupInfo, VERR_NO_MEMORY);
 
@@ -317,5 +154,5 @@
         AssertReturn(pProcess->fShutdown, VERR_WRONG_ORDER);
 
-        VgsvcGstCtrlProcessStartupInfoFree(pProcess->pStartupInfo);
+        VbglR3GuestCtrlProcStartupInfoFree(pProcess->pStartupInfo);
         pProcess->pStartupInfo = NULL;
 
@@ -1991,5 +1828,5 @@
  */
 int VGSvcGstCtrlProcessStart(const PVBOXSERVICECTRLSESSION pSession,
-                             const PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo, uint32_t uContextID)
+                             const PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo, uint32_t uContextID)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 84214)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 84215)
@@ -1035,137 +1035,4 @@
 
 /**
- * Initializes a session startup info, extended version.
- *
- * @returns VBox status code.
- * @param   pStartupInfo        Session startup info to initializes.
- * @param   cbUser              Size (in bytes) to use for the user name buffer.
- * @param   cbPassword          Size (in bytes) to use for the password buffer.
- * @param   cbDomain            Size (in bytes) to use for the domain name buffer.
- */
-int VgsvcGstCtrlSessionStartupInfoInitEx(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo,
-                                         size_t cbUser, size_t cbPassword, size_t cbDomain)
-{
-    AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
-
-    RT_BZERO(pStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO));
-
-#define ALLOC_STR(a_Str, a_cb) \
-    if ((a_cb) > 0) \
-    { \
-        pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
-        AssertPtrBreak(pStartupInfo->psz##a_Str); \
-        AssertBreak((uint32_t)a_cb == a_cb); \
-        pStartupInfo->cb##a_Str  = (uint32_t)a_cb; \
-    }
-
-    do
-    {
-        ALLOC_STR(User,     cbUser);
-        ALLOC_STR(Password, cbPassword);
-        ALLOC_STR(Domain,   cbDomain);
-
-        return VINF_SUCCESS;
-
-    } while (0);
-
-#undef ALLOC_STR
-
-    VgsvcGstCtrlSessionStartupInfoDestroy(pStartupInfo);
-    return VERR_NO_MEMORY;
-}
-
-/**
- * Initializes a session startup info.
- *
- * @returns VBox status code.
- * @param   pStartupInfo        Session startup info to initializes.
- */
-int VgsvcGstCtrlSessionStartupInfoInit(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo)
-{
-    return VgsvcGstCtrlSessionStartupInfoInitEx(pStartupInfo,
-                                                GUESTPROCESS_MAX_USER_LEN, GUESTPROCESS_MAX_PASSWORD_LEN,
-                                                GUESTPROCESS_MAX_DOMAIN_LEN);
-}
-
-/**
- * Destroys a session startup info.
- *
- * @param   pStartupInfo        Session startup info to destroy.
- */
-void VgsvcGstCtrlSessionStartupInfoDestroy(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo)
-{
-    if (!pStartupInfo)
-        return;
-
-    RTStrFree(pStartupInfo->pszUser);
-    RTStrFree(pStartupInfo->pszPassword);
-    RTStrFree(pStartupInfo->pszDomain);
-
-    RT_BZERO(pStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO));
-}
-
-/**
- * Free's a session startup info.
- *
- * @param   pStartupInfo        Session startup info to free.
- *                              The pointer will not be valid anymore after return.
- */
-static void vgsvcGstCtrlSessionStartupInfoFree(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo)
-{
-    if (!pStartupInfo)
-        return;
-
-    VgsvcGstCtrlSessionStartupInfoDestroy(pStartupInfo);
-
-    RTMemFree(pStartupInfo);
-    pStartupInfo = NULL;
-}
-
-/**
- * Duplicates a session startup info.
- *
- * @returns Duplicated session startup info on success, or NULL on error.
- * @param   pStartupInfo        Session startup info to duplicate.
- */
-static PVBOXSERVICECTRLSESSIONSTARTUPINFO vgsvcGstCtrlSessionStartupInfoDup(PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfo)
-{
-    AssertPtrReturn(pStartupInfo, NULL);
-
-    PVBOXSERVICECTRLSESSIONSTARTUPINFO pStartupInfoDup = (PVBOXSERVICECTRLSESSIONSTARTUPINFO)
-                                                                RTMemDup(pStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO));
-    if (pStartupInfoDup)
-    {
-        do
-        {
-            pStartupInfoDup->pszUser     = NULL;
-            pStartupInfoDup->pszPassword = NULL;
-            pStartupInfoDup->pszDomain   = NULL;
-
-#define DUP_STR(a_Str) \
-    if (pStartupInfo->cb##a_Str) \
-    { \
-        pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
-        AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
-        size_t cbStr = strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
-        AssertBreak((uint32_t)cbStr == cbStr); \
-        pStartupInfoDup->cb##a_Str  = (uint32_t)cbStr; \
-    }
-            DUP_STR(User);
-            DUP_STR(Password);
-            DUP_STR(Domain);
-
-#undef DUP_STR
-
-            return pStartupInfoDup;
-
-        } while (0); /* To use break macros above. */
-
-        vgsvcGstCtrlSessionStartupInfoFree(pStartupInfoDup);
-    }
-
-    return NULL;
-}
-
-/**
  * Handles starting a guest processes.
  *
@@ -1184,36 +1051,13 @@
      * parameter to retrieve the stuff from the host. On output this then
      * will contain the actual block size. */
-    VBOXSERVICECTRLPROCSTARTUPINFO startupInfo;
-    int rc = VgsvcGstCtrlProcessStartupInfoInit(&startupInfo);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = VbglR3GuestCtrlProcGetStart(pHostCtx,
-                                     /* Command */
-                                     startupInfo.pszCmd,      startupInfo.cbCmd,
-                                     /* Flags */
-                                     &startupInfo.fFlags,
-                                     /* Arguments */
-                                     startupInfo.pszArgs,     startupInfo.cbArgs,     &startupInfo.cArgs,
-                                     /* Environment */
-                                     startupInfo.pszEnv,      &startupInfo.cbEnv,     &startupInfo.cEnvVars,
-                                     /* Credentials; for hosts with VBox < 4.3 (protocol version 1).
-                                      * For protocol v2 and up the credentials are part of the session
-                                      * opening call. */
-                                     startupInfo.pszUser,     startupInfo.cbUser,
-                                     startupInfo.pszPassword, startupInfo.cbPassword,
-                                     /* Timeout (in ms) */
-                                     &startupInfo.uTimeLimitMS,
-                                     /* Process priority */
-                                     &startupInfo.uPriority,
-                                     /* Process affinity */
-                                     startupInfo.uAffinity,  sizeof(startupInfo.uAffinity), &startupInfo.uNumAffinity);
+    PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo;
+    int rc = VbglR3GuestCtrlProcGetStart(pHostCtx, &pStartupInfo);
     if (RT_SUCCESS(rc))
     {
         VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
-                     startupInfo.pszCmd, startupInfo.fFlags,
-                     startupInfo.cArgs ? startupInfo.pszArgs : "<None>",
-                     startupInfo.cEnvVars ? startupInfo.pszEnv : "<None>",
-                     startupInfo.uTimeLimitMS);
+                     pStartupInfo->pszCmd, pStartupInfo->fFlags,
+                     pStartupInfo->cArgs    ? pStartupInfo->pszArgs : "<None>",
+                     pStartupInfo->cEnvVars ? pStartupInfo->pszEnv  : "<None>",
+                     pStartupInfo->uTimeLimitMS);
 
         bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */
@@ -1224,5 +1068,5 @@
 
             if (fStartAllowed)
-                rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID);
+                rc = VGSvcGstCtrlProcessStart(pSession, pStartupInfo, pHostCtx->uContextID);
             else
                 rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */
@@ -1238,4 +1082,7 @@
                 VGSvcError("Error sending start process status to host, rc=%Rrc\n", rc2);
         }
+
+        VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
+        pStartupInfo = NULL;
     }
     else
@@ -1244,6 +1091,4 @@
         VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     }
-
-    VgsvcGstCtrlProcessStartupInfoDestroy(&startupInfo);
 
     return rc;
@@ -2350,5 +2195,5 @@
  * @param   uCtrlSessionThread      The session thread debug ordinal.
  */
-static int vgsvcVGSvcGstCtrlSessionThreadCreateProcess(const PVBOXSERVICECTRLSESSIONSTARTUPINFO pSessionStartupInfo,
+static int vgsvcVGSvcGstCtrlSessionThreadCreateProcess(const PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pSessionStartupInfo,
                                                        PVBOXSERVICECTRLSESSIONTHREAD pSessionThread, uint32_t uCtrlSessionThread)
 {
@@ -2579,5 +2424,5 @@
  *                                  Optional.
  */
-int VGSvcGstCtrlSessionThreadCreate(PRTLISTANCHOR pList, const PVBOXSERVICECTRLSESSIONSTARTUPINFO pSessionStartupInfo,
+int VGSvcGstCtrlSessionThreadCreate(PRTLISTANCHOR pList, const PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pSessionStartupInfo,
                                     PVBOXSERVICECTRLSESSIONTHREAD *ppSessionThread)
 {
@@ -2617,5 +2462,5 @@
 
         /* Duplicate startup info. */
-        pSessionThread->pStartupInfo = vgsvcGstCtrlSessionStartupInfoDup(pSessionStartupInfo);
+        pSessionThread->pStartupInfo = VbglR3GuestCtrlSessionStartupInfoDup(pSessionStartupInfo);
         AssertPtrReturn(pSessionThread->pStartupInfo, VERR_NO_MEMORY);
 
@@ -2785,5 +2630,5 @@
     if (RT_SUCCESS(rc))
     {
-        vgsvcGstCtrlSessionStartupInfoFree(pThread->pStartupInfo);
+        VbglR3GuestCtrlSessionStartupInfoFree(pThread->pStartupInfo);
         pThread->pStartupInfo = NULL;
 
