VirtualBox

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

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

Main/GuestCtrl: Introduced host<->guest PID mapping for immediate returns of executeProcess(); bugfixes.

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