Index: trunk/doc/manual/en_US/man_VBoxManage-guestcontrol.xml
===================================================================
--- trunk/doc/manual/en_US/man_VBoxManage-guestcontrol.xml	(revision 99119)
+++ trunk/doc/manual/en_US/man_VBoxManage-guestcontrol.xml	(revision 99120)
@@ -78,4 +78,5 @@
       <arg>--unquoted-args</arg>
       <arg>--username=<replaceable>username</replaceable></arg>
+      <arg>--cwd=<replaceable>directory</replaceable></arg>
       <arg>--verbose</arg>
       <arg choice="req">-- <replaceable>program/arg0</replaceable> <arg rep="repeat"><replaceable>argument</replaceable></arg></arg>
@@ -102,4 +103,5 @@
       <arg>--unquoted-args</arg>
       <arg>--username=<replaceable>username</replaceable></arg>
+      <arg>--cwd=<replaceable>directory</replaceable></arg>
       <arg>--verbose</arg>
       <arg choice="req">-- <replaceable>program/arg0</replaceable> <arg rep="repeat"><replaceable>argument</replaceable></arg></arg>
@@ -502,4 +504,15 @@
               run on the guest VM. For example:
               <filename>C:\Windows\System32\calc.exe</filename>.
+            </para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--cwd=<replaceable>path-to-directory</replaceable></option></term>
+          <listitem><para>
+              Specifies the absolute path of a directory in which
+              to start the program. Optional. The directory must
+              exist and be accessible to the guest user. For example:
+              <filename>C:\Users\production\work_area</filename>.
+            </para><para>
+              The short form of this option is <option>-C</option>.
             </para></listitem>
         </varlistentry>
Index: trunk/include/VBox/GuestHost/GuestControl.h
===================================================================
--- trunk/include/VBox/GuestHost/GuestControl.h	(revision 99119)
+++ trunk/include/VBox/GuestHost/GuestControl.h	(revision 99120)
@@ -194,4 +194,5 @@
  */
 #define GUEST_PROC_DEF_CMD_LEN        _1K
+#define GUEST_PROC_DEF_CWD_LEN        _1K
 #define GUEST_PROC_DEF_ARGS_LEN       _1K
 #define GUEST_PROC_DEF_ENV_LEN        _1K
@@ -205,4 +206,5 @@
  */
 #define GUEST_PROC_MAX_CMD_LEN            _1M
+#define GUEST_PROC_MAX_CWD_LEN            RTPATH_MAX
 #define GUEST_PROC_MAX_ARGS_LEN           _2M
 #define GUEST_PROC_MAX_ENV_LEN            _4M
Index: trunk/include/VBox/HostServices/GuestControlSvc.h
===================================================================
--- trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 99119)
+++ trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 99120)
@@ -814,5 +814,7 @@
  * The toolbox commands now are being marked as deprecated.
  * @since 7.1 */
-# define VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS        RT_BIT_64(4)
+#define VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS         RT_BIT_64(4)
+/** Supports specifying the working directory for run / start. */
+#define VBOX_GUESTCTRL_GF_0_PROCESS_CWD             RT_BIT_64(5)
 /** Bit that must be set in the 2nd parameter, will be cleared if the host reponds
  * correctly (old hosts might not). */
@@ -830,4 +832,8 @@
  * @since 6.1.6  */
 #define VBOX_GUESTCTRL_HF_0_PROCESS_ARGV0           RT_BIT_64(1)
+/** Host sends the working directory for run / start, if guest
+ * reports VBOX_GUESTCTRL_GF_0_PROCESS_CWD.
+ * @since 6.1.20 ??  */
+#define VBOX_GUESTCTRL_HF_0_PROCESS_CWD             RT_BIT_64(2)
 /** @} */
 
@@ -1210,4 +1216,7 @@
             /** Pointer to process affinity blocks (uint64_t). */
             HGCMFunctionParameter affinity;
+            /** Working directory request, filled if guest
+             *  reports VBOX_GUESTCTRL_GF_0_PROCESS_CWD. */
+            HGCMFunctionParameter cwd;
         } v2;
     } u;
Index: trunk/include/VBox/VBoxGuestLib.h
===================================================================
--- trunk/include/VBox/VBoxGuestLib.h	(revision 99119)
+++ trunk/include/VBox/VBoxGuestLib.h	(revision 99120)
@@ -1029,4 +1029,8 @@
     /** Number of environment variables specified in pszEnv. */
     uint32_t cEnvVars;
+    /** Optional working directory. */
+    char *pszCwd;
+    /** Size (in bytes) of optional working directory string. */
+    uint32_t cbCwd;
     /** User name (account) to start the process under. */
     char *pszUser;
Index: trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp	(revision 99119)
+++ trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp	(revision 99120)
@@ -1391,4 +1391,5 @@
  * @param   pStartupInfo        Process startup info to initializes.
  * @param   cbCmd               Size (in bytes) to use for the command buffer.
+ * @param   cbCwd               Size (in bytes) to use for the current working directory.
  * @param   cbUser              Size (in bytes) to use for the user name buffer.
  * @param   cbPassword          Size (in bytes) to use for the password buffer.
@@ -1399,4 +1400,5 @@
 VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
                                                      size_t cbCmd,
+                                                     size_t cbCwd,
                                                      size_t cbUser, size_t cbPassword, size_t cbDomain,
                                                      size_t cbArgs, size_t cbEnv)
@@ -1404,4 +1406,5 @@
     AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
     AssertReturn(cbCmd,           VERR_INVALID_PARAMETER);
+    AssertReturn(cbCwd,           VERR_INVALID_PARAMETER);
     AssertReturn(cbUser,          VERR_INVALID_PARAMETER);
     AssertReturn(cbPassword,      VERR_INVALID_PARAMETER);
@@ -1423,4 +1426,5 @@
     {
         ALLOC_STR(Cmd,      cbCmd);
+        ALLOC_STR(Cwd,      cbCwd);
         ALLOC_STR(Args,     cbArgs);
         ALLOC_STR(Env,      cbEnv);
@@ -1448,4 +1452,5 @@
     return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
                                                 GUEST_PROC_DEF_CMD_LEN,
+                                                GUEST_PROC_DEF_CWD_LEN,
                                                 GUEST_PROC_DEF_USER_LEN     /* Deprecated, now handled via session creation. */,
                                                 GUEST_PROC_DEF_PASSWORD_LEN /* Ditto. */,
@@ -1465,4 +1470,5 @@
 
     RTStrFree(pStartupInfo->pszCmd);
+    RTStrFree(pStartupInfo->pszCwd);
     RTStrFree(pStartupInfo->pszArgs);
     RTStrFree(pStartupInfo->pszEnv);
@@ -1605,4 +1611,7 @@
             VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
             VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
+            /* v2.cwd was added in 7.1.  If the host is older, the Msg struct it sends is
+             * shorter and these fields are zero-filled, which equals 'no cwd requested'. */
+            VbglHGCMParmPtrSet(&Msg.u.v2.cwd, pStartupInfo->pszCwd, pStartupInfo->cbCwd);
         }
 
@@ -1610,6 +1619,6 @@
         if (RT_FAILURE(rc))
         {
-            LogRel(("VbglR3GuestCtrlProcGetStart: 1 - %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
-                    rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
+            LogRel(("VbglR3GuestCtrlProcGetStart: 1 - %Rrc (retry %u, cbCmd=%RU32, cbCwd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
+                    rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbCwd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
 
             if (   rc == VERR_BUFFER_OVERFLOW
@@ -1624,10 +1633,11 @@
                 /* We can't tell which parameter doesn't fit, so we have to resize all. */
                 GROW_STR(Cmd , GUEST_PROC_MAX_CMD_LEN);
+                GROW_STR(Cwd,  GUEST_PROC_MAX_CWD_LEN);
                 GROW_STR(Args, GUEST_PROC_MAX_ARGS_LEN);
                 GROW_STR(Env,  GUEST_PROC_MAX_ENV_LEN);
 
 #undef GROW_STR
-                LogRel(("VbglR3GuestCtrlProcGetStart: 2 - %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
-                        rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
+                LogRel(("VbglR3GuestCtrlProcGetStart: 2 - %Rrc (retry %u, cbCmd=%RU32, cbCwd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
+                        rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbCwd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
                 LogRel(("g_fVbglR3GuestCtrlHavePeekGetCancel=%RTbool\n", RT_BOOL(g_fVbglR3GuestCtrlHavePeekGetCancel)));
             }
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 99119)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 99120)
@@ -258,4 +258,5 @@
                                       | VBOX_GUESTCTRL_GF_0_PROCESS_ARGV0
                                       | VBOX_GUESTCTRL_GF_0_PROCESS_DYNAMIC_SIZES
+                                      | VBOX_GUESTCTRL_GF_0_PROCESS_CWD
 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
                                       | VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 99119)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 99120)
@@ -1254,4 +1254,6 @@
  * @param   pszPassword                 Password of the specified user.
  * @param   pszDomain                   Domain to use for authentication.
+ * @param   pszCwd                      Current working directory to use for the created process.
+ *                                      Set to NULL if not being used.
  * @param   phProcess                   Pointer which will receive the process handle after
  *                                      successful process start.
@@ -1260,5 +1262,5 @@
                                             PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr,
                                             const char *pszAsUser, const char *pszPassword, const char *pszDomain,
-                                            PRTPROCESS phProcess)
+                                            const char *pszCwd, PRTPROCESS phProcess)
 {
 #ifndef RT_OS_WINDOWS
@@ -1272,4 +1274,5 @@
     /* pszPassword is optional. */
     /* pszDomain is optional. */
+    /* pszCwd is optional. */
     AssertPtrReturn(phProcess, VERR_INVALID_PARAMETER);
 
@@ -1411,4 +1414,8 @@
                     fProcCreateFlags |= RTPROC_FLAGS_UNQUOTED_ARGS;
             }
+            if (pszCwd && *pszCwd)
+                fProcCreateFlags |= RTPROC_FLAGS_CWD;
+            else
+                pszCwd = NULL;
 
             /* If no user name specified run with current credentials (e.g.
@@ -1447,5 +1454,5 @@
                                     pszAsUser,
                                     pszPassword && *pszPassword ? pszPassword : NULL,
-                                    NULL /*pvExtraData*/,
+                                    (void *)pszCwd /*pvExtraData*/,
                                     phProcess);
 
@@ -1545,4 +1552,6 @@
     VGSvcVerbose(3, "vgsvcGstCtrlProcessProcessWorker: fHostFeatures0       = %#x\n",     g_fControlHostFeatures0);
     VGSvcVerbose(3, "vgsvcGstCtrlProcessProcessWorker: StartupInfo.szCmd    = '%s'\n",    pProcess->pStartupInfo->pszCmd);
+    VGSvcVerbose(3, "vgsvcGstCtrlProcessProcessWorker: StartupInfo.szCwd    = '%s'\n",    pProcess->pStartupInfo->pszCwd
+                                                                                        ? pProcess->pStartupInfo->pszCwd : "<None>");
     VGSvcVerbose(3, "vgsvcGstCtrlProcessProcessWorker: StartupInfo.uNumArgs = '%RU32'\n", pProcess->pStartupInfo->cArgs);
 #ifdef DEBUG /* Never log this stuff in release mode! */
@@ -1678,5 +1687,5 @@
                                                                      fNeedsImpersonation ? pProcess->pStartupInfo->pszPassword : NULL,
                                                                      fNeedsImpersonation ? pProcess->pStartupInfo->pszDomain   : NULL,
-                                                                     &pProcess->hProcess);
+                                                                     pProcess->pStartupInfo->pszCwd, &pProcess->hProcess);
                                     if (RT_FAILURE(rc))
                                         VGSvcError("Error starting process, rc=%Rrc\n", rc);
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 99119)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 99120)
@@ -1692,8 +1692,9 @@
     if (RT_SUCCESS(rc))
     {
-        VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
+        VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, szCwd=%s, uTimeout=%RU32\n",
                      pStartupInfo->pszCmd, pStartupInfo->fFlags,
                      pStartupInfo->cArgs    ? pStartupInfo->pszArgs : "<None>",
                      pStartupInfo->cEnvVars ? pStartupInfo->pszEnv  : "<None>",
+                     pStartupInfo->cbCwd    ? pStartupInfo->pszCwd  : "<None>",
                      pStartupInfo->uTimeLimitMS);
 
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 99119)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 99120)
@@ -1170,4 +1170,5 @@
     {
         GCTLCMD_COMMON_OPTION_DEFS()
+        { "--cwd",                          'C',                                      RTGETOPT_REQ_STRING  },
         { "--putenv",                       'E',                                      RTGETOPT_REQ_STRING  },
         { "--exe",                          'e',                                      RTGETOPT_REQ_STRING  },
@@ -1200,4 +1201,5 @@
     com::SafeArray<IN_BSTR>                 aEnv;
     const char *                            pszImage            = NULL;
+    const char *                            pszCwd              = NULL;
     bool                                    fWaitForStdOut      = fRunCmd;
     bool                                    fWaitForStdErr      = fRunCmd;
@@ -1239,4 +1241,8 @@
                 case kGstCtrlRunOpt_Profile:
                     aCreateFlags.push_back(ProcessCreateFlag_Profile);
+                    break;
+
+                case 'C':
+                    pszCwd = ValueUnion.psz;
                     break;
 
@@ -1358,4 +1364,5 @@
             ComPtr<IGuestProcess> pProcess;
             CHECK_ERROR_BREAK(pCtx->pGuestSession, ProcessCreate(Bstr(pszImage).raw(),
+                                                                 Bstr(pszCwd).raw(),
                                                                  ComSafeArrayAsInParam(aArgs),
                                                                  ComSafeArrayAsInParam(aEnv),
Index: trunk/src/VBox/HostServices/GuestControl/VBoxGuestControlSvc.cpp
===================================================================
--- trunk/src/VBox/HostServices/GuestControl/VBoxGuestControlSvc.cpp	(revision 99119)
+++ trunk/src/VBox/HostServices/GuestControl/VBoxGuestControlSvc.cpp	(revision 99120)
@@ -952,4 +952,5 @@
 /** Host feature mask for GUEST_MSG_REPORT_FEATURES/GUEST_MSG_QUERY_FEATURES. */
 static uint64_t const g_fGstCtrlHostFeatures0 = VBOX_GUESTCTRL_HF_0_NOTIFY_RDWR_OFFSET
+                                              | VBOX_GUESTCTRL_HF_0_PROCESS_CWD
                                               | VBOX_GUESTCTRL_HF_0_PROCESS_ARGV0;
 
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 99119)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 99120)
@@ -14814,5 +14814,5 @@
   <interface
     name="IGuestSession" extends="$unknown"
-    uuid="234f0627-866d-48c2-91a5-4c9d50f04928"
+    uuid="5591bead-9c1d-4cbd-9669-2d0b04fac0a8"
     wsmap="managed"
     reservedMethods="8" reservedAttributes="12"
@@ -15947,5 +15947,5 @@
           If ProcessCreateFlag_WaitForStdOut and/or ProcessCreateFlag_WaitForStdErr
           are set, the guest process will not enter the terminated state until
-          all data from the specified streams have been read read.
+          all data from the specified streams have been read.
         </note>
 
@@ -15961,7 +15961,18 @@
         <desc>
           Full path to the file to execute in the guest.  The file has to
-          exists in the guest VM with executable right to the session user in
+          exist in the guest VM with executable right to the session user in
           order to succeed.  If empty/null, the first entry in the
           @a arguments array will be used instead (i.e. argv[0]).
+        </desc>
+      </param>
+      <param name="cwd" type="wstring" dir="in">
+        <desc>
+          Path to the directory in which to execute in the guest.  The
+          directory has to exist in the guest VM with search rights to the
+          session user in order to succeed.  If empty/null, the session
+          user's default (typically 'home') directory is used.  If not a
+          full path, it is interpreted relative to the default directory;
+          e.g. 'work' means '$HOME/work' (according to the guest's '$HOME'-
+          like concept).
         </desc>
       </param>
@@ -16017,8 +16028,19 @@
         See <link to="IGuestSession::processCreate"/> for more information.
       </desc>
+      <param name="cwd" type="wstring" dir="in">
+        <desc>
+          Path to the directory in which to execute in the guest.  The
+          directory has to exist in the guest VM with search rights to the
+          session user in order to succeed.  If empty/null, the session
+          user's default (typically 'home') directory is used.  If not a
+          full path, it is interpreted relative to the default directory;
+          e.g. 'work' means '$HOME/work' (according to the guest's '$HOME'-
+          like concept).
+        </desc>
+      </param>
       <param name="executable" type="wstring" dir="in">
         <desc>
           Full path to the file to execute in the guest.  The file has to
-          exists in the guest VM with executable right to the session user in
+          exist in the guest VM with executable right to the session user in
           order to succeed.  If empty/null, the first entry in the
           @a arguments array will be used instead (i.e. argv[0]).
Index: trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
===================================================================
--- trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 99119)
+++ trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 99120)
@@ -945,4 +945,6 @@
     /** The executable. */
     Utf8Str                     mExecutable;
+    /** The working directory. Optional, can be empty if not used. */
+    Utf8Str                     mCwd;
     /** Arguments vector (starting with argument \#0). */
     ProcessArguments            mArguments;
Index: trunk/src/VBox/Main/include/GuestSessionImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 99119)
+++ trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 99120)
@@ -212,4 +212,5 @@
                         ULONG aMode);
     HRESULT processCreate(const com::Utf8Str &aCommand,
+                          const com::Utf8Str &aCwd,
                           const std::vector<com::Utf8Str> &aArguments,
                           const std::vector<com::Utf8Str> &aEnvironment,
@@ -218,4 +219,5 @@
                           ComPtr<IGuestProcess> &aGuestProcess);
     HRESULT processCreateEx(const com::Utf8Str &aCommand,
+                            const com::Utf8Str &aCwd,
                             const std::vector<com::Utf8Str> &aArguments,
                             const std::vector<com::Utf8Str> &aEnvironment,
Index: trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 99119)
+++ trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 99120)
@@ -1158,7 +1158,7 @@
 int GuestProcess::i_startProcess(uint32_t cMsTimeout, int *pvrcGuest)
 {
-    LogFlowThisFunc(("cMsTimeout=%RU32, procExe=%s, procTimeoutMS=%RU32, procFlags=%x, sessionID=%RU32\n",
-                     cMsTimeout, mData.mProcess.mExecutable.c_str(), mData.mProcess.mTimeoutMS, mData.mProcess.mFlags,
-                     mSession->i_getId()));
+    LogFlowThisFunc(("cMsTimeout=%RU32, procExe=%s, cwd=%s, procTimeoutMS=%RU32, procFlags=%x, sessionID=%RU32\n",
+                     cMsTimeout, mData.mProcess.mExecutable.c_str(), mData.mProcess.mCwd.c_str(),
+                     mData.mProcess.mTimeoutMS, mData.mProcess.mFlags, mSession->i_getId()));
 
     /* Wait until the caller function (if kicked off by a thread)
@@ -1215,7 +1215,23 @@
         return VERR_BUFFER_OVERFLOW;
 
+    Guest *pGuest = mSession->i_getParent();
+    AssertPtr(pGuest);
+    const uint64_t fGuestControlFeatures0 = pGuest->i_getGuestControlFeatures0();
+
+    /* Check if the Guest Additions support setting the current working directory for the new process
+     * if the caller wants to set one, and bail out early if it doesn't. */
+    if (   !mData.mProcess.mCwd.isEmpty()
+        && (   uProtocol < 2
+            || !(fGuestControlFeatures0 & VBOX_GUESTCTRL_GF_0_PROCESS_CWD)))
+    {
+        LogRel2(("Guest Control: Installed Guest Addtions don't support setting the current working directory to '%s'!\n",
+                 mData.mProcess.mCwd.c_str()));
+        return VERR_NOT_SUPPORTED;
+    }
+
     size_t cbArgs = 0;
     char *pszArgs = NULL;
     int vrc = VINF_SUCCESS;
+
     if (cArgs)
     {
@@ -1229,9 +1245,4 @@
         }
         papszArgv[cArgs] = NULL;
-
-        Guest *pGuest = mSession->i_getParent();
-        AssertPtr(pGuest);
-
-        const uint64_t fGuestControlFeatures0 = pGuest->i_getGuestControlFeatures0();
 
         /* If the Guest Additions don't support using argv[0] correctly (< 6.1.x), don't supply it. */
@@ -1299,4 +1310,7 @@
             /* The actual CPU affinity blocks. */
             HGCMSvcSetPv(&paParms[i++], (void *)&mData.mProcess.mAffinity, sizeof(mData.mProcess.mAffinity));
+            /* Supply working directory, if guest supports it. */
+            if (fGuestControlFeatures0 & VBOX_GUESTCTRL_GF_0_PROCESS_CWD)
+                HGCMSvcSetRTCStr(&paParms[i++], mData.mProcess.mCwd);
         }
 
Index: trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 99119)
+++ trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 99120)
@@ -4943,5 +4943,6 @@
 
 
-HRESULT GuestSession::processCreate(const com::Utf8Str &aExecutable, const std::vector<com::Utf8Str> &aArguments,
+HRESULT GuestSession::processCreate(const com::Utf8Str &aExecutable, const com::Utf8Str &aCwd,
+                                    const std::vector<com::Utf8Str> &aArguments,
                                     const std::vector<com::Utf8Str> &aEnvironment,
                                     const std::vector<ProcessCreateFlag_T> &aFlags,
@@ -4951,9 +4952,10 @@
 
     std::vector<LONG> affinityIgnored;
-    return processCreateEx(aExecutable, aArguments, aEnvironment, aFlags, aTimeoutMS, ProcessPriority_Default,
-                           affinityIgnored, aGuestProcess);
-}
-
-HRESULT GuestSession::processCreateEx(const com::Utf8Str &aExecutable, const std::vector<com::Utf8Str> &aArguments,
+    return processCreateEx(aExecutable, aCwd, aArguments, aEnvironment, aFlags, aTimeoutMS,
+                           ProcessPriority_Default, affinityIgnored, aGuestProcess);
+}
+
+HRESULT GuestSession::processCreateEx(const com::Utf8Str &aExecutable, const com::Utf8Str &aCwd,
+                                      const std::vector<com::Utf8Str> &aArguments,
                                       const std::vector<com::Utf8Str> &aEnvironment,
                                       const std::vector<ProcessCreateFlag_T> &aFlags, ULONG aTimeoutMS,
@@ -4978,4 +4980,15 @@
     }
 
+    uint32_t const uProtocol              = i_getProtocolVersion();
+    uint64_t const fGuestControlFeatures0 = mParent->i_getGuestControlFeatures0();
+
+    /* If a current working directory (CWD) is set, make sure that the installed Guest Additions actually 
+     * support this before doing anything else. */
+    if (   !aCwd.isEmpty()
+        && (   uProtocol < 2
+            || !(fGuestControlFeatures0 & VBOX_GUESTCTRL_GF_0_PROCESS_CWD)))
+        return setError(VBOX_E_NOT_SUPPORTED,
+                        tr("Setting the current working directory is not supported by the installed Guest Addtions!"));
+
     /* The rest of the input is being validated in i_processCreateEx(). */
 
@@ -4996,4 +5009,7 @@
     else /* If no arguments were given, add the executable as argv[0] by default. */
         procInfo.mArguments.push_back(procInfo.mExecutable);
+
+    /* Optional working directory */
+    procInfo.mCwd = aCwd;
 
     /* Combine the environment changes associated with the ones passed in by
