VirtualBox

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

Last change on this file since 95140 was 95140, checked in by vboxsync, 2 years ago

Frontends + Main: Adjust to the new rules wrt. to rc -> hrc,vrc usage. This also fixes quite a few bugs wrt shadow variables, wrong return values and output error translations / exit codes. Also see @todos added. ​​bugref:10223

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

© 2023 Oracle
ContactPrivacy policyTerms of Use