VirtualBox

Changeset 48014 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 23, 2013 9:01:29 AM (11 years ago)
Author:
vboxsync
Message:

FE/VBoxManage/GuestCtrl: Implemented handling guest file, process and session (un)registration and status changes when using "watch".

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r47926 r48014  
    6262using namespace com;
    6363
     64/** @todo Move this into a helper module. */
     65static const char *ctrlFileStatusToText(FileStatus_T enmStatus);
     66static const char *ctrlProcessStatusToText(ProcessStatus_T enmStatus);
     67static const char *ctrlSessionStatusToText(GuestSessionStatus_T enmStatus);
     68
     69class GuestFileEventListener;
     70typedef ListenerImpl<GuestFileEventListener> GuestFileEventListenerImpl;
     71VBOX_LISTENER_DECLARE(GuestFileEventListenerImpl)
     72
     73class GuestProcessEventListener;
     74typedef ListenerImpl<GuestProcessEventListener> GuestProcessEventListenerImpl;
     75VBOX_LISTENER_DECLARE(GuestProcessEventListenerImpl)
     76
     77class GuestSessionEventListener;
     78typedef ListenerImpl<GuestSessionEventListener> GuestSessionEventListenerImpl;
     79VBOX_LISTENER_DECLARE(GuestSessionEventListenerImpl)
     80
     81/** Simple statistics class for binding locally
     82 *  held data to a specific guest object. */
     83class GuestEventStats
     84{
     85
     86public:
     87
     88    GuestEventStats(void)
     89        : uLastUpdatedMS(RTTimeMilliTS())
     90    {
     91    }
     92
     93    /** @todo Make this more a class than a structure. */
     94public:
     95
     96    uint64_t uLastUpdatedMS;
     97};
     98
     99class GuestFileStats : public GuestEventStats
     100{
     101
     102public:
     103
     104    GuestFileStats(void) { }
     105
     106    GuestFileStats(ComObjPtr<GuestFileEventListenerImpl> pListenerImpl)
     107        : mListener(pListenerImpl)
     108    {
     109    }
     110
     111public: /** @todo */
     112
     113    ComObjPtr<GuestFileEventListenerImpl> mListener;
     114};
     115
     116class GuestProcStats : public GuestEventStats
     117{
     118
     119public:
     120
     121    GuestProcStats(void) { }
     122
     123    GuestProcStats(ComObjPtr<GuestProcessEventListenerImpl> pListenerImpl)
     124        : mListener(pListenerImpl)
     125    {
     126    }
     127
     128public: /** @todo */
     129
     130    ComObjPtr<GuestProcessEventListenerImpl> mListener;
     131};
     132
     133class GuestSessionStats : public GuestEventStats
     134{
     135
     136public:
     137
     138    GuestSessionStats(void) { }
     139
     140    GuestSessionStats(ComObjPtr<GuestSessionEventListenerImpl> pListenerImpl)
     141        : mListener(pListenerImpl)
     142    {
     143    }
     144
     145public: /** @todo */
     146
     147    ComObjPtr<GuestSessionEventListenerImpl> mListener;
     148};
     149
     150/** Map containing all watched guest files. */
     151typedef std::map< ComPtr<IGuestFile>, GuestFileStats > GuestEventFiles;
     152/** Map containing all watched guest processes. */
     153typedef std::map< ComPtr<IGuestProcess>, GuestProcStats > GuestEventProcs;
     154/** Map containing all watched guest sessions. */
     155typedef std::map< ComPtr<IGuestSession>, GuestSessionStats > GuestEventSessions;
     156
     157class GuestListenerBase
     158{
     159public:
     160
     161    GuestListenerBase(void)
     162        : mfVerbose(false)
     163    {
     164    }
     165
     166    virtual ~GuestListenerBase(void)
     167    {
     168    }
     169
     170    HRESULT init(bool fVerbose = false)
     171    {
     172        mfVerbose = fVerbose;
     173        return S_OK;
     174    }
     175
     176protected:
     177
     178    /** Verbose flag. */
     179    bool mfVerbose;
     180};
     181
     182/**
     183 *  Handler for guest process events.
     184 */
     185class GuestFileEventListener : public GuestListenerBase
     186{
     187public:
     188
     189    GuestFileEventListener(void)
     190    {
     191    }
     192
     193    virtual ~GuestFileEventListener(void)
     194    {
     195    }
     196
     197    void uninit(void)
     198    {
     199
     200    }
     201
     202    STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
     203    {
     204        switch (aType)
     205        {
     206            case VBoxEventType_OnGuestFileStateChanged:
     207            {
     208                HRESULT rc;
     209                do
     210                {
     211                    ComPtr<IGuestFileStateChangedEvent> pEvent = aEvent;
     212                    Assert(!pEvent.isNull());
     213
     214                    ComPtr<IGuestFile> pProcess;
     215                    CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pProcess.asOutParam()));
     216                    AssertBreak(!pProcess.isNull());
     217                    FileStatus_T fileSts;
     218                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&fileSts));
     219                    Bstr strPath;
     220                    CHECK_ERROR_BREAK(pProcess, COMGETTER(FileName)(strPath.asOutParam()));
     221                    ULONG uID;
     222                    CHECK_ERROR_BREAK(pProcess, COMGETTER(Id)(&uID));
     223
     224                    RTPrintf("File ID=%RU32 \"%s\" changed status to [%s]\n",
     225                             uID, Utf8Str(strPath).c_str(),
     226                             ctrlFileStatusToText(fileSts));
     227
     228                } while (0);
     229                break;
     230            }
     231
     232            default:
     233                AssertFailed();
     234        }
     235
     236        return S_OK;
     237    }
     238
     239protected:
     240
     241};
     242
     243/**
     244 *  Handler for guest process events.
     245 */
     246class GuestProcessEventListener : public GuestListenerBase
     247{
     248public:
     249
     250    GuestProcessEventListener(void)
     251    {
     252    }
     253
     254    virtual ~GuestProcessEventListener(void)
     255    {
     256    }
     257
     258    void uninit(void)
     259    {
     260
     261    }
     262
     263    STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
     264    {
     265        switch (aType)
     266        {
     267            case VBoxEventType_OnGuestProcessStateChanged:
     268            {
     269                HRESULT rc;
     270                do
     271                {
     272                    ComPtr<IGuestProcessStateChangedEvent> pEvent = aEvent;
     273                    Assert(!pEvent.isNull());
     274
     275                    ComPtr<IGuestProcess> pProcess;
     276                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam()));
     277                    AssertBreak(!pProcess.isNull());
     278                    ProcessStatus_T procSts;
     279                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&procSts));
     280                    Bstr strPath;
     281                    CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam()));
     282                    ULONG uPID;
     283                    CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID));
     284
     285                    RTPrintf("Process PID=%RU32 \"%s\" changed status to [%s]\n",
     286                             uPID, Utf8Str(strPath).c_str(),
     287                             ctrlProcessStatusToText(procSts));
     288
     289                } while (0);
     290                break;
     291            }
     292
     293            default:
     294                AssertFailed();
     295        }
     296
     297        return S_OK;
     298    }
     299
     300protected:
     301
     302};
     303
     304/**
     305 *  Handler for guest session events.
     306 */
     307class GuestSessionEventListener : public GuestListenerBase
     308{
     309public:
     310
     311    GuestSessionEventListener(void)
     312    {
     313    }
     314
     315    virtual ~GuestSessionEventListener(void)
     316    {
     317    }
     318
     319    void uninit(void)
     320    {
     321        GuestEventProcs::iterator itProc = mProcs.begin();
     322        while (itProc != mProcs.end())
     323        {
     324            if (!itProc->first.isNull())
     325            {
     326                HRESULT rc;
     327                do
     328                {
     329                    /* Listener unregistration. */
     330                    ComPtr<IEventSource> pES;
     331                    CHECK_ERROR_BREAK(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
     332                    if (!pES.isNull())
     333                        CHECK_ERROR_BREAK(pES, UnregisterListener(itProc->second.mListener));
     334                } while (0);
     335                itProc->first->Release();
     336            }
     337
     338            itProc++;
     339        }
     340        mProcs.clear();
     341
     342        GuestEventFiles::iterator itFile = mFiles.begin();
     343        while (itFile != mFiles.end())
     344        {
     345            if (!itFile->first.isNull())
     346            {
     347                HRESULT rc;
     348                do
     349                {
     350                    /* Listener unregistration. */
     351                    ComPtr<IEventSource> pES;
     352                    CHECK_ERROR_BREAK(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
     353                    if (!pES.isNull())
     354                        CHECK_ERROR_BREAK(pES, UnregisterListener(itFile->second.mListener));
     355                } while (0);
     356                itFile->first->Release();
     357            }
     358
     359            itFile++;
     360        }
     361        mFiles.clear();
     362    }
     363
     364    STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
     365    {
     366        switch (aType)
     367        {
     368            case VBoxEventType_OnGuestFileRegistered:
     369            {
     370                HRESULT rc;
     371                do
     372                {
     373                    ComPtr<IGuestFileRegisteredEvent> pEvent = aEvent;
     374                    Assert(!pEvent.isNull());
     375
     376                    ComPtr<IGuestFile> pFile;
     377                    CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pFile.asOutParam()));
     378                    AssertBreak(!pFile.isNull());
     379                    BOOL fRegistered;
     380                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
     381                    Bstr strPath;
     382                    CHECK_ERROR_BREAK(pFile, COMGETTER(FileName)(strPath.asOutParam()));
     383
     384                    RTPrintf("File \"%s\" %s\n",
     385                             Utf8Str(strPath).c_str(),
     386                             fRegistered ? "registered" : "unregistered");
     387                    if (fRegistered)
     388                    {
     389                        if (mfVerbose)
     390                            RTPrintf("Registering ...\n");
     391
     392                        /* Register for IGuestFile events. */
     393                        ComObjPtr<GuestFileEventListenerImpl> pListener;
     394                        pListener.createObject();
     395                        CHECK_ERROR_BREAK(pListener, init(new GuestFileEventListener()));
     396
     397                        ComPtr<IEventSource> es;
     398                        CHECK_ERROR_BREAK(pFile, COMGETTER(EventSource)(es.asOutParam()));
     399                        com::SafeArray<VBoxEventType_T> eventTypes;
     400                        eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
     401                        CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
     402                                                               true /* Active listener */));
     403
     404                        GuestFileStats fileStats(pListener);
     405                        mFiles[pFile] = fileStats;
     406                    }
     407                    else
     408                    {
     409                        GuestEventFiles::iterator itFile = mFiles.find(pFile);
     410                        if (itFile != mFiles.end())
     411                        {
     412                            if (mfVerbose)
     413                                RTPrintf("Unregistering file ...\n");
     414
     415                            if (!itFile->first.isNull())
     416                            {
     417                                /* Listener unregistration. */
     418                                ComPtr<IEventSource> pES;
     419                                CHECK_ERROR(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
     420                                if (!pES.isNull())
     421                                    CHECK_ERROR(pES, UnregisterListener(itFile->second.mListener));
     422                                itFile->first->Release();
     423                            }
     424
     425                            mFiles.erase(itFile);
     426                        }
     427                    }
     428
     429                } while (0);
     430                break;
     431            }
     432
     433            case VBoxEventType_OnGuestProcessRegistered:
     434            {
     435                HRESULT rc;
     436                do
     437                {
     438                    ComPtr<IGuestProcessRegisteredEvent> pEvent = aEvent;
     439                    Assert(!pEvent.isNull());
     440
     441                    ComPtr<IGuestProcess> pProcess;
     442                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam()));
     443                    AssertBreak(!pProcess.isNull());
     444                    BOOL fRegistered;
     445                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
     446                    Bstr strPath;
     447                    CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam()));
     448
     449                    RTPrintf("Process \"%s\" %s\n",
     450                             Utf8Str(strPath).c_str(),
     451                             fRegistered ? "registered" : "unregistered");
     452                    if (fRegistered)
     453                    {
     454                        if (mfVerbose)
     455                            RTPrintf("Registering ...\n");
     456
     457                        /* Register for IGuestProcess events. */
     458                        ComObjPtr<GuestProcessEventListenerImpl> pListener;
     459                        pListener.createObject();
     460                        CHECK_ERROR_BREAK(pListener, init(new GuestProcessEventListener()));
     461
     462                        ComPtr<IEventSource> es;
     463                        CHECK_ERROR_BREAK(pProcess, COMGETTER(EventSource)(es.asOutParam()));
     464                        com::SafeArray<VBoxEventType_T> eventTypes;
     465                        eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
     466                        CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
     467                                                               true /* Active listener */));
     468
     469                        GuestProcStats procStats(pListener);
     470                        mProcs[pProcess] = procStats;
     471                    }
     472                    else
     473                    {
     474                        GuestEventProcs::iterator itProc = mProcs.find(pProcess);
     475                        if (itProc != mProcs.end())
     476                        {
     477                            if (mfVerbose)
     478                                RTPrintf("Unregistering process ...\n");
     479
     480                            if (!itProc->first.isNull())
     481                            {
     482                                /* Listener unregistration. */
     483                                ComPtr<IEventSource> pES;
     484                                CHECK_ERROR(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
     485                                if (!pES.isNull())
     486                                    CHECK_ERROR(pES, UnregisterListener(itProc->second.mListener));
     487                                itProc->first->Release();
     488                            }
     489
     490                            mProcs.erase(itProc);
     491                        }
     492                    }
     493
     494                } while (0);
     495                break;
     496            }
     497
     498            case VBoxEventType_OnGuestSessionStateChanged:
     499            {
     500                HRESULT rc;
     501                do
     502                {
     503                    ComPtr<IGuestSessionStateChangedEvent> pEvent = aEvent;
     504                    Assert(!pEvent.isNull());
     505                    ComPtr<IGuestSession> pSession;
     506                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
     507                    AssertBreak(!pSession.isNull());
     508
     509                    GuestSessionStatus_T sessSts;
     510                    CHECK_ERROR_BREAK(pSession, COMGETTER(Status)(&sessSts));
     511                    ULONG uID;
     512                    CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));
     513                    Bstr strName;
     514                    CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));
     515
     516                    RTPrintf("Session ID=%RU32 \"%s\" changed status to [%s]\n",
     517                             uID, Utf8Str(strName).c_str(),
     518                             ctrlSessionStatusToText(sessSts));
     519
     520                } while (0);
     521                break;
     522            }
     523
     524            default:
     525                AssertFailed();
     526        }
     527
     528        return S_OK;
     529    }
     530
     531protected:
     532
     533    GuestEventFiles mFiles;
     534    GuestEventProcs mProcs;
     535};
     536
    64537/**
    65538 *  Handler for guest events.
    66539 */
    67 class GuestEventListener
     540class GuestEventListener : public GuestListenerBase
    68541{
    69542public:
     
    76549    }
    77550
    78     HRESULT init(void)
    79     {
    80         return S_OK;
    81     }
    82 
    83551    void uninit(void)
    84552    {
    85         mSession.setNull();
     553        GuestEventSessions::iterator itSession = mSessions.begin();
     554        while (itSession != mSessions.end())
     555        {
     556            if (!itSession->first.isNull())
     557            {
     558                HRESULT rc;
     559                do
     560                {
     561                    /* Listener unregistration. */
     562                    ComPtr<IEventSource> pES;
     563                    CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam()));
     564                    if (!pES.isNull())
     565                        CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener));
     566
     567                } while (0);
     568                itSession->first->Release();
     569            }
     570
     571            itSession++;
     572        }
     573        mSessions.clear();
    86574    }
    87575
     
    90578        switch (aType)
    91579        {
    92             case VBoxEventType_OnGuestFileRegistered:
    93                 break;
    94 
    95             case VBoxEventType_OnGuestProcessRegistered:
    96                 break;
    97 
    98580            case VBoxEventType_OnGuestSessionRegistered:
    99581            {
     
    104586                    Assert(!pEvent.isNull());
    105587
    106                     CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(mSession.asOutParam()));
    107                     AssertBreak(!mSession.isNull());
     588                    ComPtr<IGuestSession> pSession;
     589                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
     590                    AssertBreak(!pSession.isNull());
    108591                    BOOL fRegistered;
    109592                    CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
    110593                    Bstr strName;
    111                     CHECK_ERROR_BREAK(mSession, COMGETTER(Name)(strName.asOutParam()));
     594                    CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));
    112595                    ULONG uID;
    113                     CHECK_ERROR_BREAK(mSession, COMGETTER(Id)(&uID));
     596                    CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));
    114597
    115598                    RTPrintf("Session ID=%RU32 \"%s\" %s\n",
     
    118601                    if (fRegistered)
    119602                    {
    120                     #if 0
     603                        if (mfVerbose)
     604                            RTPrintf("Registering ...\n");
     605
    121606                        /* Register for IGuestSession events. */
     607                        ComObjPtr<GuestSessionEventListenerImpl> pListener;
     608                        pListener.createObject();
     609                        CHECK_ERROR_BREAK(pListener, init(new GuestSessionEventListener()));
     610
    122611                        ComPtr<IEventSource> es;
    123612                        CHECK_ERROR_BREAK(pSession, COMGETTER(EventSource)(es.asOutParam()));
     
    125614                        eventTypes.push_back(VBoxEventType_OnGuestFileRegistered);
    126615                        eventTypes.push_back(VBoxEventType_OnGuestProcessRegistered);
    127                         CHECK_ERROR_BREAK(es, RegisterListener(this, ComSafeArrayAsInParam(eventTypes),
     616                        CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
    128617                                                               true /* Active listener */));
    129                     #endif
     618
     619                        GuestSessionStats sessionStats(pListener);
     620                        mSessions[pSession] = sessionStats;
    130621                    }
    131622                    else
    132623                    {
    133                         mSession.setNull();
     624                        GuestEventSessions::iterator itSession = mSessions.find(pSession);
     625                        if (itSession != mSessions.end())
     626                        {
     627                            if (mfVerbose)
     628                                RTPrintf("Unregistering ...\n");
     629
     630                            if (!itSession->first.isNull())
     631                            {
     632                                /* Listener unregistration. */
     633                                ComPtr<IEventSource> pES;
     634                                CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam()));
     635                                if (!pES.isNull())
     636                                    CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener));
     637                                itSession->first->Release();
     638                            }
     639
     640                            mSessions.erase(itSession);
     641                        }
    134642                    }
    135643
     
    147655protected:
    148656
    149     ComPtr<IGuestSession> mSession;
     657    GuestEventSessions mSessions;
    150658};
    151659typedef ListenerImpl<GuestEventListener> GuestEventListenerImpl;
     
    475983 * string.
    476984 */
    477 static const char *ctrlExecProcessStatusToText(ProcessStatus_T enmStatus)
     985static const char *ctrlProcessStatusToText(ProcessStatus_T enmStatus)
    478986{
    479987    switch (enmStatus)
     
    12021710                    if (fVerbose)
    12031711                        RTPrintf("Exit code=%u (Status=%u [%s])\n",
    1204                                  exitCode, procStatus, ctrlExecProcessStatusToText(procStatus));
     1712                                 exitCode, procStatus, ctrlProcessStatusToText(procStatus));
    12051713
    12061714                    rcExit = (RTEXITCODE)ctrlExecProcessStatusToExitCode(procStatus, exitCode);
    12071715                }
    12081716                else if (fVerbose)
    1209                     RTPrintf("Process now is in status [%s]\n", ctrlExecProcessStatusToText(procStatus));
     1717                    RTPrintf("Process now is in status [%s]\n", ctrlProcessStatusToText(procStatus));
    12101718            }
    12111719            else
     
    30973605
    30983606                                    RTPrintf("\n\t\tProcess #%-03zu PID=%-6RU32 Status=[%s] Command=%ls",
    3099                                              a, uPID, ctrlExecProcessStatusToText(procStatus), strExecPath.raw());
     3607                                             a, uPID, ctrlProcessStatusToText(procStatus), strExecPath.raw());
    31003608                                }
    31013609                            }
     
    35874095        {
    35884096            /** @todo Timeout handling (see above)? */
    3589             RTThreadYield();
     4097            RTThreadSleep(10);
    35904098        }
    35914099
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