VirtualBox

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

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

Main: Whitespace (including tabs!) and svn:keywords cleanups by scm.

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