VirtualBox

Changeset 38290 in vbox


Ignore:
Timestamp:
Aug 3, 2011 9:22:12 AM (13 years ago)
Author:
vboxsync
Message:

GuestCtrl: Update.

Location:
trunk/src/VBox
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxGINA/Helper.cpp

    r36447 r38290  
    1717
    1818#include <windows.h>
     19#ifndef TARGET_NT4
     20# include <Wtsapi32.h>
     21#endif
    1922#include "winwlx.h"
    2023#include "Helper.h"
     
    5962bool isRemoteSession(void)
    6063{
    61     return (0 != GetSystemMetrics(SM_REMOTESESSION)) ? true : false;
     64    bool fIsRemote = false;
     65
     66#if 0
     67#ifndef TARGET_NT4
     68    WTS_SESSION_INFO *pSessionInfo = NULL;
     69    DWORD dwSessions;
     70    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,
     71                             0 /* Reserved */,
     72                             1 /* Version */,
     73                             &pSessionInfo,
     74                             &dwSessions))
     75    {
     76        DWORD dwRemoteSessions = 0;
     77        for (DWORD i = 0; i < dwSessions; i++)
     78        {
     79            switch (pSessionInfo[i].State)
     80            {
     81                case WTSConnected:
     82                case WTSActive:
     83                {
     84                    LPTSTR pBuffer;
     85                    DWORD cbBuffer;
     86                    if (  WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
     87                                                     pSessionInfo[i].SessionId,
     88                                                     WTSClientProtocolType,
     89                                                     &pBuffer, &cbBuffer)
     90                        && pBuffer
     91                        && cbBuffer)
     92                    {
     93                        USHORT uProto = (USHORT)(pBuffer);
     94                        /* Only count RDP sessions -- these are the ones we're
     95                         * interested in here. */
     96                        if (uProto == WTS_PROTOCOL_TYPE_RDP)
     97                            dwRemoteSessions++;
     98                        WTSFreeMemory(pBuffer);
     99#ifndef DEBUG
     100                        if (dwRemoteSessions) /* Bail out as soon as possible. */
     101                            break;
     102#endif
     103                    }
     104                    break;
     105                }
     106
     107                default:
     108                    break;
     109            }
     110        }
     111
     112#ifdef DEBUG
     113        Log(("VBoxGINA: %s connections detected\n",
     114             dwRemoteSessions ? "RDP" : "No RDP"));
     115#endif
     116        if (pSessionInfo)
     117            WTSFreeMemory(pSessionInfo);
     118
     119        if (dwSessions)
     120            fIsRemote = true;
     121    }
     122#endif
     123#else
     124    LPTSTR pBuffer;
     125    DWORD cbBuffer;
     126    if (  WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
     127                                     WTS_CURRENT_SESSION,
     128                                     WTSClientProtocolType,
     129                                     &pBuffer, &cbBuffer)
     130        && pBuffer
     131        && cbBuffer)
     132    {
     133        USHORT uProto = (USHORT)(pBuffer);
     134        /* Only count RDP sessions -- these are the ones we're
     135         * interested in here. */
     136        fIsRemote = uProto == WTS_PROTOCOL_TYPE_RDP;
     137        WTSFreeMemory(pBuffer);
     138    }
     139    else
     140        Log(("VBoxGINA: Error %ld querying session information\n",
     141             GetLastError()));
     142#endif
     143
     144#ifdef DEBUG
     145    Log(("VBoxGINA: Is remote session: %s\n",
     146         fIsRemote ? "Yes" : "No"));
     147#endif
     148    return fIsRemote;
    62149}
    63150
  • trunk/src/VBox/Additions/WINNT/VBoxGINA/Makefile.kmk

    r28800 r38290  
    3131        $(VBOX_LIB_IPRT_GUEST_R3) \
    3232        $(VBOX_LIB_VBGL_R3)
     33ifndef TARGET_NT4
     34 VBoxGINA_LIBS   += \
     35        WtsApi32.lib
     36endif
    3337
    3438include $(KBUILD_PATH)/subfooter.kmk
  • trunk/src/VBox/Additions/WINNT/VBoxGINA/VBoxGINA.cpp

    r37638 r38290  
    107107    HINSTANCE hDll;
    108108
    109 #ifdef DEBUG
    110     /* enable full log output */
    111     RTLogGroupSettings(RTLogDefaultInstance(), "all=~0");
     109#ifdef DEBUG_andy
     110    /* Enable full log output. */
     111    RTLogGroupSettings(RTLogRelDefaultInstance(), "+default.e.l.f.l2.l3");
    112112#endif
    113113
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r38235 r38290  
    12041204        rc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir);
    12051205
     1206    if (RT_FAILURE(rc))
     1207        return rc;
     1208
    12061209    /* Flag indicating whether the current directory was created on the
    12071210     * target or not. */
  • trunk/src/VBox/Main/Makefile.kmk

    r38235 r38290  
    677677ifdef VBOX_WITH_GUEST_CONTROL
    678678VBoxC_SOURCES += \
    679         src-client/GuestCtrlImplTasks.cpp
     679        src-client/GuestCtrlImplTasks.cpp \
     680        src-client/GuestDirEntryImpl.cpp
    680681endif
    681682
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r38269 r38290  
    3737
    3838/** Structure representing the "value" side of a "key=value" pair. */
    39 typedef struct VBOXGUESTCTRL_STREAM_PAIR
     39typedef struct VBOXGUESTCTRL_STREAMPAIR
    4040{
    4141    char *pszValue;
    42 } VBOXGUESTCTRL_STREAM_PAIR, *PVBOXGUESTCTRL_STREAM_PAIR;
     42} VBOXGUESTCTRL_STREAMPAIR, *PVBOXGUESTCTRL_STREAM_PAIR;
    4343
    4444/** Map containing "key=value" pairs of a guest process stream. */
    45 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM_PAIR > GuestCtrlStreamPairs;
    46 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM_PAIR >::iterator GuestCtrlStreamPairsIter;
    47 typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAM_PAIR >::const_iterator GuestCtrlStreamPairsIterConst;
     45typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAMPAIR > GuestCtrlStreamPairs;
     46typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAMPAIR >::iterator GuestCtrlStreamPairsIter;
     47typedef std::map< Utf8Str, VBOXGUESTCTRL_STREAMPAIR >::const_iterator GuestCtrlStreamPairsIterConst;
    4848
    4949/**
     
    9090/**
    9191 * Class for parsing machine-readable guest process output by VBoxService'
    92  * toolbox commands ("vbox_ls", "vbox_stat" etc).
     92 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
    9393 */
    9494class GuestProcessStream
  • trunk/src/VBox/Main/include/GuestImpl.h

    r38269 r38290  
    141141                                  IN_BSTR aUsername, IN_BSTR aPassword,
    142142                                  IProgress **aProgress, ULONG *aPID);
    143     HRESULT executeCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects);
    144143    HRESULT executeProcessInternal(IN_BSTR aCommand, ULONG aFlags,
    145144                                   ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
    146145                                   IN_BSTR aUsername, IN_BSTR aPassword,
    147146                                   ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC);
     147    HRESULT executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID);
     148    HRESULT executeStreamCollectBlock(ULONG aPID,
     149                                      GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock);
     150    HRESULT executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects);
     151    HRESULT executeWaitForStatusChange(ULONG uPID, ULONG uTimeoutMS, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode);
    148152    HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC);
    149153    HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC);
     
    215219    typedef struct VBOXGUESTCTRL_DIRECTORY
    216220    {
    217         char    *mpszDirectory;
    218         char    *mpszFilter;
    219         ULONG    mFlags;
     221        char                       *mpszDirectory;
     222        char                       *mpszFilter;
     223        ULONG                       mFlags;
    220224        /** Associated PID of started vbox_ls tool. */
    221         uint32_t mPID;
    222         /** Offset within the current retrieved stdout buffer. */
    223         uint64_t mOffset;
     225        uint32_t                    mPID;
     226        GuestProcessStream          mStream;
     227#if 0
     228        /** Next enetry in our stream objects vector
     229         *  to process. */
     230        uint32_t                    mNextEntry;
     231        /** The guest stream object containing all */
     232        GuestCtrlStreamObjects      mStream;
     233#endif
    224234    } VBOXGUESTCTRL_DIRECTORY, *PVBOXGUESTCTRL_DIRECTORY;
    225235    typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY > GuestDirectoryMap;
     
    230240    void directoryDestroyHandle(uint32_t uHandle);
    231241    uint32_t directoryGetPID(uint32_t uHandle);
     242    int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock);
    232243    bool directoryHandleExists(uint32_t uHandle);
    233244
     
    240251    HRESULT handleErrorCompletion(int rc);
    241252    HRESULT handleErrorHGCM(int rc);
    242 
    243     HRESULT waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS);
    244     HRESULT executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID);
    245253# endif
    246254
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r38270 r38290  
    972972    return hRC;
    973973}
    974 
    975 HRESULT Guest::waitForProcessStatusChange(ULONG uPID, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode, ULONG uTimeoutMS)
    976 {
    977     AssertPtr(pRetStatus);
    978     AssertPtr(puRetExitCode);
    979 
    980     if (uTimeoutMS == 0)
    981         uTimeoutMS = UINT32_MAX;
    982 
    983     uint64_t u64StartMS = RTTimeMilliTS();
    984 
    985     HRESULT hRC;
    986     ULONG uRetFlagsIgnored;
    987     do
    988     {
    989         /*
    990          * Do some busy waiting within the specified time period (if any).
    991          */
    992         if (   uTimeoutMS != UINT32_MAX
    993             && RTTimeMilliTS() - u64StartMS > uTimeoutMS)
    994         {
    995             hRC = setError(VBOX_E_IPRT_ERROR,
    996                            tr("The process (PID %u) did not change its status within time (%ums)"),
    997                            uPID, uTimeoutMS);
    998             break;
    999         }
    1000         hRC = GetProcessStatus(uPID, puRetExitCode, &uRetFlagsIgnored, pRetStatus);
    1001         if (FAILED(hRC))
    1002             break;
    1003         RTThreadSleep(100);
    1004     } while(*pRetStatus == ExecuteProcessStatus_Started && SUCCEEDED(hRC));
    1005     return hRC;
     974#endif /* VBOX_WITH_GUEST_CONTROL */
     975
     976STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
     977                                   ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
     978                                   IN_BSTR aUsername, IN_BSTR aPassword,
     979                                   ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress)
     980{
     981/** @todo r=bird: Eventually we should clean up all the timeout parameters
     982 *        in the API and have the same way of specifying infinite waits!  */
     983#ifndef VBOX_WITH_GUEST_CONTROL
     984    ReturnComNotImplemented();
     985#else  /* VBOX_WITH_GUEST_CONTROL */
     986    using namespace guestControl;
     987
     988    CheckComArgStrNotEmptyOrNull(aCommand);
     989    CheckComArgOutPointerValid(aPID);
     990    CheckComArgOutPointerValid(aProgress);
     991
     992    /* Do not allow anonymous executions (with system rights). */
     993    if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
     994        return setError(E_INVALIDARG, tr("No user name specified"));
     995
     996    LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n",
     997            Utf8Str(aCommand).c_str(), Utf8Str(aUsername).c_str()));
     998
     999    return executeProcessInternal(aCommand, aFlags, ComSafeArrayInArg(aArguments),
     1000                                  ComSafeArrayInArg(aEnvironment),
     1001                                  aUsername, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */);
     1002#endif
     1003}
     1004
     1005#ifdef VBOX_WITH_GUEST_CONTROL
     1006/**
     1007 * Executes and waits for an internal tool (that is, a tool which is integrated into
     1008 * VBoxService, beginning with "vbox_" (e.g. "vbox_ls")) to finish its operation.
     1009 *
     1010 * @return  HRESULT
     1011 * @param   aTool                   Name of tool to execute.
     1012 * @param   aDescription            Friendly description of the operation.
     1013 * @param   aFlags                  Execution flags.
     1014 * @param   aUsername               Username to execute tool under.
     1015 * @param   aPassword               The user's password.
     1016 * @param   aProgress               Pointer which receives the tool's progress object. Optional.
     1017 * @param   aPID                    Pointer which receives the tool's PID. Optional.
     1018 */
     1019HRESULT Guest::executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription,
     1020                                     ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
     1021                                     IN_BSTR aUsername, IN_BSTR aPassword,
     1022                                     IProgress **aProgress, ULONG *aPID)
     1023{
     1024    ComPtr<IProgress> progressTool;
     1025    ULONG uPID;
     1026
     1027    HRESULT rc = this->ExecuteProcess(aTool,
     1028                                      ExecuteProcessFlag_Hidden,
     1029                                      ComSafeArrayInArg(aArguments),
     1030                                      ComSafeArrayInArg(aEnvironment),
     1031                                      aUsername, aPassword,
     1032                                      5 * 1000 /* Wait 5s for getting the process started. */,
     1033                                      &uPID, progressTool.asOutParam());
     1034    if (SUCCEEDED(rc))
     1035    {
     1036        /* Wait for process to exit ... */
     1037        rc = progressTool->WaitForCompletion(-1);
     1038        if (FAILED(rc)) return rc;
     1039
     1040        BOOL fCompleted = FALSE;
     1041        BOOL fCanceled = FALSE;
     1042        progressTool->COMGETTER(Completed)(&fCompleted);
     1043        if (!fCompleted)
     1044            progressTool->COMGETTER(Canceled)(&fCanceled);
     1045
     1046        if (fCompleted)
     1047        {
     1048            ExecuteProcessStatus_T retStatus;
     1049            ULONG uRetExitCode, uRetFlags;
     1050            if (SUCCEEDED(rc))
     1051            {
     1052                rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
     1053                if (SUCCEEDED(rc))
     1054                {
     1055                    if (!uRetExitCode)
     1056                    {
     1057                        rc = setError(VBOX_E_IPRT_ERROR,
     1058                                      tr("Error %u occurred while %s"),
     1059                                      uRetExitCode, Utf8Str(aDescription).c_str());
     1060                    }
     1061                    else
     1062                    {
     1063                        if (aProgress)
     1064                        {
     1065                            /* Return the progress to the caller. */
     1066                            progressTool.queryInterfaceTo(aProgress);
     1067                        }
     1068                        if (aPID)
     1069                            *aPID = uPID;
     1070                    }
     1071                }
     1072            }
     1073        }
     1074        else if (fCanceled)
     1075        {
     1076            rc = setError(VBOX_E_IPRT_ERROR,
     1077                          tr("%s was aborted"), aDescription);
     1078        }
     1079        else
     1080            AssertReleaseMsgFailed(("Operation \"%s\" neither completed nor canceled!?\n",
     1081                                    Utf8Str(aDescription).c_str()));
     1082    }
     1083
     1084    return rc;
    10061085}
    10071086
     
    10901169    return rc;
    10911170}
    1092 #endif /* VBOX_WITH_GUEST_CONTROL */
    1093 
    1094 STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
    1095                                    ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
    1096                                    IN_BSTR aUsername, IN_BSTR aPassword,
    1097                                    ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress)
    1098 {
    1099 /** @todo r=bird: Eventually we should clean up all the timeout parameters
    1100  *        in the API and have the same way of specifying infinite waits!  */
    1101 #ifndef VBOX_WITH_GUEST_CONTROL
    1102     ReturnComNotImplemented();
    1103 #else  /* VBOX_WITH_GUEST_CONTROL */
    1104     using namespace guestControl;
    1105 
    1106     CheckComArgStrNotEmptyOrNull(aCommand);
    1107     CheckComArgOutPointerValid(aPID);
    1108     CheckComArgOutPointerValid(aProgress);
    1109 
    1110     /* Do not allow anonymous executions (with system rights). */
    1111     if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
    1112         return setError(E_INVALIDARG, tr("No user name specified"));
    1113 
    1114     LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n",
    1115             Utf8Str(aCommand).c_str(), Utf8Str(aUsername).c_str()));
    1116 
    1117     return executeProcessInternal(aCommand, aFlags, ComSafeArrayInArg(aArguments),
    1118                                   ComSafeArrayInArg(aEnvironment),
    1119                                   aUsername, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */);
    1120 #endif
    1121 }
    1122 
    1123 #ifdef VBOX_WITH_GUEST_CONTROL
     1171
    11241172/**
    1125  * Executes and waits for an internal tool (that is, a tool which is integrated into
    1126  * VBoxService, beginning with "vbox_" (e.g. "vbox_ls")) to finish its operation.
     1173 * Gets the next stream block from a formerly processed guest stream. Will return
     1174 * E_PENDING if not enough guest stream data was read yet, otherwise S_OK or an appropriate
     1175 * error.
    11271176 *
    11281177 * @return  HRESULT
    1129  * @param   aTool                   Name of tool to execute.
    1130  * @param   aDescription            Friendly description of the operation.
    1131  * @param   aFlags                  Execution flags.
    1132  * @param   aUsername               Username to execute tool under.
    1133  * @param   aPassword               The user's password.
    1134  * @param   aProgress               Pointer which receives the tool's progress object. Optional.
    1135  * @param   aPID                    Pointer which receives the tool's PID. Optional.
     1178 * @param   aPID                    PID of process to get the next stream block from.
     1179 * @param   stream                  Reference to an already filled guest process stream.
     1180 * @param   streamBlock             Reference to a stream block which receives the parsed data.
    11361181 */
    1137 HRESULT Guest::executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription,
    1138                                      ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
    1139                                      IN_BSTR aUsername, IN_BSTR aPassword,
    1140                                      IProgress **aProgress, ULONG *aPID)
    1141 {
    1142     ComPtr<IProgress> progressTool;
    1143     ULONG uPID;
    1144 
    1145     HRESULT rc = this->ExecuteProcess(aTool,
    1146                                       ExecuteProcessFlag_Hidden,
    1147                                       ComSafeArrayInArg(aArguments),
    1148                                       ComSafeArrayInArg(aEnvironment),
    1149                                       aUsername, aPassword,
    1150                                       5 * 1000 /* Wait 5s for getting the process started. */,
    1151                                       &uPID, progressTool.asOutParam());
    1152     if (SUCCEEDED(rc))
    1153     {
    1154         /* Wait for process to exit ... */
    1155         rc = progressTool->WaitForCompletion(-1);
    1156         if (FAILED(rc)) return rc;
    1157 
    1158         BOOL fCompleted = FALSE;
    1159         BOOL fCanceled = FALSE;
    1160         progressTool->COMGETTER(Completed)(&fCompleted);
    1161         if (!fCompleted)
    1162             progressTool->COMGETTER(Canceled)(&fCanceled);
    1163 
    1164         if (fCompleted)
    1165         {
    1166             ExecuteProcessStatus_T retStatus;
    1167             ULONG uRetExitCode, uRetFlags;
    1168             if (SUCCEEDED(rc))
    1169             {
    1170                 rc = GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
    1171                 if (SUCCEEDED(rc))
    1172                 {
    1173                     if (!uRetExitCode)
    1174                     {
    1175                         rc = setError(VBOX_E_IPRT_ERROR,
    1176                                       tr("Error %u occurred while %s"),
    1177                                       uRetExitCode, Utf8Str(aDescription).c_str());
    1178                     }
    1179                     else
    1180                     {
    1181                         if (aProgress)
    1182                         {
    1183                             /* Return the progress to the caller. */
    1184                             progressTool.queryInterfaceTo(aProgress);
    1185                         }
    1186                         if (aPID)
    1187                             *aPID = uPID;
    1188                     }
    1189                 }
    1190             }
    1191         }
    1192         else if (fCanceled)
    1193         {
    1194             rc = setError(VBOX_E_IPRT_ERROR,
    1195                           tr("%s was aborted"), aDescription);
    1196         }
    1197         else
    1198             AssertReleaseMsgFailed(("Operation \"%s\" neither completed nor canceled!?\n",
    1199                                     Utf8Str(aDescription).c_str()));
    1200     }
    1201 
    1202     return rc;
    1203 }
    1204 
    1205 HRESULT Guest::executeCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects)
    1206 {
     1182HRESULT Guest::executeStreamCollectBlock(ULONG aPID,
     1183                                         GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock)
     1184{
     1185    HRESULT rc = S_OK;
     1186
    12071187    SafeArray<BYTE> aOutputData;
    12081188    ULONG cbOutputData = 0;
    1209 
    1210     int rc = S_OK;
    1211     GuestProcessStream guestStream;
    1212 
     1189    int vrc = VINF_SUCCESS;
    12131190    for (;;)
    12141191    {
     
    12191196            && aOutputData.size())
    12201197        {
     1198            int vrc = stream.AddData(aOutputData.raw(), aOutputData.size());
     1199            if (RT_UNLIKELY(RT_FAILURE(vrc)))
     1200            {
     1201                rc = setError(VBOX_E_IPRT_ERROR,
     1202                              tr("Error while adding guest output to stream buffer (%Rrc)"), vrc);
     1203                break;
     1204            }
     1205            else
     1206            {
     1207                /* Try to parse the stream output we gathered until now. If we still need more
     1208                 * data the parsing routine will tell us and we just do another poll round. */
     1209                vrc = stream.ParseBlock(streamBlock);
     1210                if (RT_SUCCESS(vrc))
     1211                {
     1212                    /* Yay, we're done! */
     1213                    break;
     1214                }
     1215                else if (vrc == VERR_MORE_DATA)
     1216                {
     1217                    /* We need another poll round. */
     1218                    continue;
     1219                }
     1220                else
     1221                    rc = setError(VBOX_E_IPRT_ERROR,
     1222                                  tr("Error while parsing guest output (%Rrc)"), vrc);
     1223            }
     1224        }
     1225        else /* No more output! */
     1226        {
     1227            if (vrc == VERR_MORE_DATA)
     1228                rc = E_PENDING; /** @todo Find a better rc! */
     1229            break;
     1230        }
     1231    }
     1232
     1233    return rc;
     1234}
     1235
     1236/**
     1237 * Gets output from a formerly started guest process, tries to parse all of its guest
     1238 * stream (as long as data is available) and returns a stream object which can contain
     1239 * multiple stream blocks (which in turn then can contain key=value pairs).
     1240 *
     1241 * @return  HRESULT
     1242 * @param   aPID                    PID of process to get/parse the output from.
     1243 * @param   streamObjects           Reference to a guest stream object structure for
     1244 *                                  storing the parsed data.
     1245 */
     1246HRESULT Guest::executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects)
     1247{
     1248    HRESULT rc = S_OK;
     1249
     1250    SafeArray<BYTE> aOutputData;
     1251    ULONG cbOutputData = 0;
     1252    GuestProcessStream guestStream;
     1253
     1254    for (;;)
     1255    {
     1256        rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None,
     1257                                    10 * 1000 /* Timeout in ms */,
     1258                                    _64K, ComSafeArrayAsOutParam(aOutputData));
     1259        if (   SUCCEEDED(rc)
     1260            && aOutputData.size())
     1261        {
    12211262            int vrc = guestStream.AddData(aOutputData.raw(), aOutputData.size());
    12221263            if (RT_UNLIKELY(RT_FAILURE(vrc)))
     1264            {
    12231265                rc = setError(VBOX_E_IPRT_ERROR,
    12241266                              tr("Error while adding guest output to stream buffer (%Rrc)"), vrc);
     1267                break;
     1268            }
    12251269        }
    12261270        else /* No more output! */
     
    12301274    if (SUCCEEDED(rc))
    12311275    {
    1232         GuestProcessStreamBlock curPairs;
    1233         int vrc = guestStream.ParseBlock(curPairs);
    1234         if (   RT_SUCCESS(vrc)
    1235             || vrc == VERR_MORE_DATA)
    1236         {
    1237             /** @todo Catch exceptions! */
    1238             if (curPairs.GetCount())
    1239                 streamObjects.push_back(curPairs);
    1240         }
    1241         else
    1242             rc = setError(VBOX_E_IPRT_ERROR,
    1243                           tr("Error while parsing guest output (%Rrc)"), vrc);
     1276        for (;;)
     1277        {
     1278            GuestProcessStreamBlock curBlock;
     1279            rc = executeStreamCollectBlock(aPID,
     1280                                           guestStream, curBlock);
     1281            if (SUCCEEDED(rc))
     1282
     1283            {
     1284                if (curBlock.GetCount())
     1285                    streamObjects.push_back(curBlock);
     1286                else
     1287                    break; /* No more data. */
     1288            }
     1289            else
     1290            {
     1291                rc = setError(VBOX_E_IPRT_ERROR,
     1292                              tr("Error while parsing guest stream block"));
     1293                break;
     1294            }
     1295        }
    12441296    }
    12451297
    12461298    return rc;
     1299}
     1300
     1301/**
     1302 * Does busy waiting on a formerly started guest process.
     1303 *
     1304 * @return  HRESULT
     1305 * @param   uPID                    PID of guest process to wait for.
     1306 * @param   uTimeoutMS              Waiting timeout (in ms). Specify 0 for an infinite timeout.
     1307 * @param   pRetStatus              Pointer which receives current process status after the change.
     1308 *                                  Optional.
     1309 * @param   puRetExitCode           Pointer which receives the final exit code in case of guest process
     1310 *                                  termination. Optional.
     1311 */
     1312HRESULT Guest::executeWaitForStatusChange(ULONG uPID, ULONG uTimeoutMS,
     1313                                          ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode)
     1314{
     1315    if (uTimeoutMS == 0)
     1316        uTimeoutMS = UINT32_MAX;
     1317
     1318    uint64_t u64StartMS = RTTimeMilliTS();
     1319
     1320    HRESULT hRC;
     1321    ULONG uExitCode, uRetFlags;
     1322    ExecuteProcessStatus_T curStatus;
     1323    hRC = GetProcessStatus(uPID, &uExitCode, &uRetFlags, &curStatus);
     1324    if (FAILED(hRC))
     1325        return hRC;
     1326
     1327    do
     1328    {
     1329        if (   uTimeoutMS != UINT32_MAX
     1330            && RTTimeMilliTS() - u64StartMS > uTimeoutMS)
     1331        {
     1332            hRC = setError(VBOX_E_IPRT_ERROR,
     1333                           tr("The process (PID %u) did not change its status within time (%ums)"),
     1334                           uPID, uTimeoutMS);
     1335            break;
     1336        }
     1337        hRC = GetProcessStatus(uPID, &uExitCode, &uRetFlags, &curStatus);
     1338        if (FAILED(hRC))
     1339            break;
     1340        RTThreadSleep(100);
     1341    } while(*pRetStatus == curStatus);
     1342
     1343    if (SUCCEEDED(hRC))
     1344    {
     1345        if (pRetStatus)
     1346            *pRetStatus = curStatus;
     1347        if (puRetExitCode)
     1348            *puRetExitCode = uExitCode;
     1349    }
     1350    return hRC;
    12471351}
    12481352
  • trunk/src/VBox/Main/src-client/GuestCtrlImplDir.cpp

    r38269 r38290  
    1818#include "GuestImpl.h"
    1919#include "GuestCtrlImplPrivate.h"
     20#include "GuestDirEntryImpl.h"
    2021
    2122#include "Global.h"
     
    210211        RTStrFree(it->second.mpszFilter);
    211212
     213        /* Destroy raw guest stream buffer - not used
     214         * anymore. */
     215        it->second.mStream.Destroy();
     216
    212217        /* Remove callback context (not used anymore). */
    213218        mGuestDirectoryMap.erase(it);
     
    230235
    231236    return 0;
     237}
     238
     239int Guest::directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock)
     240{
     241    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     242
     243    GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
     244    if (it != mGuestDirectoryMap.end())
     245    {
     246        HRESULT hr = executeStreamCollectBlock(it->second.mPID,
     247                                               it->second.mStream, streamBlock);
     248        if (FAILED(hr))
     249            return VERR_INVALID_PARAMETER; /** @todo Find better rc! */
     250
     251        return VINF_SUCCESS;
     252    }
     253
     254    return VERR_NOT_FOUND;
    232255}
    233256
     
    363386    using namespace guestControl;
    364387
    365     uint32_t uPID = directoryGetPID(aHandle);
    366     if (uPID)
    367     {
    368         SafeArray<BYTE> aOutputData;
    369         ULONG cbOutputData = 0;
    370 
    371         HRESULT rc = this->GetProcessOutput(uPID, ProcessOutputFlag_None,
    372                                             30 * 1000 /* Timeout in ms */,
    373                                             _64K, ComSafeArrayAsOutParam(aOutputData));
    374         if (SUCCEEDED(rc))
     388    CheckComArgOutPointerValid(aDirEntry);
     389
     390    AutoCaller autoCaller(this);
     391    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     392
     393    HRESULT rc = S_OK;
     394    try
     395    {
     396        GuestProcessStreamBlock streamBlock;
     397        int vrc = directoryGetNextEntry(aHandle, streamBlock);
     398        if (RT_SUCCESS(vrc))
    375399        {
    376 
     400            ComObjPtr <GuestDirEntry> pDirEntry;
     401            rc = pDirEntry.createObject();
     402            ComAssertComRC(rc);
     403
     404            rc = pDirEntry->init(this, streamBlock);
     405            if (SUCCEEDED(rc))
     406            {
     407                pDirEntry.queryInterfaceTo(aDirEntry);
     408            }
     409            else
     410                rc = setError(VBOX_E_IPRT_ERROR,
     411                              Guest::tr("Unable to init guest directory entry"));
    377412        }
    378 
    379         return rc;
    380     }
    381 
    382     return setError(VBOX_E_IPRT_ERROR,
    383                     Guest::tr("Directory handle is invalid"));
     413        else
     414            rc = setError(VBOX_E_IPRT_ERROR,
     415                          Guest::tr("Directory handle is invalid"));
     416    }
     417    catch (std::bad_alloc &)
     418    {
     419        rc = E_OUTOFMEMORY;
     420    }
     421    return rc;
    384422#endif
    385423}
  • trunk/src/VBox/Main/src-client/GuestCtrlImplFile.cpp

    r38269 r38290  
    167167        {
    168168            GuestCtrlStreamObjects streamObjs;
    169             rc = executeCollectOutput(uPID, streamObjs);
     169            rc = executeStreamCollectOutput(uPID, streamObjs);
    170170            if (SUCCEEDED(rc))
    171171            {
  • trunk/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp

    r38237 r38290  
    356356                            ExecuteProcessStatus_T retStatus;
    357357                            ULONG uRetExitCode;
    358                             rc = pGuest->waitForProcessStatusChange(uPID, &retStatus, &uRetExitCode, 10 * 1000 /* 10s timeout. */);
     358                            rc = pGuest->executeWaitForStatusChange(uPID, 10 * 1000 /* 10s timeout. */,
     359                                                                    &retStatus, &uRetExitCode);
    359360                            if (FAILED(rc))
    360361                            {
Note: See TracChangeset for help on using the changeset viewer.

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