VirtualBox

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

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

Runtime: new guest OS type for Solaris 11
Frontends/VirtualBox: add new patterns for Solaris 11 guest OS type, reuse the icon
Frontends/VBoxManage: more details for "list ostypes"
Main/xml: make guest OS type in config file an arbitrary string (still validated/mapped in the old way in the settings code), remove hardcoded limit of 8 network adapters
Main/Global: move list of valid guest OS types into a single place, add function to get the network adapter limit for each chipset type
Main/Console+Machine+Snapshot+NetworkAdapter+Appliance+VirtualBox+Guest+SystemProperties: consistently use the appropriate network adapter limit so that ICH9 chipset can use 36 network adapters, adapt to cleaned up guest OS type handling, remove leftover rendundant guest OS mapping, whitespace
Network/NAT: release log message cosmetics, allow unlimited number of instances, fix maxconn clamping
Network/PCNet+VirtioNet+E1000: allow unlimited number of instances

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.0 KB
Line 
1/* $Id: GuestImpl.cpp 39248 2011-11-09 12:29:53Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation: Guest
4 */
5
6/*
7 * Copyright (C) 2006-2011 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#include "VMMDev.h"
24
25#include "AutoCaller.h"
26#include "Logging.h"
27
28#include <VBox/VMMDev.h>
29#ifdef VBOX_WITH_GUEST_CONTROL
30# include <VBox/com/array.h>
31# include <VBox/com/ErrorInfo.h>
32#endif
33#include <iprt/cpp/utils.h>
34#include <VBox/vmm/pgm.h>
35
36// defines
37/////////////////////////////////////////////////////////////////////////////
38
39// constructor / destructor
40/////////////////////////////////////////////////////////////////////////////
41
42DEFINE_EMPTY_CTOR_DTOR (Guest)
43
44HRESULT Guest::FinalConstruct()
45{
46 return BaseFinalConstruct();
47}
48
49void Guest::FinalRelease()
50{
51 uninit ();
52 BaseFinalRelease();
53}
54
55// public methods only for internal purposes
56/////////////////////////////////////////////////////////////////////////////
57
58/**
59 * Initializes the guest object.
60 */
61HRESULT Guest::init(Console *aParent)
62{
63 LogFlowThisFunc(("aParent=%p\n", aParent));
64
65 ComAssertRet(aParent, E_INVALIDARG);
66
67 /* Enclose the state transition NotReady->InInit->Ready */
68 AutoInitSpan autoInitSpan(this);
69 AssertReturn(autoInitSpan.isOk(), E_FAIL);
70
71 unconst(mParent) = aParent;
72
73 /* Confirm a successful initialization when it's the case */
74 autoInitSpan.setSucceeded();
75
76 ULONG aMemoryBalloonSize;
77 HRESULT ret = mParent->machine()->COMGETTER(MemoryBalloonSize)(&aMemoryBalloonSize);
78 if (ret == S_OK)
79 mMemoryBalloonSize = aMemoryBalloonSize;
80 else
81 mMemoryBalloonSize = 0; /* Default is no ballooning */
82
83 BOOL fPageFusionEnabled;
84 ret = mParent->machine()->COMGETTER(PageFusionEnabled)(&fPageFusionEnabled);
85 if (ret == S_OK)
86 mfPageFusionEnabled = fPageFusionEnabled;
87 else
88 mfPageFusionEnabled = false; /* Default is no page fusion*/
89
90 mStatUpdateInterval = 0; /* Default is not to report guest statistics at all */
91
92 /* Clear statistics. */
93 for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
94 mCurrentGuestStat[i] = 0;
95
96#ifdef VBOX_WITH_GUEST_CONTROL
97 /* Init the context ID counter at 1000. */
98 mNextContextID = 1000;
99#endif
100
101 return S_OK;
102}
103
104/**
105 * Uninitializes the instance and sets the ready flag to FALSE.
106 * Called either from FinalRelease() or by the parent when it gets destroyed.
107 */
108void Guest::uninit()
109{
110 LogFlowThisFunc(("\n"));
111
112#ifdef VBOX_WITH_GUEST_CONTROL
113 /* Scope write lock as much as possible. */
114 {
115 /*
116 * Cleanup must be done *before* AutoUninitSpan to cancel all
117 * all outstanding waits in API functions (which hold AutoCaller
118 * ref counts).
119 */
120 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
121
122 /* Clean up callback data. */
123 CallbackMapIter it;
124 for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
125 callbackDestroy(it->first);
126
127 /* Clear process map. */
128 mGuestProcessMap.clear();
129 }
130#endif
131
132 /* Enclose the state transition Ready->InUninit->NotReady */
133 AutoUninitSpan autoUninitSpan(this);
134 if (autoUninitSpan.uninitDone())
135 return;
136
137 unconst(mParent) = NULL;
138}
139
140// IGuest properties
141/////////////////////////////////////////////////////////////////////////////
142
143STDMETHODIMP Guest::COMGETTER(OSTypeId)(BSTR *aOSTypeId)
144{
145 CheckComArgOutPointerValid(aOSTypeId);
146
147 AutoCaller autoCaller(this);
148 if (FAILED(autoCaller.rc())) return autoCaller.rc();
149
150 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
151
152 /* Redirect the call to IMachine if no additions are installed. */
153 if (mData.mAdditionsVersion.isEmpty())
154 return mParent->machine()->COMGETTER(OSTypeId)(aOSTypeId);
155
156 mData.mOSTypeId.cloneTo(aOSTypeId);
157
158 return S_OK;
159}
160
161STDMETHODIMP Guest::COMGETTER(AdditionsRunLevel) (AdditionsRunLevelType_T *aRunLevel)
162{
163 AutoCaller autoCaller(this);
164 if (FAILED(autoCaller.rc())) return autoCaller.rc();
165
166 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
167
168 *aRunLevel = mData.mAdditionsRunLevel;
169
170 return S_OK;
171}
172
173STDMETHODIMP Guest::COMGETTER(AdditionsVersion) (BSTR *aAdditionsVersion)
174{
175 CheckComArgOutPointerValid(aAdditionsVersion);
176
177 AutoCaller autoCaller(this);
178 if (FAILED(autoCaller.rc())) return autoCaller.rc();
179
180 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
181
182 HRESULT hr = S_OK;
183 if ( mData.mAdditionsVersion.isEmpty()
184 /* Only try alternative way if GA are active! */
185 && mData.mAdditionsRunLevel > AdditionsRunLevelType_None)
186 {
187 /*
188 * If we got back an empty string from GetAdditionsVersion() we either
189 * really don't have the Guest Additions version yet or the guest is running
190 * older Guest Additions (< 3.2.0) which don't provide VMMDevReq_ReportGuestInfo2,
191 * so get the version + revision from the (hopefully) provided guest properties
192 * instead.
193 */
194 Bstr addVersion;
195 LONG64 u64Timestamp;
196 Bstr flags;
197 hr = mParent->machine()->GetGuestProperty(Bstr("/VirtualBox/GuestAdd/Version").raw(),
198 addVersion.asOutParam(), &u64Timestamp, flags.asOutParam());
199 if (hr == S_OK)
200 {
201 Bstr addRevision;
202 hr = mParent->machine()->GetGuestProperty(Bstr("/VirtualBox/GuestAdd/Revision").raw(),
203 addRevision.asOutParam(), &u64Timestamp, flags.asOutParam());
204 if ( hr == S_OK
205 && !addVersion.isEmpty()
206 && !addRevision.isEmpty())
207 {
208 /* Some Guest Additions versions had interchanged version + revision values,
209 * so check if the version value at least has a dot to identify it and change
210 * both values to reflect the right content. */
211 if (!Utf8Str(addVersion).contains("."))
212 {
213 Bstr addTemp = addVersion;
214 addVersion = addRevision;
215 addRevision = addTemp;
216 }
217
218 Bstr additionsVersion = BstrFmt("%ls r%ls",
219 addVersion.raw(), addRevision.raw());
220 additionsVersion.cloneTo(aAdditionsVersion);
221 }
222 /** @todo r=bird: else: Should not return failure! */
223 }
224 else
225 {
226 /* If getting the version + revision above fails or they simply aren't there
227 * because of *really* old Guest Additions we only can report the interface
228 * version to at least have something. */
229 mData.mInterfaceVersion.cloneTo(aAdditionsVersion);
230 /** @todo r=bird: hr is still indicating failure! */
231 }
232 }
233 else
234 mData.mAdditionsVersion.cloneTo(aAdditionsVersion);
235
236 return hr;
237}
238
239STDMETHODIMP Guest::COMGETTER(Facilities)(ComSafeArrayOut(IAdditionsFacility*, aFacilities))
240{
241 CheckComArgOutPointerValid(aFacilities);
242
243 AutoCaller autoCaller(this);
244 if (FAILED(autoCaller.rc())) return autoCaller.rc();
245
246 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
247
248 SafeIfaceArray<IAdditionsFacility> fac(mData.mFacilityMap);
249 fac.detachTo(ComSafeArrayOutArg(aFacilities));
250
251 return S_OK;
252}
253
254BOOL Guest::isPageFusionEnabled()
255{
256 AutoCaller autoCaller(this);
257 if (FAILED(autoCaller.rc())) return false;
258
259 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
260
261 return mfPageFusionEnabled;
262}
263
264STDMETHODIMP Guest::COMGETTER(MemoryBalloonSize)(ULONG *aMemoryBalloonSize)
265{
266 CheckComArgOutPointerValid(aMemoryBalloonSize);
267
268 AutoCaller autoCaller(this);
269 if (FAILED(autoCaller.rc())) return autoCaller.rc();
270
271 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
272
273 *aMemoryBalloonSize = mMemoryBalloonSize;
274
275 return S_OK;
276}
277
278STDMETHODIMP Guest::COMSETTER(MemoryBalloonSize)(ULONG aMemoryBalloonSize)
279{
280 AutoCaller autoCaller(this);
281 if (FAILED(autoCaller.rc())) return autoCaller.rc();
282
283 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
284
285 /* We must be 100% sure that IMachine::COMSETTER(MemoryBalloonSize)
286 * does not call us back in any way! */
287 HRESULT ret = mParent->machine()->COMSETTER(MemoryBalloonSize)(aMemoryBalloonSize);
288 if (ret == S_OK)
289 {
290 mMemoryBalloonSize = aMemoryBalloonSize;
291 /* forward the information to the VMM device */
292 VMMDev *pVMMDev = mParent->getVMMDev();
293 /* MUST release all locks before calling VMM device as its critsect
294 * has higher lock order than anything in Main. */
295 alock.release();
296 if (pVMMDev)
297 {
298 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
299 if (pVMMDevPort)
300 pVMMDevPort->pfnSetMemoryBalloon(pVMMDevPort, aMemoryBalloonSize);
301 }
302 }
303
304 return ret;
305}
306
307STDMETHODIMP Guest::COMGETTER(StatisticsUpdateInterval)(ULONG *aUpdateInterval)
308{
309 CheckComArgOutPointerValid(aUpdateInterval);
310
311 AutoCaller autoCaller(this);
312 if (FAILED(autoCaller.rc())) return autoCaller.rc();
313
314 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
315
316 *aUpdateInterval = mStatUpdateInterval;
317 return S_OK;
318}
319
320STDMETHODIMP Guest::COMSETTER(StatisticsUpdateInterval)(ULONG aUpdateInterval)
321{
322 AutoCaller autoCaller(this);
323 if (FAILED(autoCaller.rc())) return autoCaller.rc();
324
325 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
326
327 mStatUpdateInterval = aUpdateInterval;
328 /* forward the information to the VMM device */
329 VMMDev *pVMMDev = mParent->getVMMDev();
330 /* MUST release all locks before calling VMM device as its critsect
331 * has higher lock order than anything in Main. */
332 alock.release();
333 if (pVMMDev)
334 {
335 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
336 if (pVMMDevPort)
337 pVMMDevPort->pfnSetStatisticsInterval(pVMMDevPort, aUpdateInterval);
338 }
339
340 return S_OK;
341}
342
343STDMETHODIMP Guest::InternalGetStatistics(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
344 ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared,
345 ULONG *aMemCache, ULONG *aPageTotal,
346 ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal)
347{
348 CheckComArgOutPointerValid(aCpuUser);
349 CheckComArgOutPointerValid(aCpuKernel);
350 CheckComArgOutPointerValid(aCpuIdle);
351 CheckComArgOutPointerValid(aMemTotal);
352 CheckComArgOutPointerValid(aMemFree);
353 CheckComArgOutPointerValid(aMemBalloon);
354 CheckComArgOutPointerValid(aMemShared);
355 CheckComArgOutPointerValid(aMemCache);
356 CheckComArgOutPointerValid(aPageTotal);
357 CheckComArgOutPointerValid(aMemAllocTotal);
358 CheckComArgOutPointerValid(aMemFreeTotal);
359 CheckComArgOutPointerValid(aMemBalloonTotal);
360 CheckComArgOutPointerValid(aMemSharedTotal);
361
362 AutoCaller autoCaller(this);
363 if (FAILED(autoCaller.rc())) return autoCaller.rc();
364
365 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
366
367 *aCpuUser = mCurrentGuestStat[GUESTSTATTYPE_CPUUSER];
368 *aCpuKernel = mCurrentGuestStat[GUESTSTATTYPE_CPUKERNEL];
369 *aCpuIdle = mCurrentGuestStat[GUESTSTATTYPE_CPUIDLE];
370 *aMemTotal = mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */
371 *aMemFree = mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K); /* page (4K) -> 1KB units */
372 *aMemBalloon = mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K); /* page (4K) -> 1KB units */
373 *aMemCache = mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K); /* page (4K) -> 1KB units */
374 *aPageTotal = mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */
375
376 /* MUST release all locks before calling any PGM statistics queries,
377 * as they are executed by EMT and that might deadlock us by VMM device
378 * activity which waits for the Guest object lock. */
379 alock.release();
380 Console::SafeVMPtr pVM (mParent);
381 if (pVM.isOk())
382 {
383 uint64_t uFreeTotal, uAllocTotal, uBalloonedTotal, uSharedTotal;
384 *aMemFreeTotal = 0;
385 int rc = PGMR3QueryGlobalMemoryStats(pVM.raw(), &uAllocTotal, &uFreeTotal, &uBalloonedTotal, &uSharedTotal);
386 AssertRC(rc);
387 if (rc == VINF_SUCCESS)
388 {
389 *aMemAllocTotal = (ULONG)(uAllocTotal / _1K); /* bytes -> KB */
390 *aMemFreeTotal = (ULONG)(uFreeTotal / _1K);
391 *aMemBalloonTotal = (ULONG)(uBalloonedTotal / _1K);
392 *aMemSharedTotal = (ULONG)(uSharedTotal / _1K);
393 }
394 else
395 return E_FAIL;
396
397 /* Query the missing per-VM memory statistics. */
398 *aMemShared = 0;
399 uint64_t uTotalMem, uPrivateMem, uSharedMem, uZeroMem;
400 rc = PGMR3QueryMemoryStats(pVM.raw(), &uTotalMem, &uPrivateMem, &uSharedMem, &uZeroMem);
401 if (rc == VINF_SUCCESS)
402 {
403 *aMemShared = (ULONG)(uSharedMem / _1K);
404 }
405 else
406 return E_FAIL;
407 }
408 else
409 {
410 *aMemAllocTotal = 0;
411 *aMemFreeTotal = 0;
412 *aMemBalloonTotal = 0;
413 *aMemSharedTotal = 0;
414 *aMemShared = 0;
415 return E_FAIL;
416 }
417
418 return S_OK;
419}
420
421HRESULT Guest::setStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal)
422{
423 AutoCaller autoCaller(this);
424 if (FAILED(autoCaller.rc())) return autoCaller.rc();
425
426 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
427
428 if (enmType >= GUESTSTATTYPE_MAX)
429 return E_INVALIDARG;
430
431 mCurrentGuestStat[enmType] = aVal;
432 return S_OK;
433}
434
435/**
436 * Returns the status of a specified Guest Additions facility.
437 *
438 * @return aStatus Current status of specified facility.
439 * @param aType Facility to get the status from.
440 * @param aTimestamp Timestamp of last facility status update in ms (optional).
441 */
442STDMETHODIMP Guest::GetFacilityStatus(AdditionsFacilityType_T aType, LONG64 *aTimestamp, AdditionsFacilityStatus_T *aStatus)
443{
444 AutoCaller autoCaller(this);
445 if (FAILED(autoCaller.rc())) return autoCaller.rc();
446
447 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
448
449 CheckComArgNotNull(aStatus);
450 /* Not checking for aTimestamp is intentional; it's optional. */
451
452 FacilityMapIterConst it = mData.mFacilityMap.find(aType);
453 if (it != mData.mFacilityMap.end())
454 {
455 AdditionsFacility *pFacility = it->second;
456 ComAssert(pFacility);
457 *aStatus = pFacility->getStatus();
458 if (aTimestamp)
459 *aTimestamp = pFacility->getLastUpdated();
460 }
461 else
462 {
463 /*
464 * Do not fail here -- could be that the facility never has been brought up (yet) but
465 * the host wants to have its status anyway. So just tell we don't know at this point.
466 */
467 *aStatus = AdditionsFacilityStatus_Unknown;
468 if (aTimestamp)
469 *aTimestamp = RTTimeMilliTS();
470 }
471 return S_OK;
472}
473
474STDMETHODIMP Guest::GetAdditionsStatus(AdditionsRunLevelType_T aLevel, BOOL *aActive)
475{
476 AutoCaller autoCaller(this);
477 if (FAILED(autoCaller.rc())) return autoCaller.rc();
478
479 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
480
481 HRESULT rc = S_OK;
482 switch (aLevel)
483 {
484 case AdditionsRunLevelType_System:
485 *aActive = (mData.mAdditionsRunLevel > AdditionsRunLevelType_None);
486 break;
487
488 case AdditionsRunLevelType_Userland:
489 *aActive = (mData.mAdditionsRunLevel >= AdditionsRunLevelType_Userland);
490 break;
491
492 case AdditionsRunLevelType_Desktop:
493 *aActive = (mData.mAdditionsRunLevel >= AdditionsRunLevelType_Desktop);
494 break;
495
496 default:
497 rc = setError(VBOX_E_NOT_SUPPORTED,
498 tr("Invalid status level defined: %u"), aLevel);
499 break;
500 }
501
502 return rc;
503}
504
505STDMETHODIMP Guest::SetCredentials(IN_BSTR aUserName, IN_BSTR aPassword,
506 IN_BSTR aDomain, BOOL aAllowInteractiveLogon)
507{
508 AutoCaller autoCaller(this);
509 if (FAILED(autoCaller.rc())) return autoCaller.rc();
510
511 /* forward the information to the VMM device */
512 VMMDev *pVMMDev = mParent->getVMMDev();
513 if (pVMMDev)
514 {
515 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
516 if (pVMMDevPort)
517 {
518 uint32_t u32Flags = VMMDEV_SETCREDENTIALS_GUESTLOGON;
519 if (!aAllowInteractiveLogon)
520 u32Flags = VMMDEV_SETCREDENTIALS_NOLOCALLOGON;
521
522 pVMMDevPort->pfnSetCredentials(pVMMDevPort,
523 Utf8Str(aUserName).c_str(),
524 Utf8Str(aPassword).c_str(),
525 Utf8Str(aDomain).c_str(),
526 u32Flags);
527 return S_OK;
528 }
529 }
530
531 return setError(VBOX_E_VM_ERROR,
532 tr("VMM device is not available (is the VM running?)"));
533}
534
535// public methods only for internal purposes
536/////////////////////////////////////////////////////////////////////////////
537
538/**
539 * Sets the general Guest Additions information like
540 * API (interface) version and OS type. Gets called by
541 * vmmdevUpdateGuestInfo.
542 *
543 * @param aInterfaceVersion
544 * @param aOsType
545 */
546void Guest::setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType)
547{
548 AutoCaller autoCaller(this);
549 AssertComRCReturnVoid(autoCaller.rc());
550
551 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
552
553 /*
554 * Note: The Guest Additions API (interface) version is deprecated
555 * and will not be used anymore! We might need it to at least report
556 * something as version number if *really* ancient Guest Additions are
557 * installed (without the guest version + revision properties having set).
558 */
559 mData.mInterfaceVersion = aInterfaceVersion;
560
561 /*
562 * Older Additions rely on the Additions API version whether they
563 * are assumed to be active or not. Since newer Additions do report
564 * the Additions version *before* calling this function (by calling
565 * VMMDevReportGuestInfo2, VMMDevReportGuestStatus, VMMDevReportGuestInfo,
566 * in that order) we can tell apart old and new Additions here. Old
567 * Additions never would set VMMDevReportGuestInfo2 (which set mData.mAdditionsVersion)
568 * so they just rely on the aInterfaceVersion string (which gets set by
569 * VMMDevReportGuestInfo).
570 *
571 * So only mark the Additions as being active (run level = system) when we
572 * don't have the Additions version set.
573 */
574 if (mData.mAdditionsVersion.isEmpty())
575 {
576 if (aInterfaceVersion.isEmpty())
577 mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
578 else
579 {
580 mData.mAdditionsRunLevel = AdditionsRunLevelType_System;
581
582 /*
583 * To keep it compatible with the old Guest Additions behavior we need to set the
584 * "graphics" (feature) facility to active as soon as we got the Guest Additions
585 * interface version.
586 */
587 facilityUpdate(VBoxGuestFacilityType_Graphics, VBoxGuestFacilityStatus_Active);
588 }
589 }
590
591 /*
592 * Older Additions didn't have this finer grained capability bit,
593 * so enable it by default. Newer Additions will not enable this here
594 * and use the setSupportedFeatures function instead.
595 */
596 facilityUpdate(VBoxGuestFacilityType_Graphics, facilityIsActive(VBoxGuestFacilityType_VBoxGuestDriver) ?
597 VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive);
598
599 /*
600 * Note! There is a race going on between setting mAdditionsRunLevel and
601 * mSupportsGraphics here and disabling/enabling it later according to
602 * its real status when using new(er) Guest Additions.
603 */
604 mData.mOSTypeId = Global::OSTypeId(aOsType);
605}
606
607/**
608 * Sets the Guest Additions version information details.
609 * Gets called by vmmdevUpdateGuestInfo2.
610 *
611 * @param aAdditionsVersion
612 * @param aVersionName
613 */
614void Guest::setAdditionsInfo2(Bstr aAdditionsVersion, Bstr aVersionName, Bstr aRevision)
615{
616 AutoCaller autoCaller(this);
617 AssertComRCReturnVoid(autoCaller.rc());
618
619 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
620
621 if (!aVersionName.isEmpty())
622 /*
623 * aVersionName could be "x.y.z_BETA1_FOOBAR", so append revision manually to
624 * become "x.y.z_BETA1_FOOBAR r12345".
625 */
626 mData.mAdditionsVersion = BstrFmt("%ls r%ls", aVersionName.raw(), aRevision.raw());
627 else /* aAdditionsVersion is in x.y.zr12345 format. */
628 mData.mAdditionsVersion = aAdditionsVersion;
629}
630
631bool Guest::facilityIsActive(VBoxGuestFacilityType enmFacility)
632{
633 Assert(enmFacility < INT32_MAX);
634 FacilityMapIterConst it = mData.mFacilityMap.find((AdditionsFacilityType_T)enmFacility);
635 if (it != mData.mFacilityMap.end())
636 {
637 AdditionsFacility *pFac = it->second;
638 return (pFac->getStatus() == AdditionsFacilityStatus_Active);
639 }
640 return false;
641}
642
643HRESULT Guest::facilityUpdate(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus)
644{
645 ComAssertRet(enmFacility < INT32_MAX, E_INVALIDARG);
646
647 HRESULT rc;
648 RTTIMESPEC tsNow;
649 RTTimeNow(&tsNow);
650
651 FacilityMapIter it = mData.mFacilityMap.find((AdditionsFacilityType_T)enmFacility);
652 if (it != mData.mFacilityMap.end())
653 {
654 AdditionsFacility *pFac = it->second;
655 rc = pFac->update((AdditionsFacilityStatus_T)enmStatus, tsNow);
656 }
657 else
658 {
659 ComObjPtr<AdditionsFacility> pFacility;
660 pFacility.createObject();
661 ComAssert(!pFacility.isNull());
662 rc = pFacility->init(this,
663 (AdditionsFacilityType_T)enmFacility,
664 (AdditionsFacilityStatus_T)enmStatus);
665 if (SUCCEEDED(rc))
666 mData.mFacilityMap.insert(std::make_pair((AdditionsFacilityType_T)enmFacility, pFacility));
667 }
668
669 LogFlowFunc(("Returned with rc=%Rrc\n"));
670 return rc;
671}
672
673/**
674 * Sets the status of a certain Guest Additions facility.
675 * Gets called by vmmdevUpdateGuestStatus.
676 *
677 * @param enmFacility Facility to set the status for.
678 * @param enmStatus Actual status to set.
679 * @param aFlags
680 */
681void Guest::setAdditionsStatus(VBoxGuestFacilityType enmFacility, VBoxGuestFacilityStatus enmStatus, ULONG aFlags)
682{
683 AutoCaller autoCaller(this);
684 AssertComRCReturnVoid(autoCaller.rc());
685
686 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
687
688 /*
689 * Set overall additions run level.
690 */
691
692 /* First check for disabled status. */
693 uint32_t uCurFacility = enmFacility + (enmStatus == VBoxGuestFacilityStatus_Active ? 0 : -1);
694 if ( enmFacility < VBoxGuestFacilityType_VBoxGuestDriver
695 || ( enmFacility == VBoxGuestFacilityType_All
696 && enmStatus == VBoxGuestFacilityStatus_Inactive)
697 )
698 {
699 mData.mAdditionsRunLevel = AdditionsRunLevelType_None;
700 }
701 else if (uCurFacility >= VBoxGuestFacilityType_VBoxTrayClient)
702 {
703 mData.mAdditionsRunLevel = AdditionsRunLevelType_Desktop;
704 }
705 else if (uCurFacility >= VBoxGuestFacilityType_VBoxService)
706 {
707 mData.mAdditionsRunLevel = AdditionsRunLevelType_Userland;
708 }
709 else if (uCurFacility >= VBoxGuestFacilityType_VBoxGuestDriver)
710 {
711 mData.mAdditionsRunLevel = AdditionsRunLevelType_System;
712 }
713 else /* Should never happen! */
714 AssertMsgFailed(("Invalid facility status/run level detected! uCurFacility=%d\n", uCurFacility));
715
716 /*
717 * Set a specific facility status.
718 */
719 if (enmFacility > VBoxGuestFacilityType_Unknown)
720 {
721 if (enmFacility == VBoxGuestFacilityType_All)
722 {
723 FacilityMapIter it = mData.mFacilityMap.begin();
724 while (it != mData.mFacilityMap.end())
725 {
726 facilityUpdate((VBoxGuestFacilityType)it->first, enmStatus);
727 it++;
728 }
729 }
730 else /* Update one facility only. */
731 facilityUpdate(enmFacility, enmStatus);
732 }
733}
734
735/**
736 * Sets the supported features (and whether they are active or not).
737 *
738 * @param fCaps Guest capability bit mask (VMMDEV_GUEST_SUPPORTS_XXX).
739 */
740void Guest::setSupportedFeatures(uint32_t aCaps)
741{
742 AutoCaller autoCaller(this);
743 AssertComRCReturnVoid(autoCaller.rc());
744
745 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
746
747 facilityUpdate(VBoxGuestFacilityType_Seamless, aCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS ?
748 VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive);
749 /** @todo Add VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING */
750 facilityUpdate(VBoxGuestFacilityType_Graphics, aCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ?
751 VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive);
752}
753/* 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