Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 42807)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 42808)
@@ -60,6 +60,4 @@
 using namespace com;
 
-#undef VBOX_WITH_GUEST_CONTROL2
-
 /**
  * IVirtualBoxCallback implementation for handling the GuestControlCallback in
@@ -77,16 +75,8 @@
     }
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    ComPtr<IGuest> pGuest;
-#else
     ComPtr<IGuestSession> pGuestSession;
-#endif
     bool fVerbose;
     bool fDryRun;
     bool fHostToGuest;
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    Utf8Str strUsername;
-    Utf8Str strPassword;
-#endif
 } COPYCONTEXT, *PCOPYCONTEXT;
 
@@ -311,73 +301,4 @@
 }
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-/**
- * Translates a process status to a human readable
- * string.
- */
-static const char *ctrlExecProcessStatusToText(ExecuteProcessStatus_T enmStatus)
-{
-    switch (enmStatus)
-    {
-        case ExecuteProcessStatus_Started:
-            return "started";
-        case ExecuteProcessStatus_TerminatedNormally:
-            return "successfully terminated";
-        case ExecuteProcessStatus_TerminatedSignal:
-            return "terminated by signal";
-        case ExecuteProcessStatus_TerminatedAbnormally:
-            return "abnormally aborted";
-        case ExecuteProcessStatus_TimedOutKilled:
-            return "timed out";
-        case ExecuteProcessStatus_TimedOutAbnormally:
-            return "timed out, hanging";
-        case ExecuteProcessStatus_Down:
-            return "killed";
-        case ExecuteProcessStatus_Error:
-            return "error";
-        default:
-            break;
-    }
-    return "unknown";
-}
-
-static int ctrlExecProcessStatusToExitCode(ExecuteProcessStatus_T enmStatus, ULONG uExitCode)
-{
-    int vrc = EXITCODEEXEC_SUCCESS;
-    switch (enmStatus)
-    {
-        case ExecuteProcessStatus_Started:
-            vrc = EXITCODEEXEC_SUCCESS;
-            break;
-        case ExecuteProcessStatus_TerminatedNormally:
-            vrc = !uExitCode ? EXITCODEEXEC_SUCCESS : EXITCODEEXEC_CODE;
-            break;
-        case ExecuteProcessStatus_TerminatedSignal:
-            vrc = EXITCODEEXEC_TERM_SIGNAL;
-            break;
-        case ExecuteProcessStatus_TerminatedAbnormally:
-            vrc = EXITCODEEXEC_TERM_ABEND;
-            break;
-        case ExecuteProcessStatus_TimedOutKilled:
-            vrc = EXITCODEEXEC_TIMEOUT;
-            break;
-        case ExecuteProcessStatus_TimedOutAbnormally:
-            vrc = EXITCODEEXEC_TIMEOUT;
-            break;
-        case ExecuteProcessStatus_Down:
-            /* Service/OS is stopping, process was killed, so
-             * not exactly an error of the started process ... */
-            vrc = EXITCODEEXEC_DOWN;
-            break;
-        case ExecuteProcessStatus_Error:
-            vrc = EXITCODEEXEC_FAILED;
-            break;
-        default:
-            AssertMsgFailed(("Unknown exit code (%u) from guest process returned!\n", enmStatus));
-            break;
-    }
-    return vrc;
-}
-#else
 /**
  * Translates a process status to a human readable
@@ -462,5 +383,4 @@
     return vrc;
 }
-#endif
 
 static int ctrlPrintError(com::ErrorInfo &errorInfo)
@@ -480,5 +400,5 @@
         return VERR_GENERAL_FAILURE; /** @todo */
     }
-    AssertMsgFailedReturn(("Object has indicated no error (%Rrc)!?\n", errorInfo.getResultCode()),
+    AssertMsgFailedReturn(("Object has indicated no error (%Rhrc)!?\n", errorInfo.getResultCode()),
                           VERR_INVALID_PARAMETER);
 }
@@ -582,89 +502,4 @@
 }
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-/**
- * Prints the desired guest output to a stream.
- *
- * @return  IPRT status code.
- * @param   pGuest          Pointer to IGuest interface.
- * @param   uPID            PID of guest process to get the output from.
- * @param   fOutputFlags    Output flags of type ProcessOutputFlag.
- * @param   cMsTimeout      Timeout value (in ms) to wait for output.
- */
-static int ctrlExecPrintOutput(IGuest *pGuest, ULONG uPID,
-                               PRTSTREAM pStrmOutput, uint32_t fOutputFlags,
-                               RTMSINTERVAL cMsTimeout)
-{
-    AssertPtrReturn(pGuest, VERR_INVALID_POINTER);
-    AssertReturn(uPID, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(pStrmOutput, VERR_INVALID_POINTER);
-
-    SafeArray<BYTE> aOutputData;
-    ULONG cbOutputData = 0;
-
-    int vrc = VINF_SUCCESS;
-    HRESULT rc = pGuest->GetProcessOutput(uPID, fOutputFlags,
-                                          cMsTimeout,
-                                          _64K, ComSafeArrayAsOutParam(aOutputData));
-    if (FAILED(rc))
-    {
-        vrc = ctrlPrintError(pGuest, COM_IIDOF(IGuest));
-        cbOutputData = 0;
-    }
-    else
-    {
-        cbOutputData = aOutputData.size();
-        if (cbOutputData > 0)
-        {
-            BYTE *pBuf = aOutputData.raw();
-            AssertPtr(pBuf);
-            pBuf[cbOutputData - 1] = 0; /* Properly terminate buffer. */
-
-            /** @todo r=bird: Use a VFS I/O stream filter for doing this, it's a
-            *        generic problem and the new VFS APIs will handle it more
-            *        transparently. (requires writing dos2unix/unix2dos filters ofc) */
-
-            /*
-             * If aOutputData is text data from the guest process' stdout or stderr,
-             * it has a platform dependent line ending. So standardize on
-             * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
-             * Windows. Otherwise we end up with CR/CR/LF on Windows.
-             */
-
-            char *pszBufUTF8;
-            vrc = RTStrCurrentCPToUtf8(&pszBufUTF8, (const char*)aOutputData.raw());
-            if (RT_SUCCESS(vrc))
-            {
-                cbOutputData = strlen(pszBufUTF8);
-
-                ULONG cbOutputDataPrint = cbOutputData;
-                for (char *s = pszBufUTF8, *d = s;
-                     s - pszBufUTF8 < (ssize_t)cbOutputData;
-                     s++, d++)
-                {
-                    if (*s == '\r')
-                    {
-                        /* skip over CR, adjust destination */
-                        d--;
-                        cbOutputDataPrint--;
-                    }
-                    else if (s != d)
-                        *d = *s;
-                }
-
-                vrc = RTStrmWrite(pStrmOutput, pszBufUTF8, cbOutputDataPrint);
-                if (RT_FAILURE(vrc))
-                    RTMsgError("Unable to write output, rc=%Rrc\n", vrc);
-
-                RTStrFree(pszBufUTF8);
-            }
-            else
-                RTMsgError("Unable to convert output, rc=%Rrc\n", vrc);
-        }
-    }
-
-    return vrc;
-}
-#else
 /**
  * Prints the desired guest output to a stream.
@@ -684,5 +519,5 @@
 
     SafeArray<BYTE> aOutputData;
-    HRESULT rc = pProcess->Read(uHandle, _64K, 1 /* timeout */,
+    HRESULT rc = pProcess->Read(uHandle, _64K, 30 * 1000 /* 30s timeout. */,
                                 ComSafeArrayAsOutParam(aOutputData));
     if (FAILED(rc))
@@ -698,5 +533,4 @@
     return vrc;
 }
-#endif
 
 /**
@@ -713,5 +547,5 @@
         return RT_INDEFINITE_WAIT;
 
-    uint64_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs;
+    uint32_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs;
     if (u64ElapsedMs >= cMsTimeout)
         return 0;
@@ -754,21 +588,21 @@
 
     Utf8Str                 strCmd;
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    uint32_t                fExecFlags      = ExecuteProcessFlag_None;
-#else
-    com::SafeArray<ProcessCreateFlag_T> aCreateFlags;
+    com::SafeArray<ProcessCreateFlag_T>  aCreateFlags;
     com::SafeArray<ProcessWaitForFlag_T> aWaitFlags;
-#endif
-    com::SafeArray<IN_BSTR> args;
-    com::SafeArray<IN_BSTR> env;
-    Utf8Str                 strUsername;
-    Utf8Str                 strPassword;
-    Utf8Str                 strDomain;
-    RTMSINTERVAL            cMsTimeout      = 0;
-    OUTPUTTYPE              eOutputType     = OUTPUTTYPE_UNDEFINED;
-    bool                    fWaitForExit    = false;
-    bool                    fVerbose        = false;
-
-    int                     vrc             = VINF_SUCCESS;
+    com::SafeArray<IN_BSTR>              args;
+    com::SafeArray<IN_BSTR>              env;
+    Utf8Str                              strUsername;
+    Utf8Str                              strPassword;
+    Utf8Str                              strDomain;
+    RTMSINTERVAL                         cMsTimeout      = 0;
+    OUTPUTTYPE                           eOutputType     = OUTPUTTYPE_UNDEFINED;
+    bool                                 fWaitForExit    = false;
+    bool                                 fVerbose        = false;
+    int                                  vrc             = VINF_SUCCESS;
+
+    /* Wait for process start in any case. This is useful for scripting VBoxManage
+     * when relying on its overall exit code. */
+    aWaitFlags.push_back(ProcessWaitForFlag_Start);
+
     while (   (ch = RTGetOpt(&GetState, &ValueUnion))
            && RT_SUCCESS(vrc))
@@ -799,17 +633,9 @@
 
             case GETOPTDEF_EXEC_IGNOREORPHANEDPROCESSES:
-#ifndef VBOX_WITH_GUEST_CONTROL2
-                fExecFlags |= ExecuteProcessFlag_IgnoreOrphanedProcesses;
-#else
                 aCreateFlags.push_back(ProcessCreateFlag_IgnoreOrphanedProcesses);
-#endif
                 break;
 
             case GETOPTDEF_EXEC_NO_PROFILE:
-#ifndef VBOX_WITH_GUEST_CONTROL2
-                fExecFlags |= ExecuteProcessFlag_NoProfile;
-#else
                 aCreateFlags.push_back(ProcessCreateFlag_NoProfile);
-#endif
                 break;
 
@@ -855,28 +681,17 @@
 
             case GETOPTDEF_EXEC_WAITFOREXIT:
-#ifndef VBOX_WITH_GUEST_CONTROL2
-#else
                 aWaitFlags.push_back(ProcessWaitForFlag_Terminate);
-#endif
                 fWaitForExit = true;
                 break;
 
             case GETOPTDEF_EXEC_WAITFORSTDOUT:
-#ifndef VBOX_WITH_GUEST_CONTROL2
-                fExecFlags |= ExecuteProcessFlag_WaitForStdOut;
-#else
                 aCreateFlags.push_back(ProcessCreateFlag_WaitForStdOut);
                 aWaitFlags.push_back(ProcessWaitForFlag_StdOut);
-#endif
                 fWaitForExit = true;
                 break;
 
             case GETOPTDEF_EXEC_WAITFORSTDERR:
-#ifndef VBOX_WITH_GUEST_CONTROL2
-                fExecFlags |= ExecuteProcessFlag_WaitForStdErr;
-#else
                 aCreateFlags.push_back(ProcessCreateFlag_WaitForStdErr);
                 aWaitFlags.push_back(ProcessWaitForFlag_StdErr);
-#endif
                 fWaitForExit = true;
                 break;
@@ -918,164 +733,9 @@
     }
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    /* Get current time stamp to later calculate rest of timeout left. */
-    uint64_t u64StartMS = RTTimeMilliTS();
-
-    /*
-     * Execute the process.
-     */
-    ComPtr<IProgress> pProgress;
-    ULONG uPID = 0;
-    rc = pGuest->ExecuteProcess(Bstr(strCmd).raw(),
-                               fExecFlags,
-                               ComSafeArrayAsInParam(args),
-                               ComSafeArrayAsInParam(env),
-                               Bstr(strUsername).raw(),
-                               Bstr(strPassword).raw(),
-                               cMsTimeout,
-                               &uPID,
-                               pProgress.asOutParam());
-    if (FAILED(rc))
-    {
-        ctrlPrintError(pGuest, COM_IIDOF(IGuest));
-        return RTEXITCODE_FAILURE;
-    }
-
-    if (fVerbose)
-        RTPrintf("Process '%s' (PID: %u) started\n", strCmd.c_str(), uPID);
-    if (fWaitForExit)
-    {
-        if (fVerbose)
-        {
-            if (cMsTimeout) /* Wait with a certain timeout. */
-            {
-                /* Calculate timeout value left after process has been started.  */
-                uint64_t u64Elapsed = RTTimeMilliTS() - u64StartMS;
-                /* Is timeout still bigger than current difference? */
-                if (cMsTimeout > u64Elapsed)
-                    RTPrintf("Waiting for process to exit (%ums left) ...\n", cMsTimeout - u64Elapsed);
-                else
-                    RTPrintf("No time left to wait for process!\n"); /** @todo a bit misleading ... */
-            }
-            else /* Wait forever. */
-                RTPrintf("Waiting for process to exit ...\n");
-        }
-
-        /* Setup signal handling if cancelable. */
-        ASSERT(pProgress);
-        bool fCanceledAlready = false;
-        BOOL fCancelable;
-        HRESULT hrc = pProgress->COMGETTER(Cancelable)(&fCancelable);
-        if (FAILED(hrc))
-            fCancelable = FALSE;
-        if (fCancelable)
-            ctrlSignalHandlerInstall();
-
-        vrc = RTStrmSetMode(g_pStdOut, 1 /* Binary mode */, -1 /* Code set, unchanged */);
-        if (RT_FAILURE(vrc))
-            RTMsgError("Unable to set stdout's binary mode, rc=%Rrc\n", vrc);
-
-        PRTSTREAM pStream = g_pStdOut; /* StdOut by default. */
-        AssertPtr(pStream);
-
-        /* Wait for process to exit ... */
-        BOOL fCompleted    = FALSE;
-        BOOL fCanceled     = FALSE;
-        while (   SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted)))
-               && !fCompleted)
-        {
-            /* Do we need to output stuff? */
-            RTMSINTERVAL cMsTimeLeft;
-            if (fExecFlags & ExecuteProcessFlag_WaitForStdOut)
-            {
-                cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
-                if (cMsTimeLeft)
-                    vrc = ctrlExecPrintOutput(pGuest, uPID,
-                                              pStream, ProcessOutputFlag_None /* StdOut */,
-                                              cMsTimeLeft == RT_INDEFINITE_WAIT ? 0 : cMsTimeLeft);
-            }
-
-            if (fExecFlags & ExecuteProcessFlag_WaitForStdErr)
-            {
-                cMsTimeLeft = ctrlExecGetRemainingTime(u64StartMS, cMsTimeout);
-                if (cMsTimeLeft)
-                    vrc = ctrlExecPrintOutput(pGuest, uPID,
-                                              pStream, ProcessOutputFlag_StdErr /* StdErr */,
-                                              cMsTimeLeft == RT_INDEFINITE_WAIT ? 0 : cMsTimeLeft);
-            }
-
-            /* Process async cancelation */
-            if (g_fGuestCtrlCanceled && !fCanceledAlready)
-            {
-                hrc = pProgress->Cancel();
-                if (SUCCEEDED(hrc))
-                    fCanceledAlready = TRUE;
-                else
-                    g_fGuestCtrlCanceled = false;
-            }
-
-            /* Progress canceled by Main API? */
-            if (   SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled)))
-                && fCanceled)
-                break;
-
-            /* Did we run out of time? */
-            if (   cMsTimeout
-                && RTTimeMilliTS() - u64StartMS > cMsTimeout)
-            {
-                pProgress->Cancel();
-                break;
-            }
-        } /* while */
-
-        /* Undo signal handling */
-        if (fCancelable)
-            ctrlSignalHandlerUninstall();
-
-        /* Report status back to the user. */
-        if (fCanceled)
-        {
-            if (fVerbose)
-                RTPrintf("Process execution canceled!\n");
-            return EXITCODEEXEC_CANCELED;
-        }
-        else if (   fCompleted
-                 && SUCCEEDED(rc)) /* The GetProcessOutput rc. */
-        {
-            LONG iRc;
-            CHECK_ERROR_RET(pProgress, COMGETTER(ResultCode)(&iRc), rc);
-            if (FAILED(iRc))
-                vrc = ctrlPrintProgressError(pProgress);
-            else
-            {
-                ExecuteProcessStatus_T retStatus;
-                ULONG uRetExitCode, uRetFlags;
-                rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
-                if (SUCCEEDED(rc))
-                {
-                    if (fVerbose)
-                        RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, retStatus, ctrlExecProcessStatusToText(retStatus), uRetFlags);
-                    return ctrlExecProcessStatusToExitCode(retStatus, uRetExitCode);
-                }
-                else
-                {
-                    ctrlPrintError(pGuest, COM_IIDOF(IGuest));
-                    return RTEXITCODE_FAILURE;
-                }
-            }
-        }
-        else
-        {
-            if (fVerbose)
-                RTPrintf("Process execution aborted!\n");
-            return EXITCODEEXEC_TERM_ABEND;
-        }
-    }
-#else
     ComPtr<IGuestSession> pGuestSession;
     rc = pGuest->CreateSession(Bstr(strUsername).raw(),
                                Bstr(strPassword).raw(),
                                Bstr(strDomain).raw(),
-                               Bstr("guest exec").raw(),
+                               Bstr("VBoxManage Guest Control Exec").raw(),
                                pGuestSession.asOutParam());
     if (FAILED(rc))
@@ -1103,14 +763,4 @@
         return RTEXITCODE_FAILURE;
     }
-    ULONG uPID = 0;
-    rc = pProcess->COMGETTER(PID)(&uPID);
-    if (FAILED(rc))
-    {
-        ctrlPrintError(pProcess, COM_IIDOF(IProcess));
-        return RTEXITCODE_FAILURE;
-    }
-
-    if (fVerbose)
-        RTPrintf("Process '%s' (PID: %u) started\n", strCmd.c_str(), uPID);
 
     if (fWaitForExit)
@@ -1143,4 +793,6 @@
         /* Wait for process to exit ... */
         RTMSINTERVAL cMsTimeLeft = 1;
+        bool fReadStdOut, fReadStdErr;
+        fReadStdOut = fReadStdErr = false;
         bool fCompleted = false;
         while (!fCompleted && cMsTimeLeft != 0)
@@ -1155,13 +807,30 @@
             }
 
+#ifdef DEBUG
+            if (fVerbose)
+                RTPrintf("rc=%Rrc, waitResult=%ld\n", rc, waitResult);
+#endif
             switch (waitResult)
             {
+                case ProcessWaitResult_Start:
+                {
+                    if (fVerbose)
+                    {
+                        ULONG uPID = 0;
+                        rc = pProcess->COMGETTER(PID)(&uPID);
+                        if (FAILED(rc))
+                        {
+                            ctrlPrintError(pProcess, COM_IIDOF(IProcess));
+                            return RTEXITCODE_FAILURE;
+                        }
+                        RTPrintf("Process '%s' (PID: %u) started\n", strCmd.c_str(), uPID);
+                    }
+                    break;
+                }
                 case ProcessWaitResult_StdOut:
-                    /* Do we need to fetch stdout data? */
-                    vrc = ctrlExecPrintOutput(pProcess, g_pStdOut, 1 /* StdOut */);
+                    fReadStdOut = true;
                     break;
-                case ProcessWaitResult_StdErr:
-                    /* Do we need to fetch stderr data? */
-                    vrc = ctrlExecPrintOutput(pProcess, g_pStdErr, 2 /* StdErr */);
+               case ProcessWaitResult_StdErr:
+                    fReadStdErr = true;
                     break;
                 case ProcessWaitResult_Terminate:
@@ -1169,7 +838,27 @@
                     fCompleted = true;
                     break;
+               case ProcessWaitResult_Any:
+                   fReadStdOut = fReadStdErr = true;
+                   break;
                 default:
                     /* Ignore all other results, let the timeout expire */;
-            }
+                    break;
+            }
+
+            if (fReadStdOut) /* Do we need to fetch stdout data? */
+            {
+                vrc = ctrlExecPrintOutput(pProcess, g_pStdOut, 1 /* StdOut */);
+                fReadStdOut = false;
+            }
+
+            if (fReadStdErr) /* Do we need to fetch stdout data? */
+            {
+                vrc = ctrlExecPrintOutput(pProcess, g_pStdErr, 2 /* StdErr */);
+                fReadStdErr = false;
+            }
+
+            if (RT_FAILURE(vrc))
+                break;
+
         } /* while */
 
@@ -1202,5 +891,4 @@
         }
     }
-#endif
 
     return RT_FAILURE(vrc) || FAILED(rc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS;
@@ -1233,12 +921,4 @@
     PCOPYCONTEXT pContext = new COPYCONTEXT();
     AssertPtrReturn(pContext, VERR_NO_MEMORY); /**< @todo r=klaus cannot happen with new */
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    NOREF(strDomain);
-    NOREF(strSessionName);
-    pContext->pGuest = pGuest;
-
-    pContext->strUsername = strUsername;
-    pContext->strPassword = strPassword;
-#else
     ComPtr<IGuestSession> pGuestSession;
     HRESULT rc = pGuest->CreateSession(Bstr(strUsername).raw(),
@@ -1250,9 +930,8 @@
         return ctrlPrintError(pGuest, COM_IIDOF(IGuest));
 
-#endif
-
     pContext->fVerbose = fVerbose;
     pContext->fDryRun = fDryRun;
     pContext->fHostToGuest = fHostToGuest;
+    pContext->pGuestSession = pGuestSession;
 
     *ppContext = pContext;
@@ -1270,9 +949,6 @@
     if (pContext)
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-#else
         if (pContext->pGuestSession)
             pContext->pGuestSession->Close();
-#endif
         delete pContext;
     }
@@ -1446,21 +1122,10 @@
     if (pContext->fHostToGuest) /* We want to create directories on the guest. */
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        HRESULT rc = pContext->pGuest->DirectoryCreate(Bstr(pszDir).raw(),
-                                                       Bstr(pContext->strUsername).raw(), Bstr(pContext->strPassword).raw(),
-                                                       0700, DirectoryCreateFlag_Parents);
-        if (FAILED(rc))
-            vrc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-#else
-        ComPtr<IGuestDirectory> pDirectory;
         SafeArray<DirectoryCreateFlag_T> dirCreateFlags;
         dirCreateFlags.push_back(DirectoryCreateFlag_Parents);
         HRESULT rc = pContext->pGuestSession->DirectoryCreate(Bstr(pszDir).raw(),
-                                                              0700, ComSafeArrayAsInParam(dirCreateFlags), pDirectory.asOutParam());
+                                                              0700, ComSafeArrayAsInParam(dirCreateFlags));
         if (FAILED(rc))
             vrc = ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
-        if (!pDirectory.isNull())
-            pDirectory->Close();
-#endif
     }
     else /* ... or on the host. */
@@ -1495,14 +1160,4 @@
     {
         BOOL fDirExists = FALSE;
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        /** @todo Replace with DirectoryExists as soon as API is in place. */
-        HRESULT rc = pContext->pGuest->FileExists(Bstr(pszDir).raw(),
-                                                  Bstr(pContext->strUsername).raw(),
-                                                  Bstr(pContext->strPassword).raw(), &fDirExists);
-        if (FAILED(rc))
-            vrc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-        else
-            *fExists = fDirExists ? true : false;
-#else
         HRESULT rc = pContext->pGuestSession->DirectoryExists(Bstr(pszDir).raw(), &fDirExists);
         if (FAILED(rc))
@@ -1510,5 +1165,4 @@
         else
             *fExists = fDirExists ? true : false;
-#endif
     }
     else
@@ -1573,13 +1227,4 @@
     {
         BOOL fFileExists = FALSE;
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        HRESULT rc = pContext->pGuest->FileExists(Bstr(pszFile).raw(),
-                                                  Bstr(pContext->strUsername).raw(),
-                                                  Bstr(pContext->strPassword).raw(), &fFileExists);
-        if (FAILED(rc))
-            vrc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-        else
-            *fExists = fFileExists ? true : false;
-#else
         HRESULT rc = pContext->pGuestSession->FileExists(Bstr(pszFile).raw(), &fFileExists);
         if (FAILED(rc))
@@ -1587,5 +1232,4 @@
         else
             *fExists = fFileExists ? true : false;
-#endif
     }
     else
@@ -1658,10 +1302,4 @@
     if (pContext->fHostToGuest)
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        Assert(!fFlags);
-        rc = pContext->pGuest->CopyToGuest(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
-                                           Bstr(pContext->strUsername).raw(), Bstr(pContext->strPassword).raw(),
-                                           fFlags, pProgress.asOutParam());
-#else
         SafeArray<CopyFileFlag_T> copyFlags;
         rc = pContext->pGuestSession->CopyTo(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
@@ -1669,28 +1307,16 @@
 
                                              pProgress.asOutParam());
-#endif
     }
     else
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        Assert(!fFlags);
-        rc = pContext->pGuest->CopyFromGuest(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
-                                             Bstr(pContext->strUsername).raw(), Bstr(pContext->strPassword).raw(),
-                                             fFlags, pProgress.asOutParam());
-#else
         SafeArray<CopyFileFlag_T> copyFlags;
         rc = pContext->pGuestSession->CopyFrom(Bstr(pszFileSource).raw(), Bstr(pszFileDest).raw(),
                                                ComSafeArrayAsInParam(copyFlags),
                                                pProgress.asOutParam());
-#endif
     }
 
     if (FAILED(rc))
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        vrc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-#else
         vrc = ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
-#endif
     }
     else
@@ -1914,15 +1540,4 @@
      * target or not. */
     bool fDirCreated = false;
-
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    ULONG uDirHandle;
-    HRESULT rc = pContext->pGuest->DirectoryOpen(Bstr(szCurDir).raw(), Bstr(pszFilter).raw(),
-                                                 DirectoryOpenFlag_None /* No flags supported yet. */,
-                                                 Bstr(pContext->strUsername).raw(), Bstr(pContext->strPassword).raw(),
-                                                 &uDirHandle);
-    if (FAILED(rc))
-        return ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-    ComPtr<IGuestDirEntry> dirEntry;
-#else
     SafeArray<DirectoryOpenFlag_T> dirOpenFlags; /* No flags supported yet. */
     ComPtr<IGuestDirectory> pDirectory;
@@ -1933,20 +1548,11 @@
         return ctrlPrintError(pContext->pGuestSession, COM_IIDOF(IGuestSession));
     ComPtr<IFsObjInfo> dirEntry;
-#endif
     while (true)
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        rc = pContext->pGuest->DirectoryRead(uDirHandle, dirEntry.asOutParam());
-#else
         rc = pDirectory->Read(dirEntry.asOutParam());
-#endif
         if (FAILED(rc))
             break;
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        GuestDirEntryType_T enmType;
-#else
         FsObjType_T enmType;
-#endif
         dirEntry->COMGETTER(Type)(&enmType);
 
@@ -1956,9 +1562,5 @@
         switch (enmType)
         {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-            case GuestDirEntryType_Directory:
-#else
             case FsObjType_Directory:
-#endif
             {
                 Assert(!strName.isEmpty());
@@ -1999,9 +1601,5 @@
             }
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-            case GuestDirEntryType_Symlink:
-#else
             case FsObjType_Symlink:
-#endif
                 if (   (fFlags & CopyFileFlag_Recursive)
                     && (fFlags & CopyFileFlag_FollowLinks))
@@ -2012,9 +1610,5 @@
                     break;
 
-#ifndef VBOX_WITH_GUEST_CONTROL2
-            case GuestDirEntryType_File:
-#else
             case FsObjType_File:
-#endif
             {
                 Assert(!strName.isEmpty());
@@ -2092,25 +1686,13 @@
 
             default:
-#ifndef VBOX_WITH_GUEST_CONTROL2
-                vrc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-#else
                 vrc = ctrlPrintError(pDirectory, COM_IIDOF(IGuestDirectory));
-#endif
-                break;
-        }
-    }
-
-#ifndef VBOX_WITH_GUEST_CONTROL2
-    HRESULT rc2 = pContext->pGuest->DirectoryClose(uDirHandle);
-#else
+                break;
+        }
+    }
+
     HRESULT rc2 = pDirectory->Close();
-#endif
     if (FAILED(rc2))
     {
-#ifndef VBOX_WITH_GUEST_CONTROL2
-        int vrc2 = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
-#else
         int vrc2 = ctrlPrintError(pDirectory, COM_IIDOF(IGuestDirectory));
-#endif
         if (RT_SUCCESS(vrc))
             vrc = vrc2;
@@ -2344,6 +1926,6 @@
     PCOPYCONTEXT pContext;
     vrc = ctrlCopyContextCreate(guest, fVerbose, fDryRun, fHostToGuest,
-                                strUsername.c_str(), strPassword.c_str(),
-                                strDomain.c_str(), "guest copy", &pContext);
+                                strUsername, strPassword, strDomain,
+                                "VBoxManage Guest Control Copy", &pContext);
     if (RT_FAILURE(vrc))
     {
@@ -2479,5 +2061,5 @@
 }
 
-static int handleCtrlCreateDirectory(ComPtr<IGuest> guest, HandlerArg *pArg)
+static int handleCtrlCreateDirectory(ComPtr<IGuest> pGuest, HandlerArg *pArg)
 {
     AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
@@ -2509,5 +2091,5 @@
     Utf8Str strPassword;
     Utf8Str strDomain;
-    uint32_t fFlags = DirectoryCreateFlag_None;
+    SafeArray<DirectoryCreateFlag_T> dirCreateFlags;
     uint32_t fDirMode = 0; /* Default mode. */
     bool fVerbose = false;
@@ -2525,5 +2107,5 @@
 
             case 'P': /* Create parents */
-                fFlags |= DirectoryCreateFlag_Parents;
+                dirCreateFlags.push_back(DirectoryCreateFlag_Parents);
                 break;
 
@@ -2577,4 +2159,13 @@
         RTPrintf("Creating %u directories ...\n", cDirs);
 
+    ComPtr<IGuestSession> pGuestSession;
+    hrc = pGuest->CreateSession(Bstr(strUsername).raw(),
+                                Bstr(strPassword).raw(),
+                                Bstr(strDomain).raw(),
+                                Bstr("VBoxManage Guest Control MkDir").raw(),
+                                pGuestSession.asOutParam());
+    if (FAILED(hrc))
+        return ctrlPrintError(pGuest, COM_IIDOF(IGuest));
+
     DESTDIRMAPITER it = mapDirs.begin();
     while (it != mapDirs.end())
@@ -2583,10 +2174,8 @@
             RTPrintf("Creating directory \"%s\" ...\n", it->first.c_str());
 
-        hrc = guest->DirectoryCreate(Bstr(it->first).raw(),
-                                     Bstr(strUsername).raw(), Bstr(strPassword).raw(),
-                                     fDirMode, fFlags);
+        hrc = pGuestSession->DirectoryCreate(Bstr(it->first).raw(), fDirMode, ComSafeArrayAsInParam(dirCreateFlags));
         if (FAILED(hrc))
         {
-            ctrlPrintError(guest, COM_IIDOF(IGuest)); /* Return code ignored, save original rc. */
+            ctrlPrintError(pGuest, COM_IIDOF(IGuestSession)); /* Return code ignored, save original rc. */
             break;
         }
@@ -2595,8 +2184,11 @@
     }
 
+    if (!pGuestSession.isNull())
+        pGuestSession->Close();
+
     return FAILED(hrc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS;
 }
 
-static int handleCtrlStat(ComPtr<IGuest> guest, HandlerArg *pArg)
+static int handleCtrlStat(ComPtr<IGuest> pGuest, HandlerArg *pArg)
 {
     AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
@@ -2683,8 +2275,16 @@
         return errorSyntax(USAGE_GUESTCONTROL, "No user name specified!");
 
+    ComPtr<IGuestSession> pGuestSession;
+    HRESULT hrc = pGuest->CreateSession(Bstr(strUsername).raw(),
+                                        Bstr(strPassword).raw(),
+                                        Bstr(strDomain).raw(),
+                                        Bstr("VBoxManage Guest Control Stat").raw(),
+                                        pGuestSession.asOutParam());
+    if (FAILED(hrc))
+        return ctrlPrintError(pGuest, COM_IIDOF(IGuest));
+
     /*
      * Create the directories.
      */
-    HRESULT hrc = S_OK;
     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     DESTDIRMAPITER it = mapObjs.begin();
@@ -2694,31 +2294,51 @@
             RTPrintf("Checking for element \"%s\" ...\n", it->first.c_str());
 
-        BOOL fExists;
-        hrc = guest->FileExists(Bstr(it->first).raw(),
-                                Bstr(strUsername).raw(), Bstr(strPassword).raw(),
-                                &fExists);
+        ComPtr<IGuestFsObjInfo> pFsObjInfo;
+        hrc = pGuestSession->FileQueryInfo(Bstr(it->first).raw(), pFsObjInfo.asOutParam());
         if (FAILED(hrc))
-        {
-            ctrlPrintError(guest, COM_IIDOF(IGuest)); /* Return code ignored, save original rc. */
-            rcExit = RTEXITCODE_FAILURE;
-        }
-        else
-        {
-            /** @todo: Output vbox_stat's stdout output to get more information about
-             *         what happened. */
-
+            hrc = pGuestSession->DirectoryQueryInfo(Bstr(it->first).raw(), pFsObjInfo.asOutParam());
+
+        if (FAILED(hrc))
+        {
             /* If there's at least one element which does not exist on the guest,
              * drop out with exitcode 1. */
-            if (!fExists)
-            {
-                if (fVerbose)
-                    RTPrintf("Cannot stat for element \"%s\": No such file or directory\n",
-                             it->first.c_str());
-                rcExit = RTEXITCODE_FAILURE;
-            }
+            if (fVerbose)
+                RTPrintf("Cannot stat for element \"%s\": No such element\n",
+                         it->first.c_str());
+            rcExit = RTEXITCODE_FAILURE;
+        }
+        else
+        {
+            FsObjType_T objType;
+            hrc = pFsObjInfo->COMGETTER(Type)(&objType);
+            if (FAILED(hrc))
+                return ctrlPrintError(pGuest, COM_IIDOF(IGuestFsObjInfo));
+            switch (objType)
+            {
+                case FsObjType_File:
+                    RTPrintf("Element \"%s\" found: Is a file\n", it->first.c_str());
+                    break;
+
+                case FsObjType_Directory:
+                    RTPrintf("Element \"%s\" found: Is a directory\n", it->first.c_str());
+                    break;
+
+                case FsObjType_Symlink:
+                    RTPrintf("Element \"%s\" found: Is a symlink\n", it->first.c_str());
+                    break;
+
+                default:
+                    RTPrintf("Element \"%s\" found, type unknown (%ld)\n", it->first.c_str(), objType);
+                    break;
+            }
+
+            /** @todo: Show more information about this element. */
         }
 
         it++;
     }
+
+    if (!pGuestSession.isNull())
+        pGuestSession->Close();
 
     return rcExit;
Index: /trunk/src/VBox/Main/include/GuestSessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 42807)
+++ /trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 42808)
@@ -195,5 +195,5 @@
     STDMETHOD(CopyFrom)(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress);
     STDMETHOD(CopyTo)(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress);
-    STDMETHOD(DirectoryCreate)(IN_BSTR aPath, ULONG aMode, ComSafeArrayIn(DirectoryCreateFlag_T, aFlags), IGuestDirectory **aDirectory);
+    STDMETHOD(DirectoryCreate)(IN_BSTR aPath, ULONG aMode, ComSafeArrayIn(DirectoryCreateFlag_T, aFlags));
     STDMETHOD(DirectoryCreateTemp)(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory);
     STDMETHOD(DirectoryExists)(IN_BSTR aPath, BOOL *aExists);
@@ -245,5 +245,5 @@
      * @{ */
     int                     directoryClose(ComObjPtr<GuestDirectory> pDirectory);
-    int                     directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory);
+    int                     directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags);
     int                     objectCreateTempInternal(Utf8Str strTemplate,
                                                      Utf8Str strPath,
@@ -252,4 +252,5 @@
                                                      int *prc);
     int                     directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory);
+    int                     directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData);
     int                     dispatchToProcess(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
     int                     fileClose(ComObjPtr<GuestFile> pFile);
@@ -259,4 +260,5 @@
     int                     fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData);
     int                     fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize);
+    int                     fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData);
     const GuestCredentials &getCredentials(void);
     const GuestEnvironment &getEnvironment(void);
Index: /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 42807)
+++ /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 42808)
@@ -38,4 +38,10 @@
 
 
+/*
+ * If the following define is enabled the Guest Additions update code also
+ * checks for locations which were not supposed to happen due to not resolving
+ * environment variables in VBoxService toolbox arguments. So a file copied
+ * to "%TEMP%\foo.exe" became "C:\Windows\EMPfoo.exe".
+ */
 #define VBOX_SERVICE_ENVARG_BUG
 
@@ -1422,5 +1428,5 @@
 }
 
-int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)
+int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags)
 {
     LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
@@ -1476,25 +1482,18 @@
     }
 
-    if (RT_FAILURE(rc))
-        return rc;
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    /* Create the directory object. */
-    HRESULT hr = pDirectory.createObject();
-    if (FAILED(hr))
-        return VERR_COM_UNEXPECTED;
-
-    /* Note: There will be a race between creating and getting/initing the directory
-             object here. */
-    rc = pDirectory->init(this /* Parent */, strPath);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    /* Add the created directory to our vector. */
-    mData.mDirectories.push_back(pDirectory);
-
-    LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
-                 strPath.c_str(), mData.mId));
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData)
+{
+    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
+
+    int rc = fsQueryInfoInternal(strPath, objData);
+    if (RT_SUCCESS(rc))
+    {
+        rc = objData.mType == FsObjType_Directory
+           ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -1795,6 +1794,37 @@
 }
 
-/* Note: Will work on directories and others, too. */
 int GuestSession::fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData)
+{
+    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
+
+    int rc = fsQueryInfoInternal(strPath, objData);
+    if (RT_SUCCESS(rc))
+    {
+        rc = objData.mType == FsObjType_File
+           ? VINF_SUCCESS : VERR_NOT_A_FILE;
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int GuestSession::fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize)
+{
+    AssertPtrReturn(pllSize, VERR_INVALID_POINTER);
+
+    GuestFsObjData objData;
+    int rc = fileQueryInfoInternal(strPath, objData);
+    if (RT_SUCCESS(rc))
+    {
+        if (objData.mType == FsObjType_File)
+            *pllSize = objData.mObjectSize;
+        else
+            rc = VERR_NOT_A_FILE;
+    }
+
+    return rc;
+}
+
+int GuestSession::fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData)
 {
     LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
@@ -1868,21 +1898,4 @@
 }
 
-int GuestSession::fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize)
-{
-    AssertPtrReturn(pllSize, VERR_INVALID_POINTER);
-
-    GuestFsObjData objData;
-    int rc = fileQueryInfoInternal(strPath, objData);
-    if (RT_SUCCESS(rc))
-    {
-        if (objData.mType == FsObjType_File)
-            *pllSize = objData.mObjectSize;
-        else
-            rc = VERR_NOT_A_FILE;
-    }
-
-    return rc;
-}
-
 const GuestCredentials& GuestSession::getCredentials(void)
 {
@@ -2238,5 +2251,5 @@
 
 STDMETHODIMP GuestSession::DirectoryCreate(IN_BSTR aPath, ULONG aMode,
-                                           ComSafeArrayIn(DirectoryCreateFlag_T, aFlags), IGuestDirectory **aDirectory)
+                                           ComSafeArrayIn(DirectoryCreateFlag_T, aFlags))
 {
 #ifndef VBOX_WITH_GUEST_CONTROL
@@ -2247,5 +2260,4 @@
     if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
         return setError(E_INVALIDARG, tr("No directory to create specified"));
-    /* aDirectory is optional. */
 
     AutoCaller autoCaller(this);
@@ -2269,20 +2281,6 @@
 
     ComObjPtr <GuestDirectory> pDirectory;
-    int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags, pDirectory);
-    if (RT_SUCCESS(rc))
-    {
-        if (aDirectory)
-        {
-            /* Return directory object to the caller. */
-            hr = pDirectory.queryInterfaceTo(aDirectory);
-        }
-        else
-        {
-            rc = directoryClose(pDirectory);
-            if (RT_FAILURE(rc))
-                hr = setError(VBOX_E_IPRT_ERROR, tr("Unable to close directory object, rc=%Rrc"), rc);
-        }
-    }
-    else
+    int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags);
+    if (RT_FAILURE(rc))
     {
         switch (rc)
@@ -2462,8 +2460,47 @@
     LogFlowThisFuncEnter();
 
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    ReturnComNotImplemented();
+    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+        return setError(E_INVALIDARG, tr("No directory to query information for specified"));
+    CheckComArgOutPointerValid(aInfo);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    HRESULT hr = S_OK;
+
+    GuestFsObjData objData;
+    int rc = directoryQueryInfoInternal(Utf8Str(aPath), objData);
+    if (RT_SUCCESS(rc))
+    {
+        if (objData.mType == FsObjType_Directory)
+        {
+            ComObjPtr<GuestFsObjInfo> pFsObjInfo;
+            hr = pFsObjInfo.createObject();
+            if (FAILED(hr))
+                return VERR_COM_UNEXPECTED;
+
+            rc = pFsObjInfo->init(objData);
+            if (RT_SUCCESS(rc))
+                hr = pFsObjInfo.queryInterfaceTo(aInfo);
+        }
+    }
+
+    if (RT_FAILURE(rc))
+    {
+        switch (rc)
+        {
+            /** @todo Add more errors here! */
+
+            case VERR_NOT_A_DIRECTORY:
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a directory"));
+                break;
+
+            default:
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory information failed: %Rrc"), rc);
+                break;
+        }
+    }
+
+    return hr;
 #endif /* VBOX_WITH_GUEST_CONTROL */
 }
@@ -2753,8 +2790,44 @@
     LogFlowThisFuncEnter();
 
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    ReturnComNotImplemented();
+    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+        return setError(E_INVALIDARG, tr("No file to query information for specified"));
+    CheckComArgOutPointerValid(aInfo);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    HRESULT hr = S_OK;
+
+    GuestFsObjData objData;
+    int rc = fileQueryInfoInternal(Utf8Str(aPath), objData);
+    if (RT_SUCCESS(rc))
+    {
+        ComObjPtr<GuestFsObjInfo> pFsObjInfo;
+        hr = pFsObjInfo.createObject();
+        if (FAILED(hr))
+            return VERR_COM_UNEXPECTED;
+
+        rc = pFsObjInfo->init(objData);
+        if (RT_SUCCESS(rc))
+            hr = pFsObjInfo.queryInterfaceTo(aInfo);
+    }
+
+    if (RT_FAILURE(rc))
+    {
+        switch (rc)
+        {
+            /** @todo Add more errors here! */
+
+            case VERR_NOT_A_FILE:
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a file"));
+                break;
+
+            default:
+               hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information failed: %Rrc"), rc);
+               break;
+        }
+    }
+
+    return hr;
 #endif /* VBOX_WITH_GUEST_CONTROL */
 }
