VirtualBox

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

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

Applied a simple memory leak detector to libjpeg and VBoxC (Windows host only), the code completely disabled by default.

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