VirtualBox

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

Last change on this file since 25275 was 25200, checked in by vboxsync, 15 years ago

Main: make MediumAttachment instance data private

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

© 2023 Oracle
ContactPrivacy policyTerms of Use