VirtualBox

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

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

Main: fix bug that dvd/floppy host drives would not be restored from machine settings but always result in empty drives

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette