VirtualBox

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

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

Main/HostImpl-solaris: fix another unchecked strdup

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

© 2023 Oracle
ContactPrivacy policyTerms of Use