VirtualBox

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

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

Main: fix locking order violations introduced by r64323 by using a new, separate lock for the host drives

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