VirtualBox

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

Last change on this file since 17879 was 17684, checked in by vboxsync, 16 years ago

#3551: “Main: Replace remaining collections with safe arrays”
Replaced HostUSBDeviceCollection. Reviewed/Okayed by dmik, sunlover.

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