VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/VirtualBoxClientImpl.cpp@ 66345

Last change on this file since 66345 was 66279, checked in by vboxsync, 8 years ago

Main/Frontends/Installer: bugref:3300: tabs, spaces, doxygen

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.7 KB
Line 
1/* $Id: VirtualBoxClientImpl.cpp 66279 2017-03-28 07:23:33Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2010-2016 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#include "VirtualBoxClientImpl.h"
19
20#include "AutoCaller.h"
21#include "VBoxEvents.h"
22#include "Logging.h"
23#include "VBox/com/ErrorInfo.h"
24
25#include <iprt/asm.h>
26#include <iprt/thread.h>
27#include <iprt/critsect.h>
28#include <iprt/semaphore.h>
29#include <iprt/cpp/utils.h>
30#ifdef RT_OS_WINDOWS
31# include <iprt/ldr.h>
32# include <msi.h>
33#endif
34
35
36/** Waiting time between probing whether VBoxSVC is alive. */
37#define VBOXCLIENT_DEFAULT_INTERVAL 30000
38
39
40/** Initialize instance counter class variable */
41uint32_t VirtualBoxClient::g_cInstances = 0;
42
43LONG VirtualBoxClient::s_cUnnecessaryAtlModuleLocks = 0;
44
45// constructor / destructor
46/////////////////////////////////////////////////////////////////////////////
47
48HRESULT VirtualBoxClient::FinalConstruct()
49{
50 HRESULT rc = init();
51 BaseFinalConstruct();
52 return rc;
53}
54
55void VirtualBoxClient::FinalRelease()
56{
57 uninit();
58 BaseFinalRelease();
59}
60
61
62// public initializer/uninitializer for internal purposes only
63/////////////////////////////////////////////////////////////////////////////
64
65#ifdef VBOX_WITH_SDS
66
67HRESULT CreateVirtualBoxThroughSDS(ComPtr<IVirtualBox> &aVirtualBox)
68{
69 ComPtr<IVirtualBoxSDS> aVirtualBoxSDS;
70
71 HRESULT rc = CoCreateInstance(CLSID_VirtualBoxSDS, /* the VirtualBoxSDS object */
72 NULL, /* no aggregation */
73 CLSCTX_LOCAL_SERVER, /* the object lives in the current process */
74 IID_IVirtualBoxSDS, /* IID of the interface */
75 (void **)aVirtualBoxSDS.asOutParam());
76 if (FAILED(rc))
77 {
78 //AssertComRCThrow(rc, setError(rc,
79 // tr("Could not create VirtualBoxSDS bridge object for VirtualBoxClient")));
80 Assert(SUCCEEDED(rc));
81 return rc;
82 }
83
84 rc = aVirtualBoxSDS->get_VirtualBox(aVirtualBox.asOutParam());
85 if (FAILED(rc))
86 {
87 Assert(SUCCEEDED(rc));
88 //AssertComRCThrow(rc, setError(rc,
89 // tr("Could not create VirtualBox object for VirtualBoxClient")));
90 }
91 return rc;
92}
93
94HRESULT ReleaseVirtualBoxThroughSDS()
95{
96 ComPtr<IVirtualBoxSDS> aVirtualBoxSDS;
97
98 HRESULT rc = CoCreateInstance(CLSID_VirtualBoxSDS, /* the VirtualBoxSDS object */
99 NULL, /* no aggregation */
100 CLSCTX_LOCAL_SERVER, /* the object lives in the current process */
101 IID_IVirtualBoxSDS, /* IID of the interface */
102 (void **)aVirtualBoxSDS.asOutParam());
103 if (FAILED(rc))
104 {
105 //AssertComRCThrow(rc, setError(rc,
106 // tr("Could not create VirtualBoxSDS bridge object for VirtualBoxClient")));
107 LogRel(("ReleaseVirtualBox - instantiation of IVirtualBoxSDS failed, %x\n", rc));
108 Assert(SUCCEEDED(rc));
109 return rc;
110 }
111
112 rc = aVirtualBoxSDS->ReleaseVirtualBox();
113 if (FAILED(rc))
114 {
115 LogRel(("DeregisterVirtualBox() failed, %x\n", rc));
116 Assert(SUCCEEDED(rc));
117 }
118 return rc;
119}
120
121#endif
122
123/**
124 * Initializes the VirtualBoxClient object.
125 *
126 * @returns COM result indicator
127 */
128HRESULT VirtualBoxClient::init()
129{
130
131#ifdef VBOX_WITH_SDS
132 // TODO: AM rework for final version
133 // setup COM Security to enable impersonation
134 // This works for console Virtual Box clients, GUI has own security settings
135 // For GUI Virtual Box it will be second call so can return TOO_LATE error
136 HRESULT hrGUICoInitializeSecurity = CoInitializeSecurity(NULL,
137 -1,
138 NULL,
139 NULL,
140 RPC_C_AUTHN_LEVEL_DEFAULT,
141 RPC_C_IMP_LEVEL_IMPERSONATE,
142 NULL,
143 EOAC_NONE,
144 NULL);
145 //Assert(RPC_E_TOO_LATE != hrGUICoInitializeSecurity);
146 Assert(SUCCEEDED(hrGUICoInitializeSecurity) || hrGUICoInitializeSecurity == RPC_E_TOO_LATE);
147#endif
148
149 LogFlowThisFuncEnter();
150
151 /* Enclose the state transition NotReady->InInit->Ready */
152 AutoInitSpan autoInitSpan(this);
153 AssertReturn(autoInitSpan.isOk(), E_FAIL);
154
155 /* Important: DO NOT USE any kind of "early return" (except the single
156 * one above, checking the init span success) in this method. It is vital
157 * for correct error handling that it has only one point of return, which
158 * does all the magic on COM to signal object creation success and
159 * reporting the error later for every API method. COM translates any
160 * unsuccessful object creation to REGDB_E_CLASSNOTREG errors or similar
161 * unhelpful ones which cause us a lot of grief with troubleshooting. */
162
163 HRESULT rc = S_OK;
164 try
165 {
166 if (ASMAtomicIncU32(&g_cInstances) != 1)
167 AssertFailedStmt(throw setError(E_FAIL,
168 tr("Attempted to create more than one VirtualBoxClient instance")));
169
170 mData.m_ThreadWatcher = NIL_RTTHREAD;
171 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
172
173#ifdef VBOX_WITH_SDS
174 // TODO: AM create virtual box through SDS
175 rc = CreateVirtualBoxThroughSDS(mData.m_pVirtualBox);
176#else
177 rc = mData.m_pVirtualBox.createLocalObject(CLSID_VirtualBox);
178#endif
179 if (FAILED(rc))
180#ifdef RT_OS_WINDOWS
181 throw i_investigateVirtualBoxObjectCreationFailure(rc);
182#else
183 throw rc;
184#endif
185
186 /* VirtualBox error return is postponed to method calls, fetch it. */
187 ULONG rev;
188 rc = mData.m_pVirtualBox->COMGETTER(Revision)(&rev);
189 if (FAILED(rc))
190 throw rc;
191
192 rc = unconst(mData.m_pEventSource).createObject();
193 AssertComRCThrow(rc, setError(rc,
194 tr("Could not create EventSource for VirtualBoxClient")));
195 rc = mData.m_pEventSource->init();
196 AssertComRCThrow(rc, setError(rc,
197 tr("Could not initialize EventSource for VirtualBoxClient")));
198
199 /* HACK ALERT! This is for DllCanUnloadNow(). */
200 s_cUnnecessaryAtlModuleLocks++;
201 AssertMsg(s_cUnnecessaryAtlModuleLocks == 1, ("%d\n", s_cUnnecessaryAtlModuleLocks));
202
203 /* Setting up the VBoxSVC watcher thread. If anything goes wrong here it
204 * is not considered important enough to cause any sort of visible
205 * failure. The monitoring will not be done, but that's all. */
206 int vrc = RTSemEventCreate(&mData.m_SemEvWatcher);
207 if (RT_FAILURE(vrc))
208 {
209 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
210 AssertRCStmt(vrc, throw setError(VBOX_E_IPRT_ERROR,
211 tr("Failed to create semaphore (rc=%Rrc)"),
212 vrc));
213 }
214
215 vrc = RTThreadCreate(&mData.m_ThreadWatcher, SVCWatcherThread, this, 0,
216 RTTHREADTYPE_INFREQUENT_POLLER, RTTHREADFLAGS_WAITABLE, "VBoxSVCWatcher");
217 if (RT_FAILURE(vrc))
218 {
219 RTSemEventDestroy(mData.m_SemEvWatcher);
220 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
221 AssertRCStmt(vrc, throw setError(VBOX_E_IPRT_ERROR,
222 tr("Failed to create watcher thread (rc=%Rrc)"),
223 vrc));
224 }
225 }
226 catch (HRESULT err)
227 {
228 /* we assume that error info is set by the thrower */
229 rc = err;
230 }
231 catch (...)
232 {
233 rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
234 }
235
236 /* Confirm a successful initialization when it's the case. Must be last,
237 * as on failure it will uninitialize the object. */
238 if (SUCCEEDED(rc))
239 autoInitSpan.setSucceeded();
240 else
241 autoInitSpan.setFailed(rc);
242
243 LogFlowThisFunc(("rc=%Rhrc\n", rc));
244 LogFlowThisFuncLeave();
245 /* Unconditionally return success, because the error return is delayed to
246 * the attribute/method calls through the InitFailed object state. */
247 return S_OK;
248}
249
250#ifdef RT_OS_WINDOWS
251/**
252 * Looks into why we failed to create the VirtualBox object.
253 *
254 * @returns hrcCaller thru setError.
255 * @param hrcCaller The failure status code.
256 */
257HRESULT VirtualBoxClient::i_investigateVirtualBoxObjectCreationFailure(HRESULT hrcCaller)
258{
259 // TODO: AM place creation of VBox through SDS
260 /*
261 * First step is to try get an IUnknown interface of the VirtualBox object.
262 *
263 * This will succeed even when oleaut32.msm (see @bugref{8016}, @ticketref{12087})
264 * is accidentally installed and messes up COM. It may also succeed when the COM
265 * registration is partially broken (though that's unlikely to happen these days).
266 */
267 IUnknown *pUnknown = NULL;
268 HRESULT hrc = CoCreateInstance(CLSID_VirtualBox, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void **)&pUnknown);
269 if (FAILED(hrc))
270 {
271 if (hrc == hrcCaller)
272 return setError(hrcCaller, tr("Completely failed to instantiate CLSID_VirtualBox: %Rhrc"), hrcCaller);
273 return setError(hrcCaller, tr("Completely failed to instantiate CLSID_VirtualBox: %Rhrc & %Rhrc"), hrcCaller, hrc);
274 }
275
276 /*
277 * Try query the IVirtualBox interface (should fail), if it succeed we return
278 * straight away so we have more columns to spend on long messages below.
279 */
280 IVirtualBox *pVirtualBox;
281 hrc = pUnknown->QueryInterface(IID_IVirtualBox, (void **)&pVirtualBox);
282 if (SUCCEEDED(hrc))
283 {
284 pVirtualBox->Release();
285 pUnknown->Release();
286 return setError(hrcCaller,
287 tr("Failed to instantiate CLSID_VirtualBox the first time, but worked when checking out why ... weird"));
288 }
289
290 /*
291 * Check for oleaut32.msm traces in the registry.
292 */
293 HKEY hKey;
294 LSTATUS lrc = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID\\{00020420-0000-0000-C000-000000000046}\\InprocServer32",
295 0 /*fFlags*/, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | STANDARD_RIGHTS_READ, &hKey);
296 if (lrc == ERROR_SUCCESS)
297 {
298 wchar_t wszBuf[8192];
299 DWORD cbBuf = sizeof(wszBuf) - sizeof(wchar_t);
300 DWORD dwType = 0;
301 lrc = RegQueryValueExW(hKey, L"InprocServer32", NULL /*pvReserved*/, &dwType, (BYTE *)&wszBuf[0], &cbBuf);
302 if (lrc == ERROR_SUCCESS)
303 {
304 wszBuf[cbBuf / sizeof(wchar_t)] = '\0';
305 bool fSetError = false;
306
307 /*
308 * Try decode the string and improve the message.
309 */
310 typedef UINT (WINAPI *PFNMSIDECOMPOSEDESCRIPTORW)(PCWSTR pwszDescriptor,
311 LPWSTR pwszProductCode /*[40]*/,
312 LPWSTR pwszFeatureId /*[40]*/,
313 LPWSTR pwszComponentCode /*[40]*/,
314 DWORD *poffArguments);
315 PFNMSIDECOMPOSEDESCRIPTORW pfnMsiDecomposeDescriptorW;
316 pfnMsiDecomposeDescriptorW = (PFNMSIDECOMPOSEDESCRIPTORW)RTLdrGetSystemSymbol("msi.dll", "MsiDecomposeDescriptorW");
317 if ( pfnMsiDecomposeDescriptorW
318 && ( dwType == REG_SZ
319 || dwType == REG_MULTI_SZ))
320 {
321 wchar_t wszProductCode[RTUUID_STR_LENGTH + 2 + 16] = { 0 };
322 wchar_t wszFeatureId[RTUUID_STR_LENGTH + 2 + 16] = { 0 };
323 wchar_t wszComponentCode[RTUUID_STR_LENGTH + 2 + 16] = { 0 };
324 DWORD offArguments = ~(DWORD)0;
325 UINT uRc = pfnMsiDecomposeDescriptorW(wszBuf, wszProductCode, wszFeatureId, wszComponentCode, &offArguments);
326 if (uRc == 0)
327 {
328 /*
329 * Can we resolve the product code into a name?
330 */
331 typedef UINT (WINAPI *PFNMSIOPENPRODUCTW)(PCWSTR, MSIHANDLE *);
332 PFNMSIOPENPRODUCTW pfnMsiOpenProductW;
333 pfnMsiOpenProductW = (PFNMSIOPENPRODUCTW)RTLdrGetSystemSymbol("msi.dll", "MsiOpenProductW");
334
335 typedef UINT (WINAPI *PFNMSICLOSEHANDLE)(MSIHANDLE);
336 PFNMSICLOSEHANDLE pfnMsiCloseHandle;
337 pfnMsiCloseHandle = (PFNMSICLOSEHANDLE)RTLdrGetSystemSymbol("msi.dll", "MsiCloseHandle");
338
339 typedef UINT (WINAPI *PFNGETPRODUCTPROPERTYW)(MSIHANDLE, PCWSTR, PWSTR, PDWORD);
340 PFNGETPRODUCTPROPERTYW pfnMsiGetProductPropertyW;
341 pfnMsiGetProductPropertyW = (PFNGETPRODUCTPROPERTYW)RTLdrGetSystemSymbol("msi.dll", "MsiGetProductPropertyW");
342 if ( pfnMsiGetProductPropertyW
343 && pfnMsiCloseHandle
344 && pfnMsiOpenProductW)
345 {
346 MSIHANDLE hMsi = 0;
347 uRc = pfnMsiOpenProductW(wszProductCode, &hMsi);
348 if (uRc == 0)
349 {
350 static wchar_t const * const s_apwszProps[] =
351 {
352 INSTALLPROPERTY_INSTALLEDPRODUCTNAME,
353 INSTALLPROPERTY_PRODUCTNAME,
354 INSTALLPROPERTY_PACKAGENAME,
355 };
356
357 wchar_t wszProductName[1024];
358 DWORD cwcProductName;
359 unsigned i = 0;
360 do
361 {
362 cwcProductName = RT_ELEMENTS(wszProductName) - 1;
363 uRc = pfnMsiGetProductPropertyW(hMsi, s_apwszProps[i], wszProductName, &cwcProductName);
364 }
365 while ( ++i < RT_ELEMENTS(s_apwszProps)
366 && ( uRc != 0
367 || cwcProductName < 2
368 || cwcProductName >= RT_ELEMENTS(wszProductName)) );
369 uRc = pfnMsiCloseHandle(hMsi);
370 if (uRc == 0 && cwcProductName >= 2)
371 {
372 wszProductName[RT_MIN(cwcProductName, RT_ELEMENTS(wszProductName) - 1)] = '\0';
373 setError(hrcCaller,
374 tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.\n"
375 "PSDispatch looks broken by the '%ls' (%ls) program, suspecting that it features the broken oleaut32.msm module as component %ls.\n"
376 "\n"
377 "We suggest you try uninstall '%ls'.\n"
378 "\n"
379 "See also https://support.microsoft.com/en-us/kb/316911 "),
380 wszProductName, wszProductCode, wszComponentCode, wszProductName);
381 fSetError = true;
382 }
383 }
384 }
385
386 /* MSI uses COM and may mess up our stuff. So, we wait with the fallback till afterwards in this case. */
387 if (!fSetError)
388 {
389 setError(hrcCaller,
390 tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, CLSID_VirtualBox w/ IUnknown works.\n"
391 "PSDispatch looks broken by installer %ls featuring the broken oleaut32.msm module as component %ls.\n"
392 "\n"
393 "See also https://support.microsoft.com/en-us/kb/316911 "),
394 wszProductCode, wszComponentCode);
395 fSetError = true;
396 }
397 }
398 }
399 if (!fSetError)
400 setError(hrcCaller, tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, CLSID_VirtualBox w/ IUnknown works.\n"
401 "PSDispatch looks broken by some installer featuring the broken oleaut32.msm module as a component.\n"
402 "\n"
403 "See also https://support.microsoft.com/en-us/kb/316911 "));
404 }
405 else if (lrc == ERROR_FILE_NOT_FOUND)
406 setError(hrcCaller, tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.\n"
407 "PSDispatch looks fine. Weird"));
408 else
409 setError(hrcCaller, tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.\n"
410 "Checking out PSDispatch registration ended with error: %u (%#x)"), lrc, lrc);
411 RegCloseKey(hKey);
412 }
413
414 pUnknown->Release();
415 return hrcCaller;
416}
417#endif /* RT_OS_WINDOWS */
418
419/**
420 * Uninitializes the instance and sets the ready flag to FALSE.
421 * Called either from FinalRelease() or by the parent when it gets destroyed.
422 */
423void VirtualBoxClient::uninit()
424{
425 LogFlowThisFunc(("\n"));
426
427#ifdef VBOX_WITH_SDS
428 ReleaseVirtualBoxThroughSDS();
429#endif
430
431 /* Enclose the state transition Ready->InUninit->NotReady */
432 AutoUninitSpan autoUninitSpan(this);
433 if (autoUninitSpan.uninitDone())
434 return;
435
436 if (mData.m_ThreadWatcher != NIL_RTTHREAD)
437 {
438 /* Signal the event semaphore and wait for the thread to terminate.
439 * if it hangs for some reason exit anyway, this can cause a crash
440 * though as the object will no longer be available. */
441 RTSemEventSignal(mData.m_SemEvWatcher);
442 RTThreadWait(mData.m_ThreadWatcher, 30000, NULL);
443 mData.m_ThreadWatcher = NIL_RTTHREAD;
444 RTSemEventDestroy(mData.m_SemEvWatcher);
445 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
446 }
447
448 mData.m_pVirtualBox.setNull();
449
450 ASMAtomicDecU32(&g_cInstances);
451}
452
453// IVirtualBoxClient properties
454/////////////////////////////////////////////////////////////////////////////
455
456/**
457 * Returns a reference to the VirtualBox object.
458 *
459 * @returns COM status code
460 * @param aVirtualBox Address of result variable.
461 */
462HRESULT VirtualBoxClient::getVirtualBox(ComPtr<IVirtualBox> &aVirtualBox)
463{
464 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
465 aVirtualBox = mData.m_pVirtualBox;
466 return S_OK;
467}
468
469/**
470 * Create a new Session object and return a reference to it.
471 *
472 * @returns COM status code
473 * @param aSession Address of result variable.
474 */
475HRESULT VirtualBoxClient::getSession(ComPtr<ISession> &aSession)
476{
477 /* this is not stored in this object, no need to lock */
478 ComPtr<ISession> pSession;
479 HRESULT rc = pSession.createInprocObject(CLSID_Session);
480 if (SUCCEEDED(rc))
481 aSession = pSession;
482 return rc;
483}
484
485/**
486 * Return reference to the EventSource associated with this object.
487 *
488 * @returns COM status code
489 * @param aEventSource Address of result variable.
490 */
491HRESULT VirtualBoxClient::getEventSource(ComPtr<IEventSource> &aEventSource)
492{
493 /* this is const, no need to lock */
494 aEventSource = mData.m_pEventSource;
495 return aEventSource.isNull() ? E_FAIL : S_OK;
496}
497
498// IVirtualBoxClient methods
499/////////////////////////////////////////////////////////////////////////////
500
501/**
502 * Checks a Machine object for any pending errors.
503 *
504 * @returns COM status code
505 * @param aMachine Machine object to check.
506 */
507HRESULT VirtualBoxClient::checkMachineError(const ComPtr<IMachine> &aMachine)
508{
509 BOOL fAccessible = FALSE;
510 HRESULT rc = aMachine->COMGETTER(Accessible)(&fAccessible);
511 if (FAILED(rc))
512 return setError(rc, tr("Could not check the accessibility status of the VM"));
513 else if (!fAccessible)
514 {
515 ComPtr<IVirtualBoxErrorInfo> pAccessError;
516 rc = aMachine->COMGETTER(AccessError)(pAccessError.asOutParam());
517 if (FAILED(rc))
518 return setError(rc, tr("Could not get the access error message of the VM"));
519 else
520 {
521 ErrorInfo info(pAccessError);
522 ErrorInfoKeeper eik(info);
523 return info.getResultCode();
524 }
525 }
526 return S_OK;
527}
528
529// private methods
530/////////////////////////////////////////////////////////////////////////////
531
532/*static*/
533DECLCALLBACK(int) VirtualBoxClient::SVCWatcherThread(RTTHREAD ThreadSelf,
534 void *pvUser)
535{
536 NOREF(ThreadSelf);
537 Assert(pvUser);
538 VirtualBoxClient *pThis = (VirtualBoxClient *)pvUser;
539 RTSEMEVENT sem = pThis->mData.m_SemEvWatcher;
540 RTMSINTERVAL cMillies = VBOXCLIENT_DEFAULT_INTERVAL;
541 int vrc;
542
543 /* The likelihood of early crashes are high, so start with a short wait. */
544 vrc = RTSemEventWait(sem, cMillies / 2);
545
546 /* As long as the waiting times out keep retrying the wait. */
547 while (RT_FAILURE(vrc))
548 {
549 {
550 HRESULT rc = S_OK;
551 ComPtr<IVirtualBox> pV;
552 {
553 AutoReadLock alock(pThis COMMA_LOCKVAL_SRC_POS);
554 pV = pThis->mData.m_pVirtualBox;
555 }
556 if (!pV.isNull())
557 {
558 ULONG rev;
559 rc = pV->COMGETTER(Revision)(&rev);
560 if (FAILED_DEAD_INTERFACE(rc))
561 {
562 LogRel(("VirtualBoxClient: detected unresponsive VBoxSVC (rc=%Rhrc)\n", rc));
563 {
564 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);
565 /* Throw away the VirtualBox reference, it's no longer
566 * usable as VBoxSVC terminated in the mean time. */
567 pThis->mData.m_pVirtualBox.setNull();
568 }
569 fireVBoxSVCAvailabilityChangedEvent(pThis->mData.m_pEventSource, FALSE);
570 }
571 }
572 else
573 {
574 /* Try to get a new VirtualBox reference straight away, and if
575 * this fails use an increased waiting time as very frequent
576 * restart attempts in some wedged config can cause high CPU
577 * and disk load. */
578 ComPtr<IVirtualBox> pVirtualBox;
579 rc = pVirtualBox.createLocalObject(CLSID_VirtualBox);
580 if (FAILED(rc))
581 cMillies = 3 * VBOXCLIENT_DEFAULT_INTERVAL;
582 else
583 {
584 LogRel(("VirtualBoxClient: detected working VBoxSVC (rc=%Rhrc)\n", rc));
585 {
586 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);
587 /* Update the VirtualBox reference, there's a working
588 * VBoxSVC again from now on. */
589 pThis->mData.m_pVirtualBox = pVirtualBox;
590 }
591 fireVBoxSVCAvailabilityChangedEvent(pThis->mData.m_pEventSource, TRUE);
592 cMillies = VBOXCLIENT_DEFAULT_INTERVAL;
593 }
594 }
595 }
596 vrc = RTSemEventWait(sem, cMillies);
597 }
598 return 0;
599}
600
601/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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