VirtualBox

Changeset 37375 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jun 8, 2011 10:51:26 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
72150
Message:

GuestCtrl: Added APIs for guest directory enumeration, guest file existence and copy from guest support, some API renaming/cleanup (work in progress).

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r37244 r37375  
    81148114      <desc>No flag set.</desc>
    81158115    </const>
    8116 
    81178116    <const name="WaitForProcessStartOnly" value="1">
    81188117      <desc>Only use the specified timeout value to wait for starting the guest process - the guest
    81198118        process itself then uses an infinite timeout.</desc>
    81208119    </const>
    8121 
    81228120    <const name="IgnoreOrphanedProcesses" value="2">
    81238121      <desc>Do not report an error when executed processes are still alive when VBoxService or the guest OS is shutting down.</desc>
    81248122    </const>
    8125 
    81268123    <const name="Hidden"                  value="4">
    81278124      <desc>Don't show the started process according to the guest OS guidelines.</desc>
     
    81368133      Guest process execution status.
    81378134    </desc>
    8138 
    81398135    <const name="Undefined"               value="0">
    81408136      <desc>Process is in an undefined state.</desc>
     
    81448140      <desc>Process has been started.</desc>
    81458141    </const>
    8146 
    81478142    <const name="TerminatedNormally"      value="2">
    81488143      <desc>Process terminated normally.</desc>
    81498144    </const>
    8150 
    81518145    <const name="TerminatedSignal"        value="3">
    81528146      <desc>Process terminated via signal.</desc>
    81538147    </const>
    8154 
    81558148    <const name="TerminatedAbnormally"    value="4">
    81568149      <desc>Process terminated abnormally.</desc>
    81578150    </const>
    8158 
    81598151     <const name="TimedOutKilled"         value="5">
    81608152      <desc>Process timed out and was killed.</desc>
    81618153    </const>
    8162 
    81638154    <const name="TimedOutAbnormally"      value="6">
    81648155      <desc>Process timed out and was not killed successfully.</desc>
    81658156    </const>
    8166 
    81678157    <const name="Down"                    value="7">
    81688158      <desc>Service/OS is stopping, process was killed.</desc>
    81698159    </const>
    8170 
    81718160    <const name="Error"                   value="8">
    81728161      <desc>Something went wrong (error code in flags).</desc>
     
    81818170      Guest process input flags.
    81828171    </desc>
    8183 
    81848172    <const name="None"                    value="0">
    81858173      <desc>No flag set.</desc>
    81868174    </const>
    8187 
    81888175    <const name="EndOfFile"               value="1">
    81898176      <desc>End of file (input) reached.</desc>
     
    81998186      type of output to retrieve.
    82008187    </desc>
    8201 
    82028188    <const name="None"                     value="0">
    82038189      <desc>No flags set. Get output from stdout.</desc>
    82048190    </const>
    8205 
    82068191    <const name="StdErr"                   value="1">
    82078192      <desc>Get output from stderr.</desc>
     
    82178202      are implemented.
    82188203    </desc>
    8219 
    82208204    <const name="None"                    value="0">
    82218205      <desc>No flag set.</desc>
    82228206    </const>
    8223 
    82248207    <const name="Recursive"               value="1">
    82258208      <desc>Copy directories recursively.</desc>
    82268209    </const>
    8227 
    82288210    <const name="Update"                  value="2">
    82298211      <desc>Only copy when the source file is newer than the destination file or when the destination file is missing.</desc>
    82308212    </const>
    8231 
    82328213    <const name="FollowLinks"             value="4">
    82338214      <desc>Follow symbolic links.</desc>
     
    82368217
    82378218  <enum
    8238     name="CreateDirectoryFlag"
    8239     uuid="26ff5bdd-c81f-4304-857b-b8be5e3f9cd6"
    8240   >
     8219    name="DirectoryCreateFlag"
     8220    uuid="bd721b0e-ced5-4f79-b368-249897c32a36"
     8221    >
    82418222    <desc>
    82428223      Directory creation flags.
    82438224    </desc>
    8244 
    82458225    <const name="None"                    value="0">
    82468226      <desc>No flag set.</desc>
    82478227    </const>
    8248 
    82498228    <const name="Parents"                 value="1">
    82508229      <desc>No error if existing, make parent directories as needed.</desc>
     
    82528231  </enum>
    82538232
     8233  <enum
     8234    name="DirectoryOpenFlag"
     8235    uuid="fc8f6203-0072-4f34-bd08-0b35e50bf071"
     8236    >
     8237    <desc>
     8238      Directory open flags.
     8239    </desc>
     8240    <const name="None"                    value="0">
     8241      <desc>No flag set.</desc>
     8242    </const>
     8243  </enum>
     8244
     8245  <enum
     8246    name="GuestDirEntryType"
     8247    uuid="6d19d924-1b77-4fc8-b369-a3b2c85c8241"
     8248    >
     8249    <desc>
     8250      Guest directory entry type.
     8251    </desc>
     8252    <const name="Unknown"                 value="0">
     8253      <desc>Unknown.</desc>
     8254    </const>
     8255    <const name="Directory"               value="4">
     8256      <desc>Regular file.</desc>
     8257    </const>
     8258    <const name="File"                    value="10">
     8259      <desc>Regular file.</desc>
     8260    </const>
     8261    <const name="Symlink"                 value="12">
     8262      <desc>Symbolic link.</desc>
     8263    </const>
     8264  </enum>
     8265
     8266  <interface
     8267    name="IGuestDirEntry" extends="$unknown"
     8268    uuid="20a66efc-c2f6-4438-826f-38454c04369e"
     8269    wsmap="struct"
     8270    >
     8271    <desc>
     8272      Structure representing a directory entry on the guest OS.
     8273    </desc>
     8274    <attribute name="nodeId" type="long long" readonly="yes">
     8275      <desc>The unique identifier (within the guest's file system) of this file system object.</desc>
     8276    </attribute>
     8277    <attribute name="name" type="wstring" readonly="yes">
     8278      <desc>The filename.</desc>
     8279    </attribute>
     8280    <attribute name="type" type="GuestDirEntryType" readonly="yes">
     8281      <desc>The entry type.</desc>
     8282    </attribute>
     8283  </interface>
     8284
    82548285  <interface
    82558286    name="IGuest" extends="$unknown"
    8256     uuid="4e78f7dd-8ca1-47e5-a344-5207f793df71"
     8287    uuid="44637074-a613-48cd-9b5d-77117f971529"
    82578288    wsmap="managed"
    82588289    >
     
    85078538        </desc>
    85088539      </param>
    8509       <param name="data" type="octet" dir="return" safearray="yes">
     8540      <param name="data" type="octet" safearray="yes" dir="return">
    85108541        <desc>
    85118542          Buffer for retrieving the actual output. A data size of 0 means end of file
     
    85498580    </method>
    85508581
     8582    <method name="copyFromGuest">
     8583      <desc>
     8584        Copies files/directories from guest to the host.
     8585
     8586        <result name="VBOX_E_IPRT_ERROR">
     8587          Error while copying.
     8588        </result>
     8589
     8590      </desc>
     8591      <param name="source" type="wstring" dir="in">
     8592        <desc>
     8593          Source file on the guest to copy.
     8594        </desc>
     8595      </param>
     8596      <param name="dest" type="wstring" dir="in">
     8597        <desc>
     8598          Destination path on the host.
     8599        </desc>
     8600      </param>
     8601      <param name="userName" type="wstring" dir="in">
     8602        <desc>
     8603          User name under which the copy command will be executed; the
     8604          user has to exist and have the appropriate rights to read from
     8605          the source path.
     8606        </desc>
     8607      </param>
     8608      <param name="password" type="wstring" dir="in">
     8609        <desc>
     8610          Password of the user account specified.
     8611        </desc>
     8612      </param>
     8613      <param name="flags" type="unsigned long" dir="in">
     8614        <desc>
     8615          <link to="CopyFileFlag"/> flags. Not used at the moment and should be set to 0.
     8616        </desc>
     8617      </param>
     8618      <param name="progress" type="IProgress" dir="return">
     8619        <desc>Progress object to track the operation completion.</desc>
     8620      </param>
     8621    </method>
     8622
    85518623    <method name="copyToGuest">
    85528624      <desc>
     
    85908662    </method>
    85918663
    8592     <method name="createDirectory">
     8664    <method name="directoryClose">
     8665      <desc>
     8666        Closes a formerly opened guest directory.
     8667
     8668        <result name="VBOX_E_IPRT_ERROR">
     8669          Error while closing directory.
     8670        </result>
     8671
     8672      </desc>
     8673      <param name="handle" type="unsigned long" dir="in">
     8674        <desc>
     8675          Handle of opened directory to close.
     8676        </desc>
     8677      </param>
     8678    </method>
     8679
     8680    <method name="directoryCreate">
    85938681      <desc>
    85948682        Creates a directory on the guest.
     
    86238711      <param name="flags" type="unsigned long" dir="in">
    86248712        <desc>
    8625           <link to="CreateDirectoryFlag"/> flags.
    8626         </desc>
    8627       </param>
    8628       <param name="progress" type="IProgress" dir="return">
    8629         <desc>Progress object to track the operation completion.</desc>
     8713          <link to="DirectoryCreateFlag"/> flags.
     8714        </desc>
     8715      </param>
     8716    </method>
     8717
     8718    <method name="directoryOpen">
     8719      <desc>
     8720        Opens a directory on the guest.
     8721
     8722        <result name="VBOX_E_IPRT_ERROR">
     8723          Error while opening / reading directory.
     8724        </result>
     8725
     8726      </desc>
     8727      <param name="directory" type="wstring" dir="in">
     8728        <desc>
     8729          Directory to read.
     8730        </desc>
     8731      </param>
     8732      <param name="filter" type="wstring" dir="in">
     8733        <desc>
     8734          Directory filter (DOS style wildcards). Set to empty
     8735          string if no filter required.
     8736        </desc>
     8737      </param>
     8738      <param name="flags" type="unsigned long" dir="in">
     8739        <desc>
     8740          <link to="DirectoryOpenFlag"/> flags.
     8741        </desc>
     8742      </param>
     8743      <param name="userName" type="wstring" dir="in">
     8744        <desc>
     8745          User name under which the directory reading will be performed; the
     8746          user has to exist and have the appropriate rights to access / read the
     8747          desired directory.
     8748        </desc>
     8749      </param>
     8750      <param name="password" type="wstring" dir="in">
     8751        <desc>
     8752          Password of the user account specified.
     8753        </desc>
     8754      </param>
     8755      <param name="handle" type="unsigned long" dir="out">
     8756        <desc>
     8757          Handle of opened directory returned by openDirectory.
     8758        </desc>
     8759      </param>
     8760    </method>
     8761
     8762    <method name="directoryRead">
     8763      <desc>
     8764        Reads the next directory entry of an opened guest directory.
     8765
     8766        <result name="VBOX_E_IPRT_ERROR">
     8767          Error while opening / reading directory.
     8768        </result>
     8769
     8770      </desc>
     8771      <param name="handle" type="unsigned long" dir="in">
     8772        <desc>
     8773          Handle of opened directory returned by openDirectory.
     8774        </desc>
     8775      </param>
     8776      <param name="entry" type="IGuestDirEntry" dir="out">
     8777        <desc>
     8778          Information about next directory entry on success.
     8779        </desc>
     8780      </param>
     8781    </method>
     8782
     8783    <method name="fileExists">
     8784      <desc>
     8785        Checks if the specified file name exists and is a regular file.
     8786
     8787        <result name="VBOX_E_IPRT_ERROR">
     8788          Error while looking up information.
     8789        </result>
     8790
     8791      </desc>
     8792      <param name="file" type="wstring" dir="in">
     8793        <desc>
     8794          Full path of file to check.
     8795        </desc>
     8796      </param>
     8797      <param name="userName" type="wstring" dir="in">
     8798        <desc>
     8799          User name under which the lookup will be performed; the
     8800          user has to exist and have the appropriate rights to access / read the
     8801          desired directory.
     8802        </desc>
     8803      </param>
     8804      <param name="password" type="wstring" dir="in">
     8805        <desc>
     8806          Password of the user account specified.
     8807        </desc>
     8808      </param>
     8809      <param name="exists" type="boolean" dir="out">
     8810        <desc>
     8811          True if it's a regular file, false if it isn't (or doesn't exist).
     8812        </desc>
    86308813      </param>
    86318814    </method>
     
    89059088         this progress. This means sub-operation number, description, percent
    89069089         and so on.
    8907          
     9090
    89089091         You have to take care on setting up at least the same count on
    89099092         sub-operations in this progress object like there are in the other
    8910          progress object. 
     9093         progress object.
    89119094
    89129095         If the other progress object supports cancel and this object gets any
  • trunk/src/VBox/Main/include/GuestImpl.h

    r36102 r37375  
    8888    STDMETHOD(SetCredentials)(IN_BSTR aUserName, IN_BSTR aPassword,
    8989                              IN_BSTR aDomain, BOOL aAllowInteractiveLogon);
     90    // Process execution
    9091    STDMETHOD(ExecuteProcess)(IN_BSTR aCommand, ULONG aFlags,
    9192                              ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
     
    9596    STDMETHOD(SetProcessInput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ComSafeArrayIn(BYTE, aData), ULONG *aBytesWritten);
    9697    STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus_T *aStatus);
     98    // File copying
     99    STDMETHOD(CopyFromGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);
    97100    STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);
    98     STDMETHOD(CreateDirectory)(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aMode, ULONG aFlags, IProgress **aProgress);
     101    // Directory handling
     102    STDMETHOD(DirectoryClose)(ULONG aHandle);
     103    STDMETHOD(DirectoryCreate)(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword, ULONG aMode, ULONG aFlags);
     104    STDMETHOD(DirectoryOpen)(IN_BSTR aDirectory, IN_BSTR aFilter,
     105                             ULONG aFlags, IN_BSTR aUserName, IN_BSTR aPassword, ULONG *aHandle);
     106    STDMETHOD(DirectoryRead)(ULONG aHandle, IGuestDirEntry **aDirEntry);
     107    // File handling
     108    STDMETHOD(FileExists)(IN_BSTR aFile, IN_BSTR aUserName, IN_BSTR aPassword, BOOL *aExists);
     109    // Misc stuff
    99110    STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
    100111                                     ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache,
     
    107118                                   IN_BSTR aUserName, IN_BSTR aPassword,
    108119                                   ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC);
    109     HRESULT createDirectoryInternal(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword,
    110                                     ULONG aMode, ULONG aFlags, IProgress **aProgress, int *pRC);
     120    HRESULT directoryCreateInternal(IN_BSTR aDirectory, IN_BSTR aUserName, IN_BSTR aPassword,
     121                                    ULONG aMode, ULONG aFlags, int *pRC);
    111122    void setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType);
    112123    void setAdditionsInfo2(Bstr aAdditionsVersion, Bstr aVersionName, Bstr aRevision);
     
    131142    // Internal tasks.
    132143    struct TaskGuest; /* Worker thread helper. */
    133     HRESULT taskCopyFile(TaskGuest *aTask);
     144    HRESULT taskCopyFileToGuest(TaskGuest *aTask);
     145    HRESULT taskCopyFileFromGuest(TaskGuest *aTask);
    134146    HRESULT taskUpdateGuestAdditions(TaskGuest *aTask);
    135147
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r36887 r37375  
    4545    enum TaskType
    4646    {
    47         /** Copies a file to the guest. */
    48         CopyFile = 50,
     47        /** Copies a file from host to the guest. */
     48        CopyFileToGuest   = 50,
     49        /** Copies a file from guest to the host. */
     50        CopyFileFromGuest = 55,
    4951
    5052        /** Update Guest Additions by directly copying the required installer
     
    6062          rc(S_OK)
    6163    {}
    62     ~TaskGuest() {}
     64    virtual ~TaskGuest() {}
    6365
    6466    int startThread();
     
    110112    {
    111113#ifdef VBOX_WITH_GUEST_CONTROL
    112         case TaskGuest::CopyFile:
    113         {
    114             rc = pGuest->taskCopyFile(task.get());
     114        case TaskGuest::CopyFileToGuest:
     115        {
     116            rc = pGuest->taskCopyFileToGuest(task.get());
     117            break;
     118        }
     119        case TaskGuest::CopyFileFromGuest:
     120        {
     121            rc = pGuest->taskCopyFileFromGuest(task.get());
    115122            break;
    116123        }
     
    182189
    183190#ifdef VBOX_WITH_GUEST_CONTROL
    184 HRESULT Guest::taskCopyFile(TaskGuest *aTask)
     191HRESULT Guest::taskCopyFileToGuest(TaskGuest *aTask)
    185192{
    186193    LogFlowFuncEnter();
     
    458465}
    459466
     467HRESULT Guest::taskCopyFileFromGuest(TaskGuest *aTask)
     468{
     469    LogFlowFuncEnter();
     470
     471    AutoCaller autoCaller(this);
     472    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     473
     474    /*
     475     * Do *not* take a write lock here since we don't (and won't)
     476     * touch any class-specific data (of IGuest) here - only the member functions
     477     * which get called here can do that.
     478     */
     479
     480    HRESULT rc = S_OK;
     481
     482    try
     483    {
     484        Guest *pGuest = aTask->pGuest;
     485        AssertPtr(pGuest);
     486
     487
     488
     489#if 0
     490        /* Does our source file exist? */
     491        if (!RTFileExists(aTask->strSource.c_str()))
     492        {
     493            rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     494                                                 Guest::tr("Source file \"%s\" does not exist, or is not a file"),
     495                                                 aTask->strSource.c_str());
     496        }
     497        else
     498        {
     499            RTFILE fileSource;
     500            int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(),
     501                                 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
     502            if (RT_FAILURE(vrc))
     503            {
     504                rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     505                                                     Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"),
     506                                                     aTask->strSource.c_str(),  vrc);
     507            }
     508            else
     509            {
     510                uint64_t cbSize;
     511                vrc = RTFileGetSize(fileSource, &cbSize);
     512                if (RT_FAILURE(vrc))
     513                {
     514                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     515                                                         Guest::tr("Could not query file size of \"%s\" (%Rrc)"),
     516                                                         aTask->strSource.c_str(), vrc);
     517                }
     518                else
     519                {
     520                    com::SafeArray<IN_BSTR> args;
     521                    com::SafeArray<IN_BSTR> env;
     522
     523                    /*
     524                     * Prepare tool command line.
     525                     */
     526                    char szOutput[RTPATH_MAX];
     527                    if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 1)
     528                    {
     529                        /*
     530                         * Normalize path slashes, based on the detected guest.
     531                         */
     532                        Utf8Str osType = mData.mOSTypeId;
     533                        if (   osType.contains("Microsoft", Utf8Str::CaseInsensitive)
     534                            || osType.contains("Windows", Utf8Str::CaseInsensitive))
     535                        {
     536                            /* We have a Windows guest. */
     537                            RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */);
     538                        }
     539                        else /* ... or something which isn't from Redmond ... */
     540                        {
     541                            RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */);
     542                        }
     543
     544                        args.push_back(Bstr(szOutput).raw());             /* We want to write a file ... */
     545                    }
     546                    else
     547                    {
     548                        rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     549                                                             Guest::tr("Error preparing command line"));
     550                    }
     551
     552                    ComPtr<IProgress> execProgress;
     553                    ULONG uPID;
     554                    if (SUCCEEDED(rc))
     555                    {
     556                        LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n",
     557                                aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize));
     558                        /*
     559                         * Okay, since we gathered all stuff we need until now to start the
     560                         * actual copying, start the guest part now.
     561                         */
     562                        rc = pGuest->ExecuteProcess(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
     563                                                      ExecuteProcessFlag_Hidden
     564                                                    | ExecuteProcessFlag_WaitForProcessStartOnly,
     565                                                    ComSafeArrayAsInParam(args),
     566                                                    ComSafeArrayAsInParam(env),
     567                                                    Bstr(aTask->strUserName).raw(),
     568                                                    Bstr(aTask->strPassword).raw(),
     569                                                    5 * 1000 /* Wait 5s for getting the process started. */,
     570                                                    &uPID, execProgress.asOutParam());
     571                        if (FAILED(rc))
     572                            rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest);
     573                    }
     574
     575                    if (SUCCEEDED(rc))
     576                    {
     577                        BOOL fCompleted = FALSE;
     578                        BOOL fCanceled = FALSE;
     579
     580                        size_t cbToRead = cbSize;
     581                        size_t cbTransfered = 0;
     582                        size_t cbRead;
     583                        SafeArray<BYTE> aInputData(_64K);
     584                        while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
     585                               && !fCompleted)
     586                        {
     587                            if (!cbToRead)
     588                                cbRead = 0;
     589                            else
     590                            {
     591                                vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(),
     592                                                 RT_MIN(cbToRead, _64K), &cbRead);
     593                                /*
     594                                 * Some other error occured? There might be a chance that RTFileRead
     595                                 * could not resolve/map the native error code to an IPRT code, so just
     596                                 * print a generic error.
     597                                 */
     598                                if (RT_FAILURE(vrc))
     599                                {
     600                                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     601                                                                         Guest::tr("Could not read from file \"%s\" (%Rrc)"),
     602                                                                         aTask->strSource.c_str(), vrc);
     603                                    break;
     604                                }
     605                            }
     606
     607                            /* Resize buffer to reflect amount we just have read.
     608                             * Size 0 is allowed! */
     609                            aInputData.resize(cbRead);
     610
     611                            ULONG uFlags = ProcessInputFlag_None;
     612                            /* Did we reach the end of the content we want to transfer (last chunk)? */
     613                            if (   (cbRead < _64K)
     614                                /* Did we reach the last block which is exactly _64K? */
     615                                || (cbToRead - cbRead == 0)
     616                                /* ... or does the user want to cancel? */
     617                                || (   SUCCEEDED(aTask->progress->COMGETTER(Canceled(&fCanceled)))
     618                                    && fCanceled)
     619                               )
     620                            {
     621                                uFlags |= ProcessInputFlag_EndOfFile;
     622                            }
     623
     624                            /* Transfer the current chunk ... */
     625                            ULONG uBytesWritten;
     626                            rc = pGuest->SetProcessInput(uPID, uFlags,
     627                                                         10 * 1000 /* Wait 10s for getting the input data transfered. */,
     628                                                         ComSafeArrayAsInParam(aInputData), &uBytesWritten);
     629                            if (FAILED(rc))
     630                            {
     631                                rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest);
     632                                break;
     633                            }
     634
     635                            Assert(cbRead <= cbToRead);
     636                            Assert(cbToRead >= cbRead);
     637                            cbToRead -= cbRead;
     638
     639                            cbTransfered += uBytesWritten;
     640                            Assert(cbTransfered <= cbSize);
     641                            aTask->progress->SetCurrentOperationProgress(cbTransfered / (cbSize / 100.0));
     642
     643                            /* End of file reached? */
     644                            if (cbToRead == 0)
     645                                break;
     646
     647                            /* Did the user cancel the operation above? */
     648                            if (fCanceled)
     649                                break;
     650
     651                            /* Progress canceled by Main API? */
     652                            if (   SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled)))
     653                                && fCanceled)
     654                            {
     655                                rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     656                                                                     Guest::tr("Copy operation of file \"%s\" was canceled on guest side"),
     657                                                                     aTask->strSource.c_str());
     658                                break;
     659                            }
     660                        }
     661
     662                        if (SUCCEEDED(rc))
     663                        {
     664                            /*
     665                             * If we got here this means the started process either was completed,
     666                             * canceled or we simply got all stuff transferred.
     667                             */
     668                            ExecuteProcessStatus_T retStatus;
     669                            ULONG uRetExitCode;
     670                            rc = pGuest->waitForProcessStatusChange(uPID, &retStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */);
     671                            if (FAILED(rc))
     672                            {
     673                                rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest);
     674                            }
     675                            else
     676                            {
     677                                if (   uRetExitCode != 0
     678                                    || retStatus    != ExecuteProcessStatus_TerminatedNormally)
     679                                {
     680                                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     681                                                                         Guest::tr("Guest reported error %u while copying file \"%s\" to \"%s\""),
     682                                                                         uRetExitCode, aTask->strSource.c_str(), aTask->strDest.c_str());
     683                                }
     684                            }
     685                        }
     686
     687                        if (SUCCEEDED(rc))
     688                        {
     689                            if (fCanceled)
     690                            {
     691                                /*
     692                                 * In order to make the progress object to behave nicely, we also have to
     693                                 * notify the object with a complete event when it's canceled.
     694                                 */
     695                                aTask->progress->notifyComplete(VBOX_E_IPRT_ERROR,
     696                                                                COM_IIDOF(IGuest),
     697                                                                Guest::getStaticComponentName(),
     698                                                                Guest::tr("Copying file \"%s\" canceled"), aTask->strSource.c_str());
     699                            }
     700                            else
     701                            {
     702                                /*
     703                                 * Even if we succeeded until here make sure to check whether we really transfered
     704                                 * everything.
     705                                 */
     706                                if (   cbSize > 0
     707                                    && cbTransfered == 0)
     708                                {
     709                                    /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
     710                                     * to the destination -> access denied. */
     711                                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     712                                                                         Guest::tr("Access denied when copying file \"%s\" to \"%s\""),
     713                                                                         aTask->strSource.c_str(), aTask->strDest.c_str());
     714                                }
     715                                else if (cbTransfered < cbSize)
     716                                {
     717                                    /* If we did not copy all let the user know. */
     718                                    rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress,
     719                                                                         Guest::tr("Copying file \"%s\" failed (%u/%u bytes transfered)"),
     720                                                                         aTask->strSource.c_str(), cbTransfered, cbSize);
     721                                }
     722                                else /* Yay, all went fine! */
     723                                    aTask->progress->notifyComplete(S_OK);
     724                            }
     725                        }
     726                    }
     727                }
     728                RTFileClose(fileSource);
     729            }
     730        }
     731#endif
     732    }
     733    catch (HRESULT aRC)
     734    {
     735        rc = aRC;
     736    }
     737
     738    /* Clean up */
     739    aTask->rc = rc;
     740
     741    LogFlowFunc(("rc=%Rhrc\n", rc));
     742    LogFlowFuncLeave();
     743
     744    return VINF_SUCCESS;
     745}
     746
    460747HRESULT Guest::taskUpdateGuestAdditions(TaskGuest *aTask)
    461748{
     
    9451232            AssertPtr(pCBData);
    9461233            AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbParms, VERR_INVALID_PARAMETER);
    947             AssertReturn(CALLBACKDATAMAGICCLIENTDISCONNECTED == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1234            AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    9481235
    9491236            rc = pGuest->notifyCtrlClientDisconnected(u32Function, pCBData);
     
    9581245            AssertPtr(pCBData);
    9591246            AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbParms, VERR_INVALID_PARAMETER);
    960             AssertReturn(CALLBACKDATAMAGICEXECSTATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1247            AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    9611248
    9621249            rc = pGuest->notifyCtrlExecStatus(u32Function, pCBData);
     
    9711258            AssertPtr(pCBData);
    9721259            AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbParms, VERR_INVALID_PARAMETER);
    973             AssertReturn(CALLBACKDATAMAGICEXECOUT == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1260            AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    9741261
    9751262            rc = pGuest->notifyCtrlExecOut(u32Function, pCBData);
     
    9841271            AssertPtr(pCBData);
    9851272            AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbParms, VERR_INVALID_PARAMETER);
    986             AssertReturn(CALLBACKDATAMAGICEXECINSTATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1273            AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    9871274
    9881275            rc = pGuest->notifyCtrlExecInStatus(u32Function, pCBData);
     
    16361923                        paParms[i++].setUInt32(aTimeoutMS);
    16371924
    1638                     VMMDev *vmmDev;
     1925                    VMMDev *pVMMDev = NULL;
    16391926                    {
    16401927                        /* Make sure mParent is valid, so set the read lock while using.
     
    16451932                        /* Forward the information to the VMM device. */
    16461933                        AssertPtr(mParent);
    1647                         vmmDev = mParent->getVMMDev();
     1934                        pVMMDev = mParent->getVMMDev();
    16481935                    }
    16491936
    1650                     if (vmmDev)
     1937                    if (pVMMDev)
    16511938                    {
    16521939                        LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
    1653                         vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
     1940                        vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
    16541941                                                   i, paParms);
    16551942                    }
     
    19172204
    19182205            {
    1919                 VMMDev *vmmDev;
     2206                VMMDev *pVMMDev = NULL;
    19202207                {
    19212208                    /* Make sure mParent is valid, so set the read lock while using.
     
    19262213                    /* Forward the information to the VMM device. */
    19272214                    AssertPtr(mParent);
    1928                     vmmDev = mParent->getVMMDev();
     2215                    pVMMDev = mParent->getVMMDev();
    19292216                }
    19302217
    1931                 if (vmmDev)
     2218                if (pVMMDev)
    19322219                {
    19332220                    LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
    1934                     vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_SET_INPUT,
     2221                    vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_SET_INPUT,
    19352222                                               i, paParms);
    19362223                }
     
    20932380
    20942381        {
    2095             VMMDev *vmmDev;
     2382            VMMDev *pVMMDev = NULL;
    20962383            {
    20972384                /* Make sure mParent is valid, so set the read lock while using.
     
    21022389                /* Forward the information to the VMM device. */
    21032390                AssertPtr(mParent);
    2104                 vmmDev = mParent->getVMMDev();
     2391                pVMMDev = mParent->getVMMDev();
    21052392            }
    21062393
    2107             if (vmmDev)
     2394            if (pVMMDev)
    21082395            {
    21092396                LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
    2110                 vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_GET_OUTPUT,
     2397                vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_GET_OUTPUT,
    21112398                                           i, paParms);
    21122399            }
     
    22682555}
    22692556
    2270 STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest,
    2271                                 IN_BSTR aUserName, IN_BSTR aPassword,
    2272                                 ULONG aFlags, IProgress **aProgress)
     2557STDMETHODIMP Guest::CopyFromGuest(IN_BSTR aSource, IN_BSTR aDest,
     2558                                  IN_BSTR aUserName, IN_BSTR aPassword,
     2559                                  ULONG aFlags, IProgress **aProgress)
    22732560{
    22742561#ifndef VBOX_WITH_GUEST_CONTROL
     
    23062593
    23072594        rc = progress->init(static_cast<IGuest*>(this),
    2308                             Bstr(tr("Copying file")).raw(),
     2595                            Bstr(tr("Copying file from guest to host")).raw(),
    23092596                            TRUE /* aCancelable */);
    23102597        if (FAILED(rc)) throw rc;
    23112598
    23122599        /* Initialize our worker task. */
    2313         TaskGuest *pTask = new TaskGuest(TaskGuest::CopyFile, this, progress);
     2600        TaskGuest *pTask = new TaskGuest(TaskGuest::CopyFileFromGuest, this, progress);
     2601        AssertPtr(pTask);
     2602        std::auto_ptr<TaskGuest> task(pTask);
     2603
     2604        /* Assign data - aSource is the source file on the guest,
     2605         * aDest reflects the full path on the host. */
     2606        task->strSource   = (Utf8Str(aSource));
     2607        task->strDest     = (Utf8Str(aDest));
     2608        task->strUserName = (Utf8Str(aUserName));
     2609        task->strPassword = (Utf8Str(aPassword));
     2610        task->uFlags      = aFlags;
     2611
     2612        rc = task->startThread();
     2613        if (FAILED(rc)) throw rc;
     2614
     2615        /* Don't destruct on success. */
     2616        task.release();
     2617    }
     2618    catch (HRESULT aRC)
     2619    {
     2620        rc = aRC;
     2621    }
     2622
     2623    if (SUCCEEDED(rc))
     2624    {
     2625        /* Return progress to the caller. */
     2626        progress.queryInterfaceTo(aProgress);
     2627    }
     2628    return rc;
     2629#endif /* VBOX_WITH_GUEST_CONTROL */
     2630}
     2631
     2632STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest,
     2633                                IN_BSTR aUserName, IN_BSTR aPassword,
     2634                                ULONG aFlags, IProgress **aProgress)
     2635{
     2636#ifndef VBOX_WITH_GUEST_CONTROL
     2637    ReturnComNotImplemented();
     2638#else /* VBOX_WITH_GUEST_CONTROL */
     2639    CheckComArgStrNotEmptyOrNull(aSource);
     2640    CheckComArgStrNotEmptyOrNull(aDest);
     2641    CheckComArgStrNotEmptyOrNull(aUserName);
     2642    CheckComArgStrNotEmptyOrNull(aPassword);
     2643    CheckComArgOutPointerValid(aProgress);
     2644
     2645    AutoCaller autoCaller(this);
     2646    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2647
     2648    /* Validate flags. */
     2649    if (aFlags != CopyFileFlag_None)
     2650    {
     2651        if (   !(aFlags & CopyFileFlag_Recursive)
     2652            && !(aFlags & CopyFileFlag_Update)
     2653            && !(aFlags & CopyFileFlag_FollowLinks))
     2654        {
     2655            return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
     2656        }
     2657    }
     2658
     2659    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     2660
     2661    HRESULT rc = S_OK;
     2662
     2663    ComObjPtr<Progress> progress;
     2664    try
     2665    {
     2666        /* Create the progress object. */
     2667        progress.createObject();
     2668
     2669        rc = progress->init(static_cast<IGuest*>(this),
     2670                            Bstr(tr("Copying file from host to guest")).raw(),
     2671                            TRUE /* aCancelable */);
     2672        if (FAILED(rc)) throw rc;
     2673
     2674        /* Initialize our worker task. */
     2675        TaskGuest *pTask = new TaskGuest(TaskGuest::CopyFileToGuest, this, progress);
    23142676        AssertPtr(pTask);
    23152677        std::auto_ptr<TaskGuest> task(pTask);
     
    23432705}
    23442706
    2345 STDMETHODIMP Guest::CreateDirectory(IN_BSTR aDirectory,
     2707STDMETHODIMP Guest::DirectoryClose(ULONG aHandle)
     2708{
     2709#ifndef VBOX_WITH_GUEST_CONTROL
     2710    ReturnComNotImplemented();
     2711#else /* VBOX_WITH_GUEST_CONTROL */
     2712    using namespace guestControl;
     2713
     2714    return VBOX_E_NOT_SUPPORTED;
     2715#endif
     2716}
     2717
     2718STDMETHODIMP Guest::DirectoryCreate(IN_BSTR aDirectory,
    23462719                                    IN_BSTR aUserName, IN_BSTR aPassword,
    2347                                     ULONG aMode, ULONG aFlags,
    2348                                     IProgress **aProgress)
     2720                                    ULONG aMode, ULONG aFlags)
    23492721{
    23502722#ifndef VBOX_WITH_GUEST_CONTROL
     
    23622734            Utf8Str(aDirectory).c_str(), Utf8Str(aUserName).c_str()));
    23632735
    2364     return createDirectoryInternal(aDirectory,
     2736    return directoryCreateInternal(aDirectory,
    23652737                                   aUserName, aPassword,
    2366                                    aMode, aFlags, aProgress, NULL /* rc */);
     2738                                   aMode, aFlags, NULL /* rc */);
    23672739#endif
    23682740}
    23692741
    2370 HRESULT Guest::createDirectoryInternal(IN_BSTR aDirectory,
     2742HRESULT Guest::directoryCreateInternal(IN_BSTR aDirectory,
    23712743                                       IN_BSTR aUserName, IN_BSTR aPassword,
    2372                                        ULONG aMode, ULONG aFlags,
    2373                                        IProgress **aProgress, int *pRC)
     2744                                       ULONG aMode, ULONG aFlags, int *pRC)
    23742745{
    23752746#ifndef VBOX_WITH_GUEST_CONTROL
     
    23792750
    23802751    CheckComArgStrNotEmptyOrNull(aDirectory);
    2381     CheckComArgOutPointerValid(aProgress);
    23822752
    23832753    AutoCaller autoCaller(this);
     
    23852755
    23862756    /* Validate flags. */
    2387     if (aFlags != CreateDirectoryFlag_None)
    2388     {
    2389         if (!(aFlags & CreateDirectoryFlag_Parents))
     2757    if (aFlags != DirectoryCreateFlag_None)
     2758    {
     2759        if (!(aFlags & DirectoryCreateFlag_Parents))
    23902760        {
    23912761            return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
    23922762        }
    23932763    }
    2394 
    2395     /**
    2396      * @todo We return a progress object because we maybe later want to
    2397      *       process more than one directory (or somewhat lengthly operations)
    2398      *       that require having a progress object provided to the caller.
    2399      */
    24002764
    24012765    HRESULT rc = S_OK;
     
    24122776         * Prepare tool command line.
    24132777         */
    2414         if (aFlags & CreateDirectoryFlag_Parents)
     2778        if (aFlags & DirectoryCreateFlag_Parents)
    24152779            args.push_back(Bstr("--parents").raw());        /* We also want to create the parent directories. */
    24162780        if (aMode > 0)
     
    24442808        {
    24452809            /* Wait for process to exit ... */
     2810            rc = progressExec->WaitForCompletion(-1);
     2811            if (FAILED(rc)) return rc;
     2812
    24462813            BOOL fCompleted = FALSE;
    24472814            BOOL fCanceled = FALSE;
    2448 
    2449             while (   SUCCEEDED(progressExec->COMGETTER(Completed(&fCompleted)))
    2450                    && !fCompleted)
    2451             {
    2452                 /* Progress canceled by Main API? */
    2453                 if (   SUCCEEDED(progressExec->COMGETTER(Canceled(&fCanceled)))
    2454                     && fCanceled)
    2455                 {
    2456                     break;
    2457                 }
    2458             }
    2459 
    2460             ComObjPtr<Progress> progressCreate;
    2461             rc = progressCreate.createObject();
    2462             if (SUCCEEDED(rc))
    2463             {
    2464                 rc = progressCreate->init(static_cast<IGuest*>(this),
    2465                                           Bstr(tr("Creating directory")).raw(),
    2466                                           TRUE);
    2467             }
    2468             if (FAILED(rc)) return rc;
     2815            progressExec->COMGETTER(Completed)(&fCompleted);
     2816            if (!fCompleted)
     2817                progressExec->COMGETTER(Canceled)(&fCanceled);
    24692818
    24702819            if (fCompleted)
     
    24782827                    {
    24792828                        rc = setError(VBOX_E_IPRT_ERROR,
    2480                                       tr("Error %u while creating directory"), uRetExitCode);
     2829                                      tr("Error %u while creating guest directory"), uRetExitCode);
    24812830                    }
    24822831                }
     
    24842833            else if (fCanceled)
    24852834                rc = setError(VBOX_E_IPRT_ERROR,
    2486                                       tr("Directory creation was aborted"));
     2835                              tr("Guest directory creation was aborted"));
    24872836            else
    2488                 AssertReleaseMsgFailed(("Directory creation neither completed nor canceled!?"));
    2489 
    2490             if (SUCCEEDED(rc))
    2491                 progressCreate->notifyComplete(S_OK);
    2492             else
    2493                 progressCreate->notifyComplete(VBOX_E_IPRT_ERROR,
    2494                                                COM_IIDOF(IGuest),
    2495                                                Guest::getStaticComponentName(),
    2496                                                Guest::tr("Error while executing creation command"));
    2497 
    2498             /* Return the progress to the caller. */
    2499             progressCreate.queryInterfaceTo(aProgress);
     2837                AssertReleaseMsgFailed(("Guest directory creation neither completed nor canceled!?"));
    25002838        }
    25012839    }
     
    25062844    return rc;
    25072845#endif /* VBOX_WITH_GUEST_CONTROL */
     2846}
     2847
     2848STDMETHODIMP Guest::DirectoryOpen(IN_BSTR aDirectory, IN_BSTR aFilter,
     2849                                  ULONG aFlags, IN_BSTR aUserName, IN_BSTR aPassword,
     2850                                  ULONG *aHandle)
     2851{
     2852#ifndef VBOX_WITH_GUEST_CONTROL
     2853    ReturnComNotImplemented();
     2854#else /* VBOX_WITH_GUEST_CONTROL */
     2855    using namespace guestControl;
     2856
     2857    CheckComArgStrNotEmptyOrNull(aDirectory);
     2858    CheckComArgStrNotEmptyOrNull(aUserName);
     2859    CheckComArgStrNotEmptyOrNull(aPassword);
     2860    CheckComArgNotNull(aHandle);
     2861
     2862    AutoCaller autoCaller(this);
     2863    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2864
     2865    /* Validate flags. */
     2866    if (aFlags != DirectoryOpenFlag_None)
     2867        return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
     2868
     2869    HRESULT rc = S_OK;
     2870    try
     2871    {
     2872        Utf8Str Utf8Dir(aDirectory);
     2873        Utf8Str UtfFilter(aFilter);
     2874        Utf8Str Utf8UserName(aUserName);
     2875        Utf8Str Utf8Password(aPassword);
     2876
     2877        /*
     2878         * Create progress object.
     2879         * This progress object, compared to the one in executeProgress() above
     2880         * is only local and is used to determine whether the operation finished
     2881         * or got canceled.
     2882         */
     2883        ComObjPtr <Progress> progress;
     2884        rc = progress.createObject();
     2885        if (SUCCEEDED(rc))
     2886        {
     2887            rc = progress->init(static_cast<IGuest*>(this),
     2888                                Bstr(tr("Getting output of process")).raw(),
     2889                                TRUE /* Cancelable */);
     2890        }
     2891        if (FAILED(rc)) return rc;
     2892
     2893        PCALLBACKDATADIROPEN pData = (PCALLBACKDATADIROPEN)RTMemAlloc(sizeof(CALLBACKDATADIROPEN));
     2894        AssertReturn(pData, VBOX_E_IPRT_ERROR);
     2895        RT_ZERO(*pData);
     2896        uint32_t uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START,
     2897                                                     pData, sizeof(CALLBACKDATADIROPEN), progress);
     2898        Assert(uContextID > 0);
     2899
     2900        VBOXHGCMSVCPARM paParms[8];
     2901        int i = 0;
     2902        paParms[i++].setUInt32(uContextID);
     2903        paParms[i++].setPointer((void*)Utf8Dir.c_str(), (uint32_t)Utf8Dir.length() + 1);
     2904        paParms[i++].setPointer((void*)UtfFilter.c_str(), (uint32_t)UtfFilter.length() + 1);
     2905        paParms[i++].setUInt32(0 /* Flags, none set yet */);
     2906        paParms[i++].setPointer((void*)Utf8UserName.c_str(), (uint32_t)Utf8UserName.length() + 1);
     2907        paParms[i++].setPointer((void*)Utf8Password.c_str(), (uint32_t)Utf8Password.length() + 1);
     2908
     2909        int vrc = VINF_SUCCESS;
     2910        {
     2911            VMMDev *pVMMDev = NULL;
     2912            {
     2913                /* Make sure mParent is valid, so set the read lock while using.
     2914                 * Do not keep this lock while doing the actual call, because in the meanwhile
     2915                 * another thread could request a write lock which would be a bad idea ... */
     2916                AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     2917
     2918                /* Forward the information to the VMM device. */
     2919                AssertPtr(mParent);
     2920                pVMMDev = mParent->getVMMDev();
     2921            }
     2922
     2923            if (pVMMDev)
     2924            {
     2925                LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
     2926                vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_DIR_OPEN,
     2927                                            i, paParms);
     2928            }
     2929        }
     2930
     2931        if (RT_SUCCESS(vrc))
     2932        {
     2933            /*
     2934             * Wait for the HGCM low level callback until the process
     2935             * has been started (or something went wrong). This is necessary to
     2936             * get the PID.
     2937             */
     2938            CallbackMapIter it = getCtrlCallbackContextByID(uContextID);
     2939            Assert(it != mCallbackMap.end());
     2940            ComAssert(!it->second.pProgress.isNull());
     2941
     2942            BOOL fCanceled = FALSE;
     2943
     2944            /* Wait until operation completed. */
     2945            rc = it->second.pProgress->WaitForCompletion(10 * 1000);
     2946            if (FAILED(rc)) throw rc;
     2947
     2948            /* Was the operation canceled by one of the parties? */
     2949            rc = it->second.pProgress->COMGETTER(Canceled)(&fCanceled);
     2950            if (FAILED(rc)) throw rc;
     2951
     2952            if (!fCanceled)
     2953            {
     2954                BOOL fCompleted;
     2955                if (   SUCCEEDED(it->second.pProgress->COMGETTER(Completed)(&fCompleted))
     2956                    && fCompleted)
     2957                {
     2958                    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     2959
     2960                    /* Did we get some output? */
     2961                    pData = (PCALLBACKDATADIROPEN)it->second.pvData;
     2962                    Assert(it->second.cbData == sizeof(PCALLBACKDATADIROPEN));
     2963                    AssertPtr(pData);
     2964                }
     2965                else /* If callback not called within time ... well, that's a timeout! */
     2966                    vrc = VERR_TIMEOUT;
     2967            }
     2968            else /* Operation was canceled. */
     2969            {
     2970                vrc = VERR_CANCELLED;
     2971            }
     2972
     2973            if (RT_FAILURE(vrc))
     2974            {
     2975                if (vrc == VERR_NO_DATA)
     2976                {
     2977                    /* If there was no output data then this is no error we want
     2978                     * to report to COM. The caller just gets back a size of 0 (zero). */
     2979                    rc = S_OK;
     2980                }
     2981                else if (vrc == VERR_TIMEOUT)
     2982                {
     2983                    rc = setError(VBOX_E_IPRT_ERROR,
     2984                                  tr("The guest did not output within time"));
     2985                }
     2986                else if (vrc == VERR_CANCELLED)
     2987                {
     2988                    rc = setError(VBOX_E_IPRT_ERROR,
     2989                                  tr("The output operation was canceled"));
     2990                }
     2991                else
     2992                {
     2993                    rc = setError(E_UNEXPECTED,
     2994                                  tr("The service call failed with error %Rrc"), vrc);
     2995                }
     2996            }
     2997
     2998            {
     2999                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     3000                /* Destroy locally used progress object. */
     3001                destroyCtrlCallbackContext(it);
     3002            }
     3003        }
     3004        else /* HGCM operation failed. */
     3005            rc = setError(E_UNEXPECTED,
     3006                          tr("The HGCM call failed with error %Rrc"), vrc);
     3007
     3008        /* Cleanup. */
     3009        progress->uninit();
     3010        progress.setNull();
     3011    }
     3012    catch (std::bad_alloc &)
     3013    {
     3014        rc = E_OUTOFMEMORY;
     3015    }
     3016    return rc;
     3017#endif
     3018}
     3019
     3020STDMETHODIMP Guest::DirectoryRead(ULONG aHandle, IGuestDirEntry **aDirEntry)
     3021{
     3022#ifndef VBOX_WITH_GUEST_CONTROL
     3023    ReturnComNotImplemented();
     3024#else /* VBOX_WITH_GUEST_CONTROL */
     3025    using namespace guestControl;
     3026
     3027    return VBOX_E_NOT_SUPPORTED;
     3028#endif
     3029}
     3030
     3031STDMETHODIMP Guest::FileExists(IN_BSTR aFile, IN_BSTR aUserName, IN_BSTR aPassword, BOOL *aExists)
     3032{
     3033#ifndef VBOX_WITH_GUEST_CONTROL
     3034    ReturnComNotImplemented();
     3035#else /* VBOX_WITH_GUEST_CONTROL */
     3036    using namespace guestControl;
     3037
     3038    return VBOX_E_NOT_SUPPORTED;
     3039#endif
    25083040}
    25093041
     
    25703102#endif /* VBOX_WITH_GUEST_CONTROL */
    25713103}
     3104
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