HostImpl.cpp revision 98f65e540e4b270afc32507e1d95c9a99869eebc
/* $Id$ */
/** @file
* VirtualBox COM class implementation: Host
*/
/*
* Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
// for some reason Windows burns in sdk\...\winsock.h if this isn't included first
#include "HostImpl.h"
#ifdef VBOX_WITH_USB
# include "HostUSBDeviceImpl.h"
# include "USBDeviceFilterImpl.h"
# include "USBProxyService.h"
#endif // VBOX_WITH_USB
#include "HostNetworkInterfaceImpl.h"
#include "MachineImpl.h"
#include "AutoCaller.h"
#include "Logging.h"
#include "Performance.h"
#include "MediumImpl.h"
#include "HostPower.h"
#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
# include <HostHardwareLinux.h>
#endif
#ifdef VBOX_WITH_RESOURCE_USAGE_API
# include "PerformanceImpl.h"
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
# include <VBox/WinNetConfig.h>
#endif /* #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
#ifdef RT_OS_LINUX
# include <errno.h>
#endif /* RT_OS_LINUX */
#ifdef RT_OS_SOLARIS
# include <fcntl.h>
# include <unistd.h>
# include <stropts.h>
# include <errno.h>
# include <limits.h>
# include <stdio.h>
# include <libdevinfo.h>
/* Dynamic loading of libhal on Solaris hosts */
# ifdef VBOX_USE_LIBHAL
# include "vbox-libhal.h"
extern "C" char *getfullrawname(char *);
# endif
# include "solaris/DynLoadLibSolaris.h"
/**
* Solaris DVD drive list as returned by getDVDInfoFromDevTree().
*/
typedef struct SOLARISDVD
{
struct SOLARISDVD *pNext;
char szDescription[512];
char szRawDiskPath[PATH_MAX];
} SOLARISDVD;
/** Pointer to a Solaris DVD descriptor. */
typedef SOLARISDVD *PSOLARISDVD;
#endif /* RT_OS_SOLARIS */
#ifdef RT_OS_WINDOWS
# define _WIN32_DCOM
# include <windows.h>
# include <shellapi.h>
# define INITGUID
# include <guiddef.h>
# include <devguid.h>
# include <objbase.h>
//# include <setupapi.h>
# include <shlobj.h>
# include <cfgmgr32.h>
#endif /* RT_OS_WINDOWS */
#ifdef RT_OS_DARWIN
#endif
#ifdef VBOX_WITH_CROGL
extern bool is3DAccelerationSupported();
#endif /* VBOX_WITH_CROGL */
#include <iprt/asm-amd64-x86.h>
#ifndef VBOX_WITH_VRDP_MEMLEAK_DETECTOR
#endif /* !VBOX_WITH_VRDP_MEMLEAK_DETECTOR */
#ifdef RT_OS_SOLARIS
#endif
#ifdef VBOX_WITH_HOSTNETIF_API
# include "netif.h"
#endif
/* XXX Solaris: definitions in /usr/include/sys/regset.h clash with hwacc_svm.h */
#include <VBox/hwacc_svm.h>
#include <VBox/settings.h>
#include "VBox/com/MultiResult.h"
#include <stdio.h>
#include <algorithm>
////////////////////////////////////////////////////////////////////////////////
//
// Host private data definition
//
////////////////////////////////////////////////////////////////////////////////
{
Data()
:
#ifdef VBOX_WITH_USB
#endif
fDVDDrivesListBuilt(false),
fFloppyDrivesListBuilt(false)
{};
#ifdef VBOX_WITH_USB
/** Pointer to the USBProxyService object. */
#endif /* VBOX_WITH_USB */
// list of host drives; lazily created by getDVDDrives() and getFloppyDrives()
bool fDVDDrivesListBuilt,
#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
/** Object with information about host drives */
#endif
/* Features that can be queried with GetProcessorFeature */
/* 3D hardware acceleration supported? */
};
////////////////////////////////////////////////////////////////////////////////
//
// Constructor / destructor
//
////////////////////////////////////////////////////////////////////////////////
{
return S_OK;
}
void Host::FinalRelease()
{
uninit();
}
/**
* Initializes the host object.
*
* @param aParent VirtualBox parent object.
*/
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
m = new Data();
#ifdef VBOX_WITH_USB
/*
* Create and initialize the USB Proxy Service.
*/
# if defined (RT_OS_DARWIN)
m->pUSBProxyService = new USBProxyServiceDarwin(this);
# elif defined (RT_OS_LINUX)
m->pUSBProxyService = new USBProxyServiceLinux(this);
m->pUSBProxyService = new USBProxyServiceOs2(this);
# elif defined (RT_OS_SOLARIS)
m->pUSBProxyService = new USBProxyServiceSolaris(this);
# elif defined (RT_OS_WINDOWS)
m->pUSBProxyService = new USBProxyServiceWindows(this);
# elif defined (RT_OS_FREEBSD)
m->pUSBProxyService = new USBProxyServiceFreeBSD(this);
# else
m->pUSBProxyService = new USBProxyService(this);
# endif
#endif /* VBOX_WITH_USB */
#ifdef VBOX_WITH_RESOURCE_USAGE_API
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
#if defined (RT_OS_WINDOWS)
#elif defined (RT_OS_DARWIN)
#else
#endif
/* Cache the features reported by GetProcessorFeature. */
m->fVTSupported = false;
m->fLongModeSupported = false;
m->fPAESupported = false;
m->fNestedPagingSupported = false;
if (ASMHasCpuId())
{
/* Query AMD features. */
)
{
if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
)
{
int rc = SUPR3QueryVTxSupported();
if (RT_SUCCESS(rc))
m->fVTSupported = true;
}
}
else
if ( u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX
)
{
)
{
m->fVTSupported = true;
/* Query AMD features. */
m->fNestedPagingSupported = true;
}
}
}
#if 0 /* needs testing */
if (m->fVTSupported)
{
if (RT_SUCCESS(rc))
{
if (u32Caps & SUPVTCAPS_NESTED_PAGING)
m->fNestedPagingSupported = true;
}
/* else @todo; report BIOS trouble in some way. */
}
#endif
/* Test for 3D hardware acceleration support */
m->f3DAccelerationSupported = false;
#ifdef VBOX_WITH_CROGL
#endif /* VBOX_WITH_CROGL */
/* Confirm a successful initialization */
return S_OK;
}
/**
* Uninitializes the host object and sets the ready flag to FALSE.
* Called either from FinalRelease() or by the parent when it gets destroyed.
*/
{
LogFlowThisFunc(("\n"));
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
return;
#ifdef VBOX_WITH_RESOURCE_USAGE_API
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
#ifdef VBOX_WITH_USB
/* wait for USB proxy service to terminate before we uninit all USB
* devices */
LogFlowThisFunc(("Stopping USB proxy service...\n"));
delete m->pUSBProxyService;
m->pUSBProxyService = NULL;
LogFlowThisFunc(("Done stopping USB proxy service.\n"));
#endif
delete m->pHostPowerService;
#ifdef VBOX_WITH_USB
/* uninit all USB device filters still referenced by clients
* Note! HostUSBDeviceFilter::uninit() will modify llChildren. */
while (!m->llChildren.empty())
{
}
m->llUSBDeviceFilters.clear();
#endif
delete m;
m = NULL;
}
////////////////////////////////////////////////////////////////////////////////
//
// ISnapshot public methods
//
////////////////////////////////////////////////////////////////////////////////
/**
* Returns a list of host DVD drives.
*
* @returns COM status code
* @param drives address of result pointer
*/
{
AutoCaller autoCaller(this);
{
}
return rc;
}
/**
* Returns a list of host floppy drives.
*
* @returns COM status code
* @param drives address of result pointer
*/
{
AutoCaller autoCaller(this);
{
}
return rc;
}
#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
# define VBOX_APP_NAME L"VirtualBox"
{
int rc = VERR_GENERAL_FAILURE;
{
{
/* create a new object and add it to the list */
/* remove the curly bracket at the end */
{
// iface->setVirtualBox(m->pParent);
rc = VINF_SUCCESS;
}
else
{
Assert(0);
}
}
}
return rc;
}
#endif /* defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
/**
* Returns a list of host network interfaces.
*
* @returns COM status code
* @param drives address of result pointer
*/
STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInterface*, aNetworkInterfaces))
{
return E_POINTER;
AutoCaller autoCaller(this);
# ifdef VBOX_WITH_HOSTNETIF_API
if (rc)
{
}
# else
# if defined(RT_OS_DARWIN)
while (pEtherNICs)
{
if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), Guid(pEtherNICs->Uuid), HostNetworkInterfaceType_Bridged)))
/* next, free current */
void *pvFree = pEtherNICs;
}
# elif defined RT_OS_WINDOWS
# ifndef VBOX_WITH_NETFLT
# else /* # if defined VBOX_WITH_NETFLT */
/* we are using the INetCfg API for getting the list of miniports */
&pNc,
&lpszApp );
{
# ifdef VBOX_NETFLT_ONDEMAND_BIND
/* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
# else
/* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
# ifndef VBOX_WITH_HARDENING
{
/* TODO: try to install the netflt from here */
}
# endif
# endif
{
{
{
/* S_OK == enabled, S_FALSE == disabled */
{
{
{
{
{
if (uComponentStatus == 0)
{
}
}
}
}
}
}
}
}
}
else
{
}
}
# endif /* # if defined VBOX_WITH_NETFLT */
# elif defined RT_OS_LINUX
if (sock >= 0)
{
char pBuffer[2048];
{
{
{
{
}
}
}
}
}
# endif /* RT_OS_LINUX */
# endif
{
}
return S_OK;
#else
/* Not implemented / supported on this platform. */
#endif
}
{
#ifdef VBOX_WITH_USB
AutoCaller autoCaller(this);
#else
/* Note: The GUI depends on this method returning E_NOTIMPL with no
* extended error info to indicate that USB is simply not available
* (w/o treating it as a failure), for example, as in OSE. */
# ifndef RT_OS_WINDOWS
# endif
#endif
}
STDMETHODIMP Host::COMGETTER(USBDeviceFilters)(ComSafeArrayOut(IHostUSBDeviceFilter*, aUSBDeviceFilters))
{
#ifdef VBOX_WITH_USB
AutoCaller autoCaller(this);
return rc;
#else
/* Note: The GUI depends on this method returning E_NOTIMPL with no
* extended error info to indicate that USB is simply not available
* (w/o treating it as a failure), for example, as in OSE. */
# ifndef RT_OS_WINDOWS
# endif
#endif
}
/**
* Returns the number of installed logical processors
*
* @returns COM status code
* @param count address of result variable
*/
{
// no locking required
*aCount = RTMpGetPresentCount();
return S_OK;
}
/**
* Returns the number of online logical processors
*
* @returns COM status code
* @param count address of result variable
*/
{
// no locking required
*aCount = RTMpGetOnlineCount();
return S_OK;
}
/**
* Returns the number of installed physical processor cores.
*
* @returns COM status code
* @param count address of result variable
*/
{
// no locking required
return E_NOTIMPL;
}
/**
* Returns the (approximate) maximum speed of the given host CPU in MHz
*
* @returns COM status code
* @param cpu id to get info for.
* @param speed address of result variable, speed is 0 if unknown or aCpuId is invalid.
*/
{
// no locking required
return S_OK;
}
/**
* Returns a description string for the host CPU
*
* @returns COM status code
* @param cpu id to get info for.
* @param description address of result variable, empty string if not known or aCpuId is invalid.
*/
{
// no locking required
char szCPUModel[80];
if (RT_FAILURE(vrc))
return E_FAIL; /** @todo error reporting? */
return S_OK;
}
/**
* Returns whether a host processor feature is supported or not
*
* @returns COM status code
* @param Feature to query.
* @param address of supported bool result variable
*/
{
AutoCaller autoCaller(this);
switch (aFeature)
{
*aSupported = m->fVTSupported;
break;
case ProcessorFeature_PAE:
*aSupported = m->fPAESupported;
break;
*aSupported = m->fLongModeSupported;
break;
*aSupported = m->fNestedPagingSupported;
break;
default:
}
return S_OK;
}
/**
* Returns the specific CPUID leaf.
*
* @returns COM status code
* @param aCpuId The CPU number. Mostly ignored.
* @param aLeaf The leaf number.
* @param aSubLeaf The sub-leaf number.
* @param aValEAX Where to return EAX.
* @param aValEBX Where to return EBX.
* @param aValECX Where to return ECX.
* @param aValEDX Where to return EDX.
*/
{
// no locking required
/* Check that the CPU is online. */
/** @todo later use RTMpOnSpecific. */
if (!RTMpIsCpuOnline(aCpuId))
return RTMpIsCpuPresent(aCpuId)
return S_OK;
}
/**
* Returns the amount of installed system memory in megabytes
*
* @returns COM status code
* @param size address of result variable
*/
{
// no locking required
/* @todo This is an ugly hack. There must be a function in IPRT for that. */
if (!hal)
return E_FAIL;
*aSize /= 1024;
delete hal;
return rc;
}
/**
* Returns the current system memory free space in megabytes
*
* @returns COM status code
* @param available address of result variable
*/
{
// no locking required
/* @todo This is an ugly hack. There must be a function in IPRT for that. */
if (!hal)
return E_FAIL;
*aAvailable /= 1024;
delete hal;
return rc;
}
/**
* Returns the name string of the host operating system
*
* @returns COM status code
* @param os address of result variable
*/
{
// no locking required
char szOSName[80];
if (RT_FAILURE(vrc))
return E_FAIL; /** @todo error reporting? */
return S_OK;
}
/**
* Returns the version string of the host operating system
*
* @returns COM status code
* @param os address of result variable
*/
{
// no locking required
/* Get the OS release. Reserve some buffer space for the service pack. */
char szOSRelease[128];
if (RT_FAILURE(vrc))
return E_FAIL; /** @todo error reporting? */
/* Append the service pack if present. */
char szOSServicePack[80];
if (RT_FAILURE(vrc))
{
if (vrc != VERR_NOT_SUPPORTED)
return E_FAIL; /** @todo error reporting? */
szOSServicePack[0] = '\0';
}
if (szOSServicePack[0] != '\0')
{
}
return S_OK;
}
/**
* Returns the current host time in milliseconds since 1970-01-01 UTC.
*
* @returns COM status code
* @param time address of result variable
*/
{
// no locking required
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
/* No need to lock anything. If there ever will - watch out, the function
* called below grabs the VirtualBox lock. */
if (RT_SUCCESS(r))
return S_OK;
}
{
AutoCaller autoCaller(this);
/* No need to lock anything, the code below does not touch the state
* of the host object. If that ever changes then check for lock order
* violations with the called functions. */
/* first check whether an interface with the given name already exists */
{
iface.asOutParam())))
return setError(VBOX_E_OBJECT_NOT_FOUND,
tr("Host network interface with UUID {%RTuuid} does not exist"),
}
if (RT_SUCCESS(r))
return S_OK;
}
{
#ifdef VBOX_WITH_USB
AutoCaller autoCaller(this);
return S_OK;
#else
/* Note: The GUI depends on this method returning E_NOTIMPL with no
* extended error info to indicate that USB is simply not available
* (w/o treating it as a failure), for example, as in OSE. */
#endif
}
{
#ifdef VBOX_WITH_USB
/* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
AutoCaller autoCaller(this);
++it)
{
{
break;
}
}
return setError(VBOX_E_INVALID_OBJECT_STATE,
tr("The given USB device filter is not created within this VirtualBox instance"));
return setError(E_INVALIDARG,
tr("The given USB device filter is already in the list"));
/* iterate to the position... */
/* ...and insert */
/* notify the proxy (only when the filter is active) */
if ( m->pUSBProxyService->isActive()
{
}
// save the global settings; for that we should hold only the VirtualBox lock
#else
/* Note: The GUI depends on this method returning E_NOTIMPL with no
* extended error info to indicate that USB is simply not available
* (w/o treating it as a failure), for example, as in OSE. */
#endif
}
{
#ifdef VBOX_WITH_USB
/* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
AutoCaller autoCaller(this);
if (!m->llUSBDeviceFilters.size())
return setError(E_INVALIDARG,
tr("The USB device filter list is empty"));
return setError(E_INVALIDARG,
tr("Invalid position: %lu (must be in range [0, %lu])"),
{
/* iterate to the position... */
/* ...get an element from there... */
/* ...and remove */
}
/* notify the proxy (only when the filter is active) */
{
}
// save the global settings; for that we should hold only the VirtualBox lock
#else
/* Note: The GUI depends on this method returning E_NOTIMPL with no
* extended error info to indicate that USB is simply not available
* (w/o treating it as a failure), for example, as in OSE. */
#endif
}
{
{
}
return setError(VBOX_E_OBJECT_NOT_FOUND,
}
{
{
}
return setError(VBOX_E_OBJECT_NOT_FOUND,
}
STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInterface **networkInterface)
{
#ifndef VBOX_WITH_HOSTNETIF_API
return E_NOTIMPL;
#else
if (!name)
return E_INVALIDARG;
if (!networkInterface)
return E_POINTER;
*networkInterface = NULL;
if (RT_FAILURE(rc))
{
return E_FAIL;
}
{
Bstr n;
if (n == name)
}
if (!found)
return setError(E_INVALIDARG,
#endif
}
STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_BSTR id, IHostNetworkInterface **networkInterface)
{
#ifndef VBOX_WITH_HOSTNETIF_API
return E_NOTIMPL;
#else
return E_INVALIDARG;
if (!networkInterface)
return E_POINTER;
*networkInterface = NULL;
if (RT_FAILURE(rc))
{
return E_FAIL;
}
{
Bstr g;
if (g == id)
}
if (!found)
return setError(E_INVALIDARG,
#endif
}
{
if (RT_FAILURE(rc))
return E_FAIL;
{
return hr;
if (t == type)
{
}
}
return S_OK;
}
{
#ifdef VBOX_WITH_USB
{
{
}
}
return setErrorNoLog(VBOX_E_OBJECT_NOT_FOUND,
tr("Could not find a USB device with address '%ls'"),
aAddress);
#else /* !VBOX_WITH_USB */
return E_NOTIMPL;
#endif /* !VBOX_WITH_USB */
}
{
#ifdef VBOX_WITH_USB
{
{
}
}
"Could not find a USB device with uuid {%RTuuid}"),
#else /* !VBOX_WITH_USB */
return E_NOTIMPL;
#endif /* !VBOX_WITH_USB */
}
// public methods only for internal purposes
////////////////////////////////////////////////////////////////////////////////
{
#ifdef VBOX_WITH_USB
AutoCaller autoCaller(this);
++it)
{
/* notify the proxy (only when the filter is active) */
{
}
}
#else
#endif /* VBOX_WITH_USB */
return rc;
}
{
#ifdef VBOX_WITH_USB
AutoCaller autoCaller(this);
++it)
{
pFilter->saveSettings(f);
}
#else
#endif /* VBOX_WITH_USB */
return S_OK;
}
/**
* Sets the given pointer to point to the static list of DVD or floppy
* drives in the Host instance data, depending on the @a mediumType
* parameter.
*
* This builds the list on the first call; it adds or removes host drives
* that may have changed if fRefresh == true.
*
* The caller must hold the m->drivesLock write lock before calling this.
* To protect the list to which the caller's pointer points, the caller
* must also hold that lock.
*
* @param mediumType Must be DeviceType_Floppy or DeviceType_DVD.
* @param fRefresh Whether to refresh the host drives list even if this is not the first call.
* @param pll Caller's pointer which gets set to the static list of host drives.
* @return
*/
bool fRefresh,
{
bool *pfListBuilt = NULL;
switch (mediumType)
{
case DeviceType_DVD:
if (!m->fDVDDrivesListBuilt || fRefresh)
{
return rc;
pfListBuilt = &m->fDVDDrivesListBuilt;
}
pllCached = &m->llDVDDrives;
break;
case DeviceType_Floppy:
if (!m->fFloppyDrivesListBuilt || fRefresh)
{
return rc;
}
pllCached = &m->llFloppyDrives;
break;
default:
return E_INVALIDARG;
}
if (pfListBuilt)
{
// a list was built in llNew above:
if (!*pfListBuilt)
{
// this was the first call (instance bool is still false): then just copy the whole list and return
// and mark the instance data as "built"
*pfListBuilt = true;
}
else
{
// list was built, and this was a subsequent call: then compare the old and the new lists
// remove drives from the cached list which are no longer present
++itCached)
{
bool fFound = false;
++itNew)
{
if (strLocationNew == strLocationCached)
{
fFound = true;
break;
}
}
if (!fFound)
}
// add drives to the cached list that are not on there yet
++itNew)
{
bool fFound = false;
++itCached)
{
if (strLocationNew == strLocationCached)
{
fFound = true;
break;
}
}
if (!fFound)
}
}
}
// return cached list to caller
return rc;
}
/**
* Goes through the list of host drives that would be returned by getDrives()
* and looks for a host drive with the given UUID. If found, it sets pMedium
* to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
*
* @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
* @param uuid Medium UUID of host drive to look for.
* @param fRefresh Whether to refresh the host drives list (see getDrives())
* @param pMedium Medium object, if found…
* @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
*/
bool fRefresh,
{
{
++it)
{
{
return S_OK;
}
}
}
return VBOX_E_OBJECT_NOT_FOUND;
}
/**
* Called from getDrives() to build the DVD drives list.
* @param pll
* @return
*/
{
try
{
#if defined(RT_OS_WINDOWS)
TCHAR *p = hostDrives;
do
{
if (GetDriveType(p) == DRIVE_CDROM)
{
driveName[0] = *p;
}
p += _tcslen(p) + 1;
}
while (*p);
delete[] hostDrives;
#elif defined(RT_OS_SOLARIS)
# ifdef VBOX_USE_LIBHAL
if (!getDVDInfoFromHal(list))
# endif
{
}
{
}
#elif defined(RT_OS_DARWIN)
while (cur)
{
/* next */
}
#else
/* PORTME */
#endif
}
{
rc = E_OUTOFMEMORY;
}
return rc;
}
/**
* Called from getDrives() to build the floppy drives list.
* @param list
* @return
*/
{
try
{
#ifdef RT_OS_WINDOWS
TCHAR *p = hostDrives;
do
{
if (GetDriveType(p) == DRIVE_REMOVABLE)
{
driveName[0] = *p;
}
p += _tcslen(p) + 1;
}
while (*p);
delete[] hostDrives;
#elif defined(RT_OS_LINUX)
{
}
#else
/* PORTME */
#endif
}
{
rc = E_OUTOFMEMORY;
}
return rc;
}
#ifdef VBOX_WITH_USB
{
return m->pUSBProxyService;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
{
AutoCaller autoCaller(this);
++it)
{
{
break;
}
}
return S_OK;
}
{
return m->pParent;
}
/**
* Called by setter methods of all USB device filters.
*/
{
AutoCaller autoCaller(this);
{
if (aActiveChanged)
{
{
}
else
{
}
}
else
{
{
// update the filter in the proxy
}
}
// save the global settings... yeah, on every single filter property change
// for that we should hold only the VirtualBox lock
return m->pParent->saveSettings();
}
return S_OK;
}
/**
* Interface for obtaining a copy of the USBDeviceFilterList,
* used by the USBProxyService.
*
* @param aGlobalFilters Where to put the global filter list copy.
* @param aMachines Where to put the machine vector.
*/
{
*aGlobalFilters = m->llUSBDeviceFilters;
}
#endif /* VBOX_WITH_USB */
// private methods
////////////////////////////////////////////////////////////////////////////////
#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
/**
* Helper function to get the slice number from a device path
*
* @param pszDevLinkPath Pointer to a device path (/dev/(r)dsk/c7d1t0d0s3 etc.)
* @returns Pointer to the slice portion of the given path.
*/
static char *solarisGetSliceFromPath(const char *pszDevLinkPath)
{
else
return pszFound;
return NULL;
}
/**
* Walk device links and returns an allocated path for the first one in the snapshot.
*
* @param DevLink Handle to the device link being walked.
* @param pvArg Opaque data containing the pointer to the path.
* @returns Pointer to an allocated device path string.
*/
{
return DI_WALK_TERMINATE;
}
/**
* @param Node Handle to the current node.
* @param pvArg Opaque data (holds list pointer).
* @returns Solaris specific code whether to continue walking or not.
*/
{
{
{
char *pszProduct = NULL;
{
{
/*
* Found a DVD drive, we need to scan the minor nodes to find the correct
*/
if (DevLink)
{
{
{
continue;
}
if (!pszMinorPath)
continue;
char *pszDevLinkPath = NULL;
if (pszDevLinkPath)
{
{
/*
* We've got a fully qualified DVD drive. Add it to the list.
*/
{
if (*ppDrives)
}
}
}
}
}
}
}
}
}
return DI_WALK_CONTINUE;
}
/**
* Works on Solaris 10 as well as OpenSolaris without depending on libhal.
*/
{
if (RootNode != DI_NODE_NIL)
while (pDrives)
{
hostDVDDriveObj->init(m->pParent, DeviceType_DVD, Bstr(pDrives->szRawDiskPath), Bstr(pDrives->szDescription));
}
}
/* Solaris hosts, loading libhal at runtime */
/**
* Helper function to query the hal subsystem for information about DVD drives attached to the
* system.
*
* @returns true if information was successfully obtained, false otherwise
* @retval list drives found will be attached to this list
*/
{
bool halSuccess = false;
if (!gLibHalCheckPresence())
return false;
if (dbusConnection != 0)
{
if (halContext != 0)
{
{
{
int numDevices;
"storage.drive_type", "cdrom",
&numDevices, &dbusError);
if (halDevices != 0)
{
/* Hal is installed and working, so if no devices are reported, assume
that there are none. */
halSuccess = true;
for (int i = 0; i < numDevices; i++)
{
#ifdef RT_OS_SOLARIS
#endif
if (devNode != 0)
{
// if (validateDevice(devNode, true))
// {
/* We do not check the error here, as this field may
not even exist. */
halDevices[i], "info.vendor", 0);
{
{
}
else
{
}
}
else
{
if (product == 0)
{
LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
}
}
if (vendor != 0)
{
}
if (product != 0)
{
}
// }
// else
// {
// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
// }
#ifndef RT_OS_SOLARIS
#else
#endif
}
else
{
LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
}
}
}
else
{
LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
{
LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
}
else
{
LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
}
else
{
LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
}
}
else
{
LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
}
}
else
{
LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
return halSuccess;
}
/**
* Helper function to query the hal subsystem for information about floppy drives attached to the
* system.
*
* @returns true if information was successfully obtained, false otherwise
* @retval list drives found will be attached to this list
*/
{
bool halSuccess = false;
if (!gLibHalCheckPresence())
return false;
if (dbusConnection != 0)
{
if (halContext != 0)
{
{
{
int numDevices;
"storage.drive_type", "floppy",
&numDevices, &dbusError);
if (halDevices != 0)
{
/* Hal is installed and working, so if no devices are reported, assume
that there are none. */
halSuccess = true;
for (int i = 0; i < numDevices; i++)
{
halDevices[i], "storage.drive_type", 0);
if (driveType != 0)
{
{
continue;
}
}
else
{
/* An error occurred. The attribute "storage.drive_type"
probably didn't exist. */
continue;
}
if (devNode != 0)
{
// if (validateDevice(devNode, false))
// {
/* We do not check the error here, as this field may
not even exist. */
halDevices[i], "info.vendor", 0);
{
{
}
else
{
}
}
else
{
if (product == 0)
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
}
}
if (vendor != 0)
{
}
if (product != 0)
{
}
// }
// else
// {
// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
// }
}
else
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
}
}
}
else
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
}
else
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
}
else
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
}
}
else
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
}
}
else
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
}
return halSuccess;
}
#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
/** @todo get rid of dead code below - RT_OS_SOLARIS and RT_OS_LINUX are never both set */
#if defined(RT_OS_SOLARIS)
/**
* Helper function to parse the given mount file and add found entries
*/
{
#ifdef RT_OS_LINUX
if (mtab)
{
char *mnt_type;
char *mnt_dev;
char *tmp;
{
// supermount fs case
{
if (tmp)
{
if (mnt_type)
{
if (tmp)
*tmp = '\0';
}
}
if (tmp)
{
if (mnt_dev)
{
if (tmp)
*tmp = '\0';
}
}
}
// use strstr here to cover things fs types like "udf,iso9660"
{
/** @todo check whether we've already got the drive in our list! */
if (validateDevice(mnt_dev, true))
{
}
}
}
}
#else // RT_OS_SOLARIS
if (mntFile)
{
{
{
// skip devices we are not interested in
{
if (validateDevice(rawDevName, true))
{
}
}
}
}
}
#endif
}
/**
* Helper function to check whether the given device node is a valid drive
*/
{
bool retValue = false;
// sanity check
if (!deviceNode)
{
return false;
}
// first a simple stat() call
{
return false;
}
else
{
if (isCDROM)
{
{
int fileHandle;
// now try to open the device
if (fileHandle >= 0)
{
// this call will finally reveal the whole truth
#ifdef RT_OS_LINUX
#else
#endif
{
retValue = true;
}
}
}
} else
{
// floppy case
{
/// @todo do some more testing, maybe a nice IOCTL!
retValue = true;
}
}
}
return retValue;
}
#endif // RT_OS_SOLARIS
#ifdef VBOX_WITH_USB
/**
* Checks for the presense and status of the USB Proxy Service.
* Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
* warning) if the proxy service is not available due to the way the host is
* available on a Linux host) or E_FAIL and a corresponding error message
* otherwise. Intended to be used by methods that rely on the Proxy Service
* availability.
*
* @note This method may return a warning result code. It is recommended to use
* MultiError to store the return value.
*
* @note Locks this object for reading.
*/
{
AutoCaller autoCaller(this);
if (!m->pUSBProxyService->isActive())
{
/* disable the USB controller completely to avoid assertions if the
* USB proxy service could not start. */
return setWarning(E_FAIL,
tr("Could not load the Host USB Proxy Service (%Rrc). The service might not be installed on the host computer"),
m->pUSBProxyService->getLastError());
#ifdef RT_OS_LINUX
return setWarning (VBOX_E_HOST_ERROR,
# ifdef VBOX_WITH_DBUS
tr ("The USB Proxy Service could not be started, because neither the USB file system (usbfs) nor the hardware information service (hal) is available")
# else
tr ("The USB Proxy Service could not be started, because the USB file system (usbfs) is not available")
# endif
);
#else /* !RT_OS_LINUX */
return setWarning (E_FAIL,
tr ("The USB Proxy Service has not yet been ported to this host"));
#endif /* !RT_OS_LINUX */
return setWarning (E_FAIL,
tr ("Could not load the Host USB Proxy service (%Rrc)"),
m->pUSBProxyService->getLastError());
}
return S_OK;
}
#endif /* VBOX_WITH_USB */
#ifdef VBOX_WITH_RESOURCE_USAGE_API
{
/* Create sub metrics */
"Percentage of processor time spent in user mode.");
"Percentage of processor time spent in kernel mode.");
"Percentage of processor time spent idling.");
"Average of current frequency of all processors.");
"Total physical memory installed.");
"Physical memory currently occupied.");
"Physical memory currently available to applications.");
"Total physical memory used by the hypervisor.");
"Total physical memory free inside the hypervisor.");
"Total physical memory ballooned by the hypervisor.");
"Total physical memory shared between VMs.");
/* Create and register base metrics */
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
new pm::AggregateAvg()));
new pm::AggregateMin()));
new pm::AggregateMax()));
}
{
aCollector->unregisterMetricsFor(this);
aCollector->unregisterBaseMetricsFor(this);
}
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
/* vi: set tabstop=4 shiftwidth=4 expandtab: */