VirtualBox

source: vbox/trunk/src/VBox/Main/HostImpl.cpp@ 31388

Last change on this file since 31388 was 31388, checked in by vboxsync, 15 years ago

Main: locking optimization

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 94.9 KB
Line 
1/* $Id: HostImpl.cpp 31388 2010-08-05 10:26:18Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation: Host
4 */
5
6/*
7 * Copyright (C) 2006-2010 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#define __STDC_LIMIT_MACROS
19#define __STDC_CONSTANT_MACROS
20
21// for some reason Windows burns in sdk\...\winsock.h if this isn't included first
22#include "VBox/com/ptr.h"
23
24#include "HostImpl.h"
25
26#ifdef VBOX_WITH_USB
27# include "HostUSBDeviceImpl.h"
28# include "USBDeviceFilterImpl.h"
29# include "USBProxyService.h"
30#endif // VBOX_WITH_USB
31
32#include "HostNetworkInterfaceImpl.h"
33#include "MachineImpl.h"
34#include "AutoCaller.h"
35#include "Logging.h"
36#include "Performance.h"
37
38#include "MediumImpl.h"
39#include "HostPower.h"
40
41#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
42# include <HostHardwareLinux.h>
43#endif
44
45#ifdef VBOX_WITH_RESOURCE_USAGE_API
46# include "PerformanceImpl.h"
47#endif /* VBOX_WITH_RESOURCE_USAGE_API */
48
49#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
50# include <VBox/WinNetConfig.h>
51#endif /* #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
52
53#ifdef RT_OS_LINUX
54# include <sys/ioctl.h>
55# include <errno.h>
56# include <net/if.h>
57# include <net/if_arp.h>
58#endif /* RT_OS_LINUX */
59
60#ifdef RT_OS_SOLARIS
61# include <fcntl.h>
62# include <unistd.h>
63# include <stropts.h>
64# include <errno.h>
65# include <limits.h>
66# include <stdio.h>
67# include <libdevinfo.h>
68# include <sys/mkdev.h>
69# include <sys/scsi/generic/inquiry.h>
70# include <net/if.h>
71# include <sys/socket.h>
72# include <sys/sockio.h>
73# include <net/if_arp.h>
74# include <net/if.h>
75# include <sys/types.h>
76# include <sys/stat.h>
77# include <sys/cdio.h>
78# include <sys/dkio.h>
79# include <sys/mnttab.h>
80# include <sys/mntent.h>
81/* Dynamic loading of libhal on Solaris hosts */
82# ifdef VBOX_USE_LIBHAL
83# include "vbox-libhal.h"
84extern "C" char *getfullrawname(char *);
85# endif
86# include "solaris/DynLoadLibSolaris.h"
87
88/**
89 * Solaris DVD drive list as returned by getDVDInfoFromDevTree().
90 */
91typedef struct SOLARISDVD
92{
93 struct SOLARISDVD *pNext;
94 char szDescription[512];
95 char szRawDiskPath[PATH_MAX];
96} SOLARISDVD;
97/** Pointer to a Solaris DVD descriptor. */
98typedef SOLARISDVD *PSOLARISDVD;
99
100#endif /* RT_OS_SOLARIS */
101
102#ifdef RT_OS_WINDOWS
103# define _WIN32_DCOM
104# include <windows.h>
105# include <shellapi.h>
106# define INITGUID
107# include <guiddef.h>
108# include <devguid.h>
109# include <objbase.h>
110//# include <setupapi.h>
111# include <shlobj.h>
112# include <cfgmgr32.h>
113
114#endif /* RT_OS_WINDOWS */
115
116#ifdef RT_OS_DARWIN
117# include "darwin/iokit.h"
118#endif
119
120#ifdef VBOX_WITH_CROGL
121extern bool is3DAccelerationSupported();
122#endif /* VBOX_WITH_CROGL */
123
124#include <iprt/asm-amd64-x86.h>
125#include <iprt/string.h>
126#include <iprt/mp.h>
127#include <iprt/time.h>
128#include <iprt/param.h>
129#include <iprt/env.h>
130#include <iprt/mem.h>
131#include <iprt/system.h>
132#ifdef RT_OS_SOLARIS
133# include <iprt/path.h>
134# include <iprt/ctype.h>
135#endif
136#ifdef VBOX_WITH_HOSTNETIF_API
137# include "netif.h"
138#endif
139
140/* XXX Solaris: definitions in /usr/include/sys/regset.h clash with hwacc_svm.h */
141#undef DS
142#undef ES
143#undef CS
144#undef SS
145#undef FS
146#undef GS
147
148#include <VBox/usb.h>
149#include <VBox/x86.h>
150#include <VBox/hwacc_svm.h>
151#include <VBox/err.h>
152#include <VBox/settings.h>
153#include <VBox/sup.h>
154
155#include "VBox/com/MultiResult.h"
156
157#include <stdio.h>
158
159#include <algorithm>
160
161////////////////////////////////////////////////////////////////////////////////
162//
163// Host private data definition
164//
165////////////////////////////////////////////////////////////////////////////////
166
167struct Host::Data
168{
169 Data()
170 :
171#ifdef VBOX_WITH_USB
172 usbListsLock(LOCKCLASS_USBLIST),
173#endif
174 drivesLock(LOCKCLASS_LISTOFMEDIA),
175 fDVDDrivesListBuilt(false),
176 fFloppyDrivesListBuilt(false)
177 {};
178
179 VirtualBox *pParent;
180
181#ifdef VBOX_WITH_USB
182 WriteLockHandle usbListsLock; // protects the below two lists
183
184 USBDeviceFilterList llChildren; // all USB device filters
185 USBDeviceFilterList llUSBDeviceFilters; // USB device filters in use by the USB proxy service
186
187 /** Pointer to the USBProxyService object. */
188 USBProxyService *pUSBProxyService;
189#endif /* VBOX_WITH_USB */
190
191 // list of host drives; lazily created by getDVDDrives() and getFloppyDrives()
192 WriteLockHandle drivesLock; // protects the below two lists and the bools
193 MediaList llDVDDrives,
194 llFloppyDrives;
195 bool fDVDDrivesListBuilt,
196 fFloppyDrivesListBuilt;
197
198#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
199 /** Object with information about host drives */
200 VBoxMainDriveInfo hostDrives;
201#endif
202 /* Features that can be queried with GetProcessorFeature */
203 BOOL fVTSupported,
204 fLongModeSupported,
205 fPAESupported,
206 fNestedPagingSupported;
207
208 /* 3D hardware acceleration supported? */
209 BOOL f3DAccelerationSupported;
210
211 HostPowerService *pHostPowerService;
212};
213
214
215////////////////////////////////////////////////////////////////////////////////
216//
217// Constructor / destructor
218//
219////////////////////////////////////////////////////////////////////////////////
220
221HRESULT Host::FinalConstruct()
222{
223 return S_OK;
224}
225
226void Host::FinalRelease()
227{
228 uninit();
229}
230
231/**
232 * Initializes the host object.
233 *
234 * @param aParent VirtualBox parent object.
235 */
236HRESULT Host::init(VirtualBox *aParent)
237{
238 LogFlowThisFunc(("aParent=%p\n", aParent));
239
240 /* Enclose the state transition NotReady->InInit->Ready */
241 AutoInitSpan autoInitSpan(this);
242 AssertReturn(autoInitSpan.isOk(), E_FAIL);
243
244 m = new Data();
245
246 m->pParent = aParent;
247
248#ifdef VBOX_WITH_USB
249 /*
250 * Create and initialize the USB Proxy Service.
251 */
252# if defined (RT_OS_DARWIN)
253 m->pUSBProxyService = new USBProxyServiceDarwin(this);
254# elif defined (RT_OS_LINUX)
255 m->pUSBProxyService = new USBProxyServiceLinux(this);
256# elif defined (RT_OS_OS2)
257 m->pUSBProxyService = new USBProxyServiceOs2(this);
258# elif defined (RT_OS_SOLARIS)
259 m->pUSBProxyService = new USBProxyServiceSolaris(this);
260# elif defined (RT_OS_WINDOWS)
261 m->pUSBProxyService = new USBProxyServiceWindows(this);
262# elif defined (RT_OS_FREEBSD)
263 m->pUSBProxyService = new USBProxyServiceFreeBSD(this);
264# else
265 m->pUSBProxyService = new USBProxyService(this);
266# endif
267 HRESULT hrc = m->pUSBProxyService->init();
268 AssertComRCReturn(hrc, hrc);
269#endif /* VBOX_WITH_USB */
270
271#ifdef VBOX_WITH_RESOURCE_USAGE_API
272 registerMetrics(aParent->performanceCollector());
273#endif /* VBOX_WITH_RESOURCE_USAGE_API */
274
275#if defined (RT_OS_WINDOWS)
276 m->pHostPowerService = new HostPowerServiceWin(m->pParent);
277#elif defined (RT_OS_DARWIN)
278 m->pHostPowerService = new HostPowerServiceDarwin(m->pParent);
279#else
280 m->pHostPowerService = new HostPowerService(m->pParent);
281#endif
282
283 /* Cache the features reported by GetProcessorFeature. */
284 m->fVTSupported = false;
285 m->fLongModeSupported = false;
286 m->fPAESupported = false;
287 m->fNestedPagingSupported = false;
288
289 if (ASMHasCpuId())
290 {
291 uint32_t u32FeaturesECX;
292 uint32_t u32Dummy;
293 uint32_t u32FeaturesEDX;
294 uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX, u32AMDFeatureEDX, u32AMDFeatureECX;
295
296 ASMCpuId(0, &u32Dummy, &u32VendorEBX, &u32VendorECX, &u32VendorEDX);
297 ASMCpuId(1, &u32Dummy, &u32Dummy, &u32FeaturesECX, &u32FeaturesEDX);
298 /* Query AMD features. */
299 ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &u32AMDFeatureECX, &u32AMDFeatureEDX);
300
301 m->fLongModeSupported = !!(u32AMDFeatureEDX & X86_CPUID_AMD_FEATURE_EDX_LONG_MODE);
302 m->fPAESupported = !!(u32FeaturesEDX & X86_CPUID_FEATURE_EDX_PAE);
303
304 if ( u32VendorEBX == X86_CPUID_VENDOR_INTEL_EBX
305 && u32VendorECX == X86_CPUID_VENDOR_INTEL_ECX
306 && u32VendorEDX == X86_CPUID_VENDOR_INTEL_EDX
307 )
308 {
309 if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
310 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
311 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
312 )
313 {
314 int rc = SUPR3QueryVTxSupported();
315 if (RT_SUCCESS(rc))
316 m->fVTSupported = true;
317 }
318 }
319 else
320 if ( u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX
321 && u32VendorECX == X86_CPUID_VENDOR_AMD_ECX
322 && u32VendorEDX == X86_CPUID_VENDOR_AMD_EDX
323 )
324 {
325 if ( (u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
326 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
327 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
328 )
329 {
330 uint32_t u32SVMFeatureEDX;
331
332 m->fVTSupported = true;
333
334 /* Query AMD features. */
335 ASMCpuId(0x8000000A, &u32Dummy, &u32Dummy, &u32Dummy, &u32SVMFeatureEDX);
336 if (u32SVMFeatureEDX & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
337 m->fNestedPagingSupported = true;
338 }
339 }
340 }
341
342#if 0 /* needs testing */
343 if (m->fVTSupported)
344 {
345 uint32_t u32Caps = 0;
346
347 int rc = SUPR3QueryVTCaps(&u32Caps);
348 if (RT_SUCCESS(rc))
349 {
350 if (u32Caps & SUPVTCAPS_NESTED_PAGING)
351 m->fNestedPagingSupported = true;
352 }
353 /* else @todo; report BIOS trouble in some way. */
354 }
355#endif
356
357 /* Test for 3D hardware acceleration support */
358 m->f3DAccelerationSupported = false;
359
360#ifdef VBOX_WITH_CROGL
361 m->f3DAccelerationSupported = is3DAccelerationSupported();
362#endif /* VBOX_WITH_CROGL */
363
364 /* Confirm a successful initialization */
365 autoInitSpan.setSucceeded();
366
367 return S_OK;
368}
369
370/**
371 * Uninitializes the host object and sets the ready flag to FALSE.
372 * Called either from FinalRelease() or by the parent when it gets destroyed.
373 */
374void Host::uninit()
375{
376 LogFlowThisFunc(("\n"));
377
378 /* Enclose the state transition Ready->InUninit->NotReady */
379 AutoUninitSpan autoUninitSpan(this);
380 if (autoUninitSpan.uninitDone())
381 return;
382
383#ifdef VBOX_WITH_RESOURCE_USAGE_API
384 unregisterMetrics (m->pParent->performanceCollector());
385#endif /* VBOX_WITH_RESOURCE_USAGE_API */
386
387#ifdef VBOX_WITH_USB
388 /* wait for USB proxy service to terminate before we uninit all USB
389 * devices */
390 LogFlowThisFunc(("Stopping USB proxy service...\n"));
391 delete m->pUSBProxyService;
392 m->pUSBProxyService = NULL;
393 LogFlowThisFunc(("Done stopping USB proxy service.\n"));
394#endif
395
396 delete m->pHostPowerService;
397
398#ifdef VBOX_WITH_USB
399 /* uninit all USB device filters still referenced by clients
400 * Note! HostUSBDeviceFilter::uninit() will modify llChildren. */
401 while (!m->llChildren.empty())
402 {
403 ComObjPtr<HostUSBDeviceFilter> &pChild = m->llChildren.front();
404 pChild->uninit();
405 }
406
407 m->llUSBDeviceFilters.clear();
408#endif
409
410 delete m;
411 m = NULL;
412}
413
414////////////////////////////////////////////////////////////////////////////////
415//
416// ISnapshot public methods
417//
418////////////////////////////////////////////////////////////////////////////////
419
420/**
421 * Returns a list of host DVD drives.
422 *
423 * @returns COM status code
424 * @param drives address of result pointer
425 */
426STDMETHODIMP Host::COMGETTER(DVDDrives)(ComSafeArrayOut(IMedium *, aDrives))
427{
428 CheckComArgOutSafeArrayPointerValid(aDrives);
429
430 AutoCaller autoCaller(this);
431 if (FAILED(autoCaller.rc())) return autoCaller.rc();
432
433 AutoWriteLock alock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
434
435 MediaList *pList;
436 HRESULT rc = getDrives(DeviceType_DVD, true /* fRefresh */, pList);
437 if (SUCCEEDED(rc))
438 {
439 SafeIfaceArray<IMedium> array(*pList);
440 array.detachTo(ComSafeArrayOutArg(aDrives));
441 }
442
443 return rc;
444}
445
446/**
447 * Returns a list of host floppy drives.
448 *
449 * @returns COM status code
450 * @param drives address of result pointer
451 */
452STDMETHODIMP Host::COMGETTER(FloppyDrives)(ComSafeArrayOut(IMedium *, aDrives))
453{
454 CheckComArgOutPointerValid(aDrives);
455
456 AutoCaller autoCaller(this);
457 if (FAILED(autoCaller.rc())) return autoCaller.rc();
458
459 AutoWriteLock alock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
460
461 MediaList *pList;
462 HRESULT rc = getDrives(DeviceType_Floppy, true /* fRefresh */, pList);
463 if (SUCCEEDED(rc))
464 {
465 SafeIfaceArray<IMedium> collection(*pList);
466 collection.detachTo(ComSafeArrayOutArg(aDrives));
467 }
468
469 return rc;
470}
471
472
473#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
474# define VBOX_APP_NAME L"VirtualBox"
475
476static int vboxNetWinAddComponent(std::list< ComObjPtr<HostNetworkInterface> > *pPist,
477 INetCfgComponent *pncc)
478{
479 LPWSTR lpszName;
480 GUID IfGuid;
481 HRESULT hr;
482 int rc = VERR_GENERAL_FAILURE;
483
484 hr = pncc->GetDisplayName( &lpszName );
485 Assert(hr == S_OK);
486 if (hr == S_OK)
487 {
488 Bstr name((CBSTR)lpszName);
489
490 hr = pncc->GetInstanceGuid(&IfGuid);
491 Assert(hr == S_OK);
492 if (hr == S_OK)
493 {
494 /* create a new object and add it to the list */
495 ComObjPtr<HostNetworkInterface> iface;
496 iface.createObject();
497 /* remove the curly bracket at the end */
498 if (SUCCEEDED(iface->init (name, Guid (IfGuid), HostNetworkInterfaceType_Bridged)))
499 {
500// iface->setVirtualBox(m->pParent);
501 pPist->push_back(iface);
502 rc = VINF_SUCCESS;
503 }
504 else
505 {
506 Assert(0);
507 }
508 }
509 CoTaskMemFree(lpszName);
510 }
511
512 return rc;
513}
514#endif /* defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
515
516/**
517 * Returns a list of host network interfaces.
518 *
519 * @returns COM status code
520 * @param drives address of result pointer
521 */
522STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInterface*, aNetworkInterfaces))
523{
524#if defined(RT_OS_WINDOWS) || defined(VBOX_WITH_NETFLT) /*|| defined(RT_OS_OS2)*/
525 if (ComSafeArrayOutIsNull(aNetworkInterfaces))
526 return E_POINTER;
527
528 AutoCaller autoCaller(this);
529 if (FAILED(autoCaller.rc())) return autoCaller.rc();
530
531 std::list<ComObjPtr<HostNetworkInterface> > list;
532
533# ifdef VBOX_WITH_HOSTNETIF_API
534 int rc = NetIfList(list);
535 if (rc)
536 {
537 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
538 }
539# else
540
541# if defined(RT_OS_DARWIN)
542 PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
543 while (pEtherNICs)
544 {
545 ComObjPtr<HostNetworkInterface> IfObj;
546 IfObj.createObject();
547 if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), Guid(pEtherNICs->Uuid), HostNetworkInterfaceType_Bridged)))
548 list.push_back(IfObj);
549
550 /* next, free current */
551 void *pvFree = pEtherNICs;
552 pEtherNICs = pEtherNICs->pNext;
553 RTMemFree(pvFree);
554 }
555
556# elif defined RT_OS_WINDOWS
557# ifndef VBOX_WITH_NETFLT
558 hr = E_NOTIMPL;
559# else /* # if defined VBOX_WITH_NETFLT */
560 INetCfg *pNc;
561 INetCfgComponent *pMpNcc;
562 INetCfgComponent *pTcpIpNcc;
563 LPWSTR lpszApp;
564 HRESULT hr;
565 IEnumNetCfgBindingPath *pEnumBp;
566 INetCfgBindingPath *pBp;
567 IEnumNetCfgBindingInterface *pEnumBi;
568 INetCfgBindingInterface *pBi;
569
570 /* we are using the INetCfg API for getting the list of miniports */
571 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
572 VBOX_APP_NAME,
573 &pNc,
574 &lpszApp );
575 Assert(hr == S_OK);
576 if (hr == S_OK)
577 {
578# ifdef VBOX_NETFLT_ONDEMAND_BIND
579 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
580 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
581# else
582 /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
583 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
584# ifndef VBOX_WITH_HARDENING
585 if (hr != S_OK)
586 {
587 /* TODO: try to install the netflt from here */
588 }
589# endif
590
591# endif
592
593 if (hr == S_OK)
594 {
595 hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
596 Assert(hr == S_OK);
597 if ( hr == S_OK )
598 {
599 hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
600 Assert(hr == S_OK || hr == S_FALSE);
601 while( hr == S_OK )
602 {
603 /* S_OK == enabled, S_FALSE == disabled */
604 if (pBp->IsEnabled() == S_OK)
605 {
606 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
607 Assert(hr == S_OK);
608 if ( hr == S_OK )
609 {
610 hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
611 Assert(hr == S_OK);
612 while(hr == S_OK)
613 {
614 hr = pBi->GetLowerComponent( &pMpNcc );
615 Assert(hr == S_OK);
616 if (hr == S_OK)
617 {
618 ULONG uComponentStatus;
619 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
620 Assert(hr == S_OK);
621 if (hr == S_OK)
622 {
623 if (uComponentStatus == 0)
624 {
625 vboxNetWinAddComponent(&list, pMpNcc);
626 }
627 }
628 VBoxNetCfgWinReleaseRef( pMpNcc );
629 }
630 VBoxNetCfgWinReleaseRef(pBi);
631
632 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
633 }
634 VBoxNetCfgWinReleaseRef(pEnumBi);
635 }
636 }
637 VBoxNetCfgWinReleaseRef(pBp);
638
639 hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
640 }
641 VBoxNetCfgWinReleaseRef(pEnumBp);
642 }
643 VBoxNetCfgWinReleaseRef(pTcpIpNcc);
644 }
645 else
646 {
647 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
648 }
649
650 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
651 }
652# endif /* # if defined VBOX_WITH_NETFLT */
653
654
655# elif defined RT_OS_LINUX
656 int sock = socket(AF_INET, SOCK_DGRAM, 0);
657 if (sock >= 0)
658 {
659 char pBuffer[2048];
660 struct ifconf ifConf;
661 ifConf.ifc_len = sizeof(pBuffer);
662 ifConf.ifc_buf = pBuffer;
663 if (ioctl(sock, SIOCGIFCONF, &ifConf) >= 0)
664 {
665 for (struct ifreq *pReq = ifConf.ifc_req; (char*)pReq < pBuffer + ifConf.ifc_len; pReq++)
666 {
667 if (ioctl(sock, SIOCGIFHWADDR, pReq) >= 0)
668 {
669 if (pReq->ifr_hwaddr.sa_family == ARPHRD_ETHER)
670 {
671 RTUUID uuid;
672 Assert(sizeof(uuid) <= sizeof(*pReq));
673 memcpy(&uuid, pReq, sizeof(uuid));
674
675 ComObjPtr<HostNetworkInterface> IfObj;
676 IfObj.createObject();
677 if (SUCCEEDED(IfObj->init(Bstr(pReq->ifr_name), Guid(uuid), HostNetworkInterfaceType_Bridged)))
678 list.push_back(IfObj);
679 }
680 }
681 }
682 }
683 close(sock);
684 }
685# endif /* RT_OS_LINUX */
686# endif
687
688 std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
689 for (it = list.begin(); it != list.end(); ++it)
690 {
691 (*it)->setVirtualBox(m->pParent);
692 }
693
694 SafeIfaceArray<IHostNetworkInterface> networkInterfaces (list);
695 networkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
696
697 return S_OK;
698
699#else
700 /* Not implemented / supported on this platform. */
701 ReturnComNotImplemented();
702#endif
703}
704
705STDMETHODIMP Host::COMGETTER(USBDevices)(ComSafeArrayOut(IHostUSBDevice*, aUSBDevices))
706{
707#ifdef VBOX_WITH_USB
708 CheckComArgOutSafeArrayPointerValid(aUSBDevices);
709
710 AutoCaller autoCaller(this);
711 if (FAILED(autoCaller.rc())) return autoCaller.rc();
712
713 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
714
715 MultiResult rc = checkUSBProxyService();
716 if (FAILED(rc)) return rc;
717
718 return m->pUSBProxyService->getDeviceCollection(ComSafeArrayOutArg(aUSBDevices));
719
720#else
721 /* Note: The GUI depends on this method returning E_NOTIMPL with no
722 * extended error info to indicate that USB is simply not available
723 * (w/o treating it as a failure), for example, as in OSE. */
724 NOREF(aUSBDevices);
725# ifndef RT_OS_WINDOWS
726 NOREF(aUSBDevicesSize);
727# endif
728 ReturnComNotImplemented();
729#endif
730}
731
732STDMETHODIMP Host::COMGETTER(USBDeviceFilters)(ComSafeArrayOut(IHostUSBDeviceFilter*, aUSBDeviceFilters))
733{
734#ifdef VBOX_WITH_USB
735 CheckComArgOutSafeArrayPointerValid(aUSBDeviceFilters);
736
737 AutoCaller autoCaller(this);
738 if (FAILED(autoCaller.rc())) return autoCaller.rc();
739
740 AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
741
742 MultiResult rc = checkUSBProxyService();
743 if (FAILED(rc)) return rc;
744
745 SafeIfaceArray<IHostUSBDeviceFilter> collection(m->llUSBDeviceFilters);
746 collection.detachTo(ComSafeArrayOutArg(aUSBDeviceFilters));
747
748 return rc;
749#else
750 /* Note: The GUI depends on this method returning E_NOTIMPL with no
751 * extended error info to indicate that USB is simply not available
752 * (w/o treating it as a failure), for example, as in OSE. */
753 NOREF(aUSBDeviceFilters);
754# ifndef RT_OS_WINDOWS
755 NOREF(aUSBDeviceFiltersSize);
756# endif
757 ReturnComNotImplemented();
758#endif
759}
760
761/**
762 * Returns the number of installed logical processors
763 *
764 * @returns COM status code
765 * @param count address of result variable
766 */
767STDMETHODIMP Host::COMGETTER(ProcessorCount)(ULONG *aCount)
768{
769 CheckComArgOutPointerValid(aCount);
770 // no locking required
771
772 *aCount = RTMpGetPresentCount();
773 return S_OK;
774}
775
776/**
777 * Returns the number of online logical processors
778 *
779 * @returns COM status code
780 * @param count address of result variable
781 */
782STDMETHODIMP Host::COMGETTER(ProcessorOnlineCount)(ULONG *aCount)
783{
784 CheckComArgOutPointerValid(aCount);
785 // no locking required
786
787 *aCount = RTMpGetOnlineCount();
788 return S_OK;
789}
790
791/**
792 * Returns the number of installed physical processor cores.
793 *
794 * @returns COM status code
795 * @param count address of result variable
796 */
797STDMETHODIMP Host::COMGETTER(ProcessorCoreCount)(ULONG *aCount)
798{
799 CheckComArgOutPointerValid(aCount);
800 // no locking required
801
802 return E_NOTIMPL;
803}
804
805/**
806 * Returns the (approximate) maximum speed of the given host CPU in MHz
807 *
808 * @returns COM status code
809 * @param cpu id to get info for.
810 * @param speed address of result variable, speed is 0 if unknown or aCpuId is invalid.
811 */
812STDMETHODIMP Host::GetProcessorSpeed(ULONG aCpuId, ULONG *aSpeed)
813{
814 CheckComArgOutPointerValid(aSpeed);
815 // no locking required
816
817 *aSpeed = RTMpGetMaxFrequency(aCpuId);
818 return S_OK;
819}
820
821/**
822 * Returns a description string for the host CPU
823 *
824 * @returns COM status code
825 * @param cpu id to get info for.
826 * @param description address of result variable, empty string if not known or aCpuId is invalid.
827 */
828STDMETHODIMP Host::GetProcessorDescription(ULONG aCpuId, BSTR *aDescription)
829{
830 CheckComArgOutPointerValid(aDescription);
831 // no locking required
832
833 char szCPUModel[80];
834 int vrc = RTMpGetDescription(aCpuId, szCPUModel, sizeof(szCPUModel));
835 if (RT_FAILURE(vrc))
836 return E_FAIL; /** @todo error reporting? */
837 Bstr (szCPUModel).cloneTo(aDescription);
838 return S_OK;
839}
840
841/**
842 * Returns whether a host processor feature is supported or not
843 *
844 * @returns COM status code
845 * @param Feature to query.
846 * @param address of supported bool result variable
847 */
848STDMETHODIMP Host::GetProcessorFeature(ProcessorFeature_T aFeature, BOOL *aSupported)
849{
850 CheckComArgOutPointerValid(aSupported);
851 AutoCaller autoCaller(this);
852 if (FAILED(autoCaller.rc())) return autoCaller.rc();
853
854 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
855
856 switch (aFeature)
857 {
858 case ProcessorFeature_HWVirtEx:
859 *aSupported = m->fVTSupported;
860 break;
861
862 case ProcessorFeature_PAE:
863 *aSupported = m->fPAESupported;
864 break;
865
866 case ProcessorFeature_LongMode:
867 *aSupported = m->fLongModeSupported;
868 break;
869
870 case ProcessorFeature_NestedPaging:
871 *aSupported = m->fNestedPagingSupported;
872 break;
873
874 default:
875 ReturnComNotImplemented();
876 }
877 return S_OK;
878}
879
880/**
881 * Returns the specific CPUID leaf.
882 *
883 * @returns COM status code
884 * @param aCpuId The CPU number. Mostly ignored.
885 * @param aLeaf The leaf number.
886 * @param aSubLeaf The sub-leaf number.
887 * @param aValEAX Where to return EAX.
888 * @param aValEBX Where to return EBX.
889 * @param aValECX Where to return ECX.
890 * @param aValEDX Where to return EDX.
891 */
892STDMETHODIMP Host::GetProcessorCPUIDLeaf(ULONG aCpuId, ULONG aLeaf, ULONG aSubLeaf,
893 ULONG *aValEAX, ULONG *aValEBX, ULONG *aValECX, ULONG *aValEDX)
894{
895 CheckComArgOutPointerValid(aValEAX);
896 CheckComArgOutPointerValid(aValEBX);
897 CheckComArgOutPointerValid(aValECX);
898 CheckComArgOutPointerValid(aValEDX);
899 // no locking required
900
901 /* Check that the CPU is online. */
902 /** @todo later use RTMpOnSpecific. */
903 if (!RTMpIsCpuOnline(aCpuId))
904 return RTMpIsCpuPresent(aCpuId)
905 ? setError(E_FAIL, tr("CPU no.%u is not present"), aCpuId)
906 : setError(E_FAIL, tr("CPU no.%u is not online"), aCpuId);
907
908 uint32_t uEAX, uEBX, uECX, uEDX;
909 ASMCpuId_Idx_ECX(aLeaf, aSubLeaf, &uEAX, &uEBX, &uECX, &uEDX);
910 *aValEAX = uEAX;
911 *aValEBX = uEBX;
912 *aValECX = uECX;
913 *aValEDX = uEDX;
914
915 return S_OK;
916}
917
918/**
919 * Returns the amount of installed system memory in megabytes
920 *
921 * @returns COM status code
922 * @param size address of result variable
923 */
924STDMETHODIMP Host::COMGETTER(MemorySize)(ULONG *aSize)
925{
926 CheckComArgOutPointerValid(aSize);
927 // no locking required
928
929 /* @todo This is an ugly hack. There must be a function in IPRT for that. */
930 pm::CollectorHAL *hal = pm::createHAL();
931 if (!hal)
932 return E_FAIL;
933 ULONG tmp;
934 int rc = hal->getHostMemoryUsage(aSize, &tmp, &tmp);
935 *aSize /= 1024;
936 delete hal;
937 return rc;
938}
939
940/**
941 * Returns the current system memory free space in megabytes
942 *
943 * @returns COM status code
944 * @param available address of result variable
945 */
946STDMETHODIMP Host::COMGETTER(MemoryAvailable)(ULONG *aAvailable)
947{
948 CheckComArgOutPointerValid(aAvailable);
949 // no locking required
950
951 /* @todo This is an ugly hack. There must be a function in IPRT for that. */
952 pm::CollectorHAL *hal = pm::createHAL();
953 if (!hal)
954 return E_FAIL;
955 ULONG tmp;
956 int rc = hal->getHostMemoryUsage(&tmp, &tmp, aAvailable);
957 *aAvailable /= 1024;
958 delete hal;
959 return rc;
960}
961
962/**
963 * Returns the name string of the host operating system
964 *
965 * @returns COM status code
966 * @param os address of result variable
967 */
968STDMETHODIMP Host::COMGETTER(OperatingSystem)(BSTR *aOs)
969{
970 CheckComArgOutPointerValid(aOs);
971 // no locking required
972
973 char szOSName[80];
974 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szOSName, sizeof(szOSName));
975 if (RT_FAILURE(vrc))
976 return E_FAIL; /** @todo error reporting? */
977 Bstr (szOSName).cloneTo(aOs);
978 return S_OK;
979}
980
981/**
982 * Returns the version string of the host operating system
983 *
984 * @returns COM status code
985 * @param os address of result variable
986 */
987STDMETHODIMP Host::COMGETTER(OSVersion)(BSTR *aVersion)
988{
989 CheckComArgOutPointerValid(aVersion);
990 // no locking required
991
992 /* Get the OS release. Reserve some buffer space for the service pack. */
993 char szOSRelease[128];
994 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szOSRelease, sizeof(szOSRelease) - 32);
995 if (RT_FAILURE(vrc))
996 return E_FAIL; /** @todo error reporting? */
997
998 /* Append the service pack if present. */
999 char szOSServicePack[80];
1000 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szOSServicePack, sizeof(szOSServicePack));
1001 if (RT_FAILURE(vrc))
1002 {
1003 if (vrc != VERR_NOT_SUPPORTED)
1004 return E_FAIL; /** @todo error reporting? */
1005 szOSServicePack[0] = '\0';
1006 }
1007 if (szOSServicePack[0] != '\0')
1008 {
1009 char *psz = strchr(szOSRelease, '\0');
1010 RTStrPrintf(psz, &szOSRelease[sizeof(szOSRelease)] - psz, "sp%s", szOSServicePack);
1011 }
1012
1013 Bstr(szOSRelease).cloneTo(aVersion);
1014 return S_OK;
1015}
1016
1017/**
1018 * Returns the current host time in milliseconds since 1970-01-01 UTC.
1019 *
1020 * @returns COM status code
1021 * @param time address of result variable
1022 */
1023STDMETHODIMP Host::COMGETTER(UTCTime)(LONG64 *aUTCTime)
1024{
1025 CheckComArgOutPointerValid(aUTCTime);
1026 // no locking required
1027
1028 RTTIMESPEC now;
1029 *aUTCTime = RTTimeSpecGetMilli(RTTimeNow(&now));
1030
1031 return S_OK;
1032}
1033
1034STDMETHODIMP Host::COMGETTER(Acceleration3DAvailable)(BOOL *aSupported)
1035{
1036 CheckComArgOutPointerValid(aSupported);
1037 AutoCaller autoCaller(this);
1038 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1039
1040 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1041
1042 *aSupported = m->f3DAccelerationSupported;
1043
1044 return S_OK;
1045}
1046
1047STDMETHODIMP Host::CreateHostOnlyNetworkInterface(IHostNetworkInterface **aHostNetworkInterface,
1048 IProgress **aProgress)
1049{
1050 CheckComArgOutPointerValid(aHostNetworkInterface);
1051 CheckComArgOutPointerValid(aProgress);
1052
1053 AutoCaller autoCaller(this);
1054 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1055
1056 /* No need to lock anything. If there ever will - watch out, the function
1057 * called below grabs the VirtualBox lock. */
1058
1059 int r = NetIfCreateHostOnlyNetworkInterface(m->pParent, aHostNetworkInterface, aProgress);
1060 if (RT_SUCCESS(r))
1061 return S_OK;
1062
1063 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1064}
1065
1066STDMETHODIMP Host::RemoveHostOnlyNetworkInterface(IN_BSTR aId,
1067 IProgress **aProgress)
1068{
1069 CheckComArgOutPointerValid(aProgress);
1070
1071 AutoCaller autoCaller(this);
1072 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1073
1074 /* No need to lock anything, the code below does not touch the state
1075 * of the host object. If that ever changes then check for lock order
1076 * violations with the called functions. */
1077
1078 /* first check whether an interface with the given name already exists */
1079 {
1080 ComPtr<IHostNetworkInterface> iface;
1081 if (FAILED(FindHostNetworkInterfaceById(aId,
1082 iface.asOutParam())))
1083 return setError(VBOX_E_OBJECT_NOT_FOUND,
1084 tr("Host network interface with UUID {%RTuuid} does not exist"),
1085 Guid (aId).raw());
1086 }
1087
1088 int r = NetIfRemoveHostOnlyNetworkInterface(m->pParent, Guid(aId), aProgress);
1089 if (RT_SUCCESS(r))
1090 return S_OK;
1091
1092 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1093}
1094
1095STDMETHODIMP Host::CreateUSBDeviceFilter(IN_BSTR aName,
1096 IHostUSBDeviceFilter **aFilter)
1097{
1098#ifdef VBOX_WITH_USB
1099 CheckComArgStrNotEmptyOrNull(aName);
1100 CheckComArgOutPointerValid(aFilter);
1101
1102 AutoCaller autoCaller(this);
1103 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1104
1105 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1106
1107 ComObjPtr<HostUSBDeviceFilter> filter;
1108 filter.createObject();
1109 HRESULT rc = filter->init(this, aName);
1110 ComAssertComRCRet(rc, rc);
1111 rc = filter.queryInterfaceTo(aFilter);
1112 AssertComRCReturn(rc, rc);
1113 return S_OK;
1114#else
1115 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1116 * extended error info to indicate that USB is simply not available
1117 * (w/o treating it as a failure), for example, as in OSE. */
1118 NOREF(aName);
1119 NOREF(aFilter);
1120 ReturnComNotImplemented();
1121#endif
1122}
1123
1124STDMETHODIMP Host::InsertUSBDeviceFilter(ULONG aPosition,
1125 IHostUSBDeviceFilter *aFilter)
1126{
1127#ifdef VBOX_WITH_USB
1128 CheckComArgNotNull(aFilter);
1129
1130 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1131 AutoCaller autoCaller(this);
1132 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1133
1134 AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1135
1136 MultiResult rc = checkUSBProxyService();
1137 if (FAILED(rc)) return rc;
1138
1139 ComObjPtr<HostUSBDeviceFilter> pFilter;
1140 for (USBDeviceFilterList::iterator it = m->llChildren.begin();
1141 it != m->llChildren.end();
1142 ++it)
1143 {
1144 if (*it == aFilter)
1145 {
1146 pFilter = *it;
1147 break;
1148 }
1149 }
1150 if (pFilter.isNull())
1151 return setError(VBOX_E_INVALID_OBJECT_STATE,
1152 tr("The given USB device filter is not created within this VirtualBox instance"));
1153
1154 if (pFilter->mInList)
1155 return setError(E_INVALIDARG,
1156 tr("The given USB device filter is already in the list"));
1157
1158 /* iterate to the position... */
1159 USBDeviceFilterList::iterator itPos = m->llUSBDeviceFilters.begin();
1160 std::advance(itPos, aPosition);
1161 /* ...and insert */
1162 m->llUSBDeviceFilters.insert(itPos, pFilter);
1163 pFilter->mInList = true;
1164
1165 /* notify the proxy (only when the filter is active) */
1166 if ( m->pUSBProxyService->isActive()
1167 && pFilter->getData().mActive)
1168 {
1169 ComAssertRet(pFilter->getId() == NULL, E_FAIL);
1170 pFilter->getId() = m->pUSBProxyService->insertFilter(&pFilter->getData().mUSBFilter);
1171 }
1172
1173 // save the global settings; for that we should hold only the VirtualBox lock
1174 alock.release();
1175 AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1176 return rc = m->pParent->saveSettings();
1177#else
1178 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1179 * extended error info to indicate that USB is simply not available
1180 * (w/o treating it as a failure), for example, as in OSE. */
1181 NOREF(aPosition);
1182 NOREF(aFilter);
1183 ReturnComNotImplemented();
1184#endif
1185}
1186
1187STDMETHODIMP Host::RemoveUSBDeviceFilter(ULONG aPosition)
1188{
1189#ifdef VBOX_WITH_USB
1190
1191 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1192 AutoCaller autoCaller(this);
1193 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1194
1195 AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1196
1197 MultiResult rc = checkUSBProxyService();
1198 if (FAILED(rc)) return rc;
1199
1200 if (!m->llUSBDeviceFilters.size())
1201 return setError(E_INVALIDARG,
1202 tr("The USB device filter list is empty"));
1203
1204 if (aPosition >= m->llUSBDeviceFilters.size())
1205 return setError(E_INVALIDARG,
1206 tr("Invalid position: %lu (must be in range [0, %lu])"),
1207 aPosition, m->llUSBDeviceFilters.size() - 1);
1208
1209 ComObjPtr<HostUSBDeviceFilter> filter;
1210 {
1211 /* iterate to the position... */
1212 USBDeviceFilterList::iterator it = m->llUSBDeviceFilters.begin();
1213 std::advance (it, aPosition);
1214 /* ...get an element from there... */
1215 filter = *it;
1216 /* ...and remove */
1217 filter->mInList = false;
1218 m->llUSBDeviceFilters.erase(it);
1219 }
1220
1221 /* notify the proxy (only when the filter is active) */
1222 if (m->pUSBProxyService->isActive() && filter->getData().mActive)
1223 {
1224 ComAssertRet(filter->getId() != NULL, E_FAIL);
1225 m->pUSBProxyService->removeFilter(filter->getId());
1226 filter->getId() = NULL;
1227 }
1228
1229 // save the global settings; for that we should hold only the VirtualBox lock
1230 alock.release();
1231 AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1232 return rc = m->pParent->saveSettings();
1233#else
1234 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1235 * extended error info to indicate that USB is simply not available
1236 * (w/o treating it as a failure), for example, as in OSE. */
1237 NOREF(aPosition);
1238 ReturnComNotImplemented();
1239#endif
1240}
1241
1242STDMETHODIMP Host::FindHostDVDDrive(IN_BSTR aName, IMedium **aDrive)
1243{
1244 CheckComArgStrNotEmptyOrNull(aName);
1245 CheckComArgOutPointerValid(aDrive);
1246
1247 *aDrive = NULL;
1248
1249 SafeIfaceArray<IMedium> drivevec;
1250 HRESULT rc = COMGETTER(DVDDrives)(ComSafeArrayAsOutParam(drivevec));
1251 if (FAILED(rc)) return rc;
1252
1253 for (size_t i = 0; i < drivevec.size(); ++i)
1254 {
1255 ComPtr<IMedium> drive = drivevec[i];
1256 Bstr name, location;
1257 rc = drive->COMGETTER(Name)(name.asOutParam());
1258 if (FAILED(rc)) return rc;
1259 rc = drive->COMGETTER(Location)(location.asOutParam());
1260 if (FAILED(rc)) return rc;
1261 if (name == aName || location == aName)
1262 return drive.queryInterfaceTo(aDrive);
1263 }
1264
1265 return setError(VBOX_E_OBJECT_NOT_FOUND,
1266 Medium::tr("The host DVD drive named '%ls' could not be found"), aName);
1267}
1268
1269STDMETHODIMP Host::FindHostFloppyDrive(IN_BSTR aName, IMedium **aDrive)
1270{
1271 CheckComArgStrNotEmptyOrNull(aName);
1272 CheckComArgOutPointerValid(aDrive);
1273
1274 *aDrive = NULL;
1275
1276 SafeIfaceArray<IMedium> drivevec;
1277 HRESULT rc = COMGETTER(FloppyDrives)(ComSafeArrayAsOutParam(drivevec));
1278 if (FAILED(rc)) return rc;
1279
1280 for (size_t i = 0; i < drivevec.size(); ++i)
1281 {
1282 ComPtr<IMedium> drive = drivevec[i];
1283 Bstr name;
1284 rc = drive->COMGETTER(Name)(name.asOutParam());
1285 if (FAILED(rc)) return rc;
1286 if (name == aName)
1287 return drive.queryInterfaceTo(aDrive);
1288 }
1289
1290 return setError(VBOX_E_OBJECT_NOT_FOUND,
1291 Medium::tr("The host floppy drive named '%ls' could not be found"), aName);
1292}
1293
1294STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInterface **networkInterface)
1295{
1296#ifndef VBOX_WITH_HOSTNETIF_API
1297 return E_NOTIMPL;
1298#else
1299 if (!name)
1300 return E_INVALIDARG;
1301 if (!networkInterface)
1302 return E_POINTER;
1303
1304 *networkInterface = NULL;
1305 ComObjPtr<HostNetworkInterface> found;
1306 std::list <ComObjPtr<HostNetworkInterface> > list;
1307 int rc = NetIfList(list);
1308 if (RT_FAILURE(rc))
1309 {
1310 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
1311 return E_FAIL;
1312 }
1313 std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
1314 for (it = list.begin(); it != list.end(); ++it)
1315 {
1316 Bstr n;
1317 (*it)->COMGETTER(Name) (n.asOutParam());
1318 if (n == name)
1319 found = *it;
1320 }
1321
1322 if (!found)
1323 return setError(E_INVALIDARG,
1324 HostNetworkInterface::tr("The host network interface with the given name could not be found"));
1325
1326 found->setVirtualBox(m->pParent);
1327
1328 return found.queryInterfaceTo(networkInterface);
1329#endif
1330}
1331
1332STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_BSTR id, IHostNetworkInterface **networkInterface)
1333{
1334#ifndef VBOX_WITH_HOSTNETIF_API
1335 return E_NOTIMPL;
1336#else
1337 if (Guid(id).isEmpty())
1338 return E_INVALIDARG;
1339 if (!networkInterface)
1340 return E_POINTER;
1341
1342 *networkInterface = NULL;
1343 ComObjPtr<HostNetworkInterface> found;
1344 std::list <ComObjPtr<HostNetworkInterface> > list;
1345 int rc = NetIfList(list);
1346 if (RT_FAILURE(rc))
1347 {
1348 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
1349 return E_FAIL;
1350 }
1351 std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
1352 for (it = list.begin(); it != list.end(); ++it)
1353 {
1354 Bstr g;
1355 (*it)->COMGETTER(Id) (g.asOutParam());
1356 if (g == id)
1357 found = *it;
1358 }
1359
1360 if (!found)
1361 return setError(E_INVALIDARG,
1362 HostNetworkInterface::tr("The host network interface with the given GUID could not be found"));
1363
1364 found->setVirtualBox(m->pParent);
1365
1366 return found.queryInterfaceTo(networkInterface);
1367#endif
1368}
1369
1370STDMETHODIMP Host::FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_T type,
1371 ComSafeArrayOut(IHostNetworkInterface *, aNetworkInterfaces))
1372{
1373 std::list <ComObjPtr<HostNetworkInterface> > allList;
1374 int rc = NetIfList(allList);
1375 if (RT_FAILURE(rc))
1376 return E_FAIL;
1377
1378 std::list <ComObjPtr<HostNetworkInterface> > resultList;
1379
1380 std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
1381 for (it = allList.begin(); it != allList.end(); ++it)
1382 {
1383 HostNetworkInterfaceType_T t;
1384 HRESULT hr = (*it)->COMGETTER(InterfaceType)(&t);
1385 if (FAILED(hr))
1386 return hr;
1387
1388 if (t == type)
1389 {
1390 (*it)->setVirtualBox(m->pParent);
1391 resultList.push_back (*it);
1392 }
1393 }
1394
1395 SafeIfaceArray<IHostNetworkInterface> filteredNetworkInterfaces (resultList);
1396 filteredNetworkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
1397
1398 return S_OK;
1399}
1400
1401STDMETHODIMP Host::FindUSBDeviceByAddress(IN_BSTR aAddress,
1402 IHostUSBDevice **aDevice)
1403{
1404#ifdef VBOX_WITH_USB
1405 CheckComArgStrNotEmptyOrNull(aAddress);
1406 CheckComArgOutPointerValid(aDevice);
1407
1408 *aDevice = NULL;
1409
1410 SafeIfaceArray<IHostUSBDevice> devsvec;
1411 HRESULT rc = COMGETTER(USBDevices) (ComSafeArrayAsOutParam(devsvec));
1412 if (FAILED(rc)) return rc;
1413
1414 for (size_t i = 0; i < devsvec.size(); ++i)
1415 {
1416 Bstr address;
1417 rc = devsvec[i]->COMGETTER(Address) (address.asOutParam());
1418 if (FAILED(rc)) return rc;
1419 if (address == aAddress)
1420 {
1421 return ComObjPtr<IHostUSBDevice> (devsvec[i]).queryInterfaceTo(aDevice);
1422 }
1423 }
1424
1425 return setErrorNoLog(VBOX_E_OBJECT_NOT_FOUND,
1426 tr("Could not find a USB device with address '%ls'"),
1427 aAddress);
1428
1429#else /* !VBOX_WITH_USB */
1430 NOREF(aAddress);
1431 NOREF(aDevice);
1432 return E_NOTIMPL;
1433#endif /* !VBOX_WITH_USB */
1434}
1435
1436STDMETHODIMP Host::FindUSBDeviceById(IN_BSTR aId,
1437 IHostUSBDevice **aDevice)
1438{
1439#ifdef VBOX_WITH_USB
1440 CheckComArgExpr(aId, Guid (aId).isEmpty() == false);
1441 CheckComArgOutPointerValid(aDevice);
1442
1443 *aDevice = NULL;
1444
1445 SafeIfaceArray<IHostUSBDevice> devsvec;
1446 HRESULT rc = COMGETTER(USBDevices) (ComSafeArrayAsOutParam(devsvec));
1447 if (FAILED(rc)) return rc;
1448
1449 for (size_t i = 0; i < devsvec.size(); ++i)
1450 {
1451 Bstr id;
1452 rc = devsvec[i]->COMGETTER(Id) (id.asOutParam());
1453 if (FAILED(rc)) return rc;
1454 if (id == aId)
1455 {
1456 return ComObjPtr<IHostUSBDevice> (devsvec[i]).queryInterfaceTo(aDevice);
1457 }
1458 }
1459
1460 return setErrorNoLog (VBOX_E_OBJECT_NOT_FOUND, tr (
1461 "Could not find a USB device with uuid {%RTuuid}"),
1462 Guid (aId).raw());
1463
1464#else /* !VBOX_WITH_USB */
1465 NOREF(aId);
1466 NOREF(aDevice);
1467 return E_NOTIMPL;
1468#endif /* !VBOX_WITH_USB */
1469}
1470
1471// public methods only for internal purposes
1472////////////////////////////////////////////////////////////////////////////////
1473
1474HRESULT Host::loadSettings(const settings::Host &data)
1475{
1476 HRESULT rc = S_OK;
1477#ifdef VBOX_WITH_USB
1478 AutoCaller autoCaller(this);
1479 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1480
1481 AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1482
1483 for (settings::USBDeviceFiltersList::const_iterator it = data.llUSBDeviceFilters.begin();
1484 it != data.llUSBDeviceFilters.end();
1485 ++it)
1486 {
1487 const settings::USBDeviceFilter &f = *it;
1488 ComObjPtr<HostUSBDeviceFilter> pFilter;
1489 pFilter.createObject();
1490 rc = pFilter->init(this, f);
1491 if (FAILED(rc)) break;
1492
1493 m->llUSBDeviceFilters.push_back(pFilter);
1494 pFilter->mInList = true;
1495
1496 /* notify the proxy (only when the filter is active) */
1497 if (pFilter->getData().mActive)
1498 {
1499 HostUSBDeviceFilter *flt = pFilter; /* resolve ambiguity */
1500 flt->getId() = m->pUSBProxyService->insertFilter(&pFilter->getData().mUSBFilter);
1501 }
1502 }
1503#else
1504 NOREF(data);
1505#endif /* VBOX_WITH_USB */
1506 return rc;
1507}
1508
1509HRESULT Host::saveSettings(settings::Host &data)
1510{
1511#ifdef VBOX_WITH_USB
1512 AutoCaller autoCaller(this);
1513 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1514
1515 AutoReadLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1516
1517 data.llUSBDeviceFilters.clear();
1518
1519 for (USBDeviceFilterList::const_iterator it = m->llUSBDeviceFilters.begin();
1520 it != m->llUSBDeviceFilters.end();
1521 ++it)
1522 {
1523 ComObjPtr<HostUSBDeviceFilter> pFilter = *it;
1524 settings::USBDeviceFilter f;
1525 pFilter->saveSettings(f);
1526 data.llUSBDeviceFilters.push_back(f);
1527 }
1528#else
1529 NOREF(data);
1530#endif /* VBOX_WITH_USB */
1531
1532 return S_OK;
1533}
1534
1535/**
1536 * Sets the given pointer to point to the static list of DVD or floppy
1537 * drives in the Host instance data, depending on the @a mediumType
1538 * parameter.
1539 *
1540 * This builds the list on the first call; it adds or removes host drives
1541 * that may have changed if fRefresh == true.
1542 *
1543 * The caller must hold the m->drivesLock write lock before calling this.
1544 * To protect the list to which the caller's pointer points, the caller
1545 * must also hold that lock.
1546 *
1547 * @param mediumType Must be DeviceType_Floppy or DeviceType_DVD.
1548 * @param fRefresh Whether to refresh the host drives list even if this is not the first call.
1549 * @param pll Caller's pointer which gets set to the static list of host drives.
1550 * @return
1551 */
1552HRESULT Host::getDrives(DeviceType_T mediumType,
1553 bool fRefresh,
1554 MediaList *&pll)
1555{
1556 HRESULT rc = S_OK;
1557 Assert(m->drivesLock.isWriteLockOnCurrentThread());
1558
1559 MediaList llNew;
1560 MediaList *pllCached;
1561 bool *pfListBuilt = NULL;
1562
1563 switch (mediumType)
1564 {
1565 case DeviceType_DVD:
1566 if (!m->fDVDDrivesListBuilt || fRefresh)
1567 {
1568 rc = buildDVDDrivesList(llNew);
1569 if (FAILED(rc))
1570 return rc;
1571 pfListBuilt = &m->fDVDDrivesListBuilt;
1572 }
1573 pllCached = &m->llDVDDrives;
1574 break;
1575
1576 case DeviceType_Floppy:
1577 if (!m->fFloppyDrivesListBuilt || fRefresh)
1578 {
1579 rc = buildFloppyDrivesList(llNew);
1580 if (FAILED(rc))
1581 return rc;
1582 pfListBuilt = &m->fFloppyDrivesListBuilt;
1583 }
1584 pllCached = &m->llFloppyDrives;
1585 break;
1586
1587 default:
1588 return E_INVALIDARG;
1589 }
1590
1591 if (pfListBuilt)
1592 {
1593 // a list was built in llNew above:
1594 if (!*pfListBuilt)
1595 {
1596 // this was the first call (instance bool is still false): then just copy the whole list and return
1597 *pllCached = llNew;
1598 // and mark the instance data as "built"
1599 *pfListBuilt = true;
1600 }
1601 else
1602 {
1603 // list was built, and this was a subsequent call: then compare the old and the new lists
1604
1605 // remove drives from the cached list which are no longer present
1606 for (MediaList::iterator itCached = pllCached->begin();
1607 itCached != pllCached->end();
1608 ++itCached)
1609 {
1610 Medium *pCached = *itCached;
1611 const Utf8Str strLocationCached = pCached->getLocation();
1612 bool fFound = false;
1613 for (MediaList::iterator itNew = llNew.begin();
1614 itNew != llNew.end();
1615 ++itNew)
1616 {
1617 Medium *pNew = *itNew;
1618 const Utf8Str strLocationNew = pNew->getLocation();
1619 if (strLocationNew == strLocationCached)
1620 {
1621 fFound = true;
1622 break;
1623 }
1624 }
1625 if (!fFound)
1626 itCached = pllCached->erase(itCached);
1627 }
1628
1629 // add drives to the cached list that are not on there yet
1630 for (MediaList::iterator itNew = llNew.begin();
1631 itNew != llNew.end();
1632 ++itNew)
1633 {
1634 Medium *pNew = *itNew;
1635 const Utf8Str strLocationNew = pNew->getLocation();
1636 bool fFound = false;
1637 for (MediaList::iterator itCached = pllCached->begin();
1638 itCached != pllCached->end();
1639 ++itCached)
1640 {
1641 Medium *pCached = *itCached;
1642 const Utf8Str strLocationCached = pCached->getLocation();
1643 if (strLocationNew == strLocationCached)
1644 {
1645 fFound = true;
1646 break;
1647 }
1648 }
1649
1650 if (!fFound)
1651 pllCached->push_back(pNew);
1652 }
1653 }
1654 }
1655
1656 // return cached list to caller
1657 pll = pllCached;
1658
1659 return rc;
1660}
1661
1662/**
1663 * Goes through the list of host drives that would be returned by getDrives()
1664 * and looks for a host drive with the given UUID. If found, it sets pMedium
1665 * to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
1666 *
1667 * @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
1668 * @param uuid Medium UUID of host drive to look for.
1669 * @param fRefresh Whether to refresh the host drives list (see getDrives())
1670 * @param pMedium Medium object, if found…
1671 * @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
1672 */
1673HRESULT Host::findHostDrive(DeviceType_T mediumType,
1674 const Guid &uuid,
1675 bool fRefresh,
1676 ComObjPtr<Medium> &pMedium)
1677{
1678 MediaList *pllMedia;
1679
1680 AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
1681 HRESULT rc = getDrives(mediumType, fRefresh, pllMedia);
1682 if (SUCCEEDED(rc))
1683 {
1684 for (MediaList::iterator it = pllMedia->begin();
1685 it != pllMedia->end();
1686 ++it)
1687 {
1688 Medium *pThis = *it;
1689 if (pThis->getId() == uuid)
1690 {
1691 pMedium = pThis;
1692 return S_OK;
1693 }
1694 }
1695 }
1696
1697 return VBOX_E_OBJECT_NOT_FOUND;
1698}
1699
1700/**
1701 * Called from getDrives() to build the DVD drives list.
1702 * @param pll
1703 * @return
1704 */
1705HRESULT Host::buildDVDDrivesList(MediaList &list)
1706{
1707 HRESULT rc = S_OK;
1708
1709 Assert(m->drivesLock.isWriteLockOnCurrentThread());
1710
1711 try
1712 {
1713#if defined(RT_OS_WINDOWS)
1714 int sz = GetLogicalDriveStrings(0, NULL);
1715 TCHAR *hostDrives = new TCHAR[sz+1];
1716 GetLogicalDriveStrings(sz, hostDrives);
1717 wchar_t driveName[3] = { '?', ':', '\0' };
1718 TCHAR *p = hostDrives;
1719 do
1720 {
1721 if (GetDriveType(p) == DRIVE_CDROM)
1722 {
1723 driveName[0] = *p;
1724 ComObjPtr<Medium> hostDVDDriveObj;
1725 hostDVDDriveObj.createObject();
1726 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(driveName));
1727 list.push_back(hostDVDDriveObj);
1728 }
1729 p += _tcslen(p) + 1;
1730 }
1731 while (*p);
1732 delete[] hostDrives;
1733
1734#elif defined(RT_OS_SOLARIS)
1735# ifdef VBOX_USE_LIBHAL
1736 if (!getDVDInfoFromHal(list))
1737# endif
1738 {
1739 getDVDInfoFromDevTree(list);
1740 }
1741
1742#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
1743 if (RT_SUCCESS(m->hostDrives.updateDVDs()))
1744 for (DriveInfoList::const_iterator it = m->hostDrives.DVDBegin();
1745 SUCCEEDED(rc) && it != m->hostDrives.DVDEnd(); ++it)
1746 {
1747 ComObjPtr<Medium> hostDVDDriveObj;
1748 Utf8Str location(it->mDevice);
1749 Utf8Str description(it->mDescription);
1750 if (SUCCEEDED(rc))
1751 rc = hostDVDDriveObj.createObject();
1752 if (SUCCEEDED(rc))
1753 rc = hostDVDDriveObj->init(m->pParent, DeviceType_DVD, location, description);
1754 if (SUCCEEDED(rc))
1755 list.push_back(hostDVDDriveObj);
1756 }
1757#elif defined(RT_OS_DARWIN)
1758 PDARWINDVD cur = DarwinGetDVDDrives();
1759 while (cur)
1760 {
1761 ComObjPtr<Medium> hostDVDDriveObj;
1762 hostDVDDriveObj.createObject();
1763 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(cur->szName));
1764 list.push_back(hostDVDDriveObj);
1765
1766 /* next */
1767 void *freeMe = cur;
1768 cur = cur->pNext;
1769 RTMemFree(freeMe);
1770 }
1771#else
1772 /* PORTME */
1773#endif
1774 }
1775 catch(std::bad_alloc &)
1776 {
1777 rc = E_OUTOFMEMORY;
1778 }
1779 return rc;
1780}
1781
1782/**
1783 * Called from getDrives() to build the floppy drives list.
1784 * @param list
1785 * @return
1786 */
1787HRESULT Host::buildFloppyDrivesList(MediaList &list)
1788{
1789 HRESULT rc = S_OK;
1790
1791 Assert(m->drivesLock.isWriteLockOnCurrentThread());
1792
1793 try
1794 {
1795#ifdef RT_OS_WINDOWS
1796 int sz = GetLogicalDriveStrings(0, NULL);
1797 TCHAR *hostDrives = new TCHAR[sz+1];
1798 GetLogicalDriveStrings(sz, hostDrives);
1799 wchar_t driveName[3] = { '?', ':', '\0' };
1800 TCHAR *p = hostDrives;
1801 do
1802 {
1803 if (GetDriveType(p) == DRIVE_REMOVABLE)
1804 {
1805 driveName[0] = *p;
1806 ComObjPtr<Medium> hostFloppyDriveObj;
1807 hostFloppyDriveObj.createObject();
1808 hostFloppyDriveObj->init(m->pParent, DeviceType_Floppy, Bstr(driveName));
1809 list.push_back(hostFloppyDriveObj);
1810 }
1811 p += _tcslen(p) + 1;
1812 }
1813 while (*p);
1814 delete[] hostDrives;
1815#elif defined(RT_OS_LINUX)
1816 if (RT_SUCCESS(m->hostDrives.updateFloppies()))
1817 for (DriveInfoList::const_iterator it = m->hostDrives.FloppyBegin();
1818 SUCCEEDED(rc) && it != m->hostDrives.FloppyEnd(); ++it)
1819 {
1820 ComObjPtr<Medium> hostFloppyDriveObj;
1821 Utf8Str location(it->mDevice);
1822 Utf8Str description(it->mDescription);
1823 if (SUCCEEDED(rc))
1824 rc = hostFloppyDriveObj.createObject();
1825 if (SUCCEEDED(rc))
1826 rc = hostFloppyDriveObj->init(m->pParent, DeviceType_Floppy, location, description);
1827 if (SUCCEEDED(rc))
1828 list.push_back(hostFloppyDriveObj);
1829 }
1830#else
1831 NOREF(list);
1832 /* PORTME */
1833#endif
1834 }
1835 catch(std::bad_alloc &)
1836 {
1837 rc = E_OUTOFMEMORY;
1838 }
1839
1840 return rc;
1841}
1842
1843#ifdef VBOX_WITH_USB
1844USBProxyService* Host::usbProxyService()
1845{
1846 return m->pUSBProxyService;
1847}
1848
1849HRESULT Host::addChild(HostUSBDeviceFilter *pChild)
1850{
1851 AutoCaller autoCaller(this);
1852 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1853
1854 AutoWriteLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1855
1856 m->llChildren.push_back(pChild);
1857
1858 return S_OK;
1859}
1860
1861HRESULT Host::removeChild(HostUSBDeviceFilter *pChild)
1862{
1863 AutoCaller autoCaller(this);
1864 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1865
1866 AutoWriteLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1867
1868 for (USBDeviceFilterList::iterator it = m->llChildren.begin();
1869 it != m->llChildren.end();
1870 ++it)
1871 {
1872 if (*it == pChild)
1873 {
1874 m->llChildren.erase(it);
1875 break;
1876 }
1877 }
1878
1879 return S_OK;
1880}
1881
1882VirtualBox* Host::parent()
1883{
1884 return m->pParent;
1885}
1886
1887/**
1888 * Called by setter methods of all USB device filters.
1889 */
1890HRESULT Host::onUSBDeviceFilterChange(HostUSBDeviceFilter *aFilter,
1891 BOOL aActiveChanged /* = FALSE */)
1892{
1893 AutoCaller autoCaller(this);
1894 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1895
1896 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1897
1898 if (aFilter->mInList)
1899 {
1900 if (aActiveChanged)
1901 {
1902 // insert/remove the filter from the proxy
1903 if (aFilter->getData().mActive)
1904 {
1905 ComAssertRet(aFilter->getId() == NULL, E_FAIL);
1906 aFilter->getId() = m->pUSBProxyService->insertFilter(&aFilter->getData().mUSBFilter);
1907 }
1908 else
1909 {
1910 ComAssertRet(aFilter->getId() != NULL, E_FAIL);
1911 m->pUSBProxyService->removeFilter(aFilter->getId());
1912 aFilter->getId() = NULL;
1913 }
1914 }
1915 else
1916 {
1917 if (aFilter->getData().mActive)
1918 {
1919 // update the filter in the proxy
1920 ComAssertRet(aFilter->getId() != NULL, E_FAIL);
1921 m->pUSBProxyService->removeFilter(aFilter->getId());
1922 aFilter->getId() = m->pUSBProxyService->insertFilter(&aFilter->getData().mUSBFilter);
1923 }
1924 }
1925
1926 // save the global settings... yeah, on every single filter property change
1927 // for that we should hold only the VirtualBox lock
1928 alock.release();
1929 AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1930 return m->pParent->saveSettings();
1931 }
1932
1933 return S_OK;
1934}
1935
1936
1937/**
1938 * Interface for obtaining a copy of the USBDeviceFilterList,
1939 * used by the USBProxyService.
1940 *
1941 * @param aGlobalFilters Where to put the global filter list copy.
1942 * @param aMachines Where to put the machine vector.
1943 */
1944void Host::getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters)
1945{
1946 AutoReadLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
1947
1948 *aGlobalFilters = m->llUSBDeviceFilters;
1949}
1950
1951#endif /* VBOX_WITH_USB */
1952
1953// private methods
1954////////////////////////////////////////////////////////////////////////////////
1955
1956#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
1957
1958/**
1959 * Helper function to get the slice number from a device path
1960 *
1961 * @param pszDevLinkPath Pointer to a device path (/dev/(r)dsk/c7d1t0d0s3 etc.)
1962 * @returns Pointer to the slice portion of the given path.
1963 */
1964static char *solarisGetSliceFromPath(const char *pszDevLinkPath)
1965{
1966 char *pszFound = NULL;
1967 char *pszSlice = strrchr(pszDevLinkPath, 's');
1968 char *pszDisk = strrchr(pszDevLinkPath, 'd');
1969 if (pszSlice && pszSlice > pszDisk)
1970 pszFound = pszSlice;
1971 else
1972 pszFound = pszDisk;
1973
1974 if (pszFound && RT_C_IS_DIGIT(pszFound[1]))
1975 return pszFound;
1976
1977 return NULL;
1978}
1979
1980/**
1981 * Walk device links and returns an allocated path for the first one in the snapshot.
1982 *
1983 * @param DevLink Handle to the device link being walked.
1984 * @param pvArg Opaque data containing the pointer to the path.
1985 * @returns Pointer to an allocated device path string.
1986 */
1987static int solarisWalkDevLink(di_devlink_t DevLink, void *pvArg)
1988{
1989 char **ppszPath = (char **)pvArg;
1990 *ppszPath = strdup(di_devlink_path(DevLink));
1991 return DI_WALK_TERMINATE;
1992}
1993
1994/**
1995 * Walk all devices in the system and enumerate CD/DVD drives.
1996 * @param Node Handle to the current node.
1997 * @param pvArg Opaque data (holds list pointer).
1998 * @returns Solaris specific code whether to continue walking or not.
1999 */
2000static int solarisWalkDeviceNodeForDVD(di_node_t Node, void *pvArg)
2001{
2002 PSOLARISDVD *ppDrives = (PSOLARISDVD *)pvArg;
2003
2004 char *pszClass = NULL;
2005 if ( di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "class", &pszClass) > 0
2006 && !strcmp(pszClass, "scsi")) /* SCSI */
2007 {
2008 int *pInt = NULL;
2009 if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "inquiry-device-type", &pInt) > 0
2010 && ( *pInt == DTYPE_RODIRECT /* CDROM */
2011 || *pInt == DTYPE_OPTICAL)) /* Optical Drive */
2012 {
2013 char *pszProduct = NULL;
2014 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-product-id", &pszProduct) > 0)
2015 {
2016 char *pszVendor = NULL;
2017 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-vendor-id", &pszVendor) > 0)
2018 {
2019 /*
2020 * Found a DVD drive, we need to scan the minor nodes to find the correct
2021 * slice that represents the whole drive. "s2" is always the whole drive for CD/DVDs.
2022 */
2023 int Major = di_driver_major(Node);
2024 di_minor_t Minor = DI_MINOR_NIL;
2025 di_devlink_handle_t DevLink = di_devlink_init(NULL /* name */, 0 /* flags */);
2026 if (DevLink)
2027 {
2028 while ((Minor = di_minor_next(Node, Minor)) != DI_MINOR_NIL)
2029 {
2030 dev_t Dev = di_minor_devt(Minor);
2031 if ( Major != (int)major(Dev)
2032 || di_minor_spectype(Minor) == S_IFBLK
2033 || di_minor_type(Minor) != DDM_MINOR)
2034 {
2035 continue;
2036 }
2037
2038 char *pszMinorPath = di_devfs_minor_path(Minor);
2039 if (!pszMinorPath)
2040 continue;
2041
2042 char *pszDevLinkPath = NULL;
2043 di_devlink_walk(DevLink, NULL, pszMinorPath, DI_PRIMARY_LINK, &pszDevLinkPath, solarisWalkDevLink);
2044 di_devfs_path_free(pszMinorPath);
2045
2046 if (pszDevLinkPath)
2047 {
2048 char *pszSlice = solarisGetSliceFromPath(pszDevLinkPath);
2049 if ( pszSlice && !strcmp(pszSlice, "s2")
2050 && !strncmp(pszDevLinkPath, "/dev/rdsk", sizeof("/dev/rdsk") - 1)) /* We want only raw disks */
2051 {
2052 /*
2053 * We've got a fully qualified DVD drive. Add it to the list.
2054 */
2055 PSOLARISDVD pDrive = (PSOLARISDVD)RTMemAllocZ(sizeof(SOLARISDVD));
2056 if (RT_LIKELY(pDrive))
2057 {
2058 RTStrPrintf(pDrive->szDescription, sizeof(pDrive->szDescription), "%s %s", pszVendor, pszProduct);
2059 RTStrCopy(pDrive->szRawDiskPath, sizeof(pDrive->szRawDiskPath), pszDevLinkPath);
2060 if (*ppDrives)
2061 pDrive->pNext = *ppDrives;
2062 *ppDrives = pDrive;
2063 }
2064 }
2065 free(pszDevLinkPath);
2066 }
2067 }
2068 di_devlink_fini(&DevLink);
2069 }
2070 }
2071 }
2072 }
2073 }
2074 return DI_WALK_CONTINUE;
2075}
2076
2077/**
2078 * Solaris specific function to enumerate CD/DVD drives via the device tree.
2079 * Works on Solaris 10 as well as OpenSolaris without depending on libhal.
2080 */
2081void Host::getDVDInfoFromDevTree(std::list<ComObjPtr<Medium> > &list)
2082{
2083 PSOLARISDVD pDrives = NULL;
2084 di_node_t RootNode = di_init("/", DINFOCPYALL);
2085 if (RootNode != DI_NODE_NIL)
2086 di_walk_node(RootNode, DI_WALK_CLDFIRST, &pDrives, solarisWalkDeviceNodeForDVD);
2087
2088 di_fini(RootNode);
2089
2090 while (pDrives)
2091 {
2092 ComObjPtr<Medium> hostDVDDriveObj;
2093 hostDVDDriveObj.createObject();
2094 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(pDrives->szRawDiskPath), Bstr(pDrives->szDescription));
2095 list.push_back(hostDVDDriveObj);
2096
2097 void *pvDrive = pDrives;
2098 pDrives = pDrives->pNext;
2099 RTMemFree(pvDrive);
2100 }
2101}
2102
2103/* Solaris hosts, loading libhal at runtime */
2104
2105/**
2106 * Helper function to query the hal subsystem for information about DVD drives attached to the
2107 * system.
2108 *
2109 * @returns true if information was successfully obtained, false otherwise
2110 * @retval list drives found will be attached to this list
2111 */
2112bool Host::getDVDInfoFromHal(std::list<ComObjPtr<Medium> > &list)
2113{
2114 bool halSuccess = false;
2115 DBusError dbusError;
2116 if (!gLibHalCheckPresence())
2117 return false;
2118 gDBusErrorInit (&dbusError);
2119 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2120 if (dbusConnection != 0)
2121 {
2122 LibHalContext *halContext = gLibHalCtxNew();
2123 if (halContext != 0)
2124 {
2125 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2126 {
2127 if (gLibHalCtxInit(halContext, &dbusError))
2128 {
2129 int numDevices;
2130 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2131 "storage.drive_type", "cdrom",
2132 &numDevices, &dbusError);
2133 if (halDevices != 0)
2134 {
2135 /* Hal is installed and working, so if no devices are reported, assume
2136 that there are none. */
2137 halSuccess = true;
2138 for (int i = 0; i < numDevices; i++)
2139 {
2140 char *devNode = gLibHalDeviceGetPropertyString(halContext,
2141 halDevices[i], "block.device", &dbusError);
2142#ifdef RT_OS_SOLARIS
2143 /* The CD/DVD ioctls work only for raw device nodes. */
2144 char *tmp = getfullrawname(devNode);
2145 gLibHalFreeString(devNode);
2146 devNode = tmp;
2147#endif
2148
2149 if (devNode != 0)
2150 {
2151// if (validateDevice(devNode, true))
2152// {
2153 Utf8Str description;
2154 char *vendor, *product;
2155 /* We do not check the error here, as this field may
2156 not even exist. */
2157 vendor = gLibHalDeviceGetPropertyString(halContext,
2158 halDevices[i], "info.vendor", 0);
2159 product = gLibHalDeviceGetPropertyString(halContext,
2160 halDevices[i], "info.product", &dbusError);
2161 if ((product != 0 && product[0] != 0))
2162 {
2163 if ((vendor != 0) && (vendor[0] != 0))
2164 {
2165 description = Utf8StrFmt ("%s %s",
2166 vendor, product);
2167 }
2168 else
2169 {
2170 description = product;
2171 }
2172 ComObjPtr<Medium> hostDVDDriveObj;
2173 hostDVDDriveObj.createObject();
2174 hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2175 Bstr(devNode), Bstr(description));
2176 list.push_back (hostDVDDriveObj);
2177 }
2178 else
2179 {
2180 if (product == 0)
2181 {
2182 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2183 halDevices[i], dbusError.name, dbusError.message));
2184 gDBusErrorFree(&dbusError);
2185 }
2186 ComObjPtr<Medium> hostDVDDriveObj;
2187 hostDVDDriveObj.createObject();
2188 hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2189 Bstr(devNode));
2190 list.push_back (hostDVDDriveObj);
2191 }
2192 if (vendor != 0)
2193 {
2194 gLibHalFreeString(vendor);
2195 }
2196 if (product != 0)
2197 {
2198 gLibHalFreeString(product);
2199 }
2200// }
2201// else
2202// {
2203// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
2204// }
2205#ifndef RT_OS_SOLARIS
2206 gLibHalFreeString(devNode);
2207#else
2208 free(devNode);
2209#endif
2210 }
2211 else
2212 {
2213 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2214 halDevices[i], dbusError.name, dbusError.message));
2215 gDBusErrorFree(&dbusError);
2216 }
2217 }
2218 gLibHalFreeStringArray(halDevices);
2219 }
2220 else
2221 {
2222 LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2223 gDBusErrorFree(&dbusError);
2224 }
2225 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2226 {
2227 LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2228 gDBusErrorFree(&dbusError);
2229 }
2230 }
2231 else
2232 {
2233 LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2234 gDBusErrorFree(&dbusError);
2235 }
2236 gLibHalCtxFree(halContext);
2237 }
2238 else
2239 {
2240 LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
2241 }
2242 }
2243 else
2244 {
2245 LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
2246 }
2247 gDBusConnectionUnref(dbusConnection);
2248 }
2249 else
2250 {
2251 LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2252 gDBusErrorFree(&dbusError);
2253 }
2254 return halSuccess;
2255}
2256
2257
2258/**
2259 * Helper function to query the hal subsystem for information about floppy drives attached to the
2260 * system.
2261 *
2262 * @returns true if information was successfully obtained, false otherwise
2263 * @retval list drives found will be attached to this list
2264 */
2265bool Host::getFloppyInfoFromHal(std::list< ComObjPtr<Medium> > &list)
2266{
2267 bool halSuccess = false;
2268 DBusError dbusError;
2269 if (!gLibHalCheckPresence())
2270 return false;
2271 gDBusErrorInit (&dbusError);
2272 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2273 if (dbusConnection != 0)
2274 {
2275 LibHalContext *halContext = gLibHalCtxNew();
2276 if (halContext != 0)
2277 {
2278 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2279 {
2280 if (gLibHalCtxInit(halContext, &dbusError))
2281 {
2282 int numDevices;
2283 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2284 "storage.drive_type", "floppy",
2285 &numDevices, &dbusError);
2286 if (halDevices != 0)
2287 {
2288 /* Hal is installed and working, so if no devices are reported, assume
2289 that there are none. */
2290 halSuccess = true;
2291 for (int i = 0; i < numDevices; i++)
2292 {
2293 char *driveType = gLibHalDeviceGetPropertyString(halContext,
2294 halDevices[i], "storage.drive_type", 0);
2295 if (driveType != 0)
2296 {
2297 if (strcmp(driveType, "floppy") != 0)
2298 {
2299 gLibHalFreeString(driveType);
2300 continue;
2301 }
2302 gLibHalFreeString(driveType);
2303 }
2304 else
2305 {
2306 /* An error occurred. The attribute "storage.drive_type"
2307 probably didn't exist. */
2308 continue;
2309 }
2310 char *devNode = gLibHalDeviceGetPropertyString(halContext,
2311 halDevices[i], "block.device", &dbusError);
2312 if (devNode != 0)
2313 {
2314// if (validateDevice(devNode, false))
2315// {
2316 Utf8Str description;
2317 char *vendor, *product;
2318 /* We do not check the error here, as this field may
2319 not even exist. */
2320 vendor = gLibHalDeviceGetPropertyString(halContext,
2321 halDevices[i], "info.vendor", 0);
2322 product = gLibHalDeviceGetPropertyString(halContext,
2323 halDevices[i], "info.product", &dbusError);
2324 if ((product != 0) && (product[0] != 0))
2325 {
2326 if ((vendor != 0) && (vendor[0] != 0))
2327 {
2328 description = Utf8StrFmt ("%s %s",
2329 vendor, product);
2330 }
2331 else
2332 {
2333 description = product;
2334 }
2335 ComObjPtr<Medium> hostFloppyDrive;
2336 hostFloppyDrive.createObject();
2337 hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2338 Bstr(devNode), Bstr(description));
2339 list.push_back (hostFloppyDrive);
2340 }
2341 else
2342 {
2343 if (product == 0)
2344 {
2345 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2346 halDevices[i], dbusError.name, dbusError.message));
2347 gDBusErrorFree(&dbusError);
2348 }
2349 ComObjPtr<Medium> hostFloppyDrive;
2350 hostFloppyDrive.createObject();
2351 hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2352 Bstr(devNode));
2353 list.push_back (hostFloppyDrive);
2354 }
2355 if (vendor != 0)
2356 {
2357 gLibHalFreeString(vendor);
2358 }
2359 if (product != 0)
2360 {
2361 gLibHalFreeString(product);
2362 }
2363// }
2364// else
2365// {
2366// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
2367// }
2368 gLibHalFreeString(devNode);
2369 }
2370 else
2371 {
2372 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2373 halDevices[i], dbusError.name, dbusError.message));
2374 gDBusErrorFree(&dbusError);
2375 }
2376 }
2377 gLibHalFreeStringArray(halDevices);
2378 }
2379 else
2380 {
2381 LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2382 gDBusErrorFree(&dbusError);
2383 }
2384 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2385 {
2386 LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2387 gDBusErrorFree(&dbusError);
2388 }
2389 }
2390 else
2391 {
2392 LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2393 gDBusErrorFree(&dbusError);
2394 }
2395 gLibHalCtxFree(halContext);
2396 }
2397 else
2398 {
2399 LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
2400 }
2401 }
2402 else
2403 {
2404 LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
2405 }
2406 gDBusConnectionUnref(dbusConnection);
2407 }
2408 else
2409 {
2410 LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2411 gDBusErrorFree(&dbusError);
2412 }
2413 return halSuccess;
2414}
2415#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
2416
2417/** @todo get rid of dead code below - RT_OS_SOLARIS and RT_OS_LINUX are never both set */
2418#if defined(RT_OS_SOLARIS)
2419
2420/**
2421 * Helper function to parse the given mount file and add found entries
2422 */
2423void Host::parseMountTable(char *mountTable, std::list< ComObjPtr<Medium> > &list)
2424{
2425#ifdef RT_OS_LINUX
2426 FILE *mtab = setmntent(mountTable, "r");
2427 if (mtab)
2428 {
2429 struct mntent *mntent;
2430 char *mnt_type;
2431 char *mnt_dev;
2432 char *tmp;
2433 while ((mntent = getmntent(mtab)))
2434 {
2435 mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
2436 mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
2437 strcpy(mnt_type, mntent->mnt_type);
2438 strcpy(mnt_dev, mntent->mnt_fsname);
2439 // supermount fs case
2440 if (strcmp(mnt_type, "supermount") == 0)
2441 {
2442 tmp = strstr(mntent->mnt_opts, "fs=");
2443 if (tmp)
2444 {
2445 free(mnt_type);
2446 mnt_type = strdup(tmp + strlen("fs="));
2447 if (mnt_type)
2448 {
2449 tmp = strchr(mnt_type, ',');
2450 if (tmp)
2451 *tmp = '\0';
2452 }
2453 }
2454 tmp = strstr(mntent->mnt_opts, "dev=");
2455 if (tmp)
2456 {
2457 free(mnt_dev);
2458 mnt_dev = strdup(tmp + strlen("dev="));
2459 if (mnt_dev)
2460 {
2461 tmp = strchr(mnt_dev, ',');
2462 if (tmp)
2463 *tmp = '\0';
2464 }
2465 }
2466 }
2467 // use strstr here to cover things fs types like "udf,iso9660"
2468 if (strstr(mnt_type, "iso9660") == 0)
2469 {
2470 /** @todo check whether we've already got the drive in our list! */
2471 if (validateDevice(mnt_dev, true))
2472 {
2473 ComObjPtr<Medium> hostDVDDriveObj;
2474 hostDVDDriveObj.createObject();
2475 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(mnt_dev));
2476 list.push_back (hostDVDDriveObj);
2477 }
2478 }
2479 free(mnt_dev);
2480 free(mnt_type);
2481 }
2482 endmntent(mtab);
2483 }
2484#else // RT_OS_SOLARIS
2485 FILE *mntFile = fopen(mountTable, "r");
2486 if (mntFile)
2487 {
2488 struct mnttab mntTab;
2489 while (getmntent(mntFile, &mntTab) == 0)
2490 {
2491 const char *mountName = mntTab.mnt_special;
2492 const char *mountPoint = mntTab.mnt_mountp;
2493 const char *mountFSType = mntTab.mnt_fstype;
2494 if (mountName && mountPoint && mountFSType)
2495 {
2496 // skip devices we are not interested in
2497 if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
2498 (*mountFSType && (strncmp(mountFSType, "devfs", 5) != 0 && // skip devfs (i.e. /devices)
2499 strncmp(mountFSType, "dev", 3) != 0 && // skip dev (i.e. /dev)
2500 strncmp(mountFSType, "lofs", 4) != 0))) // skip loop-back file-system (lofs)
2501 {
2502 char *rawDevName = getfullrawname((char *)mountName);
2503 if (validateDevice(rawDevName, true))
2504 {
2505 ComObjPtr<Medium> hostDVDDriveObj;
2506 hostDVDDriveObj.createObject();
2507 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(rawDevName));
2508 list.push_back (hostDVDDriveObj);
2509 }
2510 free(rawDevName);
2511 }
2512 }
2513 }
2514
2515 fclose(mntFile);
2516 }
2517#endif
2518}
2519
2520/**
2521 * Helper function to check whether the given device node is a valid drive
2522 */
2523bool Host::validateDevice(const char *deviceNode, bool isCDROM)
2524{
2525 struct stat statInfo;
2526 bool retValue = false;
2527
2528 // sanity check
2529 if (!deviceNode)
2530 {
2531 return false;
2532 }
2533
2534 // first a simple stat() call
2535 if (stat(deviceNode, &statInfo) < 0)
2536 {
2537 return false;
2538 }
2539 else
2540 {
2541 if (isCDROM)
2542 {
2543 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2544 {
2545 int fileHandle;
2546 // now try to open the device
2547 fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
2548 if (fileHandle >= 0)
2549 {
2550 cdrom_subchnl cdChannelInfo;
2551 cdChannelInfo.cdsc_format = CDROM_MSF;
2552 // this call will finally reveal the whole truth
2553#ifdef RT_OS_LINUX
2554 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2555 (errno == EIO) || (errno == ENOENT) ||
2556 (errno == EINVAL) || (errno == ENOMEDIUM))
2557#else
2558 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2559 (errno == EIO) || (errno == ENOENT) ||
2560 (errno == EINVAL))
2561#endif
2562 {
2563 retValue = true;
2564 }
2565 close(fileHandle);
2566 }
2567 }
2568 } else
2569 {
2570 // floppy case
2571 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2572 {
2573 /// @todo do some more testing, maybe a nice IOCTL!
2574 retValue = true;
2575 }
2576 }
2577 }
2578 return retValue;
2579}
2580#endif // RT_OS_SOLARIS
2581
2582#ifdef VBOX_WITH_USB
2583/**
2584 * Checks for the presense and status of the USB Proxy Service.
2585 * Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
2586 * warning) if the proxy service is not available due to the way the host is
2587 * configured (at present, that means that usbfs and hal/DBus are not
2588 * available on a Linux host) or E_FAIL and a corresponding error message
2589 * otherwise. Intended to be used by methods that rely on the Proxy Service
2590 * availability.
2591 *
2592 * @note This method may return a warning result code. It is recommended to use
2593 * MultiError to store the return value.
2594 *
2595 * @note Locks this object for reading.
2596 */
2597HRESULT Host::checkUSBProxyService()
2598{
2599 AutoCaller autoCaller(this);
2600 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2601
2602 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2603
2604 AssertReturn(m->pUSBProxyService, E_FAIL);
2605 if (!m->pUSBProxyService->isActive())
2606 {
2607 /* disable the USB controller completely to avoid assertions if the
2608 * USB proxy service could not start. */
2609
2610 if (m->pUSBProxyService->getLastError() == VERR_FILE_NOT_FOUND)
2611 return setWarning(E_FAIL,
2612 tr("Could not load the Host USB Proxy Service (%Rrc). The service might not be installed on the host computer"),
2613 m->pUSBProxyService->getLastError());
2614 if (m->pUSBProxyService->getLastError() == VINF_SUCCESS)
2615#ifdef RT_OS_LINUX
2616 return setWarning (VBOX_E_HOST_ERROR,
2617# ifdef VBOX_WITH_DBUS
2618 tr ("The USB Proxy Service could not be started, because neither the USB file system (usbfs) nor the hardware information service (hal) is available")
2619# else
2620 tr ("The USB Proxy Service could not be started, because the USB file system (usbfs) is not available")
2621# endif
2622 );
2623#else /* !RT_OS_LINUX */
2624 return setWarning (E_FAIL,
2625 tr ("The USB Proxy Service has not yet been ported to this host"));
2626#endif /* !RT_OS_LINUX */
2627 return setWarning (E_FAIL,
2628 tr ("Could not load the Host USB Proxy service (%Rrc)"),
2629 m->pUSBProxyService->getLastError());
2630 }
2631
2632 return S_OK;
2633}
2634#endif /* VBOX_WITH_USB */
2635
2636#ifdef VBOX_WITH_RESOURCE_USAGE_API
2637
2638void Host::registerMetrics(PerformanceCollector *aCollector)
2639{
2640 pm::CollectorHAL *hal = aCollector->getHAL();
2641 /* Create sub metrics */
2642 pm::SubMetric *cpuLoadUser = new pm::SubMetric("CPU/Load/User",
2643 "Percentage of processor time spent in user mode.");
2644 pm::SubMetric *cpuLoadKernel = new pm::SubMetric("CPU/Load/Kernel",
2645 "Percentage of processor time spent in kernel mode.");
2646 pm::SubMetric *cpuLoadIdle = new pm::SubMetric("CPU/Load/Idle",
2647 "Percentage of processor time spent idling.");
2648 pm::SubMetric *cpuMhzSM = new pm::SubMetric("CPU/MHz",
2649 "Average of current frequency of all processors.");
2650 pm::SubMetric *ramUsageTotal = new pm::SubMetric("RAM/Usage/Total",
2651 "Total physical memory installed.");
2652 pm::SubMetric *ramUsageUsed = new pm::SubMetric("RAM/Usage/Used",
2653 "Physical memory currently occupied.");
2654 pm::SubMetric *ramUsageFree = new pm::SubMetric("RAM/Usage/Free",
2655 "Physical memory currently available to applications.");
2656 pm::SubMetric *ramVMMUsed = new pm::SubMetric("RAM/VMM/Used",
2657 "Total physical memory used by the hypervisor.");
2658 pm::SubMetric *ramVMMFree = new pm::SubMetric("RAM/VMM/Free",
2659 "Total physical memory free inside the hypervisor.");
2660 pm::SubMetric *ramVMMBallooned = new pm::SubMetric("RAM/VMM/Ballooned",
2661 "Total physical memory ballooned by the hypervisor.");
2662 pm::SubMetric *ramVMMShared = new pm::SubMetric("RAM/VMM/Shared",
2663 "Total physical memory shared between VMs.");
2664
2665
2666 /* Create and register base metrics */
2667 IUnknown *objptr;
2668 ComObjPtr<Host> tmp = this;
2669 tmp.queryInterfaceTo(&objptr);
2670 pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw(hal, objptr, cpuLoadUser, cpuLoadKernel,
2671 cpuLoadIdle);
2672 aCollector->registerBaseMetric (cpuLoad);
2673 pm::BaseMetric *cpuMhz = new pm::HostCpuMhz(hal, objptr, cpuMhzSM);
2674 aCollector->registerBaseMetric (cpuMhz);
2675 pm::BaseMetric *ramUsage = new pm::HostRamUsage(hal, objptr, ramUsageTotal, ramUsageUsed,
2676 ramUsageFree, ramVMMUsed, ramVMMFree, ramVMMBallooned, ramVMMShared);
2677 aCollector->registerBaseMetric (ramUsage);
2678
2679 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
2680 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2681 new pm::AggregateAvg()));
2682 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2683 new pm::AggregateMin()));
2684 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2685 new pm::AggregateMax()));
2686
2687 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, 0));
2688 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2689 new pm::AggregateAvg()));
2690 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2691 new pm::AggregateMin()));
2692 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2693 new pm::AggregateMax()));
2694
2695 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, 0));
2696 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2697 new pm::AggregateAvg()));
2698 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2699 new pm::AggregateMin()));
2700 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2701 new pm::AggregateMax()));
2702
2703 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM, 0));
2704 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2705 new pm::AggregateAvg()));
2706 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2707 new pm::AggregateMin()));
2708 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2709 new pm::AggregateMax()));
2710
2711 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal, 0));
2712 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2713 new pm::AggregateAvg()));
2714 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2715 new pm::AggregateMin()));
2716 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2717 new pm::AggregateMax()));
2718
2719 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed, 0));
2720 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2721 new pm::AggregateAvg()));
2722 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2723 new pm::AggregateMin()));
2724 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2725 new pm::AggregateMax()));
2726
2727 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree, 0));
2728 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2729 new pm::AggregateAvg()));
2730 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2731 new pm::AggregateMin()));
2732 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2733 new pm::AggregateMax()));
2734
2735 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed, 0));
2736 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed,
2737 new pm::AggregateAvg()));
2738 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed,
2739 new pm::AggregateMin()));
2740 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed,
2741 new pm::AggregateMax()));
2742
2743 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree, 0));
2744 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree,
2745 new pm::AggregateAvg()));
2746 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree,
2747 new pm::AggregateMin()));
2748 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree,
2749 new pm::AggregateMax()));
2750
2751 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned, 0));
2752 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned,
2753 new pm::AggregateAvg()));
2754 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned,
2755 new pm::AggregateMin()));
2756 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned,
2757 new pm::AggregateMax()));
2758
2759 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared, 0));
2760 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared,
2761 new pm::AggregateAvg()));
2762 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared,
2763 new pm::AggregateMin()));
2764 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared,
2765 new pm::AggregateMax()));
2766}
2767
2768void Host::unregisterMetrics (PerformanceCollector *aCollector)
2769{
2770 aCollector->unregisterMetricsFor(this);
2771 aCollector->unregisterBaseMetricsFor(this);
2772}
2773
2774#endif /* VBOX_WITH_RESOURCE_USAGE_API */
2775
2776/* 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