VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostImpl.cpp@ 49761

Last change on this file since 49761 was 49761, checked in by vboxsync, 11 years ago

Main/Host: remove redundant casts, plus lots of whitespace cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 114.6 KB
Line 
1/* $Id: HostImpl.cpp 49761 2013-12-03 18:34:22Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation: Host
4 */
5
6/*
7 * Copyright (C) 2004-2013 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 "HostVideoInputDeviceImpl.h"
34#include "MachineImpl.h"
35#include "AutoCaller.h"
36#include "Logging.h"
37#include "Performance.h"
38
39#include "MediumImpl.h"
40#include "HostPower.h"
41
42#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
43# include <HostHardwareLinux.h>
44#endif
45
46#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
47# include <set>
48#endif
49
50#ifdef VBOX_WITH_RESOURCE_USAGE_API
51# include "PerformanceImpl.h"
52#endif /* VBOX_WITH_RESOURCE_USAGE_API */
53
54#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
55# include <VBox/VBoxNetCfg-win.h>
56#endif /* #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
57
58#if defined(RT_OS_DARWIN) && ARCH_BITS == 32
59# include <sys/types.h>
60# include <sys/sysctl.h>
61#endif
62
63#ifdef RT_OS_LINUX
64# include <sys/ioctl.h>
65# include <errno.h>
66# include <net/if.h>
67# include <net/if_arp.h>
68#endif /* RT_OS_LINUX */
69
70#ifdef RT_OS_SOLARIS
71# include <fcntl.h>
72# include <unistd.h>
73# include <stropts.h>
74# include <errno.h>
75# include <limits.h>
76# include <stdio.h>
77# include <libdevinfo.h>
78# include <sys/mkdev.h>
79# include <sys/scsi/generic/inquiry.h>
80# include <net/if.h>
81# include <sys/socket.h>
82# include <sys/sockio.h>
83# include <net/if_arp.h>
84# include <net/if.h>
85# include <sys/types.h>
86# include <sys/stat.h>
87# include <sys/cdio.h>
88# include <sys/dkio.h>
89# include <sys/mnttab.h>
90# include <sys/mntent.h>
91/* Dynamic loading of libhal on Solaris hosts */
92# ifdef VBOX_USE_LIBHAL
93# include "vbox-libhal.h"
94extern "C" char *getfullrawname(char *);
95# endif
96# include "solaris/DynLoadLibSolaris.h"
97
98/**
99 * Solaris DVD drive list as returned by getDVDInfoFromDevTree().
100 */
101typedef struct SOLARISDVD
102{
103 struct SOLARISDVD *pNext;
104 char szDescription[512];
105 char szRawDiskPath[PATH_MAX];
106} SOLARISDVD;
107/** Pointer to a Solaris DVD descriptor. */
108typedef SOLARISDVD *PSOLARISDVD;
109
110
111
112#endif /* RT_OS_SOLARIS */
113
114#ifdef RT_OS_WINDOWS
115# define _WIN32_DCOM
116# include <windows.h>
117# include <shellapi.h>
118# define INITGUID
119# include <guiddef.h>
120# include <devguid.h>
121# include <objbase.h>
122//# include <setupapi.h>
123# include <shlobj.h>
124# include <cfgmgr32.h>
125
126#endif /* RT_OS_WINDOWS */
127
128#ifdef RT_OS_DARWIN
129# include "darwin/iokit.h"
130#endif
131
132#ifdef VBOX_WITH_CROGL
133#include <VBox/VBoxOGLTest.h>
134#endif /* VBOX_WITH_CROGL */
135
136#include <iprt/asm-amd64-x86.h>
137#include <iprt/string.h>
138#include <iprt/mp.h>
139#include <iprt/time.h>
140#include <iprt/param.h>
141#include <iprt/env.h>
142#include <iprt/mem.h>
143#include <iprt/system.h>
144#ifndef RT_OS_WINDOWS
145# include <iprt/path.h>
146#endif
147#ifdef RT_OS_SOLARIS
148# include <iprt/ctype.h>
149#endif
150#ifdef VBOX_WITH_HOSTNETIF_API
151# include "netif.h"
152#endif
153
154/* XXX Solaris: definitions in /usr/include/sys/regset.h clash with hm_svm.h */
155#undef DS
156#undef ES
157#undef CS
158#undef SS
159#undef FS
160#undef GS
161
162#include <VBox/usb.h>
163#include <VBox/vmm/hm_svm.h>
164#include <VBox/err.h>
165#include <VBox/settings.h>
166#include <VBox/sup.h>
167#include <iprt/x86.h>
168
169#include "VBox/com/MultiResult.h"
170#include "VBox/com/array.h"
171
172#include <stdio.h>
173
174#include <algorithm>
175#include <string>
176#include <vector>
177
178#include "HostDnsService.h"
179
180////////////////////////////////////////////////////////////////////////////////
181//
182// Host private data definition
183//
184////////////////////////////////////////////////////////////////////////////////
185
186struct Host::Data
187{
188 Data()
189 :
190 fDVDDrivesListBuilt(false),
191 fFloppyDrivesListBuilt(false)
192 {};
193
194 VirtualBox *pParent;
195
196 HostNetworkInterfaceList llNetIfs; // list of network interfaces
197
198#ifdef VBOX_WITH_USB
199 USBDeviceFilterList llChildren; // all USB device filters
200 USBDeviceFilterList llUSBDeviceFilters; // USB device filters in use by the USB proxy service
201
202 /** Pointer to the USBProxyService object. */
203 USBProxyService *pUSBProxyService;
204#endif /* VBOX_WITH_USB */
205
206 // list of host drives; lazily created by getDVDDrives() and getFloppyDrives(),
207 // and protected by the medium tree lock handle (including the bools).
208 MediaList llDVDDrives,
209 llFloppyDrives;
210 bool fDVDDrivesListBuilt,
211 fFloppyDrivesListBuilt;
212
213#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
214 /** Object with information about host drives */
215 VBoxMainDriveInfo hostDrives;
216#endif
217
218 /** @name Features that can be queried with GetProcessorFeature.
219 * @{ */
220 bool fVTSupported,
221 fLongModeSupported,
222 fPAESupported,
223 fNestedPagingSupported,
224 fRecheckVTSupported;
225
226 /** @} */
227
228 /** 3D hardware acceleration supported? Tristate, -1 meaning not probed. */
229 int f3DAccelerationSupported;
230
231 HostPowerService *pHostPowerService;
232 /** Host's DNS informaton fetching */
233 HostDnsMonitorProxy hostDnsMonitorProxy;
234};
235
236
237////////////////////////////////////////////////////////////////////////////////
238//
239// Constructor / destructor
240//
241////////////////////////////////////////////////////////////////////////////////
242DEFINE_EMPTY_CTOR_DTOR(Host)
243
244HRESULT Host::FinalConstruct()
245{
246 return BaseFinalConstruct();
247}
248
249void Host::FinalRelease()
250{
251 uninit();
252 BaseFinalRelease();
253}
254
255/**
256 * Initializes the host object.
257 *
258 * @param aParent VirtualBox parent object.
259 */
260HRESULT Host::init(VirtualBox *aParent)
261{
262 HRESULT hrc;
263 LogFlowThisFunc(("aParent=%p\n", aParent));
264
265 /* Enclose the state transition NotReady->InInit->Ready */
266 AutoInitSpan autoInitSpan(this);
267 AssertReturn(autoInitSpan.isOk(), E_FAIL);
268
269 m = new Data();
270
271 m->pParent = aParent;
272
273#ifdef VBOX_WITH_USB
274 /*
275 * Create and initialize the USB Proxy Service.
276 */
277# if defined (RT_OS_DARWIN)
278 m->pUSBProxyService = new USBProxyServiceDarwin(this);
279# elif defined (RT_OS_LINUX)
280 m->pUSBProxyService = new USBProxyServiceLinux(this);
281# elif defined (RT_OS_OS2)
282 m->pUSBProxyService = new USBProxyServiceOs2(this);
283# elif defined (RT_OS_SOLARIS)
284 m->pUSBProxyService = new USBProxyServiceSolaris(this);
285# elif defined (RT_OS_WINDOWS)
286 m->pUSBProxyService = new USBProxyServiceWindows(this);
287# elif defined (RT_OS_FREEBSD)
288 m->pUSBProxyService = new USBProxyServiceFreeBSD(this);
289# else
290 m->pUSBProxyService = new USBProxyService(this);
291# endif
292 hrc = m->pUSBProxyService->init();
293 AssertComRCReturn(hrc, hrc);
294#endif /* VBOX_WITH_USB */
295
296#ifdef VBOX_WITH_RESOURCE_USAGE_API
297 i_registerMetrics(aParent->performanceCollector());
298#endif /* VBOX_WITH_RESOURCE_USAGE_API */
299 /* Create the list of network interfaces so their metrics get registered. */
300 i_updateNetIfList();
301
302 m->hostDnsMonitorProxy.init(HostDnsMonitor::getHostDnsMonitor(), m->pParent);
303
304#if defined (RT_OS_WINDOWS)
305 m->pHostPowerService = new HostPowerServiceWin(m->pParent);
306#elif defined (RT_OS_DARWIN)
307 m->pHostPowerService = new HostPowerServiceDarwin(m->pParent);
308#else
309 m->pHostPowerService = new HostPowerService(m->pParent);
310#endif
311
312 /* Cache the features reported by GetProcessorFeature. */
313 m->fVTSupported = false;
314 m->fLongModeSupported = false;
315 m->fPAESupported = false;
316 m->fNestedPagingSupported = false;
317 m->fRecheckVTSupported = false;
318
319 if (ASMHasCpuId())
320 {
321 /* Note! This code is duplicated in SUPDrv.c and other places! */
322 uint32_t uMaxId, uVendorEBX, uVendorECX, uVendorEDX;
323 ASMCpuId(0, &uMaxId, &uVendorEBX, &uVendorECX, &uVendorEDX);
324 if (ASMIsValidStdRange(uMaxId))
325 {
326 /* PAE? */
327 uint32_t uDummy, fFeaturesEcx, fFeaturesEdx;
328 ASMCpuId(1, &uDummy, &uDummy, &fFeaturesEcx, &fFeaturesEdx);
329 m->fPAESupported = RT_BOOL(fFeaturesEdx & X86_CPUID_FEATURE_EDX_PAE);
330
331 /* Long Mode? */
332 uint32_t uExtMaxId, fExtFeaturesEcx, fExtFeaturesEdx;
333 ASMCpuId(0x80000000, &uExtMaxId, &uDummy, &uDummy, &uDummy);
334 ASMCpuId(0x80000001, &uDummy, &uDummy, &fExtFeaturesEcx, &fExtFeaturesEdx);
335 m->fLongModeSupported = ASMIsValidExtRange(uExtMaxId)
336 && (fExtFeaturesEdx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
337
338#if defined(RT_OS_DARWIN) && ARCH_BITS == 32 /* darwin.x86 has some optimizations of 64-bit on 32-bit. */
339 int f64bitCapable = 0;
340 size_t cbParameter = sizeof(f64bitCapable);
341 if (sysctlbyname("hw.cpu64bit_capable", &f64bitCapable, &cbParameter, NULL, NULL) != -1)
342 m->fLongModeSupported = f64bitCapable != 0;
343#endif
344
345 /* VT-x? */
346 if ( ASMIsIntelCpuEx(uVendorEBX, uVendorECX, uVendorEDX)
347 || ASMIsViaCentaurCpuEx(uVendorEBX, uVendorECX, uVendorEDX))
348 {
349 if ( (fFeaturesEcx & X86_CPUID_FEATURE_ECX_VMX)
350 && (fFeaturesEdx & X86_CPUID_FEATURE_EDX_MSR)
351 && (fFeaturesEdx & X86_CPUID_FEATURE_EDX_FXSR)
352 )
353 {
354 int rc = SUPR3QueryVTxSupported();
355 if (RT_SUCCESS(rc))
356 m->fVTSupported = true;
357 }
358 }
359 /* AMD-V */
360 else if (ASMIsAmdCpuEx(uVendorEBX, uVendorECX, uVendorEDX))
361 {
362 if ( (fExtFeaturesEcx & X86_CPUID_AMD_FEATURE_ECX_SVM)
363 && (fFeaturesEdx & X86_CPUID_FEATURE_EDX_MSR)
364 && (fFeaturesEdx & X86_CPUID_FEATURE_EDX_FXSR)
365 && ASMIsValidExtRange(uExtMaxId)
366 )
367 {
368 m->fVTSupported = true;
369
370 /* Query AMD features. */
371 if (uExtMaxId >= 0x8000000a)
372 {
373 uint32_t fSVMFeaturesEdx;
374 ASMCpuId(0x8000000a, &uDummy, &uDummy, &uDummy, &fSVMFeaturesEdx);
375 if (fSVMFeaturesEdx & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
376 m->fNestedPagingSupported = true;
377 }
378 }
379 }
380 }
381 }
382
383 /* Check with SUPDrv if VT-x and AMD-V are really supported (may fail). */
384 if (m->fVTSupported)
385 {
386 int rc = SUPR3InitEx(false /*fUnrestricted*/, NULL);
387 if (RT_SUCCESS(rc))
388 {
389 uint32_t fVTCaps;
390 rc = SUPR3QueryVTCaps(&fVTCaps);
391 if (RT_SUCCESS(rc))
392 {
393 Assert(fVTCaps & (SUPVTCAPS_AMD_V | SUPVTCAPS_VT_X));
394 if (fVTCaps & SUPVTCAPS_NESTED_PAGING)
395 m->fNestedPagingSupported = true;
396 else
397 Assert(m->fNestedPagingSupported == false);
398 }
399 else
400 {
401 LogRel(("SUPR0QueryVTCaps -> %Rrc\n", rc));
402 m->fVTSupported = m->fNestedPagingSupported = false;
403 }
404 }
405 else
406 m->fRecheckVTSupported = true; /* Try again later when the driver is loaded. */
407 }
408
409#ifdef VBOX_WITH_CROGL
410 /* Test for 3D hardware acceleration support later when (if ever) need. */
411 m->f3DAccelerationSupported = -1;
412#else
413 m->f3DAccelerationSupported = false;
414#endif
415
416#if defined (RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
417 /* Extract the list of configured host-only interfaces */
418 std::set<Utf8Str> aConfiguredNames;
419 SafeArray<BSTR> aGlobalExtraDataKeys;
420 hrc = aParent->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys));
421 AssertMsg(SUCCEEDED(hrc), ("VirtualBox::GetExtraDataKeys failed with %Rhrc\n", hrc));
422 for (size_t i = 0; i < aGlobalExtraDataKeys.size(); ++i)
423 {
424 Utf8Str strKey = aGlobalExtraDataKeys[i];
425
426 if (!strKey.startsWith("HostOnly/vboxnet"))
427 continue;
428
429 size_t pos = strKey.find("/", sizeof("HostOnly/vboxnet"));
430 if (pos != Utf8Str::npos)
431 aConfiguredNames.insert(strKey.substr(sizeof("HostOnly"),
432 pos - sizeof("HostOnly")));
433 }
434
435 for (std::set<Utf8Str>::const_iterator it = aConfiguredNames.begin();
436 it != aConfiguredNames.end();
437 ++it)
438 {
439 ComPtr<IHostNetworkInterface> hif;
440 ComPtr<IProgress> progress;
441
442 int r = NetIfCreateHostOnlyNetworkInterface(m->pParent,
443 hif.asOutParam(),
444 progress.asOutParam(),
445 it->c_str());
446 if (RT_FAILURE(r))
447 LogRel(("failed to create %s, error (0x%x)\n", it->c_str(), r));
448 }
449
450#endif /* defined (RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) */
451
452 /* Confirm a successful initialization */
453 autoInitSpan.setSucceeded();
454
455 return S_OK;
456}
457
458/**
459 * Uninitializes the host object and sets the ready flag to FALSE.
460 * Called either from FinalRelease() or by the parent when it gets destroyed.
461 */
462void Host::uninit()
463{
464 LogFlowThisFunc(("\n"));
465
466 /* Enclose the state transition Ready->InUninit->NotReady */
467 AutoUninitSpan autoUninitSpan(this);
468 if (autoUninitSpan.uninitDone())
469 return;
470
471#ifdef VBOX_WITH_RESOURCE_USAGE_API
472 PerformanceCollector *aCollector = m->pParent->performanceCollector();
473 i_unregisterMetrics (aCollector);
474#endif /* VBOX_WITH_RESOURCE_USAGE_API */
475 /*
476 * Note that unregisterMetrics() has unregistered all metrics associated
477 * with Host including network interface ones. We can destroy network
478 * interface objects now.
479 */
480 m->llNetIfs.clear();
481
482#ifdef VBOX_WITH_USB
483 /* wait for USB proxy service to terminate before we uninit all USB
484 * devices */
485 LogFlowThisFunc(("Stopping USB proxy service...\n"));
486 delete m->pUSBProxyService;
487 m->pUSBProxyService = NULL;
488 LogFlowThisFunc(("Done stopping USB proxy service.\n"));
489#endif
490
491 delete m->pHostPowerService;
492
493#ifdef VBOX_WITH_USB
494 /* uninit all USB device filters still referenced by clients
495 * Note! HostUSBDeviceFilter::uninit() will modify llChildren. */
496 while (!m->llChildren.empty())
497 {
498 ComObjPtr<HostUSBDeviceFilter> &pChild = m->llChildren.front();
499 pChild->uninit();
500 }
501
502 m->llUSBDeviceFilters.clear();
503#endif
504
505 delete m;
506 m = NULL;
507}
508
509////////////////////////////////////////////////////////////////////////////////
510//
511// IHost public methods
512//
513////////////////////////////////////////////////////////////////////////////////
514
515/**
516 * Returns a list of host DVD drives.
517 *
518 * @returns COM status code
519 * @param drives address of result pointer
520 */
521
522HRESULT Host::getDVDDrives(std::vector<ComPtr<IMedium> > &aDVDDrives)
523{
524 AutoWriteLock alock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
525 MediaList *pList;
526 aDVDDrives.resize(0);
527 HRESULT rc = i_getDrives(DeviceType_DVD, true /* fRefresh */, pList);
528 if (SUCCEEDED(rc))
529 {
530 aDVDDrives.resize(pList->size());
531 size_t i = 0;
532 for (MediaList::const_iterator it= pList->begin(); it!= pList->end(); ++it, ++i)
533 {
534 (*it).queryInterfaceTo(aDVDDrives[i].asOutParam());
535 }
536 }
537
538 return rc;
539}
540
541/**
542 * Returns a list of host floppy drives.
543 *
544 * @returns COM status code
545 * @param drives address of result pointer
546 */
547HRESULT Host::getFloppyDrives(std::vector<ComPtr<IMedium> > &aFloppyDrives)
548{
549 AutoWriteLock alock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
550
551 MediaList *pList;
552 aFloppyDrives.resize(0);
553 HRESULT rc = i_getDrives(DeviceType_Floppy, true /* fRefresh */, pList);
554 if (SUCCEEDED(rc))
555 {
556 aFloppyDrives.resize(pList->size());
557 size_t i = 0;
558 for (MediaList::const_iterator it = pList->begin(); it != pList->end(); ++it, ++i)
559 {
560 (*it).queryInterfaceTo(aFloppyDrives[i].asOutParam());
561 }
562 }
563
564 return rc;
565}
566
567
568#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
569# define VBOX_APP_NAME L"VirtualBox"
570
571static int vboxNetWinAddComponent(std::list< ComObjPtr<HostNetworkInterface> > *pPist,
572 INetCfgComponent *pncc)
573{
574 LPWSTR lpszName;
575 GUID IfGuid;
576 HRESULT hr;
577 int rc = VERR_GENERAL_FAILURE;
578
579 hr = pncc->GetDisplayName(&lpszName);
580 Assert(hr == S_OK);
581 if (hr == S_OK)
582 {
583 Bstr name((CBSTR)lpszName);
584
585 hr = pncc->GetInstanceGuid(&IfGuid);
586 Assert(hr == S_OK);
587 if (hr == S_OK)
588 {
589 /* create a new object and add it to the list */
590 ComObjPtr<HostNetworkInterface> iface;
591 iface.createObject();
592 /* remove the curly bracket at the end */
593 if (SUCCEEDED(iface->init (name, name, Guid (IfGuid), HostNetworkInterfaceType_Bridged)))
594 {
595// iface->setVirtualBox(m->pParent);
596 pPist->push_back(iface);
597 rc = VINF_SUCCESS;
598 }
599 else
600 {
601 Assert(0);
602 }
603 }
604 CoTaskMemFree(lpszName);
605 }
606
607 return rc;
608}
609#endif /* defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
610
611/**
612 * Returns a list of host network interfaces.
613 *
614 * @returns COM status code
615 * @param drives address of result pointer
616 */
617HRESULT Host::getNetworkInterfaces(std::vector<ComPtr<IHostNetworkInterface> > &aNetworkInterfaces)
618{
619 aNetworkInterfaces.resize(0);
620#if defined(RT_OS_WINDOWS) || defined(VBOX_WITH_NETFLT) /*|| defined(RT_OS_OS2)*/
621 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
622# ifdef VBOX_WITH_HOSTNETIF_API
623 int rc = i_updateNetIfList();
624 if (rc)
625 {
626 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
627 }
628 aNetworkInterfaces.resize(m->llNetIfs.size());
629 size_t i = 0;
630 for (HostNetworkInterfaceList::iterator it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it, ++i)
631 {
632 (*it).queryInterfaceTo(aNetworkInterfaces[i].asOutParam());
633 }
634
635 return S_OK;
636
637# else
638 std::list<ComObjPtr<HostNetworkInterface> > list;
639
640# if defined(RT_OS_DARWIN)
641 PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
642 while (pEtherNICs)
643 {
644 ComObjPtr<HostNetworkInterface> IfObj;
645 IfObj.createObject();
646 if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), Guid(pEtherNICs->Uuid), HostNetworkInterfaceType_Bridged)))
647 list.push_back(IfObj);
648
649 /* next, free current */
650 void *pvFree = pEtherNICs;
651 pEtherNICs = pEtherNICs->pNext;
652 RTMemFree(pvFree);
653 }
654
655# elif defined RT_OS_WINDOWS
656# ifndef VBOX_WITH_NETFLT
657 hr = E_NOTIMPL;
658# else /* # if defined VBOX_WITH_NETFLT */
659 INetCfg *pNc;
660 INetCfgComponent *pMpNcc;
661 INetCfgComponent *pTcpIpNcc;
662 LPWSTR lpszApp;
663 HRESULT hr;
664 IEnumNetCfgBindingPath *pEnumBp;
665 INetCfgBindingPath *pBp;
666 IEnumNetCfgBindingInterface *pEnumBi;
667 INetCfgBindingInterface *pBi;
668
669 /* we are using the INetCfg API for getting the list of miniports */
670 hr = VBoxNetCfgWinQueryINetCfg(FALSE,
671 VBOX_APP_NAME,
672 &pNc,
673 &lpszApp);
674 Assert(hr == S_OK);
675 if (hr == S_OK)
676 {
677# ifdef VBOX_NETFLT_ONDEMAND_BIND
678 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
679 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
680# else
681 /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
682 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
683# ifndef VBOX_WITH_HARDENING
684 if (hr != S_OK)
685 {
686 /* TODO: try to install the netflt from here */
687 }
688# endif
689
690# endif
691
692 if (hr == S_OK)
693 {
694 hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
695 Assert(hr == S_OK);
696 if (hr == S_OK)
697 {
698 hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
699 Assert(hr == S_OK || hr == S_FALSE);
700 while (hr == S_OK)
701 {
702 /* S_OK == enabled, S_FALSE == disabled */
703 if (pBp->IsEnabled() == S_OK)
704 {
705 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
706 Assert(hr == S_OK);
707 if (hr == S_OK)
708 {
709 hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
710 Assert(hr == S_OK);
711 while (hr == S_OK)
712 {
713 hr = pBi->GetLowerComponent(&pMpNcc);
714 Assert(hr == S_OK);
715 if (hr == S_OK)
716 {
717 ULONG uComponentStatus;
718 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
719 Assert(hr == S_OK);
720 if (hr == S_OK)
721 {
722 if (uComponentStatus == 0)
723 {
724 vboxNetWinAddComponent(&list, pMpNcc);
725 }
726 }
727 VBoxNetCfgWinReleaseRef(pMpNcc);
728 }
729 VBoxNetCfgWinReleaseRef(pBi);
730
731 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
732 }
733 VBoxNetCfgWinReleaseRef(pEnumBi);
734 }
735 }
736 VBoxNetCfgWinReleaseRef(pBp);
737
738 hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
739 }
740 VBoxNetCfgWinReleaseRef(pEnumBp);
741 }
742 VBoxNetCfgWinReleaseRef(pTcpIpNcc);
743 }
744 else
745 {
746 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)\n", hr));
747 }
748
749 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
750 }
751# endif /* # if defined VBOX_WITH_NETFLT */
752
753
754# elif defined RT_OS_LINUX
755 int sock = socket(AF_INET, SOCK_DGRAM, 0);
756 if (sock >= 0)
757 {
758 char pBuffer[2048];
759 struct ifconf ifConf;
760 ifConf.ifc_len = sizeof(pBuffer);
761 ifConf.ifc_buf = pBuffer;
762 if (ioctl(sock, SIOCGIFCONF, &ifConf) >= 0)
763 {
764 for (struct ifreq *pReq = ifConf.ifc_req; (char*)pReq < pBuffer + ifConf.ifc_len; pReq++)
765 {
766 if (ioctl(sock, SIOCGIFHWADDR, pReq) >= 0)
767 {
768 if (pReq->ifr_hwaddr.sa_family == ARPHRD_ETHER)
769 {
770 RTUUID uuid;
771 Assert(sizeof(uuid) <= sizeof(*pReq));
772 memcpy(&uuid, pReq, sizeof(uuid));
773
774 ComObjPtr<HostNetworkInterface> IfObj;
775 IfObj.createObject();
776 if (SUCCEEDED(IfObj->init(Bstr(pReq->ifr_name), Guid(uuid), HostNetworkInterfaceType_Bridged)))
777 list.push_back(IfObj);
778 }
779 }
780 }
781 }
782 close(sock);
783 }
784# endif /* RT_OS_LINUX */
785
786 SafeIfaceArray<IHostNetworkInterface> networkInterfaces (list);
787 networkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
788
789 return S_OK;
790
791# endif
792#else
793 /* Not implemented / supported on this platform. */
794 ReturnComNotImplemented();
795#endif
796}
797
798HRESULT Host::getUSBDevices(std::vector<ComPtr<IHostUSBDevice> > &aUSBDevices)
799{
800 aUSBDevices.resize(0);
801#ifdef VBOX_WITH_USB
802 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
803 HRESULT rc = i_checkUSBProxyService();
804 if (FAILED(rc)) return rc;
805 SafeIfaceArray<IHostUSBDevice> resultArr;
806 rc = m->pUSBProxyService->getDeviceCollection(ComSafeArrayAsOutParam(resultArr));
807 if (FAILED(rc)) return rc;
808 aUSBDevices.resize(resultArr.size());
809 for (size_t i = 0; i < resultArr.size(); ++i)
810 {
811 ComObjPtr<IHostUSBDevice> iHu = resultArr[i];
812 iHu.queryInterfaceTo(aUSBDevices[i].asOutParam());
813 }
814
815 return rc;
816
817#else
818 /* Note: The GUI depends on this method returning E_NOTIMPL with no
819 * extended error info to indicate that USB is simply not available
820 * (w/o treating it as a failure), for example, as in OSE. */
821 NOREF(aUSBDeviceFilters);
822# ifndef RT_OS_WINDOWS
823 NOREF(aUSBDeviceFiltersSize);
824# endif
825 ReturnComNotImplemented();
826#endif
827 return S_OK;
828}
829
830/**
831 * This method return the list of registered name servers
832 */
833HRESULT Host::getNameServers(std::vector<com::Utf8Str> &aNameServers)
834{
835 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
836
837 aNameServers.resize(0);
838 com::SafeArray<BSTR> resultArr;
839 resultArr.setNull();
840 HRESULT rc = m->hostDnsMonitorProxy.GetNameServers(ComSafeArrayAsOutParam(resultArr));
841 if (FAILED(rc)) return rc;
842 aNameServers.resize(resultArr.size());
843 for (size_t i = 0; i < resultArr.size(); ++i)
844 {
845 aNameServers[i] = com::Utf8Str(resultArr[i]);
846 }
847 return rc;
848}
849
850
851/**
852 * This method returns the domain name of the host
853 */
854HRESULT Host::getDomainName(com::Utf8Str &aDomainName)
855{
856 BSTR bstr;
857 HRESULT rc = m->hostDnsMonitorProxy.GetDomainName(&bstr);
858 if SUCCEEDED(rc)
859 aDomainName = com::Utf8Str(bstr);
860 return rc;
861 /* XXX: note here should be synchronization with thread polling state
862 * changes in name resoving system on host */
863}
864
865
866/**
867 * This method returns the search string.
868 */
869HRESULT Host::getSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
870{
871 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
872 com::SafeArray<BSTR> resultArr;
873 aSearchStrings.resize(0);
874 resultArr.setNull();
875 HRESULT rc = m->hostDnsMonitorProxy.GetSearchStrings(ComSafeArrayAsOutParam(resultArr));
876 if (FAILED(rc)) return rc;
877 aSearchStrings.resize(resultArr.size());
878 for (size_t i = 0; i < resultArr.size(); ++i)
879 {
880 aSearchStrings[i] = com::Utf8Str(resultArr[i]);
881 }
882 return rc;
883}
884
885HRESULT Host::getUSBDeviceFilters(std::vector<ComPtr<IHostUSBDeviceFilter> > &aUSBDeviceFilters)
886{
887 aUSBDeviceFilters.resize(0);
888#ifdef VBOX_WITH_USB
889 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
890 HRESULT rc = i_checkUSBProxyService();
891 if (FAILED(rc)) return rc;
892 aUSBDeviceFilters.resize(m->llUSBDeviceFilters.size());
893 size_t i = 0;
894 for (USBDeviceFilterList::iterator it = m->llUSBDeviceFilters.begin(); it != m->llUSBDeviceFilters.end(); ++it, ++i)
895 {
896 (*it).queryInterfaceTo(aUSBDeviceFilters[i].asOutParam());
897 }
898
899 return rc;
900#else
901 /* Note: The GUI depends on this method returning E_NOTIMPL with no
902 * extended error info to indicate that USB is simply not available
903 * (w/o treating it as a failure), for example, as in OSE. */
904 NOREF(aUSBDeviceFilters);
905# ifndef RT_OS_WINDOWS
906 NOREF(aUSBDeviceFiltersSize);
907# endif
908 ReturnComNotImplemented();
909#endif
910}
911
912/**
913 * Returns the number of installed logical processors
914 *
915 * @returns COM status code
916 * @param count address of result variable
917 */
918
919HRESULT Host::getProcessorCount(ULONG *aCount)
920{
921 // no locking required
922
923 *aCount = RTMpGetPresentCount();
924 return S_OK;
925}
926
927/**
928 * Returns the number of online logical processors
929 *
930 * @returns COM status code
931 * @param count address of result variable
932 */
933HRESULT Host::getProcessorOnlineCount(ULONG *aCount)
934{
935 // no locking required
936
937 *aCount = RTMpGetOnlineCount();
938 return S_OK;
939}
940
941/**
942 * Returns the number of installed physical processor cores.
943 *
944 * @returns COM status code
945 * @param count address of result variable
946 */
947HRESULT Host::getProcessorCoreCount(ULONG *aCount)
948{
949 // no locking required
950
951 *aCount = RTMpGetPresentCoreCount();
952 return S_OK;
953}
954
955/**
956 * Returns the number of installed physical processor cores.
957 *
958 * @returns COM status code
959 * @param count address of result variable
960 */
961HRESULT Host::getProcessorOnlineCoreCount(ULONG *aCount)
962{
963 // no locking required
964
965 *aCount = RTMpGetOnlineCoreCount();
966 return S_OK;
967}
968
969/**
970 * Returns the (approximate) maximum speed of the given host CPU in MHz
971 *
972 * @returns COM status code
973 * @param cpu id to get info for.
974 * @param speed address of result variable, speed is 0 if unknown or aCpuId is invalid.
975 */
976HRESULT Host::getProcessorSpeed(ULONG aCpuId,
977 ULONG *aSpeed)
978{
979 // no locking required
980
981 *aSpeed = RTMpGetMaxFrequency(aCpuId);
982 return S_OK;
983}
984
985/**
986 * Returns a description string for the host CPU
987 *
988 * @returns COM status code
989 * @param cpu id to get info for.
990 * @param description address of result variable, empty string if not known or aCpuId is invalid.
991 */
992HRESULT Host::getProcessorDescription(ULONG aCpuId, com::Utf8Str &aDescription)
993{
994 // no locking required
995
996 char szCPUModel[80];
997 szCPUModel[0] = 0;
998 int vrc = RTMpGetDescription(aCpuId, szCPUModel, sizeof(szCPUModel));
999 if (RT_FAILURE(vrc))
1000 return E_FAIL; /** @todo error reporting? */
1001 aDescription = Utf8Str(szCPUModel);
1002 return S_OK;
1003}
1004
1005/**
1006 * Returns whether a host processor feature is supported or not
1007 *
1008 * @returns COM status code
1009 * @param Feature to query.
1010 * @param address of supported bool result variable
1011 */
1012HRESULT Host::getProcessorFeature(ProcessorFeature_T aFeature, BOOL *aSupported)
1013{
1014 /* Validate input. */
1015 switch (aFeature)
1016 {
1017 case ProcessorFeature_HWVirtEx:
1018 case ProcessorFeature_PAE:
1019 case ProcessorFeature_LongMode:
1020 case ProcessorFeature_NestedPaging:
1021 break;
1022 default:
1023 return setError(E_INVALIDARG, tr("The aFeature value %d (%#x) is out of range."), (int)aFeature, (int)aFeature);
1024 }
1025
1026 /* Do the job. */
1027 AutoCaller autoCaller(this);
1028 HRESULT hrc = autoCaller.rc();
1029 if (SUCCEEDED(hrc))
1030 {
1031 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1032
1033 if ( m->fRecheckVTSupported
1034 && ( aFeature == ProcessorFeature_HWVirtEx
1035 || aFeature == ProcessorFeature_NestedPaging)
1036 )
1037 {
1038 alock.release();
1039
1040 /* Perhaps the driver is available now... */
1041 int rc = SUPR3InitEx(false /*fUnrestricted*/, NULL);
1042 if (RT_SUCCESS(rc))
1043 {
1044 uint32_t fVTCaps;
1045 rc = SUPR3QueryVTCaps(&fVTCaps);
1046
1047 AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
1048 if (RT_SUCCESS(rc))
1049 {
1050 Assert(fVTCaps & (SUPVTCAPS_AMD_V | SUPVTCAPS_VT_X));
1051 if (fVTCaps & SUPVTCAPS_NESTED_PAGING)
1052 m->fNestedPagingSupported = true;
1053 else
1054 Assert(m->fNestedPagingSupported == false);
1055 }
1056 else
1057 {
1058 LogRel(("SUPR0QueryVTCaps -> %Rrc\n", rc));
1059 m->fVTSupported = m->fNestedPagingSupported = true;
1060 }
1061 }
1062
1063 alock.acquire();
1064 }
1065
1066 switch (aFeature)
1067 {
1068 case ProcessorFeature_HWVirtEx:
1069 *aSupported = m->fVTSupported;
1070 break;
1071
1072 case ProcessorFeature_PAE:
1073 *aSupported = m->fPAESupported;
1074 break;
1075
1076 case ProcessorFeature_LongMode:
1077 *aSupported = m->fLongModeSupported;
1078 break;
1079
1080 case ProcessorFeature_NestedPaging:
1081 *aSupported = m->fNestedPagingSupported;
1082 break;
1083
1084 default:
1085 AssertFailed();
1086 }
1087 }
1088 return hrc;
1089}
1090
1091/**
1092 * Returns the specific CPUID leaf.
1093 *
1094 * @returns COM status code
1095 * @param aCpuId The CPU number. Mostly ignored.
1096 * @param aLeaf The leaf number.
1097 * @param aSubLeaf The sub-leaf number.
1098 * @param aValEAX Where to return EAX.
1099 * @param aValEBX Where to return EBX.
1100 * @param aValECX Where to return ECX.
1101 * @param aValEDX Where to return EDX.
1102 */
1103HRESULT Host::getProcessorCPUIDLeaf(ULONG aCpuId, ULONG aLeaf, ULONG aSubLeaf,
1104 ULONG *aValEAX, ULONG *aValEBX, ULONG *aValECX, ULONG *aValEDX)
1105{
1106 // no locking required
1107
1108 /* Check that the CPU is online. */
1109 /** @todo later use RTMpOnSpecific. */
1110 if (!RTMpIsCpuOnline(aCpuId))
1111 return RTMpIsCpuPresent(aCpuId)
1112 ? setError(E_FAIL, tr("CPU no.%u is not present"), aCpuId)
1113 : setError(E_FAIL, tr("CPU no.%u is not online"), aCpuId);
1114
1115 uint32_t uEAX, uEBX, uECX, uEDX;
1116 ASMCpuId_Idx_ECX(aLeaf, aSubLeaf, &uEAX, &uEBX, &uECX, &uEDX);
1117 *aValEAX = uEAX;
1118 *aValEBX = uEBX;
1119 *aValECX = uECX;
1120 *aValEDX = uEDX;
1121
1122 return S_OK;
1123}
1124
1125/**
1126 * Returns the amount of installed system memory in megabytes
1127 *
1128 * @returns COM status code
1129 * @param size address of result variable
1130 */
1131HRESULT Host::getMemorySize(ULONG *aSize)
1132{
1133 // no locking required
1134
1135 uint64_t cb;
1136 int rc = RTSystemQueryTotalRam(&cb);
1137 if (RT_FAILURE(rc))
1138 return E_FAIL;
1139 *aSize = (ULONG)(cb / _1M);
1140 return S_OK;
1141}
1142
1143/**
1144 * Returns the current system memory free space in megabytes
1145 *
1146 * @returns COM status code
1147 * @param available address of result variable
1148 */
1149HRESULT Host::getMemoryAvailable(ULONG *aAvailable)
1150{
1151 // no locking required
1152
1153 uint64_t cb;
1154 int rc = RTSystemQueryAvailableRam(&cb);
1155 if (RT_FAILURE(rc))
1156 return E_FAIL;
1157 *aAvailable = (ULONG)(cb / _1M);
1158 return S_OK;
1159}
1160
1161/**
1162 * Returns the name string of the host operating system
1163 *
1164 * @returns COM status code
1165 * @param os address of result variable
1166 */
1167HRESULT Host::getOperatingSystem(com::Utf8Str &aOperatingSystem)
1168{
1169 // no locking required
1170
1171 char szOSName[80];
1172 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szOSName, sizeof(szOSName));
1173 if (RT_FAILURE(vrc))
1174 return E_FAIL; /** @todo error reporting? */
1175 aOperatingSystem = Utf8Str(szOSName);
1176 return S_OK;
1177}
1178
1179/**
1180 * Returns the version string of the host operating system
1181 *
1182 * @returns COM status code
1183 * @param os address of result variable
1184 */
1185HRESULT Host::getOSVersion(com::Utf8Str &aVersion)
1186{
1187 // no locking required
1188
1189 /* Get the OS release. Reserve some buffer space for the service pack. */
1190 char szOSRelease[128];
1191 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szOSRelease, sizeof(szOSRelease) - 32);
1192 if (RT_FAILURE(vrc))
1193 return E_FAIL; /** @todo error reporting? */
1194
1195 /* Append the service pack if present. */
1196 char szOSServicePack[80];
1197 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szOSServicePack, sizeof(szOSServicePack));
1198 if (RT_FAILURE(vrc))
1199 {
1200 if (vrc != VERR_NOT_SUPPORTED)
1201 return E_FAIL; /** @todo error reporting? */
1202 szOSServicePack[0] = '\0';
1203 }
1204 if (szOSServicePack[0] != '\0')
1205 {
1206 char *psz = strchr(szOSRelease, '\0');
1207 RTStrPrintf(psz, &szOSRelease[sizeof(szOSRelease)] - psz, "sp%s", szOSServicePack);
1208 }
1209
1210 aVersion = szOSRelease;
1211 return S_OK;
1212}
1213
1214/**
1215 * Returns the current host time in milliseconds since 1970-01-01 UTC.
1216 *
1217 * @returns COM status code
1218 * @param time address of result variable
1219 */
1220HRESULT Host::getUTCTime(LONG64 *aUTCTime)
1221{
1222 // no locking required
1223
1224 RTTIMESPEC now;
1225 *aUTCTime = RTTimeSpecGetMilli(RTTimeNow(&now));
1226
1227 return S_OK;
1228}
1229
1230
1231HRESULT Host::getAcceleration3DAvailable(BOOL *aSupported)
1232{
1233 HRESULT hrc = S_OK;
1234 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1235 if (m->f3DAccelerationSupported != -1)
1236 *aSupported = m->f3DAccelerationSupported;
1237 else
1238 {
1239 alock.release();
1240
1241#ifdef VBOX_WITH_CROGL
1242 bool fSupported = VBoxOglIs3DAccelerationSupported();
1243#else
1244 bool fSupported = false; /* shoudn't get here, but just in case. */
1245#endif
1246 AutoWriteLock alock2(this COMMA_LOCKVAL_SRC_POS);
1247
1248 m->f3DAccelerationSupported = fSupported;
1249 alock2.release();
1250 *aSupported = fSupported;
1251 }
1252
1253#ifdef DEBUG_misha
1254 AssertMsgFailed(("should not be here any more!\n"));
1255#endif
1256
1257 return hrc;
1258}
1259
1260HRESULT Host::createHostOnlyNetworkInterface(ComPtr<IHostNetworkInterface> &aHostInterface,
1261 ComPtr<IProgress> &aProgress)
1262
1263{
1264#ifdef VBOX_WITH_HOSTNETIF_API
1265 /* No need to lock anything. If there ever will - watch out, the function
1266 * called below grabs the VirtualBox lock. */
1267 IHostNetworkInterface *iHn = aHostInterface;
1268 IProgress *iHn2 = aProgress;
1269
1270 int r = NetIfCreateHostOnlyNetworkInterface(m->pParent, &iHn, &iHn2);
1271 if (RT_SUCCESS(r))
1272 {
1273 if (!iHn)
1274 return setError(E_FAIL,
1275 tr("Unable to create a host network interface"));
1276
1277#if !defined(RT_OS_WINDOWS)
1278 Bstr tmpAddr, tmpMask, tmpName;
1279 HRESULT hrc;
1280 hrc = aHostInterface->COMGETTER(Name)(tmpName.asOutParam());
1281 ComAssertComRCRet(hrc, hrc);
1282 hrc = aHostInterface->COMGETTER(IPAddress)(tmpAddr.asOutParam());
1283 ComAssertComRCRet(hrc, hrc);
1284 hrc = aHostInterface->COMGETTER(NetworkMask)(tmpMask.asOutParam());
1285 ComAssertComRCRet(hrc, hrc);
1286 /*
1287 * We need to write the default IP address and mask to extra data now,
1288 * so the interface gets re-created after vboxnetadp.ko reload.
1289 * Note that we avoid calling EnableStaticIpConfig since it would
1290 * change the address on host's interface as well and we want to
1291 * postpone the change until VM actually starts.
1292 */
1293 hrc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress",
1294 tmpName.raw()).raw(),
1295 tmpAddr.raw());
1296 ComAssertComRCRet(hrc, hrc);
1297
1298 hrc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask",
1299 tmpName.raw()).raw(),
1300 tmpMask.raw());
1301 ComAssertComRCRet(hrc, hrc);
1302#endif
1303 }
1304
1305 return S_OK;
1306#else
1307 return E_NOTIMPL;
1308#endif
1309}
1310
1311HRESULT Host::removeHostOnlyNetworkInterface(const com::Guid &aId,
1312 ComPtr<IProgress> &aProgress)
1313
1314{
1315#ifdef VBOX_WITH_HOSTNETIF_API
1316 /* No need to lock anything, the code below does not touch the state
1317 * of the host object. If that ever changes then check for lock order
1318 * violations with the called functions. */
1319
1320 Bstr name;
1321 HRESULT rc;
1322
1323 /* first check whether an interface with the given name already exists */
1324 {
1325 ComPtr<IHostNetworkInterface> iface;
1326 rc = findHostNetworkInterfaceById(aId, iface);
1327 if (FAILED(rc))
1328 return setError(VBOX_E_OBJECT_NOT_FOUND,
1329 tr("Host network interface with UUID {%RTuuid} does not exist"),
1330 Guid (aId).raw());
1331 rc = iface->COMGETTER(Name)(name.asOutParam());
1332 ComAssertComRCRet(rc, rc);
1333 }
1334
1335 IProgress *iPr = aProgress;
1336
1337 int r = NetIfRemoveHostOnlyNetworkInterface(m->pParent, Guid(aId).ref(), &iPr);
1338 if (RT_SUCCESS(r))
1339 {
1340 /* Drop configuration parameters for removed interface */
1341 rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", name.raw()).raw(), NULL);
1342 rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", name.raw()).raw(), NULL);
1343 rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", name.raw()).raw(), NULL);
1344 rc = m->pParent->SetExtraData(BstrFmt("HostOnly/%ls/IPV6NetMask", name.raw()).raw(), NULL);
1345
1346 return S_OK;
1347 }
1348
1349 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1350#else
1351 return E_NOTIMPL;
1352#endif
1353}
1354
1355HRESULT Host::createUSBDeviceFilter(const com::Utf8Str &aName,
1356 ComPtr<IHostUSBDeviceFilter> &aFilter)
1357{
1358#ifdef VBOX_WITH_USB
1359
1360 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1361
1362 ComObjPtr<HostUSBDeviceFilter> filter;
1363 filter.createObject();
1364 HRESULT rc = filter->init(this, Bstr(aName).raw());
1365 ComAssertComRCRet(rc, rc);
1366 rc = filter.queryInterfaceTo(aFilter.asOutParam());
1367 AssertComRCReturn(rc, rc);
1368 return S_OK;
1369#else
1370 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1371 * extended error info to indicate that USB is simply not available
1372 * (w/o treating it as a failure), for example, as in OSE. */
1373 NOREF(aName);
1374 NOREF(aFilter);
1375 ReturnComNotImplemented();
1376#endif
1377}
1378
1379HRESULT Host::insertUSBDeviceFilter(ULONG aPosition,
1380 const ComPtr<IHostUSBDeviceFilter> &aFilter)
1381{
1382#ifdef VBOX_WITH_USB
1383 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1384
1385 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1386
1387 clearError();
1388 MultiResult rc = i_checkUSBProxyService();
1389 if (FAILED(rc)) return rc;
1390
1391 ComObjPtr<HostUSBDeviceFilter> pFilter;
1392 for (USBDeviceFilterList::iterator it = m->llChildren.begin();
1393 it != m->llChildren.end();
1394 ++it)
1395 {
1396 if (*it == aFilter)
1397 {
1398 pFilter = *it;
1399 break;
1400 }
1401 }
1402 if (pFilter.isNull())
1403 return setError(VBOX_E_INVALID_OBJECT_STATE,
1404 tr("The given USB device filter is not created within this VirtualBox instance"));
1405
1406 if (pFilter->mInList)
1407 return setError(E_INVALIDARG,
1408 tr("The given USB device filter is already in the list"));
1409
1410 /* iterate to the position... */
1411 USBDeviceFilterList::iterator itPos = m->llUSBDeviceFilters.begin();
1412 std::advance(itPos, aPosition);
1413 /* ...and insert */
1414 m->llUSBDeviceFilters.insert(itPos, pFilter);
1415 pFilter->mInList = true;
1416
1417 /* notify the proxy (only when the filter is active) */
1418 if ( m->pUSBProxyService->isActive()
1419 && pFilter->getData().mActive)
1420 {
1421 ComAssertRet(pFilter->getId() == NULL, E_FAIL);
1422 pFilter->getId() = m->pUSBProxyService->insertFilter(&pFilter->getData().mUSBFilter);
1423 }
1424
1425 // save the global settings; for that we should hold only the VirtualBox lock
1426 alock.release();
1427 AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1428 return rc = m->pParent->saveSettings();
1429#else
1430
1431 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1432 * extended error info to indicate that USB is simply not available
1433 * (w/o treating it as a failure), for example, as in OSE. */
1434 NOREF(aPosition);
1435 NOREF(aFilter);
1436 ReturnComNotImplemented();
1437#endif
1438}
1439
1440HRESULT Host::removeUSBDeviceFilter(ULONG aPosition)
1441{
1442#ifdef VBOX_WITH_USB
1443
1444 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1445 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1446
1447 clearError();
1448 MultiResult rc = i_checkUSBProxyService();
1449 if (FAILED(rc)) return rc;
1450
1451 if (!m->llUSBDeviceFilters.size())
1452 return setError(E_INVALIDARG,
1453 tr("The USB device filter list is empty"));
1454
1455 if (aPosition >= m->llUSBDeviceFilters.size())
1456 return setError(E_INVALIDARG,
1457 tr("Invalid position: %lu (must be in range [0, %lu])"),
1458 aPosition, m->llUSBDeviceFilters.size() - 1);
1459
1460 ComObjPtr<HostUSBDeviceFilter> filter;
1461 {
1462 /* iterate to the position... */
1463 USBDeviceFilterList::iterator it = m->llUSBDeviceFilters.begin();
1464 std::advance (it, aPosition);
1465 /* ...get an element from there... */
1466 filter = *it;
1467 /* ...and remove */
1468 filter->mInList = false;
1469 m->llUSBDeviceFilters.erase(it);
1470 }
1471
1472 /* notify the proxy (only when the filter is active) */
1473 if (m->pUSBProxyService->isActive() && filter->getData().mActive)
1474 {
1475 ComAssertRet(filter->getId() != NULL, E_FAIL);
1476 m->pUSBProxyService->removeFilter(filter->getId());
1477 filter->getId() = NULL;
1478 }
1479
1480 // save the global settings; for that we should hold only the VirtualBox lock
1481 alock.release();
1482 AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
1483 return rc = m->pParent->saveSettings();
1484#else
1485 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1486 * extended error info to indicate that USB is simply not available
1487 * (w/o treating it as a failure), for example, as in OSE. */
1488 NOREF(aPosition);
1489 ReturnComNotImplemented();
1490#endif
1491}
1492
1493HRESULT Host::findHostDVDDrive(const com::Utf8Str &aName,
1494 ComPtr<IMedium> &aDrive)
1495{
1496 ComObjPtr<Medium> medium;
1497 HRESULT rc = i_findHostDriveByNameOrId(DeviceType_DVD, aName, medium);
1498 if (SUCCEEDED(rc))
1499 rc = medium.queryInterfaceTo(aDrive.asOutParam());
1500 else
1501 rc = setError(rc, Medium::tr("The host DVD drive named '%ls' could not be found"), Bstr(aName).raw());
1502 return rc;
1503}
1504
1505HRESULT Host::findHostFloppyDrive(const com::Utf8Str &aName, ComPtr<IMedium> &aDrive)
1506{
1507 aDrive = NULL;
1508
1509 ComObjPtr<Medium>medium;
1510
1511 HRESULT rc = i_findHostDriveByNameOrId(DeviceType_Floppy, aName, medium);
1512 if (SUCCEEDED(rc))
1513 return medium.queryInterfaceTo(aDrive.asOutParam());
1514 else
1515 return setError(rc, Medium::tr("The host floppy drive named '%ls' could not be found"), Bstr(aName).raw());
1516}
1517
1518HRESULT Host::findHostNetworkInterfaceByName(const com::Utf8Str &aName,
1519 ComPtr<IHostNetworkInterface> &aNetworkInterface)
1520{
1521#ifndef VBOX_WITH_HOSTNETIF_API
1522 return E_NOTIMPL;
1523#else
1524 if (!aName.length())
1525 return E_INVALIDARG;
1526
1527 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1528
1529 aNetworkInterface = NULL;
1530
1531 ComObjPtr<HostNetworkInterface> found;
1532 int rc = i_updateNetIfList();
1533 if (RT_FAILURE(rc))
1534 {
1535 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
1536 return E_FAIL;
1537 }
1538 for (HostNetworkInterfaceList::iterator it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it)
1539 {
1540 Bstr n;
1541 (*it)->COMGETTER(Name)(n.asOutParam());
1542 if (n == aName)
1543 found = *it;
1544 }
1545
1546 if (!found)
1547 return setError(E_INVALIDARG,
1548 HostNetworkInterface::tr("The host network interface with the given name could not be found"));
1549
1550 return found.queryInterfaceTo(aNetworkInterface.asOutParam());
1551#endif
1552}
1553
1554HRESULT Host::findHostNetworkInterfaceById(const com::Guid &aId,
1555 ComPtr<IHostNetworkInterface> &aNetworkInterface)
1556{
1557#ifndef VBOX_WITH_HOSTNETIF_API
1558 return E_NOTIMPL;
1559#else
1560 if (!aId.isValid())
1561 return E_INVALIDARG;
1562
1563 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1564
1565 aNetworkInterface = NULL;
1566
1567 ComObjPtr<HostNetworkInterface> found;
1568 int rc = i_updateNetIfList();
1569 if (RT_FAILURE(rc))
1570 {
1571 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
1572 return E_FAIL;
1573 }
1574 HostNetworkInterfaceList::iterator it;
1575 for (it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it)
1576 {
1577 Bstr g;
1578 (*it)->COMGETTER(Id)(g.asOutParam());
1579 if (Guid(g) == aId)
1580 found = *it;
1581 }
1582
1583 if (!found)
1584 return setError(E_INVALIDARG,
1585 HostNetworkInterface::tr("The host network interface with the given GUID could not be found"));
1586 return found.queryInterfaceTo(aNetworkInterface.asOutParam());
1587
1588#endif
1589}
1590
1591HRESULT Host::findHostNetworkInterfacesOfType(HostNetworkInterfaceType_T aType,
1592 std::vector<ComPtr<IHostNetworkInterface> > &aNetworkInterfaces)
1593{
1594 aNetworkInterfaces.resize(0);
1595#ifdef VBOX_WITH_HOSTNETIF_API
1596 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1597 int rc = i_updateNetIfList();
1598 if (RT_FAILURE(rc))
1599 return E_FAIL;
1600
1601 HostNetworkInterfaceList resultList;
1602
1603 for (HostNetworkInterfaceList::iterator it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it)
1604 {
1605 HostNetworkInterfaceType_T t;
1606 HRESULT hr = (*it)->COMGETTER(InterfaceType)(&t);
1607 if (FAILED(hr))
1608 return hr;
1609
1610 if (t == aType)
1611 resultList.push_back(*it);
1612 }
1613 aNetworkInterfaces.resize(resultList.size());
1614 size_t i = 0;
1615 for (HostNetworkInterfaceList::iterator it = resultList.begin(); it != resultList.end(); ++it, ++i)
1616 {
1617 (*it).queryInterfaceTo(aNetworkInterfaces[i].asOutParam());
1618 }
1619
1620 return S_OK;
1621#else
1622 return E_NOTIMPL;
1623#endif
1624}
1625
1626HRESULT Host::findUSBDeviceByAddress(const com::Utf8Str &aName,
1627 ComPtr<IHostUSBDevice> &aDevice)
1628{
1629#ifdef VBOX_WITH_USB
1630
1631 aDevice = NULL;
1632 SafeIfaceArray<IHostUSBDevice> devsvec;
1633 HRESULT rc = COMGETTER(USBDevices)(ComSafeArrayAsOutParam(devsvec));
1634 if (FAILED(rc)) return rc;
1635
1636 for (size_t i = 0; i < devsvec.size(); ++i)
1637 {
1638 Bstr address;
1639 rc = devsvec[i]->COMGETTER(Address)(address.asOutParam());
1640 if (FAILED(rc)) return rc;
1641 if (address == aName)
1642 {
1643 return (ComObjPtr<IHostUSBDevice>(devsvec[i]).queryInterfaceTo(aDevice.asOutParam()));
1644 }
1645 }
1646
1647 return setErrorNoLog(VBOX_E_OBJECT_NOT_FOUND,
1648 tr("Could not find a USB device with address '%ls'"),
1649 Bstr(aName).raw());
1650
1651#else /* !VBOX_WITH_USB */
1652 NOREF(aAddress);
1653 NOREF(aDevice);
1654 return E_NOTIMPL;
1655#endif /* !VBOX_WITH_USB */
1656}
1657HRESULT Host::findUSBDeviceById(const com::Guid &aId,
1658 ComPtr<IHostUSBDevice> &aDevice)
1659{
1660#ifdef VBOX_WITH_USB
1661 if (!aId.isValid())
1662 return E_INVALIDARG;
1663
1664 aDevice = NULL;
1665
1666 SafeIfaceArray<IHostUSBDevice> devsvec;
1667 HRESULT rc = COMGETTER(USBDevices)(ComSafeArrayAsOutParam(devsvec));
1668 if (FAILED(rc)) return rc;
1669
1670 for (size_t i = 0; i < devsvec.size(); ++i)
1671 {
1672 Bstr id;
1673 rc = devsvec[i]->COMGETTER(Id)(id.asOutParam());
1674 if (FAILED(rc)) return rc;
1675 if (Guid(id) == aId)
1676 {
1677 return (ComObjPtr<IHostUSBDevice>(devsvec[i]).queryInterfaceTo(aDevice.asOutParam()));
1678 }
1679 }
1680 return setErrorNoLog (VBOX_E_OBJECT_NOT_FOUND, tr (
1681 "Could not find a USB device with uuid {%RTuuid}"),
1682 aId.raw());
1683
1684#else /* !VBOX_WITH_USB */
1685 NOREF(aId);
1686 NOREF(aDevice);
1687 return E_NOTIMPL;
1688#endif /* !VBOX_WITH_USB */
1689}
1690
1691HRESULT Host::generateMACAddress(com::Utf8Str &aAddress)
1692{
1693 // no locking required
1694 i_generateMACAddress(aAddress);
1695 return S_OK;
1696}
1697
1698/**
1699 * Returns a list of host video capture devices (webcams, etc).
1700 *
1701 * @returns COM status code
1702 * @param aVideoInputDevices Array of interface pointers to be filled.
1703 */
1704HRESULT Host::getVideoInputDevices(std::vector<ComPtr<IHostVideoInputDevice> > &aVideoInputDevices)
1705{
1706 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1707 HostVideoInputDeviceList list;
1708 aVideoInputDevices.resize(0);
1709
1710 HRESULT hr = HostVideoInputDevice::queryHostDevices(m->pParent, &list);
1711
1712 if (SUCCEEDED(hr))
1713 {
1714 aVideoInputDevices.resize(list.size());
1715 size_t i = 0;
1716 for (HostVideoInputDeviceList::const_iterator it = list.begin(); it != list.end(); ++it, ++i)
1717 {
1718 (*it).queryInterfaceTo(aVideoInputDevices[i].asOutParam());
1719 }
1720 }
1721
1722 return hr;
1723}
1724
1725// public methods only for internal purposes
1726////////////////////////////////////////////////////////////////////////////////
1727
1728HRESULT Host::i_loadSettings(const settings::Host &data)
1729{
1730 HRESULT rc = S_OK;
1731#ifdef VBOX_WITH_USB
1732 AutoCaller autoCaller(this);
1733 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1734
1735 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1736
1737 for (settings::USBDeviceFiltersList::const_iterator it = data.llUSBDeviceFilters.begin();
1738 it != data.llUSBDeviceFilters.end();
1739 ++it)
1740 {
1741 const settings::USBDeviceFilter &f = *it;
1742 ComObjPtr<HostUSBDeviceFilter> pFilter;
1743 pFilter.createObject();
1744 rc = pFilter->init(this, f);
1745 if (FAILED(rc)) break;
1746
1747 m->llUSBDeviceFilters.push_back(pFilter);
1748 pFilter->mInList = true;
1749
1750 /* notify the proxy (only when the filter is active) */
1751 if (pFilter->getData().mActive)
1752 {
1753 HostUSBDeviceFilter *flt = pFilter; /* resolve ambiguity */
1754 flt->getId() = m->pUSBProxyService->insertFilter(&pFilter->getData().mUSBFilter);
1755 }
1756 }
1757#else
1758 NOREF(data);
1759#endif /* VBOX_WITH_USB */
1760 return rc;
1761}
1762
1763HRESULT Host::i_saveSettings(settings::Host &data)
1764{
1765#ifdef VBOX_WITH_USB
1766 AutoCaller autoCaller(this);
1767 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1768
1769 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1770
1771 data.llUSBDeviceFilters.clear();
1772
1773 for (USBDeviceFilterList::const_iterator it = m->llUSBDeviceFilters.begin();
1774 it != m->llUSBDeviceFilters.end();
1775 ++it)
1776 {
1777 ComObjPtr<HostUSBDeviceFilter> pFilter = *it;
1778 settings::USBDeviceFilter f;
1779 pFilter->saveSettings(f);
1780 data.llUSBDeviceFilters.push_back(f);
1781 }
1782#else
1783 NOREF(data);
1784#endif /* VBOX_WITH_USB */
1785
1786 return S_OK;
1787}
1788
1789/**
1790 * Sets the given pointer to point to the static list of DVD or floppy
1791 * drives in the Host instance data, depending on the @a mediumType
1792 * parameter.
1793 *
1794 * This builds the list on the first call; it adds or removes host drives
1795 * that may have changed if fRefresh == true.
1796 *
1797 * The caller must hold the medium tree write lock before calling this.
1798 * To protect the list to which the caller's pointer points, the caller
1799 * must also hold that lock.
1800 *
1801 * @param mediumType Must be DeviceType_Floppy or DeviceType_DVD.
1802 * @param fRefresh Whether to refresh the host drives list even if this is not the first call.
1803 * @param pll Caller's pointer which gets set to the static list of host drives.
1804 * @returns COM status code
1805 */
1806HRESULT Host::i_getDrives(DeviceType_T mediumType,
1807 bool fRefresh,
1808 MediaList *&pll)
1809{
1810 HRESULT rc = S_OK;
1811 Assert(m->pParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
1812
1813 MediaList llNew;
1814 MediaList *pllCached;
1815 bool *pfListBuilt = NULL;
1816
1817 switch (mediumType)
1818 {
1819 case DeviceType_DVD:
1820 if (!m->fDVDDrivesListBuilt || fRefresh)
1821 {
1822 rc = i_buildDVDDrivesList(llNew);
1823 if (FAILED(rc))
1824 return rc;
1825 pfListBuilt = &m->fDVDDrivesListBuilt;
1826 }
1827 pllCached = &m->llDVDDrives;
1828 break;
1829
1830 case DeviceType_Floppy:
1831 if (!m->fFloppyDrivesListBuilt || fRefresh)
1832 {
1833 rc = i_buildFloppyDrivesList(llNew);
1834 if (FAILED(rc))
1835 return rc;
1836 pfListBuilt = &m->fFloppyDrivesListBuilt;
1837 }
1838 pllCached = &m->llFloppyDrives;
1839 break;
1840
1841 default:
1842 return E_INVALIDARG;
1843 }
1844
1845 if (pfListBuilt)
1846 {
1847 // a list was built in llNew above:
1848 if (!*pfListBuilt)
1849 {
1850 // this was the first call (instance bool is still false): then just copy the whole list and return
1851 *pllCached = llNew;
1852 // and mark the instance data as "built"
1853 *pfListBuilt = true;
1854 }
1855 else
1856 {
1857 // list was built, and this was a subsequent call: then compare the old and the new lists
1858
1859 // remove drives from the cached list which are no longer present
1860 for (MediaList::iterator itCached = pllCached->begin();
1861 itCached != pllCached->end();
1862 /*nothing */)
1863 {
1864 Medium *pCached = *itCached;
1865 const Utf8Str strLocationCached = pCached->getLocationFull();
1866 bool fFound = false;
1867 for (MediaList::iterator itNew = llNew.begin();
1868 itNew != llNew.end();
1869 ++itNew)
1870 {
1871 Medium *pNew = *itNew;
1872 const Utf8Str strLocationNew = pNew->getLocationFull();
1873 if (strLocationNew == strLocationCached)
1874 {
1875 fFound = true;
1876 break;
1877 }
1878 }
1879 if (!fFound)
1880 itCached = pllCached->erase(itCached);
1881 else
1882 ++itCached;
1883 }
1884
1885 // add drives to the cached list that are not on there yet
1886 for (MediaList::iterator itNew = llNew.begin();
1887 itNew != llNew.end();
1888 ++itNew)
1889 {
1890 Medium *pNew = *itNew;
1891 const Utf8Str strLocationNew = pNew->getLocationFull();
1892 bool fFound = false;
1893 for (MediaList::iterator itCached = pllCached->begin();
1894 itCached != pllCached->end();
1895 ++itCached)
1896 {
1897 Medium *pCached = *itCached;
1898 const Utf8Str strLocationCached = pCached->getLocationFull();
1899 if (strLocationNew == strLocationCached)
1900 {
1901 fFound = true;
1902 break;
1903 }
1904 }
1905
1906 if (!fFound)
1907 pllCached->push_back(pNew);
1908 }
1909 }
1910 }
1911
1912 // return cached list to caller
1913 pll = pllCached;
1914
1915 return rc;
1916}
1917
1918/**
1919 * Goes through the list of host drives that would be returned by getDrives()
1920 * and looks for a host drive with the given UUID. If found, it sets pMedium
1921 * to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
1922 *
1923 * @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
1924 * @param uuid Medium UUID of host drive to look for.
1925 * @param fRefresh Whether to refresh the host drives list (see getDrives())
1926 * @param pMedium Medium object, if found…
1927 * @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
1928 */
1929HRESULT Host::i_findHostDriveById(DeviceType_T mediumType,
1930 const Guid &uuid,
1931 bool fRefresh,
1932 ComObjPtr<Medium> &pMedium)
1933{
1934 MediaList *pllMedia;
1935
1936 AutoWriteLock wlock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
1937 HRESULT rc = i_getDrives(mediumType, fRefresh, pllMedia);
1938 if (SUCCEEDED(rc))
1939 {
1940 for (MediaList::iterator it = pllMedia->begin();
1941 it != pllMedia->end();
1942 ++it)
1943 {
1944 Medium *pThis = *it;
1945 AutoCaller mediumCaller(pThis);
1946 AutoReadLock mediumLock(pThis COMMA_LOCKVAL_SRC_POS);
1947 if (pThis->getId() == uuid)
1948 {
1949 pMedium = pThis;
1950 return S_OK;
1951 }
1952 }
1953 }
1954
1955 return VBOX_E_OBJECT_NOT_FOUND;
1956}
1957
1958/**
1959 * Goes through the list of host drives that would be returned by getDrives()
1960 * and looks for a host drive with the given name. If found, it sets pMedium
1961 * to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
1962 *
1963 * @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
1964 * @param strLocationFull Name (path) of host drive to look for.
1965 * @param fRefresh Whether to refresh the host drives list (see getDrives())
1966 * @param pMedium Medium object, if found…
1967 * @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
1968 */
1969HRESULT Host::i_findHostDriveByName(DeviceType_T mediumType,
1970 const Utf8Str &strLocationFull,
1971 bool fRefresh,
1972 ComObjPtr<Medium> &pMedium)
1973{
1974 MediaList *pllMedia;
1975
1976 AutoWriteLock wlock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
1977 HRESULT rc = i_getDrives(mediumType, fRefresh, pllMedia);
1978 if (SUCCEEDED(rc))
1979 {
1980 for (MediaList::iterator it = pllMedia->begin();
1981 it != pllMedia->end();
1982 ++it)
1983 {
1984 Medium *pThis = *it;
1985 AutoCaller mediumCaller(pThis);
1986 AutoReadLock mediumLock(pThis COMMA_LOCKVAL_SRC_POS);
1987 if (pThis->getLocationFull() == strLocationFull)
1988 {
1989 pMedium = pThis;
1990 return S_OK;
1991 }
1992 }
1993 }
1994
1995 return VBOX_E_OBJECT_NOT_FOUND;
1996}
1997
1998/**
1999 * Goes through the list of host drives that would be returned by getDrives()
2000 * and looks for a host drive with the given name, location or ID. If found,
2001 * it sets pMedium to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
2002 *
2003 * @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
2004 * @param strNameOrId Name or full location or UUID of host drive to look for.
2005 * @param pMedium Medium object, if found…
2006 * @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
2007 */
2008HRESULT Host::i_findHostDriveByNameOrId(DeviceType_T mediumType,
2009 const Utf8Str &strNameOrId,
2010 ComObjPtr<Medium> &pMedium)
2011{
2012 AutoWriteLock wlock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
2013
2014 Guid uuid(strNameOrId);
2015 if (uuid.isValid() && !uuid.isZero())
2016 return i_findHostDriveById(mediumType, uuid, true /* fRefresh */, pMedium);
2017
2018 // string is not a syntactically valid UUID: try a name then
2019 return i_findHostDriveByName(mediumType, strNameOrId, true /* fRefresh */, pMedium);
2020}
2021
2022/**
2023 * Called from getDrives() to build the DVD drives list.
2024 * @param pll
2025 * @return
2026 */
2027HRESULT Host::i_buildDVDDrivesList(MediaList &list)
2028{
2029 HRESULT rc = S_OK;
2030
2031 Assert(m->pParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
2032
2033 try
2034 {
2035#if defined(RT_OS_WINDOWS)
2036 int sz = GetLogicalDriveStrings(0, NULL);
2037 TCHAR *hostDrives = new TCHAR[sz+1];
2038 GetLogicalDriveStrings(sz, hostDrives);
2039 wchar_t driveName[3] = { '?', ':', '\0' };
2040 TCHAR *p = hostDrives;
2041 do
2042 {
2043 if (GetDriveType(p) == DRIVE_CDROM)
2044 {
2045 driveName[0] = *p;
2046 ComObjPtr<Medium> hostDVDDriveObj;
2047 hostDVDDriveObj.createObject();
2048 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(driveName));
2049 list.push_back(hostDVDDriveObj);
2050 }
2051 p += _tcslen(p) + 1;
2052 }
2053 while (*p);
2054 delete[] hostDrives;
2055
2056#elif defined(RT_OS_SOLARIS)
2057# ifdef VBOX_USE_LIBHAL
2058 if (!i_getDVDInfoFromHal(list))
2059# endif
2060 {
2061 i_getDVDInfoFromDevTree(list);
2062 }
2063
2064#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
2065 if (RT_SUCCESS(m->hostDrives.updateDVDs()))
2066 for (DriveInfoList::const_iterator it = m->hostDrives.DVDBegin();
2067 SUCCEEDED(rc) && it != m->hostDrives.DVDEnd(); ++it)
2068 {
2069 ComObjPtr<Medium> hostDVDDriveObj;
2070 Utf8Str location(it->mDevice);
2071 Utf8Str description(it->mDescription);
2072 if (SUCCEEDED(rc))
2073 rc = hostDVDDriveObj.createObject();
2074 if (SUCCEEDED(rc))
2075 rc = hostDVDDriveObj->init(m->pParent, DeviceType_DVD, location, description);
2076 if (SUCCEEDED(rc))
2077 list.push_back(hostDVDDriveObj);
2078 }
2079#elif defined(RT_OS_DARWIN)
2080 PDARWINDVD cur = DarwinGetDVDDrives();
2081 while (cur)
2082 {
2083 ComObjPtr<Medium> hostDVDDriveObj;
2084 hostDVDDriveObj.createObject();
2085 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(cur->szName));
2086 list.push_back(hostDVDDriveObj);
2087
2088 /* next */
2089 void *freeMe = cur;
2090 cur = cur->pNext;
2091 RTMemFree(freeMe);
2092 }
2093#else
2094 /* PORTME */
2095#endif
2096 }
2097 catch(std::bad_alloc &)
2098 {
2099 rc = E_OUTOFMEMORY;
2100 }
2101 return rc;
2102}
2103
2104/**
2105 * Called from getDrives() to build the floppy drives list.
2106 * @param list
2107 * @return
2108 */
2109HRESULT Host::i_buildFloppyDrivesList(MediaList &list)
2110{
2111 HRESULT rc = S_OK;
2112
2113 Assert(m->pParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
2114
2115 try
2116 {
2117#ifdef RT_OS_WINDOWS
2118 int sz = GetLogicalDriveStrings(0, NULL);
2119 TCHAR *hostDrives = new TCHAR[sz+1];
2120 GetLogicalDriveStrings(sz, hostDrives);
2121 wchar_t driveName[3] = { '?', ':', '\0' };
2122 TCHAR *p = hostDrives;
2123 do
2124 {
2125 if (GetDriveType(p) == DRIVE_REMOVABLE)
2126 {
2127 driveName[0] = *p;
2128 ComObjPtr<Medium> hostFloppyDriveObj;
2129 hostFloppyDriveObj.createObject();
2130 hostFloppyDriveObj->init(m->pParent, DeviceType_Floppy, Bstr(driveName));
2131 list.push_back(hostFloppyDriveObj);
2132 }
2133 p += _tcslen(p) + 1;
2134 }
2135 while (*p);
2136 delete[] hostDrives;
2137#elif defined(RT_OS_LINUX)
2138 if (RT_SUCCESS(m->hostDrives.updateFloppies()))
2139 for (DriveInfoList::const_iterator it = m->hostDrives.FloppyBegin();
2140 SUCCEEDED(rc) && it != m->hostDrives.FloppyEnd(); ++it)
2141 {
2142 ComObjPtr<Medium> hostFloppyDriveObj;
2143 Utf8Str location(it->mDevice);
2144 Utf8Str description(it->mDescription);
2145 if (SUCCEEDED(rc))
2146 rc = hostFloppyDriveObj.createObject();
2147 if (SUCCEEDED(rc))
2148 rc = hostFloppyDriveObj->init(m->pParent, DeviceType_Floppy, location, description);
2149 if (SUCCEEDED(rc))
2150 list.push_back(hostFloppyDriveObj);
2151 }
2152#else
2153 NOREF(list);
2154 /* PORTME */
2155#endif
2156 }
2157 catch(std::bad_alloc &)
2158 {
2159 rc = E_OUTOFMEMORY;
2160 }
2161
2162 return rc;
2163}
2164
2165#ifdef VBOX_WITH_USB
2166USBProxyService* Host::i_usbProxyService()
2167{
2168 return m->pUSBProxyService;
2169}
2170
2171HRESULT Host::i_addChild(HostUSBDeviceFilter *pChild)
2172{
2173 AutoCaller autoCaller(this);
2174 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2175
2176 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2177
2178 m->llChildren.push_back(pChild);
2179
2180 return S_OK;
2181}
2182
2183HRESULT Host::i_removeChild(HostUSBDeviceFilter *pChild)
2184{
2185 AutoCaller autoCaller(this);
2186 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2187
2188 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2189
2190 for (USBDeviceFilterList::iterator it = m->llChildren.begin();
2191 it != m->llChildren.end();
2192 ++it)
2193 {
2194 if (*it == pChild)
2195 {
2196 m->llChildren.erase(it);
2197 break;
2198 }
2199 }
2200
2201 return S_OK;
2202}
2203
2204VirtualBox* Host::i_parent()
2205{
2206 return m->pParent;
2207}
2208
2209/**
2210 * Called by setter methods of all USB device filters.
2211 */
2212HRESULT Host::i_onUSBDeviceFilterChange(HostUSBDeviceFilter *aFilter,
2213 BOOL aActiveChanged /* = FALSE */)
2214{
2215 AutoCaller autoCaller(this);
2216 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2217
2218 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2219
2220 if (aFilter->mInList)
2221 {
2222 if (aActiveChanged)
2223 {
2224 // insert/remove the filter from the proxy
2225 if (aFilter->getData().mActive)
2226 {
2227 ComAssertRet(aFilter->getId() == NULL, E_FAIL);
2228 aFilter->getId() = m->pUSBProxyService->insertFilter(&aFilter->getData().mUSBFilter);
2229 }
2230 else
2231 {
2232 ComAssertRet(aFilter->getId() != NULL, E_FAIL);
2233 m->pUSBProxyService->removeFilter(aFilter->getId());
2234 aFilter->getId() = NULL;
2235 }
2236 }
2237 else
2238 {
2239 if (aFilter->getData().mActive)
2240 {
2241 // update the filter in the proxy
2242 ComAssertRet(aFilter->getId() != NULL, E_FAIL);
2243 m->pUSBProxyService->removeFilter(aFilter->getId());
2244 aFilter->getId() = m->pUSBProxyService->insertFilter(&aFilter->getData().mUSBFilter);
2245 }
2246 }
2247
2248 // save the global settings... yeah, on every single filter property change
2249 // for that we should hold only the VirtualBox lock
2250 alock.release();
2251 AutoWriteLock vboxLock(m->pParent COMMA_LOCKVAL_SRC_POS);
2252 return m->pParent->saveSettings();
2253 }
2254
2255 return S_OK;
2256}
2257
2258
2259/**
2260 * Interface for obtaining a copy of the USBDeviceFilterList,
2261 * used by the USBProxyService.
2262 *
2263 * @param aGlobalFilters Where to put the global filter list copy.
2264 * @param aMachines Where to put the machine vector.
2265 */
2266void Host::i_getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters)
2267{
2268 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
2269
2270 *aGlobalFilters = m->llUSBDeviceFilters;
2271}
2272
2273#endif /* VBOX_WITH_USB */
2274
2275// private methods
2276////////////////////////////////////////////////////////////////////////////////
2277
2278#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
2279
2280/**
2281 * Helper function to get the slice number from a device path
2282 *
2283 * @param pszDevLinkPath Pointer to a device path (/dev/(r)dsk/c7d1t0d0s3 etc.)
2284 * @returns Pointer to the slice portion of the given path.
2285 */
2286static char *solarisGetSliceFromPath(const char *pszDevLinkPath)
2287{
2288 char *pszFound = NULL;
2289 char *pszSlice = strrchr(pszDevLinkPath, 's');
2290 char *pszDisk = strrchr(pszDevLinkPath, 'd');
2291 if (pszSlice && pszSlice > pszDisk)
2292 pszFound = pszSlice;
2293 else
2294 pszFound = pszDisk;
2295
2296 if (pszFound && RT_C_IS_DIGIT(pszFound[1]))
2297 return pszFound;
2298
2299 return NULL;
2300}
2301
2302/**
2303 * Walk device links and returns an allocated path for the first one in the snapshot.
2304 *
2305 * @param DevLink Handle to the device link being walked.
2306 * @param pvArg Opaque data containing the pointer to the path.
2307 * @returns Pointer to an allocated device path string.
2308 */
2309static int solarisWalkDevLink(di_devlink_t DevLink, void *pvArg)
2310{
2311 char **ppszPath = (char **)pvArg;
2312 *ppszPath = strdup(di_devlink_path(DevLink));
2313 return DI_WALK_TERMINATE;
2314}
2315
2316/**
2317 * Walk all devices in the system and enumerate CD/DVD drives.
2318 * @param Node Handle to the current node.
2319 * @param pvArg Opaque data (holds list pointer).
2320 * @returns Solaris specific code whether to continue walking or not.
2321 */
2322static int solarisWalkDeviceNodeForDVD(di_node_t Node, void *pvArg)
2323{
2324 PSOLARISDVD *ppDrives = (PSOLARISDVD *)pvArg;
2325
2326 /*
2327 * Check for "removable-media" or "hotpluggable" instead of "SCSI" so that we also include USB CD-ROMs.
2328 * As unfortunately the Solaris drivers only export these common properties.
2329 */
2330 int *pInt = NULL;
2331 if ( di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "removable-media", &pInt) >= 0
2332 || di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "hotpluggable", &pInt) >= 0)
2333 {
2334 if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "inquiry-device-type", &pInt) > 0
2335 && ( *pInt == DTYPE_RODIRECT /* CDROM */
2336 || *pInt == DTYPE_OPTICAL)) /* Optical Drive */
2337 {
2338 char *pszProduct = NULL;
2339 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-product-id", &pszProduct) > 0)
2340 {
2341 char *pszVendor = NULL;
2342 if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-vendor-id", &pszVendor) > 0)
2343 {
2344 /*
2345 * Found a DVD drive, we need to scan the minor nodes to find the correct
2346 * slice that represents the whole drive. "s2" is always the whole drive for CD/DVDs.
2347 */
2348 int Major = di_driver_major(Node);
2349 di_minor_t Minor = DI_MINOR_NIL;
2350 di_devlink_handle_t DevLink = di_devlink_init(NULL /* name */, 0 /* flags */);
2351 if (DevLink)
2352 {
2353 while ((Minor = di_minor_next(Node, Minor)) != DI_MINOR_NIL)
2354 {
2355 dev_t Dev = di_minor_devt(Minor);
2356 if ( Major != (int)major(Dev)
2357 || di_minor_spectype(Minor) == S_IFBLK
2358 || di_minor_type(Minor) != DDM_MINOR)
2359 {
2360 continue;
2361 }
2362
2363 char *pszMinorPath = di_devfs_minor_path(Minor);
2364 if (!pszMinorPath)
2365 continue;
2366
2367 char *pszDevLinkPath = NULL;
2368 di_devlink_walk(DevLink, NULL, pszMinorPath, DI_PRIMARY_LINK, &pszDevLinkPath, solarisWalkDevLink);
2369 di_devfs_path_free(pszMinorPath);
2370
2371 if (pszDevLinkPath)
2372 {
2373 char *pszSlice = solarisGetSliceFromPath(pszDevLinkPath);
2374 if ( pszSlice && !strcmp(pszSlice, "s2")
2375 && !strncmp(pszDevLinkPath, RT_STR_TUPLE("/dev/rdsk"))) /* We want only raw disks */
2376 {
2377 /*
2378 * We've got a fully qualified DVD drive. Add it to the list.
2379 */
2380 PSOLARISDVD pDrive = (PSOLARISDVD)RTMemAllocZ(sizeof(SOLARISDVD));
2381 if (RT_LIKELY(pDrive))
2382 {
2383 RTStrPrintf(pDrive->szDescription, sizeof(pDrive->szDescription), "%s %s", pszVendor, pszProduct);
2384 RTStrCopy(pDrive->szRawDiskPath, sizeof(pDrive->szRawDiskPath), pszDevLinkPath);
2385 if (*ppDrives)
2386 pDrive->pNext = *ppDrives;
2387 *ppDrives = pDrive;
2388
2389 /* We're not interested in any of the other slices, stop minor nodes traversal. */
2390 free(pszDevLinkPath);
2391 break;
2392 }
2393 }
2394 free(pszDevLinkPath);
2395 }
2396 }
2397 di_devlink_fini(&DevLink);
2398 }
2399 }
2400 }
2401 }
2402 }
2403 return DI_WALK_CONTINUE;
2404}
2405
2406/**
2407 * Solaris specific function to enumerate CD/DVD drives via the device tree.
2408 * Works on Solaris 10 as well as OpenSolaris without depending on libhal.
2409 */
2410void Host::i_getDVDInfoFromDevTree(std::list<ComObjPtr<Medium> > &list)
2411{
2412 PSOLARISDVD pDrives = NULL;
2413 di_node_t RootNode = di_init("/", DINFOCPYALL);
2414 if (RootNode != DI_NODE_NIL)
2415 di_walk_node(RootNode, DI_WALK_CLDFIRST, &pDrives, solarisWalkDeviceNodeForDVD);
2416
2417 di_fini(RootNode);
2418
2419 while (pDrives)
2420 {
2421 ComObjPtr<Medium> hostDVDDriveObj;
2422 hostDVDDriveObj.createObject();
2423 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(pDrives->szRawDiskPath), Bstr(pDrives->szDescription));
2424 list.push_back(hostDVDDriveObj);
2425
2426 void *pvDrive = pDrives;
2427 pDrives = pDrives->pNext;
2428 RTMemFree(pvDrive);
2429 }
2430}
2431
2432/* Solaris hosts, loading libhal at runtime */
2433
2434/**
2435 * Helper function to query the hal subsystem for information about DVD drives attached to the
2436 * system.
2437 *
2438 * @returns true if information was successfully obtained, false otherwise
2439 * @retval list drives found will be attached to this list
2440 */
2441bool Host::i_getDVDInfoFromHal(std::list<ComObjPtr<Medium> > &list)
2442{
2443 bool halSuccess = false;
2444 DBusError dbusError;
2445 if (!gLibHalCheckPresence())
2446 return false;
2447 gDBusErrorInit (&dbusError);
2448 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2449 if (dbusConnection != 0)
2450 {
2451 LibHalContext *halContext = gLibHalCtxNew();
2452 if (halContext != 0)
2453 {
2454 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2455 {
2456 if (gLibHalCtxInit(halContext, &dbusError))
2457 {
2458 int numDevices;
2459 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2460 "storage.drive_type", "cdrom",
2461 &numDevices, &dbusError);
2462 if (halDevices != 0)
2463 {
2464 /* Hal is installed and working, so if no devices are reported, assume
2465 that there are none. */
2466 halSuccess = true;
2467 for (int i = 0; i < numDevices; i++)
2468 {
2469 char *devNode = gLibHalDeviceGetPropertyString(halContext,
2470 halDevices[i], "block.device", &dbusError);
2471#ifdef RT_OS_SOLARIS
2472 /* The CD/DVD ioctls work only for raw device nodes. */
2473 char *tmp = getfullrawname(devNode);
2474 gLibHalFreeString(devNode);
2475 devNode = tmp;
2476#endif
2477
2478 if (devNode != 0)
2479 {
2480// if (validateDevice(devNode, true))
2481// {
2482 Utf8Str description;
2483 char *vendor, *product;
2484 /* We do not check the error here, as this field may
2485 not even exist. */
2486 vendor = gLibHalDeviceGetPropertyString(halContext,
2487 halDevices[i], "info.vendor", 0);
2488 product = gLibHalDeviceGetPropertyString(halContext,
2489 halDevices[i], "info.product", &dbusError);
2490 if ((product != 0 && product[0] != 0))
2491 {
2492 if ((vendor != 0) && (vendor[0] != 0))
2493 {
2494 description = Utf8StrFmt ("%s %s",
2495 vendor, product);
2496 }
2497 else
2498 {
2499 description = product;
2500 }
2501 ComObjPtr<Medium> hostDVDDriveObj;
2502 hostDVDDriveObj.createObject();
2503 hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2504 Bstr(devNode), Bstr(description));
2505 list.push_back (hostDVDDriveObj);
2506 }
2507 else
2508 {
2509 if (product == 0)
2510 {
2511 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2512 halDevices[i], dbusError.name, dbusError.message));
2513 gDBusErrorFree(&dbusError);
2514 }
2515 ComObjPtr<Medium> hostDVDDriveObj;
2516 hostDVDDriveObj.createObject();
2517 hostDVDDriveObj->init(m->pParent, DeviceType_DVD,
2518 Bstr(devNode));
2519 list.push_back (hostDVDDriveObj);
2520 }
2521 if (vendor != 0)
2522 {
2523 gLibHalFreeString(vendor);
2524 }
2525 if (product != 0)
2526 {
2527 gLibHalFreeString(product);
2528 }
2529// }
2530// else
2531// {
2532// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
2533// }
2534#ifndef RT_OS_SOLARIS
2535 gLibHalFreeString(devNode);
2536#else
2537 free(devNode);
2538#endif
2539 }
2540 else
2541 {
2542 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2543 halDevices[i], dbusError.name, dbusError.message));
2544 gDBusErrorFree(&dbusError);
2545 }
2546 }
2547 gLibHalFreeStringArray(halDevices);
2548 }
2549 else
2550 {
2551 LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2552 gDBusErrorFree(&dbusError);
2553 }
2554 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2555 {
2556 LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2557 gDBusErrorFree(&dbusError);
2558 }
2559 }
2560 else
2561 {
2562 LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2563 gDBusErrorFree(&dbusError);
2564 }
2565 gLibHalCtxFree(halContext);
2566 }
2567 else
2568 {
2569 LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
2570 }
2571 }
2572 else
2573 {
2574 LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
2575 }
2576 gDBusConnectionUnref(dbusConnection);
2577 }
2578 else
2579 {
2580 LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2581 gDBusErrorFree(&dbusError);
2582 }
2583 return halSuccess;
2584}
2585
2586
2587/**
2588 * Helper function to query the hal subsystem for information about floppy drives attached to the
2589 * system.
2590 *
2591 * @returns true if information was successfully obtained, false otherwise
2592 * @retval list drives found will be attached to this list
2593 */
2594bool Host::i_getFloppyInfoFromHal(std::list< ComObjPtr<Medium> > &list)
2595{
2596 bool halSuccess = false;
2597 DBusError dbusError;
2598 if (!gLibHalCheckPresence())
2599 return false;
2600 gDBusErrorInit (&dbusError);
2601 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
2602 if (dbusConnection != 0)
2603 {
2604 LibHalContext *halContext = gLibHalCtxNew();
2605 if (halContext != 0)
2606 {
2607 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
2608 {
2609 if (gLibHalCtxInit(halContext, &dbusError))
2610 {
2611 int numDevices;
2612 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
2613 "storage.drive_type", "floppy",
2614 &numDevices, &dbusError);
2615 if (halDevices != 0)
2616 {
2617 /* Hal is installed and working, so if no devices are reported, assume
2618 that there are none. */
2619 halSuccess = true;
2620 for (int i = 0; i < numDevices; i++)
2621 {
2622 char *driveType = gLibHalDeviceGetPropertyString(halContext,
2623 halDevices[i], "storage.drive_type", 0);
2624 if (driveType != 0)
2625 {
2626 if (strcmp(driveType, "floppy") != 0)
2627 {
2628 gLibHalFreeString(driveType);
2629 continue;
2630 }
2631 gLibHalFreeString(driveType);
2632 }
2633 else
2634 {
2635 /* An error occurred. The attribute "storage.drive_type"
2636 probably didn't exist. */
2637 continue;
2638 }
2639 char *devNode = gLibHalDeviceGetPropertyString(halContext,
2640 halDevices[i], "block.device", &dbusError);
2641 if (devNode != 0)
2642 {
2643// if (validateDevice(devNode, false))
2644// {
2645 Utf8Str description;
2646 char *vendor, *product;
2647 /* We do not check the error here, as this field may
2648 not even exist. */
2649 vendor = gLibHalDeviceGetPropertyString(halContext,
2650 halDevices[i], "info.vendor", 0);
2651 product = gLibHalDeviceGetPropertyString(halContext,
2652 halDevices[i], "info.product", &dbusError);
2653 if ((product != 0) && (product[0] != 0))
2654 {
2655 if ((vendor != 0) && (vendor[0] != 0))
2656 {
2657 description = Utf8StrFmt ("%s %s",
2658 vendor, product);
2659 }
2660 else
2661 {
2662 description = product;
2663 }
2664 ComObjPtr<Medium> hostFloppyDrive;
2665 hostFloppyDrive.createObject();
2666 hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2667 Bstr(devNode), Bstr(description));
2668 list.push_back (hostFloppyDrive);
2669 }
2670 else
2671 {
2672 if (product == 0)
2673 {
2674 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
2675 halDevices[i], dbusError.name, dbusError.message));
2676 gDBusErrorFree(&dbusError);
2677 }
2678 ComObjPtr<Medium> hostFloppyDrive;
2679 hostFloppyDrive.createObject();
2680 hostFloppyDrive->init(m->pParent, DeviceType_DVD,
2681 Bstr(devNode));
2682 list.push_back (hostFloppyDrive);
2683 }
2684 if (vendor != 0)
2685 {
2686 gLibHalFreeString(vendor);
2687 }
2688 if (product != 0)
2689 {
2690 gLibHalFreeString(product);
2691 }
2692// }
2693// else
2694// {
2695// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
2696// }
2697 gLibHalFreeString(devNode);
2698 }
2699 else
2700 {
2701 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
2702 halDevices[i], dbusError.name, dbusError.message));
2703 gDBusErrorFree(&dbusError);
2704 }
2705 }
2706 gLibHalFreeStringArray(halDevices);
2707 }
2708 else
2709 {
2710 LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2711 gDBusErrorFree(&dbusError);
2712 }
2713 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
2714 {
2715 LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2716 gDBusErrorFree(&dbusError);
2717 }
2718 }
2719 else
2720 {
2721 LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2722 gDBusErrorFree(&dbusError);
2723 }
2724 gLibHalCtxFree(halContext);
2725 }
2726 else
2727 {
2728 LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
2729 }
2730 }
2731 else
2732 {
2733 LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
2734 }
2735 gDBusConnectionUnref(dbusConnection);
2736 }
2737 else
2738 {
2739 LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2740 gDBusErrorFree(&dbusError);
2741 }
2742 return halSuccess;
2743}
2744#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
2745
2746/** @todo get rid of dead code below - RT_OS_SOLARIS and RT_OS_LINUX are never both set */
2747#if defined(RT_OS_SOLARIS)
2748
2749/**
2750 * Helper function to parse the given mount file and add found entries
2751 */
2752void Host::i_parseMountTable(char *mountTable, std::list< ComObjPtr<Medium> > &list)
2753{
2754#ifdef RT_OS_LINUX
2755 FILE *mtab = setmntent(mountTable, "r");
2756 if (mtab)
2757 {
2758 struct mntent *mntent;
2759 char *mnt_type;
2760 char *mnt_dev;
2761 char *tmp;
2762 while ((mntent = getmntent(mtab)))
2763 {
2764 mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
2765 mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
2766 strcpy(mnt_type, mntent->mnt_type);
2767 strcpy(mnt_dev, mntent->mnt_fsname);
2768 // supermount fs case
2769 if (strcmp(mnt_type, "supermount") == 0)
2770 {
2771 tmp = strstr(mntent->mnt_opts, "fs=");
2772 if (tmp)
2773 {
2774 free(mnt_type);
2775 mnt_type = strdup(tmp + strlen("fs="));
2776 if (mnt_type)
2777 {
2778 tmp = strchr(mnt_type, ',');
2779 if (tmp)
2780 *tmp = '\0';
2781 }
2782 }
2783 tmp = strstr(mntent->mnt_opts, "dev=");
2784 if (tmp)
2785 {
2786 free(mnt_dev);
2787 mnt_dev = strdup(tmp + strlen("dev="));
2788 if (mnt_dev)
2789 {
2790 tmp = strchr(mnt_dev, ',');
2791 if (tmp)
2792 *tmp = '\0';
2793 }
2794 }
2795 }
2796 // use strstr here to cover things fs types like "udf,iso9660"
2797 if (strstr(mnt_type, "iso9660") == 0)
2798 {
2799 /** @todo check whether we've already got the drive in our list! */
2800 if (i_validateDevice(mnt_dev, true))
2801 {
2802 ComObjPtr<Medium> hostDVDDriveObj;
2803 hostDVDDriveObj.createObject();
2804 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(mnt_dev));
2805 list.push_back (hostDVDDriveObj);
2806 }
2807 }
2808 free(mnt_dev);
2809 free(mnt_type);
2810 }
2811 endmntent(mtab);
2812 }
2813#else // RT_OS_SOLARIS
2814 FILE *mntFile = fopen(mountTable, "r");
2815 if (mntFile)
2816 {
2817 struct mnttab mntTab;
2818 while (getmntent(mntFile, &mntTab) == 0)
2819 {
2820 const char *mountName = mntTab.mnt_special;
2821 const char *mountPoint = mntTab.mnt_mountp;
2822 const char *mountFSType = mntTab.mnt_fstype;
2823 if (mountName && mountPoint && mountFSType)
2824 {
2825 // skip devices we are not interested in
2826 if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
2827 (*mountFSType && (strncmp(mountFSType, RT_STR_TUPLE("devfs")) != 0 && // skip devfs (i.e. /devices)
2828 strncmp(mountFSType, RT_STR_TUPLE("dev")) != 0 && // skip dev (i.e. /dev)
2829 strncmp(mountFSType, RT_STR_TUPLE("lofs")) != 0))) // skip loop-back file-system (lofs)
2830 {
2831 char *rawDevName = getfullrawname((char *)mountName);
2832 if (i_validateDevice(rawDevName, true))
2833 {
2834 ComObjPtr<Medium> hostDVDDriveObj;
2835 hostDVDDriveObj.createObject();
2836 hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(rawDevName));
2837 list.push_back (hostDVDDriveObj);
2838 }
2839 free(rawDevName);
2840 }
2841 }
2842 }
2843
2844 fclose(mntFile);
2845 }
2846#endif
2847}
2848
2849/**
2850 * Helper function to check whether the given device node is a valid drive
2851 */
2852bool Host::i_validateDevice(const char *deviceNode, bool isCDROM)
2853{
2854 struct stat statInfo;
2855 bool retValue = false;
2856
2857 // sanity check
2858 if (!deviceNode)
2859 {
2860 return false;
2861 }
2862
2863 // first a simple stat() call
2864 if (stat(deviceNode, &statInfo) < 0)
2865 {
2866 return false;
2867 }
2868 else
2869 {
2870 if (isCDROM)
2871 {
2872 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2873 {
2874 int fileHandle;
2875 // now try to open the device
2876 fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
2877 if (fileHandle >= 0)
2878 {
2879 cdrom_subchnl cdChannelInfo;
2880 cdChannelInfo.cdsc_format = CDROM_MSF;
2881 // this call will finally reveal the whole truth
2882#ifdef RT_OS_LINUX
2883 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2884 (errno == EIO) || (errno == ENOENT) ||
2885 (errno == EINVAL) || (errno == ENOMEDIUM))
2886#else
2887 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2888 (errno == EIO) || (errno == ENOENT) ||
2889 (errno == EINVAL))
2890#endif
2891 {
2892 retValue = true;
2893 }
2894 close(fileHandle);
2895 }
2896 }
2897 } else
2898 {
2899 // floppy case
2900 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2901 {
2902 /// @todo do some more testing, maybe a nice IOCTL!
2903 retValue = true;
2904 }
2905 }
2906 }
2907 return retValue;
2908}
2909#endif // RT_OS_SOLARIS
2910
2911#ifdef VBOX_WITH_USB
2912/**
2913 * Checks for the presence and status of the USB Proxy Service.
2914 * Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
2915 * warning) if the proxy service is not available due to the way the host is
2916 * configured (at present, that means that usbfs and hal/DBus are not
2917 * available on a Linux host) or E_FAIL and a corresponding error message
2918 * otherwise. Intended to be used by methods that rely on the Proxy Service
2919 * availability.
2920 *
2921 * @note This method may return a warning result code. It is recommended to use
2922 * MultiError to store the return value.
2923 *
2924 * @note Locks this object for reading.
2925 */
2926HRESULT Host::i_checkUSBProxyService()
2927{
2928 AutoCaller autoCaller(this);
2929 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2930
2931 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
2932
2933 AssertReturn(m->pUSBProxyService, E_FAIL);
2934 if (!m->pUSBProxyService->isActive())
2935 {
2936 /* disable the USB controller completely to avoid assertions if the
2937 * USB proxy service could not start. */
2938
2939 switch (m->pUSBProxyService->getLastError())
2940 {
2941 case VERR_FILE_NOT_FOUND: /** @todo what does this mean? */
2942 return setWarning(E_FAIL,
2943 tr("Could not load the Host USB Proxy Service (VERR_FILE_NOT_FOUND). The service might not be installed on the host computer"));
2944 case VERR_VUSB_USB_DEVICE_PERMISSION:
2945 return setWarning(E_FAIL,
2946 tr("VirtualBox is not currently allowed to access USB devices. You can change this by adding your user to the 'vboxusers' group. Please see the user manual for a more detailed explanation"));
2947 case VERR_VUSB_USBFS_PERMISSION:
2948 return setWarning(E_FAIL,
2949 tr("VirtualBox is not currently allowed to access USB devices. You can change this by allowing your user to access the 'usbfs' folder and files. Please see the user manual for a more detailed explanation"));
2950 case VINF_SUCCESS:
2951 return setWarning(E_FAIL,
2952 tr("The USB Proxy Service has not yet been ported to this host"));
2953 default:
2954 return setWarning (E_FAIL, "%s: %Rrc",
2955 tr ("Could not load the Host USB Proxy service"),
2956 m->pUSBProxyService->getLastError());
2957 }
2958 }
2959
2960 return S_OK;
2961}
2962#endif /* VBOX_WITH_USB */
2963
2964HRESULT Host::i_updateNetIfList()
2965{
2966#ifdef VBOX_WITH_HOSTNETIF_API
2967 AssertReturn(AutoCaller(this).state() == InInit ||
2968 isWriteLockOnCurrentThread(), E_FAIL);
2969
2970 HostNetworkInterfaceList list, listCopy;
2971 int rc = NetIfList(list);
2972 if (rc)
2973 {
2974 Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
2975 return E_FAIL;
2976 }
2977 AssertReturn(m->pParent, E_FAIL);
2978 /* Make a copy as the original may be partially destroyed later. */
2979 listCopy = list;
2980 HostNetworkInterfaceList::iterator itOld, itNew;
2981# ifdef VBOX_WITH_RESOURCE_USAGE_API
2982 PerformanceCollector *aCollector = m->pParent->performanceCollector();
2983# endif
2984 for (itOld = m->llNetIfs.begin(); itOld != m->llNetIfs.end(); ++itOld)
2985 {
2986 bool fGone = true;
2987 Bstr nameOld;
2988 (*itOld)->COMGETTER(Name)(nameOld.asOutParam());
2989 for (itNew = listCopy.begin(); itNew != listCopy.end(); ++itNew)
2990 {
2991 Bstr nameNew;
2992 (*itNew)->COMGETTER(Name)(nameNew.asOutParam());
2993 if (nameNew == nameOld)
2994 {
2995 fGone = false;
2996 listCopy.erase(itNew);
2997 break;
2998 }
2999 }
3000 if (fGone)
3001 {
3002# ifdef VBOX_WITH_RESOURCE_USAGE_API
3003 (*itOld)->unregisterMetrics(aCollector, this);
3004# endif
3005 }
3006 }
3007 /*
3008 * Need to set the references to VirtualBox object in all interface objects
3009 * (see @bugref{6439}).
3010 */
3011 for (itNew = list.begin(); itNew != list.end(); ++itNew)
3012 (*itNew)->setVirtualBox(m->pParent);
3013 /* At this point listCopy will contain newly discovered interfaces only. */
3014 for (itNew = listCopy.begin(); itNew != listCopy.end(); ++itNew)
3015 {
3016 HostNetworkInterfaceType_T t;
3017 HRESULT hr = (*itNew)->COMGETTER(InterfaceType)(&t);
3018 if (FAILED(hr))
3019 {
3020 Bstr n;
3021 (*itNew)->COMGETTER(Name)(n.asOutParam());
3022 LogRel(("Host::updateNetIfList: failed to get interface type for %ls\n", n.raw()));
3023 }
3024 else if (t == HostNetworkInterfaceType_Bridged)
3025 {
3026# ifdef VBOX_WITH_RESOURCE_USAGE_API
3027 (*itNew)->registerMetrics(aCollector, this);
3028# endif
3029 }
3030 }
3031 m->llNetIfs = list;
3032 return S_OK;
3033#else
3034 return E_NOTIMPL;
3035#endif
3036}
3037
3038#ifdef VBOX_WITH_RESOURCE_USAGE_API
3039
3040void Host::i_registerDiskMetrics(PerformanceCollector *aCollector)
3041{
3042 pm::CollectorHAL *hal = aCollector->getHAL();
3043 /* Create sub metrics */
3044 Utf8StrFmt fsNameBase("FS/{%s}/Usage", "/");
3045 //Utf8StrFmt fsNameBase("Filesystem/[root]/Usage");
3046 pm::SubMetric *fsRootUsageTotal = new pm::SubMetric(fsNameBase + "/Total",
3047 "Root file system size.");
3048 pm::SubMetric *fsRootUsageUsed = new pm::SubMetric(fsNameBase + "/Used",
3049 "Root file system space currently occupied.");
3050 pm::SubMetric *fsRootUsageFree = new pm::SubMetric(fsNameBase + "/Free",
3051 "Root file system space currently empty.");
3052
3053 pm::BaseMetric *fsRootUsage = new pm::HostFilesystemUsage(hal, this,
3054 fsNameBase, "/",
3055 fsRootUsageTotal,
3056 fsRootUsageUsed,
3057 fsRootUsageFree);
3058 aCollector->registerBaseMetric (fsRootUsage);
3059
3060 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal, 0));
3061 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
3062 new pm::AggregateAvg()));
3063 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
3064 new pm::AggregateMin()));
3065 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
3066 new pm::AggregateMax()));
3067
3068 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed, 0));
3069 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
3070 new pm::AggregateAvg()));
3071 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
3072 new pm::AggregateMin()));
3073 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
3074 new pm::AggregateMax()));
3075
3076 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree, 0));
3077 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
3078 new pm::AggregateAvg()));
3079 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
3080 new pm::AggregateMin()));
3081 aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
3082 new pm::AggregateMax()));
3083
3084 /* For now we are concerned with the root file system only. */
3085 pm::DiskList disksUsage, disksLoad;
3086 int rc = hal->getDiskListByFs("/", disksUsage, disksLoad);
3087 if (RT_FAILURE(rc))
3088 return;
3089 pm::DiskList::iterator it;
3090 for (it = disksLoad.begin(); it != disksLoad.end(); ++it)
3091 {
3092 Utf8StrFmt strName("Disk/%s", it->c_str());
3093 pm::SubMetric *fsLoadUtil = new pm::SubMetric(strName + "/Load/Util",
3094 "Percentage of time disk was busy serving I/O requests.");
3095 pm::BaseMetric *fsLoad = new pm::HostDiskLoadRaw(hal, this, strName + "/Load",
3096 *it, fsLoadUtil);
3097 aCollector->registerBaseMetric (fsLoad);
3098
3099 aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil, 0));
3100 aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
3101 new pm::AggregateAvg()));
3102 aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
3103 new pm::AggregateMin()));
3104 aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
3105 new pm::AggregateMax()));
3106 }
3107 for (it = disksUsage.begin(); it != disksUsage.end(); ++it)
3108 {
3109 Utf8StrFmt strName("Disk/%s", it->c_str());
3110 pm::SubMetric *fsUsageTotal = new pm::SubMetric(strName + "/Usage/Total",
3111 "Disk size.");
3112 pm::BaseMetric *fsUsage = new pm::HostDiskUsage(hal, this, strName + "/Usage",
3113 *it, fsUsageTotal);
3114 aCollector->registerBaseMetric (fsUsage);
3115
3116 aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal, 0));
3117 aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal,
3118 new pm::AggregateAvg()));
3119 aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal,
3120 new pm::AggregateMin()));
3121 aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal,
3122 new pm::AggregateMax()));
3123 }
3124}
3125
3126void Host::i_registerMetrics(PerformanceCollector *aCollector)
3127{
3128 pm::CollectorHAL *hal = aCollector->getHAL();
3129 /* Create sub metrics */
3130 pm::SubMetric *cpuLoadUser = new pm::SubMetric("CPU/Load/User",
3131 "Percentage of processor time spent in user mode.");
3132 pm::SubMetric *cpuLoadKernel = new pm::SubMetric("CPU/Load/Kernel",
3133 "Percentage of processor time spent in kernel mode.");
3134 pm::SubMetric *cpuLoadIdle = new pm::SubMetric("CPU/Load/Idle",
3135 "Percentage of processor time spent idling.");
3136 pm::SubMetric *cpuMhzSM = new pm::SubMetric("CPU/MHz",
3137 "Average of current frequency of all processors.");
3138 pm::SubMetric *ramUsageTotal = new pm::SubMetric("RAM/Usage/Total",
3139 "Total physical memory installed.");
3140 pm::SubMetric *ramUsageUsed = new pm::SubMetric("RAM/Usage/Used",
3141 "Physical memory currently occupied.");
3142 pm::SubMetric *ramUsageFree = new pm::SubMetric("RAM/Usage/Free",
3143 "Physical memory currently available to applications.");
3144 pm::SubMetric *ramVMMUsed = new pm::SubMetric("RAM/VMM/Used",
3145 "Total physical memory used by the hypervisor.");
3146 pm::SubMetric *ramVMMFree = new pm::SubMetric("RAM/VMM/Free",
3147 "Total physical memory free inside the hypervisor.");
3148 pm::SubMetric *ramVMMBallooned = new pm::SubMetric("RAM/VMM/Ballooned",
3149 "Total physical memory ballooned by the hypervisor.");
3150 pm::SubMetric *ramVMMShared = new pm::SubMetric("RAM/VMM/Shared",
3151 "Total physical memory shared between VMs.");
3152
3153
3154 /* Create and register base metrics */
3155 pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw(hal, this, cpuLoadUser, cpuLoadKernel,
3156 cpuLoadIdle);
3157 aCollector->registerBaseMetric (cpuLoad);
3158 pm::BaseMetric *cpuMhz = new pm::HostCpuMhz(hal, this, cpuMhzSM);
3159 aCollector->registerBaseMetric (cpuMhz);
3160 pm::BaseMetric *ramUsage = new pm::HostRamUsage(hal, this,
3161 ramUsageTotal,
3162 ramUsageUsed,
3163 ramUsageFree);
3164 aCollector->registerBaseMetric (ramUsage);
3165 pm::BaseMetric *ramVmm = new pm::HostRamVmm(aCollector->getGuestManager(), this,
3166 ramVMMUsed,
3167 ramVMMFree,
3168 ramVMMBallooned,
3169 ramVMMShared);
3170 aCollector->registerBaseMetric (ramVmm);
3171
3172 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
3173 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
3174 new pm::AggregateAvg()));
3175 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
3176 new pm::AggregateMin()));
3177 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
3178 new pm::AggregateMax()));
3179
3180 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel, 0));
3181 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
3182 new pm::AggregateAvg()));
3183 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
3184 new pm::AggregateMin()));
3185 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadKernel,
3186 new pm::AggregateMax()));
3187
3188 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle, 0));
3189 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
3190 new pm::AggregateAvg()));
3191 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
3192 new pm::AggregateMin()));
3193 aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadIdle,
3194 new pm::AggregateMax()));
3195
3196 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM, 0));
3197 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
3198 new pm::AggregateAvg()));
3199 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
3200 new pm::AggregateMin()));
3201 aCollector->registerMetric(new pm::Metric(cpuMhz, cpuMhzSM,
3202 new pm::AggregateMax()));
3203
3204 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal, 0));
3205 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
3206 new pm::AggregateAvg()));
3207 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
3208 new pm::AggregateMin()));
3209 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageTotal,
3210 new pm::AggregateMax()));
3211
3212 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed, 0));
3213 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
3214 new pm::AggregateAvg()));
3215 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
3216 new pm::AggregateMin()));
3217 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
3218 new pm::AggregateMax()));
3219
3220 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree, 0));
3221 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
3222 new pm::AggregateAvg()));
3223 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
3224 new pm::AggregateMin()));
3225 aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageFree,
3226 new pm::AggregateMax()));
3227
3228 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed, 0));
3229 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed,
3230 new pm::AggregateAvg()));
3231 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed,
3232 new pm::AggregateMin()));
3233 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMUsed,
3234 new pm::AggregateMax()));
3235
3236 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree, 0));
3237 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree,
3238 new pm::AggregateAvg()));
3239 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree,
3240 new pm::AggregateMin()));
3241 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMFree,
3242 new pm::AggregateMax()));
3243
3244 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned, 0));
3245 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned,
3246 new pm::AggregateAvg()));
3247 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned,
3248 new pm::AggregateMin()));
3249 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMBallooned,
3250 new pm::AggregateMax()));
3251
3252 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared, 0));
3253 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
3254 new pm::AggregateAvg()));
3255 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
3256 new pm::AggregateMin()));
3257 aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
3258 new pm::AggregateMax()));
3259 i_registerDiskMetrics(aCollector);
3260}
3261
3262void Host::i_unregisterMetrics (PerformanceCollector *aCollector)
3263{
3264 aCollector->unregisterMetricsFor(this);
3265 aCollector->unregisterBaseMetricsFor(this);
3266}
3267
3268#endif /* VBOX_WITH_RESOURCE_USAGE_API */
3269
3270
3271/* static */
3272void Host::i_generateMACAddress(Utf8Str &mac)
3273{
3274 /*
3275 * Our strategy is as follows: the first three bytes are our fixed
3276 * vendor ID (080027). The remaining 3 bytes will be taken from the
3277 * start of a GUID. This is a fairly safe algorithm.
3278 */
3279 Guid guid;
3280 guid.create();
3281 mac = Utf8StrFmt("080027%02X%02X%02X",
3282 guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]);
3283}
3284
3285/* 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