1
/* $Id: HostImpl.cpp $ */
3
* VirtualBox COM class implementation: Host
7
* Copyright (C) 2006-2011 Oracle Corporation
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.
18
#define __STDC_LIMIT_MACROS
19
#define __STDC_CONSTANT_MACROS
21
// for some reason Windows burns in sdk\...\winsock.h if this isn't included first
22
#include "VBox/com/ptr.h"
27
# include "HostUSBDeviceImpl.h"
28
# include "USBDeviceFilterImpl.h"
29
# include "USBProxyService.h"
30
#endif // VBOX_WITH_USB
32
#include "HostNetworkInterfaceImpl.h"
33
#include "MachineImpl.h"
34
#include "AutoCaller.h"
36
#include "Performance.h"
38
#include "MediumImpl.h"
39
#include "HostPower.h"
41
#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
42
# include <HostHardwareLinux.h>
45
#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
49
#ifdef VBOX_WITH_RESOURCE_USAGE_API
50
# include "PerformanceImpl.h"
51
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
53
#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
54
# include <VBox/VBoxNetCfg-win.h>
55
#endif /* #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
58
# include <sys/ioctl.h>
61
# include <net/if_arp.h>
62
#endif /* RT_OS_LINUX */
71
# include <libdevinfo.h>
72
# include <sys/mkdev.h>
73
# include <sys/scsi/generic/inquiry.h>
75
# include <sys/socket.h>
76
# include <sys/sockio.h>
77
# include <net/if_arp.h>
79
# include <sys/types.h>
80
# include <sys/stat.h>
81
# include <sys/cdio.h>
82
# include <sys/dkio.h>
83
# include <sys/mnttab.h>
84
# include <sys/mntent.h>
85
/* Dynamic loading of libhal on Solaris hosts */
86
# ifdef VBOX_USE_LIBHAL
87
# include "vbox-libhal.h"
88
extern "C" char *getfullrawname(char *);
90
# include "solaris/DynLoadLibSolaris.h"
93
* Solaris DVD drive list as returned by getDVDInfoFromDevTree().
95
typedef struct SOLARISDVD
97
struct SOLARISDVD *pNext;
98
char szDescription[512];
99
char szRawDiskPath[PATH_MAX];
101
/** Pointer to a Solaris DVD descriptor. */
102
typedef SOLARISDVD *PSOLARISDVD;
104
#endif /* RT_OS_SOLARIS */
108
# include <windows.h>
109
# include <shellapi.h>
111
# include <guiddef.h>
112
# include <devguid.h>
113
# include <objbase.h>
114
//# include <setupapi.h>
116
# include <cfgmgr32.h>
118
#endif /* RT_OS_WINDOWS */
121
# include "darwin/iokit.h"
124
#ifdef VBOX_WITH_CROGL
125
extern bool is3DAccelerationSupported();
126
#endif /* VBOX_WITH_CROGL */
128
#include <iprt/asm-amd64-x86.h>
129
#include <iprt/string.h>
131
#include <iprt/time.h>
132
#include <iprt/param.h>
133
#include <iprt/env.h>
134
#include <iprt/mem.h>
135
#include <iprt/system.h>
137
# include <iprt/path.h>
138
# include <iprt/ctype.h>
140
#ifdef VBOX_WITH_HOSTNETIF_API
144
/* XXX Solaris: definitions in /usr/include/sys/regset.h clash with hwacc_svm.h */
152
#include <VBox/usb.h>
153
#include <VBox/vmm/hwacc_svm.h>
154
#include <VBox/err.h>
155
#include <VBox/settings.h>
156
#include <VBox/sup.h>
157
#include <iprt/x86.h>
159
#include "VBox/com/MultiResult.h"
165
////////////////////////////////////////////////////////////////////////////////
167
// Host private data definition
169
////////////////////////////////////////////////////////////////////////////////
176
usbListsLock(LOCKCLASS_USBLIST),
178
drivesLock(LOCKCLASS_LISTOFMEDIA),
179
fDVDDrivesListBuilt(false),
180
fFloppyDrivesListBuilt(false)
186
WriteLockHandle usbListsLock; // protects the below two lists
188
USBDeviceFilterList llChildren; // all USB device filters
189
USBDeviceFilterList llUSBDeviceFilters; // USB device filters in use by the USB proxy service
191
/** Pointer to the USBProxyService object. */
192
USBProxyService *pUSBProxyService;
193
#endif /* VBOX_WITH_USB */
195
// list of host drives; lazily created by getDVDDrives() and getFloppyDrives()
196
WriteLockHandle drivesLock; // protects the below two lists and the bools
197
MediaList llDVDDrives,
199
bool fDVDDrivesListBuilt,
200
fFloppyDrivesListBuilt;
202
#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
203
/** Object with information about host drives */
204
VBoxMainDriveInfo hostDrives;
206
/* Features that can be queried with GetProcessorFeature */
210
fNestedPagingSupported;
212
/* 3D hardware acceleration supported? */
213
BOOL f3DAccelerationSupported;
215
HostPowerService *pHostPowerService;
219
////////////////////////////////////////////////////////////////////////////////
221
// Constructor / destructor
223
////////////////////////////////////////////////////////////////////////////////
225
HRESULT Host::FinalConstruct()
227
return BaseFinalConstruct();
230
void Host::FinalRelease()
237
* Initializes the host object.
239
* @param aParent VirtualBox parent object.
241
HRESULT Host::init(VirtualBox *aParent)
244
LogFlowThisFunc(("aParent=%p\n", aParent));
246
/* Enclose the state transition NotReady->InInit->Ready */
247
AutoInitSpan autoInitSpan(this);
248
AssertReturn(autoInitSpan.isOk(), E_FAIL);
252
m->pParent = aParent;
256
* Create and initialize the USB Proxy Service.
258
# if defined (RT_OS_DARWIN)
259
m->pUSBProxyService = new USBProxyServiceDarwin(this);
260
# elif defined (RT_OS_LINUX)
261
m->pUSBProxyService = new USBProxyServiceLinux(this);
262
# elif defined (RT_OS_OS2)
263
m->pUSBProxyService = new USBProxyServiceOs2(this);
264
# elif defined (RT_OS_SOLARIS)
265
m->pUSBProxyService = new USBProxyServiceSolaris(this);
266
# elif defined (RT_OS_WINDOWS)
267
m->pUSBProxyService = new USBProxyServiceWindows(this);
268
# elif defined (RT_OS_FREEBSD)
269
m->pUSBProxyService = new USBProxyServiceFreeBSD(this);
271
m->pUSBProxyService = new USBProxyService(this);
273
hrc = m->pUSBProxyService->init();
274
AssertComRCReturn(hrc, hrc);
275
#endif /* VBOX_WITH_USB */
277
#ifdef VBOX_WITH_RESOURCE_USAGE_API
278
registerMetrics(aParent->performanceCollector());
279
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
281
#if defined (RT_OS_WINDOWS)
282
m->pHostPowerService = new HostPowerServiceWin(m->pParent);
283
#elif defined (RT_OS_DARWIN)
284
m->pHostPowerService = new HostPowerServiceDarwin(m->pParent);
286
m->pHostPowerService = new HostPowerService(m->pParent);
289
/* Cache the features reported by GetProcessorFeature. */
290
m->fVTSupported = false;
291
m->fLongModeSupported = false;
292
m->fPAESupported = false;
293
m->fNestedPagingSupported = false;
297
uint32_t u32FeaturesECX;
299
uint32_t u32FeaturesEDX;
300
uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX, u32AMDFeatureEDX, u32AMDFeatureECX;
302
ASMCpuId(0, &u32Dummy, &u32VendorEBX, &u32VendorECX, &u32VendorEDX);
303
ASMCpuId(1, &u32Dummy, &u32Dummy, &u32FeaturesECX, &u32FeaturesEDX);
304
/* Query AMD features. */
305
ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &u32AMDFeatureECX, &u32AMDFeatureEDX);
307
m->fLongModeSupported = !!(u32AMDFeatureEDX & X86_CPUID_AMD_FEATURE_EDX_LONG_MODE);
308
m->fPAESupported = !!(u32FeaturesEDX & X86_CPUID_FEATURE_EDX_PAE);
310
if ( u32VendorEBX == X86_CPUID_VENDOR_INTEL_EBX
311
&& u32VendorECX == X86_CPUID_VENDOR_INTEL_ECX
312
&& u32VendorEDX == X86_CPUID_VENDOR_INTEL_EDX
315
if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
316
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
317
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
320
int rc = SUPR3QueryVTxSupported();
322
m->fVTSupported = true;
326
if ( u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX
327
&& u32VendorECX == X86_CPUID_VENDOR_AMD_ECX
328
&& u32VendorEDX == X86_CPUID_VENDOR_AMD_EDX
331
if ( (u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
332
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
333
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
336
uint32_t u32SVMFeatureEDX;
338
m->fVTSupported = true;
340
/* Query AMD features. */
341
ASMCpuId(0x8000000A, &u32Dummy, &u32Dummy, &u32Dummy, &u32SVMFeatureEDX);
342
if (u32SVMFeatureEDX & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
343
m->fNestedPagingSupported = true;
348
#if 0 /* needs testing */
351
uint32_t u32Caps = 0;
353
int rc = SUPR3QueryVTCaps(&u32Caps);
356
if (u32Caps & SUPVTCAPS_NESTED_PAGING)
357
m->fNestedPagingSupported = true;
359
/* else @todo; report BIOS trouble in some way. */
363
/* Test for 3D hardware acceleration support */
364
m->f3DAccelerationSupported = false;
366
#ifdef VBOX_WITH_CROGL
367
m->f3DAccelerationSupported = is3DAccelerationSupported();
368
#endif /* VBOX_WITH_CROGL */
370
#if defined (RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
371
/* Extract the list of configured host-only interfaces */
372
std::set<Utf8Str> aConfiguredNames;
373
SafeArray<BSTR> aGlobalExtraDataKeys;
374
hrc = aParent->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys));
375
AssertMsg(SUCCEEDED(hrc), ("VirtualBox::GetExtraDataKeys failed with %Rhrc\n", hrc));
376
for (size_t i = 0; i < aGlobalExtraDataKeys.size(); ++i)
378
Utf8Str strKey = aGlobalExtraDataKeys[i];
380
if (!strKey.startsWith("HostOnly/vboxnet"))
383
size_t pos = strKey.find("/", sizeof("HostOnly/vboxnet"));
384
if (pos != Utf8Str::npos)
385
aConfiguredNames.insert(strKey.substr(sizeof("HostOnly"),
386
pos - sizeof("HostOnly")));
389
for (std::set<Utf8Str>::const_iterator it = aConfiguredNames.begin();
390
it != aConfiguredNames.end();
393
ComPtr<IHostNetworkInterface> hif;
394
ComPtr<IProgress> progress;
396
int r = NetIfCreateHostOnlyNetworkInterface(m->pParent,
398
progress.asOutParam(),
404
#endif /* defined (RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) */
406
/* Confirm a successful initialization */
407
autoInitSpan.setSucceeded();
413
* Uninitializes the host object and sets the ready flag to FALSE.
414
* Called either from FinalRelease() or by the parent when it gets destroyed.
418
LogFlowThisFunc(("\n"));
420
/* Enclose the state transition Ready->InUninit->NotReady */
421
AutoUninitSpan autoUninitSpan(this);
422
if (autoUninitSpan.uninitDone())
425
#ifdef VBOX_WITH_RESOURCE_USAGE_API
426
unregisterMetrics (m->pParent->performanceCollector());
427
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
430
/* wait for USB proxy service to terminate before we uninit all USB
432
LogFlowThisFunc(("Stopping USB proxy service...\n"));
433
delete m->pUSBProxyService;
434
m->pUSBProxyService = NULL;
435
LogFlowThisFunc(("Done stopping USB proxy service.\n"));
438
delete m->pHostPowerService;
441
/* uninit all USB device filters still referenced by clients
442
* Note! HostUSBDeviceFilter::uninit() will modify llChildren. */
443
while (!m->llChildren.empty())
445
ComObjPtr<HostUSBDeviceFilter> &pChild = m->llChildren.front();
449
m->llUSBDeviceFilters.clear();
456
////////////////////////////////////////////////////////////////////////////////
458
// ISnapshot public methods
460
////////////////////////////////////////////////////////////////////////////////
463
* Returns a list of host DVD drives.
465
* @returns COM status code
466
* @param drives address of result pointer
468
STDMETHODIMP Host::COMGETTER(DVDDrives)(ComSafeArrayOut(IMedium *, aDrives))
470
CheckComArgOutSafeArrayPointerValid(aDrives);
472
AutoCaller autoCaller(this);
473
if (FAILED(autoCaller.rc())) return autoCaller.rc();
475
AutoWriteLock alock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
478
HRESULT rc = getDrives(DeviceType_DVD, true /* fRefresh */, pList);
481
SafeIfaceArray<IMedium> array(*pList);
482
array.detachTo(ComSafeArrayOutArg(aDrives));
489
* Returns a list of host floppy drives.
491
* @returns COM status code
492
* @param drives address of result pointer
494
STDMETHODIMP Host::COMGETTER(FloppyDrives)(ComSafeArrayOut(IMedium *, aDrives))
496
CheckComArgOutPointerValid(aDrives);
498
AutoCaller autoCaller(this);
499
if (FAILED(autoCaller.rc())) return autoCaller.rc();
501
AutoWriteLock alock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
504
HRESULT rc = getDrives(DeviceType_Floppy, true /* fRefresh */, pList);
507
SafeIfaceArray<IMedium> collection(*pList);
508
collection.detachTo(ComSafeArrayOutArg(aDrives));
515
#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
516
# define VBOX_APP_NAME L"VirtualBox"
518
static int vboxNetWinAddComponent(std::list< ComObjPtr<HostNetworkInterface> > *pPist,
519
INetCfgComponent *pncc)
524
int rc = VERR_GENERAL_FAILURE;
526
hr = pncc->GetDisplayName( &lpszName );
530
Bstr name((CBSTR)lpszName);
532
hr = pncc->GetInstanceGuid(&IfGuid);
536
/* create a new object and add it to the list */
537
ComObjPtr<HostNetworkInterface> iface;
538
iface.createObject();
539
/* remove the curly bracket at the end */
540
if (SUCCEEDED(iface->init (name, Guid (IfGuid), HostNetworkInterfaceType_Bridged)))
542
// iface->setVirtualBox(m->pParent);
543
pPist->push_back(iface);
551
CoTaskMemFree(lpszName);
556
#endif /* defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
559
* Returns a list of host network interfaces.
561
* @returns COM status code
562
* @param drives address of result pointer
564
STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInterface*, aNetworkInterfaces))
566
#if defined(RT_OS_WINDOWS) || defined(VBOX_WITH_NETFLT) /*|| defined(RT_OS_OS2)*/
567
if (ComSafeArrayOutIsNull(aNetworkInterfaces))
570
AutoCaller autoCaller(this);
571
if (FAILED(autoCaller.rc())) return autoCaller.rc();
573
std::list<ComObjPtr<HostNetworkInterface> > list;
575
# ifdef VBOX_WITH_HOSTNETIF_API
576
int rc = NetIfList(list);
579
Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
583
# if defined(RT_OS_DARWIN)
584
PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
587
ComObjPtr<HostNetworkInterface> IfObj;
588
IfObj.createObject();
589
if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), Guid(pEtherNICs->Uuid), HostNetworkInterfaceType_Bridged)))
590
list.push_back(IfObj);
592
/* next, free current */
593
void *pvFree = pEtherNICs;
594
pEtherNICs = pEtherNICs->pNext;
598
# elif defined RT_OS_WINDOWS
599
# ifndef VBOX_WITH_NETFLT
601
# else /* # if defined VBOX_WITH_NETFLT */
603
INetCfgComponent *pMpNcc;
604
INetCfgComponent *pTcpIpNcc;
607
IEnumNetCfgBindingPath *pEnumBp;
608
INetCfgBindingPath *pBp;
609
IEnumNetCfgBindingInterface *pEnumBi;
610
INetCfgBindingInterface *pBi;
612
/* we are using the INetCfg API for getting the list of miniports */
613
hr = VBoxNetCfgWinQueryINetCfg( FALSE,
620
# ifdef VBOX_NETFLT_ONDEMAND_BIND
621
/* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
622
hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
624
/* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
625
hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
626
# ifndef VBOX_WITH_HARDENING
629
/* TODO: try to install the netflt from here */
637
hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
641
hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
642
Assert(hr == S_OK || hr == S_FALSE);
645
/* S_OK == enabled, S_FALSE == disabled */
646
if (pBp->IsEnabled() == S_OK)
648
hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
652
hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
656
hr = pBi->GetLowerComponent( &pMpNcc );
660
ULONG uComponentStatus;
661
hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
665
if (uComponentStatus == 0)
667
vboxNetWinAddComponent(&list, pMpNcc);
670
VBoxNetCfgWinReleaseRef( pMpNcc );
672
VBoxNetCfgWinReleaseRef(pBi);
674
hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
676
VBoxNetCfgWinReleaseRef(pEnumBi);
679
VBoxNetCfgWinReleaseRef(pBp);
681
hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
683
VBoxNetCfgWinReleaseRef(pEnumBp);
685
VBoxNetCfgWinReleaseRef(pTcpIpNcc);
689
LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
692
VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
694
# endif /* # if defined VBOX_WITH_NETFLT */
697
# elif defined RT_OS_LINUX
698
int sock = socket(AF_INET, SOCK_DGRAM, 0);
702
struct ifconf ifConf;
703
ifConf.ifc_len = sizeof(pBuffer);
704
ifConf.ifc_buf = pBuffer;
705
if (ioctl(sock, SIOCGIFCONF, &ifConf) >= 0)
707
for (struct ifreq *pReq = ifConf.ifc_req; (char*)pReq < pBuffer + ifConf.ifc_len; pReq++)
709
if (ioctl(sock, SIOCGIFHWADDR, pReq) >= 0)
711
if (pReq->ifr_hwaddr.sa_family == ARPHRD_ETHER)
714
Assert(sizeof(uuid) <= sizeof(*pReq));
715
memcpy(&uuid, pReq, sizeof(uuid));
717
ComObjPtr<HostNetworkInterface> IfObj;
718
IfObj.createObject();
719
if (SUCCEEDED(IfObj->init(Bstr(pReq->ifr_name), Guid(uuid), HostNetworkInterfaceType_Bridged)))
720
list.push_back(IfObj);
727
# endif /* RT_OS_LINUX */
730
std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
731
for (it = list.begin(); it != list.end(); ++it)
733
(*it)->setVirtualBox(m->pParent);
736
SafeIfaceArray<IHostNetworkInterface> networkInterfaces (list);
737
networkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
742
/* Not implemented / supported on this platform. */
743
ReturnComNotImplemented();
747
STDMETHODIMP Host::COMGETTER(USBDevices)(ComSafeArrayOut(IHostUSBDevice*, aUSBDevices))
750
CheckComArgOutSafeArrayPointerValid(aUSBDevices);
752
AutoCaller autoCaller(this);
753
if (FAILED(autoCaller.rc())) return autoCaller.rc();
755
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
757
HRESULT rc = checkUSBProxyService();
758
if (FAILED(rc)) return rc;
760
return m->pUSBProxyService->getDeviceCollection(ComSafeArrayOutArg(aUSBDevices));
763
/* Note: The GUI depends on this method returning E_NOTIMPL with no
764
* extended error info to indicate that USB is simply not available
765
* (w/o treating it as a failure), for example, as in OSE. */
767
# ifndef RT_OS_WINDOWS
768
NOREF(aUSBDevicesSize);
770
ReturnComNotImplemented();
774
STDMETHODIMP Host::COMGETTER(USBDeviceFilters)(ComSafeArrayOut(IHostUSBDeviceFilter*, aUSBDeviceFilters))
777
CheckComArgOutSafeArrayPointerValid(aUSBDeviceFilters);
779
AutoCaller autoCaller(this);
780
if (FAILED(autoCaller.rc())) return autoCaller.rc();
782
AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
784
HRESULT rc = checkUSBProxyService();
785
if (FAILED(rc)) return rc;
787
SafeIfaceArray<IHostUSBDeviceFilter> collection(m->llUSBDeviceFilters);
788
collection.detachTo(ComSafeArrayOutArg(aUSBDeviceFilters));
792
/* Note: The GUI depends on this method returning E_NOTIMPL with no
793
* extended error info to indicate that USB is simply not available
794
* (w/o treating it as a failure), for example, as in OSE. */
795
NOREF(aUSBDeviceFilters);
796
# ifndef RT_OS_WINDOWS
797
NOREF(aUSBDeviceFiltersSize);
799
ReturnComNotImplemented();
804
* Returns the number of installed logical processors
806
* @returns COM status code
807
* @param count address of result variable
809
STDMETHODIMP Host::COMGETTER(ProcessorCount)(ULONG *aCount)
811
CheckComArgOutPointerValid(aCount);
812
// no locking required
814
*aCount = RTMpGetPresentCount();
819
* Returns the number of online logical processors
821
* @returns COM status code
822
* @param count address of result variable
824
STDMETHODIMP Host::COMGETTER(ProcessorOnlineCount)(ULONG *aCount)
826
CheckComArgOutPointerValid(aCount);
827
// no locking required
829
*aCount = RTMpGetOnlineCount();
834
* Returns the number of installed physical processor cores.
836
* @returns COM status code
837
* @param count address of result variable
839
STDMETHODIMP Host::COMGETTER(ProcessorCoreCount)(ULONG *aCount)
841
CheckComArgOutPointerValid(aCount);
842
// no locking required
848
* Returns the (approximate) maximum speed of the given host CPU in MHz
850
* @returns COM status code
851
* @param cpu id to get info for.
852
* @param speed address of result variable, speed is 0 if unknown or aCpuId is invalid.
854
STDMETHODIMP Host::GetProcessorSpeed(ULONG aCpuId, ULONG *aSpeed)
856
CheckComArgOutPointerValid(aSpeed);
857
// no locking required
859
*aSpeed = RTMpGetMaxFrequency(aCpuId);
864
* Returns a description string for the host CPU
866
* @returns COM status code
867
* @param cpu id to get info for.
868
* @param description address of result variable, empty string if not known or aCpuId is invalid.
870
STDMETHODIMP Host::GetProcessorDescription(ULONG aCpuId, BSTR *aDescription)
872
CheckComArgOutPointerValid(aDescription);
873
// no locking required
876
int vrc = RTMpGetDescription(aCpuId, szCPUModel, sizeof(szCPUModel));
878
return E_FAIL; /** @todo error reporting? */
879
Bstr (szCPUModel).cloneTo(aDescription);
884
* Returns whether a host processor feature is supported or not
886
* @returns COM status code
887
* @param Feature to query.
888
* @param address of supported bool result variable
890
STDMETHODIMP Host::GetProcessorFeature(ProcessorFeature_T aFeature, BOOL *aSupported)
892
CheckComArgOutPointerValid(aSupported);
893
AutoCaller autoCaller(this);
894
if (FAILED(autoCaller.rc())) return autoCaller.rc();
896
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
900
case ProcessorFeature_HWVirtEx:
901
*aSupported = m->fVTSupported;
904
case ProcessorFeature_PAE:
905
*aSupported = m->fPAESupported;
908
case ProcessorFeature_LongMode:
909
*aSupported = m->fLongModeSupported;
912
case ProcessorFeature_NestedPaging:
913
*aSupported = m->fNestedPagingSupported;
917
ReturnComNotImplemented();
923
* Returns the specific CPUID leaf.
925
* @returns COM status code
926
* @param aCpuId The CPU number. Mostly ignored.
927
* @param aLeaf The leaf number.
928
* @param aSubLeaf The sub-leaf number.
929
* @param aValEAX Where to return EAX.
930
* @param aValEBX Where to return EBX.
931
* @param aValECX Where to return ECX.
932
* @param aValEDX Where to return EDX.
934
STDMETHODIMP Host::GetProcessorCPUIDLeaf(ULONG aCpuId, ULONG aLeaf, ULONG aSubLeaf,
935
ULONG *aValEAX, ULONG *aValEBX, ULONG *aValECX, ULONG *aValEDX)
937
CheckComArgOutPointerValid(aValEAX);
938
CheckComArgOutPointerValid(aValEBX);
939
CheckComArgOutPointerValid(aValECX);
940
CheckComArgOutPointerValid(aValEDX);
941
// no locking required
943
/* Check that the CPU is online. */
944
/** @todo later use RTMpOnSpecific. */
945
if (!RTMpIsCpuOnline(aCpuId))
946
return RTMpIsCpuPresent(aCpuId)
947
? setError(E_FAIL, tr("CPU no.%u is not present"), aCpuId)
948
: setError(E_FAIL, tr("CPU no.%u is not online"), aCpuId);
950
uint32_t uEAX, uEBX, uECX, uEDX;
951
ASMCpuId_Idx_ECX(aLeaf, aSubLeaf, &uEAX, &uEBX, &uECX, &uEDX);
961
* Returns the amount of installed system memory in megabytes
963
* @returns COM status code
964
* @param size address of result variable
966
STDMETHODIMP Host::COMGETTER(MemorySize)(ULONG *aSize)
968
CheckComArgOutPointerValid(aSize);
969
// no locking required
971
/* @todo This is an ugly hack. There must be a function in IPRT for that. */
972
pm::CollectorHAL *hal = pm::createHAL();
976
int rc = hal->getHostMemoryUsage(aSize, &tmp, &tmp);
983
* Returns the current system memory free space in megabytes
985
* @returns COM status code
986
* @param available address of result variable
988
STDMETHODIMP Host::COMGETTER(MemoryAvailable)(ULONG *aAvailable)
990
CheckComArgOutPointerValid(aAvailable);
991
// no locking required
993
/* @todo This is an ugly hack. There must be a function in IPRT for that. */
994
pm::CollectorHAL *hal = pm::createHAL();
998
int rc = hal->getHostMemoryUsage(&tmp, &tmp, aAvailable);
1005
* Returns the name string of the host operating system
1007
* @returns COM status code
1008
* @param os address of result variable
1010
STDMETHODIMP Host::COMGETTER(OperatingSystem)(BSTR *aOs)
1012
CheckComArgOutPointerValid(aOs);
1013
// no locking required
1016
int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szOSName, sizeof(szOSName));
1017
if (RT_FAILURE(vrc))
1018
return E_FAIL; /** @todo error reporting? */
1019
Bstr (szOSName).cloneTo(aOs);
1024
* Returns the version string of the host operating system
1026
* @returns COM status code
1027
* @param os address of result variable
1029
STDMETHODIMP Host::COMGETTER(OSVersion)(BSTR *aVersion)
1031
CheckComArgOutPointerValid(aVersion);
1032
// no locking required
1034
/* Get the OS release. Reserve some buffer space for the service pack. */
1035
char szOSRelease[128];
1036
int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szOSRelease, sizeof(szOSRelease) - 32);
1037
if (RT_FAILURE(vrc))
1038
return E_FAIL; /** @todo error reporting? */
1040
/* Append the service pack if present. */
1041
char szOSServicePack[80];
1042
vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szOSServicePack, sizeof(szOSServicePack));
1043
if (RT_FAILURE(vrc))
1045
if (vrc != VERR_NOT_SUPPORTED)
1046
return E_FAIL; /** @todo error reporting? */
1047
szOSServicePack[0] = '\0';
1049
if (szOSServicePack[0] != '\0')
1051
char *psz = strchr(szOSRelease, '\0');
1052
RTStrPrintf(psz, &szOSRelease[sizeof(szOSRelease)] - psz, "sp%s", szOSServicePack);
1055
Bstr(szOSRelease).cloneTo(aVersion);
1060
* Returns the current host time in milliseconds since 1970-01-01 UTC.
1062
* @returns COM status code
1063
* @param time address of result variable
1065
STDMETHODIMP Host::COMGETTER(UTCTime)(LONG64 *aUTCTime)
1067
CheckComArgOutPointerValid(aUTCTime);
1068
// no locking required
1071
*aUTCTime = RTTimeSpecGetMilli(RTTimeNow(&now));
1076
STDMETHODIMP Host::COMGETTER(Acceleration3DAvailable)(BOOL *aSupported)
1078
CheckComArgOutPointerValid(aSupported);
1079
AutoCaller autoCaller(this);
1080
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1082
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1084
*aSupported = m->f3DAccelerationSupported;
1089
STDMETHODIMP Host::CreateHostOnlyNetworkInterface(IHostNetworkInterface **aHostNetworkInterface,
1090
IProgress **aProgress)
1092
CheckComArgOutPointerValid(aHostNetworkInterface);
1093
CheckComArgNotNull(*aHostNetworkInterface);
1094
CheckComArgOutPointerValid(aProgress);
1096
AutoCaller autoCaller(this);
1097
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1099
#ifdef VBOX_WITH_HOSTNETIF_API
1100
/* No need to lock anything. If there ever will - watch out, the function
1101
* called below grabs the VirtualBox lock. */
1103
int r = NetIfCreateHostOnlyNetworkInterface(m->pParent, aHostNetworkInterface, aProgress);
1106
#if !defined(RT_OS_WINDOWS)
1107
Bstr tmpAddr, tmpMask, tmpName;
1109
hrc = (*aHostNetworkInterface)->COMGETTER(Name)(tmpName.asOutParam());
1110
ComAssertComRCRet(hrc, hrc);
1111
hrc = (*aHostNetworkInterface)->COMGETTER(IPAddress)(tmpAddr.asOutParam());
1112
ComAssertComRCRet(hrc, hrc);
1113
hrc = (*aHostNetworkInterface)->COMGETTER(NetworkMask)(tmpMask.asOutParam());
1114
ComAssertComRCRet(hrc, hrc);
1116
* We need to write the default IP address and mask to extra data now,
1117
* so the interface gets re-created after vboxnetadp.ko reload.
1118
* Note that we avoid calling EnableStaticIpConfig since it would
1119
* change the address on host's interface as well and we want to
1120
* postpone the change until VM actually starts.
1122
hrc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress",
1123
tmpName.raw()).raw(),
1125
ComAssertComRCRet(hrc, hrc);
1127
hrc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask",
1128
tmpName.raw()).raw(),
1130
ComAssertComRCRet(hrc, hrc);
1135
return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1141
STDMETHODIMP Host::RemoveHostOnlyNetworkInterface(IN_BSTR aId,
1142
IProgress **aProgress)
1144
CheckComArgOutPointerValid(aProgress);
1146
AutoCaller autoCaller(this);
1147
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1149
#ifdef VBOX_WITH_HOSTNETIF_API
1150
/* No need to lock anything, the code below does not touch the state
1151
* of the host object. If that ever changes then check for lock order
1152
* violations with the called functions. */
1157
/* first check whether an interface with the given name already exists */
1159
ComPtr<IHostNetworkInterface> iface;
1160
if (FAILED(FindHostNetworkInterfaceById(aId,
1161
iface.asOutParam())))
1162
return setError(VBOX_E_OBJECT_NOT_FOUND,
1163
tr("Host network interface with UUID {%RTuuid} does not exist"),
1165
rc = iface->COMGETTER(Name)(name.asOutParam());
1166
ComAssertComRCRet(rc, rc);
1169
int r = NetIfRemoveHostOnlyNetworkInterface(m->pParent, Guid(aId).ref(), aProgress);
1172
/* Drop configuration parameters for removed interface */
1173
rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", name.raw()).raw(), NULL);
1174
rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", name.raw()).raw(), NULL);
1175
rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", name.raw()).raw(), NULL);
1176
rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPV6NetMask", name.raw()).raw(), NULL);
1181
return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1187
STDMETHODIMP Host::CreateUSBDeviceFilter(IN_BSTR aName,
1188
IHostUSBDeviceFilter **aFilter)
1190
#ifdef VBOX_WITH_USB
1191
CheckComArgStrNotEmptyOrNull(aName);
1192
CheckComArgOutPointerValid(aFilter);
1194
AutoCaller autoCaller(this);
1195
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1197
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1199
ComObjPtr<HostUSBDeviceFilter> filter;
1200
filter.createObject();
1201
HRESULT rc = filter->init(this, aName);
1202
ComAssertComRCRet(rc, rc);
1203
rc = filter.queryInterfaceTo(aFilter);
1204
AssertComRCReturn(rc, rc);
1207
/* Note: The GUI depends on this method returning E_NOTIMPL with no
1208
* extended error info to indicate that USB is simply not available
1209
* (w/o treating it as a failure), for example, as in OSE. */
1212
ReturnComNotImplemented();
1216
STDMETHODIMP Host::InsertUSBDeviceFilter(ULONG aPosition,
1217
IHostUSBDeviceFilter *aFilter)
1219
#ifdef VBOX_WITH_USB
1220
CheckComArgNotNull(aFilter);
1222
/* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1223
AutoCaller autoCaller(this);
1224
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1226
AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1229
MultiResult rc = checkUSBProxyService();
1230
if (FAILED(rc)) return rc;
1232
ComObjPtr<HostUSBDeviceFilter> pFilter;
1233
for (USBDeviceFilterList::iterator it = m->llChildren.begin();
1234
it != m->llChildren.end();
1243
if (pFilter.isNull())
1244
return setError(VBOX_E_INVALID_OBJECT_STATE,
1245
tr("The given USB device filter is not created within this VirtualBox instance"));
1247
if (pFilter->mInList)
1248
return setError(E_INVALIDARG,
1249
tr("The given USB device filter is already in the list"));
1251
/* iterate to the position... */
1252
USBDeviceFilterList::iterator itPos = m->llUSBDeviceFilters.begin();
1253
std::advance(itPos, aPosition);
1255
m->llUSBDeviceFilters.insert(itPos, pFilter);
1256
pFilter->mInList = true;
1258
/* notify the proxy (only when the filter is active) */
1259
if ( m->pUSBProxyService->isActive()
1260
&& pFilter->getData().mActive)
1262
ComAssertRet(pFilter->getId() == NULL, E_FAIL);
1263
pFilter->getId() = m->pUSBProxyService->insertFilter(&pFilter->getData().mUSBFilter);
1266
// save the global settings; for that we should hold only the VirtualBox lock
1268
AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1269
return rc = m->pParent->saveSettings();
1271
/* Note: The GUI depends on this method returning E_NOTIMPL with no
1272
* extended error info to indicate that USB is simply not available
1273
* (w/o treating it as a failure), for example, as in OSE. */
1276
ReturnComNotImplemented();
1280
STDMETHODIMP Host::RemoveUSBDeviceFilter(ULONG aPosition)
1282
#ifdef VBOX_WITH_USB
1284
/* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1285
AutoCaller autoCaller(this);
1286
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1288
AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1291
MultiResult rc = checkUSBProxyService();
1292
if (FAILED(rc)) return rc;
1294
if (!m->llUSBDeviceFilters.size())
1295
return setError(E_INVALIDARG,
1296
tr("The USB device filter list is empty"));
1298
if (aPosition >= m->llUSBDeviceFilters.size())
1299
return setError(E_INVALIDARG,
1300
tr("Invalid position: %lu (must be in range [0, %lu])"),
1301
aPosition, m->llUSBDeviceFilters.size() - 1);
1303
ComObjPtr<HostUSBDeviceFilter> filter;
1305
/* iterate to the position... */
1306
USBDeviceFilterList::iterator it = m->llUSBDeviceFilters.begin();
1307
std::advance (it, aPosition);
1308
/* ...get an element from there... */
1311
filter->mInList = false;
1312
m->llUSBDeviceFilters.erase(it);
1315
/* notify the proxy (only when the filter is active) */
1316
if (m->pUSBProxyService->isActive() && filter->getData().mActive)
1318
ComAssertRet(filter->getId() != NULL, E_FAIL);
1319
m->pUSBProxyService->removeFilter(filter->getId());
1320
filter->getId() = NULL;
1323
// save the global settings; for that we should hold only the VirtualBox lock
1325
AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1326
return rc = m->pParent->saveSettings();
1328
/* Note: The GUI depends on this method returning E_NOTIMPL with no
1329
* extended error info to indicate that USB is simply not available
1330
* (w/o treating it as a failure), for example, as in OSE. */
1332
ReturnComNotImplemented();
1336
STDMETHODIMP Host::FindHostDVDDrive(IN_BSTR aName, IMedium **aDrive)
1338
CheckComArgStrNotEmptyOrNull(aName);
1339
CheckComArgOutPointerValid(aDrive);
1341
ComObjPtr<Medium>medium;
1342
HRESULT rc = findHostDriveByNameOrId(DeviceType_DVD, Utf8Str(aName), medium);
1344
return medium.queryInterfaceTo(aDrive);
1346
return setError(rc, Medium::tr("The host DVD drive named '%ls' could not be found"), aName);
1349
STDMETHODIMP Host::FindHostFloppyDrive(IN_BSTR aName, IMedium **aDrive)
1351
CheckComArgStrNotEmptyOrNull(aName);
1352
CheckComArgOutPointerValid(aDrive);
1356
ComObjPtr<Medium>medium;
1357
HRESULT rc = findHostDriveByNameOrId(DeviceType_Floppy, Utf8Str(aName), medium);
1359
return medium.queryInterfaceTo(aDrive);
1361
return setError(rc, Medium::tr("The host floppy drive named '%ls' could not be found"), aName);
1364
STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInterface **networkInterface)
1366
#ifndef VBOX_WITH_HOSTNETIF_API
1370
return E_INVALIDARG;
1371
if (!networkInterface)
1374
*networkInterface = NULL;
1375
ComObjPtr<HostNetworkInterface> found;
1376
std::list <ComObjPtr<HostNetworkInterface> > list;
1377
int rc = NetIfList(list);
1380
Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
1383
std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
1384
for (it = list.begin(); it != list.end(); ++it)
1387
(*it)->COMGETTER(Name) (n.asOutParam());
1393
return setError(E_INVALIDARG,
1394
HostNetworkInterface::tr("The host network interface with the given name could not be found"));
1396
found->setVirtualBox(m->pParent);
1398
return found.queryInterfaceTo(networkInterface);
1402
STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_BSTR id, IHostNetworkInterface **networkInterface)
1404
#ifndef VBOX_WITH_HOSTNETIF_API
1407
if (Guid(id).isEmpty())
1408
return E_INVALIDARG;
1409
if (!networkInterface)
1412
*networkInterface = NULL;
1413
ComObjPtr<HostNetworkInterface> found;
1414
std::list <ComObjPtr<HostNetworkInterface> > list;
1415
int rc = NetIfList(list);
1418
Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
1421
std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
1422
for (it = list.begin(); it != list.end(); ++it)
1425
(*it)->COMGETTER(Id) (g.asOutParam());
1431
return setError(E_INVALIDARG,
1432
HostNetworkInterface::tr("The host network interface with the given GUID could not be found"));
1434
found->setVirtualBox(m->pParent);
1436
return found.queryInterfaceTo(networkInterface);
1440
STDMETHODIMP Host::FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_T type,
1441
ComSafeArrayOut(IHostNetworkInterface *, aNetworkInterfaces))
1443
#ifdef VBOX_WITH_HOSTNETIF_API
1444
std::list <ComObjPtr<HostNetworkInterface> > allList;
1445
int rc = NetIfList(allList);
1449
std::list <ComObjPtr<HostNetworkInterface> > resultList;
1451
std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
1452
for (it = allList.begin(); it != allList.end(); ++it)
1454
HostNetworkInterfaceType_T t;
1455
HRESULT hr = (*it)->COMGETTER(InterfaceType)(&t);
1461
(*it)->setVirtualBox(m->pParent);
1462
resultList.push_back (*it);
1466
SafeIfaceArray<IHostNetworkInterface> filteredNetworkInterfaces (resultList);
1467
filteredNetworkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
1475
STDMETHODIMP Host::FindUSBDeviceByAddress(IN_BSTR aAddress,
1476
IHostUSBDevice **aDevice)
1478
#ifdef VBOX_WITH_USB
1479
CheckComArgStrNotEmptyOrNull(aAddress);
1480
CheckComArgOutPointerValid(aDevice);
1484
SafeIfaceArray<IHostUSBDevice> devsvec;
1485
HRESULT rc = COMGETTER(USBDevices) (ComSafeArrayAsOutParam(devsvec));
1486
if (FAILED(rc)) return rc;
1488
for (size_t i = 0; i < devsvec.size(); ++i)
1491
rc = devsvec[i]->COMGETTER(Address) (address.asOutParam());
1492
if (FAILED(rc)) return rc;
1493
if (address == aAddress)
1495
return ComObjPtr<IHostUSBDevice> (devsvec[i]).queryInterfaceTo(aDevice);
1499
return setErrorNoLog(VBOX_E_OBJECT_NOT_FOUND,
1500
tr("Could not find a USB device with address '%ls'"),
1503
#else /* !VBOX_WITH_USB */
1507
#endif /* !VBOX_WITH_USB */
1510
STDMETHODIMP Host::FindUSBDeviceById(IN_BSTR aId,
1511
IHostUSBDevice **aDevice)
1513
#ifdef VBOX_WITH_USB
1514
CheckComArgExpr(aId, Guid (aId).isEmpty() == false);
1515
CheckComArgOutPointerValid(aDevice);
1519
SafeIfaceArray<IHostUSBDevice> devsvec;
1520
HRESULT rc = COMGETTER(USBDevices) (ComSafeArrayAsOutParam(devsvec));
1521
if (FAILED(rc)) return rc;
1523
for (size_t i = 0; i < devsvec.size(); ++i)
1526
rc = devsvec[i]->COMGETTER(Id) (id.asOutParam());
1527
if (FAILED(rc)) return rc;
1530
return ComObjPtr<IHostUSBDevice> (devsvec[i]).queryInterfaceTo(aDevice);
1534
return setErrorNoLog (VBOX_E_OBJECT_NOT_FOUND, tr (
1535
"Could not find a USB device with uuid {%RTuuid}"),
1538
#else /* !VBOX_WITH_USB */
1542
#endif /* !VBOX_WITH_USB */
1545
STDMETHODIMP Host::GenerateMACAddress(BSTR *aAddress)
1547
CheckComArgOutPointerValid(aAddress);
1548
// no locking required
1550
generateMACAddress(mac);
1551
Bstr(mac).cloneTo(aAddress);
1555
// public methods only for internal purposes
1556
////////////////////////////////////////////////////////////////////////////////
1558
HRESULT Host::loadSettings(const settings::Host &data)
1561
#ifdef VBOX_WITH_USB
1562
AutoCaller autoCaller(this);
1563
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1565
AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1567
for (settings::USBDeviceFiltersList::const_iterator it = data.llUSBDeviceFilters.begin();
1568
it != data.llUSBDeviceFilters.end();
1571
const settings::USBDeviceFilter &f = *it;
1572
ComObjPtr<HostUSBDeviceFilter> pFilter;
1573
pFilter.createObject();
1574
rc = pFilter->init(this, f);
1575
if (FAILED(rc)) break;
1577
m->llUSBDeviceFilters.push_back(pFilter);
1578
pFilter->mInList = true;
1580
/* notify the proxy (only when the filter is active) */
1581
if (pFilter->getData().mActive)
1583
HostUSBDeviceFilter *flt = pFilter; /* resolve ambiguity */
1584
flt->getId() = m->pUSBProxyService->insertFilter(&pFilter->getData().mUSBFilter);
1589
#endif /* VBOX_WITH_USB */
1593
HRESULT Host::saveSettings(settings::Host &data)
1595
#ifdef VBOX_WITH_USB
1596
AutoCaller autoCaller(this);
1597
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1599
AutoReadLock alock1(this COMMA_LOCKVAL_SRC_POS);
1600
AutoReadLock alock2(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1602
data.llUSBDeviceFilters.clear();
1604
for (USBDeviceFilterList::const_iterator it = m->llUSBDeviceFilters.begin();
1605
it != m->llUSBDeviceFilters.end();
1608
ComObjPtr<HostUSBDeviceFilter> pFilter = *it;
1609
settings::USBDeviceFilter f;
1610
pFilter->saveSettings(f);
1611
data.llUSBDeviceFilters.push_back(f);
1615
#endif /* VBOX_WITH_USB */
1621
* Sets the given pointer to point to the static list of DVD or floppy
1622
* drives in the Host instance data, depending on the @a mediumType
1625
* This builds the list on the first call; it adds or removes host drives
1626
* that may have changed if fRefresh == true.
1628
* The caller must hold the m->drivesLock write lock before calling this.
1629
* To protect the list to which the caller's pointer points, the caller
1630
* must also hold that lock.
1632
* @param mediumType Must be DeviceType_Floppy or DeviceType_DVD.
1633
* @param fRefresh Whether to refresh the host drives list even if this is not the first call.
1634
* @param pll Caller's pointer which gets set to the static list of host drives.
1637
HRESULT Host::getDrives(DeviceType_T mediumType,
1642
Assert(m->drivesLock.isWriteLockOnCurrentThread());
1645
MediaList *pllCached;
1646
bool *pfListBuilt = NULL;
1650
case DeviceType_DVD:
1651
if (!m->fDVDDrivesListBuilt || fRefresh)
1653
rc = buildDVDDrivesList(llNew);
1656
pfListBuilt = &m->fDVDDrivesListBuilt;
1658
pllCached = &m->llDVDDrives;
1661
case DeviceType_Floppy:
1662
if (!m->fFloppyDrivesListBuilt || fRefresh)
1664
rc = buildFloppyDrivesList(llNew);
1667
pfListBuilt = &m->fFloppyDrivesListBuilt;
1669
pllCached = &m->llFloppyDrives;
1673
return E_INVALIDARG;
1678
// a list was built in llNew above:
1681
// this was the first call (instance bool is still false): then just copy the whole list and return
1683
// and mark the instance data as "built"
1684
*pfListBuilt = true;
1688
// list was built, and this was a subsequent call: then compare the old and the new lists
1690
// remove drives from the cached list which are no longer present
1691
for (MediaList::iterator itCached = pllCached->begin();
1692
itCached != pllCached->end();
1695
Medium *pCached = *itCached;
1696
const Utf8Str strLocationCached = pCached->getLocationFull();
1697
bool fFound = false;
1698
for (MediaList::iterator itNew = llNew.begin();
1699
itNew != llNew.end();
1702
Medium *pNew = *itNew;
1703
const Utf8Str strLocationNew = pNew->getLocationFull();
1704
if (strLocationNew == strLocationCached)
1711
itCached = pllCached->erase(itCached);
1716
// add drives to the cached list that are not on there yet
1717
for (MediaList::iterator itNew = llNew.begin();
1718
itNew != llNew.end();
1721
Medium *pNew = *itNew;
1722
const Utf8Str strLocationNew = pNew->getLocationFull();
1723
bool fFound = false;
1724
for (MediaList::iterator itCached = pllCached->begin();
1725
itCached != pllCached->end();
1728
Medium *pCached = *itCached;
1729
const Utf8Str strLocationCached = pCached->getLocationFull();
1730
if (strLocationNew == strLocationCached)
1738
pllCached->push_back(pNew);
1743
// return cached list to caller
1750
* Goes through the list of host drives that would be returned by getDrives()
1751
* and looks for a host drive with the given UUID. If found, it sets pMedium
1752
* to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
1754
* @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
1755
* @param uuid Medium UUID of host drive to look for.
1756
* @param fRefresh Whether to refresh the host drives list (see getDrives())
1757
* @param pMedium Medium object, if found…
1758
* @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
1760
HRESULT Host::findHostDriveById(DeviceType_T mediumType,
1763
ComObjPtr<Medium> &pMedium)
1765
MediaList *pllMedia;
1767
AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
1768
HRESULT rc = getDrives(mediumType, fRefresh, pllMedia);
1771
for (MediaList::iterator it = pllMedia->begin();
1772
it != pllMedia->end();
1775
Medium *pThis = *it;
1776
AutoCaller mediumCaller(pThis);
1777
AutoReadLock mediumLock(pThis COMMA_LOCKVAL_SRC_POS);
1778
if (pThis->getId() == uuid)
1786
return VBOX_E_OBJECT_NOT_FOUND;
1790
* Goes through the list of host drives that would be returned by getDrives()
1791
* and looks for a host drive with the given name. If found, it sets pMedium
1792
* to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
1794
* @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
1795
* @param strLocationFull Name (path) of host drive to look for.
1796
* @param fRefresh Whether to refresh the host drives list (see getDrives())
1797
* @param pMedium Medium object, if found…
1798
* @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
1800
HRESULT Host::findHostDriveByName(DeviceType_T mediumType,
1801
const Utf8Str &strLocationFull,
1803
ComObjPtr<Medium> &pMedium)
1805
MediaList *pllMedia;
1807
AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
1808
HRESULT rc = getDrives(mediumType, fRefresh, pllMedia);
1811
for (MediaList::iterator it = pllMedia->begin();
1812
it != pllMedia->end();
1815
Medium *pThis = *it;
1816
AutoCaller mediumCaller(pThis);
1817
AutoReadLock mediumLock(pThis COMMA_LOCKVAL_SRC_POS);
1818
if (pThis->getLocationFull() == strLocationFull)
1826
return VBOX_E_OBJECT_NOT_FOUND;
1830
* Goes through the list of host drives that would be returned by getDrives()
1831
* and looks for a host drive with the given name, location or ID. If found,
1832
* it sets pMedium to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
1834
* @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
1835
* @param strNameOrId Name or full location or UUID of host drive to look for.
1836
* @param pMedium Medium object, if found…
1837
* @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
1839
HRESULT Host::findHostDriveByNameOrId(DeviceType_T mediumType,
1840
const Utf8Str &strNameOrId,
1841
ComObjPtr<Medium> &pMedium)
1843
AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
1845
Guid uuid(strNameOrId);
1846
if (!uuid.isEmpty())
1847
return findHostDriveById(mediumType, uuid, true /* fRefresh */, pMedium);
1849
// string is not a syntactically valid UUID: try a name then
1850
return findHostDriveByName(mediumType, strNameOrId, true /* fRefresh */, pMedium);
1854
* Called from getDrives() to build the DVD drives list.
1858
HRESULT Host::buildDVDDrivesList(MediaList &list)
1862
Assert(m->drivesLock.isWriteLockOnCurrentThread());
1866
#if defined(RT_OS_WINDOWS)
1867
int sz = GetLogicalDriveStrings(0, NULL);
1868
TCHAR *hostDrives = new TCHAR[sz+1];
1869
GetLogicalDriveStrings(sz, hostDrives);
1870
wchar_t driveName[3] = { '?', ':', '\0' };
1871
TCHAR *p = hostDrives;
1874
if (GetDriveType(p) == DRIVE_CDROM)
1877
ComObjPtr<Medium> hostDVDDriveObj;
1878
hostDVDDriveObj.createObject();
1879
hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(driveName));
1880
list.push_back(hostDVDDriveObj);
1882
p += _tcslen(p) + 1;
1885
delete[] hostDrives;
1887
#elif defined(RT_OS_SOLARIS)
1888
# ifdef VBOX_USE_LIBHAL
1889
if (!getDVDInfoFromHal(list))
1892
getDVDInfoFromDevTree(list);
1895
#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
1896
if (RT_SUCCESS(m->hostDrives.updateDVDs()))
1897
for (DriveInfoList::const_iterator it = m->hostDrives.DVDBegin();
1898
SUCCEEDED(rc) && it != m->hostDrives.DVDEnd(); ++it)
1900
ComObjPtr<Medium> hostDVDDriveObj;
1901
Utf8Str location(it->mDevice);
1902
Utf8Str description(it->mDescription);
1904
rc = hostDVDDriveObj.createObject();
1906
rc = hostDVDDriveObj->init(m->pParent, DeviceType_DVD, location, description);
1908
list.push_back(hostDVDDriveObj);
1910
#elif defined(RT_OS_DARWIN)
1911
PDARWINDVD cur = DarwinGetDVDDrives();
1914
ComObjPtr<Medium> hostDVDDriveObj;
1915
hostDVDDriveObj.createObject();
1916
hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(cur->szName));
1917
list.push_back(hostDVDDriveObj);
1928
catch(std::bad_alloc &)
1936
* Called from getDrives() to build the floppy drives list.
1940
HRESULT Host::buildFloppyDrivesList(MediaList &list)
1944
Assert(m->drivesLock.isWriteLockOnCurrentThread());
1948
#ifdef RT_OS_WINDOWS
1949
int sz = GetLogicalDriveStrings(0, NULL);
1950
TCHAR *hostDrives = new TCHAR[sz+1];
1951
GetLogicalDriveStrings(sz, hostDrives);
1952
wchar_t driveName[3] = { '?', ':', '\0' };
1953
TCHAR *p = hostDrives;
1956
if (GetDriveType(p) == DRIVE_REMOVABLE)
1959
ComObjPtr<Medium> hostFloppyDriveObj;
1960
hostFloppyDriveObj.createObject();
1961
hostFloppyDriveObj->init(m->pParent, DeviceType_Floppy, Bstr(driveName));
1962
list.push_back(hostFloppyDriveObj);
1964
p += _tcslen(p) + 1;
1967
delete[] hostDrives;
1968
#elif defined(RT_OS_LINUX)
1969
if (RT_SUCCESS(m->hostDrives.updateFloppies()))
1970
for (DriveInfoList::const_iterator it = m->hostDrives.FloppyBegin();
1971
SUCCEEDED(rc) && it != m->hostDrives.FloppyEnd(); ++it)
1973
ComObjPtr<Medium> hostFloppyDriveObj;
1974
Utf8Str location(it->mDevice);
1975
Utf8Str description(it->mDescription);
1977
rc = hostFloppyDriveObj.createObject();
1979
rc = hostFloppyDriveObj->init(m->pParent, DeviceType_Floppy, location, description);
1981
list.push_back(hostFloppyDriveObj);
1988
catch(std::bad_alloc &)
1996
#ifdef VBOX_WITH_USB
1997
USBProxyService* Host::usbProxyService()
1999
return m->pUSBProxyService;
2002
HRESULT Host::addChild(HostUSBDeviceFilter *pChild)
2004
AutoCaller autoCaller(this);
2005
if (FAILED(autoCaller.rc())) return autoCaller.rc();
2007
AutoWriteLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
2009
m->llChildren.push_back(pChild);
2014
HRESULT Host::removeChild(HostUSBDeviceFilter *pChild)
2016
AutoCaller autoCaller(this);
2017
if (FAILED(autoCaller.rc())) return autoCaller.rc();
2019
AutoWriteLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
2021
for (USBDeviceFilterList::iterator it = m->llChildren.begin();
2022
it != m->llChildren.end();
2027
m->llChildren.erase(it);
2035
VirtualBox* Host::parent()
2041
* Called by setter methods of all USB device filters.
2043
HRESULT Host::onUSBDeviceFilterChange(HostUSBDeviceFilter *aFilter,
2044
BOOL aActiveChanged /* = FALSE */)
2046
AutoCaller autoCaller(this);
2047
if (FAILED(autoCaller.rc())) return autoCaller.rc();
2049
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2051
if (aFilter->mInList)
2055
// insert/remove the filter from the proxy
2056
if (aFilter->getData().mActive)
2058
ComAssertRet(aFilter->getId() == NULL, E_FAIL);
2059
aFilter->getId() = m->pUSBProxyService->insertFilter(&aFilter->getData().mUSBFilter);
2063
ComAssertRet(aFilter->getId() != NULL, E_FAIL);
2064
m->pUSBProxyService->removeFilter(aFilter->getId());
2065
aFilter->getId() = NULL;
2070
if (aFilter->getData().mActive)
2072
// update the filter in the proxy
2073
ComAssertRet(aFilter->getId() != NULL, E_FAIL);
2074
m->pUSBProxyService->removeFilter(aFilter->getId());
2075
aFilter->getId() = m->pUSBProxyService->insertFilter(&aFilter->getData().mUSBFilter);
2079
// save the global settings... yeah, on every single filter property change
2080
// for that we should hold only the VirtualBox lock
2082
AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
2083
return m->pParent->saveSettings();
2091
* Interface for obtaining a copy of the USBDeviceFilterList,
2092
* used by the USBProxyService.
2094
* @param aGlobalFilters Where to put the global filter list copy.
2095
* @param aMachines Where to put the machine vector.
2097
void Host::getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters)
2099
AutoReadLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
2101
*aGlobalFilters = m->llUSBDeviceFilters;
2104
#endif /* VBOX_WITH_USB */
2107
////////////////////////////////////////////////////////////////////////////////
2109
#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
2112
* Helper function to get the slice number from a device path
2114
* @param pszDevLinkPath Pointer to a device path (/dev/(r)dsk/c7d1t0d0s3 etc.)
2115
* @returns Pointer to the slice portion of the given path.
2117
static char *solarisGetSliceFromPath(const char *pszDevLinkPath)
2119
char *pszFound = NULL;
2120
char *pszSlice = strrchr(pszDevLinkPath, 's');
2121
char *pszDisk = strrchr(pszDevLinkPath, 'd');
2122
if (pszSlice && pszSlice > pszDisk)
2123
pszFound = pszSlice;
2127
if (pszFound && RT_C_IS_DIGIT(pszFound[1]))
2134
* Walk device links and returns an allocated path for the first one in the snapshot.
2136
* @param DevLink Handle to the device link being walked.
2137
* @param pvArg Opaque data containing the pointer to the path.
2138
* @returns Pointer to an allocated device path string.
2140
static int solarisWalkDevLink(di_devlink_t DevLink, void *pvArg)
2142
char **ppszPath = (char **)pvArg;
2143
*ppszPath = strdup(di_devlink_path(DevLink));
2144
return DI_WALK_TERMINATE;
2148
* Walk all devices in the system and enumerate CD/DVD drives.
2149
* @param Node Handle to the current node.
2150
* @param pvArg Opaque data (holds list pointer).
2151
* @returns Solaris specific code whether to continue walking or not.
2153
static int solarisWalkDeviceNodeForDVD(di_node_t Node, void *pvArg)
2155
PSOLARISDVD *ppDrives = (PSOLARISDVD *)pvArg;
2158
* Check for "removable-media" or "hotpluggable" instead of "SCSI" so that we also include USB CD-ROMs.
2159
* As unfortunately the Solaris drivers only export these common properties.
2162
if ( di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "removable-media", &pInt) >= 0
2163
|| di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "hotpluggable", &pInt) >= 0)
2165
if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "inquiry-device-type", &pInt) > 0
2166
&& ( *pInt == DTYPE_RODIRECT /* CDROM */
2167
|| *pInt == DTYPE_OPTICAL)) /* Optical Drive */
2169
char *pszProduct = NULL;
2170
if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-product-id", &pszProduct) > 0)
2172
char *pszVendor = NULL;
2173
if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-vendor-id", &pszVendor) > 0)
2176
* Found a DVD drive, we need to scan the minor nodes to find the correct
2177
* slice that represents the whole drive. "s2" is always the whole drive for CD/DVDs.
2179
int Major = di_driver_major(Node);
2180
di_minor_t Minor = DI_MINOR_NIL;
2181
di_devlink_handle_t DevLink = di_devlink_init(NULL /* name */, 0 /* flags */);
2184
while ((Minor = di_minor_next(Node, Minor)) != DI_MINOR_NIL)
2186
dev_t Dev = di_minor_devt(Minor);
2187
if ( Major != (int)major(Dev)
2188
|| di_minor_spectype(Minor) == S_IFBLK
2189
|| di_minor_type(Minor) != DDM_MINOR)
2194
char *pszMinorPath = di_devfs_minor_path(Minor);
2198
char *pszDevLinkPath = NULL;
2199
di_devlink_walk(DevLink, NULL, pszMinorPath, DI_PRIMARY_LINK, &pszDevLinkPath, solarisWalkDevLink);
2200
di_devfs_path_free(pszMinorPath);
2204
char *pszSlice = solarisGetSliceFromPath(pszDevLinkPath);
2205
if ( pszSlice && !strcmp(pszSlice, "s2")
2206
&& !strncmp(pszDevLinkPath, "/dev/rdsk", sizeof("/dev/rdsk") - 1)) /* We want only raw disks */
2209
* We've got a fully qualified DVD drive. Add it to the list.
2211
PSOLARISDVD pDrive = (PSOLARISDVD)RTMemAllocZ(sizeof(SOLARISDVD));
2212
if (RT_LIKELY(pDrive))
2214
RTStrPrintf(pDrive->szDescription, sizeof(pDrive->szDescription), "%s %s", pszVendor, pszProduct);
2215
RTStrCopy(pDrive->szRawDiskPath, sizeof(pDrive->szRawDiskPath), pszDevLinkPath);
2217
pDrive->pNext = *ppDrives;
2220
/* We're not interested in any of the other slices, stop minor nodes traversal. */
2221
free(pszDevLinkPath);
2225
free(pszDevLinkPath);
2228
di_devlink_fini(&DevLink);
2234
return DI_WALK_CONTINUE;
2238
* Solaris specific function to enumerate CD/DVD drives via the device tree.
2239
* Works on Solaris 10 as well as OpenSolaris without depending on libhal.
2241
void Host::getDVDInfoFromDevTree(std::list<ComObjPtr<Medium> > &list)
2243
PSOLARISDVD pDrives = NULL;
2244
di_node_t RootNode = di_init("/", DINFOCPYALL);
2245
if (RootNode != DI_NODE_NIL)
2246
di_walk_node(RootNode, DI_WALK_CLDFIRST, &pDrives, solarisWalkDeviceNodeForDVD);
2252
ComObjPtr<Medium> hostDVDDriveObj;
2253
hostDVDDriveObj.createObject();
2254
hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(pDrives->szRawDiskPath), Bstr(pDrives->szDescription));
2255
list.push_back(hostDVDDriveObj);
2257
void *pvDrive = pDrives;
2258
pDrives = pDrives->pNext;
2263
/* Solaris hosts, loading libhal at runtime */
2266
* Helper function to query the hal subsystem for information about DVD drives attached to the
2269
* @returns true if information was successfully obtained, false otherwise
2270
* @retval list drives found will be attached to this list
2272
bool Host::getDVDInfoFromHal(std::list<ComObjPtr<Medium> > &list)
2274
bool halSuccess = false;
2275
DBusError dbusError;
2276
if (!gLibHalCheckPresence())
2278
gDBusErrorInit (&dbusError);
2279
DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2280
if (dbusConnection != 0)
2282
LibHalContext *halContext = gLibHalCtxNew();
2283
if (halContext != 0)
2285
if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2287
if (gLibHalCtxInit(halContext, &dbusError))
2290
char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2291
"storage.drive_type", "cdrom",
2292
&numDevices, &dbusError);
2293
if (halDevices != 0)
2295
/* Hal is installed and working, so if no devices are reported, assume
2296
that there are none. */
2298
for (int i = 0; i < numDevices; i++)
2300
char *devNode = gLibHalDeviceGetPropertyString(halContext,
2301
halDevices[i], "block.device", &dbusError);
2302
#ifdef RT_OS_SOLARIS
2303
/* The CD/DVD ioctls work only for raw device nodes. */
2304
char *tmp = getfullrawname(devNode);
2305
gLibHalFreeString(devNode);
2311
// if (validateDevice(devNode, true))
2313
Utf8Str description;
2314
char *vendor, *product;
2315
/* We do not check the error here, as this field may
2317
vendor = gLibHalDeviceGetPropertyString(halContext,
2318
halDevices[i], "info.vendor", 0);
2319
product = gLibHalDeviceGetPropertyString(halContext,
2320
halDevices[i], "info.product", &dbusError);
2321
if ((product != 0 && product[0] != 0))
2323
if ((vendor != 0) && (vendor[0] != 0))
2325
description = Utf8StrFmt ("%s %s",
2330
description = product;
2332
ComObjPtr<Medium> hostDVDDriveObj;
2333
hostDVDDriveObj.createObject();
2334
hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2335
Bstr(devNode), Bstr(description));
2336
list.push_back (hostDVDDriveObj);
2342
LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2343
halDevices[i], dbusError.name, dbusError.message));
2344
gDBusErrorFree(&dbusError);
2346
ComObjPtr<Medium> hostDVDDriveObj;
2347
hostDVDDriveObj.createObject();
2348
hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2350
list.push_back (hostDVDDriveObj);
2354
gLibHalFreeString(vendor);
2358
gLibHalFreeString(product);
2363
// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
2365
#ifndef RT_OS_SOLARIS
2366
gLibHalFreeString(devNode);
2373
LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2374
halDevices[i], dbusError.name, dbusError.message));
2375
gDBusErrorFree(&dbusError);
2378
gLibHalFreeStringArray(halDevices);
2382
LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2383
gDBusErrorFree(&dbusError);
2385
if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2387
LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2388
gDBusErrorFree(&dbusError);
2393
LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2394
gDBusErrorFree(&dbusError);
2396
gLibHalCtxFree(halContext);
2400
LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
2405
LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
2407
gDBusConnectionUnref(dbusConnection);
2411
LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2412
gDBusErrorFree(&dbusError);
2419
* Helper function to query the hal subsystem for information about floppy drives attached to the
2422
* @returns true if information was successfully obtained, false otherwise
2423
* @retval list drives found will be attached to this list
2425
bool Host::getFloppyInfoFromHal(std::list< ComObjPtr<Medium> > &list)
2427
bool halSuccess = false;
2428
DBusError dbusError;
2429
if (!gLibHalCheckPresence())
2431
gDBusErrorInit (&dbusError);
2432
DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2433
if (dbusConnection != 0)
2435
LibHalContext *halContext = gLibHalCtxNew();
2436
if (halContext != 0)
2438
if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2440
if (gLibHalCtxInit(halContext, &dbusError))
2443
char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2444
"storage.drive_type", "floppy",
2445
&numDevices, &dbusError);
2446
if (halDevices != 0)
2448
/* Hal is installed and working, so if no devices are reported, assume
2449
that there are none. */
2451
for (int i = 0; i < numDevices; i++)
2453
char *driveType = gLibHalDeviceGetPropertyString(halContext,
2454
halDevices[i], "storage.drive_type", 0);
2457
if (strcmp(driveType, "floppy") != 0)
2459
gLibHalFreeString(driveType);
2462
gLibHalFreeString(driveType);
2466
/* An error occurred. The attribute "storage.drive_type"
2467
probably didn't exist. */
2470
char *devNode = gLibHalDeviceGetPropertyString(halContext,
2471
halDevices[i], "block.device", &dbusError);
2474
// if (validateDevice(devNode, false))
2476
Utf8Str description;
2477
char *vendor, *product;
2478
/* We do not check the error here, as this field may
2480
vendor = gLibHalDeviceGetPropertyString(halContext,
2481
halDevices[i], "info.vendor", 0);
2482
product = gLibHalDeviceGetPropertyString(halContext,
2483
halDevices[i], "info.product", &dbusError);
2484
if ((product != 0) && (product[0] != 0))
2486
if ((vendor != 0) && (vendor[0] != 0))
2488
description = Utf8StrFmt ("%s %s",
2493
description = product;
2495
ComObjPtr<Medium> hostFloppyDrive;
2496
hostFloppyDrive.createObject();
2497
hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2498
Bstr(devNode), Bstr(description));
2499
list.push_back (hostFloppyDrive);
2505
LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2506
halDevices[i], dbusError.name, dbusError.message));
2507
gDBusErrorFree(&dbusError);
2509
ComObjPtr<Medium> hostFloppyDrive;
2510
hostFloppyDrive.createObject();
2511
hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2513
list.push_back (hostFloppyDrive);
2517
gLibHalFreeString(vendor);
2521
gLibHalFreeString(product);
2526
// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
2528
gLibHalFreeString(devNode);
2532
LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2533
halDevices[i], dbusError.name, dbusError.message));
2534
gDBusErrorFree(&dbusError);
2537
gLibHalFreeStringArray(halDevices);
2541
LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2542
gDBusErrorFree(&dbusError);
2544
if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2546
LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2547
gDBusErrorFree(&dbusError);
2552
LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2553
gDBusErrorFree(&dbusError);
2555
gLibHalCtxFree(halContext);
2559
LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
2564
LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
2566
gDBusConnectionUnref(dbusConnection);
2570
LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2571
gDBusErrorFree(&dbusError);
2575
#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
2577
/** @todo get rid of dead code below - RT_OS_SOLARIS and RT_OS_LINUX are never both set */
2578
#if defined(RT_OS_SOLARIS)
2581
* Helper function to parse the given mount file and add found entries
2583
void Host::parseMountTable(char *mountTable, std::list< ComObjPtr<Medium> > &list)
2586
FILE *mtab = setmntent(mountTable, "r");
2589
struct mntent *mntent;
2593
while ((mntent = getmntent(mtab)))
2595
mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
2596
mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
2597
strcpy(mnt_type, mntent->mnt_type);
2598
strcpy(mnt_dev, mntent->mnt_fsname);
2599
// supermount fs case
2600
if (strcmp(mnt_type, "supermount") == 0)
2602
tmp = strstr(mntent->mnt_opts, "fs=");
2606
mnt_type = strdup(tmp + strlen("fs="));
2609
tmp = strchr(mnt_type, ',');
2614
tmp = strstr(mntent->mnt_opts, "dev=");
2618
mnt_dev = strdup(tmp + strlen("dev="));
2621
tmp = strchr(mnt_dev, ',');
2627
// use strstr here to cover things fs types like "udf,iso9660"
2628
if (strstr(mnt_type, "iso9660") == 0)
2630
/** @todo check whether we've already got the drive in our list! */
2631
if (validateDevice(mnt_dev, true))
2633
ComObjPtr<Medium> hostDVDDriveObj;
2634
hostDVDDriveObj.createObject();
2635
hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(mnt_dev));
2636
list.push_back (hostDVDDriveObj);
2644
#else // RT_OS_SOLARIS
2645
FILE *mntFile = fopen(mountTable, "r");
2648
struct mnttab mntTab;
2649
while (getmntent(mntFile, &mntTab) == 0)
2651
const char *mountName = mntTab.mnt_special;
2652
const char *mountPoint = mntTab.mnt_mountp;
2653
const char *mountFSType = mntTab.mnt_fstype;
2654
if (mountName && mountPoint && mountFSType)
2656
// skip devices we are not interested in
2657
if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
2658
(*mountFSType && (strncmp(mountFSType, "devfs", 5) != 0 && // skip devfs (i.e. /devices)
2659
strncmp(mountFSType, "dev", 3) != 0 && // skip dev (i.e. /dev)
2660
strncmp(mountFSType, "lofs", 4) != 0))) // skip loop-back file-system (lofs)
2662
char *rawDevName = getfullrawname((char *)mountName);
2663
if (validateDevice(rawDevName, true))
2665
ComObjPtr<Medium> hostDVDDriveObj;
2666
hostDVDDriveObj.createObject();
2667
hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(rawDevName));
2668
list.push_back (hostDVDDriveObj);
2681
* Helper function to check whether the given device node is a valid drive
2683
bool Host::validateDevice(const char *deviceNode, bool isCDROM)
2685
struct stat statInfo;
2686
bool retValue = false;
2694
// first a simple stat() call
2695
if (stat(deviceNode, &statInfo) < 0)
2703
if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2706
// now try to open the device
2707
fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
2708
if (fileHandle >= 0)
2710
cdrom_subchnl cdChannelInfo;
2711
cdChannelInfo.cdsc_format = CDROM_MSF;
2712
// this call will finally reveal the whole truth
2714
if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2715
(errno == EIO) || (errno == ENOENT) ||
2716
(errno == EINVAL) || (errno == ENOMEDIUM))
2718
if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2719
(errno == EIO) || (errno == ENOENT) ||
2731
if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2733
/// @todo do some more testing, maybe a nice IOCTL!
2740
#endif // RT_OS_SOLARIS
2742
#ifdef VBOX_WITH_USB
2744
* Checks for the presence and status of the USB Proxy Service.
2745
* Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
2746
* warning) if the proxy service is not available due to the way the host is
2747
* configured (at present, that means that usbfs and hal/DBus are not
2748
* available on a Linux host) or E_FAIL and a corresponding error message
2749
* otherwise. Intended to be used by methods that rely on the Proxy Service
2752
* @note This method may return a warning result code. It is recommended to use
2753
* MultiError to store the return value.
2755
* @note Locks this object for reading.
2757
HRESULT Host::checkUSBProxyService()
2759
AutoCaller autoCaller(this);
2760
if (FAILED(autoCaller.rc())) return autoCaller.rc();
2762
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2764
AssertReturn(m->pUSBProxyService, E_FAIL);
2765
if (!m->pUSBProxyService->isActive())
2767
/* disable the USB controller completely to avoid assertions if the
2768
* USB proxy service could not start. */
2770
switch (m->pUSBProxyService->getLastError())
2772
case VERR_FILE_NOT_FOUND: /** @todo what does this mean? */
2773
return setWarning(E_FAIL,
2774
tr("Could not load the Host USB Proxy Service (VERR_FILE_NOT_FOUND). The service might not be installed on the host computer"));
2775
case VERR_VUSB_USB_DEVICE_PERMISSION:
2776
return setWarning(E_FAIL,
2777
tr("VirtualBox is not currently allowed to access USB devices. You can change this by adding your user to the 'vboxusers' group. Please see the user manual for a more detailed explanation"));
2778
case VERR_VUSB_USBFS_PERMISSION:
2779
return setWarning(E_FAIL,
2780
tr("VirtualBox is not currently allowed to access USB devices. You can change this by allowing your user to access the 'usbfs' folder and files. Please see the user manual for a more detailed explanation"));
2782
return setWarning(E_FAIL,
2783
tr("The USB Proxy Service has not yet been ported to this host"));
2785
return setWarning (E_FAIL, "%s: %Rrc",
2786
tr ("Could not load the Host USB Proxy service"),
2787
m->pUSBProxyService->getLastError());
2793
#endif /* VBOX_WITH_USB */
2795
#ifdef VBOX_WITH_RESOURCE_USAGE_API
2797
void Host::registerMetrics(PerformanceCollector *aCollector)
2799
pm::CollectorHAL *hal = aCollector->getHAL();
2800
/* Create sub metrics */
2801
pm::SubMetric *cpuLoadUser = new pm::SubMetric("CPU/Load/User",
2802
"Percentage of processor time spent in user mode.");
2803
pm::SubMetric *cpuLoadKernel = new pm::SubMetric("CPU/Load/Kernel",
2804
"Percentage of processor time spent in kernel mode.");
2805
pm::SubMetric *cpuLoadIdle = new pm::SubMetric("CPU/Load/Idle",
2806
"Percentage of processor time spent idling.");
2807
pm::SubMetric *cpuMhzSM = new pm::SubMetric("CPU/MHz",
2808
"Average of current frequency of all processors.");
2809
pm::SubMetric *ramUsageTotal = new pm::SubMetric("RAM/Usage/Total",
2810
"Total physical memory installed.");
2811
pm::SubMetric *ramUsageUsed = new pm::SubMetric("RAM/Usage/Used",
2812
"Physical memory currently occupied.");
2813
pm::SubMetric *ramUsageFree = new pm::SubMetric("RAM/Usage/Free",
2814
"Physical memory currently available to applications.");
2815
pm::SubMetric *ramVMMUsed = new pm::SubMetric("RAM/VMM/Used",
2816
"Total physical memory used by the hypervisor.");
2817
pm::SubMetric *ramVMMFree = new pm::SubMetric("RAM/VMM/Free",
2818
"Total physical memory free inside the hypervisor.");
2819
pm::SubMetric *ramVMMBallooned = new pm::SubMetric("RAM/VMM/Ballooned",
2820
"Total physical memory ballooned by the hypervisor.");
2821
pm::SubMetric *ramVMMShared = new pm::SubMetric("RAM/VMM/Shared",
2822
"Total physical memory shared between VMs.");
2825
/* Create and register base metrics */
2827
ComObjPtr<Host> tmp = this;
2828
tmp.queryInterfaceTo(&objptr);
2829
pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw(hal, objptr, cpuLoadUser, cpuLoadKernel,
2831
aCollector->registerBaseMetric (cpuLoad);
2832
pm::BaseMetric *cpuMhz = new pm::HostCpuMhz(hal, objptr, cpuMhzSM);
2833
aCollector->registerBaseMetric (cpuMhz);
2834
pm::BaseMetric *ramUsage = new pm::HostRamUsage(hal, objptr,
2838
aCollector->registerBaseMetric (ramUsage);
2839
pm::BaseMetric *ramVmm = new pm::HostRamVmm(aCollector->getGuestManager(), objptr,
2844
aCollector->registerBaseMetric (ramVmm);
2846
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
2847
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2848
new pm::AggregateAvg()));
2849
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2850
new pm::AggregateMin()));
2851
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2852
new pm::AggregateMax()));
2854
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, 0));
2855
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2856
new pm::AggregateAvg()));
2857
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2858
new pm::AggregateMin()));
2859
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2860
new pm::AggregateMax()));
2862
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, 0));
2863
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2864
new pm::AggregateAvg()));
2865
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2866
new pm::AggregateMin()));
2867
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2868
new pm::AggregateMax()));
2870
aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM, 0));
2871
aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2872
new pm::AggregateAvg()));
2873
aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2874
new pm::AggregateMin()));
2875
aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2876
new pm::AggregateMax()));
2878
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal, 0));
2879
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2880
new pm::AggregateAvg()));
2881
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2882
new pm::AggregateMin()));
2883
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2884
new pm::AggregateMax()));
2886
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed, 0));
2887
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2888
new pm::AggregateAvg()));
2889
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2890
new pm::AggregateMin()));
2891
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2892
new pm::AggregateMax()));
2894
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree, 0));
2895
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2896
new pm::AggregateAvg()));
2897
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2898
new pm::AggregateMin()));
2899
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2900
new pm::AggregateMax()));
2902
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed, 0));
2903
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed,
2904
new pm::AggregateAvg()));
2905
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed,
2906
new pm::AggregateMin()));
2907
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed,
2908
new pm::AggregateMax()));
2910
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree, 0));
2911
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree,
2912
new pm::AggregateAvg()));
2913
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree,
2914
new pm::AggregateMin()));
2915
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree,
2916
new pm::AggregateMax()));
2918
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned, 0));
2919
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned,
2920
new pm::AggregateAvg()));
2921
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned,
2922
new pm::AggregateMin()));
2923
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned,
2924
new pm::AggregateMax()));
2926
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared, 0));
2927
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
2928
new pm::AggregateAvg()));
2929
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
2930
new pm::AggregateMin()));
2931
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
2932
new pm::AggregateMax()));
2935
void Host::unregisterMetrics (PerformanceCollector *aCollector)
2937
aCollector->unregisterMetricsFor(this);
2938
aCollector->unregisterBaseMetricsFor(this);
2943
void Host::generateMACAddress(Utf8Str &mac)
2946
* Our strategy is as follows: the first three bytes are our fixed
2947
* vendor ID (080027). The remaining 3 bytes will be taken from the
2948
* start of a GUID. This is a fairly safe algorithm.
2952
mac = Utf8StrFmt("080027%02X%02X%02X",
2953
guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]);
2956
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
2958
/* vi: set tabstop=4 shiftwidth=4 expandtab: */