VirtualBox

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

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

OSE build fix

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

© 2023 Oracle
ContactPrivacy policyTerms of Use