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
Line 
1/* $Id: VBoxManageGuestCtrlListener.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxManage - Guest control listener implementations.
4 */
5
6/*
7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
8 *
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
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
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
39#include <iprt/semaphore.h>
40#include <iprt/time.h>
41
42#include <map>
43#include <vector>
44
45DECLARE_TRANSLATION_CONTEXT(GuestCtrlLsnr);
46
47
48/** Event semaphore we're using for notification. */
49extern RTSEMEVENT g_SemEventGuestCtrlCanceled;
50
51
52/*
53 * GuestListenerBase
54 * GuestListenerBase
55 * GuestListenerBase
56 */
57
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
74
75/*
76 * GuestFileEventListener
77 * GuestFileEventListener
78 * GuestFileEventListener
79 */
80
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 {
100 HRESULT hrc;
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;
112 CHECK_ERROR_BREAK(pProcess, COMGETTER(Filename)(strPath.asOutParam()));
113 ULONG uID;
114 CHECK_ERROR_BREAK(pProcess, COMGETTER(Id)(&uID));
115
116 RTPrintf(GuestCtrlLsnr::tr("File ID=%RU32 \"%s\" changed status to [%s]\n"),
117 uID, Utf8Str(strPath).c_str(), gctlFileStatusToText(fileSts));
118
119 } while (0);
120 break;
121 }
122
123 default:
124 AssertFailed();
125 }
126
127 return S_OK;
128}
129
130
131/*
132 * GuestProcessEventListener
133 * GuestProcessEventListener
134 * GuestProcessEventListener
135 */
136
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 {
156 HRESULT hrc;
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
172 RTPrintf(GuestCtrlLsnr::tr("Process PID=%RU32 \"%s\" changed status to [%s]\n"),
173 uPID, Utf8Str(strPath).c_str(), gctlProcessStatusToText(procSts));
174
175 } while (0);
176 break;
177 }
178
179 default:
180 AssertFailed();
181 }
182
183 return S_OK;
184}
185
186
187/*
188 * GuestSessionEventListener
189 * GuestSessionEventListener
190 * GuestSessionEventListener
191 */
192
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 {
208 HRESULT hrc;
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
219 ++itProc;
220 }
221 mProcs.clear();
222
223 GuestEventFiles::iterator itFile = mFiles.begin();
224 while (itFile != mFiles.end())
225 {
226 if (!itFile->first.isNull())
227 {
228 HRESULT hrc;
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
239 ++itFile;
240 }
241 mFiles.clear();
242}
243
244STDMETHODIMP GuestSessionEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
245{
246 switch (aType)
247 {
248 case VBoxEventType_OnGuestFileRegistered:
249 {
250 HRESULT hrc;
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;
262 CHECK_ERROR_BREAK(pFile, COMGETTER(Filename)(strPath.asOutParam()));
263
264 RTPrintf(GuestCtrlLsnr::tr("File \"%s\" %s\n"),
265 Utf8Str(strPath).c_str(),
266 fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered"));
267 if (fRegistered)
268 {
269 if (mfVerbose)
270 RTPrintf(GuestCtrlLsnr::tr("Registering ...\n"));
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)
293 RTPrintf(GuestCtrlLsnr::tr("Unregistering file ...\n"));
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 {
314 HRESULT hrc;
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
328 RTPrintf(GuestCtrlLsnr::tr("Process \"%s\" %s\n"),
329 Utf8Str(strPath).c_str(),
330 fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered"));
331 if (fRegistered)
332 {
333 if (mfVerbose)
334 RTPrintf(GuestCtrlLsnr::tr("Registering ...\n"));
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)
357 RTPrintf(GuestCtrlLsnr::tr("Unregistering process ...\n"));
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 {
378 HRESULT hrc;
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
394 RTPrintf(GuestCtrlLsnr::tr("Session ID=%RU32 \"%s\" changed status to [%s]\n"),
395 uID, Utf8Str(strName).c_str(), gctlGuestSessionStatusToText(sessSts));
396
397 } while (0);
398 break;
399 }
400
401 default:
402 AssertFailed();
403 }
404
405 return S_OK;
406}
407
408
409/*
410 * GuestEventListener
411 * GuestEventListener
412 * GuestEventListener
413 */
414
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 {
430 HRESULT hrc;
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
442 ++itSession;
443 }
444 mSessions.clear();
445}
446
447STDMETHODIMP GuestEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent)
448{
449 switch (aType)
450 {
451 case VBoxEventType_OnGuestSessionRegistered:
452 {
453 HRESULT hrc;
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
469 RTPrintf(GuestCtrlLsnr::tr("Session ID=%RU32 \"%s\" %s\n"),
470 uID, Utf8Str(strName).c_str(),
471 fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered"));
472 if (fRegistered)
473 {
474 if (mfVerbose)
475 RTPrintf(GuestCtrlLsnr::tr("Registering ...\n"));
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);
487 eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
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)
500 RTPrintf(GuestCtrlLsnr::tr("Unregistering ...\n"));
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}
525
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
549 HRESULT hrc;
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)
562 RTPrintf(GuestCtrlLsnr::tr("Reached run level %RU32\n"), RunLevelCur);
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