Index: /trunk/include/VBox/GuestHost/GuestControl.h
===================================================================
--- /trunk/include/VBox/GuestHost/GuestControl.h	(revision 75823)
+++ /trunk/include/VBox/GuestHost/GuestControl.h	(revision 75824)
@@ -2,4 +2,6 @@
 /** @file
  * Guest Control - Common Guest and Host Code.
+ *
+ * @todo r=bird: Just merge this with GuestControlSvc.h!
  */
 
@@ -124,5 +126,5 @@
 #define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
 /** Mask of valid flags. */
-#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
+#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000003)
 /** @} */
 
Index: /trunk/include/VBox/HostServices/GuestControlSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 75823)
+++ /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 75824)
@@ -153,5 +153,5 @@
      * Gets the current status of a running process, e.g.
      * new data on stdout/stderr, process terminated etc.
-     ** Note: Legacy (VBox < 4.3) command.
+     * @note Legacy (VBox < 4.3) command.
      */
     HOST_EXEC_GET_OUTPUT = 102,
@@ -371,9 +371,14 @@
     /** Skip message.
      *
-     * This skips the current message, replying to the sender with
-     * VERR_NOT_SUPPORTED if appropriate.  No parameters.
+     * This skips the current message, replying to the main backend as best it can.
+     * Takes between zero and two parameters.  The first parameter is the 32-bit
+     * VBox status code to pass onto Main when skipping the command, defaults to
+     * VERR_NOT_SUPPORTED.  The second parameter is the 32-bit message ID of the
+     * command to skip, by default whatever is first in the queue is removed.  This
+     * is also the case if UINT32_MAX is specified.
      *
      * @retval  VINF_SUCCESS on success.
      * @retval  VERR_NOT_FOUND if no message pending.
+     * @retval  VERR_MISMATCH if the specified message ID didn't match.
      * @retval  VERR_INVALID_CLIENT_ID
      * @retval  VERR_WRONG_PARAMETER_COUNT
@@ -615,6 +620,7 @@
 
 /**
- * Guest file seeking types. Has to
- * match FileSeekType in Main.
+ * Guest file seeking types. Has to match FileSeekType in Main.
+ *
+ * @note This is not compatible with RTFileSeek, which is an unncessary pain.
  */
 enum GUEST_FILE_SEEKTYPE
Index: /trunk/include/VBox/VBoxGuestLib.h
===================================================================
--- /trunk/include/VBox/VBoxGuestLib.h	(revision 75823)
+++ /trunk/include/VBox/VBoxGuestLib.h	(revision 75824)
@@ -752,9 +752,7 @@
      *        Use a union for the HGCM stuff then. */
 
-    /** IN: HGCM client ID to use for
-     *      communication. */
+    /** IN: HGCM client ID to use for communication. */
     uint32_t uClientID;
-    /** IN/OUT: Context ID to retrieve
-     *          or to use. */
+    /** IN/OUT: Context ID to retrieve or to use. */
     uint32_t uContextID;
     /** IN: Protocol version to use. */
@@ -773,5 +771,5 @@
 VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType,
                                           void *pvPayload, uint32_t cbPayload);
-VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg);
 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId);
 VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters);
Index: /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp	(revision 75823)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp	(revision 75824)
@@ -427,12 +427,21 @@
  * @return  IPRT status code.
  * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
- */
-VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient)
+ * @param   rcSkip          The status code to pass back to Main when skipping.
+ * @param   idMsg           The message ID to skip, pass UINT32_MAX to pass any.
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg)
 {
     if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
     {
-        VBGLIOCHGCMCALL Hdr;
-        VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_SKIP, 0);
-        return VbglR3HGCMCall(&Hdr, sizeof(Hdr));
+        struct
+        {
+            VBGLIOCHGCMCALL         Hdr;
+            HGCMFunctionParameter   rcSkip;
+            HGCMFunctionParameter   idMsg;
+        } Msg;
+        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SKIP, 2);
+        VbglHGCMParmUInt32Set(&Msg.rcSkip, (uint32_t)rcSkip);
+        VbglHGCMParmUInt32Set(&Msg.idMsg, idMsg);
+        return VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
     }
 
@@ -624,7 +633,4 @@
                 *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
         }
-        /* Try get the context ID so we can inform the host about this message retrival failure. */
-        else if (Msg.context.u.value32 != HOST_SESSION_CREATE)
-            Msg.context.GetUInt32(&pCtx->uContextID);
 
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
@@ -666,5 +672,5 @@
 
 /**
- * Retrieves a HOST_SESSION_CLOSE message.
+ * Retrieves a HOST_PATH_RENAME message.
  */
 VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX     pCtx,
@@ -698,4 +704,5 @@
             Msg.flags.GetUInt32(pfFlags);
         }
+
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
     return rc;
@@ -913,5 +920,9 @@
         }
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
-    return rc;
+
+    if (   rc != VERR_TOO_MUCH_DATA
+        || g_fVbglR3GuestCtrlHavePeekGetCancel)
+        return rc;
+    return VERR_BUFFER_OVERFLOW;
 }
 
@@ -1129,5 +1140,9 @@
         }
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
-    return rc;
+
+    if (   rc != VERR_TOO_MUCH_DATA
+        || g_fVbglR3GuestCtrlHavePeekGetCancel)
+        return rc;
+    return VERR_BUFFER_OVERFLOW;
 }
 
@@ -1167,5 +1182,9 @@
         }
     } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
-    return rc;
+
+    if (   rc != VERR_TOO_MUCH_DATA
+        || g_fVbglR3GuestCtrlHavePeekGetCancel)
+        return rc;
+    return VERR_BUFFER_OVERFLOW;
 }
 
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 75823)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 75824)
@@ -306,5 +306,5 @@
                     if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient))
                     {
-                        rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient);
+                        rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient, VERR_NOT_SUPPORTED, idMsg);
                         VGSvcVerbose(1, "Skipped unexpected message idMsg=%RU32 (%s), cParms=%RU32 (rc=%Rrc)\n",
                                      idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms, rc);
@@ -421,15 +421,8 @@
         }
     }
-    /*
-     * If we cannot retrieve the message, make sure to skip the command.
-     *
-     * Note! If we totally failed to get any valid context ID, the host will
-     *       not see the notification and be stuck till it times out.
-     */
     else
     {
-        VGSvcError("Error fetching guest session parameters: %Rrc\n", rc);
-        VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc);
-        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID);
+        VGSvcError("Error fetching parameters for opening guest session: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     }
     VGSvcVerbose(3, "Opening a new guest session returned rc=%Rrc\n", rc);
@@ -442,7 +435,7 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
-    uint32_t uSessionID;
+    uint32_t idSession;
     uint32_t fFlags;
-    int rc = VbglR3GuestCtrlSessionGetClose(pHostCtx, &fFlags, &uSessionID);
+    int rc = VbglR3GuestCtrlSessionGetClose(pHostCtx, &fFlags, &idSession);
     if (RT_SUCCESS(rc))
     {
@@ -452,5 +445,5 @@
         RTListForEach(&g_lstControlSessionThreads, pThread, VBOXSERVICECTRLSESSIONTHREAD, Node)
         {
-            if (pThread->StartupInfo.uSessionID == uSessionID)
+            if (pThread->StartupInfo.uSessionID == idSession)
             {
                 rc = VGSvcGstCtrlSessionThreadDestroy(pThread, fFlags);
@@ -458,5 +451,6 @@
             }
         }
-#if 0
+
+#if 0 /** @todo A bit of a mess here as this message goes to both to this process (master) and the session process. */
         if (RT_FAILURE(rc))
         {
@@ -473,8 +467,11 @@
         }
 #endif
-        VGSvcVerbose(2, "Closing guest session %RU32 returned rc=%Rrc\n", uSessionID, rc);
+        VGSvcVerbose(2, "Closing guest session %RU32 returned rc=%Rrc\n", idSession, rc);
     }
     else
-        VGSvcError("Closing guest session %RU32 failed with rc=%Rrc\n", uSessionID, rc);
+    {
+        VGSvcError("Error fetching parameters for closing guest session: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 75823)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 75824)
@@ -62,4 +62,28 @@
 
 
+/**
+ * Helper that grows the scratch buffer.
+ * @returns Success indicator.
+ */
+static bool vgsvcGstCtrlSessionGrowScratchBuf(void **ppvScratchBuf, uint32_t *pcbScratchBuf, uint32_t cbMinBuf)
+{
+    uint32_t cbNew = *pcbScratchBuf * 2;
+    if (   cbNew    <= VMMDEV_MAX_HGCM_DATA_SIZE
+        && cbMinBuf <= VMMDEV_MAX_HGCM_DATA_SIZE)
+    {
+        while (cbMinBuf > cbNew)
+            cbNew *= 2;
+        void *pvNew = RTMemRealloc(*ppvScratchBuf, cbNew);
+        if (pvNew)
+        {
+            *ppvScratchBuf = pvNew;
+            *pcbScratchBuf = cbNew;
+            return true;
+        }
+    }
+    return false;
+}
+
+
 
 static int vgsvcGstCtrlSessionFileDestroy(PVBOXSERVICECTRLFILE pFile)
@@ -102,15 +126,15 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
-    char szDir[RTPATH_MAX];
-    uint32_t fFlags = 0;
-
-    int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx,
-                                         /* Directory to remove. */
-                                         szDir, sizeof(szDir),
-                                         /* Flags of type DIRREMOVE_FLAG_. */
-                                         &fFlags);
-    if (RT_SUCCESS(rc))
-    {
-        AssertReturn(!(fFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
+    /*
+     * Retrieve the message.
+     */
+    char        szDir[RTPATH_MAX];
+    uint32_t    fFlags; /* DIRREMOVE_FLAG_XXX */
+    int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx, szDir, sizeof(szDir), &fFlags);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Do some validating before executing the job.
+         */
         if (!(fFlags & ~DIRREMOVE_FLAG_VALID_MASK))
         {
@@ -120,26 +144,38 @@
                 if (fFlags & DIRREMOVE_FLAG_CONTENT_ONLY)
                     fFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY;
-
                 rc = RTDirRemoveRecursive(szDir, fFlagsRemRec);
+                VGSvcVerbose(4, "[Dir %s]: rmdir /s (%#x) -> rc=%Rrc\n", szDir, fFlags, rc);
             }
-            else /* Only delete directory if not empty. */
+            else
+            {
+                /* Only delete directory if not empty. */
                 rc = RTDirRemove(szDir);
+                VGSvcVerbose(4, "[Dir %s]: rmdir (%#x), rc=%Rrc\n", szDir, fFlags, rc);
+            }
         }
         else
+        {
+            VGSvcError("[Dir %s]: Unsupported flags: %#x (all %#x)\n", szDir, (fFlags & ~DIRREMOVE_FLAG_VALID_MASK), fFlags);
             rc = VERR_NOT_SUPPORTED;
-
-        VGSvcVerbose(4, "[Dir %s]: Removing with fFlags=0x%x, rc=%Rrc\n", szDir, fFlags, rc);
-
-        /* Report back in any case. */
+        }
+
+        /*
+         * Report result back to host.
+         */
         int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("[Dir %s]: Failed to report removing status, rc=%Rrc\n", szDir, rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-#ifdef DEBUG
-    VGSvcVerbose(4, "Removing directory '%s' returned rc=%Rrc\n", szDir, rc);
-#endif
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for rmdir operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
+
+    VGSvcVerbose(6, "Removing directory '%s' returned rc=%Rrc\n", szDir, rc);
     return rc;
 }
@@ -151,12 +187,14 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
-    char szFile[RTPATH_MAX];
-    char szAccess[64];
-    char szDisposition[64];
-    char szSharing[64];
+    /*
+     * Retrieve the message.
+     */
+    char     szFile[RTPATH_MAX];
+    char     szAccess[64];
+    char     szDisposition[64];
+    char     szSharing[64];
     uint32_t uCreationMode = 0;
-    uint64_t offOpen = 0;
-    uint32_t uHandle = 0;
-
+    uint64_t offOpen       = 0;
+    uint32_t uHandle       = 0;
     int rc = VbglR3GuestCtrlFileGetOpen(pHostCtx,
                                         /* File to open. */
@@ -179,43 +217,51 @@
         if (pFile)
         {
-            if (!strlen(szFile))
-                rc = VERR_INVALID_PARAMETER;
-
-            if (RT_SUCCESS(rc))
+            pFile->hFile = NIL_RTFILE; /* Not zero or NULL! */
+            if (szFile[0])
             {
                 RTStrCopy(pFile->szName, sizeof(pFile->szName), szFile);
 
+/** @todo
+ * Implement szSharing!
+ */
                 uint64_t fFlags;
                 rc = RTFileModeToFlagsEx(szAccess, szDisposition, NULL /* pszSharing, not used yet */, &fFlags);
                 VGSvcVerbose(4, "[File %s] Opening with fFlags=0x%x, rc=%Rrc\n", pFile->szName, fFlags, rc);
-
                 if (RT_SUCCESS(rc))
+                {
                     rc = RTFileOpen(&pFile->hFile, pFile->szName, fFlags);
-                if (   RT_SUCCESS(rc)
-                    && offOpen)
-                {
-                    /* Seeking is optional. However, the whole operation
-                     * will fail if we don't succeed seeking to the wanted position. */
-                    rc = RTFileSeek(pFile->hFile, (int64_t)offOpen, RTFILE_SEEK_BEGIN, NULL /* Current offset */);
-                    if (RT_FAILURE(rc))
-                        VGSvcError("[File %s] Seeking to offset %RU64 failed; rc=%Rrc\n", pFile->szName, offOpen, rc);
+                    if (RT_SUCCESS(rc))
+                    {
+                        /* Seeking is optional. However, the whole operation
+                         * will fail if we don't succeed seeking to the wanted position. */
+                        if (offOpen)
+                            rc = RTFileSeek(pFile->hFile, (int64_t)offOpen, RTFILE_SEEK_BEGIN, NULL /* Current offset */);
+                        if (RT_SUCCESS(rc))
+                        {
+                            /*
+                             * Succeeded!
+                             */
+                            uHandle = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHostCtx->uContextID);
+                            pFile->uHandle = uHandle;
+                            RTListAppend(&pSession->lstFiles, &pFile->Node);
+                            VGSvcVerbose(2, "[File %s] Opened (ID=%RU32)\n", pFile->szName, pFile->uHandle);
+                        }
+                        else
+                            VGSvcError("[File %s] Seeking to offset %RU64 failed: rc=%Rrc\n", pFile->szName, offOpen, rc);
+                    }
+                    else
+                        VGSvcError("[File %s] Opening failed with rc=%Rrc\n", pFile->szName, rc);
                 }
-                else if (RT_FAILURE(rc))
-                    VGSvcError("[File %s] Opening failed with rc=%Rrc\n", pFile->szName, rc);
             }
-
-            if (RT_SUCCESS(rc))
+            else
             {
-                uHandle = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHostCtx->uContextID);
-                pFile->uHandle = uHandle;
-
-                RTListAppend(&pSession->lstFiles, &pFile->Node);
-
-                VGSvcVerbose(2, "[File %s] Opened (ID=%RU32)\n", pFile->szName, pFile->uHandle);
+                VGSvcError("[File %s] empty filename!\n");
+                rc = VERR_INVALID_NAME;
             }
 
+            /* clean up if we failed. */
             if (RT_FAILURE(rc))
             {
-                if (pFile->hFile)
+                if (pFile->hFile != NIL_RTFILE)
                     RTFileClose(pFile->hFile);
                 RTMemFree(pFile);
@@ -225,10 +271,19 @@
             rc = VERR_NO_MEMORY;
 
-        /* Report back in any case. */
+        /*
+         * Report result back to host.
+         */
         int rc2 = VbglR3GuestCtrlFileCbOpen(pHostCtx, rc, uHandle);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("[File %s]: Failed to report file open status, rc=%Rrc\n", szFile, rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for open file operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     }
 
@@ -244,4 +299,7 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the message.
+     */
     uint32_t uHandle = 0;
     int rc = VbglR3GuestCtrlFileGetClose(pHostCtx, &uHandle /* File handle to close */);
@@ -252,18 +310,28 @@
         {
             VGSvcVerbose(2, "[File %s] Closing (handle=%RU32)\n", pFile ? pFile->szName : "<Not found>", uHandle);
-
             rc = vgsvcGstCtrlSessionFileDestroy(pFile);
         }
         else
+        {
+            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
             rc = VERR_NOT_FOUND;
-
-        /* Report back in any case. */
+        }
+
+        /*
+         * Report result back to host.
+         */
         int rc2 = VbglR3GuestCtrlFileCbClose(pHostCtx, rc);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report file close status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for close file operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -271,9 +339,12 @@
 
 static int vgsvcGstCtrlSessionHandleFileRead(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
-                                             void *pvScratchBuf, size_t cbScratchBuf)
+                                             void **ppvScratchBuf, uint32_t *pcbScratchBuf)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     uint32_t uHandle = 0;
     uint32_t cbToRead;
@@ -281,42 +352,42 @@
     if (RT_SUCCESS(rc))
     {
-        void *pvDataRead = pvScratchBuf;
+        /*
+         * Locate the file and do the reading.
+         *
+         * If the request is larger than our scratch buffer, try grow it - just
+         * ignore failure as the host better respect our buffer limits.
+         */
         size_t cbRead = 0;
-
         PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
         if (pFile)
         {
-            if (cbToRead)
-            {
-                if (cbToRead > cbScratchBuf)
-                {
-                    pvDataRead = RTMemAlloc(cbToRead);
-                    if (!pvDataRead)
-                        rc = VERR_NO_MEMORY;
-                }
-
-                if (RT_LIKELY(RT_SUCCESS(rc)))
-                    rc = RTFileRead(pFile->hFile, pvDataRead, cbToRead, &cbRead);
-            }
-            else
-                rc = VERR_BUFFER_UNDERFLOW;
+            if (*pcbScratchBuf < cbToRead)
+                 vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToRead);
+
+            rc = RTFileRead(pFile->hFile, *ppvScratchBuf, RT_MIN(cbToRead, *pcbScratchBuf), &cbRead);
+            VGSvcVerbose(5, "[File %s] Read %zu/%RU32 bytes, rc=%Rrc\n", pFile->szName, cbRead, cbToRead, rc);
         }
         else
+        {
+            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
             rc = VERR_NOT_FOUND;
-
-        VGSvcVerbose(4, "[File %s] Read %zu/%RU32 bytes, rc=%Rrc\n", pFile ? pFile->szName : "<Not found>", cbRead, cbToRead, rc);
-
-        /* Report back in any case. */
-        int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, pvDataRead, (uint32_t)cbRead);
-        if (   cbToRead > cbScratchBuf
-            && pvDataRead)
-            RTMemFree(pvDataRead);
-
+        }
+
+        /*
+         * Report result and data back to the host.
+         */
+        int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, *ppvScratchBuf, (uint32_t)cbRead);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report file read status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for file read operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -324,9 +395,12 @@
 
 static int vgsvcGstCtrlSessionHandleFileReadAt(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
-                                               void *pvScratchBuf, size_t cbScratchBuf)
+                                               void **ppvScratchBuf, uint32_t *pcbScratchBuf)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     uint32_t uHandle = 0;
     uint32_t cbToRead;
@@ -335,43 +409,42 @@
     if (RT_SUCCESS(rc))
     {
-        void *pvDataRead = pvScratchBuf;
+        /*
+         * Locate the file and do the reading.
+         *
+         * If the request is larger than our scratch buffer, try grow it - just
+         * ignore failure as the host better respect our buffer limits.
+         */
         size_t cbRead = 0;
-
         PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
         if (pFile)
         {
-            if (cbToRead)
-            {
-                if (cbToRead > cbScratchBuf)
-                {
-                    pvDataRead = RTMemAlloc(cbToRead);
-                    if (!pvDataRead)
-                        rc = VERR_NO_MEMORY;
-                }
-
-                if (RT_SUCCESS(rc))
-                    rc = RTFileReadAt(pFile->hFile, (RTFOFF)offReadAt, pvDataRead, cbToRead, &cbRead);
-
-                VGSvcVerbose(4, "[File %s] Read %zu bytes @ %RU64, rc=%Rrc\n",
-                             pFile ? pFile->szName : "<Not found>", cbRead, offReadAt, rc);
-            }
-            else
-                rc = VERR_BUFFER_UNDERFLOW;
+            if (*pcbScratchBuf < cbToRead)
+                 vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToRead);
+
+            rc = RTFileReadAt(pFile->hFile, (RTFOFF)offReadAt, *ppvScratchBuf, RT_MIN(cbToRead, *pcbScratchBuf), &cbRead);
+            VGSvcVerbose(5, "[File %s] Read %zu bytes @ %RU64, rc=%Rrc\n", pFile->szName, cbRead, offReadAt, rc);
         }
         else
+        {
+            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
             rc = VERR_NOT_FOUND;
-
-        /* Report back in any case. */
-        int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, pvDataRead, (uint32_t)cbRead);
-        if (   cbToRead > cbScratchBuf
-            && pvDataRead)
-            RTMemFree(pvDataRead);
-
+        }
+
+        /*
+         * Report result and data back to the host.
+         */
+        int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, *ppvScratchBuf, (uint32_t)cbRead);
         if (RT_FAILURE(rc2))
-            VGSvcError("Failed to report file read status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+        {
+            VGSvcError("Failed to report file read at status, rc=%Rrc\n", rc2);
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for file read at operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -379,41 +452,53 @@
 
 static int vgsvcGstCtrlSessionHandleFileWrite(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
-                                              void *pvScratchBuf, size_t cbScratchBuf)
+                                              void **ppvScratchBuf, uint32_t *pcbScratchBuf)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
-    AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER);
-
+
+    /*
+     * Retrieve the request and data to write.
+     */
     uint32_t uHandle = 0;
     uint32_t cbToWrite;
-    int rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, pvScratchBuf, (uint32_t)cbScratchBuf, &cbToWrite);
-    if (RT_SUCCESS(rc))
-    {
-        /* Make sure that we only write up to cbScratchBuf bytes. */
-        if (cbToWrite > (uint32_t)cbScratchBuf)
-            cbToWrite = (uint32_t)cbScratchBuf;
-
+    int rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite);
+    if (   rc == VERR_BUFFER_OVERFLOW
+        && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToWrite))
+        rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Locate the file and do the writing.
+         */
         size_t cbWritten = 0;
         PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
         if (pFile)
         {
-            rc = RTFileWrite(pFile->hFile, pvScratchBuf, cbToWrite, &cbWritten);
-#ifdef DEBUG
-            VGSvcVerbose(4, "[File %s] Writing pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n",
-                         pFile->szName, pvScratchBuf, cbToWrite, cbWritten, rc);
-#endif
+            rc = RTFileWrite(pFile->hFile, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), &cbWritten);
+            VGSvcVerbose(5, "[File %s] Writing %p LB %RU32 =>  %Rrc, cbWritten=%zu\n",
+                         pFile->szName, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), rc, cbWritten);
         }
         else
+        {
+            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
             rc = VERR_NOT_FOUND;
-
-        /* Report back in any case. */
+        }
+
+        /*
+         * Report result back to host.
+         */
         int rc2 = VbglR3GuestCtrlFileCbWrite(pHostCtx, rc, (uint32_t)cbWritten);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report file write status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for file write operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -421,39 +506,54 @@
 
 static int vgsvcGstCtrlSessionHandleFileWriteAt(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
-                                                void *pvScratchBuf, size_t cbScratchBuf)
+                                                void **ppvScratchBuf, uint32_t *pcbScratchBuf)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
-    AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER);
-
+
+    /*
+     * Retrieve the request and data to write.
+     */
     uint32_t uHandle = 0;
     uint32_t cbToWrite;
     uint64_t offWriteAt;
-
-    int rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, pvScratchBuf, (uint32_t)cbScratchBuf, &cbToWrite, &offWriteAt);
-    if (RT_SUCCESS(rc))
-    {
+    int rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite, &offWriteAt);
+    if (   rc == VERR_BUFFER_OVERFLOW
+        && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToWrite))
+        rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite, &offWriteAt);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Locate the file and do the writing.
+         */
         size_t cbWritten = 0;
         PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
         if (pFile)
         {
-            rc = RTFileWriteAt(pFile->hFile, (RTFOFF)offWriteAt, pvScratchBuf, cbToWrite, &cbWritten);
-#ifdef DEBUG
-            VGSvcVerbose(4, "[File %s] Writing offWriteAt=%RI64, pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n",
-                         pFile->szName, offWriteAt, pvScratchBuf, cbToWrite, cbWritten, rc);
-#endif
+            rc = RTFileWriteAt(pFile->hFile, (RTFOFF)offWriteAt, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), &cbWritten);
+            VGSvcVerbose(5, "[File %s] Writing %p LB %RU32 @ %RU64 =>  %Rrc, cbWritten=%zu\n",
+                         pFile->szName, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), offWriteAt, rc, cbWritten);
         }
         else
+        {
+            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
             rc = VERR_NOT_FOUND;
-
-        /* Report back in any case. */
+        }
+
+        /*
+         * Report result back to host.
+         */
         int rc2 = VbglR3GuestCtrlFileCbWrite(pHostCtx, rc, (uint32_t)cbWritten);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report file write status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for file write at operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -465,4 +565,7 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     uint32_t uHandle = 0;
     uint32_t uSeekMethod;
@@ -472,133 +575,155 @@
     {
         uint64_t offActual = 0;
+
+        /*
+         * Validate and convert the seek method to IPRT speak.
+         */
+        static const uint8_t s_abMethods[GUEST_FILE_SEEKTYPE_END + 1] =
+        {
+            UINT8_MAX, RTFILE_SEEK_BEGIN, UINT8_MAX, UINT8_MAX, RTFILE_SEEK_CURRENT,
+            UINT8_MAX, UINT8_MAX, UINT8_MAX, GUEST_FILE_SEEKTYPE_END
+        };
+        if (   uSeekMethod < RT_ELEMENTS(s_abMethods)
+            && s_abMethods[uSeekMethod] != UINT8_MAX)
+        {
+            /*
+             * Locate the file and do the seek.
+             */
+            PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
+            if (pFile)
+            {
+                rc = RTFileSeek(pFile->hFile, (int64_t)offSeek, s_abMethods[uSeekMethod], &offActual);
+                VGSvcVerbose(5, "[File %s]: Seeking to offSeek=%RI64, uSeekMethodIPRT=%u, rc=%Rrc\n",
+                             pFile->szName, offSeek, s_abMethods[uSeekMethod], rc);
+            }
+            else
+            {
+                VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
+                rc = VERR_NOT_FOUND;
+            }
+        }
+        else
+        {
+            VGSvcError("Invalid seek method: %#x\n", uSeekMethod);
+            rc = VERR_NOT_SUPPORTED;
+        }
+
+        /*
+         * Report result back to host.
+         */
+        int rc2 = VbglR3GuestCtrlFileCbSeek(pHostCtx, rc, offActual);
+        if (RT_FAILURE(rc2))
+        {
+            VGSvcError("Failed to report file seek status, rc=%Rrc\n", rc2);
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for file seek operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
+    return rc;
+}
+
+
+static int vgsvcGstCtrlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
+{
+    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
+
+    /*
+     * Retrieve the request.
+     */
+    uint32_t uHandle = 0;
+    int rc = VbglR3GuestCtrlFileGetTell(pHostCtx, &uHandle);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Locate the file and ask for the current position.
+         */
+        uint64_t offCurrent = 0;
         PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
         if (pFile)
         {
-            unsigned uSeekMethodIprt;
-            switch (uSeekMethod)
-            {
-                case GUEST_FILE_SEEKTYPE_BEGIN:
-                    uSeekMethodIprt = RTFILE_SEEK_BEGIN;
-                    break;
-
-                case GUEST_FILE_SEEKTYPE_CURRENT:
-                    uSeekMethodIprt = RTFILE_SEEK_CURRENT;
-                    break;
-
-                case GUEST_FILE_SEEKTYPE_END:
-                    uSeekMethodIprt = RTFILE_SEEK_END;
-                    break;
-
-                default:
-                    rc = VERR_NOT_SUPPORTED;
-                    uSeekMethodIprt = RTFILE_SEEK_BEGIN; /* Shut up MSC */
-                    break;
-            }
-
+            offCurrent = RTFileTell(pFile->hFile);
+            VGSvcVerbose(5, "[File %s]: Telling offCurrent=%RU64\n", pFile->szName, offCurrent);
+        }
+        else
+        {
+            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
+            rc = VERR_NOT_FOUND;
+        }
+
+        /*
+         * Report result back to host.
+         */
+        int rc2 = VbglR3GuestCtrlFileCbTell(pHostCtx, rc, offCurrent);
+        if (RT_FAILURE(rc2))
+        {
+            VGSvcError("Failed to report file tell status, rc=%Rrc\n", rc2);
             if (RT_SUCCESS(rc))
-            {
-                rc = RTFileSeek(pFile->hFile, (int64_t)offSeek, uSeekMethodIprt, &offActual);
-#ifdef DEBUG
-                VGSvcVerbose(4, "[File %s]: Seeking to offSeek=%RI64, uSeekMethodIPRT=%RU16, rc=%Rrc\n",
-                             pFile->szName, offSeek, uSeekMethodIprt, rc);
-#endif
-            }
-        }
-        else
-            rc = VERR_NOT_FOUND;
-
-        /* Report back in any case. */
-        int rc2 = VbglR3GuestCtrlFileCbSeek(pHostCtx, rc, offActual);
-        if (RT_FAILURE(rc2))
-            VGSvcError("Failed to report file seek status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-    return rc;
-}
-
-
-static int vgsvcGstCtrlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for file tell operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
+    return rc;
+}
+
+
+static int vgsvcGstCtrlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
-    uint32_t uHandle = 0;
-    int rc = VbglR3GuestCtrlFileGetTell(pHostCtx, &uHandle);
-    if (RT_SUCCESS(rc))
-    {
-        uint64_t uOffCurrent = 0;
-        PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
-        if (pFile)
-        {
-            uOffCurrent = RTFileTell(pFile->hFile);
-#ifdef DEBUG
-            VGSvcVerbose(4, "[File %s]: Telling uOffCurrent=%RU64\n", pFile->szName, uOffCurrent);
-#endif
+    /*
+     * Retrieve the request.
+     */
+    char     szSource[RTPATH_MAX];
+    char     szDest[RTPATH_MAX];
+    uint32_t fFlags = 0; /* PATHRENAME_FLAG_XXX */
+    int rc = VbglR3GuestCtrlPathGetRename(pHostCtx, szSource, sizeof(szSource), szDest, sizeof(szDest), &fFlags);
+    if (RT_SUCCESS(rc))
+    {
+        /*
+         * Validate the flags (kudos for using the same as IPRT), then do the renaming.
+         */
+        AssertCompile(PATHRENAME_FLAG_NO_REPLACE  == RTPATHRENAME_FLAGS_NO_REPLACE);
+        AssertCompile(PATHRENAME_FLAG_REPLACE     == RTPATHRENAME_FLAGS_REPLACE);
+        AssertCompile(PATHRENAME_FLAG_NO_SYMLINKS == RTPATHRENAME_FLAGS_NO_SYMLINKS);
+        AssertCompile(PATHRENAME_FLAG_VALID_MASK  == (RTPATHRENAME_FLAGS_NO_REPLACE | RTPATHRENAME_FLAGS_REPLACE | RTPATHRENAME_FLAGS_NO_SYMLINKS));
+        if (!(fFlags & ~PATHRENAME_FLAG_VALID_MASK))
+        {
+            VGSvcVerbose(4, "Renaming '%s' to '%s', fFlags=%#x, rc=%Rrc\n", szSource, szDest, fFlags, rc);
+            rc = RTPathRename(szSource, szDest, fFlags);
         }
         else
-            rc = VERR_NOT_FOUND;
-
-        /* Report back in any case. */
-        int rc2 = VbglR3GuestCtrlFileCbTell(pHostCtx, rc, uOffCurrent);
-        if (RT_FAILURE(rc2))
-            VGSvcError("Failed to report file tell status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-    return rc;
-}
-
-
-static int vgsvcGstCtrlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
-{
-    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
-    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
-
-    char szSource[RTPATH_MAX];
-    char szDest[RTPATH_MAX];
-    uint32_t fFlags = 0;
-
-    int rc = VbglR3GuestCtrlPathGetRename(pHostCtx,
-                                          szSource, sizeof(szSource),
-                                          szDest, sizeof(szDest),
-                                          /* Flags of type PATHRENAME_FLAG_. */
-                                          &fFlags);
-    if (RT_SUCCESS(rc))
-    {
-        if (fFlags & ~PATHRENAME_FLAG_VALID_MASK)
+        {
+            VGSvcError("Invalid rename flags: %#x\n", fFlags);
             rc = VERR_NOT_SUPPORTED;
-
-        VGSvcVerbose(4, "Renaming '%s' to '%s', fFlags=0x%x, rc=%Rrc\n", szSource, szDest, fFlags, rc);
-
-        if (RT_SUCCESS(rc))
-        {
-            unsigned fPathRenameFlags = 0;
-
-            if (fFlags & PATHRENAME_FLAG_NO_REPLACE)
-                fPathRenameFlags |= RTPATHRENAME_FLAGS_NO_REPLACE;
-
-            if (fFlags & PATHRENAME_FLAG_REPLACE)
-                fPathRenameFlags |= RTPATHRENAME_FLAGS_REPLACE;
-
-            if (fFlags & PATHRENAME_FLAG_NO_SYMLINKS)
-                fPathRenameFlags |= RTPATHRENAME_FLAGS_NO_SYMLINKS;
-
-            rc = RTPathRename(szSource, szDest, fPathRenameFlags);
-        }
-
-        /* Report back in any case. */
+        }
+
+        /*
+         * Report result back to host.
+         */
         int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report renaming status, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-#ifdef DEBUG
-    VGSvcVerbose(4, "Renaming '%s' to '%s' returned rc=%Rrc\n", szSource, szDest, rc);
-#endif
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for rename operation: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
+    VGSvcVerbose(5, "Renaming '%s' to '%s' returned rc=%Rrc\n", szSource, szDest, rc);
     return rc;
 }
@@ -617,22 +742,33 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     int rc = VbglR3GuestCtrlPathGetUserDocuments(pHostCtx);
     if (RT_SUCCESS(rc))
     {
+        /*
+         * Get the path and pass it back to the host..
+         */
         char szPath[RTPATH_MAX];
         rc = RTPathUserDocuments(szPath, sizeof(szPath));
-
 #ifdef DEBUG
         VGSvcVerbose(2, "User documents is '%s', rc=%Rrc\n", szPath, rc);
 #endif
-        /* Report back in any case. */
-        int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */,
-                                            szPath, (uint32_t)strlen(szPath) + 1 /* Include terminating zero */);
+
+        int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, szPath,
+                                            RT_SUCCESS(rc) ? (uint32_t)strlen(szPath) + 1 /* Include terminating zero */ : 0);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report user documents, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for user documents path request: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -651,7 +787,13 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     int rc = VbglR3GuestCtrlPathGetUserHome(pHostCtx);
     if (RT_SUCCESS(rc))
     {
+        /*
+         * Get the path and pass it back to the host..
+         */
         char szPath[RTPATH_MAX];
         rc = RTPathUserHome(szPath, sizeof(szPath));
@@ -661,12 +803,18 @@
 #endif
         /* Report back in any case. */
-        int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */,
-                                            szPath, (uint32_t)strlen(szPath) + 1 /* Include terminating zero */);
+        int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, szPath,
+                                            RT_SUCCESS(rc) ?(uint32_t)strlen(szPath) + 1 /* Include terminating zero */ : 0);
         if (RT_FAILURE(rc2))
+        {
             VGSvcError("Failed to report user home, rc=%Rrc\n", rc2);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for user home directory path request: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -685,35 +833,14 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
-    int rc = VINF_SUCCESS;
-    bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */
-
-    switch (pHostCtx->uProtocol)
-    {
-        case 1: /* Guest Additions < 4.3. */
-            if (pHostCtx->uNumParms != 11)
-                rc = VERR_NOT_SUPPORTED;
-            break;
-
-        case 2: /* Guest Additions >= 4.3. */
-            if (pHostCtx->uNumParms != 12)
-                rc = VERR_NOT_SUPPORTED;
-            break;
-
-        default:
-            rc = VERR_NOT_SUPPORTED;
-            break;
-    }
-
-    if (RT_SUCCESS(rc))
-    {
-        VBOXSERVICECTRLPROCSTARTUPINFO startupInfo;
-        RT_ZERO(startupInfo);
-
-        /* Initialize maximum environment block size -- needed as input
-         * parameter to retrieve the stuff from the host. On output this then
-         * will contain the actual block size. */
-        startupInfo.cbEnv = sizeof(startupInfo.szEnv);
-
-        rc = VbglR3GuestCtrlProcGetStart(pHostCtx,
+/** @todo this hardcoded stuff needs redoing.   */
+
+    /* Initialize maximum environment block size -- needed as input
+     * parameter to retrieve the stuff from the host. On output this then
+     * will contain the actual block size. */
+    VBOXSERVICECTRLPROCSTARTUPINFO startupInfo;
+    RT_ZERO(startupInfo);
+    startupInfo.cbEnv = sizeof(startupInfo.szEnv);
+
+    int rc = VbglR3GuestCtrlProcGetStart(pHostCtx,
                                          /* Command */
                                          startupInfo.szCmd,      sizeof(startupInfo.szCmd),
@@ -735,45 +862,37 @@
                                          /* Process affinity */
                                          startupInfo.uAffinity,  sizeof(startupInfo.uAffinity), &startupInfo.uNumAffinity);
+    if (RT_SUCCESS(rc))
+    {
+        VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
+                     startupInfo.szCmd, startupInfo.uFlags,
+                     startupInfo.uNumArgs ? startupInfo.szArgs : "<None>",
+                     startupInfo.uNumEnvVars ? startupInfo.szEnv : "<None>",
+                     startupInfo.uTimeLimitMS);
+
+        bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */
+        rc = VGSvcGstCtrlSessionProcessStartAllowed(pSession, &fStartAllowed);
         if (RT_SUCCESS(rc))
         {
-            VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
-                         startupInfo.szCmd, startupInfo.uFlags,
-                         startupInfo.uNumArgs ? startupInfo.szArgs : "<None>",
-                         startupInfo.uNumEnvVars ? startupInfo.szEnv : "<None>",
-                         startupInfo.uTimeLimitMS);
-
-            rc = VGSvcGstCtrlSessionProcessStartAllowed(pSession, &fStartAllowed);
-            if (RT_SUCCESS(rc))
-            {
-                if (fStartAllowed)
-                    rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID);
-                else
-                    rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */
-            }
-        }
-    }
-
-    /* In case of an error we need to notify the host to not wait forever for our response. */
-    if (RT_FAILURE(rc))
-    {
-        VGSvcError("Starting process failed with rc=%Rrc, protocol=%RU32, parameters=%RU32\n",
-                   rc, pHostCtx->uProtocol, pHostCtx->uNumParms);
-
-        /* Don't report back if we didn't supply sufficient buffer for getting
-         * the actual command -- we don't have the matching context ID. */
-        if (rc != VERR_TOO_MUCH_DATA)
-        {
-            /*
-             * Note: The context ID can be 0 because we mabye weren't able to fetch the command
-             *       from the host. The host in case has to deal with that!
-             */
-            int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /* PID, invalid */,
-                                                  PROC_STS_ERROR, rc,
-                                                  NULL /* pvData */, 0 /* cbData */);
+            if (fStartAllowed)
+                rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID);
+            else
+                rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */
+        }
+
+        /* We're responsible for signaling errors to the host (it will wait for ever otherwise). */
+        if (RT_FAILURE(rc))
+        {
+            VGSvcError("Starting process failed with rc=%Rrc, protocol=%RU32, parameters=%RU32\n",
+                       rc, pHostCtx->uProtocol, pHostCtx->uNumParms);
+            int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /*nil-PID*/, PROC_STS_ERROR, rc, NULL /*pvData*/, 0 /*cbData*/);
             if (RT_FAILURE(rc2))
                 VGSvcError("Error sending start process status to host, rc=%Rrc\n", rc2);
         }
     }
-
+    else
+    {
+        VGSvcError("Failed to retrieve parameters for process start: %Rrc (cParms=%u)\n", rc, pHostCtx->uNumParms);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -786,56 +905,37 @@
  * @param   pSession            The session which is in charge.
  * @param   pHostCtx            The host context to use.
- * @param   pvScratchBuf        The scratch buffer.
- * @param   cbScratchBuf        The scratch buffer size for retrieving the input
+ * @param   ppvScratchBuf       The scratch buffer, we may grow it.
+ * @param   pcbScratchBuf       The scratch buffer size for retrieving the input
  *                              data.
  */
 static int vgsvcGstCtrlSessionHandleProcInput(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
-                                              void *pvScratchBuf, size_t cbScratchBuf)
+                                              void **ppvScratchBuf, uint32_t *pcbScratchBuf)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
-    AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
-
+
+    /*
+     * Retrieve the data from the host.
+     */
     uint32_t uPID;
     uint32_t fFlags;
-    uint32_t cbSize;
-
-#if 0 /* unused */
-    uint32_t uStatus = INPUT_STS_UNDEFINED; /* Status sent back to the host. */
-    uint32_t cbWritten = 0; /* Number of bytes written to the guest. */
-#endif
-
-    /*
-     * Ask the host for the input data.
-     */
-    int rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags,
-                                         pvScratchBuf, (uint32_t)cbScratchBuf, &cbSize);
-    if (RT_FAILURE(rc))
-        VGSvcError("Failed to retrieve process input command for PID=%RU32, rc=%Rrc\n", uPID, rc);
-    else if (cbSize > cbScratchBuf)
-    {
-        VGSvcError("Too much process input received, rejecting: uPID=%RU32, cbSize=%RU32, cbScratchBuf=%RU32\n",
-                   uPID, cbSize, cbScratchBuf);
-        rc = VERR_TOO_MUCH_DATA;
-    }
-    else
-    {
-        /*
-         * Is this the last input block we need to deliver? Then let the pipe know ...
-         */
-        bool fPendingClose = false;
+    uint32_t cbInput;
+    int rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, *ppvScratchBuf, *pcbScratchBuf, &cbInput);
+    if (   rc == VERR_BUFFER_OVERFLOW
+        && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbInput))
+        rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, *ppvScratchBuf, *pcbScratchBuf, &cbInput);
+    if (RT_SUCCESS(rc))
+    {
         if (fFlags & INPUT_FLAG_EOF)
-        {
-            fPendingClose = true;
-#ifdef DEBUG
-            VGSvcVerbose(4, "Got last process input block for PID=%RU32 (%RU32 bytes) ...\n", uPID, cbSize);
-#endif
-        }
-
+            VGSvcVerbose(4, "Got last process input block for PID=%RU32 (%RU32 bytes) ...\n", uPID, cbInput);
+
+        /*
+         * Locate the process and feed it.
+         */
         PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
         if (pProcess)
         {
-            rc = VGSvcGstCtrlProcessHandleInput(pProcess, pHostCtx, fPendingClose, pvScratchBuf, cbSize);
+            rc = VGSvcGstCtrlProcessHandleInput(pProcess, pHostCtx, RT_BOOL(fFlags & INPUT_FLAG_EOF),
+                                                *ppvScratchBuf, RT_MIN(cbInput, *pcbScratchBuf));
             if (RT_FAILURE(rc))
                 VGSvcError("Error handling input command for PID=%RU32, rc=%Rrc\n", uPID, rc);
@@ -843,10 +943,17 @@
         }
         else
-            rc = VERR_NOT_FOUND;
-    }
-
-#ifdef DEBUG
-    VGSvcVerbose(4, "Setting input for PID=%RU32 resulted in rc=%Rrc\n", uPID, rc);
-#endif
+        {
+            VGSvcError("Could not find PID %u for feeding %u bytes to it.\n", uPID, cbInput);
+            rc = VERR_PROCESS_NOT_FOUND;
+            VbglR3GuestCtrlProcCbStatusInput(pHostCtx, uPID, INPUT_STS_ERROR, rc, 0);
+        }
+    }
+    else
+    {
+        VGSvcError("Failed to retrieve parameters for process input: %Rrc (scratch %u bytes)\n", rc, *pcbScratchBuf);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
+
+    VGSvcVerbose(6, "Feeding input to PID=%RU32 resulted in rc=%Rrc\n", uPID, rc);
     return rc;
 }
@@ -865,8 +972,10 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     uint32_t uPID;
     uint32_t uHandleID;
     uint32_t fFlags;
-
     int rc = VbglR3GuestCtrlProcGetOutput(pHostCtx, &uPID, &uHandleID, &fFlags);
 #ifdef DEBUG_andy
@@ -876,4 +985,7 @@
     if (RT_SUCCESS(rc))
     {
+        /*
+         * Locate the process and hand it the output request.
+         */
         PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
         if (pProcess)
@@ -885,5 +997,18 @@
         }
         else
-            rc = VERR_NOT_FOUND;
+        {
+            VGSvcError("Could not find PID %u for draining handle %u (%#x).\n", uPID, uHandleID, uHandleID);
+            rc = VERR_PROCESS_NOT_FOUND;
+/** @todo r=bird:
+ *
+ *  No way to report status status code for output requests?
+ *
+ */
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for process output request: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     }
 
@@ -907,8 +1032,14 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     uint32_t uPID;
     int rc = VbglR3GuestCtrlProcGetTerminate(pHostCtx, &uPID);
     if (RT_SUCCESS(rc))
     {
+        /*
+         * Locate the process and terminate it.
+         */
         PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
         if (pProcess)
@@ -919,7 +1050,19 @@
         }
         else
-            rc = VERR_NOT_FOUND;
-    }
-
+        {
+            VGSvcError("Could not find PID %u for termination.\n", uPID);
+            rc = VERR_PROCESS_NOT_FOUND;
+/** @todo r=bird:
+ *
+ *  No way to report status status code for output requests?
+ *
+ */
+        }
+    }
+    else
+    {
+        VGSvcError("Error fetching parameters for process termination request: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
 #ifdef DEBUG_andy
     VGSvcVerbose(4, "Terminating PID=%RU32 resulted in rc=%Rrc\n", uPID, rc);
@@ -934,10 +1077,18 @@
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
 
+    /*
+     * Retrieve the request.
+     */
     uint32_t uPID;
-    uint32_t uWaitFlags; uint32_t uTimeoutMS;
-
+    uint32_t uWaitFlags;
+    uint32_t uTimeoutMS;
     int rc = VbglR3GuestCtrlProcGetWaitFor(pHostCtx, &uPID, &uWaitFlags, &uTimeoutMS);
     if (RT_SUCCESS(rc))
     {
+        /*
+         * Locate the process and the realize that this call makes no sense
+         * since we'll notify the host when a process terminates anyway and
+         * hopefully don't need any additional encouragement.
+         */
         PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
         if (pProcess)
@@ -949,5 +1100,9 @@
             rc = VERR_NOT_FOUND;
     }
-
+    else
+    {
+        VGSvcError("Error fetching parameters for process wait request: %Rrc\n", rc);
+        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
+    }
     return rc;
 }
@@ -955,9 +1110,9 @@
 
 int VGSvcGstCtrlSessionHandler(PVBOXSERVICECTRLSESSION pSession, uint32_t uMsg, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
-                               void *pvScratchBuf, size_t cbScratchBuf, volatile bool *pfShutdown)
+                               void **ppvScratchBuf, uint32_t *pcbScratchBuf, volatile bool *pfShutdown)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
+    AssertPtrReturn(*ppvScratchBuf, VERR_INVALID_POINTER);
     AssertPtrReturn(pfShutdown, VERR_INVALID_POINTER);
 
@@ -990,5 +1145,5 @@
 
         case HOST_EXEC_SET_INPUT:
-            rc = vgsvcGstCtrlSessionHandleProcInput(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
+            rc = vgsvcGstCtrlSessionHandleProcInput(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
             break;
 
@@ -1017,20 +1172,20 @@
         case HOST_FILE_READ:
             if (fImpersonated)
-                rc = vgsvcGstCtrlSessionHandleFileRead(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
+                rc = vgsvcGstCtrlSessionHandleFileRead(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
             break;
 
         case HOST_FILE_READ_AT:
             if (fImpersonated)
-                rc = vgsvcGstCtrlSessionHandleFileReadAt(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
+                rc = vgsvcGstCtrlSessionHandleFileReadAt(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
             break;
 
         case HOST_FILE_WRITE:
             if (fImpersonated)
-                rc = vgsvcGstCtrlSessionHandleFileWrite(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
+                rc = vgsvcGstCtrlSessionHandleFileWrite(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
             break;
 
         case HOST_FILE_WRITE_AT:
             if (fImpersonated)
-                rc = vgsvcGstCtrlSessionHandleFileWriteAt(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
+                rc = vgsvcGstCtrlSessionHandleFileWriteAt(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
             break;
 
@@ -1063,47 +1218,54 @@
             break;
     }
-
-    if (rc == VERR_NOT_SUPPORTED)
-    {
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else if (rc != VERR_NOT_SUPPORTED) /* Note: Reply to host must must be sent by above handler. */
+        VGSvcError("Error while handling message (uMsg=%RU32, cParms=%RU32), rc=%Rrc\n", uMsg, pHostCtx->uNumParms, rc);
+    else
+    {
+        /* We must skip and notify host here as best we can... */
         VGSvcVerbose(3, "Unsupported message (uMsg=%RU32, cParms=%RU32) from host, skipping\n", uMsg, pHostCtx->uNumParms);
-
-        /*
-         * !!! HACK ALERT BEGIN !!!
-         * As peeking for the current message by VbglR3GuestCtrlMsgWaitFor() / GUEST_MSG_WAIT only gives us the message type and
-         * the number of parameters, but *not* the actual context ID the message is bound to, try to retrieve it here.
-         *
-         * This is needed in order to reply to the host with the current context ID, without breaking existing clients.
-         * Not doing this isn't fatal, but will make host clients wait longer (timing out) for not implemented messages. */
-        /** @todo Get rid of this as soon as we have a protocol bump (v4). */
-        struct HGCMMsgSkip
-        {
-            VBGLIOCHGCMCALL hdr;
-            /** UInt32: Context ID. */
-            HGCMFunctionParameter context;
-        };
-
-        HGCMMsgSkip Msg;
-        VBGL_HGCM_HDR_INIT(&Msg.hdr, pHostCtx->uClientID, GUEST_MSG_WAIT, pHostCtx->uNumParms);
-        Msg.context.SetUInt32(0);
-
-        /* Retrieve the context ID of the message which is not supported and put it in pHostCtx. */
-        int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
-        if (RT_SUCCESS(rc2))
-            Msg.context.GetUInt32(&pHostCtx->uContextID);
-
-        /* Now fake a reply to the message. */
-        rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, VERR_NOT_SUPPORTED);
-        AssertRC(rc2);
-
-        /*  !!!                !!!
-         *  !!! HACK ALERT END !!!
-         *  !!!                !!! */
-
-        /* Tell the host service to skip the message. */
-        VbglR3GuestCtrlMsgSkipOld(pHostCtx->uClientID);
-
-        rc = VINF_SUCCESS;
-    }
-    /* Note: Other replies must be reported to the host service by the appropriate command handlers above. */
+        if (VbglR3GuestCtrlSupportsOptimizations(pHostCtx->uClientID))
+            VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, VERR_NOT_SUPPORTED, uMsg);
+        else
+        {
+            /*
+             * !!! HACK ALERT BEGIN !!!
+             * As peeking for the current message by VbglR3GuestCtrlMsgWaitFor() / GUEST_MSG_WAIT only gives us the message type and
+             * the number of parameters, but *not* the actual context ID the message is bound to, try to retrieve it here.
+             *
+             * This is needed in order to reply to the host with the current context ID, without breaking existing clients.
+             * Not doing this isn't fatal, but will make host clients wait longer (timing out) for not implemented messages. */
+            /** @todo Get rid of this as soon as we have a protocol bump (v4). */
+            struct HGCMMsgSkip
+            {
+                VBGLIOCHGCMCALL hdr;
+                /** UInt32: Context ID. */
+                HGCMFunctionParameter context;
+            };
+
+            HGCMMsgSkip Msg;
+            VBGL_HGCM_HDR_INIT(&Msg.hdr, pHostCtx->uClientID, GUEST_MSG_WAIT, pHostCtx->uNumParms);
+            Msg.context.SetUInt32(0);
+
+            /* Retrieve the context ID of the message which is not supported and put it in pHostCtx. */
+            int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+            if (RT_SUCCESS(rc2))
+                Msg.context.GetUInt32(&pHostCtx->uContextID);
+
+            /* Now fake a reply to the message. */
+            rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, VERR_NOT_SUPPORTED);
+            AssertRC(rc2);
+
+            /*  !!!                !!!
+             *  !!! HACK ALERT END !!!
+             *  !!!                !!! */
+
+            /* Tell the host service to skip the message. */
+            VbglR3GuestCtrlMsgSkipOld(pHostCtx->uClientID);
+
+            rc = VINF_SUCCESS;
+        }
+    }
 
     if (RT_FAILURE(rc))
@@ -1403,9 +1565,8 @@
             /*
              * Allocate a scratch buffer for commands which also send payload data with them.
+             * This buffer may grow if the host sends us larger chunks of data.
              */
-            /** @todo Make buffer size configurable via guest properties/argv! */
             uint32_t cbScratchBuf = _64K;
-            Assert(RT_IS_POWER_OF_TWO(cbScratchBuf)); /** @todo r=bird: No idea why this needs to be the case... */
-            uint8_t *pvScratchBuf = (uint8_t *)RTMemAlloc(cbScratchBuf);
+            void    *pvScratchBuf = RTMemAlloc(cbScratchBuf);
             if (pvScratchBuf)
             {
@@ -1418,17 +1579,15 @@
                     VGSvcVerbose(3, "Waiting for host msg ...\n");
                     uint32_t uMsg = 0;
-                    uint32_t cParms = 0;
-                    rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &cParms);
+                    rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &CtxHost.uNumParms);
                     if (RT_SUCCESS(rc))
                     {
-                        VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, cParms, rc);
+                        VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, CtxHost.uNumParms, rc);
 
                         /*
-                         * Set number of parameters for current host context and pass it on to the session handler.
+                         * Pass it on to the session handler.
                          * Note! Only when handling HOST_SESSION_CLOSE is the rc used.
                          */
-                        CtxHost.uNumParms = cParms;
                         bool fShutdown = false;
-                        rc = VGSvcGstCtrlSessionHandler(pSession, uMsg, &CtxHost, pvScratchBuf, cbScratchBuf, &fShutdown);
+                        rc = VGSvcGstCtrlSessionHandler(pSession, uMsg, &CtxHost, &pvScratchBuf, &cbScratchBuf, &fShutdown);
                         if (fShutdown)
                             break;
Index: /trunk/src/VBox/HostServices/GuestControl/service.cpp
===================================================================
--- /trunk/src/VBox/HostServices/GuestControl/service.cpp	(revision 75823)
+++ /trunk/src/VBox/HostServices/GuestControl/service.cpp	(revision 75824)
@@ -62,4 +62,5 @@
 #define LOG_GROUP LOG_GROUP_GUEST_CONTROL
 #include <VBox/HostServices/GuestControlSvc.h>
+#include <VBox/GuestHost/GuestControl.h> /** @todo r=bird: Why two headers??? */
 
 #include <VBox/log.h>
@@ -915,5 +916,5 @@
     int clientMsgGet(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     int clientMsgCancel(uint32_t idClient, uint32_t cParms);
-    int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms);
+    int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     int clientSessionPrepare(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     int clientSessionCancelPrepared(uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
@@ -974,5 +975,5 @@
         pThis->mClientStateMap[idClient] = ClientState(pThis->mpHelpers, idClient);
     }
-    catch (std::bad_alloc)
+    catch (std::bad_alloc &)
     {
         return VERR_NO_MEMORY;
@@ -1417,11 +1418,26 @@
  * @param   hCall       The call handle for completing it.
  * @param   cParms      Number of parameters.
- */
-int GstCtrlService::clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms)
+ * @param   paParms     The parameters.
+ */
+int GstCtrlService::clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
 {
     /*
      * Validate the call.
      */
-    ASSERT_GUEST_RETURN(cParms == 0, VERR_WRONG_PARAMETER_COUNT);
+    ASSERT_GUEST_RETURN(cParms <= 2, VERR_WRONG_PARAMETER_COUNT);
+
+    int32_t rcSkip = VERR_NOT_SUPPORTED;
+    if (cParms >= 1)
+    {
+        ASSERT_GUEST_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE);
+        rcSkip = (int32_t)paParms[0].u.uint32;
+    }
+
+    uint32_t idMsg = UINT32_MAX;
+    if (cParms >= 2)
+    {
+        ASSERT_GUEST_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE);
+        idMsg = paParms[1].u.uint32;
+    }
 
     ClientStateMapIter ItClientState = mClientStateMap.find(idClient);
@@ -1434,31 +1450,113 @@
     if (!rClientState.mHostCmdList.empty())
     {
-        int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS);
-        if (RT_SUCCESS(rc))
-        {
-            /*
-             * Remove the command from the queue.
-             */
-            HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin();
-            rClientState.mHostCmdList.pop_front();
-
-            /*
-             * Compose a reply to the host service.
-             */
-            VBOXHGCMSVCPARM aReplyParams[4];
-            HGCMSvcSetU32(&aReplyParams[0], pFirstCmd->m_idContext);
-            HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mMsgType);
-            HGCMSvcSetU32(&aReplyParams[2], (uint32_t)VERR_NOT_SUPPORTED);
-            HGCMSvcSetPv(&aReplyParams[3], NULL, 0);
-            GstCtrlService::hostCallback(GUEST_MSG_REPLY,  RT_ELEMENTS(aReplyParams), aReplyParams);
-
-            /*
-             * Free the command.
-             */
-            pFirstCmd->SaneRelease();
-        }
-        else
-            LogFunc(("pfnCallComplete -> %Rrc\n", rc));
-        return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
+        HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin();
+        if (   pFirstCmd->mMsgType == idMsg
+            || idMsg == UINT32_MAX)
+        {
+            int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS);
+            if (RT_SUCCESS(rc))
+            {
+                /*
+                 * Remove the command from the queue.
+                 */
+                HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin();
+                if (pFirstCmd )
+                {
+                    rClientState.mHostCmdList.pop_front();
+
+                    /*
+                     * Compose a reply to the host service.
+                     */
+                    VBOXHGCMSVCPARM aReplyParams[5];
+                    HGCMSvcSetU32(&aReplyParams[0], pFirstCmd->m_idContext);
+                    switch (pFirstCmd->mMsgType)
+                    {
+                        case HOST_EXEC_CMD:
+                            HGCMSvcSetU32(&aReplyParams[1], 0);              /* pid */
+                            HGCMSvcSetU32(&aReplyParams[2], PROC_STS_ERROR); /* status */
+                            HGCMSvcSetU32(&aReplyParams[3], rcSkip);         /* flags / whatever */
+                            HGCMSvcSetPv(&aReplyParams[4], NULL, 0);         /* data buffer */
+                            GstCtrlService::hostCallback(GUEST_EXEC_STATUS, 5, aReplyParams);
+                            break;
+
+                        case HOST_SESSION_CREATE:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_SESSION_NOTIFYTYPE_ERROR);    /* type */
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                            /* result */
+                            GstCtrlService::hostCallback(GUEST_SESSION_NOTIFY, 3, aReplyParams);
+                            break;
+
+                        case HOST_EXEC_SET_INPUT:
+                            HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mParmCount >= 2 ? pFirstCmd->mpParms[1].u.uint32 : 0);
+                            HGCMSvcSetU32(&aReplyParams[2], INPUT_STS_ERROR);   /* status */
+                            HGCMSvcSetU32(&aReplyParams[3], rcSkip);            /* flags / whatever */
+                            HGCMSvcSetU32(&aReplyParams[4], 0);                 /* bytes consumed */
+                            GstCtrlService::hostCallback(GUEST_EXEC_INPUT_STATUS, 5, aReplyParams);
+                            break;
+
+                        case HOST_FILE_OPEN:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_OPEN); /* type*/
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                     /* rc */
+                            HGCMSvcSetU32(&aReplyParams[3], VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pFirstCmd->m_idContext)); /* handle */
+                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
+                            break;
+                        case HOST_FILE_CLOSE:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_ERROR); /* type*/
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
+                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 3, aReplyParams);
+                            break;
+                        case HOST_FILE_READ:
+                        case HOST_FILE_READ_AT:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_READ);  /* type */
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
+                            HGCMSvcSetPv(&aReplyParams[3], NULL, 0);                      /* data buffer */
+                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
+                            break;
+                        case HOST_FILE_WRITE:
+                        case HOST_FILE_WRITE_AT:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_WRITE); /* type */
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
+                            HGCMSvcSetU32(&aReplyParams[3], 0);                           /* bytes written */
+                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
+                            break;
+                        case HOST_FILE_SEEK:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_SEEK);  /* type */
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
+                            HGCMSvcSetU64(&aReplyParams[3], 0);                           /* actual */
+                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
+                            break;
+                        case HOST_FILE_TELL:
+                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_TELL);  /* type */
+                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
+                            HGCMSvcSetU64(&aReplyParams[3], 0);                           /* actual */
+                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
+                            break;
+
+                        case HOST_EXEC_GET_OUTPUT: /** @todo This can't be right/work. */
+                        case HOST_EXEC_TERMINATE:  /** @todo This can't be right/work. */
+                        case HOST_EXEC_WAIT_FOR:   /** @todo This can't be right/work. */
+                        case HOST_PATH_USER_DOCUMENTS:
+                        case HOST_PATH_USER_HOME:
+                        case HOST_PATH_RENAME:
+                        case HOST_DIR_REMOVE:
+                        default:
+                            HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mMsgType);
+                            HGCMSvcSetU32(&aReplyParams[2], (uint32_t)rcSkip);
+                            HGCMSvcSetPv(&aReplyParams[3], NULL, 0);
+                            GstCtrlService::hostCallback(GUEST_MSG_REPLY, 4, aReplyParams);
+                            break;
+                    }
+
+                    /*
+                     * Free the command.
+                     */
+                    pFirstCmd->SaneRelease();
+                }
+            }
+            else
+                LogFunc(("pfnCallComplete -> %Rrc\n", rc));
+            return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
+        }
+        LogFunc(("Warning: GUEST_MSG_SKIP mismatch! Found %u, caller expected %u!\n", pFirstCmd->mMsgType, idMsg));
+        return VERR_MISMATCH;
     }
     return VERR_NOT_FOUND;
@@ -2018,5 +2116,5 @@
         case GUEST_MSG_SKIP:
             LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", idClient));
-            rc = pThis->clientMsgSkip(idClient, hCall, cParms);
+            rc = pThis->clientMsgSkip(idClient, hCall, cParms, paParms);
             break;
         case GUEST_SESSION_PREPARE:
