VirtualBox

Changeset 98526 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Feb 10, 2023 3:10:50 PM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
155802
Message:

Guest Control: Initial commit (work in progress, disabled by default). bugref:9783

IGuestDirectory:

Added new attributes id + status + an own event source. Also added for rewind support via rewind().

New event types for guest directory [un]registration, state changes and entry reads.

Location:
trunk/src/VBox/Main/src-client
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r98278 r98526  
    5353
    5454
     55#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     56/**
     57 * Returns a stringyfied error of a guest fs error.
     58 *
     59 * @returns Stringyfied error.
     60 * @param   guestErrorInfo      Guest error info to get stringyfied error for.
     61 */
     62/* static */
     63Utf8Str GuestFs::guestErrorToString(const GuestErrorInfo &guestErrorInfo)
     64{
     65    Utf8Str strErr;
     66
     67    /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
     68    switch (guestErrorInfo.getVrc())
     69    {
     70        case VERR_ACCESS_DENIED:
     71            strErr.printf(tr("Access to \"%s\" denied"), guestErrorInfo.getWhat().c_str());
     72            break;
     73
     74        case VERR_FILE_NOT_FOUND: /* This is the most likely error. */
     75            RT_FALL_THROUGH();
     76        case VERR_PATH_NOT_FOUND:
     77            strErr.printf(tr("No such file or directory \"%s\""), guestErrorInfo.getWhat().c_str());
     78            break;
     79
     80        case VERR_INVALID_VM_HANDLE:
     81            strErr.printf(tr("VMM device is not available (is the VM running?)"));
     82            break;
     83
     84        case VERR_HGCM_SERVICE_NOT_FOUND:
     85            strErr.printf(tr("The guest execution service is not available"));
     86            break;
     87
     88        case VERR_BAD_EXE_FORMAT:
     89            strErr.printf(tr("The file \"%s\" is not an executable format"), guestErrorInfo.getWhat().c_str());
     90            break;
     91
     92        case VERR_AUTHENTICATION_FAILURE:
     93            strErr.printf(tr("The user \"%s\" was not able to logon"), guestErrorInfo.getWhat().c_str());
     94            break;
     95
     96        case VERR_INVALID_NAME:
     97            strErr.printf(tr("The file \"%s\" is an invalid name"), guestErrorInfo.getWhat().c_str());
     98            break;
     99
     100        case VERR_TIMEOUT:
     101            strErr.printf(tr("The guest did not respond within time"));
     102            break;
     103
     104        case VERR_CANCELLED:
     105            strErr.printf(tr("The execution operation was canceled"));
     106            break;
     107
     108        case VERR_GSTCTL_MAX_CID_OBJECTS_REACHED:
     109            strErr.printf(tr("Maximum number of concurrent guest processes has been reached"));
     110            break;
     111
     112        case VERR_NOT_FOUND:
     113            strErr.printf(tr("The guest execution service is not ready (yet)"));
     114            break;
     115
     116        default:
     117            strErr.printf(tr("Unhandled error %Rrc for \"%s\" occurred on guest -- please file a bug report"),
     118                          guestErrorInfo.getVrc(), guestErrorInfo.getWhat().c_str());
     119            break;
     120    }
     121
     122    return strErr;
     123}
     124
     125
     126/**
     127 * Set the file system object data from a given GSTCTLFSOBJINFO struct.
     128 *
     129 * @returns VBox status code.
     130 * @param   pFsObjInfo          Pointer to GSTCTLFSOBJINFO struct to use.
     131 * @param   strUser             Resolved user name owning the object on the guest.
     132 * @param   strGroups           Resolved user group(s) the object on the guest is associated with.
     133 *                              On Windows there can be multiple groups assigned. The groups are separated with ";"
     134 *                              The first group found is always the primary group.
     135 * @param   pvACL               ACL data associated with the object.
     136 * @param   cbACL               Size of ACL data (in bytes) associated with the object.
     137 */
     138int GuestFsObjData::FromGuestFsObjInfo(PCGSTCTLFSOBJINFO pFsObjInfo,
     139                                       const Utf8Str &strUser /* = "" */, const Utf8Str &strGroups /* = "" */, const void *pvACL /* = NULL */, size_t cbACL /* = 0 */)
     140{
     141    RT_NOREF(pvACL, cbACL);
     142
     143    int rc;
     144
     145    mType = GuestBase::fileModeToFsObjType(pFsObjInfo->Attr.fMode);
     146
     147    mFileAttrs = "";
     148    switch (mType)
     149    {
     150        case FsObjType_File:      mFileAttrs += '-'; break;
     151        case FsObjType_Directory: mFileAttrs += 'd'; break;
     152        case FsObjType_Symlink:   mFileAttrs += 'l'; break;
     153        case FsObjType_DevChar:   mFileAttrs += 'c'; break;
     154        case FsObjType_DevBlock:  mFileAttrs += 'b'; break;
     155        case FsObjType_Fifo:      mFileAttrs += 'f'; break;
     156        case FsObjType_Socket:    mFileAttrs += 's'; break;
     157        case FsObjType_WhiteOut:  mFileAttrs += 'w'; break;
     158        default:
     159            mFileAttrs += '?';
     160            AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
     161            break;
     162    }
     163
     164#define ADD_ATTR(a_Flag, a_Set, a_Clear) \
     165    mFileAttrs += pFsObjInfo->Attr.fMode & a_Flag ? a_Set : a_Clear
     166
     167    ADD_ATTR(RTFS_UNIX_IRUSR, 'r', '-');
     168    ADD_ATTR(RTFS_UNIX_IWUSR, 'w', '-');
     169    ADD_ATTR(RTFS_UNIX_IXUSR, 'x', '-');
     170
     171    ADD_ATTR(RTFS_UNIX_IRGRP, 'r', '-');
     172    ADD_ATTR(RTFS_UNIX_IWGRP, 'w', '-');
     173    ADD_ATTR(RTFS_UNIX_IXGRP, 'x', '-');
     174
     175    ADD_ATTR(RTFS_UNIX_IROTH, 'r', '-');
     176    ADD_ATTR(RTFS_UNIX_IWOTH, 'w', '-');
     177    ADD_ATTR(RTFS_UNIX_IXOTH, 'x', '-');
     178
     179    /** @todo Implement sticky bits. */
     180    mFileAttrs += "   "; /* Reserve 3 chars for sticky bits. */
     181
     182    mFileAttrs += " "; /* Separator. */
     183
     184    ADD_ATTR(RTFS_DOS_READONLY              , 'R', '-');
     185    ADD_ATTR(RTFS_DOS_HIDDEN                , 'H', '-');
     186    ADD_ATTR(RTFS_DOS_SYSTEM                , 'S', '-');
     187    ADD_ATTR(RTFS_DOS_DIRECTORY             , 'D', '-');
     188    ADD_ATTR(RTFS_DOS_ARCHIVED              , 'A', '-');
     189    ADD_ATTR(RTFS_DOS_NT_DEVICE             , 'd', '-');
     190    ADD_ATTR(RTFS_DOS_NT_NORMAL             , 'N', '-');
     191    ADD_ATTR(RTFS_DOS_NT_TEMPORARY          , 'T', '-');
     192    ADD_ATTR(RTFS_DOS_NT_SPARSE_FILE        , 'P', '-');
     193    ADD_ATTR(RTFS_DOS_NT_REPARSE_POINT      , 'J', '-');
     194    ADD_ATTR(RTFS_DOS_NT_COMPRESSED         , 'C', '-');
     195    ADD_ATTR(RTFS_DOS_NT_OFFLINE            , 'O', '-');
     196    ADD_ATTR(RTFS_DOS_NT_NOT_CONTENT_INDEXED, 'I', '-');
     197    ADD_ATTR(RTFS_DOS_NT_ENCRYPTED          , 'E', '-');
     198
     199#undef ADD_ATTR
     200
     201    mObjectSize       = pFsObjInfo->cbObject;
     202    mAllocatedSize    = pFsObjInfo->cbAllocated;
     203    mAccessTime       = pFsObjInfo->AccessTime.i64NanosecondsRelativeToUnixEpoch;
     204    mBirthTime        = pFsObjInfo->BirthTime.i64NanosecondsRelativeToUnixEpoch;
     205    mChangeTime       = pFsObjInfo->ChangeTime.i64NanosecondsRelativeToUnixEpoch;
     206    mModificationTime = pFsObjInfo->ModificationTime.i64NanosecondsRelativeToUnixEpoch;
     207    mUserName         = strUser;
     208    mUID              = pFsObjInfo->Attr.u.Unix.uid;
     209    mGID              = pFsObjInfo->Attr.u.Unix.gid;
     210    mGroupName        = strGroups; /** @todo Separate multiple group. */
     211    mNumHardLinks     = pFsObjInfo->Attr.u.Unix.cHardlinks;
     212    mNodeIDDevice     = pFsObjInfo->Attr.u.Unix.INodeIdDevice;
     213    mNodeID           = pFsObjInfo->Attr.u.Unix.INodeId;
     214    mDeviceNumber     =    RTFS_IS_DEV_BLOCK(pFsObjInfo->Attr.fMode)
     215                        || RTFS_IS_DEV_CHAR (pFsObjInfo->Attr.fMode) ? pFsObjInfo->Attr.u.Unix.Device : 0;
     216    mGenerationID     = pFsObjInfo->Attr.u.Unix.GenerationId;
     217    mUserFlags        = 0;
     218
     219    mACL              = ""; /** @todo Implement ACL handling. */
     220
     221    return VINF_SUCCESS;
     222}
     223#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     224
     225#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    55226/**
    56227 * Extracts the timespec from a given stream block key.
     
    62233 */
    63234/* static */
    64 PRTTIMESPEC GuestFsObjData::TimeSpecFromKey(const GuestProcessStreamBlock &strmBlk, const Utf8Str &strKey, PRTTIMESPEC pTimeSpec)
     235PRTTIMESPEC GuestFsObjData::TimeSpecFromKey(const GuestToolboxStreamBlock &strmBlk, const Utf8Str &strKey, PRTTIMESPEC pTimeSpec)
    65236{
    66237    AssertPtrReturn(pTimeSpec, NULL);
     
    84255 */
    85256/* static */
    86 int64_t GuestFsObjData::UnixEpochNsFromKey(const GuestProcessStreamBlock &strmBlk, const Utf8Str &strKey)
     257int64_t GuestFsObjData::UnixEpochNsFromKey(const GuestToolboxStreamBlock &strmBlk, const Utf8Str &strKey)
    87258{
    88259    RTTIMESPEC TimeSpec;
     
    103274 * @param  fLong                Whether the stream block contains long (detailed) information or not.
    104275 */
    105 int GuestFsObjData::FromLs(const GuestProcessStreamBlock &strmBlk, bool fLong)
     276int GuestFsObjData::FromToolboxLs(const GuestToolboxStreamBlock &strmBlk, bool fLong)
    106277{
    107278    LogFlowFunc(("\n"));
     
    253424 * @param   strmBlk             Stream block output data to parse.
    254425 */
    255 int GuestFsObjData::FromRm(const GuestProcessStreamBlock &strmBlk)
     426int GuestFsObjData::FromToolboxRm(const GuestToolboxStreamBlock &strmBlk)
    256427{
    257428#ifdef DEBUG
     
    272443 * @param   strmBlk             Stream block output data to parse.
    273444 */
    274 int GuestFsObjData::FromStat(const GuestProcessStreamBlock &strmBlk)
     445int GuestFsObjData::FromToolboxStat(const GuestToolboxStreamBlock &strmBlk)
    275446{
    276447    /* Should be identical output. */
    277     return GuestFsObjData::FromLs(strmBlk, true /*fLong*/);
     448    return GuestFsObjData::FromToolboxLs(strmBlk, true /*fLong*/);
    278449}
    279450
     
    285456 * @param   strmBlk             Stream block output data to parse.
    286457 */
    287 int GuestFsObjData::FromMkTemp(const GuestProcessStreamBlock &strmBlk)
     458int GuestFsObjData::FromToolboxMkTemp(const GuestToolboxStreamBlock &strmBlk)
    288459{
    289460    LogFlowFunc(("\n"));
     
    302473}
    303474
     475#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     476
    304477/**
    305478 * Returns the IPRT-compatible file mode.
     
    337510///////////////////////////////////////////////////////////////////////////////
    338511
     512#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    339513/** @todo *NOT* thread safe yet! */
    340514/** @todo Add exception handling for STL stuff! */
    341515
    342 GuestProcessStreamBlock::GuestProcessStreamBlock(void)
    343 {
    344 
    345 }
    346 
    347 GuestProcessStreamBlock::~GuestProcessStreamBlock()
     516GuestToolboxStreamBlock::GuestToolboxStreamBlock(void)
     517{
     518
     519}
     520
     521GuestToolboxStreamBlock::~GuestToolboxStreamBlock()
    348522{
    349523    Clear();
     
    353527 * Clears (destroys) the currently stored stream pairs.
    354528 */
    355 void GuestProcessStreamBlock::Clear(void)
     529void GuestToolboxStreamBlock::Clear(void)
    356530{
    357531    mPairs.clear();
     
    362536 * Dumps the currently stored stream pairs to the (debug) log.
    363537 */
    364 void GuestProcessStreamBlock::DumpToLog(void) const
     538void GuestToolboxStreamBlock::DumpToLog(void) const
    365539{
    366540    LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items):\n",
     
    382556 * @param  piVal                Pointer to value to return.
    383557 */
    384 int GuestProcessStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const
     558int GuestToolboxStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const
    385559{
    386560    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
     
    401575 * @param   pszKey              Name of key to get the value for.
    402576 */
    403 int64_t GuestProcessStreamBlock::GetInt64(const char *pszKey) const
     577int64_t GuestToolboxStreamBlock::GetInt64(const char *pszKey) const
    404578{
    405579    int64_t iVal;
     
    414588 * @return  uint32_t            Current number of stream pairs.
    415589 */
    416 size_t GuestProcessStreamBlock::GetCount(void) const
     590size_t GuestToolboxStreamBlock::GetCount(void) const
    417591{
    418592    return mPairs.size();
     
    425599 * @retval  VERR_NOT_FOUND if the return code string ("rc") was not found.
    426600 */
    427 int GuestProcessStreamBlock::GetVrc(void) const
     601int GuestToolboxStreamBlock::GetVrc(void) const
    428602{
    429603    const char *pszValue = GetString("rc");
     
    440614 * @param   pszKey              Name of key to get the value for.
    441615 */
    442 const char *GuestProcessStreamBlock::GetString(const char *pszKey) const
     616const char *GuestToolboxStreamBlock::GetString(const char *pszKey) const
    443617{
    444618    AssertPtrReturn(pszKey, NULL);
     
    464638 * @param   puVal               Pointer to value to return.
    465639 */
    466 int GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const
     640int GuestToolboxStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const
    467641{
    468642    const char *pszValue = GetString(pszKey);
     
    482656 * @param   iDefault            The default to return on error if not found.
    483657 */
    484 int32_t GuestProcessStreamBlock::GetInt32(const char *pszKey, int32_t iDefault) const
     658int32_t GuestToolboxStreamBlock::GetInt32(const char *pszKey, int32_t iDefault) const
    485659{
    486660    const char *pszValue = GetString(pszKey);
     
    503677 * @param   uDefault            The default value to return.
    504678 */
    505 uint32_t GuestProcessStreamBlock::GetUInt32(const char *pszKey, uint32_t uDefault /*= 0*/) const
     679uint32_t GuestToolboxStreamBlock::GetUInt32(const char *pszKey, uint32_t uDefault /*= 0*/) const
    506680{
    507681    uint32_t uVal;
     
    518692 * @param   pszValue            Value to set. Set NULL for deleting the key.
    519693 */
    520 int GuestProcessStreamBlock::SetValue(const char *pszKey, const char *pszValue)
     694int GuestToolboxStreamBlock::SetValue(const char *pszKey, const char *pszValue)
    521695{
    522696    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
     
    538712        if (pszValue)
    539713        {
    540             GuestProcessStreamValue val(pszValue);
     714            GuestToolboxStreamValue val(pszValue);
    541715            mPairs[strKey] = val;
    542716        }
     
    551725///////////////////////////////////////////////////////////////////////////////
    552726
    553 GuestProcessStream::GuestProcessStream(void)
     727GuestToolboxStream::GuestToolboxStream(void)
    554728    : m_cbMax(_32M)
    555729    , m_cbAllocated(0)
     
    558732    , m_pbBuffer(NULL) { }
    559733
    560 GuestProcessStream::~GuestProcessStream(void)
     734GuestToolboxStream::~GuestToolboxStream(void)
    561735{
    562736    Destroy();
     
    571745 * @param   cbData              Size (in bytes) of data to add.
    572746 */
    573 int GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
     747int GuestToolboxStream::AddData(const BYTE *pbData, size_t cbData)
    574748{
    575749    AssertPtrReturn(pbData, VERR_INVALID_POINTER);
     
    642816 * Destroys the internal data buffer.
    643817 */
    644 void GuestProcessStream::Destroy(void)
     818void GuestToolboxStream::Destroy(void)
    645819{
    646820    if (m_pbBuffer)
     
    662836 * @param   pszFile             Absolute path to host file to dump the output to.
    663837 */
    664 void GuestProcessStream::Dump(const char *pszFile)
     838void GuestToolboxStream::Dump(const char *pszFile)
    665839{
    666840    LogFlowFunc(("Dumping contents of stream=0x%p (cbAlloc=%u, cbSize=%u, cbOff=%u) to %s\n",
     
    694868 * @param streamBlock               Reference to guest stream block to fill.
    695869 */
    696 int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock)
     870int GuestToolboxStream::ParseBlock(GuestToolboxStreamBlock &streamBlock)
    697871{
    698872    if (   !m_pbBuffer
     
    749923    return vrc;
    750924}
     925#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    751926
    752927GuestBase::GuestBase(void)
     
    13521527    Utf8Str strErr;
    13531528
    1354 #define CASE_TOOL_ERROR(a_eType, a_strTool) \
     1529#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     1530# define CASE_TOOL_ERROR(a_eType, a_strTool) \
    13551531    case a_eType: \
    13561532    { \
    1357         strErr = GuestProcessTool::guestErrorToString(a_strTool, guestErrorInfo); \
     1533        strErr = GuestProcessToolbox::guestErrorToString(a_strTool, guestErrorInfo); \
    13581534        break; \
    13591535    }
     1536#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    13601537
    13611538    switch (guestErrorInfo.getType())
     
    13771554            break;
    13781555
    1379         CASE_TOOL_ERROR(GuestErrorInfo::Type_ToolCat,    VBOXSERVICE_TOOL_CAT);
     1556        case GuestErrorInfo::Type_Fs:
     1557            strErr = GuestFs::guestErrorToString(guestErrorInfo);
     1558            break;
     1559
     1560#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    13801561        CASE_TOOL_ERROR(GuestErrorInfo::Type_ToolLs,     VBOXSERVICE_TOOL_LS);
    13811562        CASE_TOOL_ERROR(GuestErrorInfo::Type_ToolMkDir,  VBOXSERVICE_TOOL_MKDIR);
     
    13831564        CASE_TOOL_ERROR(GuestErrorInfo::Type_ToolRm,     VBOXSERVICE_TOOL_RM);
    13841565        CASE_TOOL_ERROR(GuestErrorInfo::Type_ToolStat,   VBOXSERVICE_TOOL_STAT);
    1385 
     1566#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    13861567        default:
    13871568            AssertMsgFailed(("Type not implemented (type=%RU32, vrc=%Rrc)\n", guestErrorInfo.getType(), guestErrorInfo.getVrc()));
     
    14051586FsObjType_T GuestBase::fileModeToFsObjType(RTFMODE fMode)
    14061587{
    1407     if (RTFS_IS_FILE(fMode))           return FsObjType_File;
     1588         if (RTFS_IS_FIFO(fMode))      return FsObjType_Fifo;
     1589    else if (RTFS_IS_DEV_CHAR(fMode))  return FsObjType_DevChar;
    14081590    else if (RTFS_IS_DIRECTORY(fMode)) return FsObjType_Directory;
     1591    else if (RTFS_IS_DEV_BLOCK(fMode)) return FsObjType_DevBlock;
     1592    else if (RTFS_IS_FILE(fMode))      return FsObjType_File;
    14091593    else if (RTFS_IS_SYMLINK(fMode))   return FsObjType_Symlink;
     1594    else if (RTFS_IS_SOCKET(fMode))    return FsObjType_Socket;
     1595    else if (RTFS_IS_WHITEOUT(fMode))  return FsObjType_WhiteOut;
    14101596
    14111597    return FsObjType_Unknown;
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r98272 r98526  
    3636# error "VBOX_WITH_GUEST_CONTROL must defined in this file"
    3737#endif
     38#include "GuestImpl.h"
    3839#include "GuestDirectoryImpl.h"
    3940#include "GuestSessionImpl.h"
    4041#include "GuestCtrlImplPrivate.h"
     42#include "VirtualBoxErrorInfoImpl.h"
    4143
    4244#include "Global.h"
    4345#include "AutoCaller.h"
     46#include "VBoxEvents.h"
    4447
    4548#include <VBox/com/array.h>
     49#include <VBox/AssertGuest.h>
    4650
    4751
     
    7074int GuestDirectory::init(Console *pConsole, GuestSession *pSession, ULONG aObjectID, const GuestDirectoryOpenInfo &openInfo)
    7175{
    72     LogFlowThisFunc(("pConsole=%p, pSession=%p, aObjectID=%RU32, strPath=%s, strFilter=%s, uFlags=%x\n",
    73                      pConsole, pSession, aObjectID, openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
     76    LogFlowThisFunc(("pConsole=%p, pSession=%p, aObjectID=%RU32, strPath=%s, enmFilter=%#x, fFlags=%x\n",
     77                     pConsole, pSession, aObjectID, openInfo.mPath.c_str(), openInfo.menmFilter, openInfo.mFlags));
    7478
    7579    AssertPtrReturn(pConsole, VERR_INVALID_POINTER);
     
    8690        mObjectID = aObjectID;
    8791
    88         mData.mOpenInfo = openInfo;
    89     }
    90 
    91     if (RT_SUCCESS(vrc))
    92     {
    93         /* Start the directory process on the guest. */
    94         GuestProcessStartupInfo procInfo;
    95         procInfo.mName.printf(tr("Opening directory \"%s\""), openInfo.mPath.c_str());
    96         procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
    97         procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
    98         procInfo.mExecutable= Utf8Str(VBOXSERVICE_TOOL_LS);
    99 
    100         procInfo.mArguments.push_back(procInfo.mExecutable);
    101         procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    102         /* We want the long output format which contains all the object details. */
    103         procInfo.mArguments.push_back(Utf8Str("-l"));
    104 #if 0 /* Flags are not supported yet. */
    105         if (uFlags & DirectoryOpenFlag_NoSymlinks)
    106             procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
    107 #endif
    108         /** @todo Recursion support? */
    109         procInfo.mArguments.push_back(openInfo.mPath); /* The directory we want to open. */
    110 
    111         /*
    112          * Start the process synchronously and keep it around so that we can use
    113          * it later in subsequent read() calls.
    114          */
    115         vrc = mData.mProcessTool.init(mSession, procInfo, false /*fAsync*/, NULL /*pvrcGuest*/);
    116         if (RT_SUCCESS(vrc))
    117         {
    118             /* As we need to know if the directory we were about to open exists and and is accessible,
    119              * do the first read here in order to return a meaningful status here. */
    120             int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    121             vrc = i_readInternal(mData.mObjData, &vrcGuest);
    122             if (RT_FAILURE(vrc))
    123             {
    124                 /*
    125                  * We need to actively terminate our process tool in case of an error here,
    126                  * as this otherwise would be done on (directory) object destruction implicitly.
    127                  * This in turn then will run into a timeout, as the directory object won't be
    128                  * around anymore at that time. Ugly, but that's how it is for the moment.
    129                  */
    130                 int vrcTerm = mData.mProcessTool.terminate(30 * RT_MS_1SEC, NULL /* prcGuest */);
    131                 AssertRC(vrcTerm);
    132 
    133                 if (vrc == VERR_GSTCTL_GUEST_ERROR)
    134                     vrc = vrcGuest;
    135             }
    136         }
     92        mData.mOpenInfo  = openInfo;
     93        mData.mStatus    = DirectoryStatus_Undefined;
     94        mData.mLastError = VINF_SUCCESS;
     95
     96        unconst(mEventSource).createObject();
     97        HRESULT hr = mEventSource->init();
     98        if (FAILED(hr))
     99            vrc = VERR_COM_UNEXPECTED;
    137100    }
    138101
     
    177140}
    178141
     142HRESULT GuestDirectory::getEventSource(ComPtr<IEventSource> &aEventSource)
     143{
     144    /* No need to lock - lifetime constant. */
     145    mEventSource.queryInterfaceTo(aEventSource.asOutParam());
     146
     147    return S_OK;
     148}
     149
    179150HRESULT GuestDirectory::getFilter(com::Utf8Str &aFilter)
    180151{
     
    184155
    185156    aFilter = mData.mOpenInfo.mFilter;
     157
     158    return S_OK;
     159}
     160
     161HRESULT GuestDirectory::getId(ULONG *aId)
     162{
     163    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     164
     165    *aId = mObjectID;
     166
     167    return S_OK;
     168}
     169
     170HRESULT GuestDirectory::getStatus(DirectoryStatus_T *aStatus)
     171{
     172    LogFlowThisFuncEnter();
     173
     174    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     175
     176    *aStatus = mData.mStatus;
    186177
    187178    return S_OK;
     
    209200    switch (pCbCtx->uMessage)
    210201    {
     202        case GUEST_MSG_DISCONNECTED:
     203            /** @todo vrc = i_onGuestDisconnected(pCbCtx, pSvcCb); */
     204            vrc = VINF_SUCCESS; // TODO
     205            break;
     206
    211207        case GUEST_MSG_DIR_NOTIFY:
    212208        {
    213             int idx = 1; /* Current parameter index. */
    214             CALLBACKDATA_DIR_NOTIFY dataCb;
    215             /* pSvcCb->mpaParms[0] always contains the context ID. */
    216             HGCMSvcGetU32(&pSvcCb->mpaParms[idx++], &dataCb.uType);
    217             HGCMSvcGetU32(&pSvcCb->mpaParms[idx++], &dataCb.rc);
    218 
    219             LogFlowFunc(("uType=%RU32, vrcGguest=%Rrc\n", dataCb.uType, (int)dataCb.rc));
    220 
    221             switch (dataCb.uType)
    222             {
    223                 /* Nothing here yet, nothing to dispatch further. */
    224 
    225                 default:
    226                     vrc = VERR_NOT_SUPPORTED;
    227                     break;
    228             }
     209            vrc = i_onDirNotify(pCbCtx, pSvcCb);
    229210            break;
    230211        }
     
    238219    LogFlowFuncLeaveRC(vrc);
    239220    return vrc;
     221}
     222
     223/**
     224 * Opens the directory on the guest side.
     225 *
     226 * @return VBox status code.
     227 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     228 */
     229int GuestDirectory::i_open(int *pvrcGuest)
     230{
     231    int vrc;
     232#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     233    if ((mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS))
     234    {
     235        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     236
     237        GuestWaitEvent *pEvent = NULL;
     238        GuestEventTypes eventTypes;
     239        try
     240        {
     241            eventTypes.push_back(VBoxEventType_OnGuestDirectoryStateChanged);
     242
     243            vrc = registerWaitEvent(eventTypes, &pEvent);
     244        }
     245        catch (std::bad_alloc &)
     246        {
     247            vrc = VERR_NO_MEMORY;
     248        }
     249
     250        /* Prepare HGCM call. */
     251        VBOXHGCMSVCPARM paParms[8];
     252        int i = 0;
     253        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     254        HGCMSvcSetPv(&paParms[i++], (void *)mData.mOpenInfo.mPath.c_str(), (ULONG)mData.mOpenInfo.mPath.length() + 1);
     255        HGCMSvcSetPv(&paParms[i++], (void *)mData.mOpenInfo.mFilter.c_str(), (ULONG)mData.mOpenInfo.mFilter.length() + 1);
     256        HGCMSvcSetU32(&paParms[i++], mData.mOpenInfo.menmFilter);
     257        HGCMSvcSetU32(&paParms[i++], mData.mOpenInfo.mFlags);
     258
     259        alock.release(); /* Drop lock before sending. */
     260
     261        vrc = sendMessage(HOST_MSG_DIR_OPEN, i, paParms);
     262        if (RT_SUCCESS(vrc))
     263        {
     264            vrc = pEvent->Wait(30 * 1000);
     265            if (RT_SUCCESS(vrc))
     266            {
     267            }
     268        }
     269    }
     270    else
     271    {
     272#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     273#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     274        vrc = i_openViaToolbox(pvrcGuest);
     275#else
     276        RT_NOREF(pvrcGuest);
     277        vrc = VERR_NOT_SUPPORTED;
     278#endif
     279#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     280    }
     281#endif
     282
     283    return vrc;
     284}
     285
     286#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     287/**
     288 * Opens the directory on the guest side (legacy version).
     289 *
     290 * @returns VBox status code.
     291 * @param   pvrcGuest           Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     292 *
     293 * @note This uses an own guest process via the built-in toolbox in VBoxSerivce.
     294 */
     295int GuestDirectory::i_openViaToolbox(int *pvrcGuest)
     296{
     297    /* Start the directory process on the guest. */
     298    GuestProcessStartupInfo procInfo;
     299    procInfo.mName.printf(tr("Opening directory \"%s\""), mData.mOpenInfo.mPath.c_str());
     300    procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
     301    procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
     302    procInfo.mExecutable= Utf8Str(VBOXSERVICE_TOOL_LS);
     303
     304    procInfo.mArguments.push_back(procInfo.mExecutable);
     305    procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     306    /* We want the long output format which contains all the object details. */
     307    procInfo.mArguments.push_back(Utf8Str("-l"));
     308# if 0 /* Flags are not supported yet. */
     309    if (uFlags & DirectoryOpenFlag_NoSymlinks)
     310        procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
     311# endif
     312    /** @todo Recursion support? */
     313    procInfo.mArguments.push_back(mData.mOpenInfo.mPath); /* The directory we want to open. */
     314
     315    /*
     316     * Start the process synchronously and keep it around so that we can use
     317     * it later in subsequent read() calls.
     318     */
     319    int vrc = mData.mProcessTool.init(mSession, procInfo, false /*fAsync*/, NULL /*pvrcGuest*/);
     320    if (RT_SUCCESS(vrc))
     321    {
     322        /* As we need to know if the directory we were about to open exists and and is accessible,
     323         * do the first read here in order to return a meaningful status here. */
     324        int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     325        vrc = i_readInternal(mData.mObjData, &vrcGuest);
     326        if (RT_FAILURE(vrc))
     327        {
     328            /*
     329             * We need to actively terminate our process tool in case of an error here,
     330             * as this otherwise would be done on (directory) object destruction implicitly.
     331             * This in turn then will run into a timeout, as the directory object won't be
     332             * around anymore at that time. Ugly, but that's how it is for the moment.
     333             */
     334            /* ignore rc */ mData.mProcessTool.terminate(30 * RT_MS_1SEC, NULL /* pvrcGuest */);
     335        }
     336
     337        if (pvrcGuest)
     338            *pvrcGuest = vrcGuest;
     339    }
     340
     341    return vrc;
     342}
     343#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     344
     345/**
     346 * Called when the guest side notifies the host of a directory event.
     347 *
     348 * @returns VBox status code.
     349 * @param   pCbCtx              Host callback context.
     350 * @param   pSvcCbData          Host callback data.
     351 */
     352int GuestDirectory::i_onDirNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
     353{
     354#ifndef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     355    RT_NOREF(pCbCtx, pSvcCbData);
     356    return VERR_NOT_SUPPORTED;
     357#else
     358    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     359    AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
     360
     361    LogFlowThisFuncEnter();
     362
     363    if (pSvcCbData->mParms < 3)
     364        return VERR_INVALID_PARAMETER;
     365
     366    int idx = 1; /* Current parameter index. */
     367    CALLBACKDATA_DIR_NOTIFY dataCb;
     368    RT_ZERO(dataCb);
     369    /* pSvcCb->mpaParms[0] always contains the context ID. */
     370    HGCMSvcGetU32(&pSvcCbData->mpaParms[idx++], &dataCb.uType);
     371    HGCMSvcGetU32(&pSvcCbData->mpaParms[idx++], &dataCb.rc);
     372
     373    int vrcGuest = (int)dataCb.rc; /* uint32_t vs. int. */
     374
     375    LogFlowThisFunc(("uType=%RU32, vrcGuest=%Rrc\n", dataCb.uType, vrcGuest));
     376
     377    if (RT_FAILURE(vrcGuest))
     378    {
     379        /** @todo Set status? */
     380
     381        /* Ignore return code, as the event to signal might not be there (anymore). */
     382        signalWaitEventInternal(pCbCtx, vrcGuest, NULL /* pPayload */);
     383        return VINF_SUCCESS; /* Report to the guest. */
     384    }
     385
     386    int vrc = VERR_NOT_SUPPORTED; /* Play safe by default. */
     387
     388    ComObjPtr<VirtualBoxErrorInfo> errorInfo;
     389    HRESULT hrc = errorInfo.createObject();
     390    ComAssertComRCRet(hrc, VERR_COM_UNEXPECTED);
     391    if (RT_FAILURE(vrcGuest))
     392    {
     393        hrc = errorInfo->initEx(VBOX_E_GSTCTL_GUEST_ERROR, vrcGuest,
     394                                COM_IIDOF(IGuestFile), getComponentName(),
     395                                i_guestErrorToString(vrcGuest, mData.mOpenInfo.mPath.c_str()));
     396        ComAssertComRCRet(hrc, VERR_COM_UNEXPECTED);
     397    }
     398
     399    switch (dataCb.uType)
     400    {
     401        case GUEST_DIR_NOTIFYTYPE_ERROR:
     402        {
     403            vrc = i_setStatus(DirectoryStatus_Error, vrcGuest);
     404            break;
     405        }
     406
     407        case GUEST_DIR_NOTIFYTYPE_OPEN:
     408        {
     409            vrc = i_setStatus(DirectoryStatus_Open, vrcGuest);
     410            break;
     411        }
     412
     413        case GUEST_DIR_NOTIFYTYPE_CLOSE:
     414        {
     415            vrc = i_setStatus(DirectoryStatus_Close, vrcGuest);
     416            break;
     417        }
     418
     419        case GUEST_DIR_NOTIFYTYPE_READ:
     420        {
     421            ASSERT_GUEST_MSG_STMT_BREAK(pSvcCbData->mParms == 7, ("mParms=%u\n", pSvcCbData->mParms),
     422                                        vrc = VERR_WRONG_PARAMETER_COUNT);
     423            ASSERT_GUEST_MSG_STMT_BREAK(pSvcCbData->mpaParms[idx].type == VBOX_HGCM_SVC_PARM_PTR,
     424                                        ("type=%u\n", pSvcCbData->mpaParms[idx].type),
     425                                        vrc = VERR_WRONG_PARAMETER_TYPE);
     426
     427            PGSTCTLFSOBJINFO pObjInfo;
     428            uint32_t         cbObjInfo;
     429            vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[idx++], (void **)&pObjInfo, &cbObjInfo);
     430            AssertRCBreak(vrc);
     431            AssertBreakStmt(cbObjInfo == sizeof(GSTCTLFSOBJINFO), VERR_INVALID_PARAMETER);
     432
     433            GuestFsObjData fsObjData(mData.mOpenInfo.mPath);
     434            vrc = fsObjData.FromGuestFsObjInfo(pObjInfo);
     435            AssertRCBreak(vrc);
     436            ComObjPtr<GuestFsObjInfo> ptrFsObjInfo;
     437            hrc = ptrFsObjInfo.createObject();
     438            ComAssertComRCBreak(hrc, VERR_COM_UNEXPECTED);
     439            vrc = ptrFsObjInfo->init(fsObjData);
     440            AssertRCBreak(vrc);
     441
     442            ::FireGuestDirectoryReadEvent(mEventSource, mSession, this, ptrFsObjInfo);
     443            break;
     444        }
     445
     446        case GUEST_DIR_NOTIFYTYPE_REWIND:
     447        {
     448            /* Note: This does not change the overall status of the directory (i.e. open). */
     449            ::FireGuestDirectoryStateChangedEvent(mEventSource, mSession, this, DirectoryStatus_Rewind, errorInfo);
     450            break;
     451        }
     452
     453        default:
     454            AssertFailed();
     455            break;
     456    }
     457
     458    try
     459    {
     460        if (RT_SUCCESS(vrc))
     461        {
     462            GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb));
     463
     464            /* Ignore return code, as the event to signal might not be there (anymore). */
     465            signalWaitEventInternal(pCbCtx, vrcGuest, &payload);
     466        }
     467        else /* OOM situation, wrong HGCM parameters or smth. not expected. */
     468        {
     469            /* Ignore return code, as the event to signal might not be there (anymore). */
     470            signalWaitEventInternalEx(pCbCtx, vrc, 0 /* guestRc */, NULL /* pPayload */);
     471        }
     472    }
     473    catch (int vrcEx) /* Thrown by GuestWaitEventPayload constructor. */
     474    {
     475        /* Also try to signal the waiter, to let it know of the OOM situation.
     476         * Ignore return code, as the event to signal might not be there (anymore). */
     477        signalWaitEventInternalEx(pCbCtx, vrcEx, 0 /* guestRc */, NULL /* pPayload */);
     478        vrc = vrcEx;
     479    }
     480
     481    LogFlowThisFunc(("uType=%RU32, rcGuest=%Rrc, vrc=%Rrc\n", dataCb.uType, vrcGuest, vrc));
     482    return vrc;
     483#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    240484}
    241485
     
    302546 *
    303547 * @return VBox status code.
    304  * @param  prcGuest             Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
    305  */
    306 int GuestDirectory::i_closeInternal(int *prcGuest)
    307 {
    308     AssertPtrReturn(prcGuest, VERR_INVALID_POINTER);
    309 
    310     int vrc = mData.mProcessTool.terminate(30 * 1000 /* 30s timeout */, prcGuest);
    311     if (RT_FAILURE(vrc))
    312         return vrc;
     548 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     549 */
     550int GuestDirectory::i_close(int *pvrcGuest)
     551{
     552    int vrc;
     553#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     554    if (mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     555    {
     556        // TODO
     557        vrc = VERR_NOT_IMPLEMENTED;
     558    }
     559    else
     560    {
     561#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     562#ifndef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     563        RT_NOREF(pvrcGuest);
     564        vrc = VINF_SUCCESS; /* Nothing to do here. */
     565#else
     566        vrc = i_closeViaToolbox(pvrcGuest);
     567#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     568#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     569    }
     570#endif
    313571
    314572    AssertPtr(mSession);
     
    321579}
    322580
     581#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     582/**
     583 * Closes this guest directory and removes it from the guest session's directory list (legacy version).
     584 *
     585 * @return VBox status code.
     586 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     587 *
     588 * @note This uses an own guest process via the built-in toolbox in VBoxSerivce.
     589 */
     590int GuestDirectory::i_closeViaToolbox(int *pvrcGuest)
     591{
     592    return mData.mProcessTool.terminate(30 * 1000 /* 30s timeout */, pvrcGuest);
     593}
     594#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     595
    323596/**
    324597 * Reads the next directory entry, internal version.
     
    326599 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available.
    327600 * @param  objData              Where to store the read directory entry as internal object data.
    328  * @param  prcGuest             Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
    329  */
    330 int GuestDirectory::i_readInternal(GuestFsObjData &objData, int *prcGuest)
    331 {
    332     AssertPtrReturn(prcGuest, VERR_INVALID_POINTER);
    333 
    334     GuestProcessStreamBlock curBlock;
    335     int vrc = mData.mProcessTool.waitEx(GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK, &curBlock, prcGuest);
     601 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     602 */
     603int GuestDirectory::i_readInternal(GuestFsObjData &objData, int *pvrcGuest)
     604{
     605    AssertPtrReturn(pvrcGuest, VERR_INVALID_POINTER);
     606
     607    int vrc;
     608#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     609    if (mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     610    {
     611        // TODO
     612        RT_NOREF(objData, pvrcGuest);
     613        vrc = 0;
     614    }
     615    else
     616    {
     617#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     618#ifndef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     619        RT_NOREF(objData);
     620        vrc = VERR_NOT_SUPPORTED;
     621#else  /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     622        vrc = i_readInternalViaToolbox(objData, pvrcGuest);
     623#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     624#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     625    }
     626#endif
     627
     628    LogFlowThisFunc(("Returning vrc=%Rrc\n", vrc));
     629    return vrc;
     630}
     631
     632#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     633/**
     634 * Reads the next directory entry, internal version (legacy version).
     635 *
     636 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available.
     637 * @param  objData              Where to store the read directory entry as internal object data.
     638 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     639 *
     640 * @note This uses an own guest process via the built-in toolbox in VBoxSerivce.
     641 */
     642int GuestDirectory::i_readInternalViaToolbox(GuestFsObjData &objData, int *pvrcGuest)
     643{
     644    GuestToolboxStreamBlock curBlock;
     645    int vrc = mData.mProcessTool.waitEx(GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK, &curBlock, pvrcGuest);
    336646    if (RT_SUCCESS(vrc))
    337647    {
     
    349659                if (curBlock.GetString("name"))
    350660                {
    351                     vrc = objData.FromLs(curBlock, true /* fLong */);
     661                    vrc = objData.FromToolboxLs(curBlock, true /* fLong */);
    352662                }
    353663                else
     
    362672    }
    363673
    364     LogFlowThisFunc(("Returning vrc=%Rrc\n", vrc));
    365     return vrc;
    366 }
     674    return vrc;
     675}
     676#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    367677
    368678/**
     
    371681 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available.
    372682 * @param  fsObjInfo            Where to store the read directory entry.
    373  * @param  prcGuest             Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
    374  */
    375 int GuestDirectory::i_read(ComObjPtr<GuestFsObjInfo> &fsObjInfo, int *prcGuest)
    376 {
    377     AssertPtrReturn(prcGuest, VERR_INVALID_POINTER);
     683 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     684 */
     685int GuestDirectory::i_read(ComObjPtr<GuestFsObjInfo> &fsObjInfo, int *pvrcGuest)
     686{
     687    AssertPtrReturn(pvrcGuest, VERR_INVALID_POINTER);
    378688
    379689    /* Create the FS info object. */
     
    393703        }
    394704    }
    395     else /* Otherwise ask the guest for the next object data (block). */
     705    else /* Otherwise ask the guest for the next object data. */
    396706    {
    397707
    398708        GuestFsObjData objData;
    399         vrc = i_readInternal(objData, prcGuest);
     709        vrc = i_readInternal(objData, pvrcGuest);
    400710        if (RT_SUCCESS(vrc))
    401711            vrc = fsObjInfo->init(objData);
     
    404714    LogFlowThisFunc(("Returning vrc=%Rrc\n", vrc));
    405715    return vrc;
     716}
     717
     718/**
     719 * Rewinds the directory reading.
     720 *
     721 * @returns VBox status code.
     722 * @retval  VERR_GSTCTL_GUEST_ERROR when an error from the guest side has been received.
     723 * @param  uTimeoutMS           Timeout (in ms) to wait.
     724 * @param  pvrcGuest            Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     725 */
     726int GuestDirectory::i_rewind(uint32_t uTimeoutMS, int *pvrcGuest)
     727{
     728    RT_NOREF(pvrcGuest);
     729#ifndef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     730    RT_NOREF(uTimeoutMS, pvrcGuest);
     731#else
     732    /* Only available for Guest Additions 7.1+. */
     733    if (mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     734    {
     735        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     736
     737        int vrc;
     738
     739        GuestWaitEvent *pEvent = NULL;
     740        GuestEventTypes eventTypes;
     741        try
     742        {
     743            eventTypes.push_back(VBoxEventType_OnGuestDirectoryStateChanged);
     744            vrc = registerWaitEvent(eventTypes, &pEvent);
     745        }
     746        catch (std::bad_alloc &)
     747        {
     748            vrc = VERR_NO_MEMORY;
     749        }
     750
     751        if (RT_FAILURE(vrc))
     752            return vrc;
     753
     754        /* Prepare HGCM call. */
     755        VBOXHGCMSVCPARM paParms[4];
     756        int i = 0;
     757        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     758        HGCMSvcSetU32(&paParms[i++], mObjectID /* Directory handle */);
     759
     760        alock.release(); /* Drop lock before sending. */
     761
     762        vrc = sendMessage(HOST_MSG_DIR_REWIND, i, paParms);
     763        if (RT_SUCCESS(vrc))
     764        {
     765            VBoxEventType_T evtType;
     766            ComPtr<IEvent> pIEvent;
     767            vrc = waitForEvent(pEvent, uTimeoutMS, &evtType, pIEvent.asOutParam());
     768            if (RT_SUCCESS(vrc))
     769            {
     770                if (evtType == VBoxEventType_OnGuestDirectoryStateChanged)
     771                {
     772                    ComPtr<IGuestDirectoryStateChangedEvent> pEvt = pIEvent;
     773                    Assert(!pEvt.isNull());
     774                }
     775                else
     776                    vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
     777            }
     778            else if (pEvent->HasGuestError()) /* Return guest vrc if available. */
     779                vrc = pEvent->GetGuestError();
     780        }
     781
     782        unregisterWaitEvent(pEvent);
     783        return vrc;
     784    }
     785#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     786
     787    return VERR_NOT_SUPPORTED;
     788}
     789
     790/**
     791 * Sets the current internal directory object status.
     792 *
     793 * @returns VBox status code.
     794 * @param   enmStatus           New directory status to set.
     795 * @param   vrcDir              New result code to set.
     796 *
     797 * @note    Takes the write lock.
     798 */
     799int GuestDirectory::i_setStatus(DirectoryStatus_T enmStatus, int vrcDir)
     800{
     801    LogFlowThisFuncEnter();
     802
     803    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     804
     805    LogFlowThisFunc(("oldStatus=%RU32, newStatus=%RU32, vrcDir=%Rrc\n", mData.mStatus, enmStatus, vrcDir));
     806
     807#ifdef VBOX_STRICT
     808    if (enmStatus == DirectoryStatus_Error)
     809        AssertMsg(RT_FAILURE(vrcDir), ("Guest vrc must be an error (%Rrc)\n", vrcDir));
     810    else
     811        AssertMsg(RT_SUCCESS(vrcDir), ("Guest vrc must not be an error (%Rrc)\n", vrcDir));
     812#endif
     813
     814    if (mData.mStatus != enmStatus)
     815    {
     816        mData.mStatus    = enmStatus;
     817        mData.mLastError = vrcDir;
     818
     819        ComObjPtr<VirtualBoxErrorInfo> errorInfo;
     820        HRESULT hrc = errorInfo.createObject();
     821        ComAssertComRCRet(hrc, VERR_COM_UNEXPECTED);
     822        if (RT_FAILURE(vrcDir))
     823        {
     824            hrc = errorInfo->initEx(VBOX_E_GSTCTL_GUEST_ERROR, vrcDir,
     825                                    COM_IIDOF(IGuestDirectory), getComponentName(),
     826                                    i_guestErrorToString(vrcDir, mData.mOpenInfo.mPath.c_str()));
     827            ComAssertComRCRet(hrc, VERR_COM_UNEXPECTED);
     828        }
     829        /* Note: On vrcDir success, errorInfo is set to S_OK and also sent via the event below. */
     830
     831        alock.release(); /* Release lock before firing off event. */
     832
     833        ::FireGuestDirectoryStateChangedEvent(mEventSource, mSession, this, enmStatus, errorInfo);
     834    }
     835
     836    return VINF_SUCCESS;
    406837}
    407838
     
    418849
    419850    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    420     int vrc = i_closeInternal(&vrcGuest);
     851    int vrc = i_close(&vrcGuest);
    421852    if (RT_FAILURE(vrc))
    422853    {
     
    468899            case VERR_GSTCTL_GUEST_ERROR:
    469900            {
    470                 GuestErrorInfo ge(GuestErrorInfo::Type_ToolLs, vrcGuest, mData.mOpenInfo.mPath.c_str());
     901                GuestErrorInfo ge(
     902#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     903                                  GuestErrorInfo::Type_ToolLs
     904#else
     905                                  GuestErrorInfo::Type_Fs
     906#endif
     907                , vrcGuest, mData.mOpenInfo.mPath.c_str());
    471908                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Reading guest directory failed: %s"),
    472909                                   GuestBase::getErrorAsString(ge).c_str());
    473910                break;
    474911            }
     912
     913#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    475914            case VERR_GSTCTL_PROCESS_EXIT_CODE:
    476915                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Reading guest directory \"%s\" failed: %Rrc"),
    477916                                   mData.mOpenInfo.mPath.c_str(), mData.mProcessTool.getRc());
    478917                break;
    479 
     918#endif
    480919            case VERR_PATH_NOT_FOUND:
    481920                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Reading guest directory \"%s\" failed: Path not found"),
     
    490929
    491930            default:
    492                 hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Reading guest directory \"%s\" returned error: %Rrc\n"),
     931                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Reading guest directory \"%s\" returned unhandled error: %Rrc\n"),
    493932                                   mData.mOpenInfo.mPath.c_str(), vrc);
    494933                break;
     
    500939}
    501940
     941HRESULT GuestDirectory::rewind(void)
     942{
     943    AutoCaller autoCaller(this);
     944    if (FAILED(autoCaller.hrc())) return autoCaller.hrc();
     945
     946    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     947    int vrc = i_rewind(30 * 1000 /* Timeout in ms */, &vrcGuest);
     948    if (RT_SUCCESS(vrc))
     949        return S_OK;
     950
     951    GuestErrorInfo ge(GuestErrorInfo::Type_Directory, vrcGuest, mData.mOpenInfo.mPath.c_str());
     952    return setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Rewinding guest directory failed: %s"),
     953                       GuestBase::getErrorAsString(ge).c_str());
     954}
     955
  • trunk/src/VBox/Main/src-client/GuestFileImpl.cpp

    r98284 r98526  
    900900int GuestFile::i_queryInfo(GuestFsObjData &objData, int *prcGuest)
    901901{
    902     AssertPtr(mSession);
     902    AssertPtrReturn(mSession, VERR_OBJECT_DESTROYED);
    903903    return mSession->i_fsQueryInfo(mData.mOpenInfo.mFilename, FALSE /* fFollowSymlinks */, objData, prcGuest);
    904904}
     
    15761576        if (GuestProcess::i_isGuestError(vrc))
    15771577        {
    1578             GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, mData.mOpenInfo.mFilename.c_str());
     1578            GuestErrorInfo ge(
     1579#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     1580                              GuestErrorInfo::Type_ToolStat,
     1581#else
     1582                              GuestErrorInfo::Type_File,
     1583#endif
     1584                              vrcGuest, mData.mOpenInfo.mFilename.c_str());
    15791585            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying guest file information failed: %s"),
    15801586                               GuestBase::getErrorAsString(ge).c_str());
     
    16091615        if (GuestProcess::i_isGuestError(vrc))
    16101616        {
    1611             GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, mData.mOpenInfo.mFilename.c_str());
     1617            GuestErrorInfo ge(
     1618#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     1619                              GuestErrorInfo::Type_ToolStat,
     1620#else
     1621                              GuestErrorInfo::Type_File,
     1622#endif
     1623                              vrcGuest, mData.mOpenInfo.mFilename.c_str());
    16121624            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying guest file size failed: %s"),
    16131625                               GuestBase::getErrorAsString(ge).c_str());
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r98272 r98526  
    22532253///////////////////////////////////////////////////////////////////////////////
    22542254
    2255 GuestProcessTool::GuestProcessTool(void)
     2255GuestProcessToolbox::GuestProcessToolbox(void)
    22562256    : pSession(NULL),
    22572257      pProcess(NULL)
     
    22592259}
    22602260
    2261 GuestProcessTool::~GuestProcessTool(void)
     2261GuestProcessToolbox::~GuestProcessToolbox(void)
    22622262{
    22632263    uninit();
     
    22742274 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    22752275 */
    2276 int GuestProcessTool::init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
    2277                            bool fAsync, int *pvrcGuest)
     2276int GuestProcessToolbox::init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
     2277                              bool fAsync, int *pvrcGuest)
    22782278{
    22792279    LogFlowThisFunc(("pGuestSession=%p, exe=%s, fAsync=%RTbool\n",
     
    23162316 * Unitializes a guest process tool by terminating it on the guest.
    23172317 */
    2318 void GuestProcessTool::uninit(void)
     2318void GuestProcessToolbox::uninit(void)
    23192319{
    23202320    /* Make sure the process is terminated and unregistered from the guest session. */
     
    23392339 * @param   strmBlock           Where to return the stream block on success.
    23402340 */
    2341 int GuestProcessTool::getCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock)
    2342 {
    2343     const GuestProcessStream *pStream = NULL;
     2341int GuestProcessToolbox::getCurrentBlock(uint32_t uHandle, GuestToolboxStreamBlock &strmBlock)
     2342{
     2343    const GuestToolboxStream *pStream = NULL;
    23442344    if (uHandle == GUEST_PROC_OUT_H_STDOUT)
    23452345        pStream = &mStdOut;
     
    23702370 * @returns Result code from guest process tool.
    23712371 */
    2372 int GuestProcessTool::getRc(void) const
     2372int GuestProcessToolbox::getRc(void) const
    23732373{
    23742374    LONG exitCode = -1;
     
    23762376    AssertComRC(hrc);
    23772377
    2378     return GuestProcessTool::exitCodeToRc(mStartupInfo, exitCode);
     2378    return GuestProcessToolbox::exitCodeToRc(mStartupInfo, exitCode);
    23792379}
    23802380
     
    23842384 * @returns \c true if running, or \c false if not.
    23852385 */
    2386 bool GuestProcessTool::isRunning(void)
     2386bool GuestProcessToolbox::isRunning(void)
    23872387{
    23882388    AssertReturn(!pProcess.isNull(), false);
     
    24092409 *         occurred (exit status <> 0 or wrong process state).
    24102410 */
    2411 bool GuestProcessTool::isTerminatedOk(void)
     2411bool GuestProcessToolbox::isTerminatedOk(void)
    24122412{
    24132413    return getTerminationStatus() == VINF_SUCCESS ? true : false;
     
    24282428 */
    24292429/* static */
    2430 int GuestProcessTool::run(      GuestSession              *pGuestSession,
    2431                           const GuestProcessStartupInfo   &startupInfo,
    2432                                 int                       *pvrcGuest /* = NULL */)
     2430int GuestProcessToolbox::run(      GuestSession              *pGuestSession,
     2431                             const GuestProcessStartupInfo   &startupInfo,
     2432                                   int                       *pvrcGuest /* = NULL */)
    24332433{
    24342434    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     
    24422442        {
    24432443            if (errorInfo.vrcGuest == VERR_GSTCTL_PROCESS_EXIT_CODE) /* Translate exit code to a meaningful error code. */
    2444                 vrcGuest = GuestProcessTool::exitCodeToRc(startupInfo, errorInfo.iExitCode);
     2444                vrcGuest = GuestProcessToolbox::exitCodeToRc(startupInfo, errorInfo.iExitCode);
    24452445            else /* At least return something. */
    24462446                vrcGuest = errorInfo.vrcGuest;
     
    24672467 */
    24682468/* static */
    2469 int GuestProcessTool::runErrorInfo(GuestSession                    *pGuestSession,
    2470                                    GuestProcessStartupInfo const  &startupInfo,
    2471                                    GuestProcessToolErrorInfo       &errorInfo)
     2469int GuestProcessToolbox::runErrorInfo(GuestSession                 *pGuestSession,
     2470                                      GuestProcessStartupInfo const &startupInfo,
     2471                                      GuestProcessToolErrorInfo     &errorInfo)
    24722472{
    24732473    return runExErrorInfo(pGuestSession, startupInfo, NULL /* paStrmOutObjects */, 0 /* cStrmOutObjects */, errorInfo);
     
    24862486 */
    24872487/* static */
    2488 int GuestProcessTool::runEx(GuestSession                   *pGuestSession,
    2489                             GuestProcessStartupInfo const &startupInfo,
    2490                             GuestCtrlStreamObjects         *paStrmOutObjects,
    2491                             uint32_t                        cStrmOutObjects,
    2492                             int                            *pvrcGuest /* = NULL */)
     2488int GuestProcessToolbox::runEx(GuestSession                  *pGuestSession,
     2489                               GuestProcessStartupInfo const &startupInfo,
     2490                               GuestCtrlStreamObjects        *paStrmOutObjects,
     2491                               uint32_t                       cStrmOutObjects,
     2492                               int                           *pvrcGuest /* = NULL */)
    24932493{
    24942494    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    24952495
    24962496    GuestProcessToolErrorInfo errorInfo = { VERR_IPE_UNINITIALIZED_STATUS, INT32_MAX };
    2497     int vrc = GuestProcessTool::runExErrorInfo(pGuestSession, startupInfo, paStrmOutObjects, cStrmOutObjects, errorInfo);
     2497    int vrc = GuestProcessToolbox::runExErrorInfo(pGuestSession, startupInfo, paStrmOutObjects, cStrmOutObjects, errorInfo);
    24982498    if (RT_SUCCESS(vrc))
    24992499    {
     
    25022502        {
    25032503            if (errorInfo.vrcGuest == VERR_GSTCTL_PROCESS_EXIT_CODE) /* Translate exit code to a meaningful error code. */
    2504                 vrcGuest = GuestProcessTool::exitCodeToRc(startupInfo, errorInfo.iExitCode);
     2504                vrcGuest = GuestProcessToolbox::exitCodeToRc(startupInfo, errorInfo.iExitCode);
    25052505            else /* At least return something. */
    25062506                vrcGuest = errorInfo.vrcGuest;
     
    25332533 */
    25342534/* static */
    2535 int GuestProcessTool::runExErrorInfo(GuestSession                  *pGuestSession,
    2536                                      GuestProcessStartupInfo const &startupInfo,
    2537                                      GuestCtrlStreamObjects        *paStrmOutObjects,
    2538                                      uint32_t                       cStrmOutObjects,
    2539                                      GuestProcessToolErrorInfo     &errorInfo)
     2535int GuestProcessToolbox::runExErrorInfo(GuestSession                  *pGuestSession,
     2536                                        GuestProcessStartupInfo const &startupInfo,
     2537                                        GuestCtrlStreamObjects        *paStrmOutObjects,
     2538                                        uint32_t                       cStrmOutObjects,
     2539                                        GuestProcessToolErrorInfo     &errorInfo)
    25402540{
    25412541    AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER);
     
    25442544    /** @todo Check if this is a valid toolbox. */
    25452545
    2546     GuestProcessTool procTool;
     2546    GuestProcessToolbox procTool;
    25472547    int vrc = procTool.init(pGuestSession, startupInfo, false /* Async */, &errorInfo.vrcGuest);
    25482548    if (RT_SUCCESS(vrc))
     
    25522552            try
    25532553            {
    2554                 GuestProcessStreamBlock strmBlk;
     2554                GuestToolboxStreamBlock strmBlk;
    25552555                vrc = procTool.waitEx(  paStrmOutObjects
    25562556                                        ? GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK
     
    25902590 * @param   piExitCode      Exit code of the tool. Optional.
    25912591 */
    2592 int GuestProcessTool::getTerminationStatus(int32_t *piExitCode /* = NULL */)
     2592int GuestProcessToolbox::getTerminationStatus(int32_t *piExitCode /* = NULL */)
    25932593{
    25942594    Assert(!pProcess.isNull());
     
    26222622 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    26232623 */
    2624 int GuestProcessTool::wait(uint32_t fToolWaitFlags, int *pvrcGuest)
     2624int GuestProcessToolbox::wait(uint32_t fToolWaitFlags, int *pvrcGuest)
    26252625{
    26262626    return waitEx(fToolWaitFlags, NULL /* pStrmBlkOut */, pvrcGuest);
     
    26362636 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    26372637 */
    2638 int GuestProcessTool::waitEx(uint32_t fToolWaitFlags, GuestProcessStreamBlock *pStrmBlkOut, int *pvrcGuest)
     2638int GuestProcessToolbox::waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStrmBlkOut, int *pvrcGuest)
    26392639{
    26402640    LogFlowThisFunc(("fToolWaitFlags=0x%x, pStreamBlock=%p, pvrcGuest=%p\n", fToolWaitFlags, pStrmBlkOut, pvrcGuest));
     
    28302830 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    28312831 */
    2832 int GuestProcessTool::terminate(uint32_t uTimeoutMS, int *pvrcGuest)
     2832int GuestProcessToolbox::terminate(uint32_t uTimeoutMS, int *pvrcGuest)
    28332833{
    28342834    LogFlowThisFuncEnter();
     
    28522852 */
    28532853/* static */
    2854 int GuestProcessTool::exitCodeToRc(const GuestProcessStartupInfo &startupInfo, int32_t iExitCode)
     2854int GuestProcessToolbox::exitCodeToRc(const GuestProcessStartupInfo &startupInfo, int32_t iExitCode)
    28552855{
    28562856    if (startupInfo.mArguments.size() == 0)
     
    28712871 */
    28722872/* static */
    2873 int GuestProcessTool::exitCodeToRc(const char *pszTool, int32_t iExitCode)
     2873int GuestProcessToolbox::exitCodeToRc(const char *pszTool, int32_t iExitCode)
    28742874{
    28752875    AssertPtrReturn(pszTool, VERR_INVALID_POINTER);
     
    29532953 */
    29542954/* static */
    2955 Utf8Str GuestProcessTool::guestErrorToString(const char *pszTool, const GuestErrorInfo &guestErrorInfo)
     2955Utf8Str GuestProcessToolbox::guestErrorToString(const char *pszTool, const GuestErrorInfo &guestErrorInfo)
    29562956{
    29572957    Utf8Str strErr;
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r98272 r98526  
    952952    int vrc = VINF_SUCCESS;
    953953
    954     GuestProcessStartupInfo procInfo;
    955     procInfo.mFlags      = ProcessCreateFlag_Hidden;
    956     procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
    957 
    958     try
    959     {
    960         procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
    961 
    962         /* Construct arguments. */
    963         if (uFlags)
    964         {
    965             if (uFlags & DirectoryCreateFlag_Parents)
    966                 procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
    967             else
    968                 vrc = VERR_INVALID_PARAMETER;
    969         }
    970 
    971         if (   RT_SUCCESS(vrc)
    972             && uMode)
    973         {
    974             procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
    975 
    976             char szMode[16];
    977             if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
     954#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     955    if (mParent->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     956    {
     957        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     958
     959        GuestWaitEvent *pEvent = NULL;
     960        vrc = registerWaitEvent(mData.mSession.mID, mData.mObjectID, &pEvent);
     961        if (RT_FAILURE(vrc))
     962            return vrc;
     963
     964        uint32_t fFlags = GSTCTL_CREATEDIRECTORY_F_NONE;
     965        if (uFlags & DirectoryCreateFlag_Parents)
     966            fFlags |= GSTCTL_CREATEDIRECTORY_F_PARENTS;
     967        Assert(!(fFlags & ~GSTCTL_CREATEDIRECTORY_F_VALID_MASK));
     968
     969        /* Prepare HGCM call. */
     970        VBOXHGCMSVCPARM paParms[4];
     971        int i = 0;
     972        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     973        HGCMSvcSetPv (&paParms[i++], (void*)strPath.c_str(), (ULONG)strPath.length() + 1);
     974        HGCMSvcSetU32(&paParms[i++], fFlags);
     975        HGCMSvcSetU32(&paParms[i++], uMode);
     976
     977        alock.release(); /* Drop lock before sending. */
     978
     979        vrc = i_sendMessage(HOST_MSG_DIR_CREATE, i, paParms);
     980        if (RT_SUCCESS(vrc))
     981        {
     982            vrc = pEvent->Wait(30 * 1000);
     983            if (RT_SUCCESS(vrc))
    978984            {
    979                 procInfo.mArguments.push_back(Utf8Str(szMode));
     985                // TODO
    980986            }
    981             else
    982                 vrc = VERR_BUFFER_OVERFLOW;
    983         }
    984 
    985         procInfo.mArguments.push_back("--");    /* '--version' is a valid directory name. */
    986         procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
    987     }
    988     catch (std::bad_alloc &)
    989     {
    990         vrc = VERR_NO_MEMORY;
    991     }
    992 
    993     if (RT_SUCCESS(vrc))
    994         vrc = GuestProcessTool::run(this, procInfo, pvrcGuest);
     987        }
     988    }
     989    else
     990    {
     991#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     992#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     993        GuestProcessStartupInfo procInfo;
     994        procInfo.mFlags      = ProcessCreateFlag_Hidden;
     995        procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
     996
     997        try
     998        {
     999            procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
     1000
     1001            /* Construct arguments. */
     1002            if (uFlags)
     1003            {
     1004                if (uFlags & DirectoryCreateFlag_Parents)
     1005                    procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
     1006                else
     1007                    vrc = VERR_INVALID_PARAMETER;
     1008            }
     1009
     1010            if (   RT_SUCCESS(vrc)
     1011                && uMode)
     1012            {
     1013                procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
     1014
     1015                char szMode[16];
     1016                if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
     1017                {
     1018                    procInfo.mArguments.push_back(Utf8Str(szMode));
     1019                }
     1020                else
     1021                    vrc = VERR_BUFFER_OVERFLOW;
     1022            }
     1023
     1024            procInfo.mArguments.push_back("--");    /* '--version' is a valid directory name. */
     1025            procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
     1026        }
     1027        catch (std::bad_alloc &)
     1028        {
     1029            vrc = VERR_NO_MEMORY;
     1030        }
     1031
     1032        if (RT_SUCCESS(vrc))
     1033            vrc = GuestProcessToolbox::run(this, procInfo, pvrcGuest);
     1034#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     1035#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     1036    }
     1037#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    9951038
    9961039    LogFlowFuncLeaveRC(vrc);
     
    11811224                     strTemplate.c_str(), strPath.c_str(), fDirectory, fMode, fSecure));
    11821225
    1183     GuestProcessStartupInfo procInfo;
    1184     procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
    1185     try
    1186     {
    1187         procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
    1188         procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
    1189         procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1226    int vrc;
     1227    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     1228#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     1229    if (mParent->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     1230    {
     1231        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1232
     1233        GuestWaitEvent *pEvent = NULL;
     1234        vrc = registerWaitEvent(mData.mSession.mID, mData.mObjectID, &pEvent);
     1235        if (RT_FAILURE(vrc))
     1236            return vrc;
     1237
     1238        uint32_t fFlags = GSTCTL_CREATETEMP_F_NONE;
    11901239        if (fDirectory)
    1191             procInfo.mArguments.push_back(Utf8Str("-d"));
    1192         if (strPath.length()) /* Otherwise use /tmp or equivalent. */
    1193         {
    1194             procInfo.mArguments.push_back(Utf8Str("-t"));
    1195             procInfo.mArguments.push_back(strPath);
    1196         }
    1197         /* Note: Secure flag and mode cannot be specified at the same time. */
     1240            fFlags |= GSTCTL_CREATETEMP_F_DIRECTORY;
    11981241        if (fSecure)
    1199         {
    1200             procInfo.mArguments.push_back(Utf8Str("--secure"));
    1201         }
    1202         else
    1203         {
    1204             procInfo.mArguments.push_back(Utf8Str("--mode"));
    1205 
    1206             /* Note: Pass the mode unmodified down to the guest. See @ticketref{21394}. */
    1207             char szMode[16];
    1208             int vrc2 = RTStrPrintf2(szMode, sizeof(szMode), "%d", fMode);
    1209             AssertRCReturn(vrc2, vrc2);
    1210             procInfo.mArguments.push_back(szMode);
    1211         }
    1212         procInfo.mArguments.push_back("--"); /* strTemplate could be '--help'. */
    1213         procInfo.mArguments.push_back(strTemplate);
    1214     }
    1215     catch (std::bad_alloc &)
    1216     {
    1217         Log(("Out of memory!\n"));
    1218         return VERR_NO_MEMORY;
    1219     }
    1220 
    1221     /** @todo Use an internal HGCM command for this operation, since
    1222      *        we now can run in a user-dedicated session. */
    1223     int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    1224     GuestCtrlStreamObjects stdOut;
    1225     int vrc = GuestProcessTool::runEx(this, procInfo, &stdOut, 1 /* cStrmOutObjects */, &vrcGuest);
    1226     if (!GuestProcess::i_isGuestError(vrc))
    1227     {
    1228         GuestFsObjData objData;
    1229         if (!stdOut.empty())
    1230         {
    1231             vrc = objData.FromMkTemp(stdOut.at(0));
    1232             if (RT_FAILURE(vrc))
     1242            fFlags |= GSTCTL_CREATETEMP_F_SECURE;
     1243        Assert(!(fFlags & ~GSTCTL_CREATETEMP_F_VALID_MASK));
     1244
     1245        /* Prepare HGCM call. */
     1246        VBOXHGCMSVCPARM paParms[8];
     1247        int i = 0;
     1248        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     1249        HGCMSvcSetStr(&paParms[i++], strTemplate.c_str());
     1250        HGCMSvcSetStr(&paParms[i++], strPath.c_str());
     1251        HGCMSvcSetU32(&paParms[i++], fFlags);
     1252        HGCMSvcSetU32(&paParms[i++], fMode);
     1253
     1254        alock.release(); /* Drop lock before sending. */
     1255
     1256        vrc = i_sendMessage(HOST_MSG_FS_CREATE_TEMP, i, paParms);
     1257        if (RT_SUCCESS(vrc))
     1258        {
     1259            vrc = pEvent->Wait(30 * 1000);
     1260            if (RT_SUCCESS(vrc))
    12331261            {
    1234                 vrcGuest = vrc;
    1235                 if (pvrcGuest)
    1236                     *pvrcGuest = vrcGuest;
    1237                 vrc = VERR_GSTCTL_GUEST_ERROR;
     1262                // TODO
    12381263            }
    12391264        }
    1240         else
    1241             vrc = VERR_BROKEN_PIPE;
    1242 
    1243         if (RT_SUCCESS(vrc))
    1244             strName = objData.mName;
    1245     }
    1246     else if (pvrcGuest)
    1247         *pvrcGuest = vrcGuest;
     1265    }
     1266    else
     1267    {
     1268#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     1269#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     1270        GuestProcessStartupInfo procInfo;
     1271        procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
     1272        try
     1273        {
     1274            procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
     1275            procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
     1276            procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1277            if (fDirectory)
     1278                procInfo.mArguments.push_back(Utf8Str("-d"));
     1279            if (strPath.length()) /* Otherwise use /tmp or equivalent. */
     1280            {
     1281                procInfo.mArguments.push_back(Utf8Str("-t"));
     1282                procInfo.mArguments.push_back(strPath);
     1283            }
     1284            /* Note: Secure flag and mode cannot be specified at the same time. */
     1285            if (fSecure)
     1286            {
     1287                procInfo.mArguments.push_back(Utf8Str("--secure"));
     1288            }
     1289            else
     1290            {
     1291                procInfo.mArguments.push_back(Utf8Str("--mode"));
     1292
     1293                /* Note: Pass the mode unmodified down to the guest. See @ticketref{21394}. */
     1294                char szMode[16];
     1295                vrc = RTStrPrintf2(szMode, sizeof(szMode), "%d", fMode);
     1296                AssertRCReturn(vrc, vrc);
     1297                procInfo.mArguments.push_back(szMode);
     1298            }
     1299            procInfo.mArguments.push_back("--"); /* strTemplate could be '--help'. */
     1300            procInfo.mArguments.push_back(strTemplate);
     1301        }
     1302        catch (std::bad_alloc &)
     1303        {
     1304            Log(("Out of memory!\n"));
     1305            return VERR_NO_MEMORY;
     1306        }
     1307
     1308        GuestCtrlStreamObjects stdOut;
     1309        vrc = GuestProcessToolbox::runEx(this, procInfo, &stdOut, 1 /* cStrmOutObjects */, &vrcGuest);
     1310        if (!GuestProcess::i_isGuestError(vrc))
     1311        {
     1312            GuestFsObjData objData;
     1313            if (!stdOut.empty())
     1314            {
     1315                vrc = objData.FromToolboxMkTemp(stdOut.at(0));
     1316                if (RT_FAILURE(vrc))
     1317                {
     1318                    vrcGuest = vrc;
     1319                    if (pvrcGuest)
     1320                        *pvrcGuest = vrcGuest;
     1321                    vrc = VERR_GSTCTL_GUEST_ERROR;
     1322                }
     1323            }
     1324            else
     1325                vrc = VERR_BROKEN_PIPE;
     1326
     1327            if (RT_SUCCESS(vrc))
     1328                strName = objData.mName;
     1329        }
     1330        else if (pvrcGuest)
     1331            *pvrcGuest = vrcGuest;
     1332#else
     1333        RT_NOREF(strName);
     1334        vrc = VERR_NOT_SUPPORTED;
     1335#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     1336#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     1337    }
     1338#endif
    12481339
    12491340    LogFlowThisFunc(("Returning vrc=%Rrc, vrcGuest=%Rrc\n", vrc, vrcGuest));
     
    12851376    }
    12861377
    1287     /* We need to release the write lock first before initializing the directory object below,
     1378    /**
     1379     * If VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT is enabled:
     1380     *
     1381     * We need to release the write lock first before opening the directory object below,
    12881382     * as we're starting a guest process as part of it. This in turn will try to acquire the session's
    12891383     * write lock. */
     
    12941388
    12951389    vrc = pDirectory->init(pConsole, this /* Parent */, idObject, openInfo);
     1390    if (RT_SUCCESS(vrc))
     1391        vrc = pDirectory->i_open(pvrcGuest);
     1392
    12961393    if (RT_FAILURE(vrc))
    12971394    {
     
    15881685    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
    15891686
    1590     GuestProcessStartupInfo procInfo;
    1591     GuestProcessStream      streamOut;
    1592 
    1593     procInfo.mFlags      = ProcessCreateFlag_WaitForStdOut;
    1594     procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_RM);
    1595 
    1596     try
    1597     {
    1598         procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
    1599         procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    1600         procInfo.mArguments.push_back("--"); /* strPath could be '--help', which is a valid filename. */
    1601         procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
    1602     }
    1603     catch (std::bad_alloc &)
    1604     {
    1605         return VERR_NO_MEMORY;
    1606     }
    1607 
     1687    int vrc;
    16081688    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    1609     GuestCtrlStreamObjects stdOut;
    1610     int vrc = GuestProcessTool::runEx(this, procInfo, &stdOut, 1 /* cStrmOutObjects */, &vrcGuest);
    1611     if (GuestProcess::i_isGuestError(vrc))
    1612     {
    1613         if (!stdOut.empty())
    1614         {
    1615             GuestFsObjData objData;
    1616             vrc = objData.FromRm(stdOut.at(0));
    1617             if (RT_FAILURE(vrc))
     1689#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     1690    if (mParent->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     1691    {
     1692        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1693
     1694        GuestWaitEvent *pEvent = NULL;
     1695        vrc = registerWaitEvent(mData.mSession.mID, mData.mObjectID, &pEvent);
     1696        if (RT_FAILURE(vrc))
     1697            return vrc;
     1698
     1699        /* Prepare HGCM call. */
     1700        VBOXHGCMSVCPARM paParms[4];
     1701        int i = 0;
     1702        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     1703        HGCMSvcSetPv (&paParms[i++], (void*)strPath.c_str(), (ULONG)strPath.length() + 1);
     1704
     1705        alock.release(); /* Drop lock before sending. */
     1706
     1707        vrc = i_sendMessage(HOST_MSG_FILE_REMOVE, i, paParms);
     1708        if (RT_SUCCESS(vrc))
     1709        {
     1710            vrc = pEvent->Wait(30 * 1000);
     1711            if (RT_SUCCESS(vrc))
    16181712            {
    1619                 vrcGuest = vrc;
    1620                 if (pvrcGuest)
    1621                     *pvrcGuest = vrcGuest;
    1622                 vrc = VERR_GSTCTL_GUEST_ERROR;
     1713                // TODO
    16231714            }
    16241715        }
    1625         else
    1626             vrc = VERR_BROKEN_PIPE;
    1627     }
    1628     else if (pvrcGuest)
    1629         *pvrcGuest = vrcGuest;
     1716    }
     1717    else
     1718    {
     1719#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     1720#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     1721        GuestProcessStartupInfo procInfo;
     1722        GuestToolboxStream  streamOut;
     1723
     1724        procInfo.mFlags      = ProcessCreateFlag_WaitForStdOut;
     1725        procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_RM);
     1726
     1727        try
     1728        {
     1729            procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
     1730            procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1731            procInfo.mArguments.push_back("--"); /* strPath could be '--help', which is a valid filename. */
     1732            procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
     1733        }
     1734        catch (std::bad_alloc &)
     1735        {
     1736            return VERR_NO_MEMORY;
     1737        }
     1738
     1739        GuestCtrlStreamObjects stdOut;
     1740        vrc = GuestProcessToolbox::runEx(this, procInfo, &stdOut, 1 /* cStrmOutObjects */, &vrcGuest);
     1741        if (GuestProcess::i_isGuestError(vrc))
     1742        {
     1743            if (!stdOut.empty())
     1744            {
     1745                GuestFsObjData objData;
     1746                vrc = objData.FromToolboxRm(stdOut.at(0));
     1747                if (RT_FAILURE(vrc))
     1748                {
     1749                    vrcGuest = vrc;
     1750                    if (pvrcGuest)
     1751                        *pvrcGuest = vrcGuest;
     1752                    vrc = VERR_GSTCTL_GUEST_ERROR;
     1753                }
     1754            }
     1755            else
     1756                vrc = VERR_BROKEN_PIPE;
     1757        }
     1758        else if (pvrcGuest)
     1759            *pvrcGuest = vrcGuest;
     1760#else
     1761        RT_NOREF(pvrcGuest);
     1762        vrc = VERR_NOT_SUPPORTED;
     1763#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     1764#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     1765    }
     1766#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    16301767
    16311768    LogFlowThisFunc(("Returning vrc=%Rrc, vrcGuest=%Rrc\n", vrc, vrcGuest));
     
    18211958    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
    18221959
    1823     /** @todo Merge this with IGuestFile::queryInfo(). */
    1824     GuestProcessStartupInfo procInfo;
    1825     procInfo.mFlags      = ProcessCreateFlag_WaitForStdOut;
    1826     try
    1827     {
    1828         procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_STAT);
    1829         procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
    1830         procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1960    int vrc;
     1961    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     1962
     1963#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     1964    if (mParent->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
     1965    {
     1966        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1967
     1968        GuestWaitEvent *pEvent = NULL;
     1969        vrc = registerWaitEvent(mData.mSession.mID, mData.mObjectID, &pEvent);
     1970        if (RT_FAILURE(vrc))
     1971            return vrc;
     1972
     1973        uint32_t fFlags = GSTCTL_QUERYINFO_F_NONE;
    18311974        if (fFollowSymlinks)
    1832             procInfo.mArguments.push_back(Utf8Str("-L"));
    1833         procInfo.mArguments.push_back("--"); /* strPath could be '--help', which is a valid filename. */
    1834         procInfo.mArguments.push_back(strPath);
    1835     }
    1836     catch (std::bad_alloc &)
    1837     {
    1838         Log(("Out of memory!\n"));
    1839         return VERR_NO_MEMORY;
    1840     }
    1841 
    1842     int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    1843     GuestCtrlStreamObjects stdOut;
    1844     int vrc = GuestProcessTool::runEx(this, procInfo,
    1845                                         &stdOut, 1 /* cStrmOutObjects */,
    1846                                         &vrcGuest);
    1847     if (!GuestProcess::i_isGuestError(vrc))
    1848     {
    1849         if (!stdOut.empty())
    1850         {
    1851             vrc = objData.FromStat(stdOut.at(0));
    1852             if (RT_FAILURE(vrc))
     1975            fFlags |= GSTCTL_QUERYINFO_F_FOLLOW_LINK;
     1976
     1977        /* Prepare HGCM call. */
     1978        VBOXHGCMSVCPARM paParms[4];
     1979        int i = 0;
     1980        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     1981        HGCMSvcSetPv (&paParms[i++], (void*)strPath.c_str(), (ULONG)strPath.length() + 1);
     1982        HGCMSvcSetU32(&paParms[i++], GSTCTLFSOBJATTRADD_UNIX /* Implicit */);
     1983        HGCMSvcSetU32(&paParms[i++], fFlags);
     1984
     1985        alock.release(); /* Drop lock before sending. */
     1986
     1987        vrc = i_sendMessage(HOST_MSG_FS_QUERY_INFO, i, paParms);
     1988        if (RT_SUCCESS(vrc))
     1989        {
     1990            vrc = pEvent->Wait(30 * 1000);
     1991            if (RT_SUCCESS(vrc))
    18531992            {
    1854                 vrcGuest = vrc;
    1855                 if (pvrcGuest)
    1856                     *pvrcGuest = vrcGuest;
    1857                 vrc = VERR_GSTCTL_GUEST_ERROR;
     1993                // TODO
     1994            #if 0
     1995                const ComPtr<IEvent> pThisEvent = pEvent->Event();
     1996                if (pThisEvent.isNotNull()) /* Make sure that we actually have an event associated. */
     1997                {
     1998                    if (pType)
     1999                    {
     2000                        HRESULT hrc = pThisEvent->COMGETTER(Type)(pType);
     2001                        if (FAILED(hrc))
     2002                            vrc = VERR_COM_UNEXPECTED;
     2003                    }
     2004                    if (   RT_SUCCESS(vrc)
     2005                        && ppEvent)
     2006                        pThisEvent.queryInterfaceTo(ppEvent);
     2007
     2008                    unconst(pThisEvent).setNull();
     2009                }
     2010
     2011                if (pEvent->Payload().Size() == sizeof(GSTCTLFSOBJINFO))
     2012                {
     2013                    HRESULT hrc1 = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
     2014                    ComAssertComRC(hrc1);
     2015
     2016                    objData.Init(strPath);
     2017
     2018                    PGSTCTLFSOBJINFO
     2019
     2020                    objData.FromGuestFsObjInfo((PGSTCTLFSOBJINFO)pEvent->Payload().Raw());
     2021                }
     2022                else
     2023                    vrc = VERR_INVALID_PARAMETER;
     2024            #endif
    18582025            }
    1859         }
    1860         else
    1861             vrc = VERR_BROKEN_PIPE;
    1862     }
    1863     else if (pvrcGuest)
    1864         *pvrcGuest = vrcGuest;
     2026            else
     2027            {
     2028                if (vrc == VERR_GSTCTL_GUEST_ERROR)
     2029                {
     2030                    if (pvrcGuest)
     2031                        *pvrcGuest = pEvent->GuestResult();
     2032                }
     2033            }
     2034        }
     2035        unregisterWaitEvent(pEvent);
     2036    }
     2037    else
     2038    {
     2039#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
     2040#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     2041        /** @todo Merge this with IGuestFile::queryInfo(). */
     2042        GuestProcessStartupInfo procInfo;
     2043        procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
     2044        try
     2045        {
     2046            procInfo.mExecutable = Utf8Str(VBOXSERVICE_TOOL_STAT);
     2047            procInfo.mArguments.push_back(procInfo.mExecutable); /* Set argv0. */
     2048            procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     2049            if (fFollowSymlinks)
     2050                procInfo.mArguments.push_back(Utf8Str("-L"));
     2051            procInfo.mArguments.push_back("--"); /* strPath could be '--help', which is a valid filename. */
     2052            procInfo.mArguments.push_back(strPath);
     2053        }
     2054        catch (std::bad_alloc &)
     2055        {
     2056            Log(("Out of memory!\n"));
     2057            return VERR_NO_MEMORY;
     2058        }
     2059
     2060        GuestCtrlStreamObjects stdOut;
     2061        vrc = GuestProcessToolbox::runEx(this, procInfo, &stdOut, 1 /* cStrmOutObjects */, &vrcGuest);
     2062        if (!GuestProcess::i_isGuestError(vrc))
     2063        {
     2064            if (!stdOut.empty())
     2065            {
     2066                vrc = objData.FromToolboxStat(stdOut.at(0));
     2067                if (RT_FAILURE(vrc))
     2068                {
     2069                    vrcGuest = vrc;
     2070                    if (pvrcGuest)
     2071                        *pvrcGuest = vrcGuest;
     2072                    vrc = VERR_GSTCTL_GUEST_ERROR;
     2073                }
     2074            }
     2075            else
     2076                vrc = VERR_BROKEN_PIPE;
     2077        }
     2078        else if (pvrcGuest)
     2079            *pvrcGuest = vrcGuest;
     2080#else
     2081        RT_NOREF(fFollowSymlinks, objData, pvrcGuest);
     2082        vrc = VERR_NOT_SUPPORTED;
     2083#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
     2084#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
     2085    }
     2086#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    18652087
    18662088    LogFlowThisFunc(("Returning vrc=%Rrc, vrcGuest=%Rrc\n", vrc, vrcGuest));
     
    38024024            case VERR_GSTCTL_GUEST_ERROR:
    38034025            {
    3804                 GuestErrorInfo ge(GuestErrorInfo::Type_ToolMkTemp, vrcGuest, aPath.c_str());
     4026                GuestErrorInfo ge(GuestErrorInfo::Type_Fs, vrcGuest, aPath.c_str());
    38054027                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Temporary guest directory creation failed: %s"),
    38064028                                   GuestBase::getErrorAsString(ge).c_str());
     
    38474069                    default:
    38484070                    {
    3849                         GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, aPath.c_str());
     4071                        GuestErrorInfo ge(GuestErrorInfo::Type_Fs, vrcGuest, aPath.c_str());
    38504072                        hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying directory existence failed: %s"),
    38514073                                           GuestBase::getErrorAsString(ge).c_str());
     
    41904412                default:
    41914413                {
    4192                     GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, aPath.c_str());
     4414                    GuestErrorInfo ge(GuestErrorInfo::Type_Fs, vrcGuest, aPath.c_str());
    41934415                    hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying guest file existence failed: %s"),
    41944416                                       GuestBase::getErrorAsString(ge).c_str());
     
    43434565        if (GuestProcess::i_isGuestError(vrc))
    43444566        {
    4345             GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, aPath.c_str());
     4567            GuestErrorInfo ge(GuestErrorInfo::Type_Fs, vrcGuest, aPath.c_str());
    43464568            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying guest file size failed: %s"),
    43474569                               GuestBase::getErrorAsString(ge).c_str());
     
    43984620            else
    43994621            {
    4400                 GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, aPath.c_str());
     4622                GuestErrorInfo ge(GuestErrorInfo::Type_Fs, vrcGuest, aPath.c_str());
    44014623                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying guest file existence information failed: %s"),
    44024624                                   GuestBase::getErrorAsString(ge).c_str());
     
    44214643    LogFlowThisFunc(("aPath=%s, aFollowSymlinks=%RTbool\n", aPath.c_str(), RT_BOOL(aFollowSymlinks)));
    44224644
    4423     GuestFsObjData Info;
     4645    GuestFsObjData objData;
    44244646    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    4425     int vrc = i_fsQueryInfo(aPath, aFollowSymlinks != FALSE, Info, &vrcGuest);
     4647    int vrc = i_fsQueryInfo(aPath, aFollowSymlinks != FALSE, objData, &vrcGuest);
    44264648    if (RT_SUCCESS(vrc))
    44274649    {
     
    44304652        if (SUCCEEDED(hrc))
    44314653        {
    4432             vrc = ptrFsObjInfo->init(Info);
     4654            vrc = ptrFsObjInfo->init(objData);
    44334655            if (RT_SUCCESS(vrc))
    44344656                hrc = ptrFsObjInfo.queryInterfaceTo(aInfo.asOutParam());
     
    44414663        if (GuestProcess::i_isGuestError(vrc))
    44424664        {
    4443             GuestErrorInfo ge(GuestErrorInfo::Type_ToolStat, vrcGuest, aPath.c_str());
     4665            GuestErrorInfo ge(GuestErrorInfo::Type_Fs, vrcGuest, aPath.c_str());
    44444666            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Querying guest file information failed: %s"),
    44454667                               GuestBase::getErrorAsString(ge).c_str());
     
    44694691        if (GuestProcess::i_isGuestError(vrc))
    44704692        {
    4471             GuestErrorInfo ge(GuestErrorInfo::Type_ToolRm, vrcGuest, aPath.c_str());
     4693            GuestErrorInfo ge(GuestErrorInfo::Type_File, vrcGuest, aPath.c_str());
    44724694            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Removing guest file failed: %s"),
    44734695                               GuestBase::getErrorAsString(ge).c_str());
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r98272 r98526  
    550550        if (vrc == VERR_GSTCTL_GUEST_ERROR)
    551551            setProgressErrorMsg(VBOX_E_IPRT_ERROR, tr("Guest file lookup failed"),
    552                                 GuestErrorInfo(GuestErrorInfo::Type_ToolStat, vrcGuest, strSrc.c_str()));
     552                                GuestErrorInfo(GuestErrorInfo::Type_Fs, vrcGuest, strSrc.c_str()));
    553553        else
    554554            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     
    12471247    }
    12481248
    1249     int vrc2 = pDir->i_closeInternal(&vrcGuest);
     1249    int vrc2 = pDir->i_close(&vrcGuest);
    12501250    if (RT_SUCCESS(vrc))
    12511251        vrc = vrc2;
     
    15441544                if (vrc == VERR_GSTCTL_GUEST_ERROR)
    15451545                    strErrorInfo = GuestBase::getErrorAsString(tr("Guest source lookup failed"),
    1546                                                                GuestErrorInfo(GuestErrorInfo::Type_ToolStat, vrcGuest, strSrc.c_str()));
     1546                                                               GuestErrorInfo(GuestErrorInfo::Type_Fs, vrcGuest, strSrc.c_str()));
    15471547                else
    15481548                    strErrorInfo.printf(tr("Guest source lookup for \"%s\" failed: %Rrc"),
     
    26302630    LogRel(("Running %s ...\n", procInfo.mName.c_str()));
    26312631
    2632     GuestProcessTool procTool;
     2632    GuestProcessToolbox procToRun;
    26332633    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    2634     int vrc = procTool.init(pSession, procInfo, false /* Async */, &vrcGuest);
     2634    int vrc = procToRun.init(pSession, procInfo, false /* Async */, &vrcGuest);
    26352635    if (RT_SUCCESS(vrc))
    26362636    {
    26372637        if (RT_SUCCESS(vrcGuest))
    2638             vrc = procTool.wait(GUESTPROCESSTOOL_WAIT_FLAG_NONE, &vrcGuest);
     2638            vrc = procToRun.wait(GUESTPROCESSTOOL_WAIT_FLAG_NONE, &vrcGuest);
    26392639        if (RT_SUCCESS(vrc))
    2640             vrc = procTool.getTerminationStatus();
     2640            vrc = procToRun.getTerminationStatus();
    26412641    }
    26422642
     
    26482648                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    26492649                                    Utf8StrFmt(tr("Running update file \"%s\" on guest failed: %Rrc"),
    2650                                                procInfo.mExecutable.c_str(), procTool.getRc()));
     2650                                               procInfo.mExecutable.c_str(), procToRun.getRc()));
    26512651                break;
    26522652
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette