VirtualBox

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

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

Main: cleanup host drives management: do not return different IMedium objects every time Host::GetDVDDrives() or HOst::GetFloppyDrives() are called; refresh the internal list only when a public API is called, but not for every single internal use such as loading machine settings file; fix code duplication

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