VirtualBox

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

Last change on this file since 18485 was 18252, checked in by vboxsync, 16 years ago

Main: performance header cleanup.

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