VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use