Index: trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 49039)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 49349)
@@ -216,4 +216,5 @@
 /**
  * Creates the default release logger outputting to the specified file.
+ * Pass NULL for disabled logging.
  *
  * @return  IPRT status code.
@@ -222,4 +223,7 @@
 int VBoxServiceLogCreate(const char *pszLogFile)
 {
+    if (!pszLogFile) /* No logging wanted? Take a shortcut. */
+        return VINF_SUCCESS;
+
     /* Create release logger (stdout + file). */
     static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 49039)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 49349)
@@ -268,5 +268,6 @@
                      * The global session object then acts as a host for all
                      * started guest processes which bring all their
-                     * credentials with them with the actual execution call.
+                     * credentials with them with the actual guest process
+                     * execution call.
                      */
                     if (ctxHost.uProtocol == 1)
@@ -407,6 +408,6 @@
 
     /*
-     * Ask the host service to cancel all pending requests so that we can
-     * shutdown properly here.
+     * Ask the host service to cancel all pending requests for the main
+     * control thread so that we can shutdown properly here.
      */
     if (g_uControlSvcClientID)
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 49039)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp	(revision 49349)
@@ -525,4 +525,7 @@
                                      pProcess->uPID, PROC_STS_STARTED, 0 /* u32Flags */,
                                      NULL /* pvData */, 0 /* cbData */);
+    if (RT_FAILURE(rc))
+        VBoxServiceError("[PID %RU32]: Error reporting starting status to host, rc=%Rrc\n",
+                         pProcess->uPID, rc);
 
     /*
@@ -576,9 +579,8 @@
                         if (RT_FAILURE(rc2))
                             VBoxServiceError("Draining IPC notification pipe failed with rc=%Rrc\n", rc2);
-#ifdef DEBUG
+
+                        /* Process all pending requests. */
                         VBoxServiceVerbose(4, "[PID %RU32]: Processing pending requests ...\n",
                                            pProcess->uPID);
-#endif
-                        /* Process all pending requests. */
                         Assert(pProcess->hReqQueue != NIL_RTREQQUEUE);
                         rc2 = RTReqQueueProcess(pProcess->hReqQueue,
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 49039)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp	(revision 49349)
@@ -23,4 +23,5 @@
 #include <iprt/asm.h>
 #include <iprt/assert.h>
+#include <iprt/dir.h>
 #include <iprt/env.h>
 #include <iprt/file.h>
@@ -57,4 +58,5 @@
 static DECLCALLBACK(int)    gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser);
 /* Host -> Guest handlers. */
+static int                  gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
 static int                  gstcntlSessionHandleFileOpen(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
 static int                  gstcntlSessionHandleFileClose(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
@@ -63,4 +65,5 @@
 static int                  gstcntlSessionHandleFileSeek(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
 static int                  gstcntlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
+static int                  gstcntlSessionHandlePathRename(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
 static int                  gstcntlSessionHandleProcExec(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
 static int                  gstcntlSessionHandleProcInput(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, void *pvScratchBuf, size_t cbScratchBuf);
@@ -118,4 +121,77 @@
 
     return NULL;
+}
+
+
+static int gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession,
+                                         PVBGLR3GUESTCTRLCMDCTX pHostCtx)
+{
+    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
+
+    char szDir[RTPATH_MAX];
+    uint32_t uFlags = 0;
+
+    int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx,
+                                         /* Directory to remove. */
+                                         szDir, sizeof(szDir),
+                                         /* Flags of type DIRREMOVE_FLAG_. */
+                                         &uFlags);
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t uFlagsRemRec = 0;
+        bool fRecursive = false;
+
+        if (!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK))
+        {
+            if (uFlags & DIRREMOVE_FLAG_RECURSIVE)
+            {
+                /* Note: DIRREMOVE_FLAG_RECURSIVE must be set explicitly.
+                 *       Play safe here. */
+                fRecursive = true;
+            }
+
+            if (uFlags & DIRREMOVE_FLAG_CONTENT_AND_DIR)
+            {
+                /* Setting direct value is intentional. */
+                uFlagsRemRec = RTDIRRMREC_F_CONTENT_AND_DIR;
+            }
+
+            if (uFlags & DIRREMOVE_FLAG_CONTENT_ONLY)
+            {
+                /* Setting direct value is intentional. */
+                uFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY;
+            }
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
+
+        VBoxServiceVerbose(4, "[Dir %s]: Removing with uFlags=0x%x, fRecursive=%RTbool\n",
+                           szDir, uFlags, fRecursive);
+
+        if (RT_SUCCESS(rc))
+        {
+            /** @todo Add own recursive function (or a new IPRT function w/ callback?) to
+             *        provide guest-to-host progress reporting. */
+            if (fRecursive)
+                rc = RTDirRemoveRecursive(szDir, uFlagsRemRec);
+            else
+                rc = RTDirRemove(szDir);
+        }
+
+        /* Report back in any case. */
+        int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
+        if (RT_FAILURE(rc2))
+            VBoxServiceError("[Dir %s]: Failed to report removing status, rc=%Rrc\n",
+                             szDir, rc2);
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+#ifdef DEBUG
+    VBoxServiceVerbose(4, "Removing directory \"%s\" returned rc=%Rrc\n",
+                       szDir, rc);
+#endif
+    return rc;
 }
 
@@ -583,4 +659,57 @@
     VBoxServiceVerbose(4, "Telling file \"%s\" (handle=%RU32) returned rc=%Rrc\n",
                        pFile ? pFile->szName : "<Not found>", uHandle, rc);
+#endif
+    return rc;
+}
+
+
+static int gstcntlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession,
+                                          PVBGLR3GUESTCTRLCMDCTX pHostCtx)
+{
+    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
+
+    char szSource[RTPATH_MAX];
+    char szDest[RTPATH_MAX];
+    uint32_t uFlags = 0;
+
+    int rc = VbglR3GuestCtrlPathGetRename(pHostCtx,
+                                          szSource, sizeof(szSource),
+                                          szDest, sizeof(szDest),
+                                          /* Flags of type PATHRENAME_FLAG_. */
+                                          &uFlags);
+    if (RT_SUCCESS(rc))
+    {
+        if (uFlags & ~PATHRENAME_FLAG_VALID_MASK)
+            rc = VERR_NOT_SUPPORTED;
+
+        VBoxServiceVerbose(4, "Renaming \"%s\" to \"%s\", uFlags=0x%x, rc=%Rrc\n",
+                           szSource, szDest, uFlags, rc);
+
+        if (RT_SUCCESS(rc))
+        {
+            if (uFlags & PATHRENAME_FLAG_NO_REPLACE)
+                uFlags |= RTPATHRENAME_FLAGS_NO_REPLACE;
+
+            if (uFlags & PATHRENAME_FLAG_REPLACE)
+                uFlags |= RTPATHRENAME_FLAGS_REPLACE;
+
+            if (uFlags & PATHRENAME_FLAG_NO_SYMLINKS)
+                uFlags |= RTPATHRENAME_FLAGS_NO_SYMLINKS;
+
+            rc = RTPathRename(szSource, szDest, uFlags);
+        }
+
+        /* Report back in any case. */
+        int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
+        if (RT_FAILURE(rc2))
+            VBoxServiceError("Failed to report renaming status, rc=%Rrc\n", rc2);
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+#ifdef DEBUG
+    VBoxServiceVerbose(4, "Renaming \"%s\" to \"%s\" returned rc=%Rrc\n",
+                       szSource, szDest, rc);
 #endif
     return rc;
@@ -905,11 +1034,14 @@
     switch (uMsg)
     {
-        case HOST_CANCEL_PENDING_WAITS:
-            VBoxServiceVerbose(1, "We were asked to quit ...\n");
-            /* Fall thru is intentional. */
         case HOST_SESSION_CLOSE:
-            /* Shutdown this fork. */
+            /* Shutdown (this fork). */
             rc = GstCntlSessionClose(pSession);
             *pfShutdown = true; /* Shutdown in any case. */
+            break;
+
+        case HOST_DIR_REMOVE:
+            rc = fImpersonated
+               ? gstcntlSessionHandleDirRemove(pSession, pHostCtx)
+               : VERR_NOT_SUPPORTED;
             break;
 
@@ -984,4 +1116,10 @@
             rc = fImpersonated
                ? gstcntlSessionHandleFileTell(pSession, pHostCtx)
+               : VERR_NOT_SUPPORTED;
+            break;
+
+        case HOST_PATH_RENAME:
+            rc = fImpersonated
+               ? gstcntlSessionHandlePathRename(pSession, pHostCtx)
                : VERR_NOT_SUPPORTED;
             break;
@@ -1057,5 +1195,5 @@
     if (RT_SUCCESS(rc))
     {
-        uint32_t uTimeoutsMS = 5 * 60 * 1000; /** @todo Make this configurable. Later. */
+        uint32_t uTimeoutsMS = 30 * 1000; /** @todo Make this configurable. Later. */
         uint64_t u64TimeoutStart = 0;
 
@@ -1080,7 +1218,30 @@
                 if (!u64TimeoutStart)
                 {
-                    VBoxServiceVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit ...\n",
-                                       uSessionID);
+                    VBoxServiceVerbose(3, "Notifying guest session process (PID=%RU32, session ID=%RU32) ...\n",
+                                       pThread->hProcess, uSessionID);
+
+                    VBGLR3GUESTCTRLCMDCTX hostCtx = { uClientID,
+                                                      VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSessionID),
+                                                      pThread->StartupInfo.uProtocol, 2 /* uNumParms */ };
+                    rc = VbglR3GuestCtrlSessionClose(&hostCtx, 0 /* uFlags */);
+                    if (RT_FAILURE(rc))
+                    {
+                        VBoxServiceError("Unable to notify guest session process (PID=%RU32, session ID=%RU32), rc=%Rrc\n",
+                                         pThread->hProcess, uSessionID, rc);
+
+                        if (rc == VERR_NOT_SUPPORTED)
+                        {
+                            /* Terminate guest session process in case it's not supported by a too old host. */
+                            rc = RTProcTerminate(pThread->hProcess);
+                            VBoxServiceVerbose(3, "Terminating guest session process (PID=%RU32) ended with rc=%Rrc\n",
+                                               pThread->hProcess, rc);
+                        }
+                        break;
+                    }
+
+                    VBoxServiceVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32ms timeout) ...\n",
+                                       uSessionID, uTimeoutsMS);
                     u64TimeoutStart = RTTimeMilliTS();
+
                     continue; /* Don't waste time on waiting. */
                 }
@@ -1222,6 +1383,15 @@
                                            GUEST_SESSION_NOTIFYTYPE_STARTED, VINF_SUCCESS);
     if (RT_FAILURE(rc2))
+    {
         VBoxServiceError("Reporting session ID=%RU32 started status failed with rc=%Rrc\n",
                          pSession->StartupInfo.uSessionID, rc2);
+
+        /*
+         * If session status cannot be posted to the host for
+         * some reason, bail out.
+         */
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
 
     /* Allocate a scratch buffer for commands which also send
@@ -1284,6 +1454,9 @@
         RTMemFree(pvScratchBuf);
 
-    VBoxServiceVerbose(3, "Disconnecting client ID=%RU32 ...\n", uClientID);
-    VbglR3GuestCtrlDisconnect(uClientID);
+    if (uClientID)
+    {
+        VBoxServiceVerbose(3, "Disconnecting client ID=%RU32 ...\n", uClientID);
+        VbglR3GuestCtrlDisconnect(uClientID);
+    }
 
     VBoxServiceVerbose(3, "Session worker returned with rc=%Rrc\n", rc);
@@ -1755,4 +1928,5 @@
                         }
 #else
+                        /* Include the session thread ID in the log file name. */
                         if (RTStrAPrintf(&pszLogNewSuffix, "-%RU32-%RU32-%s",
                                          pSessionStartupInfo->uSessionID,
@@ -1793,5 +1967,5 @@
                     rc = rc2;
 #ifdef DEBUG
-                VBoxServiceVerbose(4, "rc=%Rrc, session flags=%x\n",
+                VBoxServiceVerbose(4, "Argv building rc=%Rrc, session flags=%x\n",
                                    rc, g_Session.uFlags);
                 char szParmDumpStdOut[32];
@@ -2049,4 +2223,8 @@
     int rc = VINF_SUCCESS;
 
+    /*int rc = VbglR3GuestCtrlClose
+        if (RT_FAILURE(rc))
+            VBoxServiceError("Cancelling pending waits failed; rc=%Rrc\n", rc);*/
+
     PVBOXSERVICECTRLSESSIONTHREAD pSessionThread
          = RTListGetFirst(pList, VBOXSERVICECTRLSESSIONTHREAD, Node);
@@ -2140,8 +2318,9 @@
                 break;
 
+#ifdef DEBUG
             case VBOXSERVICESESSIONOPT_THREAD_ID:
                 /* Not handled. */
                 break;
-
+#endif
             /** @todo Implement help? */
 
