HostImpl.cpp revision 6d7c636aa41c6723d6d427826c0974050c3a8e31
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/** @file
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * VirtualBox COM class implementation
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/*
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Copyright (C) 2006-2007 innotek GmbH
441579693f771e49eb05f2bd20c316232155675bvboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * available from http://www.virtualbox.org. This file is free software;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * General Public License (GPL) as published by the Free Software
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_LINUX
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <sys/types.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <sys/stat.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <unistd.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <sys/ioctl.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <fcntl.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <mntent.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/* bird: This is a hack to work around conflicts between these linux kernel headers
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * and the GLIBC tcpip headers. They have different declarations of the 4
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * standard byte order functions. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#define _LINUX_BYTEORDER_GENERIC_H
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <linux/cdrom.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_USE_LIBHAL
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// # include <libhal.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// /* These are defined by libhal.h and by VBox header files. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// # undef TRUE
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// # undef FALSE
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "vbox-libhal.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
441579693f771e49eb05f2bd20c316232155675bvboxsync#include <errno.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* RT_OS_LINUX */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_SOLARIS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <fcntl.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <unistd.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <stropts.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <errno.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <limits.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <stdio.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <sys/types.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <sys/stat.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <sys/cdio.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <sys/dkio.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <sys/mnttab.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <sys/mntent.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# ifdef VBOX_USE_LIBHAL
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include "vbox-libhal.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncextern "C" char *getfullrawname(char *);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* RT_OS_SOLARIS */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_WINDOWS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#define _WIN32_DCOM
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <windows.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <shellapi.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#define INITGUID
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <guiddef.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <devguid.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <objbase.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <setupapi.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <shlobj.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <cfgmgr32.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* RT_OS_WINDOWS */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "HostImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "HostDVDDriveImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "HostFloppyDriveImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "HostUSBDeviceImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "USBDeviceFilterImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "USBProxyService.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "VirtualBoxImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "MachineImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "Logging.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_DARWIN
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "darwin/iokit.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_WINDOWS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include "HostNetworkInterfaceImpl.h"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <VBox/usb.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <VBox/err.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <iprt/string.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <iprt/system.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <iprt/time.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <iprt/param.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <iprt/env.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_SOLARIS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# include <iprt/path.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <stdio.h>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#include <algorithm>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// constructor / destructor
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/////////////////////////////////////////////////////////////////////////////
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::FinalConstruct()
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncvoid Host::FinalRelease()
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (isReady())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync uninit();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// public initializer/uninitializer for internal purposes only
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/////////////////////////////////////////////////////////////////////////////
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Initializes the host object.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM result indicator
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param parent handle of our parent object
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::init (VirtualBox *parent)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("isReady=%d\n", isReady()));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (parent, E_INVALIDARG);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (!isReady(), E_UNEXPECTED);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mParent = parent;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#if defined (RT_OS_DARWIN) && defined (VBOX_WITH_USB)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = new USBProxyServiceDarwin (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined (RT_OS_LINUX) && defined (VBOX_WITH_USB)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = new USBProxyServiceLinux (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined (RT_OS_OS2) && defined (VBOX_WITH_USB)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = new USBProxyServiceOs2 (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined (RT_OS_SOLARIS) && defined (VBOX_WITH_USB)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = new USBProxyServiceSolaris (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined (RT_OS_WINDOWS) && defined (VBOX_WITH_USB)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = new USBProxyServiceWin32 (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = new USBProxyService (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** @todo handle !mUSBProxySerivce->isActive() and mUSBProxyService->getLastError()
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * and somehow report or whatever that the proxy failed to startup.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Also, there might be init order issues... */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync setReady(true);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Uninitializes the host object and sets the ready flag to FALSE.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncvoid Host::uninit()
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("isReady=%d\n", isReady()));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertReturn (isReady(), (void) 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* wait for USB proxy service to terminate before we uninit all USB
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * devices */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("Stopping USB proxy service...\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync delete mUSBProxyService;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("Done stopping USB proxy service.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService = NULL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* uninit all USB device filters still referenced by clients */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync uninitDependentChildren();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBDeviceFilters.clear();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBDevices.clear();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync setReady (FALSE);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// IHost properties
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/////////////////////////////////////////////////////////////////////////////
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns a list of host DVD drives.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param drives address of result pointer
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(DVDDrives) (IHostDVDDriveCollection **drives)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!drives)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync std::list <ComObjPtr <HostDVDDrive> > list;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#if defined(RT_OS_WINDOWS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int sz = GetLogicalDriveStrings(0, NULL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync TCHAR *hostDrives = new TCHAR[sz+1];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync GetLogicalDriveStrings(sz, hostDrives);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync wchar_t driveName[3] = { '?', ':', '\0' };
6ef855ecf2121f708685307839f1262e0db1a024vboxsync TCHAR *p = hostDrives;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync do
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (GetDriveType(p) == DRIVE_CDROM)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync driveName[0] = *p;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr (driveName));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync p += _tcslen(p) + 1;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (*p);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync delete[] hostDrives;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined(RT_OS_SOLARIS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# ifdef VBOX_USE_LIBHAL
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!getDVDInfoFromHal(list))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // Not all Solaris versions ship with libhal.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // So use a fallback approach similar to Linux.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (RTEnvGet("VBOX_CDROM"))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *cdromEnv = strdup(RTEnvGet("VBOX_CDROM"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *cdromDrive;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync cdromDrive = strtok(cdromEnv, ":"); /** @todo use strtok_r. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (cdromDrive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (validateDevice(cdromDrive, true))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr (cdromDrive));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync cdromDrive = strtok(NULL, ":");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync free(cdromEnv);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // this might work on Solaris version older than Nevada.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (validateDevice("/cdrom/cdrom0", true))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr ("cdrom/cdrom0"));
441579693f771e49eb05f2bd20c316232155675bvboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // check the mounted drives
6ef855ecf2121f708685307839f1262e0db1a024vboxsync parseMountTable(MNTTAB, list);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined(RT_OS_LINUX)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_USE_LIBHAL
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!getDVDInfoFromHal(list)) /* Playing with #defines in this way is nasty, I know. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* USE_LIBHAL defined */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // On Linux without hal, the situation is much more complex. We will take a
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // heuristical approach and also allow the user to specify a list of host
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // CDROMs using an environment variable.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // The general strategy is to try some known device names and see of they
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // exist. At last, we'll enumerate the /etc/fstab file (luckily there's an
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // API to parse it) for CDROM devices. Ok, let's start!
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (RTEnvGet("VBOX_CDROM"))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *cdromEnv = strdupa(RTEnvGet("VBOX_CDROM"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *cdromDrive;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync cdromDrive = strtok(cdromEnv, ":"); /** @todo use strtok_r */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (cdromDrive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (validateDevice(cdromDrive, true))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr (cdromDrive));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync cdromDrive = strtok(NULL, ":");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // this is a good guess usually
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (validateDevice("/dev/cdrom", true))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr ("/dev/cdrom"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // check the mounted drives
6ef855ecf2121f708685307839f1262e0db1a024vboxsync parseMountTable((char*)"/etc/mtab", list);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // check the drives that can be mounted
6ef855ecf2121f708685307839f1262e0db1a024vboxsync parseMountTable((char*)"/etc/fstab", list);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined(RT_OS_DARWIN)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync PDARWINDVD cur = DarwinGetDVDDrives();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (cur)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr<HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init(Bstr(cur->szName));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back(hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* next */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync void *freeMe = cur;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync cur = cur->pNext;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTMemFree(freeMe);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* PORTME */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr<HostDVDDriveCollection> collection;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection->init (list);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.queryInterfaceTo(drives);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns a list of host floppy drives.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param drives address of result pointer
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(FloppyDrives) (IHostFloppyDriveCollection **drives)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!drives)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync std::list <ComObjPtr <HostFloppyDrive> > list;
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync#ifdef RT_OS_WINDOWS
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync int sz = GetLogicalDriveStrings(0, NULL);
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync TCHAR *hostDrives = new TCHAR[sz+1];
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync GetLogicalDriveStrings(sz, hostDrives);
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync wchar_t driveName[3] = { '?', ':', '\0' };
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync TCHAR *p = hostDrives;
939e2ecb812c6402abcc63e7d615c5444acfd02evboxsync do
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (GetDriveType(p) == DRIVE_REMOVABLE)
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync {
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync driveName[0] = *p;
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync ComObjPtr <HostFloppyDrive> hostFloppyDriveObj;
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync hostFloppyDriveObj.createObject();
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync hostFloppyDriveObj->init (Bstr (driveName));
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync list.push_back (hostFloppyDriveObj);
58015215080abff9c3a752cb331b6efe29fe8933vboxsync }
adbb0da2a65fc315cb37869fd2c6c80c7d8d5b8bvboxsync p += _tcslen(p) + 1;
58015215080abff9c3a752cb331b6efe29fe8933vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (*p);
58015215080abff9c3a752cb331b6efe29fe8933vboxsync delete[] hostDrives;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#elif defined(RT_OS_LINUX)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_USE_LIBHAL
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!getFloppyInfoFromHal(list)) /* Playing with #defines in this way is nasty, I know. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* USE_LIBHAL defined */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // As with the CDROMs, on Linux we have to take a multi-level approach
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // involving parsing the mount tables. As this is not bulletproof, we'll
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // give the user the chance to override the detection by an environment
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // variable and skip the detection.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (RTEnvGet("VBOX_FLOPPY"))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *floppyEnv = strdupa(RTEnvGet("VBOX_FLOPPY"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *floppyDrive;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync floppyDrive = strtok(floppyEnv, ":");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (floppyDrive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // check if this is an acceptable device
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (validateDevice(floppyDrive, false))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostFloppyDrive> hostFloppyDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDriveObj->init (Bstr (floppyDrive));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostFloppyDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync floppyDrive = strtok(NULL, ":");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // we assume that a floppy is always /dev/fd[x] with x from 0 to 7
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char devName[10];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (int i = 0; i <= 7; i++)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync sprintf(devName, "/dev/fd%d", i);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (validateDevice(devName, false))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostFloppyDrive> hostFloppyDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDriveObj->init (Bstr (devName));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostFloppyDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* PORTME */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr<HostFloppyDriveCollection> collection;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection->init (list);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.queryInterfaceTo(drives);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_WINDOWS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic bool IsTAPDevice(const char *guid)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HKEY hNetcard;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LONG status;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DWORD len;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int i = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync bool ret = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ, &hNetcard);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status != ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while(true)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char szEnumName[256];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char szNetCfgInstanceId[256];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DWORD dwKeyType;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HKEY hNetCardGUID;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync len = sizeof(szEnumName);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegEnumKeyExA(hNetcard, i, szEnumName, &len, NULL, NULL, NULL, NULL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status != ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync break;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegOpenKeyExA(hNetcard, szEnumName, 0, KEY_READ, &hNetCardGUID);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status == ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync len = sizeof (szNetCfgInstanceId);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegQueryValueExA(hNetCardGUID, "NetCfgInstanceId", NULL, &dwKeyType, (LPBYTE)szNetCfgInstanceId, &len);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char szNetProductName[256];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char szNetProviderName[256];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync szNetProductName[0] = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync len = sizeof(szNetProductName);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegQueryValueExA(hNetCardGUID, "ProductName", NULL, &dwKeyType, (LPBYTE)szNetProductName, &len);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync szNetProviderName[0] = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync len = sizeof(szNetProviderName);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegQueryValueExA(hNetCardGUID, "ProviderName", NULL, &dwKeyType, (LPBYTE)szNetProviderName, &len);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ( !strcmp(szNetCfgInstanceId, guid)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync && !strcmp(szNetProductName, "VirtualBox TAP Adapter")
6ef855ecf2121f708685307839f1262e0db1a024vboxsync && !strcmp(szNetProviderName, "innotek GmbH"))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ret = true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RegCloseKey(hNetCardGUID);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync break;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RegCloseKey(hNetCardGUID);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ++i;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RegCloseKey (hNetcard);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return ret;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns a list of host network interfaces.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param drives address of result pointer
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(NetworkInterfaces) (IHostNetworkInterfaceCollection **networkInterfaces)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!networkInterfaces)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync std::list <ComObjPtr <HostNetworkInterface> > list;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync static const char *NetworkKey = "SYSTEM\\CurrentControlSet\\Control\\Network\\"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "{4D36E972-E325-11CE-BFC1-08002BE10318}";
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HKEY hCtrlNet;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LONG status;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DWORD len;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, NetworkKey, 0, KEY_READ, &hCtrlNet);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status != ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_FAIL, tr("Could not open registry key \"%s\""), NetworkKey);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (int i = 0;; ++ i)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char szNetworkGUID [256];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HKEY hConnection;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char szNetworkConnection [256];
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync len = sizeof (szNetworkGUID);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegEnumKeyExA (hCtrlNet, i, szNetworkGUID, &len, NULL, NULL, NULL, NULL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status != ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync break;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!IsTAPDevice(szNetworkGUID))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync continue;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTStrPrintf (szNetworkConnection, sizeof (szNetworkConnection),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "%s\\Connection", szNetworkGUID);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegOpenKeyExA (hCtrlNet, szNetworkConnection, 0, KEY_READ, &hConnection);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status == ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DWORD dwKeyType;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegQueryValueExW (hConnection, TEXT("Name"), NULL,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync &dwKeyType, NULL, &len);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status == ERROR_SUCCESS && dwKeyType == REG_SZ)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync size_t uniLen = (len + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr name (uniLen + 1 /* extra zero */);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync status = RegQueryValueExW (hConnection, TEXT("Name"), NULL,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync &dwKeyType, (LPBYTE) name.mutableRaw(), &len);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (status == ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTLogPrintf("Connection name %ls\n", name.mutableRaw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* put a trailing zero, just in case (see MSDN) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync name.mutableRaw() [uniLen] = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* create a new object and add it to the list */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostNetworkInterface> iface;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync iface.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* remove the curly bracket at the end */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync szNetworkGUID [strlen(szNetworkGUID) - 1] = '\0';
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (SUCCEEDED (iface->init (name, Guid (szNetworkGUID + 1))))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (iface);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RegCloseKey (hConnection);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RegCloseKey (hCtrlNet);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostNetworkInterfaceCollection> collection;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection->init (list);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.queryInterfaceTo (networkInterfaces);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* RT_OS_WINDOWS */
30dced101cb78acf27e752f25c88c1f637539a1evboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(USBDevices)(IHostUSBDeviceCollection **aUSBDevices)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_WITH_USB
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aUSBDevices)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock alock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync MultiResult rc = checkUSBProxyService();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDeviceCollection> collection;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection->init (mUSBDevices);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.queryInterfaceTo (aUSBDevices);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Note: The GUI depends on this method returning E_NOTIMPL with no
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * extended error info to indicate that USB is simply not available
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * (w/o treting it as a failure), for example, as in OSE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_NOTIMPL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(USBDeviceFilters) (IHostUSBDeviceFilterCollection **aUSBDeviceFilters)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_WITH_USB
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aUSBDeviceFilters)
441579693f771e49eb05f2bd20c316232155675bvboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock alock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync MultiResult rc = checkUSBProxyService();
441579693f771e49eb05f2bd20c316232155675bvboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDeviceFilterCollection> collection;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.createObject();
441579693f771e49eb05f2bd20c316232155675bvboxsync collection->init (mUSBDeviceFilters);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync collection.queryInterfaceTo (aUSBDeviceFilters);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsync return rc;
441579693f771e49eb05f2bd20c316232155675bvboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Note: The GUI depends on this method returning E_NOTIMPL with no
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * extended error info to indicate that USB is simply not available
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * (w/o treting it as a failure), for example, as in OSE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_NOTIMPL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns the number of installed logical processors
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param count address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(ProcessorCount)(ULONG *count)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!count)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
441579693f771e49eb05f2bd20c316232155675bvboxsync AutoLock lock(this);
441579693f771e49eb05f2bd20c316232155675bvboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *count = RTSystemProcessorGetCount();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns the (approximate) speed of the host CPU in MHz
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
441579693f771e49eb05f2bd20c316232155675bvboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param speed address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(ProcessorSpeed)(ULONG *speed)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!speed)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** @todo Add a runtime function for this which uses GIP. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns a description string for the host CPU
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param description address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(ProcessorDescription)(BSTR *description)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!description)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** @todo */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns the amount of installed system memory in megabytes
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param size address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(MemorySize)(ULONG *size)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!size)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** @todo */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns the current system memory free space in megabytes
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param available address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(MemoryAvailable)(ULONG *available)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!available)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** @todo */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns the name string of the host operating system
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param os address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(OperatingSystem)(BSTR *os)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
939e2ecb812c6402abcc63e7d615c5444acfd02evboxsync if (!os)
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync return E_POINTER;
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync AutoLock lock(this);
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync CHECK_READY();
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync /** @todo */
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync return S_OK;
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync}
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync/**
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync * Returns the version string of the host operating system
383d5bd7b4b12176fbba2defc6c162e5b84e8ac0vboxsync *
939e2ecb812c6402abcc63e7d615c5444acfd02evboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param os address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(OSVersion)(BSTR *version)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
441579693f771e49eb05f2bd20c316232155675bvboxsync if (!version)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /** @todo */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns the current host time in milliseconds since 1970-01-01 UTC.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns COM status code
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @param time address of result variable
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::COMGETTER(UTCTime)(LONG64 *aUTCTime)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aUTCTime)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock(this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RTTIMESPEC now;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *aUTCTime = RTTimeSpecGetMilli(RTTimeNow(&now));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// IHost methods
6ef855ecf2121f708685307839f1262e0db1a024vboxsync////////////////////////////////////////////////////////////////////////////////
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_WINDOWS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Returns TRUE if the Windows version is 6.0 or greater (i.e. it's Vista and
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * later OSes) and it has the UAC (User Account Control) feature enabled.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncstatic BOOL IsUACEnabled()
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LONG rc = 0;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync OSVERSIONINFOEX info;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ZeroMemory (&info, sizeof (OSVERSIONINFOEX));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = GetVersionEx ((OSVERSIONINFO *) &info);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertReturn (rc != 0, FALSE);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowFunc (("dwMajorVersion=%d, dwMinorVersion=%d\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync info.dwMajorVersion, info.dwMinorVersion));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* we are interested only in Vista (and newer versions...). In all
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * earlier versions UAC is not present. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (info.dwMajorVersion < 6)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return FALSE;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* the default EnableLUA value is 1 (Enabled) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DWORD dwEnableLUA = 1;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HKEY hKey;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync 0, KEY_QUERY_VALUE, &hKey);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Assert (rc == ERROR_SUCCESS || rc == ERROR_PATH_NOT_FOUND);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (rc == ERROR_SUCCESS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsync DWORD cbEnableLUA = sizeof (dwEnableLUA);
441579693f771e49eb05f2bd20c316232155675bvboxsync rc = RegQueryValueExA (hKey, "EnableLUA", NULL, NULL,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (LPBYTE) &dwEnableLUA, &cbEnableLUA);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync RegCloseKey (hKey);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Assert (rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
441579693f771e49eb05f2bd20c316232155675bvboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsync LogFlowFunc (("rc=%d, dwEnableLUA=%d\n", rc, dwEnableLUA));
441579693f771e49eb05f2bd20c316232155675bvboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsync return dwEnableLUA == 1;
441579693f771e49eb05f2bd20c316232155675bvboxsync}
441579693f771e49eb05f2bd20c316232155675bvboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsyncstruct NetworkInterfaceHelperClientData
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync SVCHlpMsg::Code msgCode;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* for SVCHlpMsg::CreateHostNetworkInterface */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr name;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostNetworkInterface> iface;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* for SVCHlpMsg::RemoveHostNetworkInterface */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Guid guid;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync};
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHost::CreateHostNetworkInterface (INPTR BSTR aName,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync IHostNetworkInterface **aHostNetworkInterface,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync IProgress **aProgress)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aName)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_INVALIDARG;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aHostNetworkInterface)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aProgress)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HRESULT rc = S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* first check whether an interface with the given name already exists */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComPtr <IHostNetworkInterfaceCollection> coll;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = COMGETTER(NetworkInterfaces) (coll.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComPtr <IHostNetworkInterface> iface;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (SUCCEEDED (coll->FindByName (aName, iface.asOutParam())))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_FAIL,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("Host network interface '%ls' already exists"), aName);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* create a progress object */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <Progress> progress;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync progress.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = progress->init (mParent, static_cast <IHost *> (this),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (tr ("Creating host network interface")),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync FALSE /* aCancelable */);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync progress.queryInterfaceTo (aProgress);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* create a new uninitialized host interface object */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostNetworkInterface> iface;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync iface.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync iface.queryInterfaceTo (aHostNetworkInterface);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* create the networkInterfaceHelperClient() argument */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync std::auto_ptr <NetworkInterfaceHelperClientData>
441579693f771e49eb05f2bd20c316232155675bvboxsync d (new NetworkInterfaceHelperClientData());
441579693f771e49eb05f2bd20c316232155675bvboxsync AssertReturn (d.get(), E_OUTOFMEMORY);
441579693f771e49eb05f2bd20c316232155675bvboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsync d->msgCode = SVCHlpMsg::CreateHostNetworkInterface;
441579693f771e49eb05f2bd20c316232155675bvboxsync d->name = aName;
441579693f771e49eb05f2bd20c316232155675bvboxsync d->iface = iface;
441579693f771e49eb05f2bd20c316232155675bvboxsync
441579693f771e49eb05f2bd20c316232155675bvboxsync rc = mParent->startSVCHelperClient (
441579693f771e49eb05f2bd20c316232155675bvboxsync IsUACEnabled() == TRUE /* aPrivileged */,
441579693f771e49eb05f2bd20c316232155675bvboxsync networkInterfaceHelperClient,
441579693f771e49eb05f2bd20c316232155675bvboxsync static_cast <void *> (d.get()),
441579693f771e49eb05f2bd20c316232155675bvboxsync progress);
441579693f771e49eb05f2bd20c316232155675bvboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (SUCCEEDED (rc))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* d is now owned by networkInterfaceHelperClient(), so release it */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync d.release();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHost::RemoveHostNetworkInterface (INPTR GUIDPARAM aId,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync IHostNetworkInterface **aHostNetworkInterface,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync IProgress **aProgress)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aHostNetworkInterface)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
441579693f771e49eb05f2bd20c316232155675bvboxsync if (!aProgress)
441579693f771e49eb05f2bd20c316232155675bvboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync HRESULT rc = S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* first check whether an interface with the given name already exists */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComPtr <IHostNetworkInterfaceCollection> coll;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = COMGETTER(NetworkInterfaces) (coll.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComPtr <IHostNetworkInterface> iface;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (FAILED (coll->FindById (aId, iface.asOutParam())))
441579693f771e49eb05f2bd20c316232155675bvboxsync return setError (E_FAIL,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("Host network interface with UUID {%Vuuid} does not exist"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Guid (aId).raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* return the object to be removed to the caller */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync iface.queryInterfaceTo (aHostNetworkInterface);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* create a progress object */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <Progress> progress;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync progress.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = progress->init (mParent, static_cast <IHost *> (this),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (tr ("Removing host network interface")),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync FALSE /* aCancelable */);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync progress.queryInterfaceTo (aProgress);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* create the networkInterfaceHelperClient() argument */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync std::auto_ptr <NetworkInterfaceHelperClientData>
6ef855ecf2121f708685307839f1262e0db1a024vboxsync d (new NetworkInterfaceHelperClientData());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertReturn (d.get(), E_OUTOFMEMORY);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync d->msgCode = SVCHlpMsg::RemoveHostNetworkInterface;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync d->guid = aId;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = mParent->startSVCHelperClient (
6ef855ecf2121f708685307839f1262e0db1a024vboxsync IsUACEnabled() == TRUE /* aPrivileged */,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync networkInterfaceHelperClient,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync static_cast <void *> (d.get()),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync progress);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (SUCCEEDED (rc))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* d is now owned by networkInterfaceHelperClient(), so release it */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync d.release();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* RT_OS_WINDOWS */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::CreateUSBDeviceFilter (INPTR BSTR aName, IHostUSBDeviceFilter **aFilter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_WITH_USB
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aFilter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aName || *aName == 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_INVALIDARG;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDeviceFilter> filter;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HRESULT rc = filter->init (this, aName);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertComRCRet (rc, rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = filter.queryInterfaceTo (aFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertComRCReturn (rc, rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Note: The GUI depends on this method returning E_NOTIMPL with no
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * extended error info to indicate that USB is simply not available
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * (w/o treting it as a failure), for example, as in OSE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_NOTIMPL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::InsertUSBDeviceFilter (ULONG aPosition, IHostUSBDeviceFilter *aFilter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_WITH_USB
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aFilter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_INVALIDARG;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock alock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync MultiResult rc = checkUSBProxyService();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDeviceFilter> filter = getDependentChild (aFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!filter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("The given USB device filter is not created within "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "this VirtualBox instance"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (filter->mInList)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("The given USB device filter is already in the list"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* iterate to the position... */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceFilterList::iterator it = mUSBDeviceFilters.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync std::advance (it, aPosition);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* ...and insert */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBDeviceFilters.insert (it, filter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter->mInList = true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* notify the proxy (only when the filter is active) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (mUSBProxyService->isActive() && filter->data().mActive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (filter->id() == NULL, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifndef VBOX_WITH_USBFILTER
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter->id() =
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->insertFilter (ComPtr <IUSBDeviceFilter> (aFilter));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter->id() = mUSBProxyService->insertFilter (&filter->data().mUSBFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* save the global settings */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync alock.unlock();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc = mParent->saveSettings();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Note: The GUI depends on this method returning E_NOTIMPL with no
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * extended error info to indicate that USB is simply not available
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * (w/o treting it as a failure), for example, as in OSE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_NOTIMPL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncSTDMETHODIMP Host::RemoveUSBDeviceFilter (ULONG aPosition, IHostUSBDeviceFilter **aFilter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef VBOX_WITH_USB
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aFilter)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_POINTER;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock alock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync MultiResult rc = checkUSBProxyService();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCReturnRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!mUSBDeviceFilters.size())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("The USB device filter list is empty"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (aPosition >= mUSBDeviceFilters.size())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("Invalid position: %lu (must be in range [0, %lu])"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync aPosition, mUSBDeviceFilters.size() - 1);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDeviceFilter> filter;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* iterate to the position... */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceFilterList::iterator it = mUSBDeviceFilters.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync std::advance (it, aPosition);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* ...get an element from there... */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter = *it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* ...and remove */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter->mInList = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBDeviceFilters.erase (it);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.queryInterfaceTo (aFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* notify the proxy (only when the filter is active) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (mUSBProxyService->isActive() && filter->data().mActive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (filter->id() != NULL, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->removeFilter (filter->id());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter->id() = NULL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* save the global settings */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync alock.unlock();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc = mParent->saveSettings();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Note: The GUI depends on this method returning E_NOTIMPL with no
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * extended error info to indicate that USB is simply not available
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * (w/o treting it as a failure), for example, as in OSE */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return E_NOTIMPL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// public methods only for internal purposes
6ef855ecf2121f708685307839f1262e0db1a024vboxsync////////////////////////////////////////////////////////////////////////////////
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called by setter methods of all USB device filters.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::onUSBDeviceFilterChange (HostUSBDeviceFilter *aFilter,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync BOOL aActiveChanged /* = FALSE */)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock alock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (aFilter->mInList)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (aActiveChanged)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // insert/remove the filter from the proxy
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (aFilter->data().mActive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (aFilter->id() == NULL, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifndef VBOX_WITH_USBFILTER
6ef855ecf2121f708685307839f1262e0db1a024vboxsync aFilter->id() =
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->insertFilter (ComPtr <IUSBDeviceFilter> (aFilter));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync aFilter->id() = mUSBProxyService->insertFilter (&aFilter->data().mUSBFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (aFilter->id() != NULL, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->removeFilter (aFilter->id());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync aFilter->id() = NULL;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (aFilter->data().mActive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // update the filter in the proxy
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (aFilter->id() != NULL, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->removeFilter (aFilter->id());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifndef VBOX_WITH_USBFILTER
6ef855ecf2121f708685307839f1262e0db1a024vboxsync aFilter->id() =
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->insertFilter (ComPtr <IUSBDeviceFilter> (aFilter));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync aFilter->id() = mUSBProxyService->insertFilter (&aFilter->data().mUSBFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // save the global settings... yeah, on every single filter property change
6ef855ecf2121f708685307839f1262e0db1a024vboxsync alock.unlock();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return mParent->saveSettings();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::loadSettings (const settings::Key &aGlobal)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync using namespace settings;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertReturn (!aGlobal.isNull(), E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HRESULT rc = S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Key::List filters = aGlobal.key ("USBDeviceFilters").keys ("DeviceFilter");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (Key::List::const_iterator it = filters.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync it != filters.end(); ++ it)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr name = (*it).stringValue ("name");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync bool active = (*it).value <bool> ("active");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr vendorId = (*it).stringValue ("vendorId");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr productId = (*it).stringValue ("productId");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr revision = (*it).stringValue ("revision");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr manufacturer = (*it).stringValue ("manufacturer");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr product = (*it).stringValue ("product");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr serialNumber = (*it).stringValue ("serialNumber");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr port = (*it).stringValue ("port");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceFilterAction_T action;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync action = USBDeviceFilterAction_Ignore;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync const char *actionStr = (*it).stringValue ("action");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (strcmp (actionStr, "Ignore") == 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync action = USBDeviceFilterAction_Ignore;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (strcmp (actionStr, "Hold") == 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync action = USBDeviceFilterAction_Hold;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertMsgFailed (("Invalid action: '%s'\n", actionStr));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDeviceFilter> filterObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filterObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = filterObj->init (this,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync name, active, vendorId, productId, revision,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync manufacturer, product, serialNumber, port,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync action);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* error info is set by init() when appropriate */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CheckComRCBreakRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBDeviceFilters.push_back (filterObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filterObj->mInList = true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* notify the proxy (only when the filter is active) */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (filterObj->data().mActive)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HostUSBDeviceFilter *flt = filterObj; /* resolve ambiguity */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifndef VBOX_WITH_USBFILTER
6ef855ecf2121f708685307839f1262e0db1a024vboxsync flt->id() =
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->insertFilter (ComPtr <IUSBDeviceFilter> (flt));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync flt->id() = mUSBProxyService->insertFilter (&filterObj->data().mUSBFilter);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::saveSettings (settings::Key &aGlobal)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync using namespace settings;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (!aGlobal.isNull(), E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* first, delete the entry */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Key filters = aGlobal.findKey ("USBDeviceFilters");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!filters.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filters.zap();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* then, recreate it */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filters = aGlobal.createKey ("USBDeviceFilters");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (it != mUSBDeviceFilters.end())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock filterLock (*it);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync const HostUSBDeviceFilter::Data &data = (*it)->data();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Key filter = filters.appendKey ("DeviceFilter");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("name", data.mName);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <bool> ("active", !!data.mActive);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifndef VBOX_WITH_USBFILTER
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* all are optional */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mVendorId.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("vendorId", data.mVendorId.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mProductId.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("productId", data.mProductId.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mRevision.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("revision", data.mRevision.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mManufacturer.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("manufacturer", data.mManufacturer.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mProduct.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("product", data.mProduct.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mSerialNumber.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("serialNumber", data.mSerialNumber.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mPort.string())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("port", data.mPort.string());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* action is mandatory */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mAction == USBDeviceFilterAction_Ignore)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setStringValue ("action", "Ignore");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (data.mAction == USBDeviceFilterAction_Hold)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setStringValue ("action", "Hold");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertMsgFailed (("Invalid action: %d\n", data.mAction));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else /* VBOX_WITH_USBFILTER */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* all are optional */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr str;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (VendorId) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("vendorId", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (ProductId) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("productId", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (Revision) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("revision", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (Manufacturer) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("manufacturer", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (Product) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("product", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (SerialNumber) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("serialNumber", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (Port) (str.asOutParam());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!str.isNull())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setValue <Bstr> ("port", str);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* action is mandatory */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ULONG action = USBDeviceFilterAction_Null;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync (*it)->COMGETTER (Action) (&action);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (action == USBDeviceFilterAction_Ignore)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setStringValue ("action", "Ignore");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else if (action == USBDeviceFilterAction_Hold)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync filter.setStringValue ("action", "Hold");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertMsgFailed (("Invalid action: %d\n", action));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif /* VBOX_WITH_USBFILTER */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ++ it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Requests the USB proxy service to capture the given host USB device.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * When the request is completed,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * IInternalSessionControl::onUSBDeviceAttach() will be called on the given
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * machine object.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called by Console from the VM process (throug IInternalMachineControl).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Must return extended error info in case of errors.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::captureUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (aMachine, E_INVALIDARG);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Guid id (aId);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDevice> device;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceList::iterator it = mUSBDevices.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (!device && it != mUSBDevices.end())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((*it)->id() == id)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device = (*it);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ++ it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!device)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device with UUID {%Vuuid} is not currently attached to the host"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync id.raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock devLock (device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->isStatePending())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device '%s' with UUID {%Vuuid} is busy (waiting for a pending "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "state change). Please try later"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->name().raw(), id.raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->state() == USBDeviceState_NotSupported)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device '%s' with UUID {%Vuuid} cannot be accessed by guest "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "computers"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->name().raw(), id.raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->state() == USBDeviceState_Unavailable)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device '%s' with UUID {%Vuuid} is being exclusively used by the "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "host computer"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->name().raw(), id.raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->state() == USBDeviceState_Captured)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Machine::name() requires a read lock */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoReaderLock machLock (device->machine());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device '%s' with UUID {%Vuuid} is already captured by the virtual "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "machine '%ls'"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->name().raw(), id.raw(),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->machine()->name().raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* try to capture the device */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->requestCapture (aMachine);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Notification from the VM process that it is going to detach (\a aDone = false)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * or that is has just detach (\a aDone = true) the given USB device.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * When \a aDone = false we only inform the USB Proxy about what the vm is
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * up to so it doesn't get confused and create a new USB host device object
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * (a Darwin issue).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * When \a aDone = true we replay all filters against the given USB device
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * excluding filters of the machine the device is currently marked as
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * captured by.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * When the \a aDone = true request is completed,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * IInternalSessionControl::onUSBDeviceDetach() will be called on the given
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * machine object.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called by Console from the VM process (throug IInternalMachineControl).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::detachUSBDevice (SessionMachine *aMachine, INPTR GUIDPARAM aId, BOOL aDone)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("aMachine=%p, aId={%Vuuid}\n", aMachine, Guid (aId).raw()));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDevice> device;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceList::iterator it = mUSBDevices.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (!device && it != mUSBDevices.end())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((*it)->id() == aId)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device = (*it);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ++ it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (!!device, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock devLock (device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d aDone=%RTbool\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->id().raw(), device->state(), device->isStatePending(),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->pendingState(), aDone));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HRESULT rc = S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aDone)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->isStatePending())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device '%s' with UUID {%Vuuid} is busy (waiting for a pending "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "state change). Please try later"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->name().raw(), device->id().raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->detachingDevice (device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->isStatePending())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* If an async detach operation is still pending (darwin), postpone
6ef855ecf2121f708685307839f1262e0db1a024vboxsync the setHeld() + the re-applying of filters until it is completed.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync We indicate this by moving to the '*Filters' state variant. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->pendingStateEx() == HostUSBDevice::kDetachingPendingAttach)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->setLogicalReconnect (HostUSBDevice::kDetachingPendingAttachFilters);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else if (device->pendingStateEx() == HostUSBDevice::kDetachingPendingDetach)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->setLogicalReconnect (HostUSBDevice::kDetachingPendingDetachFilters);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Assert (device->pendingStateEx() == HostUSBDevice::kNothingPending);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = setError (E_INVALIDARG,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tr ("USB device '%s' with UUID {%Vuuid} is busy (waiting for a pending "
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "state change). Please try later"),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->name().raw(), device->id().raw());
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertRet (device->machine() == aMachine, E_FAIL);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* re-apply filters on the device before giving it back to the host */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->setHeld();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync rc = applyAllUSBFilters (device, aMachine);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComAssertComRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return rc;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Asks the USB proxy service to capture all currently available USB devices
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * that match filters of the given machine.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * When the request is completed,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * IInternalSessionControl::onUSBDeviceDetach() will be called on the given
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * machine object per every captured USB device.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called by Console from the VM process (through IInternalMachineControl)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * upon VM startup.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Locks this object for reading (@todo for writing now, until switched
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * to the new locking scheme).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::autoCaptureUSBDevices (SessionMachine *aMachine)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogFlowThisFunc (("aMachine=%p\n", aMachine));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (USBDeviceList::iterator it = mUSBDevices.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync it != mUSBDevices.end();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ++ it)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDevice> device = *it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock devLock (device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* skip pending devices */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->isStatePending())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync continue;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->state() == USBDeviceState_Busy ||
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->state() == USBDeviceState_Available ||
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->state() == USBDeviceState_Held)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync applyMachineUSBFilters (aMachine, device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Replays all filters against all USB devices currently marked as captured
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * by the given machine (excluding this machine's filters).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Called by Console from the VM process (throug IInternalMachineControl)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * upon normal VM termination or by SessionMachine::uninit() upon abnormal
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * VM termination (from under the Machine/SessionMachine lock).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @note Locks this object for reading (@todo for writing now, until switched
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * to the new locking scheme).
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncHRESULT Host::detachAllUSBDevices (SessionMachine *aMachine, BOOL aDone)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock lock (this);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync CHECK_READY();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync USBDeviceList::iterator it = mUSBDevices.begin();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while (it != mUSBDevices.end())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostUSBDevice> device = *it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AutoLock devLock (device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (device->machine() == aMachine)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!aDone)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!device->isStatePending())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mUSBProxyService->detachingDevice (device);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!device->isStatePending())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Assert (device->state() == USBDeviceState_Captured);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* re-apply filters on the device before giving it back to the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * host */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->setHeld();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync HRESULT rc = applyAllUSBFilters (device, aMachine);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync AssertComRC (rc);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else if (device->pendingStateEx() == HostUSBDevice::kNothingPending)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync device->cancelPendingState();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ++ it;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return S_OK;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// private methods
6ef855ecf2121f708685307839f1262e0db1a024vboxsync////////////////////////////////////////////////////////////////////////////////
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# ifdef VBOX_USE_LIBHAL
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Helper function to query the hal subsystem for information about DVD drives attached to the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * system.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns true if information was successfully obtained, false otherwise
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @retval list drives found will be attached to this list
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncbool Host::getDVDInfoFromHal(std::list <ComObjPtr <HostDVDDrive> > &list)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6182bafa91061adf250994da3e1cf8b7e91751f0vboxsync bool halSuccess = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DBusError dbusError;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!gLibHalCheckPresence())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorInit (&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (dbusConnection != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LibHalContext *halContext = gLibHalCtxNew();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (halContext != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (gLibHalCtxInit(halContext, &dbusError))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int numDevices;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char **halDevices = gLibHalFindDeviceStringMatch(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "storage.drive_type", "cdrom",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync &numDevices, &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (halDevices != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Hal is installed and working, so if no devices are reported, assume
6ef855ecf2121f708685307839f1262e0db1a024vboxsync that there are none. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halSuccess = true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (int i = 0; i < numDevices; i++)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *devNode = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "block.device", &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_SOLARIS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* The CD/DVD ioctls work only for raw device nodes. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *tmp = getfullrawname(devNode);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(devNode);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync devNode = tmp;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (devNode != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// if (validateDevice(devNode, true))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Utf8Str description;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *vendor, *product;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We do not check the error here, as this field may
6ef855ecf2121f708685307839f1262e0db1a024vboxsync not even exist. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vendor = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "info.vendor", 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync product = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "info.product", &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((product != 0 && product[0] != 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((vendor != 0) && (vendor[0] != 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync description = Utf8StrFmt ("%s %s",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vendor, product);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync description = product;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr (devNode),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (halDevices[i]),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (description));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (product == 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostDVDDriveObj->init (Bstr (devNode),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (halDevices[i]));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostDVDDriveObj);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (vendor != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(vendor);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (product != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(product);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifndef RT_OS_SOLARIS
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(devNode);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync free(devNode);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#endif
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeStringArray(halDevices);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalCtxFree(halContext);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusConnectionUnref(dbusConnection);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return halSuccess;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Helper function to query the hal subsystem for information about floppy drives attached to the
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * system.
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @returns true if information was successfully obtained, false otherwise
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * @retval list drives found will be attached to this list
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncbool Host::getFloppyInfoFromHal(std::list <ComObjPtr <HostFloppyDrive> > &list)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync bool halSuccess = false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DBusError dbusError;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!gLibHalCheckPresence())
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return false;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorInit (&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (dbusConnection != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LibHalContext *halContext = gLibHalCtxNew();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (halContext != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (gLibHalCtxInit(halContext, &dbusError))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync int numDevices;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char **halDevices = gLibHalFindDeviceStringMatch(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync "storage.drive_type", "floppy",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync &numDevices, &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (halDevices != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* Hal is installed and working, so if no devices are reported, assume
6ef855ecf2121f708685307839f1262e0db1a024vboxsync that there are none. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halSuccess = true;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync for (int i = 0; i < numDevices; i++)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *driveType = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "storage.drive_type", 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (driveType != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (strcmp(driveType, "floppy") != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(driveType);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync continue;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(driveType);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* An error occurred. The attribute "storage.drive_type"
6ef855ecf2121f708685307839f1262e0db1a024vboxsync probably didn't exist. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync continue;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *devNode = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "block.device", &dbusError);
230bd8589bba39933ac5ec21482d6186d675e604vboxsync if (devNode != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// if (validateDevice(devNode, false))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Utf8Str description;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *vendor, *product;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync /* We do not check the error here, as this field may
6ef855ecf2121f708685307839f1262e0db1a024vboxsync not even exist. */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vendor = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "info.vendor", 0);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync product = gLibHalDeviceGetPropertyString(halContext,
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], "info.product", &dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((product != 0) && (product[0] != 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if ((vendor != 0) && (vendor[0] != 0))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync description = Utf8StrFmt ("%s %s",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync vendor, product);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync description = product;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostFloppyDrive> hostFloppyDrive;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDrive.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDrive->init (Bstr (devNode),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (halDevices[i]),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (description));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostFloppyDrive);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (product == 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync ComObjPtr <HostFloppyDrive> hostFloppyDrive;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDrive.createObject();
6ef855ecf2121f708685307839f1262e0db1a024vboxsync hostFloppyDrive->init (Bstr (devNode),
6ef855ecf2121f708685307839f1262e0db1a024vboxsync Bstr (halDevices[i]));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync list.push_back (hostFloppyDrive);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (vendor != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(vendor);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (product != 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(product);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync// }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeString(devNode);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
6ef855ecf2121f708685307839f1262e0db1a024vboxsync halDevices[i], dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalFreeStringArray(halDevices);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gLibHalCtxFree(halContext);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusConnectionUnref(dbusConnection);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync else
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync gDBusErrorFree(&dbusError);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync return halSuccess;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync}
6ef855ecf2121f708685307839f1262e0db1a024vboxsync# endif /* VBOX_USE_HAL defined */
6ef855ecf2121f708685307839f1262e0db1a024vboxsync
6ef855ecf2121f708685307839f1262e0db1a024vboxsync/**
6ef855ecf2121f708685307839f1262e0db1a024vboxsync * Helper function to parse the given mount file and add found entries
6ef855ecf2121f708685307839f1262e0db1a024vboxsync */
6ef855ecf2121f708685307839f1262e0db1a024vboxsyncvoid Host::parseMountTable(char *mountTable, std::list <ComObjPtr <HostDVDDrive> > &list)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync{
6ef855ecf2121f708685307839f1262e0db1a024vboxsync#ifdef RT_OS_LINUX
6ef855ecf2121f708685307839f1262e0db1a024vboxsync FILE *mtab = setmntent(mountTable, "r");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (mtab)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync struct mntent *mntent;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *mnt_type;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *mnt_dev;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync char *tmp;
6ef855ecf2121f708685307839f1262e0db1a024vboxsync while ((mntent = getmntent(mtab)))
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync strcpy(mnt_type, mntent->mnt_type);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync strcpy(mnt_dev, mntent->mnt_fsname);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync // supermount fs case
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (strcmp(mnt_type, "supermount") == 0)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tmp = strstr(mntent->mnt_opts, "fs=");
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (tmp)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync free(mnt_type);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync mnt_type = strdup(tmp + strlen("fs="));
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (mnt_type)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync {
6ef855ecf2121f708685307839f1262e0db1a024vboxsync tmp = strchr(mnt_type, ',');
6ef855ecf2121f708685307839f1262e0db1a024vboxsync if (tmp)
6ef855ecf2121f708685307839f1262e0db1a024vboxsync *tmp = '\0';
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync }
230bd8589bba39933ac5ec21482d6186d675e604vboxsync }
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync tmp = strstr(mntent->mnt_opts, "dev=");
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync if (tmp)
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync {
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync free(mnt_dev);
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync mnt_dev = strdup(tmp + strlen("dev="));
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync if (mnt_dev)
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync {
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync tmp = strchr(mnt_dev, ',');
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync if (tmp)
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync *tmp = '\0';
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync }
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync }
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync }
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync // use strstr here to cover things fs types like "udf,iso9660"
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync if (strstr(mnt_type, "iso9660") == 0)
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync {
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync /** @todo check whether we've already got the drive in our list! */
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync if (validateDevice(mnt_dev, true))
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync {
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync ComObjPtr <HostDVDDrive> hostDVDDriveObj;
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync hostDVDDriveObj.createObject();
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync hostDVDDriveObj->init (Bstr (mnt_dev));
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync list.push_back (hostDVDDriveObj);
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync }
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync }
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync free(mnt_dev);
152e1e373e38dea3d8cfe8bc06c7d3050cb130e2vboxsync free(mnt_type);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
6ef855ecf2121f708685307839f1262e0db1a024vboxsync endmntent(mtab);
6ef855ecf2121f708685307839f1262e0db1a024vboxsync }
#else // RT_OS_SOLARIS
FILE *mntFile = fopen(mountTable, "r");
if (mntFile)
{
struct mnttab mntTab;
while (getmntent(mntFile, &mntTab) == 0)
{
char *mountName = strdup(mntTab.mnt_special);
char *mountPoint = strdup(mntTab.mnt_mountp);
char *mountFSType = strdup(mntTab.mnt_fstype);
// skip devices we are not interested in
if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
(*mountFSType && (strcmp(mountFSType, "devfs") != 0 && // skip devfs (i.e. /devices)
strcmp(mountFSType, "dev") != 0 && // skip dev (i.e. /dev)
strcmp(mountFSType, "lofs") != 0)) && // skip loop-back file-system (lofs)
(*mountPoint && strcmp(mountPoint, "/") != 0)) // skip point '/' (Can CD/DVD be mounted at '/' ???)
{
char *rawDevName = getfullrawname(mountName);
if (validateDevice(rawDevName, true))
{
ComObjPtr <HostDVDDrive> hostDVDDriveObj;
hostDVDDriveObj.createObject();
hostDVDDriveObj->init (Bstr (rawDevName));
list.push_back (hostDVDDriveObj);
}
free(rawDevName);
}
free(mountName);
free(mountPoint);
free(mountFSType);
}
fclose(mntFile);
}
#endif
}
/**
* Helper function to check whether the given device node is a valid drive
*/
bool Host::validateDevice(const char *deviceNode, bool isCDROM)
{
struct stat statInfo;
bool retValue = false;
// sanity check
if (!deviceNode)
{
return false;
}
// first a simple stat() call
if (stat(deviceNode, &statInfo) < 0)
{
return false;
} else
{
if (isCDROM)
{
if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
{
int fileHandle;
// now try to open the device
fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
if (fileHandle >= 0)
{
cdrom_subchnl cdChannelInfo;
cdChannelInfo.cdsc_format = CDROM_MSF;
// this call will finally reveal the whole truth
#ifdef RT_OS_LINUX
if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
(errno == EIO) || (errno == ENOENT) ||
(errno == EINVAL) || (errno == ENOMEDIUM))
#else
if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
(errno == EIO) || (errno == ENOENT) ||
(errno == EINVAL))
#endif
{
retValue = true;
}
close(fileHandle);
}
}
} else
{
// floppy case
if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
{
/// @todo do some more testing, maybe a nice IOCTL!
retValue = true;
}
}
}
return retValue;
}
#endif // RT_OS_LINUX || RT_OS_SOLARIS
/**
* Applies all (golbal and VM) filters to the given USB device. The device
* must be either a newly attached device or a device released by a VM.
*
* This method will request the USB proxy service to release the device (give
* it back to the host) if none of the global or VM filters want to capture
* the device.
*
* @param aDevice USB device to apply filters to.
* @param aMachine Machine the device was released by or @c NULL.
*
* @note the method must be called from under this object's write lock and
* from the aDevice's write lock.
*/
HRESULT Host::applyAllUSBFilters (ComObjPtr <HostUSBDevice> &aDevice,
SessionMachine *aMachine /* = NULL */)
{
LogFlowThisFunc (("\n"));
/// @todo must check for read lock, it's enough here
AssertReturn (isLockedOnCurrentThread(), E_FAIL);
AssertReturn (aDevice->isLockedOnCurrentThread(), E_FAIL);
AssertReturn (aDevice->state() != USBDeviceState_Captured, E_FAIL);
AssertReturn (aDevice->isStatePending() == false, E_FAIL);
/* ignore unsupported devices */
if (aDevice->state() == USBDeviceState_NotSupported)
return S_OK;
/* ignore unavailable devices as well */
if (aDevice->state() == USBDeviceState_Unavailable)
return S_OK;
VirtualBox::SessionMachineVector machines;
mParent->getOpenedMachines (machines);
/// @todo it may be better to take a copy of filters to iterate and leave
/// the host lock before calling HostUSBDevice:requestCapture() (which
/// calls the VM process).
/* apply global filters */
USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
for (; it != mUSBDeviceFilters.end(); ++ it)
{
AutoLock filterLock (*it);
const HostUSBDeviceFilter::Data &data = (*it)->data();
if (aDevice->isMatch (data))
{
#ifndef VBOX_WITH_USBFILTER
USBDeviceFilterAction_T action = data.mAction;
#else
ULONG action = USBDeviceFilterAction_Null;
(*it)->COMGETTER (Action) (&action);
#endif
if (action == USBDeviceFilterAction_Ignore)
{
/* request to give the device back to the host*/
aDevice->requestRelease();
/* nothing to do any more */
return S_OK;
}
if (action == USBDeviceFilterAction_Hold)
break;
}
}
/* apply machine filters */
size_t i = 0;
for (; i < machines.size(); ++ i)
{
/* skip the machine the device was just detached from */
if (aMachine && machines [i] == aMachine)
continue;
if (applyMachineUSBFilters (machines [i], aDevice))
break;
}
if (i == machines.size())
{
/* no matched machine filters, check what to do */
if (it == mUSBDeviceFilters.end())
{
/* no any filter matched at all */
/* request to give the device back to the host */
aDevice->requestRelease();
}
else
{
/* there was a global Hold filter */
aDevice->requestHold();
}
}
return S_OK;
}
/**
* Runs through filters of the given machine and asks the USB proxy service
* to capture the given USB device when there is a match.
*
* @param aMachine Machine whose filters are to be run.
* @param aDevice USB device, a candidate for auto-capturing.
* @return @c true if there was a match and @c false otherwise.
*
* @note the method must be called from under this object's write lock and
* from the aDevice's write lock.
*
* @note Locks aMachine for reading.
*/
bool Host::applyMachineUSBFilters (SessionMachine *aMachine,
ComObjPtr <HostUSBDevice> &aDevice)
{
LogFlowThisFunc (("\n"));
AssertReturn (aMachine, false);
/// @todo must check for read lock, it's enough here
AssertReturn (isLockedOnCurrentThread(), false);
AssertReturn (aDevice->isLockedOnCurrentThread(), false);
AssertReturn (aDevice->state() != USBDeviceState_NotSupported, false);
AssertReturn (aDevice->state() != USBDeviceState_Unavailable, false);
AssertReturn (aDevice->isStatePending() == false, false);
ULONG maskedIfs;
bool hasMatch = aMachine->hasMatchingUSBFilter (aDevice, &maskedIfs);
if (hasMatch)
{
/* try to capture the device */
return aDevice->requestCapture (aMachine, maskedIfs);
}
return hasMatch;
}
/**
* Called by USB proxy service when a new device is physically attached
* to the host.
*
* @param aDevice Pointer to the device which has been attached.
*/
void Host::onUSBDeviceAttached (HostUSBDevice *aDevice)
{
LogFlowThisFunc (("aDevice=%p\n", aDevice));
AssertReturnVoid (aDevice);
AssertReturnVoid (isLockedOnCurrentThread());
AssertReturnVoid (aDevice->isLockedOnCurrentThread());
LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n",
aDevice->id().raw(), aDevice->state(), aDevice->isStatePending(),
aDevice->pendingState()));
Assert (aDevice->isStatePending() == false);
/* add to the collecion */
mUSBDevices.push_back (aDevice);
/* apply all filters */
ComObjPtr <HostUSBDevice> device (aDevice);
HRESULT rc = applyAllUSBFilters (device);
AssertComRC (rc);
}
/**
* Called by USB proxy service when the device is physically detached
* from the host.
*
* @param aDevice Pointer to the device which has been detached.
*/
void Host::onUSBDeviceDetached (HostUSBDevice *aDevice)
{
LogFlowThisFunc (("aDevice=%p\n", aDevice));
AssertReturnVoid (aDevice);
AssertReturnVoid (isLockedOnCurrentThread());
AssertReturnVoid (aDevice->isLockedOnCurrentThread());
LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n",
aDevice->id().raw(), aDevice->state(), aDevice->isStatePending(),
aDevice->pendingState()));
Guid id = aDevice->id();
ComObjPtr <HostUSBDevice> device;
Host::USBDeviceList::iterator it = mUSBDevices.begin();
while (it != mUSBDevices.end())
{
if ((*it)->id() == id)
{
device = (*it);
break;
}
++ it;
}
AssertReturnVoid (!!device);
/* remove from the collecion */
mUSBDevices.erase (it);
/* Detach the device from any machine currently using it,
reset all data and uninitialize the device object. */
device->onDetachedPhys();
}
/**
* Called by USB proxy service when the state of the device has changed
* either because of the state change request or because of some external
* interaction.
*
* @param aDevice The device in question.
*/
void Host::onUSBDeviceStateChanged (HostUSBDevice *aDevice)
{
LogFlowThisFunc (("aDevice=%p\n", aDevice));
AssertReturnVoid (aDevice);
AssertReturnVoid (isLockedOnCurrentThread());
AssertReturnVoid (aDevice->isLockedOnCurrentThread());
LogFlowThisFunc (("id={%Vuuid} state=%d isStatePending=%RTbool pendingState=%d\n",
aDevice->id().raw(), aDevice->state(), aDevice->isStatePending(),
aDevice->pendingState()));
ComObjPtr <HostUSBDevice> device (aDevice);
if (device->isStatePending())
{
/* it was a state change request */
if (device->pendingStateEx() == HostUSBDevice::kDetachingPendingAttachFilters)
{
/* The device has completed an asynchronous detach operation, subject
it to the filters and such if the current state permits this.
(handlePendingStateChange will disassociate itself from the machine.) */
ComObjPtr <SessionMachine> machine (device->machine());
device->handlePendingStateChange();
if (device->state() == USBDeviceState_Captured)
{
Log (("USB: running filters on async detached device\n"));
device->setHeld();
HRESULT rc = applyAllUSBFilters (device, machine);
AssertComRC (rc);
}
else
Log (("USB: async detached devices reappeared in stated %d instead of %d!\n",
device->state(), USBDeviceState_Captured));
}
else
device->handlePendingStateChange();
}
else if ( device->state() == USBDeviceState_Available
|| device->state() == USBDeviceState_Busy)
{
/* The device has gone from being unavailable (not subject to filters) to being
available / busy. This transition can be triggered by udevd or manual
permission changes on Linux. On all systems may be triggered by the host
ceasing to use the device - like unmounting an MSD in the Finder or invoking
the "Safely remove XXXX" stuff on Windows (perhaps). */
HRESULT rc = applyAllUSBFilters (device);
AssertComRC (rc);
}
else
{
/* some external state change */
/// @todo re-run all USB filters probably
AssertFailed();
}
}
/**
* 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.
*/
HRESULT Host::checkUSBProxyService()
{
#ifdef VBOX_WITH_USB
AutoLock lock (this);
CHECK_READY();
AssertReturn (mUSBProxyService, E_FAIL);
if (!mUSBProxyService->isActive())
{
/* disable the USB controller completely to avoid assertions if the
* USB proxy service could not start. */
if (mUSBProxyService->getLastError() == VERR_FILE_NOT_FOUND)
return setWarning (E_FAIL,
tr ("Could not load the Host USB Proxy Service (%Vrc). "
"The service might be not installed on the host computer"),
mUSBProxyService->getLastError());
if (mUSBProxyService->getLastError() == VINF_SUCCESS)
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 (%Vrc)"),
mUSBProxyService->getLastError());
}
return S_OK;
#else
return E_NOTIMPL;
#endif
}
#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.
*/
#define NETSHELL_LIBRARY _T("netshell.dll")
/**
* Use the IShellFolder API to rename the connection.
*/
static HRESULT rename_shellfolder (PCWSTR wGuid, PCWSTR wNewName)
{
/* 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
}
};
LPITEMIDLIST pidl = NULL;
IShellFolder *pShellFolder = NULL;
HRESULT hr;
/* Build the display name in the form "::{GUID}". */
if (wcslen (wGuid) >= MAX_PATH)
return E_INVALIDARG;
WCHAR szAdapterGuid[MAX_PATH + 2] = {0};
swprintf (szAdapterGuid, L"::%ls", wGuid);
/* Create an instance of the network connections folder. */
hr = CoCreateInstance (CLSID_NetworkConnections, NULL,
CLSCTX_INPROC_SERVER, IID_IShellFolder,
reinterpret_cast <LPVOID *> (&pShellFolder));
/* Parse the display name. */
if (SUCCEEDED (hr))
{
hr = pShellFolder->ParseDisplayName (NULL, NULL, szAdapterGuid, NULL,
&pidl, NULL);
}
if (SUCCEEDED (hr))
{
hr = pShellFolder->SetNameOf (NULL, pidl, wNewName, SHGDN_NORMAL,
&pidl);
}
CoTaskMemFree (pidl);
if (pShellFolder)
pShellFolder->Release();
return hr;
}
extern "C" HRESULT RenameConnection (PCWSTR GuidString, PCWSTR NewName)
{
typedef HRESULT (WINAPI *lpHrRenameConnection) (const GUID *, PCWSTR);
lpHrRenameConnection RenameConnectionFunc = NULL;
HRESULT status;
/* First try the IShellFolder interface, which was unimplemented
* for the network connections folder before XP. */
status = rename_shellfolder (GuidString, NewName);
if (status == E_NOTIMPL)
{
/** @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. */
CLSID clsid;
HINSTANCE hNetShell;
status = CLSIDFromString ((LPOLESTR) GuidString, &clsid);
if (FAILED(status))
return E_FAIL;
hNetShell = LoadLibrary (NETSHELL_LIBRARY);
if (hNetShell == NULL)
return E_FAIL;
RenameConnectionFunc =
(lpHrRenameConnection) GetProcAddress (hNetShell,
"HrRenameConnection");
if (RenameConnectionFunc == NULL)
{
FreeLibrary (hNetShell);
return E_FAIL;
}
status = RenameConnectionFunc (&clsid, NewName);
FreeLibrary (hNetShell);
}
if (FAILED (status))
return status;
return S_OK;
}
#define DRIVERHWID _T("vboxtap")
#define SetErrBreak(strAndArgs) \
if (1) { \
aErrMsg = Utf8StrFmt strAndArgs; vrc = VERR_GENERAL_FAILURE; break; \
} else do {} while (0)
/* static */
int Host::createNetworkInterface (SVCHlpClient *aClient,
const Utf8Str &aName,
Guid &aGUID, Utf8Str &aErrMsg)
{
LogFlowFuncEnter();
LogFlowFunc (("Network connection name = '%s'\n", aName.raw()));
AssertReturn (aClient, VERR_INVALID_POINTER);
AssertReturn (!aName.isNull(), VERR_INVALID_PARAMETER);
int vrc = VINF_SUCCESS;
HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA DeviceInfoData;
DWORD ret = 0;
BOOL found = FALSE;
BOOL registered = FALSE;
BOOL destroyList = FALSE;
TCHAR pCfgGuidString [50];
do
{
BOOL ok;
GUID netGuid;
SP_DRVINFO_DATA DriverInfoData;
SP_DEVINSTALL_PARAMS DeviceInstallParams;
TCHAR className [MAX_PATH];
DWORD index = 0;
PSP_DRVINFO_DETAIL_DATA pDriverInfoDetail;
/* for our purposes, 2k buffer is more
* than enough to obtain the hardware ID
* of the VBoxTAP driver. */
DWORD detailBuf [2048];
HKEY hkey = NULL;
DWORD cbSize;
DWORD dwValueType;
/* initialize the structure size */
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
/* copy the net class GUID */
memcpy(&netGuid, &GUID_DEVCLASS_NET, sizeof(GUID_DEVCLASS_NET));
/* create an empty device info set associated with the net class GUID */
hDeviceInfo = SetupDiCreateDeviceInfoList (&netGuid, NULL);
if (hDeviceInfo == INVALID_HANDLE_VALUE)
SetErrBreak (("SetupDiCreateDeviceInfoList failed (0x%08X)",
GetLastError()));
/* get the class name from GUID */
ok = SetupDiClassNameFromGuid (&netGuid, className, MAX_PATH, NULL);
if (!ok)
SetErrBreak (("SetupDiClassNameFromGuid failed (0x%08X)",
GetLastError()));
/* create a device info element and add the new device instance
* key to registry */
ok = SetupDiCreateDeviceInfo (hDeviceInfo, className, &netGuid, NULL, NULL,
DICD_GENERATE_ID, &DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiCreateDeviceInfo failed (0x%08X)",
GetLastError()));
/* select the newly created device info to be the currently
selected member */
ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
GetLastError()));
/* build a list of class drivers */
ok = SetupDiBuildDriverInfoList (hDeviceInfo, &DeviceInfoData,
SPDIT_CLASSDRIVER);
if (!ok)
SetErrBreak (("SetupDiBuildDriverInfoList failed (0x%08X)",
GetLastError()));
destroyList = TRUE;
/* enumerate the driver info list */
while (TRUE)
{
BOOL ret;
ret = SetupDiEnumDriverInfo (hDeviceInfo, &DeviceInfoData,
SPDIT_CLASSDRIVER, index, &DriverInfoData);
/* 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;
}
}
pDriverInfoDetail = (PSP_DRVINFO_DETAIL_DATA) detailBuf;
pDriverInfoDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
/* if we successfully find the hardware ID and it turns out to
* be the one for the loopback driver, then we are done. */
if (SetupDiGetDriverInfoDetail (hDeviceInfo,
&DeviceInfoData,
&DriverInfoData,
pDriverInfoDetail,
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;
while (t && *t && t < (TCHAR *) &detailBuf [sizeof(detailBuf) / sizeof (detailBuf[0])])
{
if (!_tcsicmp(t, DRIVERHWID))
break;
t += _tcslen(t) + 1;
}
if (t && *t && t < (TCHAR *) &detailBuf [sizeof(detailBuf) / sizeof (detailBuf[0])])
{
found = TRUE;
break;
}
}
index ++;
}
if (!found)
SetErrBreak ((tr ("Could not find Host Interface Networking driver! "
"Please reinstall")));
/* set the loopback driver to be the currently selected */
ok = SetupDiSetSelectedDriver (hDeviceInfo, &DeviceInfoData,
&DriverInfoData);
if (!ok)
SetErrBreak (("SetupDiSetSelectedDriver failed (0x%08X)",
GetLastError()));
/* register the phantom device to prepare for install */
ok = SetupDiCallClassInstaller (DIF_REGISTERDEVICE, hDeviceInfo,
&DeviceInfoData);
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 */
ok = SetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hDeviceInfo,
&DeviceInfoData);
if (!ok)
{
if (GetLastError() != ERROR_DI_DO_DEFAULT)
SetErrBreak (("SetupDiCallClassInstaller (DIF_ALLOW_INSTALL) failed (0x%08X)",
GetLastError()));
/* that's fine */
}
/* install the files first */
ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hDeviceInfo,
&DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES) failed (0x%08X)",
GetLastError()));
/* get the device install parameters and disable filecopy */
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
ok = SetupDiGetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
&DeviceInstallParams);
if (ok)
{
DeviceInstallParams.Flags |= DI_NOFILECOPY;
ok = SetupDiSetDeviceInstallParams (hDeviceInfo, &DeviceInfoData,
&DeviceInstallParams);
if (!ok)
SetErrBreak (("SetupDiSetDeviceInstallParams failed (0x%08X)",
GetLastError()));
}
/*
* Register any device-specific co-installers for this device,
*/
ok = SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS,
hDeviceInfo,
&DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS) failed (0x%08X)",
GetLastError()));
/*
* install any installer-specified interfaces.
* and then do the real install
*/
ok = SetupDiCallClassInstaller (DIF_INSTALLINTERFACES,
hDeviceInfo,
&DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLINTERFACES) failed (0x%08X)",
GetLastError()));
ok = SetupDiCallClassInstaller (DIF_INSTALLDEVICE,
hDeviceInfo,
&DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_INSTALLDEVICE) failed (0x%08X)",
GetLastError()));
/* Figure out NetCfgInstanceId */
hkey = SetupDiOpenDevRegKey (hDeviceInfo,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_READ);
if (hkey == INVALID_HANDLE_VALUE)
SetErrBreak (("SetupDiOpenDevRegKey failed (0x%08X)",
GetLastError()));
cbSize = sizeof (pCfgGuidString);
DWORD ret;
ret = RegQueryValueEx (hkey, _T ("NetCfgInstanceId"), NULL,
&dwValueType, (LPBYTE) pCfgGuidString, &cbSize);
RegCloseKey (hkey);
ret = RenameConnection (pCfgGuidString, Bstr (aName));
if (FAILED (ret))
SetErrBreak (("Failed to set interface name (ret=0x%08X, "
"pCfgGuidString='%ls', cbSize=%d)",
ret, pCfgGuidString, cbSize));
}
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)
SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
found = SetupDiDeleteDeviceInfo (hDeviceInfo, &DeviceInfoData);
/* destroy the driver info list */
if (destroyList)
SetupDiDestroyDriverInfoList (hDeviceInfo, &DeviceInfoData,
SPDIT_CLASSDRIVER);
/* clean up the device info set */
SetupDiDestroyDeviceInfoList (hDeviceInfo);
}
/* return the network connection GUID on success */
if (VBOX_SUCCESS (vrc))
{
/* remove the curly bracket at the end */
pCfgGuidString [_tcslen (pCfgGuidString) - 1] = '\0';
LogFlowFunc (("Network connection GUID string = {%ls}\n", pCfgGuidString + 1));
aGUID = Guid (Utf8Str (pCfgGuidString + 1));
LogFlowFunc (("Network connection GUID = {%Vuuid}\n", aGUID.raw()));
Assert (!aGUID.isEmpty());
}
LogFlowFunc (("vrc=%Vrc\n", vrc));
LogFlowFuncLeave();
return vrc;
}
/* static */
int Host::removeNetworkInterface (SVCHlpClient *aClient,
const Guid &aGUID,
Utf8Str &aErrMsg)
{
LogFlowFuncEnter();
LogFlowFunc (("Network connection GUID = {%Vuuid}\n", aGUID.raw()));
AssertReturn (aClient, VERR_INVALID_POINTER);
AssertReturn (!aGUID.isEmpty(), VERR_INVALID_PARAMETER);
int vrc = VINF_SUCCESS;
do
{
TCHAR lszPnPInstanceId [512] = {0};
/* We have to find the device instance ID through a registry search */
HKEY hkeyNetwork = 0;
HKEY hkeyConnection = 0;
do
{
char strRegLocation [256];
sprintf (strRegLocation,
"SYSTEM\\CurrentControlSet\\Control\\Network\\"
"{4D36E972-E325-11CE-BFC1-08002BE10318}\\{%s}",
aGUID.toString().raw());
LONG status;
status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, strRegLocation, 0,
KEY_READ, &hkeyNetwork);
if ((status != ERROR_SUCCESS) || !hkeyNetwork)
SetErrBreak ((
tr ("Host interface network is not found in registry (%s) [1]"),
strRegLocation));
status = RegOpenKeyExA (hkeyNetwork, "Connection", 0,
KEY_READ, &hkeyConnection);
if ((status != ERROR_SUCCESS) || !hkeyConnection)
SetErrBreak ((
tr ("Host interface network is not found in registry (%s) [2]"),
strRegLocation));
DWORD len = sizeof (lszPnPInstanceId);
DWORD dwKeyType;
status = RegQueryValueExW (hkeyConnection, L"PnPInstanceID", NULL,
&dwKeyType, (LPBYTE) lszPnPInstanceId, &len);
if ((status != ERROR_SUCCESS) || (dwKeyType != REG_SZ))
SetErrBreak ((
tr ("Host interface network is not found in registry (%s) [3]"),
strRegLocation));
}
while (0);
if (hkeyConnection)
RegCloseKey (hkeyConnection);
if (hkeyNetwork)
RegCloseKey (hkeyNetwork);
if (VBOX_FAILURE (vrc))
break;
/*
* Now we are going to enumerate all network devices and
* wait until we encounter the right device instance ID
*/
HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
do
{
BOOL ok;
DWORD ret = 0;
GUID netGuid;
SP_DEVINFO_DATA DeviceInfoData;
DWORD index = 0;
BOOL found = FALSE;
DWORD size = 0;
/* initialize the structure size */
DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
/* copy the net class GUID */
memcpy (&netGuid, &GUID_DEVCLASS_NET, sizeof (GUID_DEVCLASS_NET));
/* return a device info set contains all installed devices of the Net class */
hDeviceInfo = SetupDiGetClassDevs (&netGuid, NULL, NULL, DIGCF_PRESENT);
if (hDeviceInfo == INVALID_HANDLE_VALUE)
SetErrBreak (("SetupDiGetClassDevs failed (0x%08X)", GetLastError()));
/* enumerate the driver info list */
while (TRUE)
{
TCHAR *deviceHwid;
ok = SetupDiEnumDeviceInfo (hDeviceInfo, index, &DeviceInfoData);
if (!ok)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
break;
else
{
index++;
continue;
}
}
/* try to get the hardware ID registry property */
ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
&DeviceInfoData,
SPDRP_HARDWAREID,
NULL,
NULL,
0,
&size);
if (!ok)
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
index++;
continue;
}
deviceHwid = (TCHAR *) malloc (size);
ok = SetupDiGetDeviceRegistryProperty (hDeviceInfo,
&DeviceInfoData,
SPDRP_HARDWAREID,
NULL,
(PBYTE)deviceHwid,
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 && *t && t < &deviceHwid[size / sizeof(TCHAR)];
t += _tcslen (t) + 1)
{
if (!_tcsicmp (DRIVERHWID, t))
{
/* get the device instance ID */
TCHAR devID [MAX_DEVICE_ID_LEN];
if (CM_Get_Device_ID(DeviceInfoData.DevInst,
devID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS)
{
/* compare to what we determined before */
if (wcscmp(devID, lszPnPInstanceId) == 0)
{
found = TRUE;
break;
}
}
}
}
if (deviceHwid)
{
free (deviceHwid);
deviceHwid = NULL;
}
if (found)
break;
index++;
}
if (found == FALSE)
SetErrBreak ((tr ("Host Interface Network driver not found (0x%08X)"),
GetLastError()));
ok = SetupDiSetSelectedDevice (hDeviceInfo, &DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiSetSelectedDevice failed (0x%08X)",
GetLastError()));
ok = SetupDiCallClassInstaller (DIF_REMOVE, hDeviceInfo, &DeviceInfoData);
if (!ok)
SetErrBreak (("SetupDiCallClassInstaller (DIF_REMOVE) failed (0x%08X)",
GetLastError()));
}
while (0);
/* clean up the device info set */
if (hDeviceInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList (hDeviceInfo);
if (VBOX_FAILURE (vrc))
break;
}
while (0);
LogFlowFunc (("vrc=%Vrc\n", vrc));
LogFlowFuncLeave();
return vrc;
}
#undef SetErrBreak
/* static */
HRESULT Host::networkInterfaceHelperClient (SVCHlpClient *aClient,
Progress *aProgress,
void *aUser, int *aVrc)
{
LogFlowFuncEnter();
LogFlowFunc (("aClient={%p}, aProgress={%p}, aUser={%p}\n",
aClient, aProgress, aUser));
AssertReturn ((aClient == NULL && aProgress == NULL && aVrc == NULL) ||
(aClient != NULL && aProgress != NULL && aVrc != NULL),
E_POINTER);
AssertReturn (aUser, E_POINTER);
std::auto_ptr <NetworkInterfaceHelperClientData>
d (static_cast <NetworkInterfaceHelperClientData *> (aUser));
if (aClient == NULL)
{
/* "cleanup only" mode, just return (it will free aUser) */
return S_OK;
}
HRESULT rc = S_OK;
int vrc = VINF_SUCCESS;
switch (d->msgCode)
{
case SVCHlpMsg::CreateHostNetworkInterface:
{
LogFlowFunc (("CreateHostNetworkInterface:\n"));
LogFlowFunc (("Network connection name = '%ls'\n", d->name.raw()));
/* write message and parameters */
vrc = aClient->write (d->msgCode);
if (VBOX_FAILURE (vrc)) break;
vrc = aClient->write (Utf8Str (d->name));
if (VBOX_FAILURE (vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
SVCHlpMsg::Code reply = SVCHlpMsg::Null;
vrc = aClient->read (reply);
if (VBOX_FAILURE (vrc)) break;
switch (reply)
{
case SVCHlpMsg::CreateHostNetworkInterface_OK:
{
/* read the GUID */
Guid guid;
vrc = aClient->read (guid);
if (VBOX_FAILURE (vrc)) break;
LogFlowFunc (("Network connection GUID = {%Vuuid}\n", guid.raw()));
/* initialize the object returned to the caller by
* CreateHostNetworkInterface() */
rc = d->iface->init (d->name, guid);
endLoop = true;
break;
}
case SVCHlpMsg::Error:
{
/* read the error message */
Utf8Str errMsg;
vrc = aClient->read (errMsg);
if (VBOX_FAILURE (vrc)) break;
rc = setError (E_FAIL, errMsg);
endLoop = true;
break;
}
default:
{
endLoop = true;
ComAssertMsgFailedBreak ((
"Invalid message code %d (%08lX)\n",
reply, reply),
rc = E_FAIL);
}
}
}
break;
}
case SVCHlpMsg::RemoveHostNetworkInterface:
{
LogFlowFunc (("RemoveHostNetworkInterface:\n"));
LogFlowFunc (("Network connection GUID = {%Vuuid}\n", d->guid.raw()));
/* write message and parameters */
vrc = aClient->write (d->msgCode);
if (VBOX_FAILURE (vrc)) break;
vrc = aClient->write (d->guid);
if (VBOX_FAILURE (vrc)) break;
/* wait for a reply */
bool endLoop = false;
while (!endLoop)
{
SVCHlpMsg::Code reply = SVCHlpMsg::Null;
vrc = aClient->read (reply);
if (VBOX_FAILURE (vrc)) break;
switch (reply)
{
case SVCHlpMsg::OK:
{
/* no parameters */
rc = S_OK;
endLoop = true;
break;
}
case SVCHlpMsg::Error:
{
/* read the error message */
Utf8Str errMsg;
vrc = aClient->read (errMsg);
if (VBOX_FAILURE (vrc)) break;
rc = setError (E_FAIL, errMsg);
endLoop = true;
break;
}
default:
{
endLoop = true;
ComAssertMsgFailedBreak ((
"Invalid message code %d (%08lX)\n",
reply, reply),
rc = E_FAIL);
}
}
}
break;
}
default:
ComAssertMsgFailedBreak ((
"Invalid message code %d (%08lX)\n",
d->msgCode, d->msgCode),
rc = E_FAIL);
}
if (aVrc)
*aVrc = vrc;
LogFlowFunc (("rc=0x%08X, vrc=%Vrc\n", rc, vrc));
LogFlowFuncLeave();
return rc;
}
/* static */
int Host::networkInterfaceHelperServer (SVCHlpClient *aClient,
SVCHlpMsg::Code aMsgCode)
{
LogFlowFuncEnter();
LogFlowFunc (("aClient={%p}, aMsgCode=%d\n", aClient, aMsgCode));
AssertReturn (aClient, VERR_INVALID_POINTER);
int vrc = VINF_SUCCESS;
switch (aMsgCode)
{
case SVCHlpMsg::CreateHostNetworkInterface:
{
LogFlowFunc (("CreateHostNetworkInterface:\n"));
Utf8Str name;
vrc = aClient->read (name);
if (VBOX_FAILURE (vrc)) break;
Guid guid;
Utf8Str errMsg;
vrc = createNetworkInterface (aClient, name, guid, errMsg);
if (VBOX_SUCCESS (vrc))
{
/* write success followed by GUID */
vrc = aClient->write (SVCHlpMsg::CreateHostNetworkInterface_OK);
if (VBOX_FAILURE (vrc)) break;
vrc = aClient->write (guid);
if (VBOX_FAILURE (vrc)) break;
}
else
{
/* write failure followed by error message */
if (errMsg.isEmpty())
errMsg = Utf8StrFmt ("Unspecified error (%Vrc)", vrc);
vrc = aClient->write (SVCHlpMsg::Error);
if (VBOX_FAILURE (vrc)) break;
vrc = aClient->write (errMsg);
if (VBOX_FAILURE (vrc)) break;
}
break;
}
case SVCHlpMsg::RemoveHostNetworkInterface:
{
LogFlowFunc (("RemoveHostNetworkInterface:\n"));
Guid guid;
vrc = aClient->read (guid);
if (VBOX_FAILURE (vrc)) break;
Utf8Str errMsg;
vrc = removeNetworkInterface (aClient, guid, errMsg);
if (VBOX_SUCCESS (vrc))
{
/* write parameter-less success */
vrc = aClient->write (SVCHlpMsg::OK);
if (VBOX_FAILURE (vrc)) break;
}
else
{
/* write failure followed by error message */
if (errMsg.isEmpty())
errMsg = Utf8StrFmt ("Unspecified error (%Vrc)", vrc);
vrc = aClient->write (SVCHlpMsg::Error);
if (VBOX_FAILURE (vrc)) break;
vrc = aClient->write (errMsg);
if (VBOX_FAILURE (vrc)) break;
}
break;
}
default:
AssertMsgFailedBreak ((
"Invalid message code %d (%08lX)\n", aMsgCode, aMsgCode),
VERR_GENERAL_FAILURE);
}
LogFlowFunc (("vrc=%Vrc\n", vrc));
LogFlowFuncLeave();
return vrc;
}
#endif /* RT_OS_WINDOWS */