VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrlListener.cpp@ 93428

Last change on this file since 93428 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.9 KB
Line 
1/* $Id: VBoxManageGuestCtrlListener.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBoxManage - Guest control listener implementations.
4 */
5
6/*
7 * Copyright (C) 2013-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include "VBoxManage.h"
23#include "VBoxManageGuestCtrl.h"
24
25#ifndef VBOX_ONLY_DOCS
26
27#include <VBox/com/com.h>
28#include <VBox/com/ErrorInfo.h>
29#include <VBox/com/errorprint.h>
30
31#include <iprt/semaphore.h>
32#include <iprt/time.h>
33
34#include <map>
35#include <vector>
36
37DECLARE_TRANSLATION_CONTEXT(GuestCtrlLsnr);
38
39
40/** Event semaphore we're using for notification. */
41extern RTSEMEVENT g_SemEventGuestCtrlCanceled;
42
43
44/*
45 * GuestListenerBase
46 * GuestListenerBase
47 * GuestListenerBase
48 */
49
50GuestListenerBase::GuestListenerBase(void)
51 : mfVerbose(false)
52{
53}
54
55GuestListenerBase::~GuestListenerBase(void)
56{
57}
58
59HRESULT GuestListenerBase::init(bool fVerbose)
60{
61 mfVerbose = fVerbose;
62 return S_OK;
63}
64
65
66
67/*
68 * GuestFileEventListener
69 * GuestFileEventListener
70 * GuestFileEventListener
71 */
72
73GuestFileEventListener::GuestFileEventListener(void)
74{
75}
76
77GuestFileEventListener::~GuestFileEventListener(void)
78{
79}
80
81void GuestFileEventListener::uninit(void)
82{
83
84}
85
86STDMETHODIMP GuestFileEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
87{
88 switch (aType)
89 {
90 case VBoxEventType_OnGuestFileStateChanged:
91 {
92 HRESULT rc;
93 do
94 {
95 ComPtr<IGuestFileStateChangedEvent> pEvent = aEvent;
96 Assert(!pEvent.isNull());
97
98 ComPtr<IGuestFile> pProcess;
99 CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pProcess.asOutParam()));
100 AssertBreak(!pProcess.isNull());
101 FileStatus_T fileSts;
102 CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&fileSts));
103 Bstr strPath;
104 CHECK_ERROR_BREAK(pProcess, COMGETTER(Filename)(strPath.asOutParam()));
105 ULONG uID;
106 CHECK_ERROR_BREAK(pProcess, COMGETTER(Id)(&uID));
107
108 RTPrintf(GuestCtrlLsnr::tr("File ID=%RU32 \"%s\" changed status to [%s]\n"),
109 uID, Utf8Str(strPath).c_str(), gctlFileStatusToText(fileSts));
110
111 } while (0);
112 break;
113 }
114
115 default:
116 AssertFailed();
117 }
118
119 return S_OK;
120}
121
122
123/*
124 * GuestProcessEventListener
125 * GuestProcessEventListener
126 * GuestProcessEventListener
127 */
128
129GuestProcessEventListener::GuestProcessEventListener(void)
130{
131}
132
133GuestProcessEventListener::~GuestProcessEventListener(void)
134{
135}
136
137void GuestProcessEventListener::uninit(void)
138{
139
140}
141
142STDMETHODIMP GuestProcessEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
143{
144 switch (aType)
145 {
146 case VBoxEventType_OnGuestProcessStateChanged:
147 {
148 HRESULT rc;
149 do
150 {
151 ComPtr<IGuestProcessStateChangedEvent> pEvent = aEvent;
152 Assert(!pEvent.isNull());
153
154 ComPtr<IGuestProcess> pProcess;
155 CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam()));
156 AssertBreak(!pProcess.isNull());
157 ProcessStatus_T procSts;
158 CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&procSts));
159 Bstr strPath;
160 CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam()));
161 ULONG uPID;
162 CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID));
163
164 RTPrintf(GuestCtrlLsnr::tr("Process PID=%RU32 \"%s\" changed status to [%s]\n"),
165 uPID, Utf8Str(strPath).c_str(), gctlProcessStatusToText(procSts));
166
167 } while (0);
168 break;
169 }
170
171 default:
172 AssertFailed();
173 }
174
175 return S_OK;
176}
177
178
179/*
180 * GuestSessionEventListener
181 * GuestSessionEventListener
182 * GuestSessionEventListener
183 */
184
185GuestSessionEventListener::GuestSessionEventListener(void)
186{
187}
188
189GuestSessionEventListener::~GuestSessionEventListener(void)
190{
191}
192
193void GuestSessionEventListener::uninit(void)
194{
195 GuestEventProcs::iterator itProc = mProcs.begin();
196 while (itProc != mProcs.end())
197 {
198 if (!itProc->first.isNull())
199 {
200 HRESULT rc;
201 do
202 {
203 /* Listener unregistration. */
204 ComPtr<IEventSource> pES;
205 CHECK_ERROR_BREAK(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
206 if (!pES.isNull())
207 CHECK_ERROR_BREAK(pES, UnregisterListener(itProc->second.mListener));
208 } while (0);
209 }
210
211 ++itProc;
212 }
213 mProcs.clear();
214
215 GuestEventFiles::iterator itFile = mFiles.begin();
216 while (itFile != mFiles.end())
217 {
218 if (!itFile->first.isNull())
219 {
220 HRESULT rc;
221 do
222 {
223 /* Listener unregistration. */
224 ComPtr<IEventSource> pES;
225 CHECK_ERROR_BREAK(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
226 if (!pES.isNull())
227 CHECK_ERROR_BREAK(pES, UnregisterListener(itFile->second.mListener));
228 } while (0);
229 }
230
231 ++itFile;
232 }
233 mFiles.clear();
234}
235
236STDMETHODIMP GuestSessionEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
237{
238 switch (aType)
239 {
240 case VBoxEventType_OnGuestFileRegistered:
241 {
242 HRESULT rc;
243 do
244 {
245 ComPtr<IGuestFileRegisteredEvent> pEvent = aEvent;
246 Assert(!pEvent.isNull());
247
248 ComPtr<IGuestFile> pFile;
249 CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pFile.asOutParam()));
250 AssertBreak(!pFile.isNull());
251 BOOL fRegistered;
252 CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
253 Bstr strPath;
254 CHECK_ERROR_BREAK(pFile, COMGETTER(Filename)(strPath.asOutParam()));
255
256 RTPrintf(GuestCtrlLsnr::tr("File \"%s\" %s\n"),
257 Utf8Str(strPath).c_str(),
258 fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered"));
259 if (fRegistered)
260 {
261 if (mfVerbose)
262 RTPrintf(GuestCtrlLsnr::tr("Registering ...\n"));
263
264 /* Register for IGuestFile events. */
265 ComObjPtr<GuestFileEventListenerImpl> pListener;
266 pListener.createObject();
267 CHECK_ERROR_BREAK(pListener, init(new GuestFileEventListener()));
268
269 ComPtr<IEventSource> es;
270 CHECK_ERROR_BREAK(pFile, COMGETTER(EventSource)(es.asOutParam()));
271 com::SafeArray<VBoxEventType_T> eventTypes;
272 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
273 CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
274 true /* Active listener */));
275
276 GuestFileStats fileStats(pListener);
277 mFiles[pFile] = fileStats;
278 }
279 else
280 {
281 GuestEventFiles::iterator itFile = mFiles.find(pFile);
282 if (itFile != mFiles.end())
283 {
284 if (mfVerbose)
285 RTPrintf(GuestCtrlLsnr::tr("Unregistering file ...\n"));
286
287 if (!itFile->first.isNull())
288 {
289 /* Listener unregistration. */
290 ComPtr<IEventSource> pES;
291 CHECK_ERROR(itFile->first, COMGETTER(EventSource)(pES.asOutParam()));
292 if (!pES.isNull())
293 CHECK_ERROR(pES, UnregisterListener(itFile->second.mListener));
294 }
295
296 mFiles.erase(itFile);
297 }
298 }
299
300 } while (0);
301 break;
302 }
303
304 case VBoxEventType_OnGuestProcessRegistered:
305 {
306 HRESULT rc;
307 do
308 {
309 ComPtr<IGuestProcessRegisteredEvent> pEvent = aEvent;
310 Assert(!pEvent.isNull());
311
312 ComPtr<IGuestProcess> pProcess;
313 CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam()));
314 AssertBreak(!pProcess.isNull());
315 BOOL fRegistered;
316 CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
317 Bstr strPath;
318 CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam()));
319
320 RTPrintf(GuestCtrlLsnr::tr("Process \"%s\" %s\n"),
321 Utf8Str(strPath).c_str(),
322 fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered"));
323 if (fRegistered)
324 {
325 if (mfVerbose)
326 RTPrintf(GuestCtrlLsnr::tr("Registering ...\n"));
327
328 /* Register for IGuestProcess events. */
329 ComObjPtr<GuestProcessEventListenerImpl> pListener;
330 pListener.createObject();
331 CHECK_ERROR_BREAK(pListener, init(new GuestProcessEventListener()));
332
333 ComPtr<IEventSource> es;
334 CHECK_ERROR_BREAK(pProcess, COMGETTER(EventSource)(es.asOutParam()));
335 com::SafeArray<VBoxEventType_T> eventTypes;
336 eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
337 CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
338 true /* Active listener */));
339
340 GuestProcStats procStats(pListener);
341 mProcs[pProcess] = procStats;
342 }
343 else
344 {
345 GuestEventProcs::iterator itProc = mProcs.find(pProcess);
346 if (itProc != mProcs.end())
347 {
348 if (mfVerbose)
349 RTPrintf(GuestCtrlLsnr::tr("Unregistering process ...\n"));
350
351 if (!itProc->first.isNull())
352 {
353 /* Listener unregistration. */
354 ComPtr<IEventSource> pES;
355 CHECK_ERROR(itProc->first, COMGETTER(EventSource)(pES.asOutParam()));
356 if (!pES.isNull())
357 CHECK_ERROR(pES, UnregisterListener(itProc->second.mListener));
358 }
359
360 mProcs.erase(itProc);
361 }
362 }
363
364 } while (0);
365 break;
366 }
367
368 case VBoxEventType_OnGuestSessionStateChanged:
369 {
370 HRESULT rc;
371 do
372 {
373 ComPtr<IGuestSessionStateChangedEvent> pEvent = aEvent;
374 Assert(!pEvent.isNull());
375 ComPtr<IGuestSession> pSession;
376 CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
377 AssertBreak(!pSession.isNull());
378
379 GuestSessionStatus_T sessSts;
380 CHECK_ERROR_BREAK(pSession, COMGETTER(Status)(&sessSts));
381 ULONG uID;
382 CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));
383 Bstr strName;
384 CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));
385
386 RTPrintf(GuestCtrlLsnr::tr("Session ID=%RU32 \"%s\" changed status to [%s]\n"),
387 uID, Utf8Str(strName).c_str(), gctlGuestSessionStatusToText(sessSts));
388
389 } while (0);
390 break;
391 }
392
393 default:
394 AssertFailed();
395 }
396
397 return S_OK;
398}
399
400
401/*
402 * GuestEventListener
403 * GuestEventListener
404 * GuestEventListener
405 */
406
407GuestEventListener::GuestEventListener(void)
408{
409}
410
411GuestEventListener::~GuestEventListener(void)
412{
413}
414
415void GuestEventListener::uninit(void)
416{
417 GuestEventSessions::iterator itSession = mSessions.begin();
418 while (itSession != mSessions.end())
419 {
420 if (!itSession->first.isNull())
421 {
422 HRESULT rc;
423 do
424 {
425 /* Listener unregistration. */
426 ComPtr<IEventSource> pES;
427 CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam()));
428 if (!pES.isNull())
429 CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener));
430
431 } while (0);
432 }
433
434 ++itSession;
435 }
436 mSessions.clear();
437}
438
439STDMETHODIMP GuestEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
440{
441 switch (aType)
442 {
443 case VBoxEventType_OnGuestSessionRegistered:
444 {
445 HRESULT rc;
446 do
447 {
448 ComPtr<IGuestSessionRegisteredEvent> pEvent = aEvent;
449 Assert(!pEvent.isNull());
450
451 ComPtr<IGuestSession> pSession;
452 CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam()));
453 AssertBreak(!pSession.isNull());
454 BOOL fRegistered;
455 CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered));
456 Bstr strName;
457 CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam()));
458 ULONG uID;
459 CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID));
460
461 RTPrintf(GuestCtrlLsnr::tr("Session ID=%RU32 \"%s\" %s\n"),
462 uID, Utf8Str(strName).c_str(),
463 fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered"));
464 if (fRegistered)
465 {
466 if (mfVerbose)
467 RTPrintf(GuestCtrlLsnr::tr("Registering ...\n"));
468
469 /* Register for IGuestSession events. */
470 ComObjPtr<GuestSessionEventListenerImpl> pListener;
471 pListener.createObject();
472 CHECK_ERROR_BREAK(pListener, init(new GuestSessionEventListener()));
473
474 ComPtr<IEventSource> es;
475 CHECK_ERROR_BREAK(pSession, COMGETTER(EventSource)(es.asOutParam()));
476 com::SafeArray<VBoxEventType_T> eventTypes;
477 eventTypes.push_back(VBoxEventType_OnGuestFileRegistered);
478 eventTypes.push_back(VBoxEventType_OnGuestProcessRegistered);
479 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
480 CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes),
481 true /* Active listener */));
482
483 GuestSessionStats sessionStats(pListener);
484 mSessions[pSession] = sessionStats;
485 }
486 else
487 {
488 GuestEventSessions::iterator itSession = mSessions.find(pSession);
489 if (itSession != mSessions.end())
490 {
491 if (mfVerbose)
492 RTPrintf(GuestCtrlLsnr::tr("Unregistering ...\n"));
493
494 if (!itSession->first.isNull())
495 {
496 /* Listener unregistration. */
497 ComPtr<IEventSource> pES;
498 CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam()));
499 if (!pES.isNull())
500 CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener));
501 }
502
503 mSessions.erase(itSession);
504 }
505 }
506
507 } while (0);
508 break;
509 }
510
511 default:
512 AssertFailed();
513 }
514
515 return S_OK;
516}
517
518/*
519 * GuestAdditionsRunlevelListener
520 * GuestAdditionsRunlevelListener
521 * GuestAdditionsRunlevelListener
522 */
523
524GuestAdditionsRunlevelListener::GuestAdditionsRunlevelListener(AdditionsRunLevelType_T enmRunLevel)
525 : mRunLevelTarget(enmRunLevel)
526{
527}
528
529GuestAdditionsRunlevelListener::~GuestAdditionsRunlevelListener(void)
530{
531}
532
533void GuestAdditionsRunlevelListener::uninit(void)
534{
535}
536
537STDMETHODIMP GuestAdditionsRunlevelListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
538{
539 Assert(mRunLevelTarget != AdditionsRunLevelType_None);
540
541 HRESULT rc;
542
543 switch (aType)
544 {
545 case VBoxEventType_OnGuestAdditionsStatusChanged:
546 {
547 ComPtr<IGuestAdditionsStatusChangedEvent> pEvent = aEvent;
548 Assert(!pEvent.isNull());
549
550 AdditionsRunLevelType_T RunLevelCur = AdditionsRunLevelType_None;
551 CHECK_ERROR_BREAK(pEvent, COMGETTER(RunLevel)(&RunLevelCur));
552
553 if (mfVerbose)
554 RTPrintf(GuestCtrlLsnr::tr("Reached run level %RU32\n"), RunLevelCur);
555
556 if (RunLevelCur == mRunLevelTarget)
557 {
558 int vrc = RTSemEventSignal(g_SemEventGuestCtrlCanceled);
559 AssertRC(vrc);
560 }
561
562 break;
563 }
564
565 default:
566 AssertFailed();
567 }
568
569 return S_OK;
570}
571
572#endif /* !VBOX_ONLY_DOCS */
Note: See TracBrowser for help on using the repository browser.

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