VirtualBox

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

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

Main/HostImpl-solaris: #4553 strdup unchecked, strtok not reentrant safe.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use