VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestImpl.cpp@ 40205

Last change on this file since 40205 was 40205, checked in by vboxsync, 13 years ago

Main: gcc warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.3 KB
Line 
1/* $Id: GuestImpl.cpp 40205 2012-02-22 08:30:14Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation: Guest
4 */
5
6/*
7 * Copyright (C) 2006-2012 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 "GuestImpl.h"
19
20#include "Global.h"
21#include "ConsoleImpl.h"
22#include "ProgressImpl.h"
23#ifdef VBOX_WITH_DRAG_AND_DROP
24# include "GuestDnDImpl.h"
25#endif
26#include "VMMDev.h"
27
28#include "AutoCaller.h"
29#include "Logging.h"
30#include "Performance.h"
31
32#include <VBox/VMMDev.h>
33#ifdef VBOX_WITH_GUEST_CONTROL
34# include <VBox/com/array.h>
35# include <VBox/com/ErrorInfo.h>
36#endif
37#include <iprt/cpp/utils.h>
38#include <iprt/timer.h>
39#include <VBox/vmm/pgm.h>
40#include <VBox/version.h>
41
42// defines
43/////////////////////////////////////////////////////////////////////////////
44
45// constructor / destructor
46/////////////////////////////////////////////////////////////////////////////
47
48DEFINE_EMPTY_CTOR_DTOR (Guest)
49
50HRESULT Guest::FinalConstruct()
51{
52 return BaseFinalConstruct();
53}
54
55void Guest::FinalRelease()
56{
57 uninit ();
58 BaseFinalRelease();
59}
60
61// public methods only for internal purposes
62/////////////////////////////////////////////////////////////////////////////
63
64/**
65 * Initializes the guest object.
66 */
67HRESULT Guest::init(Console *aParent)
68{
69 LogFlowThisFunc(("aParent=%p\n", aParent));
70
71 ComAssertRet(aParent, E_INVALIDARG);
72
73 /* Enclose the state transition NotReady->InInit->Ready */
74 AutoInitSpan autoInitSpan(this);
75 AssertReturn(autoInitSpan.isOk(), E_FAIL);
76
77 unconst(mParent) = aParent;
78
79 /* Confirm a successful initialization when it's the case */
80 autoInitSpan.setSucceeded();
81
82 ULONG aMemoryBalloonSize;
83 HRESULT ret = mParent->machine()->COMGETTER(MemoryBalloonSize)(&aMemoryBalloonSize);
84 if (ret == S_OK)
85 mMemoryBalloonSize = aMemoryBalloonSize;
86 else
87 mMemoryBalloonSize = 0; /* Default is no ballooning */
88
89 BOOL fPageFusionEnabled;
90 ret = mParent->machine()->COMGETTER(PageFusionEnabled)(&fPageFusionEnabled);
91 if (ret == S_OK)
92 mfPageFusionEnabled = fPageFusionEnabled;
93 else
94 mfPageFusionEnabled = false; /* Default is no page fusion*/
95
96 mStatUpdateInterval = 0; /* Default is not to report guest statistics at all */
97 mCollectVMMStats = false;
98
99 /* Clear statistics. */
100 for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
101 mCurrentGuestStat[i] = 0;
102 mGuestValidStats = pm::GUESTSTATMASK_NONE;
103
104 mMagic = GUEST_MAGIC;
105 int vrc = RTTimerLRCreate (&mStatTimer, 1000 /* ms */,
106 &Guest::staticUpdateStats, this);
107 AssertMsgRC (vrc, ("Failed to create guest statistics "
108 "update timer(%Rra)\n", vrc));
109
110#ifdef VBOX_WITH_GUEST_CONTROL
111 /* Init the context ID counter at 1000. */
112 mNextContextID = 1000;
113#endif
114
115#ifdef VBOX_WITH_DRAG_AND_DROP
116 m_pGuestDnD = new GuestDnD(this);
117#endif
118
119 return S_OK;
120}
121
122/**
123 * Uninitializes the instance and sets the ready flag to FALSE.
124 * Called either from FinalRelease() or by the parent when it gets destroyed.
125 */
126void Guest::uninit()
127{
128 LogFlowThisFunc(("\n"));
129
130 /* Enclose the state transition Ready->InUninit->NotReady */
131 AutoUninitSpan autoUninitSpan(this);
132 if (autoUninitSpan.uninitDone())
133 return;
134
135#ifdef VBOX_WITH_GUEST_CONTROL
136 /* Scope write lock as much as possible. */
137 {
138 /*
139 * Cleanup must be done *before* AutoUninitSpan to cancel all
140 * all outstanding waits in API functions (which hold AutoCaller
141 * ref counts).
142 */
143 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
144
145 /* Notify left over callbacks that we are about to shutdown ... */
146 CallbackMapIter it;
147 for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
148 {
149 int rc2 = callbackNotifyEx(it->first, VERR_CANCELLED,
150 Guest::tr("VM is shutting down, canceling uncompleted guest requests ..."));
151 AssertRC(rc2);
152 }
153
154 /* Destroy left over callback data. */
155 for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
156 callbackDestroy(it->first);
157
158 /* Clear process map (remove all callbacks). */
159 mGuestProcessMap.clear();
160 }
161#endif
162
163 /* Destroy stat update timer */
164 int vrc = RTTimerLRDestroy (mStatTimer);
165 AssertMsgRC (vrc, ("Failed to create guest statistics "
166 "update timer(%Rra)\n", vrc));
167 mStatTimer = NULL;
168 mMagic = 0;
169
170#ifdef VBOX_WITH_DRAG_AND_DROP
171 delete m_pGuestDnD;
172 m_pGuestDnD = NULL;
173#endif
174
175 unconst(mParent) = NULL;
176}
177
178/* static */
179void Guest::staticUpdateStats(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick)
180{
181 AssertReturnVoid (pvUser != NULL);
182 Guest *guest = static_cast <Guest *> (pvUser);
183 Assert(guest->mMagic == GUEST_MAGIC);
184 if (guest->mMagic == GUEST_MAGIC)
185 guest->updateStats(iTick);
186
187 NOREF (hTimerLR);
188}
189
190void Guest::updateStats(uint64_t iTick)
191{
192 uint64_t uFreeTotal, uAllocTotal, uBalloonedTotal, uSharedTotal;
193 uint64_t uTotalMem, uPrivateMem, uSharedMem, uZeroMem;
194
195 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
196
197 ULONG aGuestStats[GUESTSTATTYPE_MAX];
198 RT_ZERO(aGuestStats);
199 ULONG validStats = mGuestValidStats;
200 /* Check if we have anything to report */
201 if (validStats)
202 {
203 mGuestValidStats = pm::GUESTSTATMASK_NONE;
204 memcpy(aGuestStats, mCurrentGuestStat, sizeof(aGuestStats));
205 }
206 alock.release();
207 /*
208 * Calling SessionMachine may take time as the object resides in VBoxSVC
209 * process. This is why we took a snapshot of currently collected stats
210 * and released the lock.
211 */
212 uFreeTotal = 0;
213 uAllocTotal = 0;
214 uBalloonedTotal = 0;
215 uSharedTotal = 0;
216 uTotalMem = 0;
217 uPrivateMem = 0;
218 uSharedMem = 0;
219 uZeroMem = 0;
220
221 Console::SafeVMPtr pVM (mParent);
222 if (pVM.isOk())
223 {
224 int rc;
225
226 /*
227 * There is no point in collecting VM shared memory if other memory
228 * statistics are not available yet. Or is it?
229 */
230 if (validStats)
231 {
232 /* Query the missing per-VM memory statistics. */
233 rc = PGMR3QueryMemoryStats(pVM.raw(), &uTotalMem, &uPrivateMem, &uSharedMem, &uZeroMem);
234 if (rc == VINF_SUCCESS)
235 {
236 validStats |= pm::GUESTSTATMASK_MEMSHARED;
237 }
238 }
239
240 if (mCollectVMMStats)
241 {
242 rc = PGMR3QueryGlobalMemoryStats(pVM.raw(), &uAllocTotal, &uFreeTotal, &uBalloonedTotal, &uSharedTotal);
243 AssertRC(rc);
244 if (rc == VINF_SUCCESS)
245 {
246 validStats |= pm::GUESTSTATMASK_ALLOCVMM|pm::GUESTSTATMASK_FREEVMM|
247 pm::GUESTSTATMASK_BALOONVMM|pm::GUESTSTATMASK_SHAREDVMM;
248 }
249 }
250
251 }
252
253 mParent->reportGuestStatistics(validStats,
254 aGuestStats[GUESTSTATTYPE_CPUUSER],
255 aGuestStats[GUESTSTATTYPE_CPUKERNEL],
256 aGuestStats[GUESTSTATTYPE_CPUIDLE],
257 /* Convert the units for RAM usage stats: page (4K) -> 1KB units */
258 mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K),
259 mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K),
260 mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K),
261 (ULONG)(uSharedMem / _1K), /* bytes -> KB */
262 mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K),
263 mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K),
264 (ULONG)(uAllocTotal / _1K), /* bytes -> KB */
265 (ULONG)(uFreeTotal / _1K),
266 (ULONG)(uBalloonedTotal / _1K),
267 (ULONG)(uSharedTotal / _1K));
268}
269
270// IGuest properties
271/////////////////////////////////////////////////////////////////////////////
272
273STDMETHODIMP Guest::COMGETTER(OSTypeId)(BSTR *a_pbstrOSTypeId)
274{
275 CheckComArgOutPointerValid(a_pbstrOSTypeId);
276
277 AutoCaller autoCaller(this);
278 HRESULT hrc = autoCaller.rc();
279 if (SUCCEEDED(hrc))
280 {
281 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
282 if (!mData.mInterfaceVersion.isEmpty())
283 mData.mOSTypeId.cloneTo(a_pbstrOSTypeId);
284 else
285 {
286 /* Redirect the call to IMachine if no additions are installed. */
287 ComPtr<IMachine> ptrMachine(mParent->machine());
288 alock.release();
289 hrc = ptrMachine->COMGETTER(OSTypeId)(a_pbstrOSTypeId);
290 }
291 }
292 return hrc;
293}
294
295STDMETHODIMP Guest::COMGETTER(AdditionsRunLevel) (AdditionsRunLevelType_T *aRunLevel)
296{
297 AutoCaller autoCaller(this);
298 if (FAILED(autoCaller.rc())) return autoCaller.rc();
299
300 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
301
302 *aRunLevel = mData.mAdditionsRunLevel;
303
304 return S_OK;
305}
306
307STDMETHODIMP Guest::COMGETTER(AdditionsVersion)(BSTR *a_pbstrAdditionsVersion)
308{
309 CheckComArgOutPointerValid(a_pbstrAdditionsVersion);
310
311 AutoCaller autoCaller(this);
312 HRESULT hrc = autoCaller.rc();
313 if (SUCCEEDED(hrc))
314 {
315 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
316
317 /*
318 * Return the ReportGuestInfo2 version info if available.
319 */
320 if ( !mData.mAdditionsVersionNew.isEmpty()
321 || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None)
322 mData.mAdditionsVersionNew.cloneTo(a_pbstrAdditionsVersion);
323 else
324 {
325 /*
326 * If we're running older guest additions (< 3.2.0) try get it from
327 * the guest properties. Detected switched around Version and
328 * Revision in early 3.1.x releases (see r57115).
329 */
330 ComPtr<IMachine> ptrMachine = mParent->machine();
331 alock.release(); /* No need to hold this during the IPC fun. */
332
333 Bstr bstr;
334 hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam());
335 if (SUCCEEDED(hrc))
336 {
337 Utf8Str str(bstr);
338 if (str.count('.') == 0)
339 hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam());
340 str = bstr;
341 if (str.count('.') != 2)
342 hrc = E_FAIL;
343 }
344
345 if (SUCCEEDED(hrc))
346 bstr.detachTo(a_pbstrAdditionsVersion);
347 else
348 {
349 /* Returning 1.4 is better than nothing. */
350 alock.acquire();
351 mData.mInterfaceVersion.cloneTo(a_pbstrAdditionsVersion);
352 hrc = S_OK;
353 }
354 }
355 }
356 return hrc;
357}
358
359STDMETHODIMP Guest::COMGETTER(AdditionsRevision)(ULONG *a_puAdditionsRevision)
360{
361 CheckComArgOutPointerValid(a_puAdditionsRevision);
362
363 AutoCaller autoCaller(this);
364 HRESULT hrc = autoCaller.rc();
365 if (SUCCEEDED(hrc))
366 {
367 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
368
369 /*
370 * Return the ReportGuestInfo2 version info if available.
371 */
372 if ( !mData.mAdditionsVersionNew.isEmpty()
373 || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None)
374 *a_puAdditionsRevision = mData.mAdditionsRevision;
375 else
376 {
377 /*
378 * If we're running older guest additions (< 3.2.0) try get it from
379 * the guest properties. Detected switched around Version and
380 * Revision in early 3.1.x releases (see r57115).
381 */
382 ComPtr<IMachine> ptrMachine = mParent->machine();
383 alock.release(); /* No need to hold this during the IPC fun. */
384
385 Bstr bstr;
386 hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam());
387 if (SUCCEEDED(hrc))
388 {
389 Utf8Str str(bstr);
390 uint32_t uRevision;
391 int vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision);
392 if (vrc != VINF_SUCCESS && str.count('.') == 2)
393 {
394 hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam());
395 if (SUCCEEDED(hrc))
396 {
397 str = bstr;
398 vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision);
399 }
400 }
401 if (vrc == VINF_SUCCESS)
402 *a_puAdditionsRevision = uRevision;
403 else
404 hrc = VBOX_E_IPRT_ERROR;
405 }
406 if (FAILED(hrc))
407 {
408 /* Return 0 if we don't know. */
409 *a_puAdditionsRevision = 0;
410 hrc = S_OK;
411 }
412 }
413 }
414 return hrc;
415}
416
417STDMETHODIMP Guest::COMGETTER(Facilities)(ComSafeArrayOut(IAdditionsFacility*, aFacilities))
418{
419 CheckComArgOutSafeArrayPointerValid(aFacilities);
420
421 AutoCaller autoCaller(this);
422 if (FAILED(autoCaller.rc())) return autoCaller.rc();
423
424 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
425
426 SafeIfaceArray<IAdditionsFacility> fac(mData.mFacilityMap);
427 fac.detachTo(ComSafeArrayOutArg(aFacilities));
428
429 return S_OK;
430}
431
432BOOL Guest::isPageFusionEnabled()
433{
434 AutoCaller autoCaller(this);
435 if (FAILED(autoCaller.rc())) return false;
436
437 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
438
439 return mfPageFusionEnabled;
440}
441
442STDMETHODIMP Guest::COMGETTER(MemoryBalloonSize)(ULONG *aMemoryBalloonSize)
443{
444 CheckComArgOutPointerValid(aMemoryBalloonSize);
445
446 AutoCaller autoCaller(this);
447 if (FAILED(autoCaller.rc())) return autoCaller.rc();
448
449 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
450
451 *aMemoryBalloonSize = mMemoryBalloonSize;
452
453 return S_OK;
454}
455
456STDMETHODIMP Guest::COMSETTER(MemoryBalloonSize)(ULONG aMemoryBalloonSize)
457{
458 AutoCaller autoCaller(this);
459 if (FAILED(autoCaller.rc())) return autoCaller.rc();
460
461 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
462
463 /* We must be 100% sure that IMachine::COMSETTER(MemoryBalloonSize)
464 * does not call us back in any way! */
465 HRESULT ret = mParent->machine()->COMSETTER(MemoryBalloonSize)(aMemoryBalloonSize);
466 if (ret == S_OK)
467 {
468 mMemoryBalloonSize = aMemoryBalloonSize;
469 /* forward the information to the VMM device */
470 VMMDev *pVMMDev = mParent->getVMMDev();
471 /* MUST release all locks before calling VMM device as its critsect
472 * has higher lock order than anything in Main. */
473 alock.release();
474 if (pVMMDev)
475 {
476 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
477 if (pVMMDevPort)
478 pVMMDevPort->pfnSetMemoryBalloon(pVMMDevPort, aMemoryBalloonSize);
479 }
480 }
481
482 return ret;
483}
484
485STDMETHODIMP Guest::COMGETTER(StatisticsUpdateInterval)(ULONG *aUpdateInterval)
486{
487 CheckComArgOutPointerValid(aUpdateInterval);
488
489 AutoCaller autoCaller(this);
490 if (FAILED(autoCaller.rc())) return autoCaller.rc();
491
492 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
493
494 *aUpdateInterval = mStatUpdateInterval;
495 return S_OK;
496}
497
498STDMETHODIMP Guest::COMSETTER(StatisticsUpdateInterval)(ULONG aUpdateInterval)
499{
500 AutoCaller autoCaller(this);
501 if (FAILED(autoCaller.rc())) return autoCaller.rc();
502
503 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
504
505 if (mStatUpdateInterval)
506 if (aUpdateInterval == 0)
507 RTTimerLRStop(mStatTimer);
508 else
509 RTTimerLRChangeInterval(mStatTimer, aUpdateInterval);
510 else
511 if (aUpdateInterval != 0)
512 {
513 RTTimerLRChangeInterval(mStatTimer, aUpdateInterval);
514 RTTimerLRStart(mStatTimer, 0);
515 }
516 mStatUpdateInterval = aUpdateInterval;
517 /* forward the information to the VMM device */
518 VMMDev *pVMMDev = mParent->getVMMDev();
519 /* MUST release all locks before calling VMM device as its critsect
520 * has higher lock order than anything in Main. */
521 alock.release();
522 if (pVMMDev)
523 {
524 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
525 if (pVMMDevPort)
526 pVMMDevPort->pfnSetStatisticsInterval(pVMMDevPort, aUpdateInterval);
527 }
528
529 return S_OK;
530}
531
532STDMETHODIMP Guest::InternalGetStatistics(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
533 ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared,
534 ULONG *aMemCache, ULONG *aPageTotal,
535 ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal)
536{
537 CheckComArgOutPointerValid(aCpuUser);
538 CheckComArgOutPointerValid(aCpuKernel);
539 CheckComArgOutPointerValid(aCpuIdle);
540 CheckComArgOutPointerValid(aMemTotal);
541 CheckComArgOutPointerValid(aMemFree);
542 CheckComArgOutPointerValid(aMemBalloon);
543 CheckComArgOutPointerValid(aMemShared);
544 CheckComArgOutPointerValid(aMemCache);
545 CheckComArgOutPointerValid(aPageTotal);
546 CheckComArgOutPointerValid(aMemAllocTotal);
547 CheckComArgOutPointerValid(aMemFreeTotal);
548 CheckComArgOutPointerValid(aMemBalloonTotal);
549 CheckComArgOutPointerValid(aMemSharedTotal);
550
551 AutoCaller autoCaller(this);
552 if (FAILED(autoCaller.rc())) return autoCaller.rc();
553
554 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
555
556 *aCpuUser = mCurrentGuestStat[GUESTSTATTYPE_CPUUSER];
557 *aCpuKernel = mCurrentGuestStat[GUESTSTATTYPE_CPUKERNEL];
558 *aCpuIdle = mCurrentGuestStat[GUESTSTATTYPE_CPUIDLE];
559 *aMemTotal = mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */
560 *aMemFree = mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K); /* page (4K) -> 1KB units */
561 *aMemBalloon = mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K); /* page (4K) -> 1KB units */
562 *aMemCache = mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K); /* page (4K) -> 1KB units */
563 *aPageTotal = mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */
564
565 /* MUST release all locks before calling any PGM statistics queries,
566 * as they are executed by EMT and that might deadlock us by VMM device
567 * activity which waits for the Guest object lock. */
568 alock.release();
569 Console::SafeVMPtr pVM (mParent);
570 if (pVM.isOk())
571 {
572 uint64_t uFreeTotal, uAllocTotal, uBalloonedTotal, uSharedTotal;
573 *aMemFreeTotal = 0;
574 int rc = PGMR3QueryGlobalMemoryStats(pVM.raw(), &uAllocTotal, &uFreeTotal, &uBalloonedTotal, &uSharedTotal);
575 AssertRC(rc);
576 if (rc == VINF_SUCCESS)
577 {
578 *aMemAllocTotal = (ULONG)(uAllocTotal / _1K); /* bytes -> KB */
579 *aMemFreeTotal = (ULONG)(uFreeTotal / _1K);
580 *aMemBalloonTotal = (ULONG)(uBalloonedTotal / _1K);
581 *aMemSharedTotal = (ULONG)(uSharedTotal / _1K);
582 }
583 else
584 return E_FAIL;
585
586 /* Query the missing per-VM memory statistics. */
587 *aMemShared = 0;
588 uint64_t uTotalMem, uPrivateMem, uSharedMem, uZeroMem;
589 rc = PGMR3QueryMemoryStats(pVM.raw(), &uTotalMem, &uPrivateMem, &uSharedMem, &uZeroMem);
590 if (rc == VINF_SUCCESS)
591 {
592 *aMemShared = (ULONG)(uSharedMem / _1K);
593 }
594 else
595 return E_FAIL;
596 }
597 else
598 {
599 *aMemAllocTotal = 0;
600 *aMemFreeTotal = 0;
601 *aMemBalloonTotal = 0;
602 *aMemSharedTotal = 0;
603 *aMemShared = 0;
604 return E_FAIL;
605 }
606
607 return S_OK;
608}
609
610HRESULT Guest::setStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal)
611{
612 static ULONG indexToPerfMask[] =
613 {
614 pm::GUESTSTATMASK_CPUUSER,
615 pm::GUESTSTATMASK_CPUKERNEL,
616 pm::GUESTSTATMASK_CPUIDLE,
617 pm::GUESTSTATMASK_MEMTOTAL,
618 pm::GUESTSTATMASK_MEMFREE,
619 pm::GUESTSTATMASK_MEMBALLOON,
620 pm::GUESTSTATMASK_MEMCACHE,
621 pm::GUESTSTATMASK_PAGETOTAL,
622 pm::GUESTSTATMASK_NONE
623 };
624 AutoCaller autoCaller(this);
625 if (FAILED(autoCaller.rc())) return autoCaller.rc();
626
627 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
628
629 if (enmType >= GUESTSTATTYPE_MAX)
630 return E_INVALIDARG;
631
632 mCurrentGuestStat[enmType] = aVal;
633 mGuestValidStats |= indexToPerfMask[enmType];
634 return S_OK;
635}
636
637/**
638 * Returns the status of a specified Guest Additions facility.
639 *
640 * @return aStatus Current status of specified facility.
641 * @param aType Facility to get the status from.
642 * @param aTimestamp Timestamp of last facility status update in ms (optional).
643 */
644STDMETHODIMP Guest::GetFacilityStatus(AdditionsFacilityType_T aType, LONG64 *aTimestamp, AdditionsFacilityStatus_T *aStatus)
645{
646 AutoCaller autoCaller(this);
647 if (FAILED(autoCaller.rc())) return autoCaller.rc();
648
649 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
650
651 CheckComArgNotNull(aStatus);
652 /* Not checking for aTimestamp is intentional; it's optional. */
653
654 FacilityMapIterConst it = mData.mFacilityMap.find(aType);
655 if (it != mData.mFacilityMap.end())
656 {
657 AdditionsFacility *pFacility = it->second;
658 ComAssert(pFacility);
659 *aStatus = pFacility->getStatus();
660 if (aTimestamp)
661 *aTimestamp = pFacility->getLastUpdated();
662 }
663 else
664 {
665 /*
666 * Do not fail here -- could be that the facility never has been brought up (yet) but
667 * the host wants to have its status anyway. So just tell we don't know at this point.
668 */
669 *aStatus = AdditionsFacilityStatus_Unknown;
670 if (aTimestamp)
671 *aTimestamp = RTTimeMilliTS();
672 }
673 return S_OK;
674}
675
676STDMETHODIMP Guest::GetAdditionsStatus(AdditionsRunLevelType_T aLevel, BOOL *aActive)
677{
678 AutoCaller autoCaller(this);
679 if (FAILED(autoCaller.rc())) return autoCaller.rc();
680
681 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
682
683 HRESULT rc = S_OK;
684 switch (aLevel)
685 {
686 case AdditionsRunLevelType_System:
687 *aActive = (mData.mAdditionsRunLevel > AdditionsRunLevelType_None);
688 break;
689
690 case AdditionsRunLevelType_Userland:
691 *aActive = (mData.mAdditionsRunLevel >= AdditionsRunLevelType_Userland);
692 break;
693
694 case AdditionsRunLevelType_Desktop:
695 *aActive = (mData.mAdditionsRunLevel >= AdditionsRunLevelType_Desktop);
696 break;
697
698 default:
699 rc = setError(VBOX_E_NOT_SUPPORTED,
700 tr("Invalid status level defined: %u"), aLevel);
701 break;
702 }
703
704 return rc;
705}
706
707STDMETHODIMP Guest::SetCredentials(IN_BSTR aUserName, IN_BSTR aPassword,
708 IN_BSTR aDomain, BOOL aAllowInteractiveLogon)
709{
710 AutoCaller autoCaller(this);
711 if (FAILED(autoCaller.rc())) return autoCaller.rc();
712
713 /* forward the information to the VMM device */
714 VMMDev *pVMMDev = mParent->getVMMDev();
715 if (pVMMDev)
716 {
717 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
718 if (pVMMDevPort)
719 {
720 uint32_t u32Flags = VMMDEV_SETCREDENTIALS_GUESTLOGON;
721 if (!aAllowInteractiveLogon)
722 u32Flags = VMMDEV_SETCREDENTIALS_NOLOCALLOGON;
723
724 pVMMDevPort->pfnSetCredentials(pVMMDevPort,
725 Utf8Str(aUserName).c_str(),
726 Utf8Str(aPassword).c_str(),
727 Utf8Str(aDomain).c_str(),
728 u32Flags);
729 return S_OK;
730 }
731 }
732
733 return setError(VBOX_E_VM_ERROR,
734 tr("VMM device is not available (is the VM running?)"));
735}
736
737STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
738{
739 /* Input validation */
740 CheckComArgSafeArrayNotNull(allowedActions);
741 CheckComArgSafeArrayNotNull(formats);
742 CheckComArgOutPointerValid(pResultAction);
743
744 AutoCaller autoCaller(this);
745 if (FAILED(autoCaller.rc())) return autoCaller.rc();
746
747#ifdef VBOX_WITH_DRAG_AND_DROP
748 return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction);
749#else /* VBOX_WITH_DRAG_AND_DROP */
750 ReturnComNotImplemented();
751#endif /* !VBOX_WITH_DRAG_AND_DROP */
752}
753
754STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
755{
756 /* Input validation */
757 CheckComArgSafeArrayNotNull(allowedActions);
758 CheckComArgSafeArrayNotNull(formats);
759 CheckComArgOutPointerValid(pResultAction);
760
761 AutoCaller autoCaller(this);
762 if (FAILED(autoCaller.rc())) return autoCaller.rc();
763
764#ifdef VBOX_WITH_DRAG_AND_DROP
765 return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction);
766#else /* VBOX_WITH_DRAG_AND_DROP */
767 ReturnComNotImplemented();
768#endif /* !VBOX_WITH_DRAG_AND_DROP */
769}
770
771STDMETHODIMP Guest::DragHGLeave(ULONG uScreenId)
772{
773 AutoCaller autoCaller(this);
774 if (FAILED(autoCaller.rc())) return autoCaller.rc();
775
776#ifdef VBOX_WITH_DRAG_AND_DROP
777 return m_pGuestDnD->dragHGLeave(uScreenId);
778#else /* VBOX_WITH_DRAG_AND_DROP */
779 ReturnComNotImplemented();
780#endif /* !VBOX_WITH_DRAG_AND_DROP */
781}
782
783STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
784{
785 /* Input validation */
786 CheckComArgSafeArrayNotNull(allowedActions);
787 CheckComArgSafeArrayNotNull(formats);
788 CheckComArgOutPointerValid(pstrFormat);
789 CheckComArgOutPointerValid(pResultAction);
790
791 AutoCaller autoCaller(this);
792 if (FAILED(autoCaller.rc())) return autoCaller.rc();
793
794#ifdef VBOX_WITH_DRAG_AND_DROP
795 return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pstrFormat, pResultAction);
796#else /* VBOX_WITH_DRAG_AND_DROP */
797 ReturnComNotImplemented();
798#endif /* !VBOX_WITH_DRAG_AND_DROP */
799}
800
801STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
802{
803 /* Input validation */
804 CheckComArgStrNotEmptyOrNull(bstrFormat);
805 CheckComArgSafeArrayNotNull(data);
806 CheckComArgOutPointerValid(ppProgress);
807
808 AutoCaller autoCaller(this);
809 if (FAILED(autoCaller.rc())) return autoCaller.rc();
810
811#ifdef VBOX_WITH_DRAG_AND_DROP
812 return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat, ComSafeArrayInArg(data), ppProgress);
813#else /* VBOX_WITH_DRAG_AND_DROP */
814 ReturnComNotImplemented();
815#endif /* !VBOX_WITH_DRAG_AND_DROP */
816}
817
818STDMETHODIMP Guest::DragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction)
819{
820 /* Input validation */
821 CheckComArgSafeArrayNotNull(formats);
822 CheckComArgSafeArrayNotNull(allowedActions);
823 CheckComArgOutPointerValid(pDefaultAction);
824
825 AutoCaller autoCaller(this);
826 if (FAILED(autoCaller.rc())) return autoCaller.rc();
827
828#ifdef VBOX_WITH_DRAG_AND_DROP
829 return m_pGuestDnD->dragGHPending(uScreenId, ComSafeArrayOutArg(formats), ComSafeArrayOutArg(allowedActions), pDefaultAction);
830#else /* VBOX_WITH_DRAG_AND_DROP */
831 ReturnComNotImplemented();
832#endif /* !VBOX_WITH_DRAG_AND_DROP */
833}
834
835STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress)
836{
837 /* Input validation */
838 CheckComArgStrNotEmptyOrNull(bstrFormat);
839 CheckComArgOutPointerValid(ppProgress);
840
841 AutoCaller autoCaller(this);
842 if (FAILED(autoCaller.rc())) return autoCaller.rc();
843
844#ifdef VBOX_WITH_DRAG_AND_DROP
845 return m_pGuestDnD->dragGHDropped(bstrFormat, action, ppProgress);
846#else /* VBOX_WITH_DRAG_AND_DROP */
847 ReturnComNotImplemented();
848#endif /* !VBOX_WITH_DRAG_AND_DROP */
849}
850
851STDMETHODIMP Guest::DragGHGetData(ComSafeArrayOut(BYTE, data))
852{
853 /* Input validation */
854 CheckComArgSafeArrayNotNull(data);
855
856 AutoCaller autoCaller(this);
857 if (FAILED(autoCaller.rc())) return autoCaller.rc();
858
859#ifdef VBOX_WITH_DRAG_AND_DROP
860 return m_pGuestDnD->dragGHGetData(ComSafeArrayOutArg(data));
861#else /* VBOX_WITH_DRAG_AND_DROP */
862 ReturnComNotImplemented();
863#endif /* !VBOX_WITH_DRAG_AND_DROP */
864}
865
866// public methods only for internal purposes
867/////////////////////////////////////////////////////////////////////////////
868
869/**
870 * Sets the general Guest Additions information like
871 * API (interface) version and OS type. Gets called by
872 * vmmdevUpdateGuestInfo.
873 *
874 * @param aInterfaceVersion
875 * @param aOsType
876 */
877void Guest::setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType)
878{
879 RTTIMESPEC TimeSpecTS;
880 RTTimeNow(&TimeSpecTS);
881
882 AutoCaller autoCaller(this);
883 AssertComRCReturnVoid(autoCaller.rc());
884
885 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
886
887
888 /*
889 * Note: The Guest Additions API (interface) version is deprecated
890 * and will not be used anymore! We might need it to at least report
891 * something as version number if *really* ancient Guest Additions are
892 * installed (without the guest version + revision properties having set).
893 */
894 mData.mInterfaceVersion = aInterfaceVersion;
895
896 /*
897 * Older Additions rely on the Additions API version whether they
898 * are assumed to be active or not. Since newer Additions do report
899 * the Additions version *before* calling this function (by calling
900 * VMMDevReportGuestInfo2, VMMDevReportGuestStatus, VMMDevReportGuestInfo,
901 * in that order) we can tell apart old and new Additions here. Old
902 * Additions never would set VMMDevReportGuestInfo2 (which set mData.mAdditionsVersion)
903 * so they just rely on the aInterfaceVersion string (which gets set by
904 * VMMDevReportGuestInfo).
905 *
906 * So only mark the Additions as being active (run level = system) when we
907 * don't have the Additions version set.
908 */
909 if (mData.mAdditionsVersionNew.isEmpty())
910 {
911 if (aInterfaceVersion.isEmpty())
912 mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
913 else
914 {
915 mData.mAdditionsRunLevel = AdditionsRunLevelType_System;
916
917 /*
918 * To keep it compatible with the old Guest Additions behavior we need to set the
919 * "graphics" (feature) facility to active as soon as we got the Guest Additions
920 * interface version.
921 */
922 facilityUpdate(VBoxGuestFacilityType_Graphics, VBoxGuestFacilityStatus_Active, 0 /*fFlags*/, &TimeSpecTS);
923 }
924 }
925
926 /*
927 * Older Additions didn't have this finer grained capability bit,
928 * so enable it by default. Newer Additions will not enable this here
929 * and use the setSupportedFeatures function instead.
930 */
931 /** @todo r=bird: I don't get the above comment nor the code below...
932 * One talks about capability bits, the one always does something to a facility.
933 * Then there is the comment below it all, which is placed like it addresses the
934 * mOSTypeId, but talks about something which doesn't remotely like mOSTypeId...
935 *
936 * Andy, could you please try clarify and make the comments shorter and more
937 * coherent! Also, explain why this is important and what depends on it.
938 *
939 * PS. There is the VMMDEV_GUEST_SUPPORTS_GRAPHICS capability* report... It
940 * should come in pretty quickly after this update, normally.
941 */
942 facilityUpdate(VBoxGuestFacilityType_Graphics,
943 facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver)
944 ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
945 0 /*fFlags*/, &TimeSpecTS); /** @todo the timestamp isn't gonna be right here on saved state restore. */
946
947 /*
948 * Note! There is a race going on between setting mAdditionsRunLevel and
949 * mSupportsGraphics here and disabling/enabling it later according to
950 * its real status when using new(er) Guest Additions.
951 */
952 mData.mOSTypeId = Global::OSTypeId(aOsType);
953}
954
955/**
956 * Sets the Guest Additions version information details.
957 *
958 * Gets called by vmmdevUpdateGuestInfo2 and vmmdevUpdateGuestInfo (to clear the
959 * state).
960 *
961 * @param a_uFullVersion VBoxGuestInfo2::additionsMajor,
962 * VBoxGuestInfo2::additionsMinor and
963 * VBoxGuestInfo2::additionsBuild combined into
964 * one value by VBOX_FULL_VERSION_MAKE.
965 *
966 * When this is 0, it's vmmdevUpdateGuestInfo
967 * calling to reset the state.
968 *
969 * @param a_pszName Build type tag and/or publisher tag, empty
970 * string if neiter of those are present.
971 * @param a_uRevision See VBoxGuestInfo2::additionsRevision.
972 * @param a_fFeatures See VBoxGuestInfo2::additionsFeatures.
973 */
974void Guest::setAdditionsInfo2(uint32_t a_uFullVersion, const char *a_pszName, uint32_t a_uRevision, uint32_t a_fFeatures)
975{
976 AutoCaller autoCaller(this);
977 AssertComRCReturnVoid(autoCaller.rc());
978
979 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
980
981 if (a_uFullVersion)
982 {
983 mData.mAdditionsVersionNew = BstrFmt(*a_pszName ? "%u.%u.%u_%s" : "%u.%u.%u",
984 VBOX_FULL_VERSION_GET_MAJOR(a_uFullVersion),
985 VBOX_FULL_VERSION_GET_MINOR(a_uFullVersion),
986 VBOX_FULL_VERSION_GET_BUILD(a_uFullVersion),
987 a_pszName);
988 mData.mAdditionsVersionFull = a_uFullVersion;
989 mData.mAdditionsRevision = a_uRevision;
990 mData.mAdditionsFeatures = a_fFeatures;
991 }
992 else
993 {
994 Assert(!a_fFeatures && !a_uRevision && !*a_pszName);
995 mData.mAdditionsVersionNew.setNull();
996 mData.mAdditionsVersionFull = 0;
997 mData.mAdditionsRevision = 0;
998 mData.mAdditionsFeatures = 0;
999 }
1000}
1001
1002bool Guest::facilityIsActive(VBoxGuestFacilityType enmFacility)
1003{
1004 Assert(enmFacility < INT32_MAX);
1005 FacilityMapIterConst it = mData.mFacilityMap.find((AdditionsFacilityType_T)enmFacility);
1006 if (it != mData.mFacilityMap.end())
1007 {
1008 AdditionsFacility *pFac = it->second;
1009 return (pFac->getStatus() == AdditionsFacilityStatus_Active);
1010 }
1011 return false;
1012}
1013
1014void Guest::facilityUpdate(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus,
1015 uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS)
1016{
1017 AssertReturnVoid( a_enmFacility < VBoxGuestFacilityType_All
1018 && a_enmFacility > VBoxGuestFacilityType_Unknown);
1019
1020 FacilityMapIter it = mData.mFacilityMap.find((AdditionsFacilityType_T)a_enmFacility);
1021 if (it != mData.mFacilityMap.end())
1022 {
1023 AdditionsFacility *pFac = it->second;
1024 pFac->update((AdditionsFacilityStatus_T)a_enmStatus, a_fFlags, a_pTimeSpecTS);
1025 }
1026 else
1027 {
1028 if (mData.mFacilityMap.size() > 64)
1029 {
1030 /* The easy way out for now. We could automatically destroy
1031 inactive facilities like VMMDev does if we like... */
1032 AssertFailedReturnVoid();
1033 }
1034
1035 ComObjPtr<AdditionsFacility> ptrFac;
1036 ptrFac.createObject();
1037 AssertReturnVoid(!ptrFac.isNull());
1038
1039 HRESULT hrc = ptrFac->init(this, (AdditionsFacilityType_T)a_enmFacility, (AdditionsFacilityStatus_T)a_enmStatus,
1040 a_fFlags, a_pTimeSpecTS);
1041 if (SUCCEEDED(hrc))
1042 mData.mFacilityMap.insert(std::make_pair((AdditionsFacilityType_T)a_enmFacility, ptrFac));
1043 }
1044}
1045
1046/**
1047 * Sets the status of a certain Guest Additions facility.
1048 *
1049 * Gets called by vmmdevUpdateGuestStatus, which just passes the report along.
1050 *
1051 * @param a_pInterface Pointer to this interface.
1052 * @param a_enmFacility The facility.
1053 * @param a_enmStatus The status.
1054 * @param a_fFlags Flags assoicated with the update. Currently
1055 * reserved and should be ignored.
1056 * @param a_pTimeSpecTS Pointer to the timestamp of this report.
1057 * @sa PDMIVMMDEVCONNECTOR::pfnUpdateGuestStatus, vmmdevUpdateGuestStatus
1058 * @thread The emulation thread.
1059 */
1060void Guest::setAdditionsStatus(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus,
1061 uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS)
1062{
1063 Assert( a_enmFacility > VBoxGuestFacilityType_Unknown
1064 && a_enmFacility <= VBoxGuestFacilityType_All); /* Paranoia, VMMDev checks for this. */
1065
1066 AutoCaller autoCaller(this);
1067 AssertComRCReturnVoid(autoCaller.rc());
1068
1069 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1070
1071 /*
1072 * Set a specific facility status.
1073 */
1074 if (a_enmFacility == VBoxGuestFacilityType_All)
1075 for (FacilityMapIter it = mData.mFacilityMap.begin(); it != mData.mFacilityMap.end(); ++it)
1076 facilityUpdate((VBoxGuestFacilityType)it->first, a_enmStatus, a_fFlags, a_pTimeSpecTS);
1077 else /* Update one facility only. */
1078 facilityUpdate(a_enmFacility, a_enmStatus, a_fFlags, a_pTimeSpecTS);
1079
1080 /*
1081 * Recalc the runlevel.
1082 */
1083 if (facilityIsActive(VBoxGuestFacilityType_VBoxTrayClient))
1084 mData.mAdditionsRunLevel = AdditionsRunLevelType_Desktop;
1085 else if (facilityIsActive(VBoxGuestFacilityType_VBoxService))
1086 mData.mAdditionsRunLevel = AdditionsRunLevelType_Userland;
1087 else if (facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver))
1088 mData.mAdditionsRunLevel = AdditionsRunLevelType_System;
1089 else
1090 mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
1091}
1092
1093/**
1094 * Sets the supported features (and whether they are active or not).
1095 *
1096 * @param fCaps Guest capability bit mask (VMMDEV_GUEST_SUPPORTS_XXX).
1097 */
1098void Guest::setSupportedFeatures(uint32_t aCaps)
1099{
1100 AutoCaller autoCaller(this);
1101 AssertComRCReturnVoid(autoCaller.rc());
1102
1103 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1104
1105 /** @todo A nit: The timestamp is wrong on saved state restore. Would be better
1106 * to move the graphics and seamless capability -> facility translation to
1107 * VMMDev so this could be saved. */
1108 RTTIMESPEC TimeSpecTS;
1109 RTTimeNow(&TimeSpecTS);
1110
1111 facilityUpdate(VBoxGuestFacilityType_Seamless,
1112 aCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
1113 0 /*fFlags*/, &TimeSpecTS);
1114 /** @todo Add VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING */
1115 facilityUpdate(VBoxGuestFacilityType_Graphics,
1116 aCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
1117 0 /*fFlags*/, &TimeSpecTS);
1118}
1119/* 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