VirtualBox

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

Last change on this file since 31346 was 31346, checked in by vboxsync, 14 years ago

Main/HostImpl: Solaris DVD drive list fix.

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