VirtualBox

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

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

Main/Solaris: New DVD drive enumeration, works on Solaris 10 & Nevada. Removed now obsolete NSL_RESOLVED stuff on Solaris.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 94.3 KB
Line 
1/* $Id: HostImpl.cpp 31337 2010-08-03 14:05:05Z 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 char *pszSlice = solarisGetSliceFromPath(pszDevLinkPath);
2038 if ( pszSlice && !strcmp(pszSlice, "s2")
2039 && !strncmp(pszDevLinkPath, "/dev/rdsk", sizeof("/dev/rdsk") - 1)) /* We want only raw disks */
2040 {
2041 /*
2042 * We've got a fully qualified DVD drive. Add it to the list.
2043 */
2044 PSOLARISDVD pDrive = (PSOLARISDVD)RTMemAllocZ(sizeof(SOLARISDVD));
2045 if (RT_LIKELY(pDrive))
2046 {
2047 RTStrPrintf(pDrive->szDescription, sizeof(pDrive->szDescription), "%s %s", pszVendor, pszProduct);
2048 RTStrCopy(pDrive->szRawDiskPath, sizeof(pDrive->szRawDiskPath), pszDevLinkPath);
2049 if (!*ppDrives)
2050 *ppDrives = pDrive;
2051 else
2052 (*ppDrives)->pNext = pDrive;
2053 }
2054 }
2055 free(pszDevLinkPath);
2056 }
2057 }
2058 }
2059 }
2060 }
2061 }
2062 return DI_WALK_CONTINUE;
2063}
2064
2065/**
2066 * Solaris specific function to enumerate CD/DVD drives via the device tree.
2067 * Works on Solaris 10 as well as OpenSolaris without depending on libhal.
2068 */
2069void Host::getDVDInfoFromDevTree(std::list<ComObjPtr<Medium> > &list)
2070{
2071 PSOLARISDVD pDrives = NULL;
2072 di_node_t RootNode = di_init("/", DINFOCPYALL);
2073 if (RootNode != DI_NODE_NIL)
2074 di_walk_node(RootNode, DI_WALK_CLDFIRST, &pDrives, solarisWalkDeviceNodeForDVD);
2075
2076 di_fini(RootNode);
2077
2078 while (pDrives)
2079 {
2080 ComObjPtr<Medium> hostDVDDriveObj;
2081 hostDVDDriveObj.createObject();
2082 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(pDrives->szRawDiskPath), Bstr(pDrives->szDescription));
2083 list.push_back(hostDVDDriveObj);
2084
2085 void *pvDrive = pDrives;
2086 pDrives = pDrives->pNext;
2087 RTMemFree(pvDrive);
2088 }
2089}
2090
2091/* Solaris hosts, loading libhal at runtime */
2092
2093/**
2094 * Helper function to query the hal subsystem for information about DVD drives attached to the
2095 * system.
2096 *
2097 * @returns true if information was successfully obtained, false otherwise
2098 * @retval list drives found will be attached to this list
2099 */
2100bool Host::getDVDInfoFromHal(std::list<ComObjPtr<Medium> > &list)
2101{
2102 bool halSuccess = false;
2103 DBusError dbusError;
2104 if (!gLibHalCheckPresence())
2105 return false;
2106 gDBusErrorInit (&dbusError);
2107 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2108 if (dbusConnection != 0)
2109 {
2110 LibHalContext *halContext = gLibHalCtxNew();
2111 if (halContext != 0)
2112 {
2113 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2114 {
2115 if (gLibHalCtxInit(halContext, &dbusError))
2116 {
2117 int numDevices;
2118 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2119 "storage.drive_type", "cdrom",
2120 &numDevices, &dbusError);
2121 if (halDevices != 0)
2122 {
2123 /* Hal is installed and working, so if no devices are reported, assume
2124 that there are none. */
2125 halSuccess = true;
2126 for (int i = 0; i < numDevices; i++)
2127 {
2128 char *devNode = gLibHalDeviceGetPropertyString(halContext,
2129 halDevices[i], "block.device", &dbusError);
2130#ifdef RT_OS_SOLARIS
2131 /* The CD/DVD ioctls work only for raw device nodes. */
2132 char *tmp = getfullrawname(devNode);
2133 gLibHalFreeString(devNode);
2134 devNode = tmp;
2135#endif
2136
2137 if (devNode != 0)
2138 {
2139// if (validateDevice(devNode, true))
2140// {
2141 Utf8Str description;
2142 char *vendor, *product;
2143 /* We do not check the error here, as this field may
2144 not even exist. */
2145 vendor = gLibHalDeviceGetPropertyString(halContext,
2146 halDevices[i], "info.vendor", 0);
2147 product = gLibHalDeviceGetPropertyString(halContext,
2148 halDevices[i], "info.product", &dbusError);
2149 if ((product != 0 && product[0] != 0))
2150 {
2151 if ((vendor != 0) && (vendor[0] != 0))
2152 {
2153 description = Utf8StrFmt ("%s %s",
2154 vendor, product);
2155 }
2156 else
2157 {
2158 description = product;
2159 }
2160 ComObjPtr<Medium> hostDVDDriveObj;
2161 hostDVDDriveObj.createObject();
2162 hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2163 Bstr(devNode), Bstr(description));
2164 list.push_back (hostDVDDriveObj);
2165 }
2166 else
2167 {
2168 if (product == 0)
2169 {
2170 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2171 halDevices[i], dbusError.name, dbusError.message));
2172 gDBusErrorFree(&dbusError);
2173 }
2174 ComObjPtr<Medium> hostDVDDriveObj;
2175 hostDVDDriveObj.createObject();
2176 hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2177 Bstr(devNode));
2178 list.push_back (hostDVDDriveObj);
2179 }
2180 if (vendor != 0)
2181 {
2182 gLibHalFreeString(vendor);
2183 }
2184 if (product != 0)
2185 {
2186 gLibHalFreeString(product);
2187 }
2188// }
2189// else
2190// {
2191// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
2192// }
2193#ifndef RT_OS_SOLARIS
2194 gLibHalFreeString(devNode);
2195#else
2196 free(devNode);
2197#endif
2198 }
2199 else
2200 {
2201 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2202 halDevices[i], dbusError.name, dbusError.message));
2203 gDBusErrorFree(&dbusError);
2204 }
2205 }
2206 gLibHalFreeStringArray(halDevices);
2207 }
2208 else
2209 {
2210 LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2211 gDBusErrorFree(&dbusError);
2212 }
2213 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2214 {
2215 LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2216 gDBusErrorFree(&dbusError);
2217 }
2218 }
2219 else
2220 {
2221 LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2222 gDBusErrorFree(&dbusError);
2223 }
2224 gLibHalCtxFree(halContext);
2225 }
2226 else
2227 {
2228 LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
2229 }
2230 }
2231 else
2232 {
2233 LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
2234 }
2235 gDBusConnectionUnref(dbusConnection);
2236 }
2237 else
2238 {
2239 LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2240 gDBusErrorFree(&dbusError);
2241 }
2242 return halSuccess;
2243}
2244
2245
2246/**
2247 * Helper function to query the hal subsystem for information about floppy drives attached to the
2248 * system.
2249 *
2250 * @returns true if information was successfully obtained, false otherwise
2251 * @retval list drives found will be attached to this list
2252 */
2253bool Host::getFloppyInfoFromHal(std::list< ComObjPtr<Medium> > &list)
2254{
2255 bool halSuccess = false;
2256 DBusError dbusError;
2257 if (!gLibHalCheckPresence())
2258 return false;
2259 gDBusErrorInit (&dbusError);
2260 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2261 if (dbusConnection != 0)
2262 {
2263 LibHalContext *halContext = gLibHalCtxNew();
2264 if (halContext != 0)
2265 {
2266 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2267 {
2268 if (gLibHalCtxInit(halContext, &dbusError))
2269 {
2270 int numDevices;
2271 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2272 "storage.drive_type", "floppy",
2273 &numDevices, &dbusError);
2274 if (halDevices != 0)
2275 {
2276 /* Hal is installed and working, so if no devices are reported, assume
2277 that there are none. */
2278 halSuccess = true;
2279 for (int i = 0; i < numDevices; i++)
2280 {
2281 char *driveType = gLibHalDeviceGetPropertyString(halContext,
2282 halDevices[i], "storage.drive_type", 0);
2283 if (driveType != 0)
2284 {
2285 if (strcmp(driveType, "floppy") != 0)
2286 {
2287 gLibHalFreeString(driveType);
2288 continue;
2289 }
2290 gLibHalFreeString(driveType);
2291 }
2292 else
2293 {
2294 /* An error occurred. The attribute "storage.drive_type"
2295 probably didn't exist. */
2296 continue;
2297 }
2298 char *devNode = gLibHalDeviceGetPropertyString(halContext,
2299 halDevices[i], "block.device", &dbusError);
2300 if (devNode != 0)
2301 {
2302// if (validateDevice(devNode, false))
2303// {
2304 Utf8Str description;
2305 char *vendor, *product;
2306 /* We do not check the error here, as this field may
2307 not even exist. */
2308 vendor = gLibHalDeviceGetPropertyString(halContext,
2309 halDevices[i], "info.vendor", 0);
2310 product = gLibHalDeviceGetPropertyString(halContext,
2311 halDevices[i], "info.product", &dbusError);
2312 if ((product != 0) && (product[0] != 0))
2313 {
2314 if ((vendor != 0) && (vendor[0] != 0))
2315 {
2316 description = Utf8StrFmt ("%s %s",
2317 vendor, product);
2318 }
2319 else
2320 {
2321 description = product;
2322 }
2323 ComObjPtr<Medium> hostFloppyDrive;
2324 hostFloppyDrive.createObject();
2325 hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2326 Bstr(devNode), Bstr(description));
2327 list.push_back (hostFloppyDrive);
2328 }
2329 else
2330 {
2331 if (product == 0)
2332 {
2333 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2334 halDevices[i], dbusError.name, dbusError.message));
2335 gDBusErrorFree(&dbusError);
2336 }
2337 ComObjPtr<Medium> hostFloppyDrive;
2338 hostFloppyDrive.createObject();
2339 hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2340 Bstr(devNode));
2341 list.push_back (hostFloppyDrive);
2342 }
2343 if (vendor != 0)
2344 {
2345 gLibHalFreeString(vendor);
2346 }
2347 if (product != 0)
2348 {
2349 gLibHalFreeString(product);
2350 }
2351// }
2352// else
2353// {
2354// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
2355// }
2356 gLibHalFreeString(devNode);
2357 }
2358 else
2359 {
2360 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2361 halDevices[i], dbusError.name, dbusError.message));
2362 gDBusErrorFree(&dbusError);
2363 }
2364 }
2365 gLibHalFreeStringArray(halDevices);
2366 }
2367 else
2368 {
2369 LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2370 gDBusErrorFree(&dbusError);
2371 }
2372 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2373 {
2374 LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2375 gDBusErrorFree(&dbusError);
2376 }
2377 }
2378 else
2379 {
2380 LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2381 gDBusErrorFree(&dbusError);
2382 }
2383 gLibHalCtxFree(halContext);
2384 }
2385 else
2386 {
2387 LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
2388 }
2389 }
2390 else
2391 {
2392 LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
2393 }
2394 gDBusConnectionUnref(dbusConnection);
2395 }
2396 else
2397 {
2398 LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2399 gDBusErrorFree(&dbusError);
2400 }
2401 return halSuccess;
2402}
2403#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
2404
2405/** @todo get rid of dead code below - RT_OS_SOLARIS and RT_OS_LINUX are never both set */
2406#if defined(RT_OS_SOLARIS)
2407
2408/**
2409 * Helper function to parse the given mount file and add found entries
2410 */
2411void Host::parseMountTable(char *mountTable, std::list< ComObjPtr<Medium> > &list)
2412{
2413#ifdef RT_OS_LINUX
2414 FILE *mtab = setmntent(mountTable, "r");
2415 if (mtab)
2416 {
2417 struct mntent *mntent;
2418 char *mnt_type;
2419 char *mnt_dev;
2420 char *tmp;
2421 while ((mntent = getmntent(mtab)))
2422 {
2423 mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
2424 mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
2425 strcpy(mnt_type, mntent->mnt_type);
2426 strcpy(mnt_dev, mntent->mnt_fsname);
2427 // supermount fs case
2428 if (strcmp(mnt_type, "supermount") == 0)
2429 {
2430 tmp = strstr(mntent->mnt_opts, "fs=");
2431 if (tmp)
2432 {
2433 free(mnt_type);
2434 mnt_type = strdup(tmp + strlen("fs="));
2435 if (mnt_type)
2436 {
2437 tmp = strchr(mnt_type, ',');
2438 if (tmp)
2439 *tmp = '\0';
2440 }
2441 }
2442 tmp = strstr(mntent->mnt_opts, "dev=");
2443 if (tmp)
2444 {
2445 free(mnt_dev);
2446 mnt_dev = strdup(tmp + strlen("dev="));
2447 if (mnt_dev)
2448 {
2449 tmp = strchr(mnt_dev, ',');
2450 if (tmp)
2451 *tmp = '\0';
2452 }
2453 }
2454 }
2455 // use strstr here to cover things fs types like "udf,iso9660"
2456 if (strstr(mnt_type, "iso9660") == 0)
2457 {
2458 /** @todo check whether we've already got the drive in our list! */
2459 if (validateDevice(mnt_dev, true))
2460 {
2461 ComObjPtr<Medium> hostDVDDriveObj;
2462 hostDVDDriveObj.createObject();
2463 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(mnt_dev));
2464 list.push_back (hostDVDDriveObj);
2465 }
2466 }
2467 free(mnt_dev);
2468 free(mnt_type);
2469 }
2470 endmntent(mtab);
2471 }
2472#else // RT_OS_SOLARIS
2473 FILE *mntFile = fopen(mountTable, "r");
2474 if (mntFile)
2475 {
2476 struct mnttab mntTab;
2477 while (getmntent(mntFile, &mntTab) == 0)
2478 {
2479 const char *mountName = mntTab.mnt_special;
2480 const char *mountPoint = mntTab.mnt_mountp;
2481 const char *mountFSType = mntTab.mnt_fstype;
2482 if (mountName && mountPoint && mountFSType)
2483 {
2484 // skip devices we are not interested in
2485 if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
2486 (*mountFSType && (strncmp(mountFSType, "devfs", 5) != 0 && // skip devfs (i.e. /devices)
2487 strncmp(mountFSType, "dev", 3) != 0 && // skip dev (i.e. /dev)
2488 strncmp(mountFSType, "lofs", 4) != 0))) // skip loop-back file-system (lofs)
2489 {
2490 char *rawDevName = getfullrawname((char *)mountName);
2491 if (validateDevice(rawDevName, true))
2492 {
2493 ComObjPtr<Medium> hostDVDDriveObj;
2494 hostDVDDriveObj.createObject();
2495 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(rawDevName));
2496 list.push_back (hostDVDDriveObj);
2497 }
2498 free(rawDevName);
2499 }
2500 }
2501 }
2502
2503 fclose(mntFile);
2504 }
2505#endif
2506}
2507
2508/**
2509 * Helper function to check whether the given device node is a valid drive
2510 */
2511bool Host::validateDevice(const char *deviceNode, bool isCDROM)
2512{
2513 struct stat statInfo;
2514 bool retValue = false;
2515
2516 // sanity check
2517 if (!deviceNode)
2518 {
2519 return false;
2520 }
2521
2522 // first a simple stat() call
2523 if (stat(deviceNode, &statInfo) < 0)
2524 {
2525 return false;
2526 }
2527 else
2528 {
2529 if (isCDROM)
2530 {
2531 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2532 {
2533 int fileHandle;
2534 // now try to open the device
2535 fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
2536 if (fileHandle >= 0)
2537 {
2538 cdrom_subchnl cdChannelInfo;
2539 cdChannelInfo.cdsc_format = CDROM_MSF;
2540 // this call will finally reveal the whole truth
2541#ifdef RT_OS_LINUX
2542 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2543 (errno == EIO) || (errno == ENOENT) ||
2544 (errno == EINVAL) || (errno == ENOMEDIUM))
2545#else
2546 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2547 (errno == EIO) || (errno == ENOENT) ||
2548 (errno == EINVAL))
2549#endif
2550 {
2551 retValue = true;
2552 }
2553 close(fileHandle);
2554 }
2555 }
2556 } else
2557 {
2558 // floppy case
2559 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2560 {
2561 /// @todo do some more testing, maybe a nice IOCTL!
2562 retValue = true;
2563 }
2564 }
2565 }
2566 return retValue;
2567}
2568#endif // RT_OS_SOLARIS
2569
2570#ifdef VBOX_WITH_USB
2571/**
2572 * Checks for the presense and status of the USB Proxy Service.
2573 * Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
2574 * warning) if the proxy service is not available due to the way the host is
2575 * configured (at present, that means that usbfs and hal/DBus are not
2576 * available on a Linux host) or E_FAIL and a corresponding error message
2577 * otherwise. Intended to be used by methods that rely on the Proxy Service
2578 * availability.
2579 *
2580 * @note This method may return a warning result code. It is recommended to use
2581 * MultiError to store the return value.
2582 *
2583 * @note Locks this object for reading.
2584 */
2585HRESULT Host::checkUSBProxyService()
2586{
2587 AutoCaller autoCaller(this);
2588 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2589
2590 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2591
2592 AssertReturn(m->pUSBProxyService, E_FAIL);
2593 if (!m->pUSBProxyService->isActive())
2594 {
2595 /* disable the USB controller completely to avoid assertions if the
2596 * USB proxy service could not start. */
2597
2598 if (m->pUSBProxyService->getLastError() == VERR_FILE_NOT_FOUND)
2599 return setWarning(E_FAIL,
2600 tr("Could not load the Host USB Proxy Service (%Rrc). The service might not be installed on the host computer"),
2601 m->pUSBProxyService->getLastError());
2602 if (m->pUSBProxyService->getLastError() == VINF_SUCCESS)
2603#ifdef RT_OS_LINUX
2604 return setWarning (VBOX_E_HOST_ERROR,
2605# ifdef VBOX_WITH_DBUS
2606 tr ("The USB Proxy Service could not be started, because neither the USB file system (usbfs) nor the hardware information service (hal) is available")
2607# else
2608 tr ("The USB Proxy Service could not be started, because the USB file system (usbfs) is not available")
2609# endif
2610 );
2611#else /* !RT_OS_LINUX */
2612 return setWarning (E_FAIL,
2613 tr ("The USB Proxy Service has not yet been ported to this host"));
2614#endif /* !RT_OS_LINUX */
2615 return setWarning (E_FAIL,
2616 tr ("Could not load the Host USB Proxy service (%Rrc)"),
2617 m->pUSBProxyService->getLastError());
2618 }
2619
2620 return S_OK;
2621}
2622#endif /* VBOX_WITH_USB */
2623
2624#ifdef VBOX_WITH_RESOURCE_USAGE_API
2625
2626void Host::registerMetrics(PerformanceCollector *aCollector)
2627{
2628 pm::CollectorHAL *hal = aCollector->getHAL();
2629 /* Create sub metrics */
2630 pm::SubMetric *cpuLoadUser = new pm::SubMetric("CPU/Load/User",
2631 "Percentage of processor time spent in user mode.");
2632 pm::SubMetric *cpuLoadKernel = new pm::SubMetric("CPU/Load/Kernel",
2633 "Percentage of processor time spent in kernel mode.");
2634 pm::SubMetric *cpuLoadIdle = new pm::SubMetric("CPU/Load/Idle",
2635 "Percentage of processor time spent idling.");
2636 pm::SubMetric *cpuMhzSM = new pm::SubMetric("CPU/MHz",
2637 "Average of current frequency of all processors.");
2638 pm::SubMetric *ramUsageTotal = new pm::SubMetric("RAM/Usage/Total",
2639 "Total physical memory installed.");
2640 pm::SubMetric *ramUsageUsed = new pm::SubMetric("RAM/Usage/Used",
2641 "Physical memory currently occupied.");
2642 pm::SubMetric *ramUsageFree = new pm::SubMetric("RAM/Usage/Free",
2643 "Physical memory currently available to applications.");
2644 pm::SubMetric *ramVMMUsed = new pm::SubMetric("RAM/VMM/Used",
2645 "Total physical memory used by the hypervisor.");
2646 pm::SubMetric *ramVMMFree = new pm::SubMetric("RAM/VMM/Free",
2647 "Total physical memory free inside the hypervisor.");
2648 pm::SubMetric *ramVMMBallooned = new pm::SubMetric("RAM/VMM/Ballooned",
2649 "Total physical memory ballooned by the hypervisor.");
2650 pm::SubMetric *ramVMMShared = new pm::SubMetric("RAM/VMM/Shared",
2651 "Total physical memory shared between VMs.");
2652
2653
2654 /* Create and register base metrics */
2655 IUnknown *objptr;
2656 ComObjPtr<Host> tmp = this;
2657 tmp.queryInterfaceTo(&objptr);
2658 pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw(hal, objptr, cpuLoadUser, cpuLoadKernel,
2659 cpuLoadIdle);
2660 aCollector->registerBaseMetric (cpuLoad);
2661 pm::BaseMetric *cpuMhz = new pm::HostCpuMhz(hal, objptr, cpuMhzSM);
2662 aCollector->registerBaseMetric (cpuMhz);
2663 pm::BaseMetric *ramUsage = new pm::HostRamUsage(hal, objptr, ramUsageTotal, ramUsageUsed,
2664 ramUsageFree, ramVMMUsed, ramVMMFree, ramVMMBallooned, ramVMMShared);
2665 aCollector->registerBaseMetric (ramUsage);
2666
2667 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
2668 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2669 new pm::AggregateAvg()));
2670 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2671 new pm::AggregateMin()));
2672 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
2673 new pm::AggregateMax()));
2674
2675 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, 0));
2676 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2677 new pm::AggregateAvg()));
2678 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2679 new pm::AggregateMin()));
2680 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
2681 new pm::AggregateMax()));
2682
2683 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, 0));
2684 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2685 new pm::AggregateAvg()));
2686 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2687 new pm::AggregateMin()));
2688 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
2689 new pm::AggregateMax()));
2690
2691 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM, 0));
2692 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2693 new pm::AggregateAvg()));
2694 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2695 new pm::AggregateMin()));
2696 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
2697 new pm::AggregateMax()));
2698
2699 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal, 0));
2700 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2701 new pm::AggregateAvg()));
2702 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2703 new pm::AggregateMin()));
2704 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
2705 new pm::AggregateMax()));
2706
2707 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed, 0));
2708 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2709 new pm::AggregateAvg()));
2710 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2711 new pm::AggregateMin()));
2712 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
2713 new pm::AggregateMax()));
2714
2715 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree, 0));
2716 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2717 new pm::AggregateAvg()));
2718 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2719 new pm::AggregateMin()));
2720 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
2721 new pm::AggregateMax()));
2722
2723 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed, 0));
2724 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed,
2725 new pm::AggregateAvg()));
2726 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed,
2727 new pm::AggregateMin()));
2728 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMUsed,
2729 new pm::AggregateMax()));
2730
2731 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree, 0));
2732 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree,
2733 new pm::AggregateAvg()));
2734 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree,
2735 new pm::AggregateMin()));
2736 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMFree,
2737 new pm::AggregateMax()));
2738
2739 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned, 0));
2740 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned,
2741 new pm::AggregateAvg()));
2742 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned,
2743 new pm::AggregateMin()));
2744 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMBallooned,
2745 new pm::AggregateMax()));
2746
2747 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared, 0));
2748 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared,
2749 new pm::AggregateAvg()));
2750 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared,
2751 new pm::AggregateMin()));
2752 aCollector->registerMetric(new pm::Metric(ramUsage, ramVMMShared,
2753 new pm::AggregateMax()));
2754}
2755
2756void Host::unregisterMetrics (PerformanceCollector *aCollector)
2757{
2758 aCollector->unregisterMetricsFor(this);
2759 aCollector->unregisterBaseMetricsFor(this);
2760}
2761
2762#endif /* VBOX_WITH_RESOURCE_USAGE_API */
2763
2764/* 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