VirtualBox

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

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

Main: do not include VirtualBoxImpl.h from code ending in VBoxC (causes unnecessary rebuilds), and make sure that the code still builds with VBOX_WITH_RESOURCE_USAGE_API unset

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