HostImpl.cpp revision 7bb91888f724cf8f14131a3d575fa77ef9591396
/* $Id$ */
/** @file
* VirtualBox COM class implementation: Host
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* 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.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#ifdef RT_OS_LINUX
// # include <unistd.h>
// # include <fcntl.h>
// # include <mntent.h>
/* bird: This is a hack to work around conflicts between these linux kernel headers
* and the GLIBC tcpip headers. They have different declarations of the 4
* standard byte order functions. */
// # define _LINUX_BYTEORDER_GENERIC_H
# 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>
# ifdef VBOX_SOLARIS_NSL_RESOLVED
# include <libdevinfo.h>
# endif
/* 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"
#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 */
#include "HostImpl.h"
#include "HostDVDDriveImpl.h"
#include "HostFloppyDriveImpl.h"
#include "HostNetworkInterfaceImpl.h"
#ifdef VBOX_WITH_USB
# include "HostUSBDeviceImpl.h"
# include "USBDeviceFilterImpl.h"
# include "USBProxyService.h"
#endif
#include "VirtualBoxImpl.h"
#include "MachineImpl.h"
#include "Logging.h"
#ifdef RT_OS_DARWIN
#endif
#ifdef RT_OS_SOLARIS
#endif
#ifdef VBOX_WITH_HOSTNETIF_API
#include "netif.h"
#endif
#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
# include <VBox/WinNetConfig.h>
#endif /* #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
#include <stdio.h>
#include <algorithm>
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
{
return S_OK;
}
void Host::FinalRelease()
{
if (isReady())
uninit();
}
// public initializer/uninitializer for internal purposes only
/////////////////////////////////////////////////////////////////////////////
/**
* Initializes the host object.
*
* @param aParent VirtualBox parent object.
*/
{
AutoWriteLock alock (this);
#ifdef VBOX_WITH_USB
/*
* Create and initialize the USB Proxy Service.
*/
# if defined (RT_OS_DARWIN)
mUSBProxyService = new USBProxyServiceDarwin (this);
# elif defined (RT_OS_LINUX)
mUSBProxyService = new USBProxyServiceLinux (this);
mUSBProxyService = new USBProxyServiceOs2 (this);
# elif defined (RT_OS_SOLARIS)
mUSBProxyService = new USBProxyServiceSolaris (this);
# elif defined (RT_OS_WINDOWS)
mUSBProxyService = new USBProxyServiceWindows (this);
# else
mUSBProxyService = 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. */
fVTxAMDVSupported = false;
fLongModeSupported = false;
fPAESupported = false;
if (ASMHasCpuId())
{
/* Query AMD features. */
)
{
if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
)
fVTxAMDVSupported = true;
}
else
if ( u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX
)
{
)
fVTxAMDVSupported = true;
}
}
setReady(true);
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.
*/
{
AssertReturn (isReady(), (void) 0);
#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 mUSBProxyService;
LogFlowThisFunc (("Done stopping USB proxy service.\n"));
#endif
delete mHostPowerService;
/* uninit all USB device filters still referenced by clients */
#ifdef VBOX_WITH_USB
#endif
}
// IHost properties
/////////////////////////////////////////////////////////////////////////////
/**
* Returns a list of host DVD drives.
*
* @returns COM status code
* @param drives address of result pointer
*/
{
AutoWriteLock alock (this);
CHECK_READY();
#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
// Not all Solaris versions ship with libhal.
// So use a fallback approach similar to Linux.
{
if (RTEnvGet("VBOX_CDROM"))
{
char *cdromDrive;
while (cdromDrive)
{
if (validateDevice(cdromDrive, true))
{
}
}
}
else
{
// this might work on Solaris version older than Nevada.
if (validateDevice("/cdrom/cdrom0", true))
{
}
// check the mounted drives
}
}
#elif defined(RT_OS_LINUX)
{
rc = E_OUTOFMEMORY;
}
#elif defined(RT_OS_DARWIN)
while (cur)
{
/* next */
}
#else
/* PORTME */
#endif
return rc;
}
/**
* Returns a list of host floppy drives.
*
* @returns COM status code
* @param drives address of result pointer
*/
{
AutoWriteLock alock (this);
CHECK_READY();
#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)
{
rc = E_OUTOFMEMORY;
}
#else
/* PORTME */
#endif
return rc;
}
#ifdef RT_OS_WINDOWS
/**
* Windows helper function for Host::COMGETTER(NetworkInterfaces).
*
* @returns true / false.
*
* @param guid The GUID.
*/
static bool IsTAPDevice(const char *guid)
{
int i = 0;
bool ret = false;
status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ, &hNetcard);
if (status != ERROR_SUCCESS)
return false;
for (;;)
{
char szEnumName[256];
char szNetCfgInstanceId[256];
len = sizeof(szEnumName);
if (status != ERROR_SUCCESS)
break;
if (status == ERROR_SUCCESS)
{
len = sizeof(szNetCfgInstanceId);
status = RegQueryValueExA(hNetCardGUID, "NetCfgInstanceId", NULL, &dwKeyType, (LPBYTE)szNetCfgInstanceId, &len);
{
char szNetProductName[256];
char szNetProviderName[256];
szNetProductName[0] = 0;
len = sizeof(szNetProductName);
status = RegQueryValueExA(hNetCardGUID, "ProductName", NULL, &dwKeyType, (LPBYTE)szNetProductName, &len);
szNetProviderName[0] = 0;
len = sizeof(szNetProviderName);
status = RegQueryValueExA(hNetCardGUID, "ProviderName", NULL, &dwKeyType, (LPBYTE)szNetProviderName, &len);
{
ret = true;
break;
}
}
}
++i;
}
return ret;
}
#endif /* RT_OS_WINDOWS */
#ifdef RT_OS_SOLARIS
static void vboxSolarisAddHostIface(char *pszIface, int Instance, PCRTMAC pMac, void *pvHostNetworkInterfaceList)
{
std::list<ComObjPtr <HostNetworkInterface> > *pList = (std::list<ComObjPtr <HostNetworkInterface> > *)pvHostNetworkInterfaceList;
static NICMap SolarisNICMap;
if (SolarisNICMap.empty())
{
}
/*
* Try picking up description from our NIC map.
*/
char szNICInstance[128];
char szNICDesc[256];
if (Description != "")
else
/*
* Construct UUID with interface name and the MAC address if available.
*/
RTUuidClear(&Uuid);
if (pMac)
{
}
}
static boolean_t vboxSolarisAddLinkHostIface(const char *pszIface, void *pvHostNetworkInterfaceList)
{
/*
* Clip off the zone instance number from the interface name (if any).
*/
char szIfaceName[128];
if (pszColon)
*pszColon = '\0';
/*
* Get the instance number from the interface name, then clip it off.
*/
int cbInstance = 0;
for (int i = 0; i < cbIface - 1; i++)
{
if (!RT_C_IS_DIGIT(*pszEnd))
break;
cbInstance++;
pszEnd--;
}
/*
* Add the interface.
*/
/*
* Continue walking...
*/
return _B_FALSE;
}
static bool vboxSolarisSortNICList(const ComObjPtr <HostNetworkInterface> Iface1, const ComObjPtr <HostNetworkInterface> Iface2)
{
}
static bool vboxSolarisSameNIC(const ComObjPtr <HostNetworkInterface> Iface1, const ComObjPtr <HostNetworkInterface> Iface2)
{
}
# ifdef VBOX_SOLARIS_NSL_RESOLVED
static int vboxSolarisAddPhysHostIface(di_node_t Node, di_minor_t Minor, void *pvHostNetworkInterfaceList)
{
/*
* Skip aggregations.
*/
return DI_WALK_CONTINUE;
/*
* Skip softmacs.
*/
return DI_WALK_CONTINUE;
return DI_WALK_CONTINUE;
}
# endif /* VBOX_SOLARIS_NSL_RESOLVED */
#endif
#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
# define VBOX_APP_NAME L"VirtualBox"
static int vboxNetWinAddComponent(std::list <ComObjPtr <HostNetworkInterface> > * pPist, INetCfgComponent * pncc)
{
int rc = VERR_GENERAL_FAILURE;
{
{
/* create a new object and add it to the list */
/* remove the curly bracket at the end */
{
rc = VINF_SUCCESS;
}
else
{
Assert(0);
}
}
}
return rc;
}
#endif /* #if 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) (IHostNetworkInterfaceCollection **networkInterfaces)
{
if (!networkInterfaces)
return E_POINTER;
AutoWriteLock alock (this);
CHECK_READY();
#ifdef VBOX_WITH_HOSTNETIF_API
if (rc)
{
}
#else
# if defined(RT_OS_DARWIN)
while (pEtherNICs)
{
/* next, free current */
void *pvFree = pEtherNICs;
}
# elif defined(RT_OS_SOLARIS)
# ifdef VBOX_SOLARIS_NSL_RESOLVED
/*
* Use libdevinfo for determining all physical interfaces.
*/
if (Root != DI_NODE_NIL)
{
}
/*
* Use libdlpi for determining all DLPI interfaces.
*/
if (VBoxSolarisLibDlpiFound())
# endif /* VBOX_SOLARIS_NSL_RESOLVED */
/*
* This gets only the list of all plumbed logical interfaces.
* This is needed for zones which cannot access the device tree
* and in this case we just let them use the list of plumbed interfaces
* on the zone.
*/
if (Sock > 0)
{
if (!rc)
{
if (!rc)
{
for (int i = 0; i < IfNum.lifn_count; i++)
{
/*
* Skip loopback interfaces.
*/
continue;
#if 0
if (!rc)
{
/*
* We might fail if the interface has not been assigned an IP address.
* That doesn't matter; as long as it's plumbed we can pick it up.
* But, if it has not acquired an IP address we cannot obtain it's MAC
* address this way, so we just use all zeros there.
*/
if (!rc)
else
}
#endif
}
}
}
}
/*
* Weed out duplicates caused by dlpi_walk inconsistencies across Nevadas.
*/
# elif defined RT_OS_WINDOWS
# ifndef VBOX_WITH_NETFLT
static const char *NetworkKey = "SYSTEM\\CurrentControlSet\\Control\\Network\\"
"{4D36E972-E325-11CE-BFC1-08002BE10318}";
if (status != ERROR_SUCCESS)
for (int i = 0;; ++ i)
{
char szNetworkGUID [256];
char szNetworkConnection [256];
len = sizeof (szNetworkGUID);
if (status != ERROR_SUCCESS)
break;
if (!IsTAPDevice(szNetworkGUID))
continue;
"%s\\Connection", szNetworkGUID);
if (status == ERROR_SUCCESS)
{
{
if (status == ERROR_SUCCESS)
{
/* put a trailing zero, just in case (see MSDN) */
/* create a new object and add it to the list */
/* remove the curly bracket at the end */
}
}
}
}
# 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 */
{
{
{
{
}
}
}
}
}
}
}
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
AutoWriteLock alock (this);
CHECK_READY();
#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
AutoWriteLock alock (this);
CHECK_READY();
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. */
#endif
}
/**
* Returns the number of installed logical processors
*
* @returns COM status code
* @param count address of result variable
*/
{
AutoWriteLock alock (this);
CHECK_READY();
*aCount = RTMpGetPresentCount();
return S_OK;
}
/**
* Returns the number of online logical processors
*
* @returns COM status code
* @param count address of result variable
*/
{
AutoWriteLock alock (this);
CHECK_READY();
*aCount = RTMpGetOnlineCount();
return S_OK;
}
/**
* 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.
*/
{
AutoWriteLock alock (this);
CHECK_READY();
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, NULL if known or aCpuId is invalid.
*/
{
AutoWriteLock alock (this);
CHECK_READY();
/** @todo */
}
/**
* 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
*/
{
AutoWriteLock alock (this);
CHECK_READY();
switch (aFeature)
{
break;
case ProcessorFeature_PAE:
break;
break;
default:
}
return S_OK;
}
/**
* Returns the amount of installed system memory in megabytes
*
* @returns COM status code
* @param size address of result variable
*/
{
AutoWriteLock alock (this);
CHECK_READY();
/* @todo This is an ugly hack. There must be a function in IPRT for that. */
if (!hal)
return VERR_INTERNAL_ERROR;
*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
*/
{
AutoWriteLock alock (this);
CHECK_READY();
/* @todo This is an ugly hack. There must be a function in IPRT for that. */
if (!hal)
return VERR_INTERNAL_ERROR;
*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
*/
{
AutoWriteLock alock (this);
CHECK_READY();
/** @todo */
}
/**
* Returns the version string of the host operating system
*
* @returns COM status code
* @param os address of result variable
*/
{
AutoWriteLock alock (this);
CHECK_READY();
/** @todo */
}
/**
* Returns the current host time in milliseconds since 1970-01-01 UTC.
*
* @returns COM status code
* @param time address of result variable
*/
{
AutoWriteLock alock (this);
CHECK_READY();
return S_OK;
}
// IHost methods
////////////////////////////////////////////////////////////////////////////////
#ifdef RT_OS_WINDOWS
/**
* Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
* later OSes) and it has the UAC (User Account Control) feature enabled.
*/
static BOOL IsUACEnabled()
{
LogFlowFunc (("dwMajorVersion=%d, dwMinorVersion=%d\n",
/* we are interested only in Vista (and newer versions...). In all
* earlier versions UAC is not present. */
return FALSE;
/* the default EnableLUA value is 1 (Enabled) */
"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
0, KEY_QUERY_VALUE, &hKey);
if (rc == ERROR_SUCCESS)
{
RegCloseKey (hKey);
}
return dwEnableLUA == 1;
}
{
/* for SVCHlpMsg::CreateHostNetworkInterface */
/* for SVCHlpMsg::RemoveHostNetworkInterface */
};
{
AutoWriteLock alock (this);
CHECK_READY();
/* first check whether an interface with the given name already exists */
{
return setError (E_INVALIDARG,
}
/* create a progress object */
FALSE /* aCancelable */);
/* create a new uninitialized host interface object */
/* create the networkInterfaceHelperClient() argument */
d (new NetworkInterfaceHelperClientData());
static_cast <void *> (d.get()),
progress);
{
/* d is now owned by networkInterfaceHelperClient(), so release it */
d.release();
}
return rc;
}
{
AutoWriteLock alock (this);
CHECK_READY();
/* first check whether an interface with the given name already exists */
{
return setError (VBOX_E_OBJECT_NOT_FOUND,
tr ("Host network interface with UUID {%RTuuid} does not exist"),
/* return the object to be removed to the caller */
}
/* create a progress object */
FALSE /* aCancelable */);
/* create the networkInterfaceHelperClient() argument */
d (new NetworkInterfaceHelperClientData());
static_cast <void *> (d.get()),
progress);
{
/* d is now owned by networkInterfaceHelperClient(), so release it */
d.release();
}
return rc;
}
#endif /* RT_OS_WINDOWS */
{
#ifdef VBOX_WITH_USB
AutoWriteLock alock (this);
CHECK_READY();
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. */
AutoWriteLock alock (this);
CHECK_READY();
if (!filter)
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) */
{
}
/* save the global settings */
#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. */
AutoWriteLock alock (this);
CHECK_READY();
if (!mUSBDeviceFilters.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 */
#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
}
// public methods only for internal purposes
////////////////////////////////////////////////////////////////////////////////
{
using namespace settings;
AutoWriteLock alock (this);
CHECK_READY();
#ifdef VBOX_WITH_USB
{
else
else
action);
/* error info is set by init() when appropriate */
/* notify the proxy (only when the filter is active) */
{
}
}
#endif /* VBOX_WITH_USB */
return rc;
}
{
using namespace settings;
AutoWriteLock alock (this);
CHECK_READY();
#ifdef VBOX_WITH_USB
/* first, delete the entry */
/* then, recreate it */
{
/* all are optional */
/* action is mandatory */
if (action == USBDeviceFilterAction_Ignore)
else if (action == USBDeviceFilterAction_Hold)
else
++ it;
}
#endif /* VBOX_WITH_USB */
return S_OK;
}
#ifdef VBOX_WITH_USB
/**
* Called by setter methods of all USB device filters.
*/
{
AutoWriteLock alock (this);
CHECK_READY();
{
if (aActiveChanged)
{
{
}
else
{
}
}
else
{
{
// update the filter in the proxy
}
}
// save the global settings... yeah, on every single filter property change
return mParent->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.
*/
void Host::getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters, VirtualBox::SessionMachineVector *aMachines)
{
AutoWriteLock alock (this);
}
#endif /* VBOX_WITH_USB */
// private methods
////////////////////////////////////////////////////////////////////////////////
#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
/* 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
{
}
Bstr (halDevices[i]),
Bstr (description));
}
else
{
if (product == 0)
{
LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
}
Bstr (halDevices[i]));
}
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
{
}
Bstr (halDevices[i]),
Bstr (description));
}
else
{
if (product == 0)
{
LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
}
Bstr (halDevices[i]));
}
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 */
#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, 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.
*/
{
AutoWriteLock alock (this);
CHECK_READY();
if (!mUSBProxyService->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 be not installed on the host computer"),
return setWarning (E_FAIL,
tr ("The USB Proxy Service has not yet been ported to this host"));
return setWarning (E_FAIL,
tr ("Could not load the Host USB Proxy service (%Rrc)"),
}
return S_OK;
}
#endif /* VBOX_WITH_USB */
#ifdef RT_OS_WINDOWS
/* The original source of the VBoxTAP adapter creation/destruction code has the following copyright */
/*
Copyright 2004 by the Massachusetts Institute of Technology
All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the Massachusetts
Institute of Technology (M.I.T.) not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
*/
/**
* Use the IShellFolder API to rename the connection.
*/
{
/* This is the GUID for the network connections folder. It is constant.
* {7007ACC7-3202-11D1-AAD2-00805FC1270E} */
const GUID CLSID_NetworkConnections = {
0x7007ACC7, 0x3202, 0x11D1, {
0xAA, 0xD2, 0x00, 0x80, 0x5F, 0xC1, 0x27, 0x0E
}
};
/* Build the display name in the form "::{GUID}". */
return E_INVALIDARG;
/* Create an instance of the network connections folder. */
reinterpret_cast <LPVOID *> (&pShellFolder));
/* Parse the display name. */
{
}
{
&pidl);
}
if (pShellFolder)
pShellFolder->Release();
return hr;
}
{
/* First try the IShellFolder interface, which was unimplemented
* for the network connections folder before XP. */
{
/** @todo that code doesn't seem to work! */
/* The IShellFolder interface is not implemented on this platform.
* Try the (undocumented) HrRenameConnection API in the netshell
* library. */
return E_FAIL;
return E_FAIL;
"HrRenameConnection");
if (RenameConnectionFunc == NULL)
{
return E_FAIL;
}
}
return status;
return S_OK;
}
#define SetErrBreak(strAndArgs) \
if (1) { \
} else do {} while (0)
/* static */
{
int vrc = VINF_SUCCESS;
do
{
/* for our purposes, 2k buffer is more
* than enough to obtain the hardware ID
* of the VBoxTAP driver. */
/* initialize the structure size */
/* copy the net class GUID */
/* create an empty device info set associated with the net class GUID */
if (hDeviceInfo == INVALID_HANDLE_VALUE)
SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
GetLastError()));
/* get the class name from GUID */
if (!ok)
SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
GetLastError()));
/* create a device info element and add the new device instance
* key to registry */
if (!ok)
SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
GetLastError()));
/* select the newly created device info to be the currently
selected member */
if (!ok)
SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
GetLastError()));
/* build a list of class drivers */
if (!ok)
SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
GetLastError()));
destroyList = TRUE;
/* enumerate the driver info list */
while (TRUE)
{
/* if the function failed and GetLastError() returned
* ERROR_NO_MORE_ITEMS, then we have reached the end of the
* list. Othewise there was something wrong with this
* particular driver. */
if (!ret)
{
if(GetLastError() == ERROR_NO_MORE_ITEMS)
break;
else
{
index++;
continue;
}
}
/* if we successfully find the hardware ID and it turns out to
* be the one for the loopback driver, then we are done. */
sizeof (detailBuf),
NULL))
{
TCHAR * t;
/* pDriverInfoDetail->HardwareID is a MULTISZ string. Go through the
* whole list and see if there is a match somewhere. */
t = pDriverInfoDetail->HardwareID;
{
if (!_tcsicmp(t, DRIVERHWID))
break;
t += _tcslen(t) + 1;
}
{
break;
}
}
index ++;
}
if (!found)
"Please reinstall")));
/* set the loopback driver to be the currently selected */
if (!ok)
SetErrBreak (("SetupDiSetSelectedDriver failed (0x%08X)",
GetLastError()));
/* register the phantom device to prepare for install */
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller failed (0x%08X)",
GetLastError()));
/* registered, but remove if errors occur in the following code */
registered = TRUE;
/* ask the installer if we can install the device */
if (!ok)
{
if (GetLastError() != ERROR_DI_DO_DEFAULT)
SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
GetLastError()));
/* that's fine */
}
/* install the files first */
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
GetLastError()));
/* get the device install parameters and disable filecopy */
if (ok)
{
if (!ok)
SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
GetLastError()));
}
/*
* Register any device-specific co-installers for this device,
*/
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
GetLastError()));
/*
* install any installer-specified interfaces.
* and then do the real install
*/
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
GetLastError()));
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
GetLastError()));
/* Figure out NetCfgInstanceId */
0,
KEY_READ);
if (hkey == INVALID_HANDLE_VALUE)
SetErrBreak (("SetupDiOpenDevRegKey failed (0x%08X)",
GetLastError()));
cbSize = sizeof (pCfgGuidString);
RegCloseKey (hkey);
SetErrBreak (("Failed to set interface name (ret=0x%08X, "
"pCfgGuidString='%ls', cbSize=%d)",
}
while (0);
/*
* cleanup
*/
if (hDeviceInfo != INVALID_HANDLE_VALUE)
{
/* an error has occured, but the device is registered, we must remove it */
if (ret != 0 && registered)
/* destroy the driver info list */
if (destroyList)
/* clean up the device info set */
}
/* return the network connection GUID on success */
if (RT_SUCCESS (vrc))
{
/* remove the curly bracket at the end */
}
return vrc;
}
/* static */
{
int vrc = VINF_SUCCESS;
do
{
/* We have to find the device instance ID through a registry search */
HKEY hkeyNetwork = 0;
HKEY hkeyConnection = 0;
do
{
char strRegLocation [256];
"SYSTEM\\CurrentControlSet\\Control\\Network\\"
"{4D36E972-E325-11CE-BFC1-08002BE10318}\\{%s}",
KEY_READ, &hkeyNetwork);
SetErrBreak ((
tr ("Host interface network is not found in registry (%s) [1]"),
SetErrBreak ((
tr ("Host interface network is not found in registry (%s) [2]"),
SetErrBreak ((
tr ("Host interface network is not found in registry (%s) [3]"),
}
while (0);
if (hkeyConnection)
if (hkeyNetwork)
if (RT_FAILURE (vrc))
break;
/*
* Now we are going to enumerate all network devices and
* wait until we encounter the right device instance ID
*/
do
{
/* initialize the structure size */
/* copy the net class GUID */
/* return a device info set contains all installed devices of the Net class */
if (hDeviceInfo == INVALID_HANDLE_VALUE)
/* enumerate the driver info list */
while (TRUE)
{
if (!ok)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
break;
else
{
index++;
continue;
}
}
/* try to get the hardware ID registry property */
NULL,
NULL,
0,
&size);
if (!ok)
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
index++;
continue;
}
NULL,
size,
NULL);
if (!ok)
{
free (deviceHwid);
deviceHwid = NULL;
index++;
continue;
}
}
else
{
/* something is wrong. This shouldn't have worked with a NULL buffer */
index++;
continue;
}
for (TCHAR *t = deviceHwid;
t += _tcslen (t) + 1)
{
if (!_tcsicmp (DRIVERHWID, t))
{
/* get the device instance ID */
{
/* compare to what we determined before */
{
break;
}
}
}
}
if (deviceHwid)
{
free (deviceHwid);
deviceHwid = NULL;
}
if (found)
break;
index++;
}
GetLastError()));
if (!ok)
SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
GetLastError()));
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
GetLastError()));
}
while (0);
/* clean up the device info set */
if (hDeviceInfo != INVALID_HANDLE_VALUE)
if (RT_FAILURE (vrc))
break;
}
while (0);
return vrc;
}
/* static */
{
LogFlowFunc (("aClient={%p}, aProgress={%p}, aUser={%p}\n",
d (static_cast <NetworkInterfaceHelperClientData *> (aUser));
{
/* "cleanup only" mode, just return (it will free aUser) */
return S_OK;
}
int vrc = VINF_SUCCESS;
switch (d->msgCode)
{
{
LogFlowFunc (("CreateHostNetworkInterface:\n"));
/* write message and parameters */
if (RT_FAILURE (vrc)) break;
if (RT_FAILURE (vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE (vrc)) break;
switch (reply)
{
{
/* read the GUID */
if (RT_FAILURE (vrc)) break;
/* initialize the object returned to the caller by
* CreateHostNetworkInterface() */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE (vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
"Invalid message code %d (%08lX)\n",
}
}
}
break;
}
{
LogFlowFunc (("RemoveHostNetworkInterface:\n"));
/* write message and parameters */
if (RT_FAILURE (vrc)) break;
if (RT_FAILURE (vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
if (RT_FAILURE (vrc)) break;
switch (reply)
{
{
/* no parameters */
endLoop = true;
break;
}
{
/* read the error message */
if (RT_FAILURE (vrc)) break;
endLoop = true;
break;
}
default:
{
endLoop = true;
"Invalid message code %d (%08lX)\n",
}
}
}
break;
}
default:
"Invalid message code %d (%08lX)\n",
}
if (aVrc)
return rc;
}
/* static */
{
int vrc = VINF_SUCCESS;
switch (aMsgCode)
{
{
LogFlowFunc (("CreateHostNetworkInterface:\n"));
if (RT_FAILURE (vrc)) break;
if (RT_SUCCESS (vrc))
{
/* write success followed by GUID */
if (RT_FAILURE (vrc)) break;
if (RT_FAILURE (vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE (vrc)) break;
if (RT_FAILURE (vrc)) break;
}
break;
}
{
LogFlowFunc (("RemoveHostNetworkInterface:\n"));
if (RT_FAILURE (vrc)) break;
if (RT_SUCCESS (vrc))
{
/* write parameter-less success */
if (RT_FAILURE (vrc)) break;
}
else
{
/* write failure followed by error message */
if (RT_FAILURE (vrc)) break;
if (RT_FAILURE (vrc)) break;
}
break;
}
default:
}
return vrc;
}
#endif /* RT_OS_WINDOWS */
#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.");
/* 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()));
};
{
aCollector->unregisterMetricsFor (this);
aCollector->unregisterBaseMetricsFor (this);
};
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
/* vi: set tabstop=4 shiftwidth=4 expandtab: */