VirtualBox

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

Last change on this file since 19075 was 19070, checked in by vboxsync, 16 years ago

Main,VBoxManage: Implemented IHost::OperatingSystem and IHost::OSVersion using RTSystemQueryOSInfo. TODO: review error reporting.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 85.5 KB
Line 
1/* $Id: HostImpl.cpp 19070 2009-04-21 12:29:36Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation: Host
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#define __STDC_LIMIT_MACROS
23#define __STDC_CONSTANT_MACROS
24
25#ifdef RT_OS_LINUX
26// # include <sys/types.h>
27// # include <sys/stat.h>
28// # include <unistd.h>
29# include <sys/ioctl.h>
30// # include <fcntl.h>
31// # include <mntent.h>
32/* bird: This is a hack to work around conflicts between these linux kernel headers
33 * and the GLIBC tcpip headers. They have different declarations of the 4
34 * standard byte order functions. */
35// # define _LINUX_BYTEORDER_GENERIC_H
36// # include <linux/cdrom.h>
37# include <errno.h>
38# include <net/if.h>
39# include <net/if_arp.h>
40#endif /* RT_OS_LINUX */
41
42#ifdef RT_OS_SOLARIS
43# include <fcntl.h>
44# include <unistd.h>
45# include <stropts.h>
46# include <errno.h>
47# include <limits.h>
48# include <stdio.h>
49# ifdef VBOX_SOLARIS_NSL_RESOLVED
50# include <libdevinfo.h>
51# endif
52# include <net/if.h>
53# include <sys/socket.h>
54# include <sys/sockio.h>
55# include <net/if_arp.h>
56# include <net/if.h>
57# include <sys/types.h>
58# include <sys/stat.h>
59# include <sys/cdio.h>
60# include <sys/dkio.h>
61# include <sys/mnttab.h>
62# include <sys/mntent.h>
63/* Dynamic loading of libhal on Solaris hosts */
64# ifdef VBOX_USE_LIBHAL
65# include "vbox-libhal.h"
66extern "C" char *getfullrawname(char *);
67# endif
68# include "solaris/DynLoadLibSolaris.h"
69#endif /* RT_OS_SOLARIS */
70
71#ifdef RT_OS_WINDOWS
72# define _WIN32_DCOM
73# include <windows.h>
74# include <shellapi.h>
75# define INITGUID
76# include <guiddef.h>
77# include <devguid.h>
78# include <objbase.h>
79//# include <setupapi.h>
80# include <shlobj.h>
81# include <cfgmgr32.h>
82
83#endif /* RT_OS_WINDOWS */
84
85
86#include "HostImpl.h"
87#include "HostDVDDriveImpl.h"
88#include "HostFloppyDriveImpl.h"
89#include "HostNetworkInterfaceImpl.h"
90#ifdef VBOX_WITH_USB
91# include "HostUSBDeviceImpl.h"
92# include "USBDeviceFilterImpl.h"
93# include "USBProxyService.h"
94#endif
95#include "VirtualBoxImpl.h"
96#include "MachineImpl.h"
97#include "Logging.h"
98#include "Performance.h"
99
100#ifdef RT_OS_DARWIN
101# include "darwin/iokit.h"
102#endif
103
104
105#include <iprt/asm.h>
106#include <iprt/string.h>
107#include <iprt/mp.h>
108#include <iprt/time.h>
109#include <iprt/param.h>
110#include <iprt/env.h>
111#include <iprt/mem.h>
112#include <iprt/system.h>
113#ifdef RT_OS_SOLARIS
114# include <iprt/path.h>
115# include <iprt/ctype.h>
116#endif
117#ifdef VBOX_WITH_HOSTNETIF_API
118#include "netif.h"
119#endif
120
121#include <VBox/usb.h>
122#include <VBox/x86.h>
123#include <VBox/err.h>
124#include <VBox/settings.h>
125
126#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
127# include <VBox/WinNetConfig.h>
128#endif /* #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
129
130#include <stdio.h>
131
132#include <algorithm>
133
134
135
136// constructor / destructor
137/////////////////////////////////////////////////////////////////////////////
138
139HRESULT Host::FinalConstruct()
140{
141 return S_OK;
142}
143
144void Host::FinalRelease()
145{
146 if (isReady())
147 uninit();
148}
149
150// public initializer/uninitializer for internal purposes only
151/////////////////////////////////////////////////////////////////////////////
152
153/**
154 * Initializes the host object.
155 *
156 * @param aParent VirtualBox parent object.
157 */
158HRESULT Host::init (VirtualBox *aParent)
159{
160 LogFlowThisFunc (("isReady=%d\n", isReady()));
161
162 ComAssertRet (aParent, E_INVALIDARG);
163
164 AutoWriteLock alock (this);
165 ComAssertRet (!isReady(), E_FAIL);
166
167 mParent = aParent;
168
169#ifdef VBOX_WITH_USB
170 /*
171 * Create and initialize the USB Proxy Service.
172 */
173# if defined (RT_OS_DARWIN)
174 mUSBProxyService = new USBProxyServiceDarwin (this);
175# elif defined (RT_OS_LINUX)
176 mUSBProxyService = new USBProxyServiceLinux (this);
177# elif defined (RT_OS_OS2)
178 mUSBProxyService = new USBProxyServiceOs2 (this);
179# elif defined (RT_OS_SOLARIS)
180 mUSBProxyService = new USBProxyServiceSolaris (this);
181# elif defined (RT_OS_WINDOWS)
182 mUSBProxyService = new USBProxyServiceWindows (this);
183# else
184 mUSBProxyService = new USBProxyService (this);
185# endif
186 HRESULT hrc = mUSBProxyService->init();
187 AssertComRCReturn(hrc, hrc);
188#endif /* VBOX_WITH_USB */
189
190#ifdef VBOX_WITH_RESOURCE_USAGE_API
191 registerMetrics (aParent->performanceCollector());
192#endif /* VBOX_WITH_RESOURCE_USAGE_API */
193
194#if defined (RT_OS_WINDOWS)
195 mHostPowerService = new HostPowerServiceWin (mParent);
196#elif defined (RT_OS_DARWIN)
197 mHostPowerService = new HostPowerServiceDarwin (mParent);
198#else
199 mHostPowerService = new HostPowerService (mParent);
200#endif
201
202 /* Cache the features reported by GetProcessorFeature. */
203 fVTxAMDVSupported = false;
204 fLongModeSupported = false;
205 fPAESupported = false;
206
207 if (ASMHasCpuId())
208 {
209 uint32_t u32FeaturesECX;
210 uint32_t u32Dummy;
211 uint32_t u32FeaturesEDX;
212 uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX, u32AMDFeatureEDX, u32AMDFeatureECX;
213
214 ASMCpuId (0, &u32Dummy, &u32VendorEBX, &u32VendorECX, &u32VendorEDX);
215 ASMCpuId (1, &u32Dummy, &u32Dummy, &u32FeaturesECX, &u32FeaturesEDX);
216 /* Query AMD features. */
217 ASMCpuId (0x80000001, &u32Dummy, &u32Dummy, &u32AMDFeatureECX, &u32AMDFeatureEDX);
218
219 fLongModeSupported = !!(u32AMDFeatureEDX & X86_CPUID_AMD_FEATURE_EDX_LONG_MODE);
220 fPAESupported = !!(u32FeaturesEDX & X86_CPUID_FEATURE_EDX_PAE);
221
222 if ( u32VendorEBX == X86_CPUID_VENDOR_INTEL_EBX
223 && u32VendorECX == X86_CPUID_VENDOR_INTEL_ECX
224 && u32VendorEDX == X86_CPUID_VENDOR_INTEL_EDX
225 )
226 {
227 if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
228 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
229 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
230 )
231 fVTxAMDVSupported = true;
232 }
233 else
234 if ( u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX
235 && u32VendorECX == X86_CPUID_VENDOR_AMD_ECX
236 && u32VendorEDX == X86_CPUID_VENDOR_AMD_EDX
237 )
238 {
239 if ( (u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
240 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
241 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
242 )
243 fVTxAMDVSupported = true;
244 }
245 }
246
247 setReady(true);
248 return S_OK;
249}
250
251/**
252 * Uninitializes the host object and sets the ready flag to FALSE.
253 * Called either from FinalRelease() or by the parent when it gets destroyed.
254 */
255void Host::uninit()
256{
257 LogFlowThisFunc (("isReady=%d\n", isReady()));
258
259 AssertReturn (isReady(), (void) 0);
260
261#ifdef VBOX_WITH_RESOURCE_USAGE_API
262 unregisterMetrics (mParent->performanceCollector());
263#endif /* VBOX_WITH_RESOURCE_USAGE_API */
264
265#ifdef VBOX_WITH_USB
266 /* wait for USB proxy service to terminate before we uninit all USB
267 * devices */
268 LogFlowThisFunc (("Stopping USB proxy service...\n"));
269 delete mUSBProxyService;
270 mUSBProxyService = NULL;
271 LogFlowThisFunc (("Done stopping USB proxy service.\n"));
272#endif
273
274 delete mHostPowerService;
275
276 /* uninit all USB device filters still referenced by clients */
277 uninitDependentChildren();
278
279#ifdef VBOX_WITH_USB
280 mUSBDeviceFilters.clear();
281#endif
282
283 setReady (FALSE);
284}
285
286// IHost properties
287/////////////////////////////////////////////////////////////////////////////
288
289/**
290 * Returns a list of host DVD drives.
291 *
292 * @returns COM status code
293 * @param drives address of result pointer
294 */
295STDMETHODIMP Host::COMGETTER(DVDDrives) (ComSafeArrayOut (IHostDVDDrive *, aDrives))
296{
297 CheckComArgOutSafeArrayPointerValid(aDrives);
298 AutoWriteLock alock (this);
299 CHECK_READY();
300 std::list <ComObjPtr <HostDVDDrive> > list;
301 HRESULT rc = S_OK;
302
303#if defined(RT_OS_WINDOWS)
304 int sz = GetLogicalDriveStrings(0, NULL);
305 TCHAR *hostDrives = new TCHAR[sz+1];
306 GetLogicalDriveStrings(sz, hostDrives);
307 wchar_t driveName[3] = { '?', ':', '\0' };
308 TCHAR *p = hostDrives;
309 do
310 {
311 if (GetDriveType(p) == DRIVE_CDROM)
312 {
313 driveName[0] = *p;
314 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
315 hostDVDDriveObj.createObject();
316 hostDVDDriveObj->init (Bstr (driveName));
317 list.push_back (hostDVDDriveObj);
318 }
319 p += _tcslen(p) + 1;
320 }
321 while (*p);
322 delete[] hostDrives;
323
324#elif defined(RT_OS_SOLARIS)
325# ifdef VBOX_USE_LIBHAL
326 if (!getDVDInfoFromHal(list))
327# endif
328 // Not all Solaris versions ship with libhal.
329 // So use a fallback approach similar to Linux.
330 {
331 if (RTEnvGet("VBOX_CDROM"))
332 {
333 char *cdromEnv = strdup(RTEnvGet("VBOX_CDROM"));
334 char *cdromDrive;
335 cdromDrive = strtok(cdromEnv, ":"); /** @todo use strtok_r. */
336 while (cdromDrive)
337 {
338 if (validateDevice(cdromDrive, true))
339 {
340 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
341 hostDVDDriveObj.createObject();
342 hostDVDDriveObj->init (Bstr (cdromDrive));
343 list.push_back (hostDVDDriveObj);
344 }
345 cdromDrive = strtok(NULL, ":");
346 }
347 free(cdromEnv);
348 }
349 else
350 {
351 // this might work on Solaris version older than Nevada.
352 if (validateDevice("/cdrom/cdrom0", true))
353 {
354 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
355 hostDVDDriveObj.createObject();
356 hostDVDDriveObj->init (Bstr ("cdrom/cdrom0"));
357 list.push_back (hostDVDDriveObj);
358 }
359
360 // check the mounted drives
361 parseMountTable(MNTTAB, list);
362 }
363 }
364
365#elif defined(RT_OS_LINUX)
366 if (RT_SUCCESS (mHostDrives.updateDVDs()))
367 for (DriveInfoList::const_iterator it = mHostDrives.DVDBegin();
368 SUCCEEDED (rc) && it != mHostDrives.DVDEnd(); ++it)
369 {
370 ComObjPtr<HostDVDDrive> hostDVDDriveObj;
371 Bstr device (it->mDevice.c_str());
372 Bstr udi (it->mUdi.empty() ? NULL : it->mUdi.c_str());
373 Bstr description (it->mDescription.empty() ? NULL : it->mDescription.c_str());
374 if (device.isNull() || (!it->mUdi.empty() && udi.isNull()) ||
375 (!it->mDescription.empty() && description.isNull()))
376 rc = E_OUTOFMEMORY;
377 if (SUCCEEDED (rc))
378 rc = hostDVDDriveObj.createObject();
379 if (SUCCEEDED (rc))
380 rc = hostDVDDriveObj->init (device, udi, description);
381 if (SUCCEEDED (rc))
382 list.push_back(hostDVDDriveObj);
383 }
384#elif defined(RT_OS_DARWIN)
385 PDARWINDVD cur = DarwinGetDVDDrives();
386 while (cur)
387 {
388 ComObjPtr<HostDVDDrive> hostDVDDriveObj;
389 hostDVDDriveObj.createObject();
390 hostDVDDriveObj->init(Bstr(cur->szName));
391 list.push_back(hostDVDDriveObj);
392
393 /* next */
394 void *freeMe = cur;
395 cur = cur->pNext;
396 RTMemFree(freeMe);
397 }
398
399#else
400 /* PORTME */
401#endif
402
403 SafeIfaceArray <IHostDVDDrive> array (list);
404 array.detachTo(ComSafeArrayOutArg(aDrives));
405 return rc;
406}
407
408/**
409 * Returns a list of host floppy drives.
410 *
411 * @returns COM status code
412 * @param drives address of result pointer
413 */
414STDMETHODIMP Host::COMGETTER(FloppyDrives) (ComSafeArrayOut (IHostFloppyDrive *, aDrives))
415{
416 CheckComArgOutPointerValid(aDrives);
417 AutoWriteLock alock (this);
418 CHECK_READY();
419
420 std::list <ComObjPtr <HostFloppyDrive> > list;
421 HRESULT rc = S_OK;
422
423#ifdef RT_OS_WINDOWS
424 int sz = GetLogicalDriveStrings(0, NULL);
425 TCHAR *hostDrives = new TCHAR[sz+1];
426 GetLogicalDriveStrings(sz, hostDrives);
427 wchar_t driveName[3] = { '?', ':', '\0' };
428 TCHAR *p = hostDrives;
429 do
430 {
431 if (GetDriveType(p) == DRIVE_REMOVABLE)
432 {
433 driveName[0] = *p;
434 ComObjPtr <HostFloppyDrive> hostFloppyDriveObj;
435 hostFloppyDriveObj.createObject();
436 hostFloppyDriveObj->init (Bstr (driveName));
437 list.push_back (hostFloppyDriveObj);
438 }
439 p += _tcslen(p) + 1;
440 }
441 while (*p);
442 delete[] hostDrives;
443#elif defined(RT_OS_LINUX)
444 if (RT_SUCCESS (mHostDrives.updateFloppies()))
445 for (DriveInfoList::const_iterator it = mHostDrives.FloppyBegin();
446 SUCCEEDED (rc) && it != mHostDrives.FloppyEnd(); ++it)
447 {
448 ComObjPtr<HostFloppyDrive> hostFloppyDriveObj;
449 Bstr device (it->mDevice.c_str());
450 Bstr udi (it->mUdi.empty() ? NULL : it->mUdi.c_str());
451 Bstr description (it->mDescription.empty() ? NULL : it->mDescription.c_str());
452 if (device.isNull() || (!it->mUdi.empty() && udi.isNull()) ||
453 (!it->mDescription.empty() && description.isNull()))
454 rc = E_OUTOFMEMORY;
455 if (SUCCEEDED (rc))
456 rc = hostFloppyDriveObj.createObject();
457 if (SUCCEEDED (rc))
458 rc = hostFloppyDriveObj->init (device, udi, description);
459 if (SUCCEEDED (rc))
460 list.push_back(hostFloppyDriveObj);
461 }
462#else
463 /* PORTME */
464#endif
465
466 SafeIfaceArray<IHostFloppyDrive> collection (list);
467 collection.detachTo(ComSafeArrayOutArg (aDrives));
468 return rc;
469}
470
471#ifdef RT_OS_SOLARIS
472static void vboxSolarisAddHostIface(char *pszIface, int Instance, PCRTMAC pMac, void *pvHostNetworkInterfaceList)
473{
474 std::list<ComObjPtr <HostNetworkInterface> > *pList = (std::list<ComObjPtr <HostNetworkInterface> > *)pvHostNetworkInterfaceList;
475 Assert(pList);
476
477 typedef std::map <std::string, std::string> NICMap;
478 typedef std::pair <std::string, std::string> NICPair;
479 static NICMap SolarisNICMap;
480 if (SolarisNICMap.empty())
481 {
482 SolarisNICMap.insert(NICPair("afe", "ADMtek Centaur/Comet Fast Ethernet"));
483 SolarisNICMap.insert(NICPair("aggr", "Link Aggregation Interface"));
484 SolarisNICMap.insert(NICPair("bge", "Broadcom BCM57xx Gigabit Ethernet"));
485 SolarisNICMap.insert(NICPair("ce", "Cassini Gigabit Ethernet"));
486 SolarisNICMap.insert(NICPair("chxge", "Chelsio Ethernet"));
487 SolarisNICMap.insert(NICPair("dmfe", "Davicom Fast Ethernet"));
488 SolarisNICMap.insert(NICPair("dnet", "DEC 21040/41 21140 Ethernet"));
489 SolarisNICMap.insert(NICPair("e1000", "Intel PRO/1000 Gigabit Ethernet"));
490 SolarisNICMap.insert(NICPair("e1000g", "Intel PRO/1000 Gigabit Ethernet"));
491 SolarisNICMap.insert(NICPair("elx", "3COM EtherLink III Ethernet"));
492 SolarisNICMap.insert(NICPair("elxl", "3COM Ethernet"));
493 SolarisNICMap.insert(NICPair("eri", "eri Fast Ethernet"));
494 SolarisNICMap.insert(NICPair("ge", "GEM Gigabit Ethernet"));
495 SolarisNICMap.insert(NICPair("hme", "SUNW,hme Fast-Ethernet"));
496 SolarisNICMap.insert(NICPair("ipge", "PCI-E Gigabit Ethernet"));
497 SolarisNICMap.insert(NICPair("iprb", "Intel 82557/58/59 Ethernet"));
498 SolarisNICMap.insert(NICPair("mxfe", "Macronix 98715 Fast Ethernet"));
499 SolarisNICMap.insert(NICPair("nge", "Nvidia Gigabit Ethernet"));
500 SolarisNICMap.insert(NICPair("pcelx", "3COM EtherLink III PCMCIA Ethernet"));
501 SolarisNICMap.insert(NICPair("pcn", "AMD PCnet Ethernet"));
502 SolarisNICMap.insert(NICPair("qfe", "SUNW,qfe Quad Fast-Ethernet"));
503 SolarisNICMap.insert(NICPair("rge", "Realtek Gigabit Ethernet"));
504 SolarisNICMap.insert(NICPair("rtls", "Realtek 8139 Fast Ethernet"));
505 SolarisNICMap.insert(NICPair("skge", "SksKonnect Gigabit Ethernet"));
506 SolarisNICMap.insert(NICPair("spwr", "SMC EtherPower II 10/100 (9432) Ethernet"));
507 SolarisNICMap.insert(NICPair("vnic", "Virtual Network Interface Ethernet"));
508 SolarisNICMap.insert(NICPair("xge", "Neterior Xframe Gigabit Ethernet"));
509 SolarisNICMap.insert(NICPair("xge", "Neterior Xframe 10Gigabit Ethernet"));
510 }
511
512 /*
513 * Try picking up description from our NIC map.
514 */
515 char szNICInstance[128];
516 RTStrPrintf(szNICInstance, sizeof(szNICInstance), "%s%d", pszIface, Instance);
517 char szNICDesc[256];
518 std::string Description = SolarisNICMap[pszIface];
519 if (Description != "")
520 RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - %s", szNICInstance, Description.c_str());
521 else
522 RTStrPrintf(szNICDesc, sizeof(szNICDesc), "%s - Ethernet", szNICInstance);
523
524 /*
525 * Construct UUID with interface name and the MAC address if available.
526 */
527 RTUUID Uuid;
528 RTUuidClear(&Uuid);
529 memcpy(&Uuid, szNICInstance, RT_MIN(strlen(szNICInstance), sizeof(Uuid)));
530 Uuid.Gen.u8ClockSeqHiAndReserved = (Uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80;
531 Uuid.Gen.u16TimeHiAndVersion = (Uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000;
532 if (pMac)
533 {
534 Uuid.Gen.au8Node[0] = pMac->au8[0];
535 Uuid.Gen.au8Node[1] = pMac->au8[1];
536 Uuid.Gen.au8Node[2] = pMac->au8[2];
537 Uuid.Gen.au8Node[3] = pMac->au8[3];
538 Uuid.Gen.au8Node[4] = pMac->au8[4];
539 Uuid.Gen.au8Node[5] = pMac->au8[5];
540 }
541
542 ComObjPtr<HostNetworkInterface> IfObj;
543 IfObj.createObject();
544 if (SUCCEEDED(IfObj->init(Bstr(szNICDesc), Guid(Uuid), HostNetworkInterfaceType_Bridged)))
545 pList->push_back(IfObj);
546}
547
548static boolean_t vboxSolarisAddLinkHostIface(const char *pszIface, void *pvHostNetworkInterfaceList)
549{
550 /*
551 * Clip off the zone instance number from the interface name (if any).
552 */
553 char szIfaceName[128];
554 strcpy(szIfaceName, pszIface);
555 char *pszColon = (char *)memchr(szIfaceName, ':', sizeof(szIfaceName));
556 if (pszColon)
557 *pszColon = '\0';
558
559 /*
560 * Get the instance number from the interface name, then clip it off.
561 */
562 int cbInstance = 0;
563 int cbIface = strlen(szIfaceName);
564 const char *pszEnd = pszIface + cbIface - 1;
565 for (int i = 0; i < cbIface - 1; i++)
566 {
567 if (!RT_C_IS_DIGIT(*pszEnd))
568 break;
569 cbInstance++;
570 pszEnd--;
571 }
572
573 int Instance = atoi(pszEnd + 1);
574 strncpy(szIfaceName, pszIface, cbIface - cbInstance);
575 szIfaceName[cbIface - cbInstance] = '\0';
576
577 /*
578 * Add the interface.
579 */
580 vboxSolarisAddHostIface(szIfaceName, Instance, NULL, pvHostNetworkInterfaceList);
581
582 /*
583 * Continue walking...
584 */
585 return _B_FALSE;
586}
587
588static bool vboxSolarisSortNICList(const ComObjPtr <HostNetworkInterface> Iface1, const ComObjPtr <HostNetworkInterface> Iface2)
589{
590 Bstr Iface1Str;
591 (*Iface1).COMGETTER(Name) (Iface1Str.asOutParam());
592
593 Bstr Iface2Str;
594 (*Iface2).COMGETTER(Name) (Iface2Str.asOutParam());
595
596 return Iface1Str < Iface2Str;
597}
598
599static bool vboxSolarisSameNIC(const ComObjPtr <HostNetworkInterface> Iface1, const ComObjPtr <HostNetworkInterface> Iface2)
600{
601 Bstr Iface1Str;
602 (*Iface1).COMGETTER(Name) (Iface1Str.asOutParam());
603
604 Bstr Iface2Str;
605 (*Iface2).COMGETTER(Name) (Iface2Str.asOutParam());
606
607 return (Iface1Str == Iface2Str);
608}
609
610# ifdef VBOX_SOLARIS_NSL_RESOLVED
611static int vboxSolarisAddPhysHostIface(di_node_t Node, di_minor_t Minor, void *pvHostNetworkInterfaceList)
612{
613 /*
614 * Skip aggregations.
615 */
616 if (!strcmp(di_driver_name(Node), "aggr"))
617 return DI_WALK_CONTINUE;
618
619 /*
620 * Skip softmacs.
621 */
622 if (!strcmp(di_driver_name(Node), "softmac"))
623 return DI_WALK_CONTINUE;
624
625 vboxSolarisAddHostIface(di_driver_name(Node), di_instance(Node), NULL, pvHostNetworkInterfaceList);
626 return DI_WALK_CONTINUE;
627}
628# endif /* VBOX_SOLARIS_NSL_RESOLVED */
629
630#endif
631
632#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
633# define VBOX_APP_NAME L"VirtualBox"
634
635static int vboxNetWinAddComponent(std::list <ComObjPtr <HostNetworkInterface> > * pPist, INetCfgComponent * pncc)
636{
637 LPWSTR lpszName;
638 GUID IfGuid;
639 HRESULT hr;
640 int rc = VERR_GENERAL_FAILURE;
641
642 hr = pncc->GetDisplayName( &lpszName );
643 Assert(hr == S_OK);
644 if(hr == S_OK)
645 {
646 size_t cUnicodeName = wcslen(lpszName) + 1;
647 size_t uniLen = (cUnicodeName * 2 + sizeof (OLECHAR) - 1) / sizeof (OLECHAR);
648 Bstr name (uniLen + 1 /* extra zero */);
649 wcscpy((wchar_t *) name.mutableRaw(), lpszName);
650
651 hr = pncc->GetInstanceGuid(&IfGuid);
652 Assert(hr == S_OK);
653 if (hr == S_OK)
654 {
655 /* create a new object and add it to the list */
656 ComObjPtr <HostNetworkInterface> iface;
657 iface.createObject();
658 /* remove the curly bracket at the end */
659 if (SUCCEEDED (iface->init (name, Guid (IfGuid), HostNetworkInterfaceType_Bridged)))
660 {
661// iface->setVirtualBox(mParent);
662 pPist->push_back (iface);
663 rc = VINF_SUCCESS;
664 }
665 else
666 {
667 Assert(0);
668 }
669 }
670 CoTaskMemFree(lpszName);
671 }
672
673 return rc;
674}
675#endif /* defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) */
676/**
677 * Returns a list of host network interfaces.
678 *
679 * @returns COM status code
680 * @param drives address of result pointer
681 */
682STDMETHODIMP Host::COMGETTER(NetworkInterfaces) (ComSafeArrayOut (IHostNetworkInterface *, aNetworkInterfaces))
683{
684#if defined(RT_OS_WINDOWS) || defined(VBOX_WITH_NETFLT) /*|| defined(RT_OS_OS2)*/
685 if (ComSafeArrayOutIsNull (aNetworkInterfaces))
686 return E_POINTER;
687
688 AutoWriteLock alock (this);
689 CHECK_READY();
690
691 std::list <ComObjPtr <HostNetworkInterface> > list;
692
693#ifdef VBOX_WITH_HOSTNETIF_API
694 int rc = NetIfList(list);
695 if (rc)
696 {
697 Log(("Failed to get host network interface list with rc=%Vrc\n", rc));
698 }
699#else
700# if defined(RT_OS_DARWIN)
701 PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
702 while (pEtherNICs)
703 {
704 ComObjPtr<HostNetworkInterface> IfObj;
705 IfObj.createObject();
706 if (SUCCEEDED(IfObj->init(Bstr(pEtherNICs->szName), Guid(pEtherNICs->Uuid), HostNetworkInterfaceType_Bridged)))
707 list.push_back(IfObj);
708
709 /* next, free current */
710 void *pvFree = pEtherNICs;
711 pEtherNICs = pEtherNICs->pNext;
712 RTMemFree(pvFree);
713 }
714
715# elif defined(RT_OS_SOLARIS)
716
717# ifdef VBOX_SOLARIS_NSL_RESOLVED
718
719 /*
720 * Use libdevinfo for determining all physical interfaces.
721 */
722 di_node_t Root;
723 Root = di_init("/", DINFOCACHE);
724 if (Root != DI_NODE_NIL)
725 {
726 di_walk_minor(Root, DDI_NT_NET, 0, &list, vboxSolarisAddPhysHostIface);
727 di_fini(Root);
728 }
729
730 /*
731 * Use libdlpi for determining all DLPI interfaces.
732 */
733 if (VBoxSolarisLibDlpiFound())
734 g_pfnLibDlpiWalk(vboxSolarisAddLinkHostIface, &list, 0);
735
736# endif /* VBOX_SOLARIS_NSL_RESOLVED */
737
738 /*
739 * This gets only the list of all plumbed logical interfaces.
740 * This is needed for zones which cannot access the device tree
741 * and in this case we just let them use the list of plumbed interfaces
742 * on the zone.
743 */
744 int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
745 if (Sock > 0)
746 {
747 struct lifnum IfNum;
748 memset(&IfNum, 0, sizeof(IfNum));
749 IfNum.lifn_family = AF_INET;
750 int rc = ioctl(Sock, SIOCGLIFNUM, &IfNum);
751 if (!rc)
752 {
753 struct lifreq Ifaces[24];
754 struct lifconf IfConfig;
755 memset(&IfConfig, 0, sizeof(IfConfig));
756 IfConfig.lifc_family = AF_INET;
757 IfConfig.lifc_len = sizeof(Ifaces);
758 IfConfig.lifc_buf = (caddr_t)&(Ifaces[0]);
759 rc = ioctl(Sock, SIOCGLIFCONF, &IfConfig);
760 if (!rc)
761 {
762 for (int i = 0; i < IfNum.lifn_count; i++)
763 {
764 /*
765 * Skip loopback interfaces.
766 */
767 if (!strncmp(Ifaces[i].lifr_name, "lo", 2))
768 continue;
769
770#if 0
771 rc = ioctl(Sock, SIOCGLIFADDR, &(Ifaces[i]));
772 if (!rc)
773 {
774 RTMAC Mac;
775 struct arpreq ArpReq;
776 memcpy(&ArpReq.arp_pa, &Ifaces[i].lifr_addr, sizeof(struct sockaddr_in));
777
778 /*
779 * We might fail if the interface has not been assigned an IP address.
780 * That doesn't matter; as long as it's plumbed we can pick it up.
781 * But, if it has not acquired an IP address we cannot obtain it's MAC
782 * address this way, so we just use all zeros there.
783 */
784 rc = ioctl(Sock, SIOCGARP, &ArpReq);
785 if (!rc)
786 memcpy(&Mac, ArpReq.arp_ha.sa_data, sizeof(RTMAC));
787 else
788 memset(&Mac, 0, sizeof(Mac));
789
790 char szNICDesc[LIFNAMSIZ + 256];
791 char *pszIface = Ifaces[i].lifr_name;
792 strcpy(szNICDesc, pszIface);
793
794 vboxSolarisAddLinkHostIface(pszIface, &list);
795 }
796#endif
797
798 char *pszIface = Ifaces[i].lifr_name;
799 vboxSolarisAddLinkHostIface(pszIface, &list);
800 }
801 }
802 }
803 close(Sock);
804 }
805
806 /*
807 * Weed out duplicates caused by dlpi_walk inconsistencies across Nevadas.
808 */
809 list.sort(vboxSolarisSortNICList);
810 list.unique(vboxSolarisSameNIC);
811
812# elif defined RT_OS_WINDOWS
813# ifndef VBOX_WITH_NETFLT
814 hr = E_NOTIMPL;
815# else /* # if defined VBOX_WITH_NETFLT */
816 INetCfg *pNc;
817 INetCfgComponent *pMpNcc;
818 INetCfgComponent *pTcpIpNcc;
819 LPWSTR lpszApp;
820 HRESULT hr;
821 IEnumNetCfgBindingPath *pEnumBp;
822 INetCfgBindingPath *pBp;
823 IEnumNetCfgBindingInterface *pEnumBi;
824 INetCfgBindingInterface *pBi;
825
826 /* we are using the INetCfg API for getting the list of miniports */
827 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
828 VBOX_APP_NAME,
829 &pNc,
830 &lpszApp );
831 Assert(hr == S_OK);
832 if(hr == S_OK)
833 {
834#ifdef VBOX_NETFLT_ONDEMAND_BIND
835 /* for the protocol-based approach for now we just get all miniports the MS_TCPIP protocol binds to */
836 hr = pNc->FindComponent(L"MS_TCPIP", &pTcpIpNcc);
837#else
838 /* for the filter-based approach we get all miniports our filter (sun_VBoxNetFlt)is bound to */
839 hr = pNc->FindComponent(L"sun_VBoxNetFlt", &pTcpIpNcc);
840# ifndef VBOX_WITH_HARDENING
841 if(hr != S_OK)
842 {
843 /* TODO: try to install the netflt from here */
844 }
845# endif
846
847#endif
848
849 if(hr == S_OK)
850 {
851 hr = VBoxNetCfgWinGetBindingPathEnum(pTcpIpNcc, EBP_BELOW, &pEnumBp);
852 Assert(hr == S_OK);
853 if ( hr == S_OK )
854 {
855 hr = VBoxNetCfgWinGetFirstBindingPath(pEnumBp, &pBp);
856 Assert(hr == S_OK || hr == S_FALSE);
857 while( hr == S_OK )
858 {
859 /* S_OK == enabled, S_FALSE == disabled */
860 if(pBp->IsEnabled() == S_OK)
861 {
862 hr = VBoxNetCfgWinGetBindingInterfaceEnum(pBp, &pEnumBi);
863 Assert(hr == S_OK);
864 if ( hr == S_OK )
865 {
866 hr = VBoxNetCfgWinGetFirstBindingInterface(pEnumBi, &pBi);
867 Assert(hr == S_OK);
868 while(hr == S_OK)
869 {
870 hr = pBi->GetLowerComponent( &pMpNcc );
871 Assert(hr == S_OK);
872 if(hr == S_OK)
873 {
874 ULONG uComponentStatus;
875 hr = pMpNcc->GetDeviceStatus(&uComponentStatus);
876 Assert(hr == S_OK);
877 if(hr == S_OK)
878 {
879 if(uComponentStatus == 0)
880 {
881 vboxNetWinAddComponent(&list, pMpNcc);
882 }
883 }
884 VBoxNetCfgWinReleaseRef( pMpNcc );
885 }
886 VBoxNetCfgWinReleaseRef(pBi);
887
888 hr = VBoxNetCfgWinGetNextBindingInterface(pEnumBi, &pBi);
889 }
890 VBoxNetCfgWinReleaseRef(pEnumBi);
891 }
892 }
893 VBoxNetCfgWinReleaseRef(pBp);
894
895 hr = VBoxNetCfgWinGetNextBindingPath(pEnumBp, &pBp);
896 }
897 VBoxNetCfgWinReleaseRef(pEnumBp);
898 }
899 VBoxNetCfgWinReleaseRef(pTcpIpNcc);
900 }
901 else
902 {
903 LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
904 }
905
906 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
907 }
908# endif /* # if defined VBOX_WITH_NETFLT */
909
910
911# elif defined RT_OS_LINUX
912 int sock = socket(AF_INET, SOCK_DGRAM, 0);
913 if (sock >= 0)
914 {
915 char pBuffer[2048];
916 struct ifconf ifConf;
917 ifConf.ifc_len = sizeof(pBuffer);
918 ifConf.ifc_buf = pBuffer;
919 if (ioctl(sock, SIOCGIFCONF, &ifConf) >= 0)
920 {
921 for (struct ifreq *pReq = ifConf.ifc_req; (char*)pReq < pBuffer + ifConf.ifc_len; pReq++)
922 {
923 if (ioctl(sock, SIOCGIFHWADDR, pReq) >= 0)
924 {
925 if (pReq->ifr_hwaddr.sa_family == ARPHRD_ETHER)
926 {
927 RTUUID uuid;
928 Assert(sizeof(uuid) <= sizeof(*pReq));
929 memcpy(&uuid, pReq, sizeof(uuid));
930
931 ComObjPtr<HostNetworkInterface> IfObj;
932 IfObj.createObject();
933 if (SUCCEEDED(IfObj->init(Bstr(pReq->ifr_name), Guid(uuid), HostNetworkInterfaceType_Bridged)))
934 list.push_back(IfObj);
935 }
936 }
937 }
938 }
939 close(sock);
940 }
941# endif /* RT_OS_LINUX */
942#endif
943
944 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
945 for (it = list.begin(); it != list.end(); ++it)
946 {
947 (*it)->setVirtualBox(mParent);
948 }
949
950
951 SafeIfaceArray <IHostNetworkInterface> networkInterfaces (list);
952 networkInterfaces.detachTo (ComSafeArrayOutArg (aNetworkInterfaces));
953
954 return S_OK;
955
956#else
957 /* Not implemented / supported on this platform. */
958 ReturnComNotImplemented();
959#endif
960}
961
962STDMETHODIMP Host::COMGETTER(USBDevices)(ComSafeArrayOut (IHostUSBDevice *, aUSBDevices))
963{
964#ifdef VBOX_WITH_USB
965 CheckComArgOutSafeArrayPointerValid(aUSBDevices);
966
967 AutoWriteLock alock (this);
968 CHECK_READY();
969
970 MultiResult rc = checkUSBProxyService();
971 CheckComRCReturnRC (rc);
972
973 return mUSBProxyService->getDeviceCollection (ComSafeArrayOutArg(aUSBDevices));
974
975#else
976 /* Note: The GUI depends on this method returning E_NOTIMPL with no
977 * extended error info to indicate that USB is simply not available
978 * (w/o treating it as a failure), for example, as in OSE. */
979 ReturnComNotImplemented();
980#endif
981}
982
983STDMETHODIMP Host::COMGETTER(USBDeviceFilters) (ComSafeArrayOut (IHostUSBDeviceFilter *, aUSBDeviceFilters))
984{
985#ifdef VBOX_WITH_USB
986 CheckComArgOutSafeArrayPointerValid(aUSBDeviceFilters);
987
988 AutoWriteLock alock (this);
989 CHECK_READY();
990
991 MultiResult rc = checkUSBProxyService();
992 CheckComRCReturnRC (rc);
993
994 SafeIfaceArray <IHostUSBDeviceFilter> collection (mUSBDeviceFilters);
995 collection.detachTo (ComSafeArrayOutArg (aUSBDeviceFilters));
996
997 return rc;
998#else
999 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1000 * extended error info to indicate that USB is simply not available
1001 * (w/o treating it as a failure), for example, as in OSE. */
1002 ReturnComNotImplemented();
1003#endif
1004}
1005
1006/**
1007 * Returns the number of installed logical processors
1008 *
1009 * @returns COM status code
1010 * @param count address of result variable
1011 */
1012STDMETHODIMP Host::COMGETTER(ProcessorCount)(ULONG *aCount)
1013{
1014 CheckComArgOutPointerValid(aCount);
1015 AutoWriteLock alock (this);
1016 CHECK_READY();
1017 *aCount = RTMpGetPresentCount();
1018 return S_OK;
1019}
1020
1021/**
1022 * Returns the number of online logical processors
1023 *
1024 * @returns COM status code
1025 * @param count address of result variable
1026 */
1027STDMETHODIMP Host::COMGETTER(ProcessorOnlineCount)(ULONG *aCount)
1028{
1029 CheckComArgOutPointerValid(aCount);
1030 AutoWriteLock alock (this);
1031 CHECK_READY();
1032 *aCount = RTMpGetOnlineCount();
1033 return S_OK;
1034}
1035
1036/**
1037 * Returns the (approximate) maximum speed of the given host CPU in MHz
1038 *
1039 * @returns COM status code
1040 * @param cpu id to get info for.
1041 * @param speed address of result variable, speed is 0 if unknown or aCpuId is invalid.
1042 */
1043STDMETHODIMP Host::GetProcessorSpeed(ULONG aCpuId, ULONG *aSpeed)
1044{
1045 CheckComArgOutPointerValid(aSpeed);
1046 AutoWriteLock alock (this);
1047 CHECK_READY();
1048 *aSpeed = RTMpGetMaxFrequency(aCpuId);
1049 return S_OK;
1050}
1051/**
1052 * Returns a description string for the host CPU
1053 *
1054 * @returns COM status code
1055 * @param cpu id to get info for.
1056 * @param description address of result variable, NULL if known or aCpuId is invalid.
1057 */
1058STDMETHODIMP Host::GetProcessorDescription(ULONG /* aCpuId */, BSTR *aDescription)
1059{
1060 CheckComArgOutPointerValid(aDescription);
1061 AutoWriteLock alock (this);
1062 CHECK_READY();
1063 /** @todo */
1064 ReturnComNotImplemented();
1065}
1066
1067/**
1068 * Returns whether a host processor feature is supported or not
1069 *
1070 * @returns COM status code
1071 * @param Feature to query.
1072 * @param address of supported bool result variable
1073 */
1074STDMETHODIMP Host::GetProcessorFeature(ProcessorFeature_T aFeature, BOOL *aSupported)
1075{
1076 CheckComArgOutPointerValid(aSupported);
1077 AutoWriteLock alock (this);
1078 CHECK_READY();
1079
1080 switch (aFeature)
1081 {
1082 case ProcessorFeature_HWVirtEx:
1083 *aSupported = fVTxAMDVSupported;
1084 break;
1085
1086 case ProcessorFeature_PAE:
1087 *aSupported = fPAESupported;
1088 break;
1089
1090 case ProcessorFeature_LongMode:
1091 *aSupported = fLongModeSupported;
1092 break;
1093
1094 default:
1095 ReturnComNotImplemented();
1096 }
1097 return S_OK;
1098}
1099
1100/**
1101 * Returns the amount of installed system memory in megabytes
1102 *
1103 * @returns COM status code
1104 * @param size address of result variable
1105 */
1106STDMETHODIMP Host::COMGETTER(MemorySize)(ULONG *aSize)
1107{
1108 CheckComArgOutPointerValid(aSize);
1109 AutoWriteLock alock (this);
1110 CHECK_READY();
1111 /* @todo This is an ugly hack. There must be a function in IPRT for that. */
1112 pm::CollectorHAL *hal = pm::createHAL();
1113 if (!hal)
1114 return E_FAIL;
1115 ULONG tmp;
1116 int rc = hal->getHostMemoryUsage(aSize, &tmp, &tmp);
1117 *aSize /= 1024;
1118 delete hal;
1119 return rc;
1120}
1121
1122/**
1123 * Returns the current system memory free space in megabytes
1124 *
1125 * @returns COM status code
1126 * @param available address of result variable
1127 */
1128STDMETHODIMP Host::COMGETTER(MemoryAvailable)(ULONG *aAvailable)
1129{
1130 CheckComArgOutPointerValid(aAvailable);
1131 AutoWriteLock alock (this);
1132 CHECK_READY();
1133 /* @todo This is an ugly hack. There must be a function in IPRT for that. */
1134 pm::CollectorHAL *hal = pm::createHAL();
1135 if (!hal)
1136 return E_FAIL;
1137 ULONG tmp;
1138 int rc = hal->getHostMemoryUsage(&tmp, &tmp, aAvailable);
1139 *aAvailable /= 1024;
1140 delete hal;
1141 return rc;
1142}
1143
1144/**
1145 * Returns the name string of the host operating system
1146 *
1147 * @returns COM status code
1148 * @param os address of result variable
1149 */
1150STDMETHODIMP Host::COMGETTER(OperatingSystem)(BSTR *aOs)
1151{
1152 CheckComArgOutPointerValid(aOs);
1153 AutoWriteLock alock (this);
1154 CHECK_READY();
1155
1156 char szOSName[80];
1157 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szOSName, sizeof(szOSName));
1158 if (RT_FAILURE(vrc))
1159 return E_FAIL; /** @todo error reporting? */
1160 Bstr (szOSName).cloneTo (aOs);
1161 return S_OK;
1162}
1163
1164/**
1165 * Returns the version string of the host operating system
1166 *
1167 * @returns COM status code
1168 * @param os address of result variable
1169 */
1170STDMETHODIMP Host::COMGETTER(OSVersion)(BSTR *aVersion)
1171{
1172 CheckComArgOutPointerValid(aVersion);
1173 AutoWriteLock alock (this);
1174 CHECK_READY();
1175
1176 /* Get the OS release. Reserve some buffer space for the service pack. */
1177 char szOSRelease[128];
1178 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szOSRelease, sizeof(szOSRelease) - 32);
1179 if (RT_FAILURE(vrc))
1180 return E_FAIL; /** @todo error reporting? */
1181
1182 /* Append the service pack if present. */
1183 char szOSServicePack[80];
1184 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szOSServicePack, sizeof(szOSServicePack));
1185 if (RT_FAILURE(vrc))
1186 {
1187 if (vrc != VERR_NOT_SUPPORTED)
1188 return E_FAIL; /** @todo error reporting? */
1189 szOSServicePack[0] = '\0';
1190 }
1191 if (szOSServicePack[0] != '\0')
1192 {
1193 char *psz = strchr(szOSRelease, '\0');
1194 RTStrPrintf(psz, &szOSRelease[sizeof(szOSRelease)] - psz, "sp%s", szOSServicePack);
1195 }
1196
1197 Bstr (szOSRelease).cloneTo (aVersion);
1198 return S_OK;
1199}
1200
1201/**
1202 * Returns the current host time in milliseconds since 1970-01-01 UTC.
1203 *
1204 * @returns COM status code
1205 * @param time address of result variable
1206 */
1207STDMETHODIMP Host::COMGETTER(UTCTime)(LONG64 *aUTCTime)
1208{
1209 CheckComArgOutPointerValid(aUTCTime);
1210 AutoWriteLock alock (this);
1211 CHECK_READY();
1212 RTTIMESPEC now;
1213 *aUTCTime = RTTimeSpecGetMilli(RTTimeNow(&now));
1214 return S_OK;
1215}
1216
1217// IHost methods
1218////////////////////////////////////////////////////////////////////////////////
1219
1220#ifdef RT_OS_WINDOWS
1221
1222STDMETHODIMP
1223Host::CreateHostOnlyNetworkInterface (IHostNetworkInterface **aHostNetworkInterface,
1224 IProgress **aProgress)
1225{
1226 CheckComArgOutPointerValid(aHostNetworkInterface);
1227 CheckComArgOutPointerValid(aProgress);
1228
1229 AutoWriteLock alock (this);
1230 CHECK_READY();
1231
1232 int r = NetIfCreateHostOnlyNetworkInterface (mParent, aHostNetworkInterface, aProgress);
1233 if(RT_SUCCESS(r))
1234 {
1235 return S_OK;
1236 }
1237
1238 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1239}
1240
1241STDMETHODIMP
1242Host::RemoveHostOnlyNetworkInterface (IN_GUID aId,
1243 IHostNetworkInterface **aHostNetworkInterface,
1244 IProgress **aProgress)
1245{
1246 CheckComArgOutPointerValid(aHostNetworkInterface);
1247 CheckComArgOutPointerValid(aProgress);
1248
1249 AutoWriteLock alock (this);
1250 CHECK_READY();
1251
1252 /* first check whether an interface with the given name already exists */
1253 {
1254 ComPtr <IHostNetworkInterface> iface;
1255 if (FAILED (FindHostNetworkInterfaceById (aId, iface.asOutParam())))
1256 return setError (VBOX_E_OBJECT_NOT_FOUND,
1257 tr ("Host network interface with UUID {%RTuuid} does not exist"),
1258 Guid (aId).raw());
1259 }
1260
1261 int r = NetIfRemoveHostOnlyNetworkInterface (mParent, aId, aHostNetworkInterface, aProgress);
1262 if(RT_SUCCESS(r))
1263 {
1264 return S_OK;
1265 }
1266
1267 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1268}
1269
1270#endif /* RT_OS_WINDOWS */
1271
1272STDMETHODIMP Host::CreateUSBDeviceFilter (IN_BSTR aName, IHostUSBDeviceFilter **aFilter)
1273{
1274#ifdef VBOX_WITH_USB
1275 CheckComArgStrNotEmptyOrNull(aName);
1276 CheckComArgOutPointerValid(aFilter);
1277
1278 AutoWriteLock alock (this);
1279 CHECK_READY();
1280
1281 ComObjPtr <HostUSBDeviceFilter> filter;
1282 filter.createObject();
1283 HRESULT rc = filter->init (this, aName);
1284 ComAssertComRCRet (rc, rc);
1285 rc = filter.queryInterfaceTo (aFilter);
1286 AssertComRCReturn (rc, rc);
1287 return S_OK;
1288#else
1289 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1290 * extended error info to indicate that USB is simply not available
1291 * (w/o treating it as a failure), for example, as in OSE. */
1292 ReturnComNotImplemented();
1293#endif
1294}
1295
1296STDMETHODIMP Host::InsertUSBDeviceFilter (ULONG aPosition, IHostUSBDeviceFilter *aFilter)
1297{
1298#ifdef VBOX_WITH_USB
1299 CheckComArgNotNull(aFilter);
1300
1301 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1302 AutoWriteLock alock (this);
1303 CHECK_READY();
1304
1305 MultiResult rc = checkUSBProxyService();
1306 CheckComRCReturnRC (rc);
1307
1308 ComObjPtr <HostUSBDeviceFilter> filter = getDependentChild (aFilter);
1309 if (!filter)
1310 return setError (VBOX_E_INVALID_OBJECT_STATE,
1311 tr ("The given USB device filter is not created within "
1312 "this VirtualBox instance"));
1313
1314 if (filter->mInList)
1315 return setError (E_INVALIDARG,
1316 tr ("The given USB device filter is already in the list"));
1317
1318 /* iterate to the position... */
1319 USBDeviceFilterList::iterator it = mUSBDeviceFilters.begin();
1320 std::advance (it, aPosition);
1321 /* ...and insert */
1322 mUSBDeviceFilters.insert (it, filter);
1323 filter->mInList = true;
1324
1325 /* notify the proxy (only when the filter is active) */
1326 if (mUSBProxyService->isActive() && filter->data().mActive)
1327 {
1328 ComAssertRet (filter->id() == NULL, E_FAIL);
1329 filter->id() = mUSBProxyService->insertFilter (&filter->data().mUSBFilter);
1330 }
1331
1332 /* save the global settings */
1333 alock.unlock();
1334 return rc = mParent->saveSettings();
1335#else
1336 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1337 * extended error info to indicate that USB is simply not available
1338 * (w/o treating it as a failure), for example, as in OSE. */
1339 ReturnComNotImplemented();
1340#endif
1341}
1342
1343STDMETHODIMP Host::RemoveUSBDeviceFilter (ULONG aPosition, IHostUSBDeviceFilter **aFilter)
1344{
1345#ifdef VBOX_WITH_USB
1346 CheckComArgOutPointerValid(aFilter);
1347
1348 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1349 AutoWriteLock alock (this);
1350 CHECK_READY();
1351
1352 MultiResult rc = checkUSBProxyService();
1353 CheckComRCReturnRC (rc);
1354
1355 if (!mUSBDeviceFilters.size())
1356 return setError (E_INVALIDARG,
1357 tr ("The USB device filter list is empty"));
1358
1359 if (aPosition >= mUSBDeviceFilters.size())
1360 return setError (E_INVALIDARG,
1361 tr ("Invalid position: %lu (must be in range [0, %lu])"),
1362 aPosition, mUSBDeviceFilters.size() - 1);
1363
1364 ComObjPtr <HostUSBDeviceFilter> filter;
1365 {
1366 /* iterate to the position... */
1367 USBDeviceFilterList::iterator it = mUSBDeviceFilters.begin();
1368 std::advance (it, aPosition);
1369 /* ...get an element from there... */
1370 filter = *it;
1371 /* ...and remove */
1372 filter->mInList = false;
1373 mUSBDeviceFilters.erase (it);
1374 }
1375
1376 filter.queryInterfaceTo (aFilter);
1377
1378 /* notify the proxy (only when the filter is active) */
1379 if (mUSBProxyService->isActive() && filter->data().mActive)
1380 {
1381 ComAssertRet (filter->id() != NULL, E_FAIL);
1382 mUSBProxyService->removeFilter (filter->id());
1383 filter->id() = NULL;
1384 }
1385
1386 /* save the global settings */
1387 alock.unlock();
1388 return rc = mParent->saveSettings();
1389#else
1390 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1391 * extended error info to indicate that USB is simply not available
1392 * (w/o treating it as a failure), for example, as in OSE. */
1393 ReturnComNotImplemented();
1394#endif
1395}
1396
1397// public methods only for internal purposes
1398////////////////////////////////////////////////////////////////////////////////
1399
1400HRESULT Host::loadSettings (const settings::Key &aGlobal)
1401{
1402 using namespace settings;
1403
1404 AutoWriteLock alock (this);
1405 CHECK_READY();
1406
1407 AssertReturn (!aGlobal.isNull(), E_FAIL);
1408
1409 HRESULT rc = S_OK;
1410
1411#ifdef VBOX_WITH_USB
1412 Key::List filters = aGlobal.key ("USBDeviceFilters").keys ("DeviceFilter");
1413 for (Key::List::const_iterator it = filters.begin();
1414 it != filters.end(); ++ it)
1415 {
1416 Bstr name = (*it).stringValue ("name");
1417 bool active = (*it).value <bool> ("active");
1418
1419 Bstr vendorId = (*it).stringValue ("vendorId");
1420 Bstr productId = (*it).stringValue ("productId");
1421 Bstr revision = (*it).stringValue ("revision");
1422 Bstr manufacturer = (*it).stringValue ("manufacturer");
1423 Bstr product = (*it).stringValue ("product");
1424 Bstr serialNumber = (*it).stringValue ("serialNumber");
1425 Bstr port = (*it).stringValue ("port");
1426
1427 USBDeviceFilterAction_T action;
1428 action = USBDeviceFilterAction_Ignore;
1429 const char *actionStr = (*it).stringValue ("action");
1430 if (strcmp (actionStr, "Ignore") == 0)
1431 action = USBDeviceFilterAction_Ignore;
1432 else
1433 if (strcmp (actionStr, "Hold") == 0)
1434 action = USBDeviceFilterAction_Hold;
1435 else
1436 AssertMsgFailed (("Invalid action: '%s'\n", actionStr));
1437
1438 ComObjPtr <HostUSBDeviceFilter> filterObj;
1439 filterObj.createObject();
1440 rc = filterObj->init (this,
1441 name, active, vendorId, productId, revision,
1442 manufacturer, product, serialNumber, port,
1443 action);
1444 /* error info is set by init() when appropriate */
1445 CheckComRCBreakRC (rc);
1446
1447 mUSBDeviceFilters.push_back (filterObj);
1448 filterObj->mInList = true;
1449
1450 /* notify the proxy (only when the filter is active) */
1451 if (filterObj->data().mActive)
1452 {
1453 HostUSBDeviceFilter *flt = filterObj; /* resolve ambiguity */
1454 flt->id() = mUSBProxyService->insertFilter (&filterObj->data().mUSBFilter);
1455 }
1456 }
1457#endif /* VBOX_WITH_USB */
1458
1459 return rc;
1460}
1461
1462HRESULT Host::saveSettings (settings::Key &aGlobal)
1463{
1464 using namespace settings;
1465
1466 AutoWriteLock alock (this);
1467 CHECK_READY();
1468
1469 ComAssertRet (!aGlobal.isNull(), E_FAIL);
1470
1471#ifdef VBOX_WITH_USB
1472 /* first, delete the entry */
1473 Key filters = aGlobal.findKey ("USBDeviceFilters");
1474 if (!filters.isNull())
1475 filters.zap();
1476 /* then, recreate it */
1477 filters = aGlobal.createKey ("USBDeviceFilters");
1478
1479 USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
1480 while (it != mUSBDeviceFilters.end())
1481 {
1482 AutoWriteLock filterLock (*it);
1483 const HostUSBDeviceFilter::Data &data = (*it)->data();
1484
1485 Key filter = filters.appendKey ("DeviceFilter");
1486
1487 filter.setValue <Bstr> ("name", data.mName);
1488 filter.setValue <bool> ("active", !!data.mActive);
1489
1490 /* all are optional */
1491 Bstr str;
1492 (*it)->COMGETTER (VendorId) (str.asOutParam());
1493 if (!str.isNull())
1494 filter.setValue <Bstr> ("vendorId", str);
1495
1496 (*it)->COMGETTER (ProductId) (str.asOutParam());
1497 if (!str.isNull())
1498 filter.setValue <Bstr> ("productId", str);
1499
1500 (*it)->COMGETTER (Revision) (str.asOutParam());
1501 if (!str.isNull())
1502 filter.setValue <Bstr> ("revision", str);
1503
1504 (*it)->COMGETTER (Manufacturer) (str.asOutParam());
1505 if (!str.isNull())
1506 filter.setValue <Bstr> ("manufacturer", str);
1507
1508 (*it)->COMGETTER (Product) (str.asOutParam());
1509 if (!str.isNull())
1510 filter.setValue <Bstr> ("product", str);
1511
1512 (*it)->COMGETTER (SerialNumber) (str.asOutParam());
1513 if (!str.isNull())
1514 filter.setValue <Bstr> ("serialNumber", str);
1515
1516 (*it)->COMGETTER (Port) (str.asOutParam());
1517 if (!str.isNull())
1518 filter.setValue <Bstr> ("port", str);
1519
1520 /* action is mandatory */
1521 USBDeviceFilterAction_T action = USBDeviceFilterAction_Null;
1522 (*it)->COMGETTER (Action) (&action);
1523 if (action == USBDeviceFilterAction_Ignore)
1524 filter.setStringValue ("action", "Ignore");
1525 else if (action == USBDeviceFilterAction_Hold)
1526 filter.setStringValue ("action", "Hold");
1527 else
1528 AssertMsgFailed (("Invalid action: %d\n", action));
1529
1530 ++ it;
1531 }
1532#endif /* VBOX_WITH_USB */
1533
1534 return S_OK;
1535}
1536
1537#ifdef VBOX_WITH_USB
1538/**
1539 * Called by setter methods of all USB device filters.
1540 */
1541HRESULT Host::onUSBDeviceFilterChange (HostUSBDeviceFilter *aFilter,
1542 BOOL aActiveChanged /* = FALSE */)
1543{
1544 AutoWriteLock alock (this);
1545 CHECK_READY();
1546
1547 if (aFilter->mInList)
1548 {
1549 if (aActiveChanged)
1550 {
1551 // insert/remove the filter from the proxy
1552 if (aFilter->data().mActive)
1553 {
1554 ComAssertRet (aFilter->id() == NULL, E_FAIL);
1555 aFilter->id() = mUSBProxyService->insertFilter (&aFilter->data().mUSBFilter);
1556 }
1557 else
1558 {
1559 ComAssertRet (aFilter->id() != NULL, E_FAIL);
1560 mUSBProxyService->removeFilter (aFilter->id());
1561 aFilter->id() = NULL;
1562 }
1563 }
1564 else
1565 {
1566 if (aFilter->data().mActive)
1567 {
1568 // update the filter in the proxy
1569 ComAssertRet (aFilter->id() != NULL, E_FAIL);
1570 mUSBProxyService->removeFilter (aFilter->id());
1571 aFilter->id() = mUSBProxyService->insertFilter (&aFilter->data().mUSBFilter);
1572 }
1573 }
1574
1575 // save the global settings... yeah, on every single filter property change
1576 alock.unlock();
1577 return mParent->saveSettings();
1578 }
1579
1580 return S_OK;
1581}
1582
1583
1584/**
1585 * Interface for obtaining a copy of the USBDeviceFilterList,
1586 * used by the USBProxyService.
1587 *
1588 * @param aGlobalFilters Where to put the global filter list copy.
1589 * @param aMachines Where to put the machine vector.
1590 */
1591void Host::getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters, VirtualBox::SessionMachineVector *aMachines)
1592{
1593 AutoWriteLock alock (this);
1594
1595 mParent->getOpenedMachines (*aMachines);
1596 *aGlobalFilters = mUSBDeviceFilters;
1597}
1598
1599#endif /* VBOX_WITH_USB */
1600
1601// private methods
1602////////////////////////////////////////////////////////////////////////////////
1603
1604#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
1605/* Solaris hosts, loading libhal at runtime */
1606
1607/**
1608 * Helper function to query the hal subsystem for information about DVD drives attached to the
1609 * system.
1610 *
1611 * @returns true if information was successfully obtained, false otherwise
1612 * @retval list drives found will be attached to this list
1613 */
1614bool Host::getDVDInfoFromHal(std::list <ComObjPtr <HostDVDDrive> > &list)
1615{
1616 bool halSuccess = false;
1617 DBusError dbusError;
1618 if (!gLibHalCheckPresence())
1619 return false;
1620 gDBusErrorInit (&dbusError);
1621 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
1622 if (dbusConnection != 0)
1623 {
1624 LibHalContext *halContext = gLibHalCtxNew();
1625 if (halContext != 0)
1626 {
1627 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
1628 {
1629 if (gLibHalCtxInit(halContext, &dbusError))
1630 {
1631 int numDevices;
1632 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
1633 "storage.drive_type", "cdrom",
1634 &numDevices, &dbusError);
1635 if (halDevices != 0)
1636 {
1637 /* Hal is installed and working, so if no devices are reported, assume
1638 that there are none. */
1639 halSuccess = true;
1640 for (int i = 0; i < numDevices; i++)
1641 {
1642 char *devNode = gLibHalDeviceGetPropertyString(halContext,
1643 halDevices[i], "block.device", &dbusError);
1644#ifdef RT_OS_SOLARIS
1645 /* The CD/DVD ioctls work only for raw device nodes. */
1646 char *tmp = getfullrawname(devNode);
1647 gLibHalFreeString(devNode);
1648 devNode = tmp;
1649#endif
1650 if (devNode != 0)
1651 {
1652// if (validateDevice(devNode, true))
1653// {
1654 Utf8Str description;
1655 char *vendor, *product;
1656 /* We do not check the error here, as this field may
1657 not even exist. */
1658 vendor = gLibHalDeviceGetPropertyString(halContext,
1659 halDevices[i], "info.vendor", 0);
1660 product = gLibHalDeviceGetPropertyString(halContext,
1661 halDevices[i], "info.product", &dbusError);
1662 if ((product != 0 && product[0] != 0))
1663 {
1664 if ((vendor != 0) && (vendor[0] != 0))
1665 {
1666 description = Utf8StrFmt ("%s %s",
1667 vendor, product);
1668 }
1669 else
1670 {
1671 description = product;
1672 }
1673 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
1674 hostDVDDriveObj.createObject();
1675 hostDVDDriveObj->init (Bstr (devNode),
1676 Bstr (halDevices[i]),
1677 Bstr (description));
1678 list.push_back (hostDVDDriveObj);
1679 }
1680 else
1681 {
1682 if (product == 0)
1683 {
1684 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
1685 halDevices[i], dbusError.name, dbusError.message));
1686 gDBusErrorFree(&dbusError);
1687 }
1688 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
1689 hostDVDDriveObj.createObject();
1690 hostDVDDriveObj->init (Bstr (devNode),
1691 Bstr (halDevices[i]));
1692 list.push_back (hostDVDDriveObj);
1693 }
1694 if (vendor != 0)
1695 {
1696 gLibHalFreeString(vendor);
1697 }
1698 if (product != 0)
1699 {
1700 gLibHalFreeString(product);
1701 }
1702// }
1703// else
1704// {
1705// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
1706// }
1707#ifndef RT_OS_SOLARIS
1708 gLibHalFreeString(devNode);
1709#else
1710 free(devNode);
1711#endif
1712 }
1713 else
1714 {
1715 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
1716 halDevices[i], dbusError.name, dbusError.message));
1717 gDBusErrorFree(&dbusError);
1718 }
1719 }
1720 gLibHalFreeStringArray(halDevices);
1721 }
1722 else
1723 {
1724 LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1725 gDBusErrorFree(&dbusError);
1726 }
1727 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
1728 {
1729 LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1730 gDBusErrorFree(&dbusError);
1731 }
1732 }
1733 else
1734 {
1735 LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1736 gDBusErrorFree(&dbusError);
1737 }
1738 gLibHalCtxFree(halContext);
1739 }
1740 else
1741 {
1742 LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
1743 }
1744 }
1745 else
1746 {
1747 LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
1748 }
1749 gDBusConnectionUnref(dbusConnection);
1750 }
1751 else
1752 {
1753 LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1754 gDBusErrorFree(&dbusError);
1755 }
1756 return halSuccess;
1757}
1758
1759
1760/**
1761 * Helper function to query the hal subsystem for information about floppy drives attached to the
1762 * system.
1763 *
1764 * @returns true if information was successfully obtained, false otherwise
1765 * @retval list drives found will be attached to this list
1766 */
1767bool Host::getFloppyInfoFromHal(std::list <ComObjPtr <HostFloppyDrive> > &list)
1768{
1769 bool halSuccess = false;
1770 DBusError dbusError;
1771 if (!gLibHalCheckPresence())
1772 return false;
1773 gDBusErrorInit (&dbusError);
1774 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
1775 if (dbusConnection != 0)
1776 {
1777 LibHalContext *halContext = gLibHalCtxNew();
1778 if (halContext != 0)
1779 {
1780 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
1781 {
1782 if (gLibHalCtxInit(halContext, &dbusError))
1783 {
1784 int numDevices;
1785 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
1786 "storage.drive_type", "floppy",
1787 &numDevices, &dbusError);
1788 if (halDevices != 0)
1789 {
1790 /* Hal is installed and working, so if no devices are reported, assume
1791 that there are none. */
1792 halSuccess = true;
1793 for (int i = 0; i < numDevices; i++)
1794 {
1795 char *driveType = gLibHalDeviceGetPropertyString(halContext,
1796 halDevices[i], "storage.drive_type", 0);
1797 if (driveType != 0)
1798 {
1799 if (strcmp(driveType, "floppy") != 0)
1800 {
1801 gLibHalFreeString(driveType);
1802 continue;
1803 }
1804 gLibHalFreeString(driveType);
1805 }
1806 else
1807 {
1808 /* An error occurred. The attribute "storage.drive_type"
1809 probably didn't exist. */
1810 continue;
1811 }
1812 char *devNode = gLibHalDeviceGetPropertyString(halContext,
1813 halDevices[i], "block.device", &dbusError);
1814 if (devNode != 0)
1815 {
1816// if (validateDevice(devNode, false))
1817// {
1818 Utf8Str description;
1819 char *vendor, *product;
1820 /* We do not check the error here, as this field may
1821 not even exist. */
1822 vendor = gLibHalDeviceGetPropertyString(halContext,
1823 halDevices[i], "info.vendor", 0);
1824 product = gLibHalDeviceGetPropertyString(halContext,
1825 halDevices[i], "info.product", &dbusError);
1826 if ((product != 0) && (product[0] != 0))
1827 {
1828 if ((vendor != 0) && (vendor[0] != 0))
1829 {
1830 description = Utf8StrFmt ("%s %s",
1831 vendor, product);
1832 }
1833 else
1834 {
1835 description = product;
1836 }
1837 ComObjPtr <HostFloppyDrive> hostFloppyDrive;
1838 hostFloppyDrive.createObject();
1839 hostFloppyDrive->init (Bstr (devNode),
1840 Bstr (halDevices[i]),
1841 Bstr (description));
1842 list.push_back (hostFloppyDrive);
1843 }
1844 else
1845 {
1846 if (product == 0)
1847 {
1848 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
1849 halDevices[i], dbusError.name, dbusError.message));
1850 gDBusErrorFree(&dbusError);
1851 }
1852 ComObjPtr <HostFloppyDrive> hostFloppyDrive;
1853 hostFloppyDrive.createObject();
1854 hostFloppyDrive->init (Bstr (devNode),
1855 Bstr (halDevices[i]));
1856 list.push_back (hostFloppyDrive);
1857 }
1858 if (vendor != 0)
1859 {
1860 gLibHalFreeString(vendor);
1861 }
1862 if (product != 0)
1863 {
1864 gLibHalFreeString(product);
1865 }
1866// }
1867// else
1868// {
1869// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
1870// }
1871 gLibHalFreeString(devNode);
1872 }
1873 else
1874 {
1875 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
1876 halDevices[i], dbusError.name, dbusError.message));
1877 gDBusErrorFree(&dbusError);
1878 }
1879 }
1880 gLibHalFreeStringArray(halDevices);
1881 }
1882 else
1883 {
1884 LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1885 gDBusErrorFree(&dbusError);
1886 }
1887 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
1888 {
1889 LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1890 gDBusErrorFree(&dbusError);
1891 }
1892 }
1893 else
1894 {
1895 LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1896 gDBusErrorFree(&dbusError);
1897 }
1898 gLibHalCtxFree(halContext);
1899 }
1900 else
1901 {
1902 LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
1903 }
1904 }
1905 else
1906 {
1907 LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
1908 }
1909 gDBusConnectionUnref(dbusConnection);
1910 }
1911 else
1912 {
1913 LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1914 gDBusErrorFree(&dbusError);
1915 }
1916 return halSuccess;
1917}
1918#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
1919
1920#if defined(RT_OS_SOLARIS)
1921
1922/**
1923 * Helper function to parse the given mount file and add found entries
1924 */
1925void Host::parseMountTable(char *mountTable, std::list <ComObjPtr <HostDVDDrive> > &list)
1926{
1927#ifdef RT_OS_LINUX
1928 FILE *mtab = setmntent(mountTable, "r");
1929 if (mtab)
1930 {
1931 struct mntent *mntent;
1932 char *mnt_type;
1933 char *mnt_dev;
1934 char *tmp;
1935 while ((mntent = getmntent(mtab)))
1936 {
1937 mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
1938 mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
1939 strcpy(mnt_type, mntent->mnt_type);
1940 strcpy(mnt_dev, mntent->mnt_fsname);
1941 // supermount fs case
1942 if (strcmp(mnt_type, "supermount") == 0)
1943 {
1944 tmp = strstr(mntent->mnt_opts, "fs=");
1945 if (tmp)
1946 {
1947 free(mnt_type);
1948 mnt_type = strdup(tmp + strlen("fs="));
1949 if (mnt_type)
1950 {
1951 tmp = strchr(mnt_type, ',');
1952 if (tmp)
1953 *tmp = '\0';
1954 }
1955 }
1956 tmp = strstr(mntent->mnt_opts, "dev=");
1957 if (tmp)
1958 {
1959 free(mnt_dev);
1960 mnt_dev = strdup(tmp + strlen("dev="));
1961 if (mnt_dev)
1962 {
1963 tmp = strchr(mnt_dev, ',');
1964 if (tmp)
1965 *tmp = '\0';
1966 }
1967 }
1968 }
1969 // use strstr here to cover things fs types like "udf,iso9660"
1970 if (strstr(mnt_type, "iso9660") == 0)
1971 {
1972 /** @todo check whether we've already got the drive in our list! */
1973 if (validateDevice(mnt_dev, true))
1974 {
1975 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
1976 hostDVDDriveObj.createObject();
1977 hostDVDDriveObj->init (Bstr (mnt_dev));
1978 list.push_back (hostDVDDriveObj);
1979 }
1980 }
1981 free(mnt_dev);
1982 free(mnt_type);
1983 }
1984 endmntent(mtab);
1985 }
1986#else // RT_OS_SOLARIS
1987 FILE *mntFile = fopen(mountTable, "r");
1988 if (mntFile)
1989 {
1990 struct mnttab mntTab;
1991 while (getmntent(mntFile, &mntTab) == 0)
1992 {
1993 char *mountName = strdup(mntTab.mnt_special);
1994 char *mountPoint = strdup(mntTab.mnt_mountp);
1995 char *mountFSType = strdup(mntTab.mnt_fstype);
1996
1997 // skip devices we are not interested in
1998 if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
1999 (*mountFSType && (strcmp(mountFSType, "devfs") != 0 && // skip devfs (i.e. /devices)
2000 strcmp(mountFSType, "dev") != 0 && // skip dev (i.e. /dev)
2001 strcmp(mountFSType, "lofs") != 0)) && // skip loop-back file-system (lofs)
2002 (*mountPoint && strcmp(mountPoint, "/") != 0)) // skip point '/' (Can CD/DVD be mounted at '/' ???)
2003 {
2004 char *rawDevName = getfullrawname(mountName);
2005 if (validateDevice(rawDevName, true))
2006 {
2007 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
2008 hostDVDDriveObj.createObject();
2009 hostDVDDriveObj->init (Bstr (rawDevName));
2010 list.push_back (hostDVDDriveObj);
2011 }
2012 free(rawDevName);
2013 }
2014
2015 free(mountName);
2016 free(mountPoint);
2017 free(mountFSType);
2018 }
2019
2020 fclose(mntFile);
2021 }
2022#endif
2023}
2024
2025/**
2026 * Helper function to check whether the given device node is a valid drive
2027 */
2028bool Host::validateDevice(const char *deviceNode, bool isCDROM)
2029{
2030 struct stat statInfo;
2031 bool retValue = false;
2032
2033 // sanity check
2034 if (!deviceNode)
2035 {
2036 return false;
2037 }
2038
2039 // first a simple stat() call
2040 if (stat(deviceNode, &statInfo) < 0)
2041 {
2042 return false;
2043 } else
2044 {
2045 if (isCDROM)
2046 {
2047 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2048 {
2049 int fileHandle;
2050 // now try to open the device
2051 fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
2052 if (fileHandle >= 0)
2053 {
2054 cdrom_subchnl cdChannelInfo;
2055 cdChannelInfo.cdsc_format = CDROM_MSF;
2056 // this call will finally reveal the whole truth
2057#ifdef RT_OS_LINUX
2058 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2059 (errno == EIO) || (errno == ENOENT) ||
2060 (errno == EINVAL) || (errno == ENOMEDIUM))
2061#else
2062 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2063 (errno == EIO) || (errno == ENOENT) ||
2064 (errno == EINVAL))
2065#endif
2066 {
2067 retValue = true;
2068 }
2069 close(fileHandle);
2070 }
2071 }
2072 } else
2073 {
2074 // floppy case
2075 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2076 {
2077 /// @todo do some more testing, maybe a nice IOCTL!
2078 retValue = true;
2079 }
2080 }
2081 }
2082 return retValue;
2083}
2084#endif // RT_OS_SOLARIS
2085
2086#ifdef VBOX_WITH_USB
2087/**
2088 * Checks for the presense and status of the USB Proxy Service.
2089 * Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
2090 * warning) if the proxy service is not available due to the way the host is
2091 * configured (at present, that means that usbfs and hal/DBus are not
2092 * available on a Linux host) or E_FAIL and a corresponding error message
2093 * otherwise. Intended to be used by methods that rely on the Proxy Service
2094 * availability.
2095 *
2096 * @note This method may return a warning result code. It is recommended to use
2097 * MultiError to store the return value.
2098 *
2099 * @note Locks this object for reading.
2100 */
2101HRESULT Host::checkUSBProxyService()
2102{
2103 AutoWriteLock alock (this);
2104 CHECK_READY();
2105
2106 AssertReturn (mUSBProxyService, E_FAIL);
2107 if (!mUSBProxyService->isActive())
2108 {
2109 /* disable the USB controller completely to avoid assertions if the
2110 * USB proxy service could not start. */
2111
2112 if (mUSBProxyService->getLastError() == VERR_FILE_NOT_FOUND)
2113 return setWarning (E_FAIL,
2114 tr ("Could not load the Host USB Proxy Service (%Rrc). "
2115 "The service might not be installed on the host computer"),
2116 mUSBProxyService->getLastError());
2117 if (mUSBProxyService->getLastError() == VINF_SUCCESS)
2118#ifdef RT_OS_LINUX
2119 return setWarning (VBOX_E_HOST_ERROR,
2120# ifdef VBOX_WITH_DBUS
2121 tr ("The USB Proxy Service could not be started, because neither the USB file system (usbfs) nor the hardware information service (hal) is available")
2122# else
2123 tr ("The USB Proxy Service could not be started, because the USB file system (usbfs) is not available")
2124# endif
2125 );
2126#else /* !RT_OS_LINUX */
2127 return setWarning (E_FAIL,
2128 tr ("The USB Proxy Service has not yet been ported to this host"));
2129#endif /* !RT_OS_LINUX */
2130 return setWarning (E_FAIL,
2131 tr ("Could not load the Host USB Proxy service (%Rrc)"),
2132 mUSBProxyService->getLastError());
2133 }
2134
2135 return S_OK;
2136}
2137#endif /* VBOX_WITH_USB */
2138
2139#ifdef VBOX_WITH_RESOURCE_USAGE_API
2140void Host::registerMetrics (PerformanceCollector *aCollector)
2141{
2142 pm::CollectorHAL *hal = aCollector->getHAL();
2143 /* Create sub metrics */
2144 pm::SubMetric *cpuLoadUser = new pm::SubMetric ("CPU/Load/User",
2145 "Percentage of processor time spent in user mode.");
2146 pm::SubMetric *cpuLoadKernel = new pm::SubMetric ("CPU/Load/Kernel",
2147 "Percentage of processor time spent in kernel mode.");
2148 pm::SubMetric *cpuLoadIdle = new pm::SubMetric ("CPU/Load/Idle",
2149 "Percentage of processor time spent idling.");
2150 pm::SubMetric *cpuMhzSM = new pm::SubMetric ("CPU/MHz",
2151 "Average of current frequency of all processors.");
2152 pm::SubMetric *ramUsageTotal = new pm::SubMetric ("RAM/Usage/Total",
2153 "Total physical memory installed.");
2154 pm::SubMetric *ramUsageUsed = new pm::SubMetric ("RAM/Usage/Used",
2155 "Physical memory currently occupied.");
2156 pm::SubMetric *ramUsageFree = new pm::SubMetric ("RAM/Usage/Free",
2157 "Physical memory currently available to applications.");
2158 /* Create and register base metrics */
2159 IUnknown *objptr;
2160 ComObjPtr <Host> tmp = this;
2161 tmp.queryInterfaceTo (&objptr);
2162 pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw (hal, objptr, cpuLoadUser, cpuLoadKernel,
2163 cpuLoadIdle);
2164 aCollector->registerBaseMetric (cpuLoad);
2165 pm::BaseMetric *cpuMhz = new pm::HostCpuMhz (hal, objptr, cpuMhzSM);
2166 aCollector->registerBaseMetric (cpuMhz);
2167 pm::BaseMetric *ramUsage = new pm::HostRamUsage (hal, objptr, ramUsageTotal, ramUsageUsed,
2168 ramUsageFree);
2169 aCollector->registerBaseMetric (ramUsage);
2170
2171 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser, 0));
2172 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser,
2173 new pm::AggregateAvg()));
2174 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser,
2175 new pm::AggregateMin()));
2176 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser,
2177 new pm::AggregateMax()));
2178
2179 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel, 0));
2180 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel,
2181 new pm::AggregateAvg()));
2182 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel,
2183 new pm::AggregateMin()));
2184 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel,
2185 new pm::AggregateMax()));
2186
2187 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle, 0));
2188 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle,
2189 new pm::AggregateAvg()));
2190 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle,
2191 new pm::AggregateMin()));
2192 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle,
2193 new pm::AggregateMax()));
2194
2195 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM, 0));
2196 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM,
2197 new pm::AggregateAvg()));
2198 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM,
2199 new pm::AggregateMin()));
2200 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM,
2201 new pm::AggregateMax()));
2202
2203 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal, 0));
2204 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal,
2205 new pm::AggregateAvg()));
2206 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal,
2207 new pm::AggregateMin()));
2208 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal,
2209 new pm::AggregateMax()));
2210
2211 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed, 0));
2212 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed,
2213 new pm::AggregateAvg()));
2214 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed,
2215 new pm::AggregateMin()));
2216 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed,
2217 new pm::AggregateMax()));
2218
2219 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree, 0));
2220 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree,
2221 new pm::AggregateAvg()));
2222 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree,
2223 new pm::AggregateMin()));
2224 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree,
2225 new pm::AggregateMax()));
2226};
2227
2228void Host::unregisterMetrics (PerformanceCollector *aCollector)
2229{
2230 aCollector->unregisterMetricsFor (this);
2231 aCollector->unregisterBaseMetricsFor (this);
2232};
2233#endif /* VBOX_WITH_RESOURCE_USAGE_API */
2234
2235STDMETHODIMP Host::FindHostDVDDrive(IN_BSTR aName, IHostDVDDrive **aDrive)
2236{
2237 CheckComArgNotNull(aName);
2238 CheckComArgOutPointerValid(aDrive);
2239
2240 *aDrive = NULL;
2241
2242 SafeIfaceArray <IHostDVDDrive> drivevec;
2243 HRESULT rc = COMGETTER(DVDDrives) (ComSafeArrayAsOutParam(drivevec));
2244 CheckComRCReturnRC (rc);
2245
2246 for (size_t i = 0; i < drivevec.size(); ++i)
2247 {
2248 Bstr name;
2249 rc = drivevec[i]->COMGETTER(Name) (name.asOutParam());
2250 CheckComRCReturnRC (rc);
2251 if (name == aName)
2252 {
2253 ComObjPtr<HostDVDDrive> found;
2254 found.createObject();
2255 Bstr udi, description;
2256 rc = drivevec[i]->COMGETTER(Udi) (udi.asOutParam());
2257 CheckComRCReturnRC (rc);
2258 rc = drivevec[i]->COMGETTER(Description) (description.asOutParam());
2259 CheckComRCReturnRC (rc);
2260 found->init(name, udi, description);
2261 return found.queryInterfaceTo(aDrive);
2262 }
2263 }
2264
2265 return setError (VBOX_E_OBJECT_NOT_FOUND, HostDVDDrive::tr (
2266 "The host DVD drive named '%ls' could not be found"), aName);
2267}
2268
2269STDMETHODIMP Host::FindHostFloppyDrive(IN_BSTR aName, IHostFloppyDrive **aDrive)
2270{
2271 CheckComArgNotNull(aName);
2272 CheckComArgOutPointerValid(aDrive);
2273
2274 *aDrive = NULL;
2275
2276 SafeIfaceArray <IHostFloppyDrive> drivevec;
2277 HRESULT rc = COMGETTER(FloppyDrives) (ComSafeArrayAsOutParam(drivevec));
2278 CheckComRCReturnRC (rc);
2279
2280 for (size_t i = 0; i < drivevec.size(); ++i)
2281 {
2282 Bstr name;
2283 rc = drivevec[i]->COMGETTER(Name) (name.asOutParam());
2284 CheckComRCReturnRC (rc);
2285 if (name == aName)
2286 {
2287 ComObjPtr<HostFloppyDrive> found;
2288 found.createObject();
2289 Bstr udi, description;
2290 rc = drivevec[i]->COMGETTER(Udi) (udi.asOutParam());
2291 CheckComRCReturnRC (rc);
2292 rc = drivevec[i]->COMGETTER(Description) (description.asOutParam());
2293 CheckComRCReturnRC (rc);
2294 found->init(name, udi, description);
2295 return found.queryInterfaceTo(aDrive);
2296 }
2297 }
2298
2299 return setError (VBOX_E_OBJECT_NOT_FOUND, HostFloppyDrive::tr (
2300 "The host floppy drive named '%ls' could not be found"), aName);
2301}
2302
2303STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInterface **networkInterface)
2304{
2305#ifndef VBOX_WITH_HOSTNETIF_API
2306 return E_NOTIMPL;
2307#else
2308 if (!name)
2309 return E_INVALIDARG;
2310 if (!networkInterface)
2311 return E_POINTER;
2312
2313 *networkInterface = NULL;
2314 ComObjPtr <HostNetworkInterface> found;
2315 std::list <ComObjPtr <HostNetworkInterface> > list;
2316 int rc = NetIfList(list);
2317 if (RT_FAILURE(rc))
2318 {
2319 Log(("Failed to get host network interface list with rc=%Vrc\n", rc));
2320 return E_FAIL;
2321 }
2322 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
2323 for (it = list.begin(); it != list.end(); ++it)
2324 {
2325 Bstr n;
2326 (*it)->COMGETTER(Name) (n.asOutParam());
2327 if (n == name)
2328 found = *it;
2329 }
2330
2331 if (!found)
2332 return setError (E_INVALIDARG, HostNetworkInterface::tr (
2333 "The host network interface with the given name could not be found"));
2334
2335 found->setVirtualBox(mParent);
2336
2337 return found.queryInterfaceTo (networkInterface);
2338#endif
2339}
2340
2341STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_GUID id, IHostNetworkInterface **networkInterface)
2342{
2343#ifndef VBOX_WITH_HOSTNETIF_API
2344 return E_NOTIMPL;
2345#else
2346 if (Guid(id).isEmpty())
2347 return E_INVALIDARG;
2348 if (!networkInterface)
2349 return E_POINTER;
2350
2351 *networkInterface = NULL;
2352 ComObjPtr <HostNetworkInterface> found;
2353 std::list <ComObjPtr <HostNetworkInterface> > list;
2354 int rc = NetIfList(list);
2355 if (RT_FAILURE(rc))
2356 {
2357 Log(("Failed to get host network interface list with rc=%Vrc\n", rc));
2358 return E_FAIL;
2359 }
2360 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
2361 for (it = list.begin(); it != list.end(); ++it)
2362 {
2363 Guid g;
2364 (*it)->COMGETTER(Id) (g.asOutParam());
2365 if (g == Guid(id))
2366 found = *it;
2367 }
2368
2369 if (!found)
2370 return setError (E_INVALIDARG, HostNetworkInterface::tr (
2371 "The host network interface with the given GUID could not be found"));
2372
2373 found->setVirtualBox(mParent);
2374
2375 return found.queryInterfaceTo (networkInterface);
2376#endif
2377}
2378
2379STDMETHODIMP Host::FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_T type, ComSafeArrayOut (IHostNetworkInterface *, aNetworkInterfaces))
2380{
2381 std::list <ComObjPtr <HostNetworkInterface> > allList;
2382 int rc = NetIfList(allList);
2383 if(RT_FAILURE(rc))
2384 return E_FAIL;
2385
2386 std::list <ComObjPtr <HostNetworkInterface> > resultList;
2387
2388 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
2389 for (it = allList.begin(); it != allList.end(); ++it)
2390 {
2391 HostNetworkInterfaceType_T t;
2392 HRESULT hr = (*it)->COMGETTER(InterfaceType)(&t);
2393 if(FAILED(hr))
2394 return hr;
2395
2396 if(t == type)
2397 {
2398 (*it)->setVirtualBox(mParent);
2399 resultList.push_back (*it);
2400 }
2401 }
2402
2403 SafeIfaceArray <IHostNetworkInterface> filteredNetworkInterfaces (resultList);
2404 filteredNetworkInterfaces.detachTo (ComSafeArrayOutArg (aNetworkInterfaces));
2405
2406 return S_OK;
2407}
2408
2409STDMETHODIMP Host::FindUSBDeviceByAddress (IN_BSTR aAddress, IHostUSBDevice **aDevice)
2410{
2411#ifdef VBOX_WITH_USB
2412 CheckComArgNotNull(aAddress);
2413 CheckComArgOutPointerValid(aDevice);
2414
2415 *aDevice = NULL;
2416
2417 SafeIfaceArray <IHostUSBDevice> devsvec;
2418 HRESULT rc = COMGETTER(USBDevices) (ComSafeArrayAsOutParam(devsvec));
2419 CheckComRCReturnRC (rc);
2420
2421 for (size_t i = 0; i < devsvec.size(); ++i)
2422 {
2423 Bstr address;
2424 rc = devsvec[i]->COMGETTER(Address) (address.asOutParam());
2425 CheckComRCReturnRC (rc);
2426 if (address == aAddress)
2427 {
2428 return ComObjPtr<IHostUSBDevice> (devsvec[i]).queryInterfaceTo (aDevice);
2429 }
2430 }
2431
2432 return setErrorNoLog (VBOX_E_OBJECT_NOT_FOUND, tr (
2433 "Could not find a USB device with address '%ls'"),
2434 aAddress);
2435
2436#else /* !VBOX_WITH_USB */
2437 return E_NOTIMPL;
2438#endif /* !VBOX_WITH_USB */
2439}
2440
2441STDMETHODIMP Host::FindUSBDeviceById (IN_GUID aId, IHostUSBDevice **aDevice)
2442{
2443#ifdef VBOX_WITH_USB
2444 CheckComArgExpr(aId, Guid (aId).isEmpty() == false);
2445 CheckComArgOutPointerValid(aDevice);
2446
2447 *aDevice = NULL;
2448
2449 SafeIfaceArray <IHostUSBDevice> devsvec;
2450 HRESULT rc = COMGETTER(USBDevices) (ComSafeArrayAsOutParam(devsvec));
2451 CheckComRCReturnRC (rc);
2452
2453 for (size_t i = 0; i < devsvec.size(); ++i)
2454 {
2455 Guid id;
2456 rc = devsvec[i]->COMGETTER(Id) (id.asOutParam());
2457 CheckComRCReturnRC (rc);
2458 if (id == aId)
2459 {
2460 return ComObjPtr<IHostUSBDevice> (devsvec[i]).queryInterfaceTo (aDevice);
2461 }
2462 }
2463
2464 return setErrorNoLog (VBOX_E_OBJECT_NOT_FOUND, tr (
2465 "Could not find a USB device with uuid {%RTuuid}"),
2466 Guid (aId).raw());
2467
2468#else /* !VBOX_WITH_USB */
2469 return E_NOTIMPL;
2470#endif /* !VBOX_WITH_USB */
2471}
2472
2473
2474/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette