Index: /trunk/include/VBox/GuestHost/GuestControl.h
===================================================================
--- /trunk/include/VBox/GuestHost/GuestControl.h	(revision 60622)
+++ /trunk/include/VBox/GuestHost/GuestControl.h	(revision 60622)
@@ -0,0 +1,189 @@
+/* $Id$ */
+/** @file
+ * Guest Control - Common Guest and Host Code.
+ */
+
+/*
+ * Copyright (C) 2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_GuestHost_GuestControl_h
+#define ___VBox_GuestHost_GuestControl_h
+
+/* Everything defined in this file lives in this namespace. */
+namespace guestControl {
+
+/**
+ * Process status when executed in the guest.
+ */
+enum eProcessStatus
+{
+    /** Process is in an undefined state. */
+    PROC_STS_UNDEFINED = 0,
+    /** Process has been started. */
+    PROC_STS_STARTED = 1,
+    /** Process terminated normally. */
+    PROC_STS_TEN = 2,
+    /** Process terminated via signal. */
+    PROC_STS_TES = 3,
+    /** Process terminated abnormally. */
+    PROC_STS_TEA = 4,
+    /** Process timed out and was killed. */
+    PROC_STS_TOK = 5,
+    /** Process timed out and was not killed successfully. */
+    PROC_STS_TOA = 6,
+    /** Service/OS is stopping, process was killed. */
+    PROC_STS_DWN = 7,
+    /** Something went wrong (error code in flags). */
+    PROC_STS_ERROR = 8
+};
+
+/** @todo r=bird: Most defines in this file needs to be scoped a little
+ *        better!  For instance INPUT_FLAG_NONE is very generic. */
+
+/**
+ * Input flags, set by the host. This is needed for
+ * handling flags on the guest side.
+ * Note: Has to match Main's ProcessInputFlag_* flags!
+ */
+#define INPUT_FLAG_NONE                     0x0
+#define INPUT_FLAG_EOF                      RT_BIT(0)
+
+/**
+ * Guest session creation flags.
+ * Only handled internally at the moment.
+ */
+#define SESSIONCREATIONFLAG_NONE            0x0
+
+/**
+ * Guest directory removement flags.
+ * Essentially using what IPRT's RTDIRRMREC_F_
+ * defines have to offer.
+ */
+#define DIRREMOVE_FLAG_RECURSIVE            RT_BIT(0)
+/** Delete the content of the directory and the directory itself. */
+#define DIRREMOVE_FLAG_CONTENT_AND_DIR      RT_BIT(1)
+/** Only delete the content of the directory, omit the directory it self. */
+#define DIRREMOVE_FLAG_CONTENT_ONLY         RT_BIT(2)
+/** Mask of valid flags. */
+#define DIRREMOVE_FLAG_VALID_MASK           UINT32_C(0x00000003)
+
+/** @name EXECUTEPROCESSFLAG_XXX Guest process creation flags.
+ * @note Has to match Main's ProcessCreateFlag_* flags!
+ */
+#define EXECUTEPROCESSFLAG_NONE             UINT32_C(0x0)
+#define EXECUTEPROCESSFLAG_WAIT_START       RT_BIT(0)
+#define EXECUTEPROCESSFLAG_IGNORE_ORPHANED  RT_BIT(1)
+#define EXECUTEPROCESSFLAG_HIDDEN           RT_BIT(2)
+#define EXECUTEPROCESSFLAG_NO_PROFILE       RT_BIT(3) /** @todo Rename to EXECUTEPROCESSFLAG_PROFILE in next API change. */
+#define EXECUTEPROCESSFLAG_WAIT_STDOUT      RT_BIT(4)
+#define EXECUTEPROCESSFLAG_WAIT_STDERR      RT_BIT(5)
+#define EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS RT_BIT(6)
+#define EXECUTEPROCESSFLAG_UNQUOTED_ARGS    RT_BIT(7)
+/** @} */
+
+/**
+ * Pipe handle IDs used internally for referencing to
+ * a certain pipe buffer.
+ */
+#define OUTPUT_HANDLE_ID_STDOUT_DEPRECATED  0 /* Needed for VBox hosts < 4.1.0. */
+#define OUTPUT_HANDLE_ID_STDOUT             1
+#define OUTPUT_HANDLE_ID_STDERR             2
+
+/**
+ * Guest path rename flags.
+ * Essentially using what IPRT's RTPATHRENAME_FLAGS_
+ * defines have to offer.
+ */
+/** Do not replace anything. */
+#define PATHRENAME_FLAG_NO_REPLACE          UINT32_C(0)
+/** This will replace attempt any target which isn't a directory. */
+#define PATHRENAME_FLAG_REPLACE             RT_BIT(0)
+/** Don't allow symbolic links as part of the path. */
+#define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
+/** Mask of valid flags. */
+#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
+
+/**
+ * Defines for guest process array lengths.
+ */
+#define GUESTPROCESS_MAX_CMD_LEN            _1K
+#define GUESTPROCESS_MAX_ARGS_LEN           _1K
+#define GUESTPROCESS_MAX_ENV_LEN            _64K
+#define GUESTPROCESS_MAX_USER_LEN           128
+#define GUESTPROCESS_MAX_PASSWORD_LEN       128
+#define GUESTPROCESS_MAX_DOMAIN_LEN         256
+
+/** @name Internal tools built into VBoxService which are used in order to
+ *        accomplish tasks host<->guest.
+ * @{
+ */
+#define VBOXSERVICE_TOOL_CAT        "vbox_cat"
+#define VBOXSERVICE_TOOL_LS         "vbox_ls"
+#define VBOXSERVICE_TOOL_RM         "vbox_rm"
+#define VBOXSERVICE_TOOL_MKDIR      "vbox_mkdir"
+#define VBOXSERVICE_TOOL_MKTEMP     "vbox_mktemp"
+#define VBOXSERVICE_TOOL_STAT       "vbox_stat"
+/** @} */
+
+/** Special process exit codes for "vbox_cat". */
+typedef enum VBOXSERVICETOOLBOX_CAT_EXITCODE
+{
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED = RTEXITCODE_END,
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND,
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND,
+    VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION,
+    /** The usual 32-bit type hack. */
+    VBOXSERVICETOOLBOX_CAT_32BIT_HACK = 0x7fffffff
+} VBOXSERVICETOOLBOX_CAT_EXITCODE;
+
+/** Special process exit codes for "vbox_stat". */
+typedef enum VBOXSERVICETOOLBOX_STAT_EXITCODE
+{
+    VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED = RTEXITCODE_END,
+    VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND,
+    VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND,
+    /** The usual 32-bit type hack. */
+    VBOXSERVICETOOLBOX_STAT_32BIT_HACK = 0x7fffffff
+} VBOXSERVICETOOLBOX_STAT_EXITCODE;
+
+/**
+ * Input status, reported by the client.
+ */
+enum eInputStatus
+{
+    /** Input is in an undefined state. */
+    INPUT_STS_UNDEFINED = 0,
+    /** Input was written (partially, see cbProcessed). */
+    INPUT_STS_WRITTEN = 1,
+    /** Input failed with an error (see flags for rc). */
+    INPUT_STS_ERROR = 20,
+    /** Process has abandoned / terminated input handling. */
+    INPUT_STS_TERMINATED = 21,
+    /** Too much input data. */
+    INPUT_STS_OVERFLOW = 30
+};
+
+
+
+} /* namespace guestControl */
+
+#endif /* ___VBox_GuestHost_GuestControl_h */
+
Index: /trunk/include/VBox/HostServices/GuestControlSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 60621)
+++ /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 60622)
@@ -1,2 +1,3 @@
+/* $Id$ */
 /** @file
  * Guest control service - Common header for host service and guest clients.
@@ -4,5 +5,5 @@
 
 /*
- * Copyright (C) 2011-2015 Oracle Corporation
+ * Copyright (C) 2011-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -82,134 +83,4 @@
 
 /**
- * Process status when executed in the guest.
- */
-enum eProcessStatus
-{
-    /** Process is in an undefined state. */
-    PROC_STS_UNDEFINED = 0,
-    /** Process has been started. */
-    PROC_STS_STARTED = 1,
-    /** Process terminated normally. */
-    PROC_STS_TEN = 2,
-    /** Process terminated via signal. */
-    PROC_STS_TES = 3,
-    /** Process terminated abnormally. */
-    PROC_STS_TEA = 4,
-    /** Process timed out and was killed. */
-    PROC_STS_TOK = 5,
-    /** Process timed out and was not killed successfully. */
-    PROC_STS_TOA = 6,
-    /** Service/OS is stopping, process was killed. */
-    PROC_STS_DWN = 7,
-    /** Something went wrong (error code in flags). */
-    PROC_STS_ERROR = 8
-};
-
-/** @todo r=bird: Most defines in this file needs to be scoped a little
- *        better!  For instance INPUT_FLAG_NONE is very generic. */
-
-/**
- * Input flags, set by the host. This is needed for
- * handling flags on the guest side.
- * Note: Has to match Main's ProcessInputFlag_* flags!
- */
-#define INPUT_FLAG_NONE                     0x0
-#define INPUT_FLAG_EOF                      RT_BIT(0)
-
-/**
- * Guest session creation flags.
- * Only handled internally at the moment.
- */
-#define SESSIONCREATIONFLAG_NONE            0x0
-
-/**
- * Guest directory removement flags.
- * Essentially using what IPRT's RTDIRRMREC_F_
- * defines have to offer.
- */
-#define DIRREMOVE_FLAG_RECURSIVE            RT_BIT(0)
-/** Delete the content of the directory and the directory itself. */
-#define DIRREMOVE_FLAG_CONTENT_AND_DIR      RT_BIT(1)
-/** Only delete the content of the directory, omit the directory it self. */
-#define DIRREMOVE_FLAG_CONTENT_ONLY         RT_BIT(2)
-/** Mask of valid flags. */
-#define DIRREMOVE_FLAG_VALID_MASK           UINT32_C(0x00000003)
-
-/** @name EXECUTEPROCESSFLAG_XXX Guest process creation flags.
- * @note Has to match Main's ProcessCreateFlag_* flags!
- */
-#define EXECUTEPROCESSFLAG_NONE             UINT32_C(0x0)
-#define EXECUTEPROCESSFLAG_WAIT_START       RT_BIT(0)
-#define EXECUTEPROCESSFLAG_IGNORE_ORPHANED  RT_BIT(1)
-#define EXECUTEPROCESSFLAG_HIDDEN           RT_BIT(2)
-#define EXECUTEPROCESSFLAG_NO_PROFILE       RT_BIT(3) /** @todo Rename to EXECUTEPROCESSFLAG_PROFILE in next API change. */
-#define EXECUTEPROCESSFLAG_WAIT_STDOUT      RT_BIT(4)
-#define EXECUTEPROCESSFLAG_WAIT_STDERR      RT_BIT(5)
-#define EXECUTEPROCESSFLAG_EXPAND_ARGUMENTS RT_BIT(6)
-#define EXECUTEPROCESSFLAG_UNQUOTED_ARGS    RT_BIT(7)
-/** @} */
-
-/**
- * Pipe handle IDs used internally for referencing to
- * a certain pipe buffer.
- */
-#define OUTPUT_HANDLE_ID_STDOUT_DEPRECATED  0 /* Needed for VBox hosts < 4.1.0. */
-#define OUTPUT_HANDLE_ID_STDOUT             1
-#define OUTPUT_HANDLE_ID_STDERR             2
-
-/**
- * Guest path rename flags.
- * Essentially using what IPRT's RTPATHRENAME_FLAGS_
- * defines have to offer.
- */
-/** Do not replace anything. */
-#define PATHRENAME_FLAG_NO_REPLACE          UINT32_C(0)
-/** This will replace attempt any target which isn't a directory. */
-#define PATHRENAME_FLAG_REPLACE             RT_BIT(0)
-/** Don't allow symbolic links as part of the path. */
-#define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
-/** Mask of valid flags. */
-#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
-
-/**
- * Defines for guest process array lengths.
- */
-#define GUESTPROCESS_MAX_CMD_LEN            _1K
-#define GUESTPROCESS_MAX_ARGS_LEN           _1K
-#define GUESTPROCESS_MAX_ENV_LEN            _64K
-#define GUESTPROCESS_MAX_USER_LEN           128
-#define GUESTPROCESS_MAX_PASSWORD_LEN       128
-#define GUESTPROCESS_MAX_DOMAIN_LEN         256
-
-/** @name Internal tools built into VBoxService which are used in order to
- *        accomplish tasks host<->guest.
- * @{
- */
-#define VBOXSERVICE_TOOL_CAT        "vbox_cat"
-#define VBOXSERVICE_TOOL_LS         "vbox_ls"
-#define VBOXSERVICE_TOOL_RM         "vbox_rm"
-#define VBOXSERVICE_TOOL_MKDIR      "vbox_mkdir"
-#define VBOXSERVICE_TOOL_MKTEMP     "vbox_mktemp"
-#define VBOXSERVICE_TOOL_STAT       "vbox_stat"
-/** @} */
-
-/**
- * Input status, reported by the client.
- */
-enum eInputStatus
-{
-    /** Input is in an undefined state. */
-    INPUT_STS_UNDEFINED = 0,
-    /** Input was written (partially, see cbProcessed). */
-    INPUT_STS_WRITTEN = 1,
-    /** Input failed with an error (see flags for rc). */
-    INPUT_STS_ERROR = 20,
-    /** Process has abandoned / terminated input handling. */
-    INPUT_STS_TERMINATED = 21,
-    /** Too much input data. */
-    INPUT_STS_OVERFLOW = 30
-};
-
-/**
  * Structure keeping the context of a host callback.
  */
Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 60621)
+++ /trunk/include/VBox/err.h	(revision 60622)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2015 Oracle Corporation
+ * Copyright (C) 2006-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -2659,4 +2659,8 @@
 /** A guest control object has changed its overall status. */
 #define VWRN_GSTCTL_OBJECTSTATE_CHANGED             6220
+/** Guest process is in a wrong state. */
+#define VERR_GSTCTL_PROCESS_WRONG_STATE             (-6221)
+/** Started guest process terminated with an exit code <> 0. */
+#define VWRN_GSTCTL_PROCESS_EXIT_CODE               6221
 /** @} */
 
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 60621)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 60622)
@@ -91,4 +91,7 @@
 #ifdef VBOX_WITH_VBOXSERVICE_CONTROL
 # include "VBoxServiceControl.h"
+#endif
+#ifdef VBOX_WITH_VBOXSERVICE_TOOLBOX
+# include "VBoxServiceToolBox.h"
 #endif
 
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h	(revision 60621)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2013-2015 Oracle Corporation
+ * Copyright (C) 2013-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -24,4 +24,5 @@
 
 #include <VBox/VBoxGuestLib.h>
+#include <VBox/GuestHost/GuestControl.h>
 #include <VBox/HostServices/GuestControlSvc.h>
 
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 60621)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 60622)
@@ -40,4 +40,5 @@
 #include "VBoxServiceInternal.h"
 #include "VBoxServiceControl.h"
+#include "VBoxServiceToolBox.h"
 
 using namespace guestControl;
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h	(revision 60621)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h	(revision 60622)
@@ -200,8 +200,4 @@
 #endif
 
-#ifdef VBOX_WITH_VBOXSERVICE_TOOLBOX
-extern bool                     VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
-#endif
-
 #ifdef RT_OS_WINDOWS
 # ifdef VBOX_WITH_GUEST_PROPS
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp	(revision 60621)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012-2015 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -41,7 +41,12 @@
 #include <VBox/VBoxGuestLib.h>
 #include <VBox/version.h>
+
+#include <VBox/GuestHost/GuestControl.h>
+
 #include "VBoxServiceInternal.h"
+#include "VBoxServiceToolBox.h"
 #include "VBoxServiceUtils.h"
 
+using namespace guestControl;
 
 /*********************************************************************************************************************************
@@ -78,10 +83,40 @@
 } VBOXSERVICETOOLBOXOUTPUTFLAG;
 
+/*********************************************************************************************************************************
+*   Prototypes                                                                                                                   *
+*********************************************************************************************************************************/
+static RTEXITCODE vgsvcToolboxCat(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxLs(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxRm(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxMkTemp(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxMkDir(int argc, char **argv);
+static RTEXITCODE vgsvcToolboxStat(int argc, char **argv);
 
 /*********************************************************************************************************************************
 *   Structures and Typedefs                                                                                                      *
 *********************************************************************************************************************************/
-/** Pointer to a handler function. */
+/** Pointer to a tool handler function. */
 typedef RTEXITCODE (*PFNHANDLER)(int , char **);
+
+/** Definition for a specific toolbox tool. */
+typedef struct VBOXSERVICETOOLBOXTOOL
+{
+    /** Friendly name of the tool. */
+    const char *pszName;
+    /** Main handler to be invoked to use the tool. */
+    RTEXITCODE (*pfnHandler)(int argc, char **argv);
+    /** Conversion routine to convert the tool's exit code back to an IPRT rc. Optional. */
+    int        (*pfnExitCodeConvertToRc)(RTEXITCODE rcExit);
+} VBOXSERVICETOOLBOXTOOL, *PVBOXSERVICETOOLBOXTOOL;
+
+static VBOXSERVICETOOLBOXTOOL s_aTools[] =
+{
+    { VBOXSERVICE_TOOL_CAT,    vgsvcToolboxCat   , NULL },
+    { VBOXSERVICE_TOOL_LS,     vgsvcToolboxLs    , NULL },
+    { VBOXSERVICE_TOOL_RM,     vgsvcToolboxRm    , NULL },
+    { VBOXSERVICE_TOOL_MKTEMP, vgsvcToolboxMkTemp, NULL },
+    { VBOXSERVICE_TOOL_MKDIR,  vgsvcToolboxMkDir , NULL },
+    { VBOXSERVICE_TOOL_STAT,   vgsvcToolboxStat  , NULL }
+};
 
 /**
@@ -468,5 +503,5 @@
             }
 
-            /* If not input files were defined, process stdin. */
+            /* If no input files were defined, process stdin. */
             if (RTListNodeIsFirst(&inputList, &inputList))
                 rc = vgsvcToolboxCatOutput(hInput, hOutput);
@@ -478,5 +513,29 @@
     vgsvcToolboxPathBufDestroy(&inputList);
 
-    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
+    if (RT_FAILURE(rc))
+    {
+        switch (rc)
+        {
+            case VERR_ACCESS_DENIED:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED;
+
+            case VERR_FILE_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND;
+
+            case VERR_PATH_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND;
+
+            case VERR_SHARING_VIOLATION:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION;
+
+            default:
+                AssertMsgFailed(("Exit code for %Rrc not implemented\n", rc));
+                break;
+        }
+
+        return RTEXITCODE_FAILURE;
+    }
+
+    return RTEXITCODE_SUCCESS;
 }
 
@@ -1403,10 +1462,6 @@
             if (RT_FAILURE(rc2))
             {
-/** @todo r=bird: You can get a number of other errors here, like access denied. */
                 if (!(fOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE))
-                    RTMsgError("Cannot stat for '%s': No such file or directory (%Rrc)\n", pNodeIt->pszName, rc);
-                rc = VERR_FILE_NOT_FOUND;
-                /* Do not break here -- process every element in the list
-                 * and keep failing rc. */
+                    RTMsgError("Cannot stat for '%s': %Rrc\n", pNodeIt->pszName, rc2);
             }
             else
@@ -1416,7 +1471,10 @@
                                               fOutputFlags,
                                               &objInfo);
-                if (RT_FAILURE(rc2))
-                    rc = rc2;
             }
+
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+            /* Do not break here -- process every element in the list
+             * and keep (initial) failing rc. */
         }
 
@@ -1433,46 +1491,66 @@
 
     vgsvcToolboxPathBufDestroy(&fileList);
-    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
-}
-
-
-
-/**
- * Looks up the handler for the tool give by @a pszTool.
- *
- * @returns Pointer to handler function.  NULL if not found.
+
+    if (RT_FAILURE(rc))
+    {
+        switch (rc)
+        {
+            case VERR_ACCESS_DENIED:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED;
+
+            case VERR_FILE_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND;
+
+            case VERR_PATH_NOT_FOUND:
+                return (RTEXITCODE)VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND;
+
+            default:
+                AssertMsgFailed(("Exit code for %Rrc not implemented\n", rc));
+                break;
+        }
+
+        return RTEXITCODE_FAILURE;
+    }
+
+    return RTEXITCODE_SUCCESS;
+}
+
+
+/**
+ * Looks up the tool definition entry for the tool give by @a pszTool.
+ *
+ * @returns Pointer to the tool definition.  NULL if not found.
  * @param   pszTool     The name of the tool.
  */
-static PFNHANDLER vgsvcToolboxLookUpHandler(const char *pszTool)
-{
-    static struct
-    {
-        const char *pszName;
-        RTEXITCODE (*pfnHandler)(int argc, char **argv);
-    }
-    const s_aTools[] =
-    {
-        { "cat",    vgsvcToolboxCat    },
-        { "ls",     vgsvcToolboxLs     },
-        { "rm",     vgsvcToolboxRm     },
-        { "mktemp", vgsvcToolboxMkTemp },
-        { "mkdir",  vgsvcToolboxMkDir  },
-        { "stat",   vgsvcToolboxStat   },
-    };
-
-    /* Skip optional 'vbox_' prefix. */
-    if (   pszTool[0] == 'v'
-        && pszTool[1] == 'b'
-        && pszTool[2] == 'o'
-        && pszTool[3] == 'x'
-        && pszTool[4] == '_')
-        pszTool += 5;
+static PVBOXSERVICETOOLBOXTOOL const vgsvcToolboxLookUp(const char *pszTool)
+{
+    AssertPtrReturn(pszTool, NULL);
 
     /* Do a linear search, since we don't have that much stuff in the table. */
     for (unsigned i = 0; i < RT_ELEMENTS(s_aTools); i++)
         if (!strcmp(s_aTools[i].pszName, pszTool))
-            return s_aTools[i].pfnHandler;
+            return &s_aTools[i];
 
     return NULL;
+}
+
+
+/**
+ * Converts a tool's exit code back to an IPRT error code.
+ *
+ * @return  Converted IPRT status code.
+ * @param   pszTool                 Name of the toolbox tool to convert exit code for.
+ * @param   rcExit                  The tool's exit code to convert.
+ */
+int VGSvcToolboxExitCodeConvertToRc(const char *pszTool, RTEXITCODE rcExit)
+{
+    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
+
+    PVBOXSERVICETOOLBOXTOOL pTool = vgsvcToolboxLookUp(pszTool);
+    if (pTool)
+        return pTool->pfnExitCodeConvertToRc(rcExit);
+
+    AssertMsgFailed(("Tool '%s' not found\n", pszTool));
+    return VERR_GENERAL_FAILURE; /* Lookup failed, should not happen. */
 }
 
@@ -1494,7 +1572,7 @@
      */
     AssertReturn(argc > 0, false);
-    const char *pszTool    = RTPathFilename(argv[0]);
-    PFNHANDLER  pfnHandler = vgsvcToolboxLookUpHandler(pszTool);
-    if (!pfnHandler)
+    const char              *pszTool = RTPathFilename(argv[0]);
+    PVBOXSERVICETOOLBOXTOOL  pTool   = vgsvcToolboxLookUp(pszTool);
+    if (!pTool)
     {
         /*
@@ -1507,6 +1585,6 @@
         argv += 2;
         pszTool = argv[0];
-        pfnHandler = vgsvcToolboxLookUpHandler(pszTool);
-        if (!pfnHandler)
+        pTool = vgsvcToolboxLookUp(pszTool);
+        if (!pTool)
         {
            *prcExit = RTEXITCODE_SUCCESS;
@@ -1528,5 +1606,6 @@
      */
     RTMsgSetProgName("VBoxService/%s", pszTool);
-    *prcExit = pfnHandler(argc, argv);
+    AssertPtr(pTool);
+    *prcExit = pTool->pfnHandler(argc, argv);
 
     return true;
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.h
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.h	(revision 60622)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.h	(revision 60622)
@@ -0,0 +1,29 @@
+/* $Id$ */
+/** @file
+ * VBoxService - Toolbox header for sharing defines between toolbox binary and VBoxService.
+ */
+
+/*
+ * Copyright (C) 2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___VBoxServiceToolBox_h
+#define ___VBoxServiceToolBox_h
+
+#include <VBox/GuestHost/GuestControl.h>
+
+RT_C_DECLS_BEGIN
+extern bool                     VGSvcToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
+extern int                      VGSvcToolboxExitCodeConvertToRc(const char *pszTool, RTEXITCODE rcExit);
+RT_C_DECLS_END
+
+#endif /* ___VBoxServiceToolBox_h */
+
Index: /trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 60621)
+++ /trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2011-2015 Oracle Corporation
+ * Copyright (C) 2011-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -38,4 +38,5 @@
 
 #ifdef VBOX_WITH_GUEST_CONTROL
+# include <VBox/GuestHost/GuestControl.h>
 # include <VBox/HostServices/GuestControlSvc.h>
 using namespace guestControl;
@@ -702,5 +703,5 @@
     GuestProcessStartupInfo(void)
         : mFlags(ProcessCreateFlag_None),
-          mTimeoutMS(30 * 1000 /* 30s timeout by default */),
+          mTimeoutMS(UINT32_MAX /* No timeout by default */),
           mPriority(ProcessPriority_Default) { }
 
@@ -715,4 +716,6 @@
     /** Process creation flags. */
     uint32_t                    mFlags;
+    /** Timeout (in ms) the process is allowed to run.
+     *  Specify UINT32_MAX if no timeout (unlimited run time) is given. */
     ULONG                       mTimeoutMS;
     /** Process priority. */
Index: /trunk/src/VBox/Main/include/GuestDirectoryImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestDirectoryImpl.h	(revision 60621)
+++ /trunk/src/VBox/Main/include/GuestDirectoryImpl.h	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012-2014 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -73,4 +73,5 @@
         /** The directory's ID. */
         uint32_t                   mID;
+        /** The process tool instance to use. */
         GuestProcessTool           mProcessTool;
     } mData;
Index: /trunk/src/VBox/Main/include/GuestProcessImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 60621)
+++ /trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012-2014 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -184,5 +184,23 @@
 
 /**
- * Internal class for handling a VBoxService tool ("vbox_ls", vbox_stat", ...).
+ * Structure for keeping a VBoxService toolbox tool's error info around.
+ */
+struct GuestProcessToolErrorInfo
+{
+    /** Return code from the guest side for executing the process tool. */
+    int  guestRc;
+    /** The process tool's returned exit code. */
+    LONG lExitCode;
+};
+
+/**
+ * Internal class for handling the BusyBox-like tools built into VBoxService
+ * on the guest side. It's also called the VBoxService Toolbox (tm).
+ *
+ * Those initially were necessary to guarantee execution of commands (like "ls", "cat")
+ * under the behalf of a certain guest user.
+ *
+ * This class essentially helps to wrap all the gory details like process creation,
+ * information extraction and maintaining the overall status.
  */
 class GuestProcessTool
@@ -198,4 +216,8 @@
     int Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pGuestRc);
 
+    int i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
+
+    int i_getRc(void) const;
+
     GuestProcessStream &i_getStdOut(void) { return mStdOut; }
 
@@ -206,16 +228,25 @@
     int i_waitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc);
 
-    int i_getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
-
     bool i_isRunning(void);
 
+    int i_terminatedOk(LONG *plExitCode = NULL);
+
+    int i_terminate(uint32_t uTimeoutMS, int *pGuestRc);
+
+public:
+
     static int i_run(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, int *pGuestRc);
+
+    static int i_runErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, GuestProcessToolErrorInfo &errorInfo);
 
     static int i_runEx(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
                        GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, int *pGuestRc);
 
-    int i_terminatedOk(LONG *pExitCode);
-
-    int i_terminate(uint32_t uTimeoutMS, int *pGuestRc);
+    static int i_runExErrorInfo(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
+                                GuestCtrlStreamObjects *pStrmOutObjects, uint32_t cStrmOutObjects, GuestProcessToolErrorInfo &errorInfo);
+
+    static int i_exitCodeToRc(const GuestProcessStartupInfo &startupInfo, LONG lExitCode);
+
+    static int i_exitCodeToRc(const char *pszTool, LONG lExitCode);
 
 protected:
Index: /trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 60621)
+++ /trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2014 Oracle Corporation
+ * Copyright (C) 2006-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -600,10 +600,12 @@
                 hr = E_OUTOFMEMORY;
             }
-            catch(HRESULT eHR)
+            catch(...)
             {
-                LogFlowThisFunc(("Exception was caught in the function \n"));
+                LogFlowThisFunc(("Exception was caught in the function\n"));
             }
         }
     }
+
+    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     return hr;
 #endif /* VBOX_WITH_GUEST_CONTROL */
Index: /trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp	(revision 60621)
+++ /trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012-2015 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -322,7 +322,5 @@
         && !mData.mProcessTool.i_isRunning())
     {
-        rc = mData.mProcessTool.i_terminatedOk(NULL /* Exit code */);
-        if (rc == VERR_NOT_EQUAL)
-            rc = VERR_ACCESS_DENIED;
+        rc = mData.mProcessTool.i_terminatedOk();
     }
 
@@ -373,7 +371,7 @@
                 break;
 
-            case VERR_ACCESS_DENIED:
-                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
-                              mData.mOpenInfo.mPath.c_str());
+            case VWRN_GSTCTL_PROCESS_EXIT_CODE:
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: %Rrc"),
+                              mData.mOpenInfo.mPath.c_str(), mData.mProcessTool.i_getRc());
                 break;
 
Index: /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 60621)
+++ /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 60622)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012-2015 Oracle Corporation
+ * Copyright (C) 2012-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -543,8 +543,4 @@
             break;
 
-        case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
-            strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
-            break;
-
         case VERR_NOT_FOUND:
             strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
@@ -1950,16 +1946,19 @@
     int vrc = pSession->i_processCreateExInternal(mStartupInfo, pProcess);
     if (RT_SUCCESS(vrc))
+    {
+        int guestRc;
         vrc = fAsync
             ? pProcess->i_startProcessAsync()
-            : pProcess->i_startProcess(30 * 1000 /* 30s timeout */, pGuestRc);
-
-    if (   RT_SUCCESS(vrc)
-        && !fAsync
-        && (   pGuestRc
-            && RT_FAILURE(*pGuestRc)
+            : pProcess->i_startProcess(30 * 1000 /* 30s timeout */, &guestRc);
+
+        if (   RT_SUCCESS(vrc)
+            && !fAsync
+            && RT_FAILURE(guestRc)
            )
-       )
-    {
-        vrc = VERR_GSTCTL_GUEST_ERROR;
+        {
+            if (pGuestRc)
+                *pGuestRc = guestRc;
+            vrc = VERR_GSTCTL_GUEST_ERROR;
+        }
     }
 
@@ -1993,4 +1992,13 @@
 }
 
+int GuestProcessTool::i_getRc(void) const
+{
+    LONG exitCode;
+    HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
+    Assert(SUCCEEDED(hr));
+
+    return GuestProcessTool::i_exitCodeToRc(mStartupInfo, exitCode);
+}
+
 bool GuestProcessTool::i_isRunning(void)
 {
@@ -2012,11 +2020,63 @@
 
 /* static */
-int GuestProcessTool::i_run(      GuestSession            *pGuestSession,
-                            const GuestProcessStartupInfo &startupInfo,
-                            int                           *pGuestRc)
-{
-    return i_runEx(pGuestSession, startupInfo,
-                   NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
-                   pGuestRc);
+int GuestProcessTool::i_run(      GuestSession              *pGuestSession,
+                            const GuestProcessStartupInfo   &startupInfo,
+                                  int                       *pGuestRc /* = NULL */)
+{
+    int guestRc;
+
+    GuestProcessToolErrorInfo errorInfo;
+    int vrc = i_runErrorInfo(pGuestSession, startupInfo, errorInfo);
+    if (RT_SUCCESS(vrc))
+    {
+        if (errorInfo.guestRc == VWRN_GSTCTL_PROCESS_EXIT_CODE)
+        {
+            guestRc = GuestProcessTool::i_exitCodeToRc(startupInfo, errorInfo.lExitCode);
+        }
+        else
+            guestRc = errorInfo.guestRc;
+
+        if (pGuestRc)
+            *pGuestRc = guestRc;
+    }
+
+    return vrc;
+}
+
+/* static */
+int GuestProcessTool::i_runErrorInfo(      GuestSession              *pGuestSession,
+                                     const GuestProcessStartupInfo   &startupInfo,
+                                           GuestProcessToolErrorInfo &errorInfo)
+{
+    return i_runExErrorInfo(pGuestSession, startupInfo,
+                            NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
+                            errorInfo);
+}
+
+/* static */
+int GuestProcessTool::i_runEx(      GuestSession              *pGuestSession,
+                              const GuestProcessStartupInfo   &startupInfo,
+                                    GuestCtrlStreamObjects    *pStrmOutObjects,
+                                    uint32_t                   cStrmOutObjects,
+                                    int                       *pGuestRc /* = NULL */)
+{
+    int guestRc;
+
+    GuestProcessToolErrorInfo errorInfo;
+    int vrc = GuestProcessTool::i_runExErrorInfo(pGuestSession, startupInfo, pStrmOutObjects, cStrmOutObjects, errorInfo);
+    if (RT_SUCCESS(vrc))
+    {
+        if (errorInfo.guestRc == VWRN_GSTCTL_PROCESS_EXIT_CODE)
+        {
+            guestRc = GuestProcessTool::i_exitCodeToRc(startupInfo, errorInfo.lExitCode);
+        }
+        else
+            guestRc = errorInfo.guestRc;
+
+        if (pGuestRc)
+            *pGuestRc = guestRc;
+    }
+
+    return vrc;
 }
 
@@ -2030,13 +2090,12 @@
  */
 /* static */
-int GuestProcessTool::i_runEx(      GuestSession            *pGuestSession,
-                              const GuestProcessStartupInfo &startupInfo,
-                                    GuestCtrlStreamObjects  *pStrmOutObjects,
-                                    uint32_t                 cStrmOutObjects,
-                                    int                     *pGuestRc)
+int GuestProcessTool::i_runExErrorInfo(      GuestSession              *pGuestSession,
+                                       const GuestProcessStartupInfo   &startupInfo,
+                                             GuestCtrlStreamObjects    *pStrmOutObjects,
+                                             uint32_t                   cStrmOutObjects,
+                                             GuestProcessToolErrorInfo &errorInfo)
 {
     GuestProcessTool procTool;
-    int guestRc;
-    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &guestRc);
+    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &errorInfo.guestRc);
     if (RT_SUCCESS(vrc))
     {
@@ -2048,5 +2107,5 @@
                 vrc = procTool.i_waitEx(  pStrmOutObjects
                                         ? GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK
-                                        : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &guestRc);
+                                        : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &errorInfo.guestRc);
                 if (pStrmOutObjects)
                     pStrmOutObjects->push_back(strmBlk);
@@ -2062,21 +2121,23 @@
     {
         /* Make sure the process runs until completion. */
-        vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+        vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &errorInfo.guestRc);
         if (RT_SUCCESS(vrc))
-        {
-            guestRc = procTool.i_terminatedOk(NULL /* Exit code */);
-            if (RT_FAILURE(guestRc))
-                vrc = VERR_GSTCTL_GUEST_ERROR;
-        }
-    }
-
-    if (pGuestRc)
-        *pGuestRc = guestRc;
-
-    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
+            errorInfo.guestRc = procTool.i_terminatedOk(&errorInfo.lExitCode);
+    }
+
+    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc, exitCode=%ld\n", vrc, errorInfo.guestRc, errorInfo.lExitCode));
     return vrc;
 }
 
-int GuestProcessTool::i_terminatedOk(LONG *pExitCode)
+/**
+ * Reports if the tool has been run correctly.
+ *
+ * @return  Will return VWRN_GSTCTL_PROCESS_EXIT_CODE if the tool process returned an exit code <> 0,
+ *          VERR_GSTCTL_PROCESS_WRONG_STATE if the tool process is in a wrong state (e.g. still running),
+ *          or VINF_SUCCESS otherwise.
+ *
+ * @param   plExitCode      Exit code of the tool. Optional.
+ */
+int GuestProcessTool::i_terminatedOk(LONG *plExitCode /* = NULL */)
 {
     Assert(!pProcess.isNull());
@@ -2086,17 +2147,16 @@
     if (!i_isRunning())
     {
-        LONG exitCode;
-        HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
+        LONG lExitCode;
+        HRESULT hr = pProcess->COMGETTER(ExitCode(&lExitCode));
         Assert(SUCCEEDED(hr));
 
-        if (pExitCode)
-            *pExitCode = exitCode;
-
-        vrc = (exitCode != 0)
-              /** @todo Special guest control rc needed! */
-            ? VERR_NOT_EQUAL : VINF_SUCCESS;
+        if (plExitCode)
+            *plExitCode = lExitCode;
+
+        vrc = (lExitCode != 0)
+            ? VWRN_GSTCTL_PROCESS_EXIT_CODE : VINF_SUCCESS;
     }
     else
-        vrc = VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
+        vrc = VERR_GSTCTL_PROCESS_WRONG_STATE;
 
     LogFlowFuncLeaveRC(vrc);
@@ -2315,2 +2375,66 @@
 }
 
+/**
+ * Converts a toolbox tool's exit code to an IPRT error code.
+ *
+ * @return  int             Returned IPRT error for the particular tool.
+ * @param   startupInfo     Startup info of the toolbox tool to lookup error code for.
+ * @param   lExitCode       The toolbox tool's exit code to lookup IPRT error for.
+ */
+/* static */
+int GuestProcessTool::i_exitCodeToRc(const GuestProcessStartupInfo &startupInfo, LONG lExitCode)
+{
+    if (startupInfo.mArguments.size() == 0)
+    {
+        AssertFailed();
+        return VERR_GENERAL_FAILURE; /* Should not happen. */
+    }
+
+    return i_exitCodeToRc(startupInfo.mArguments[0].c_str(), lExitCode);
+}
+
+/**
+ * Converts a toolbox tool's exit code to an IPRT error code.
+ *
+ * @return  int             Returned IPRT error for the particular tool.
+ * @param   pszTool         Name of toolbox tool to lookup error code for.
+ * @param   rcExit          The toolbox tool's exit code to lookup IPRT error for.
+ */
+/* static */
+int GuestProcessTool::i_exitCodeToRc(const char *pszTool, LONG lExitCode)
+{
+    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
+
+    LogFlowFunc(("%s: %ld\n", pszTool, lExitCode));
+
+    if (lExitCode == 0) /* No error? Bail out early. */
+        return VINF_SUCCESS;
+
+    if (!RTStrICmp(pszTool, VBOXSERVICE_TOOL_CAT))
+    {
+        switch (lExitCode)
+        {
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED:     return VERR_ACCESS_DENIED;
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND:    return VERR_FILE_NOT_FOUND;
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND:    return VERR_PATH_NOT_FOUND;
+            case VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION: return VERR_SHARING_VIOLATION;
+            default:
+                break;
+        }
+    }
+    else if (!RTStrICmp(pszTool, VBOXSERVICE_TOOL_STAT))
+    {
+        switch (lExitCode)
+        {
+            case VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED:    return VERR_ACCESS_DENIED;
+            case VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND:   return VERR_FILE_NOT_FOUND;
+            case VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND:   return VERR_PATH_NOT_FOUND;
+            default:
+                break;
+        }
+    }
+
+    AssertMsgFailed(("Error code %ld for tool '%s' not handled\n", lExitCode, pszTool));
+    return VERR_GENERAL_FAILURE;
+}
+
Index: /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 60621)
+++ /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 60622)
@@ -589,4 +589,6 @@
 int GuestSession::i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc)
 {
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("uFlags=%x, uTimeoutMS=%RU32\n", uFlags, uTimeoutMS));
 
@@ -651,8 +653,9 @@
 
 int GuestSession::i_directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode,
-                                          uint32_t uFlags, int *pGuestRc)
-{
-    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
-                     strPath.c_str(), uMode, uFlags));
+                                            uint32_t uFlags, int *pGuestRc)
+{
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
+    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n", strPath.c_str(), uMode, uFlags));
 
     int vrc = VINF_SUCCESS;
@@ -717,5 +720,7 @@
                                                GuestFsObjData &objData, int *pGuestRc)
 {
-    LogFlowThisFunc(("strPath=%s fFollowSymlinks=%RTbool\n", strPath.c_str(), fFollowSymlinks));
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
+    LogFlowThisFunc(("strPath=%s, fFollowSymlinks=%RTbool\n", strPath.c_str(), fFollowSymlinks));
 
     int vrc = i_fsQueryInfoInternal(strPath, fFollowSymlinks, objData, pGuestRc);
@@ -732,4 +737,6 @@
 int GuestSession::i_directoryRemoveFromList(GuestDirectory *pDirectory)
 {
+    AssertPtrReturn(pDirectory, VERR_INVALID_POINTER);
+
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
@@ -773,4 +780,5 @@
 {
     AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
 
     LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags));
@@ -812,4 +820,6 @@
                                              bool fDirectory, Utf8Str &strName, int *pGuestRc)
 {
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool\n",
                      strTemplate.c_str(), strPath.c_str(), fDirectory));
@@ -878,4 +888,6 @@
                                           ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc)
 {
+    AssertPtrReturn(pGuestRc, VERR_INVALID_POINTER);
+
     LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
                      openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
@@ -1429,6 +1441,5 @@
         *pGuestRc = guestRc;
 
-    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
-                     vrc, guestRc));
+    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
     return vrc;
 }
@@ -1482,8 +1493,4 @@
         case VERR_MAX_PROCS_REACHED:
             strError += Utf8StrFmt(tr("Maximum number of concurrent guest processes has been reached"));
-            break;
-
-        case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
-            strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
             break;
 
@@ -1935,6 +1942,6 @@
     }
 
-    /* Adjust timeout. If set to 0, we define
-     * an infinite timeout. */
+    /* Adjust timeout.
+     * If set to 0, we define an infinite timeout (unlimited process run time). */
     if (procInfo.mTimeoutMS == 0)
         procInfo.mTimeoutMS = UINT32_MAX;
@@ -2650,6 +2657,6 @@
         {
             case VERR_GSTCTL_GUEST_ERROR:
-                /** @todo Handle VERR_NOT_EQUAL (meaning process exit code <> 0). */
-                hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %s",
+                                                    GuestDirectory::i_guestErrorToString(guestRc).c_str()));
                 break;
 
Index: /trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp	(revision 60621)
+++ /trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp	(revision 60622)
@@ -297,4 +297,6 @@
     int rc;
 
+    RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
+
     RTFILE fileLocal;
     PRTFILE pFile = &fileLocal;
@@ -338,4 +340,28 @@
     }
 
+    /*
+     * Query information about our destination first.
+     */
+    int guestRc;
+    if (RT_SUCCESS(rc))
+    {
+        GuestFsObjData objData;
+        rc = pSession->i_directoryQueryInfoInternal(mDest, true /* fFollowSymlinks */, objData, &guestRc);
+        if (RT_SUCCESS(rc))
+        {
+            mDest = Utf8StrFmt("%s/%s", mDest.c_str(), RTPathFilename(mSource.c_str()));
+        }
+        else if (rc == VERR_NOT_A_DIRECTORY)
+        {
+            rc = VINF_SUCCESS;
+        }
+    }
+
+    /** @todo Implement sparse file support? */
+
+    /*
+     * Start the actual copying process by cat'ing the source file to the
+     * destination file on the guest.
+     */
     GuestProcessStartupInfo procInfo;
     procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_CAT);
@@ -347,5 +373,5 @@
 
     /* Startup process. */
-    ComObjPtr<GuestProcess> pProcess; int guestRc;
+    ComObjPtr<GuestProcess> pProcess;
     if (RT_SUCCESS(rc))
         rc = pSession->i_processCreateExInternal(procInfo, pProcess);
@@ -353,6 +379,5 @@
     {
         Assert(!pProcess.isNull());
-        rc = pProcess->i_startProcess(30 * 1000 /* 30s timeout */,
-                                      &guestRc);
+        rc = pProcess->i_startProcess(msTimeout, &guestRc);
     }
 
@@ -370,5 +395,5 @@
                                     Utf8StrFmt(GuestSession::tr(
                                     "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
-                                               mSource.c_str(), rc));
+                                    mSource.c_str(), rc));
                 break;
         }
@@ -386,6 +411,5 @@
         for (;;)
         {
-            rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn,
-                                     30 * 1000 /* Timeout */, waitRes, &guestRc);
+            rc = pProcess->i_waitFor(ProcessWaitForFlag_StdIn, msTimeout, waitRes, &guestRc);
             if (   RT_FAILURE(rc)
                 || (   waitRes != ProcessWaitResult_StdIn
@@ -418,5 +442,5 @@
                     {
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
+                                            Utf8StrFmt(GuestSession::tr("Could not read from host file \"%s\" (%Rrc)"),
                                                        mSource.c_str(), rc));
                         break;
@@ -426,5 +450,5 @@
                 {
                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                        Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" to offset %RU64 failed: %Rrc"),
+                                        Utf8StrFmt(GuestSession::tr("Seeking host file \"%s\" to offset %RU64 failed: %Rrc"),
                                                    mSource.c_str(), cbWrittenTotal, rc));
                     break;
@@ -452,5 +476,5 @@
             rc = pProcess->i_writeData(0 /* StdIn */, fFlags,
                                        byBuf, cbRead,
-                                       30 * 1000 /* Timeout */, &cbWritten, &guestRc);
+                                       msTimeout, &cbWritten, &guestRc);
             if (RT_FAILURE(rc))
             {
@@ -464,5 +488,5 @@
                     default:
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
+                                            Utf8StrFmt(GuestSession::tr("Writing to guest file \"%s\" (offset %RU64) failed: %Rrc"),
                                             mDest.c_str(), cbWrittenTotal, rc));
                         break;
@@ -503,20 +527,63 @@
                          rc, cbToRead, cbWrittenTotal, mSourceSize));
 
+        /*
+         * Wait on termination of guest process until it completed all operations.
+         */
         if (   !fCanceled
             || RT_SUCCESS(rc))
         {
+            rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &guestRc);
+            if (   RT_FAILURE(rc)
+                || waitRes != ProcessWaitResult_Terminate)
+            {
+                if (RT_FAILURE(rc))
+                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                        Utf8StrFmt(
+                                        GuestSession::tr("Waiting on termination for copying file \"%s\" to guest failed: %Rrc"),
+                                        mSource.c_str(), rc));
+                else
+                {
+                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                        Utf8StrFmt(GuestSession::tr(
+                                                   "Waiting on termination for copying file \"%s\" to guest failed with wait result %ld"),
+                                                   mSource.c_str(), waitRes));
+                    rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                }
+            }
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Newer VBoxService toolbox versions report what went wrong via exit code.
+             * So handle this first.
+             */
+            ProcessStatus_T procStatus;
+            LONG exitCode;
+            if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
+                    && procStatus != ProcessStatus_TerminatedNormally)
+                || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
+                    && exitCode != 0)
+               )
+            {
+                LogFlowThisFunc(("procStatus=%ld, exitCode=%ld\n", procStatus, exitCode));
+                rc = GuestProcessTool::i_exitCodeToRc(procInfo, exitCode);
+                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed: %Rrc"),
+                                               mSource.c_str(), rc));
+            }
             /*
              * Even if we succeeded until here make sure to check whether we really transfered
              * everything.
              */
-            if (   mSourceSize > 0
-                && cbWrittenTotal == 0)
+            else if (   mSourceSize > 0
+                     && cbWrittenTotal == 0)
             {
                 /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
                  * to the destination -> access denied. */
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                    Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
+                                    Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to guest \"%s\""),
                                                mSource.c_str(), mDest.c_str()));
-                rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                rc = VERR_ACCESS_DENIED;
             }
             else if (cbWrittenTotal < mSourceSize)
@@ -524,52 +591,11 @@
                 /* If we did not copy all let the user know. */
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
+                                    Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to guest failed (%RU64/%RU64 bytes transfered)"),
                                                mSource.c_str(), cbWrittenTotal, mSourceSize));
-                rc = VERR_GENERAL_FAILURE; /* Fudge. */
-            }
-            else
-            {
-                rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate,
-                                         30 * 1000 /* Timeout */, waitRes, &guestRc);
-                if (   RT_FAILURE(rc)
-                    || waitRes != ProcessWaitResult_Terminate)
-                {
-                    if (RT_FAILURE(rc))
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(
-                                            GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
-                                                       mSource.c_str(), rc));
-                    else
-                    {
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr(
-                                            "Waiting on termination for copying file \"%s\" failed with wait result %ld"),
-                                                       mSource.c_str(), waitRes));
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                    }
-                }
-
-                if (RT_SUCCESS(rc))
-                {
-                    ProcessStatus_T procStatus;
-                    LONG exitCode;
-                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
-                            && procStatus != ProcessStatus_TerminatedNormally)
-                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
-                            && exitCode != 0)
-                       )
-                    {
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr(
-                                            "Copying file \"%s\" failed with status %ld, exit code %ld"),
-                                                       mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                    }
-                }
-
-
-                if (RT_SUCCESS(rc))
-                    rc = setProgressSuccess();
-            }
+                rc = VERR_INTERRUPTED;
+            }
+
+            if (RT_SUCCESS(rc))
+                rc = setProgressSuccess();
         }
     } /* processCreateExInteral */
@@ -632,4 +658,6 @@
     AutoCaller autoCaller(pSession);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    RTMSINTERVAL msTimeout = 30 * 1000; /** @todo 30s timeout for all actions. Make this configurable? */
 
     /*
@@ -651,5 +679,5 @@
         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                             Utf8StrFmt(GuestSession::tr("Object \"%s\" on the guest is not a file"), mSource.c_str()));
-        rc = VERR_GENERAL_FAILURE; /* Fudge. */
+        rc = VERR_NOT_A_FILE;
     }
 
@@ -662,5 +690,5 @@
         {
             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
+                                Utf8StrFmt(GuestSession::tr("Opening/creating destination file on host \"%s\" failed: %Rrc"),
                                            mDest.c_str(), rc));
         }
@@ -681,6 +709,5 @@
             rc = pSession->i_processCreateExInternal(procInfo, pProcess);
             if (RT_SUCCESS(rc))
-                rc = pProcess->i_startProcess(30 * 1000 /* 30s timeout */,
-                                              &guestRc);
+                rc = pProcess->i_startProcess(msTimeout, &guestRc);
             if (RT_FAILURE(rc))
             {
@@ -688,6 +715,5 @@
                 {
                     case VERR_GSTCTL_GUEST_ERROR:
-                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            GuestProcess::i_guestErrorToString(guestRc));
+                        setProgressErrorMsg(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(guestRc));
                         break;
 
@@ -696,5 +722,5 @@
                                             Utf8StrFmt(GuestSession::tr(
                                            "Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
-                                                       mSource.c_str(), rc));
+                                           mSource.c_str(), rc));
                         break;
                 }
@@ -711,6 +737,5 @@
                 for (;;)
                 {
-                    rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut,
-                                             30 * 1000 /* Timeout */, waitRes, &guestRc);
+                    rc = pProcess->i_waitFor(ProcessWaitForFlag_StdOut, msTimeout, waitRes, &guestRc);
                     if (RT_FAILURE(rc))
                     {
@@ -742,5 +767,5 @@
                         uint32_t cbRead = 0; /* readData can return with VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
                         rc = pProcess->i_readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
-                                                  30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
+                                                  msTimeout, byBuf, sizeof(byBuf),
                                                   &cbRead, &guestRc);
                         if (RT_FAILURE(rc))
@@ -755,5 +780,5 @@
                                 default:
                                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                                        Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
+                                                        Utf8StrFmt(GuestSession::tr("Reading from guest file \"%s\" (offset %RU64) failed: %Rrc"),
                                                                    mSource.c_str(), cbWrittenTotal, rc));
                                     break;
@@ -769,5 +794,5 @@
                             {
                                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                                    Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
+                                                    Utf8StrFmt(GuestSession::tr("Writing to host file \"%s\" (%RU64 bytes left) failed: %Rrc"),
                                                                 mDest.c_str(), cbToRead, rc));
                                 break;
@@ -802,20 +827,59 @@
                                  rc, guestRc, waitRes, cbWrittenTotal, objData.mObjectSize, cbToRead));
 
+                /*
+                 * Wait on termination of guest process until it completed all operations.
+                 */
                 if (   !fCanceled
                     || RT_SUCCESS(rc))
                 {
+                    rc = pProcess->i_waitFor(ProcessWaitForFlag_Terminate, msTimeout, waitRes, &guestRc);
+                    if (   RT_FAILURE(rc)
+                        || waitRes != ProcessWaitResult_Terminate)
+                    {
+                        if (RT_FAILURE(rc))
+                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                                Utf8StrFmt(
+                                                GuestSession::tr("Waiting on termination for copying file \"%s\" from guest failed: %Rrc"),
+                                                mSource.c_str(), rc));
+                        else
+                        {
+                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                                Utf8StrFmt(GuestSession::tr(
+                                                           "Waiting on termination for copying file \"%s\" from guest failed with wait result %ld"),
+                                                           mSource.c_str(), waitRes));
+                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                        }
+                    }
+                }
+
+                if (RT_SUCCESS(rc))
+                {
+                    ProcessStatus_T procStatus;
+                    LONG exitCode;
+                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
+                            && procStatus != ProcessStatus_TerminatedNormally)
+                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
+                            && exitCode != 0)
+                       )
+                    {
+                        LogFlowThisFunc(("procStatus=%ld, exitCode=%ld\n", procStatus, exitCode));
+                        rc = GuestProcessTool::i_exitCodeToRc(procInfo, exitCode);
+                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+                                            Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to host failed: %Rrc"),
+                                                       mSource.c_str(), rc));
+                    }
                     /*
                      * Even if we succeeded until here make sure to check whether we really transfered
                      * everything.
                      */
-                    if (   objData.mObjectSize > 0
-                        && cbWrittenTotal == 0)
+                    else if (   objData.mObjectSize > 0
+                             && cbWrittenTotal == 0)
                     {
                         /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
                          * to the destination -> access denied. */
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Unable to write \"%s\" to \"%s\": Access denied"),
-                                            mSource.c_str(), mDest.c_str()));
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                                            Utf8StrFmt(GuestSession::tr("Writing guest file \"%s\" to host to \"%s\" failed: Access denied"),
+                                                       mSource.c_str(), mDest.c_str()));
+                        rc = VERR_ACCESS_DENIED;
                     }
                     else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
@@ -823,27 +887,11 @@
                         /* If we did not copy all let the user know. */
                         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                            Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RI64 bytes transfered)"),
-                                                       mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
-                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
+                                            Utf8StrFmt(GuestSession::tr("Copying guest file \"%s\" to host to \"%s\" failed (%RU64/%RI64 bytes transfered)"),
+                                                       mSource.c_str(), mDest.c_str(), cbWrittenTotal, objData.mObjectSize));
+                        rc = VERR_INTERRUPTED;
                     }
-                    else
-                    {
-                        ProcessStatus_T procStatus;
-                        LONG exitCode;
-                        if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
-                                && procStatus != ProcessStatus_TerminatedNormally)
-                            || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
-                                && exitCode != 0)
-                           )
-                        {
-                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                                Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
-                                                           mSource.c_str(), procStatus, exitCode)); /**@todo Add
-                                                                                                       stringify methods! */
-                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
-                        }
-                        else /* Yay, success! */
-                            rc = setProgressSuccess();
-                    }
+
+                    if (RT_SUCCESS(rc))
+                        rc = setProgressSuccess();
                 }
             }
@@ -1098,5 +1146,4 @@
     LogRel(("Running %s ...\n", procInfo.mName.c_str()));
 
-    LONG exitCode;
     GuestProcessTool procTool; int guestRc;
     int vrc = procTool.Init(pSession, procInfo, false /* Async */, &guestRc);
@@ -1106,5 +1153,5 @@
             vrc = procTool.i_wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
         if (RT_SUCCESS(vrc))
-            vrc = procTool.i_terminatedOk(&exitCode);
+            vrc = procTool.i_terminatedOk();
     }
 
@@ -1113,8 +1160,8 @@
         switch (vrc)
         {
-            case VERR_NOT_EQUAL: /** @todo Special guest control rc needed! */
+            case VWRN_GSTCTL_PROCESS_EXIT_CODE:
                 setProgressErrorMsg(VBOX_E_IPRT_ERROR,
-                                    Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest terminated with exit code %ld"),
-                                               procInfo.mExecutable.c_str(), exitCode));
+                                    Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest failed: %Rrc"),
+                                               procInfo.mExecutable.c_str(), procTool.i_getRc()));
                 break;
 
