VirtualBox

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

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

Main. QT/FE: fix long standing COM issue

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