VirtualBox

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

Last change on this file since 17581 was 17494, checked in by vboxsync, 16 years ago

NetIf/win: moved Create/Remove hostonly if to NetIf API, some API fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 87.7 KB
Line 
1/* $Id: HostImpl.cpp 17494 2009-03-06 16:55:44Z 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)(IHostUSBDeviceCollection **aUSBDevices)
1085{
1086#ifdef VBOX_WITH_USB
1087 CheckComArgOutPointerValid(aUSBDevices);
1088
1089 AutoWriteLock alock (this);
1090 CHECK_READY();
1091
1092 MultiResult rc = checkUSBProxyService();
1093 CheckComRCReturnRC (rc);
1094
1095 return mUSBProxyService->getDeviceCollection (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 (IN_BSTR aName,
1319 IHostNetworkInterface **aHostNetworkInterface,
1320 IProgress **aProgress)
1321{
1322 CheckComArgNotNull(aName);
1323 CheckComArgOutPointerValid(aHostNetworkInterface);
1324 CheckComArgOutPointerValid(aProgress);
1325
1326 AutoWriteLock alock (this);
1327 CHECK_READY();
1328
1329 /* first check whether an interface with the given name already exists */
1330 {
1331 ComPtr <IHostNetworkInterface> iface;
1332 if (SUCCEEDED (FindHostNetworkInterfaceByName (aName, iface.asOutParam())))
1333 return setError (E_INVALIDARG,
1334 tr ("Host network interface '%ls' already exists"), aName);
1335 }
1336
1337 int r = NetIfCreateHostOnlyNetworkInterface (mParent, aName, aHostNetworkInterface, aProgress);
1338 if(RT_SUCCESS(r))
1339 {
1340 return S_OK;
1341 }
1342
1343 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1344}
1345
1346STDMETHODIMP
1347Host::RemoveHostOnlyNetworkInterface (IN_GUID aId,
1348 IHostNetworkInterface **aHostNetworkInterface,
1349 IProgress **aProgress)
1350{
1351 CheckComArgOutPointerValid(aHostNetworkInterface);
1352 CheckComArgOutPointerValid(aProgress);
1353
1354 AutoWriteLock alock (this);
1355 CHECK_READY();
1356
1357 /* first check whether an interface with the given name already exists */
1358 {
1359 ComPtr <IHostNetworkInterface> iface;
1360 if (FAILED (FindHostNetworkInterfaceById (aId, iface.asOutParam())))
1361 return setError (VBOX_E_OBJECT_NOT_FOUND,
1362 tr ("Host network interface with UUID {%RTuuid} does not exist"),
1363 Guid (aId).raw());
1364 }
1365
1366 int r = NetIfRemoveHostOnlyNetworkInterface (mParent, aId, aHostNetworkInterface, aProgress);
1367 if(RT_SUCCESS(r))
1368 {
1369 return S_OK;
1370 }
1371
1372 return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
1373}
1374
1375#endif /* RT_OS_WINDOWS */
1376
1377STDMETHODIMP Host::CreateUSBDeviceFilter (IN_BSTR aName, IHostUSBDeviceFilter **aFilter)
1378{
1379#ifdef VBOX_WITH_USB
1380 CheckComArgStrNotEmptyOrNull(aName);
1381 CheckComArgOutPointerValid(aFilter);
1382
1383 AutoWriteLock alock (this);
1384 CHECK_READY();
1385
1386 ComObjPtr <HostUSBDeviceFilter> filter;
1387 filter.createObject();
1388 HRESULT rc = filter->init (this, aName);
1389 ComAssertComRCRet (rc, rc);
1390 rc = filter.queryInterfaceTo (aFilter);
1391 AssertComRCReturn (rc, rc);
1392 return S_OK;
1393#else
1394 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1395 * extended error info to indicate that USB is simply not available
1396 * (w/o treating it as a failure), for example, as in OSE. */
1397 ReturnComNotImplemented();
1398#endif
1399}
1400
1401STDMETHODIMP Host::InsertUSBDeviceFilter (ULONG aPosition, IHostUSBDeviceFilter *aFilter)
1402{
1403#ifdef VBOX_WITH_USB
1404 CheckComArgNotNull(aFilter);
1405
1406 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1407 AutoWriteLock alock (this);
1408 CHECK_READY();
1409
1410 MultiResult rc = checkUSBProxyService();
1411 CheckComRCReturnRC (rc);
1412
1413 ComObjPtr <HostUSBDeviceFilter> filter = getDependentChild (aFilter);
1414 if (!filter)
1415 return setError (VBOX_E_INVALID_OBJECT_STATE,
1416 tr ("The given USB device filter is not created within "
1417 "this VirtualBox instance"));
1418
1419 if (filter->mInList)
1420 return setError (E_INVALIDARG,
1421 tr ("The given USB device filter is already in the list"));
1422
1423 /* iterate to the position... */
1424 USBDeviceFilterList::iterator it = mUSBDeviceFilters.begin();
1425 std::advance (it, aPosition);
1426 /* ...and insert */
1427 mUSBDeviceFilters.insert (it, filter);
1428 filter->mInList = true;
1429
1430 /* notify the proxy (only when the filter is active) */
1431 if (mUSBProxyService->isActive() && filter->data().mActive)
1432 {
1433 ComAssertRet (filter->id() == NULL, E_FAIL);
1434 filter->id() = mUSBProxyService->insertFilter (&filter->data().mUSBFilter);
1435 }
1436
1437 /* save the global settings */
1438 alock.unlock();
1439 return rc = mParent->saveSettings();
1440#else
1441 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1442 * extended error info to indicate that USB is simply not available
1443 * (w/o treating it as a failure), for example, as in OSE. */
1444 ReturnComNotImplemented();
1445#endif
1446}
1447
1448STDMETHODIMP Host::RemoveUSBDeviceFilter (ULONG aPosition, IHostUSBDeviceFilter **aFilter)
1449{
1450#ifdef VBOX_WITH_USB
1451 CheckComArgOutPointerValid(aFilter);
1452
1453 /* Note: HostUSBDeviceFilter and USBProxyService also uses this lock. */
1454 AutoWriteLock alock (this);
1455 CHECK_READY();
1456
1457 MultiResult rc = checkUSBProxyService();
1458 CheckComRCReturnRC (rc);
1459
1460 if (!mUSBDeviceFilters.size())
1461 return setError (E_INVALIDARG,
1462 tr ("The USB device filter list is empty"));
1463
1464 if (aPosition >= mUSBDeviceFilters.size())
1465 return setError (E_INVALIDARG,
1466 tr ("Invalid position: %lu (must be in range [0, %lu])"),
1467 aPosition, mUSBDeviceFilters.size() - 1);
1468
1469 ComObjPtr <HostUSBDeviceFilter> filter;
1470 {
1471 /* iterate to the position... */
1472 USBDeviceFilterList::iterator it = mUSBDeviceFilters.begin();
1473 std::advance (it, aPosition);
1474 /* ...get an element from there... */
1475 filter = *it;
1476 /* ...and remove */
1477 filter->mInList = false;
1478 mUSBDeviceFilters.erase (it);
1479 }
1480
1481 filter.queryInterfaceTo (aFilter);
1482
1483 /* notify the proxy (only when the filter is active) */
1484 if (mUSBProxyService->isActive() && filter->data().mActive)
1485 {
1486 ComAssertRet (filter->id() != NULL, E_FAIL);
1487 mUSBProxyService->removeFilter (filter->id());
1488 filter->id() = NULL;
1489 }
1490
1491 /* save the global settings */
1492 alock.unlock();
1493 return rc = mParent->saveSettings();
1494#else
1495 /* Note: The GUI depends on this method returning E_NOTIMPL with no
1496 * extended error info to indicate that USB is simply not available
1497 * (w/o treating it as a failure), for example, as in OSE. */
1498 ReturnComNotImplemented();
1499#endif
1500}
1501
1502// public methods only for internal purposes
1503////////////////////////////////////////////////////////////////////////////////
1504
1505HRESULT Host::loadSettings (const settings::Key &aGlobal)
1506{
1507 using namespace settings;
1508
1509 AutoWriteLock alock (this);
1510 CHECK_READY();
1511
1512 AssertReturn (!aGlobal.isNull(), E_FAIL);
1513
1514 HRESULT rc = S_OK;
1515
1516#ifdef VBOX_WITH_USB
1517 Key::List filters = aGlobal.key ("USBDeviceFilters").keys ("DeviceFilter");
1518 for (Key::List::const_iterator it = filters.begin();
1519 it != filters.end(); ++ it)
1520 {
1521 Bstr name = (*it).stringValue ("name");
1522 bool active = (*it).value <bool> ("active");
1523
1524 Bstr vendorId = (*it).stringValue ("vendorId");
1525 Bstr productId = (*it).stringValue ("productId");
1526 Bstr revision = (*it).stringValue ("revision");
1527 Bstr manufacturer = (*it).stringValue ("manufacturer");
1528 Bstr product = (*it).stringValue ("product");
1529 Bstr serialNumber = (*it).stringValue ("serialNumber");
1530 Bstr port = (*it).stringValue ("port");
1531
1532 USBDeviceFilterAction_T action;
1533 action = USBDeviceFilterAction_Ignore;
1534 const char *actionStr = (*it).stringValue ("action");
1535 if (strcmp (actionStr, "Ignore") == 0)
1536 action = USBDeviceFilterAction_Ignore;
1537 else
1538 if (strcmp (actionStr, "Hold") == 0)
1539 action = USBDeviceFilterAction_Hold;
1540 else
1541 AssertMsgFailed (("Invalid action: '%s'\n", actionStr));
1542
1543 ComObjPtr <HostUSBDeviceFilter> filterObj;
1544 filterObj.createObject();
1545 rc = filterObj->init (this,
1546 name, active, vendorId, productId, revision,
1547 manufacturer, product, serialNumber, port,
1548 action);
1549 /* error info is set by init() when appropriate */
1550 CheckComRCBreakRC (rc);
1551
1552 mUSBDeviceFilters.push_back (filterObj);
1553 filterObj->mInList = true;
1554
1555 /* notify the proxy (only when the filter is active) */
1556 if (filterObj->data().mActive)
1557 {
1558 HostUSBDeviceFilter *flt = filterObj; /* resolve ambiguity */
1559 flt->id() = mUSBProxyService->insertFilter (&filterObj->data().mUSBFilter);
1560 }
1561 }
1562#endif /* VBOX_WITH_USB */
1563
1564 return rc;
1565}
1566
1567HRESULT Host::saveSettings (settings::Key &aGlobal)
1568{
1569 using namespace settings;
1570
1571 AutoWriteLock alock (this);
1572 CHECK_READY();
1573
1574 ComAssertRet (!aGlobal.isNull(), E_FAIL);
1575
1576#ifdef VBOX_WITH_USB
1577 /* first, delete the entry */
1578 Key filters = aGlobal.findKey ("USBDeviceFilters");
1579 if (!filters.isNull())
1580 filters.zap();
1581 /* then, recreate it */
1582 filters = aGlobal.createKey ("USBDeviceFilters");
1583
1584 USBDeviceFilterList::const_iterator it = mUSBDeviceFilters.begin();
1585 while (it != mUSBDeviceFilters.end())
1586 {
1587 AutoWriteLock filterLock (*it);
1588 const HostUSBDeviceFilter::Data &data = (*it)->data();
1589
1590 Key filter = filters.appendKey ("DeviceFilter");
1591
1592 filter.setValue <Bstr> ("name", data.mName);
1593 filter.setValue <bool> ("active", !!data.mActive);
1594
1595 /* all are optional */
1596 Bstr str;
1597 (*it)->COMGETTER (VendorId) (str.asOutParam());
1598 if (!str.isNull())
1599 filter.setValue <Bstr> ("vendorId", str);
1600
1601 (*it)->COMGETTER (ProductId) (str.asOutParam());
1602 if (!str.isNull())
1603 filter.setValue <Bstr> ("productId", str);
1604
1605 (*it)->COMGETTER (Revision) (str.asOutParam());
1606 if (!str.isNull())
1607 filter.setValue <Bstr> ("revision", str);
1608
1609 (*it)->COMGETTER (Manufacturer) (str.asOutParam());
1610 if (!str.isNull())
1611 filter.setValue <Bstr> ("manufacturer", str);
1612
1613 (*it)->COMGETTER (Product) (str.asOutParam());
1614 if (!str.isNull())
1615 filter.setValue <Bstr> ("product", str);
1616
1617 (*it)->COMGETTER (SerialNumber) (str.asOutParam());
1618 if (!str.isNull())
1619 filter.setValue <Bstr> ("serialNumber", str);
1620
1621 (*it)->COMGETTER (Port) (str.asOutParam());
1622 if (!str.isNull())
1623 filter.setValue <Bstr> ("port", str);
1624
1625 /* action is mandatory */
1626 USBDeviceFilterAction_T action = USBDeviceFilterAction_Null;
1627 (*it)->COMGETTER (Action) (&action);
1628 if (action == USBDeviceFilterAction_Ignore)
1629 filter.setStringValue ("action", "Ignore");
1630 else if (action == USBDeviceFilterAction_Hold)
1631 filter.setStringValue ("action", "Hold");
1632 else
1633 AssertMsgFailed (("Invalid action: %d\n", action));
1634
1635 ++ it;
1636 }
1637#endif /* VBOX_WITH_USB */
1638
1639 return S_OK;
1640}
1641
1642#ifdef VBOX_WITH_USB
1643/**
1644 * Called by setter methods of all USB device filters.
1645 */
1646HRESULT Host::onUSBDeviceFilterChange (HostUSBDeviceFilter *aFilter,
1647 BOOL aActiveChanged /* = FALSE */)
1648{
1649 AutoWriteLock alock (this);
1650 CHECK_READY();
1651
1652 if (aFilter->mInList)
1653 {
1654 if (aActiveChanged)
1655 {
1656 // insert/remove the filter from the proxy
1657 if (aFilter->data().mActive)
1658 {
1659 ComAssertRet (aFilter->id() == NULL, E_FAIL);
1660 aFilter->id() = mUSBProxyService->insertFilter (&aFilter->data().mUSBFilter);
1661 }
1662 else
1663 {
1664 ComAssertRet (aFilter->id() != NULL, E_FAIL);
1665 mUSBProxyService->removeFilter (aFilter->id());
1666 aFilter->id() = NULL;
1667 }
1668 }
1669 else
1670 {
1671 if (aFilter->data().mActive)
1672 {
1673 // update the filter in the proxy
1674 ComAssertRet (aFilter->id() != NULL, E_FAIL);
1675 mUSBProxyService->removeFilter (aFilter->id());
1676 aFilter->id() = mUSBProxyService->insertFilter (&aFilter->data().mUSBFilter);
1677 }
1678 }
1679
1680 // save the global settings... yeah, on every single filter property change
1681 alock.unlock();
1682 return mParent->saveSettings();
1683 }
1684
1685 return S_OK;
1686}
1687
1688
1689/**
1690 * Interface for obtaining a copy of the USBDeviceFilterList,
1691 * used by the USBProxyService.
1692 *
1693 * @param aGlobalFilters Where to put the global filter list copy.
1694 * @param aMachines Where to put the machine vector.
1695 */
1696void Host::getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters, VirtualBox::SessionMachineVector *aMachines)
1697{
1698 AutoWriteLock alock (this);
1699
1700 mParent->getOpenedMachines (*aMachines);
1701 *aGlobalFilters = mUSBDeviceFilters;
1702}
1703
1704#endif /* VBOX_WITH_USB */
1705
1706// private methods
1707////////////////////////////////////////////////////////////////////////////////
1708
1709#if defined(RT_OS_SOLARIS) && defined(VBOX_USE_LIBHAL)
1710/* Solaris hosts, loading libhal at runtime */
1711
1712/**
1713 * Helper function to query the hal subsystem for information about DVD drives attached to the
1714 * system.
1715 *
1716 * @returns true if information was successfully obtained, false otherwise
1717 * @retval list drives found will be attached to this list
1718 */
1719bool Host::getDVDInfoFromHal(std::list <ComObjPtr <HostDVDDrive> > &list)
1720{
1721 bool halSuccess = false;
1722 DBusError dbusError;
1723 if (!gLibHalCheckPresence())
1724 return false;
1725 gDBusErrorInit (&dbusError);
1726 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
1727 if (dbusConnection != 0)
1728 {
1729 LibHalContext *halContext = gLibHalCtxNew();
1730 if (halContext != 0)
1731 {
1732 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
1733 {
1734 if (gLibHalCtxInit(halContext, &dbusError))
1735 {
1736 int numDevices;
1737 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
1738 "storage.drive_type", "cdrom",
1739 &numDevices, &dbusError);
1740 if (halDevices != 0)
1741 {
1742 /* Hal is installed and working, so if no devices are reported, assume
1743 that there are none. */
1744 halSuccess = true;
1745 for (int i = 0; i < numDevices; i++)
1746 {
1747 char *devNode = gLibHalDeviceGetPropertyString(halContext,
1748 halDevices[i], "block.device", &dbusError);
1749#ifdef RT_OS_SOLARIS
1750 /* The CD/DVD ioctls work only for raw device nodes. */
1751 char *tmp = getfullrawname(devNode);
1752 gLibHalFreeString(devNode);
1753 devNode = tmp;
1754#endif
1755 if (devNode != 0)
1756 {
1757// if (validateDevice(devNode, true))
1758// {
1759 Utf8Str description;
1760 char *vendor, *product;
1761 /* We do not check the error here, as this field may
1762 not even exist. */
1763 vendor = gLibHalDeviceGetPropertyString(halContext,
1764 halDevices[i], "info.vendor", 0);
1765 product = gLibHalDeviceGetPropertyString(halContext,
1766 halDevices[i], "info.product", &dbusError);
1767 if ((product != 0 && product[0] != 0))
1768 {
1769 if ((vendor != 0) && (vendor[0] != 0))
1770 {
1771 description = Utf8StrFmt ("%s %s",
1772 vendor, product);
1773 }
1774 else
1775 {
1776 description = product;
1777 }
1778 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
1779 hostDVDDriveObj.createObject();
1780 hostDVDDriveObj->init (Bstr (devNode),
1781 Bstr (halDevices[i]),
1782 Bstr (description));
1783 list.push_back (hostDVDDriveObj);
1784 }
1785 else
1786 {
1787 if (product == 0)
1788 {
1789 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
1790 halDevices[i], dbusError.name, dbusError.message));
1791 gDBusErrorFree(&dbusError);
1792 }
1793 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
1794 hostDVDDriveObj.createObject();
1795 hostDVDDriveObj->init (Bstr (devNode),
1796 Bstr (halDevices[i]));
1797 list.push_back (hostDVDDriveObj);
1798 }
1799 if (vendor != 0)
1800 {
1801 gLibHalFreeString(vendor);
1802 }
1803 if (product != 0)
1804 {
1805 gLibHalFreeString(product);
1806 }
1807// }
1808// else
1809// {
1810// LogRel(("Host::COMGETTER(DVDDrives): failed to validate the block device %s as a DVD drive\n"));
1811// }
1812#ifndef RT_OS_SOLARIS
1813 gLibHalFreeString(devNode);
1814#else
1815 free(devNode);
1816#endif
1817 }
1818 else
1819 {
1820 LogRel(("Host::COMGETTER(DVDDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
1821 halDevices[i], dbusError.name, dbusError.message));
1822 gDBusErrorFree(&dbusError);
1823 }
1824 }
1825 gLibHalFreeStringArray(halDevices);
1826 }
1827 else
1828 {
1829 LogRel(("Host::COMGETTER(DVDDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1830 gDBusErrorFree(&dbusError);
1831 }
1832 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
1833 {
1834 LogRel(("Host::COMGETTER(DVDDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1835 gDBusErrorFree(&dbusError);
1836 }
1837 }
1838 else
1839 {
1840 LogRel(("Host::COMGETTER(DVDDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1841 gDBusErrorFree(&dbusError);
1842 }
1843 gLibHalCtxFree(halContext);
1844 }
1845 else
1846 {
1847 LogRel(("Host::COMGETTER(DVDDrives): failed to set libhal connection to dbus.\n"));
1848 }
1849 }
1850 else
1851 {
1852 LogRel(("Host::COMGETTER(DVDDrives): failed to get a libhal context - out of memory?\n"));
1853 }
1854 gDBusConnectionUnref(dbusConnection);
1855 }
1856 else
1857 {
1858 LogRel(("Host::COMGETTER(DVDDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1859 gDBusErrorFree(&dbusError);
1860 }
1861 return halSuccess;
1862}
1863
1864
1865/**
1866 * Helper function to query the hal subsystem for information about floppy drives attached to the
1867 * system.
1868 *
1869 * @returns true if information was successfully obtained, false otherwise
1870 * @retval list drives found will be attached to this list
1871 */
1872bool Host::getFloppyInfoFromHal(std::list <ComObjPtr <HostFloppyDrive> > &list)
1873{
1874 bool halSuccess = false;
1875 DBusError dbusError;
1876 if (!gLibHalCheckPresence())
1877 return false;
1878 gDBusErrorInit (&dbusError);
1879 DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
1880 if (dbusConnection != 0)
1881 {
1882 LibHalContext *halContext = gLibHalCtxNew();
1883 if (halContext != 0)
1884 {
1885 if (gLibHalCtxSetDBusConnection (halContext, dbusConnection))
1886 {
1887 if (gLibHalCtxInit(halContext, &dbusError))
1888 {
1889 int numDevices;
1890 char **halDevices = gLibHalFindDeviceStringMatch(halContext,
1891 "storage.drive_type", "floppy",
1892 &numDevices, &dbusError);
1893 if (halDevices != 0)
1894 {
1895 /* Hal is installed and working, so if no devices are reported, assume
1896 that there are none. */
1897 halSuccess = true;
1898 for (int i = 0; i < numDevices; i++)
1899 {
1900 char *driveType = gLibHalDeviceGetPropertyString(halContext,
1901 halDevices[i], "storage.drive_type", 0);
1902 if (driveType != 0)
1903 {
1904 if (strcmp(driveType, "floppy") != 0)
1905 {
1906 gLibHalFreeString(driveType);
1907 continue;
1908 }
1909 gLibHalFreeString(driveType);
1910 }
1911 else
1912 {
1913 /* An error occurred. The attribute "storage.drive_type"
1914 probably didn't exist. */
1915 continue;
1916 }
1917 char *devNode = gLibHalDeviceGetPropertyString(halContext,
1918 halDevices[i], "block.device", &dbusError);
1919 if (devNode != 0)
1920 {
1921// if (validateDevice(devNode, false))
1922// {
1923 Utf8Str description;
1924 char *vendor, *product;
1925 /* We do not check the error here, as this field may
1926 not even exist. */
1927 vendor = gLibHalDeviceGetPropertyString(halContext,
1928 halDevices[i], "info.vendor", 0);
1929 product = gLibHalDeviceGetPropertyString(halContext,
1930 halDevices[i], "info.product", &dbusError);
1931 if ((product != 0) && (product[0] != 0))
1932 {
1933 if ((vendor != 0) && (vendor[0] != 0))
1934 {
1935 description = Utf8StrFmt ("%s %s",
1936 vendor, product);
1937 }
1938 else
1939 {
1940 description = product;
1941 }
1942 ComObjPtr <HostFloppyDrive> hostFloppyDrive;
1943 hostFloppyDrive.createObject();
1944 hostFloppyDrive->init (Bstr (devNode),
1945 Bstr (halDevices[i]),
1946 Bstr (description));
1947 list.push_back (hostFloppyDrive);
1948 }
1949 else
1950 {
1951 if (product == 0)
1952 {
1953 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"info.product\" for device %s. dbus error: %s (%s)\n",
1954 halDevices[i], dbusError.name, dbusError.message));
1955 gDBusErrorFree(&dbusError);
1956 }
1957 ComObjPtr <HostFloppyDrive> hostFloppyDrive;
1958 hostFloppyDrive.createObject();
1959 hostFloppyDrive->init (Bstr (devNode),
1960 Bstr (halDevices[i]));
1961 list.push_back (hostFloppyDrive);
1962 }
1963 if (vendor != 0)
1964 {
1965 gLibHalFreeString(vendor);
1966 }
1967 if (product != 0)
1968 {
1969 gLibHalFreeString(product);
1970 }
1971// }
1972// else
1973// {
1974// LogRel(("Host::COMGETTER(FloppyDrives): failed to validate the block device %s as a floppy drive\n"));
1975// }
1976 gLibHalFreeString(devNode);
1977 }
1978 else
1979 {
1980 LogRel(("Host::COMGETTER(FloppyDrives): failed to get property \"block.device\" for device %s. dbus error: %s (%s)\n",
1981 halDevices[i], dbusError.name, dbusError.message));
1982 gDBusErrorFree(&dbusError);
1983 }
1984 }
1985 gLibHalFreeStringArray(halDevices);
1986 }
1987 else
1988 {
1989 LogRel(("Host::COMGETTER(FloppyDrives): failed to get devices with capability \"storage.cdrom\". dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1990 gDBusErrorFree(&dbusError);
1991 }
1992 if (!gLibHalCtxShutdown(halContext, &dbusError)) /* what now? */
1993 {
1994 LogRel(("Host::COMGETTER(FloppyDrives): failed to shutdown the libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
1995 gDBusErrorFree(&dbusError);
1996 }
1997 }
1998 else
1999 {
2000 LogRel(("Host::COMGETTER(FloppyDrives): failed to initialise libhal context. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2001 gDBusErrorFree(&dbusError);
2002 }
2003 gLibHalCtxFree(halContext);
2004 }
2005 else
2006 {
2007 LogRel(("Host::COMGETTER(FloppyDrives): failed to set libhal connection to dbus.\n"));
2008 }
2009 }
2010 else
2011 {
2012 LogRel(("Host::COMGETTER(FloppyDrives): failed to get a libhal context - out of memory?\n"));
2013 }
2014 gDBusConnectionUnref(dbusConnection);
2015 }
2016 else
2017 {
2018 LogRel(("Host::COMGETTER(FloppyDrives): failed to connect to dbus. dbus error: %s (%s)\n", dbusError.name, dbusError.message));
2019 gDBusErrorFree(&dbusError);
2020 }
2021 return halSuccess;
2022}
2023#endif /* RT_OS_SOLARIS and VBOX_USE_HAL */
2024
2025#if defined(RT_OS_SOLARIS)
2026
2027/**
2028 * Helper function to parse the given mount file and add found entries
2029 */
2030void Host::parseMountTable(char *mountTable, std::list <ComObjPtr <HostDVDDrive> > &list)
2031{
2032#ifdef RT_OS_LINUX
2033 FILE *mtab = setmntent(mountTable, "r");
2034 if (mtab)
2035 {
2036 struct mntent *mntent;
2037 char *mnt_type;
2038 char *mnt_dev;
2039 char *tmp;
2040 while ((mntent = getmntent(mtab)))
2041 {
2042 mnt_type = (char*)malloc(strlen(mntent->mnt_type) + 1);
2043 mnt_dev = (char*)malloc(strlen(mntent->mnt_fsname) + 1);
2044 strcpy(mnt_type, mntent->mnt_type);
2045 strcpy(mnt_dev, mntent->mnt_fsname);
2046 // supermount fs case
2047 if (strcmp(mnt_type, "supermount") == 0)
2048 {
2049 tmp = strstr(mntent->mnt_opts, "fs=");
2050 if (tmp)
2051 {
2052 free(mnt_type);
2053 mnt_type = strdup(tmp + strlen("fs="));
2054 if (mnt_type)
2055 {
2056 tmp = strchr(mnt_type, ',');
2057 if (tmp)
2058 *tmp = '\0';
2059 }
2060 }
2061 tmp = strstr(mntent->mnt_opts, "dev=");
2062 if (tmp)
2063 {
2064 free(mnt_dev);
2065 mnt_dev = strdup(tmp + strlen("dev="));
2066 if (mnt_dev)
2067 {
2068 tmp = strchr(mnt_dev, ',');
2069 if (tmp)
2070 *tmp = '\0';
2071 }
2072 }
2073 }
2074 // use strstr here to cover things fs types like "udf,iso9660"
2075 if (strstr(mnt_type, "iso9660") == 0)
2076 {
2077 /** @todo check whether we've already got the drive in our list! */
2078 if (validateDevice(mnt_dev, true))
2079 {
2080 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
2081 hostDVDDriveObj.createObject();
2082 hostDVDDriveObj->init (Bstr (mnt_dev));
2083 list.push_back (hostDVDDriveObj);
2084 }
2085 }
2086 free(mnt_dev);
2087 free(mnt_type);
2088 }
2089 endmntent(mtab);
2090 }
2091#else // RT_OS_SOLARIS
2092 FILE *mntFile = fopen(mountTable, "r");
2093 if (mntFile)
2094 {
2095 struct mnttab mntTab;
2096 while (getmntent(mntFile, &mntTab) == 0)
2097 {
2098 char *mountName = strdup(mntTab.mnt_special);
2099 char *mountPoint = strdup(mntTab.mnt_mountp);
2100 char *mountFSType = strdup(mntTab.mnt_fstype);
2101
2102 // skip devices we are not interested in
2103 if ((*mountName && mountName[0] == '/') && // skip 'fake' devices (like -hosts, proc, fd, swap)
2104 (*mountFSType && (strcmp(mountFSType, "devfs") != 0 && // skip devfs (i.e. /devices)
2105 strcmp(mountFSType, "dev") != 0 && // skip dev (i.e. /dev)
2106 strcmp(mountFSType, "lofs") != 0)) && // skip loop-back file-system (lofs)
2107 (*mountPoint && strcmp(mountPoint, "/") != 0)) // skip point '/' (Can CD/DVD be mounted at '/' ???)
2108 {
2109 char *rawDevName = getfullrawname(mountName);
2110 if (validateDevice(rawDevName, true))
2111 {
2112 ComObjPtr <HostDVDDrive> hostDVDDriveObj;
2113 hostDVDDriveObj.createObject();
2114 hostDVDDriveObj->init (Bstr (rawDevName));
2115 list.push_back (hostDVDDriveObj);
2116 }
2117 free(rawDevName);
2118 }
2119
2120 free(mountName);
2121 free(mountPoint);
2122 free(mountFSType);
2123 }
2124
2125 fclose(mntFile);
2126 }
2127#endif
2128}
2129
2130/**
2131 * Helper function to check whether the given device node is a valid drive
2132 */
2133bool Host::validateDevice(const char *deviceNode, bool isCDROM)
2134{
2135 struct stat statInfo;
2136 bool retValue = false;
2137
2138 // sanity check
2139 if (!deviceNode)
2140 {
2141 return false;
2142 }
2143
2144 // first a simple stat() call
2145 if (stat(deviceNode, &statInfo) < 0)
2146 {
2147 return false;
2148 } else
2149 {
2150 if (isCDROM)
2151 {
2152 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2153 {
2154 int fileHandle;
2155 // now try to open the device
2156 fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
2157 if (fileHandle >= 0)
2158 {
2159 cdrom_subchnl cdChannelInfo;
2160 cdChannelInfo.cdsc_format = CDROM_MSF;
2161 // this call will finally reveal the whole truth
2162#ifdef RT_OS_LINUX
2163 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2164 (errno == EIO) || (errno == ENOENT) ||
2165 (errno == EINVAL) || (errno == ENOMEDIUM))
2166#else
2167 if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
2168 (errno == EIO) || (errno == ENOENT) ||
2169 (errno == EINVAL))
2170#endif
2171 {
2172 retValue = true;
2173 }
2174 close(fileHandle);
2175 }
2176 }
2177 } else
2178 {
2179 // floppy case
2180 if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
2181 {
2182 /// @todo do some more testing, maybe a nice IOCTL!
2183 retValue = true;
2184 }
2185 }
2186 }
2187 return retValue;
2188}
2189#endif // RT_OS_SOLARIS
2190
2191#ifdef VBOX_WITH_USB
2192/**
2193 * Checks for the presense and status of the USB Proxy Service.
2194 * Returns S_OK when the Proxy is present and OK, VBOX_E_HOST_ERROR (as a
2195 * warning) if the proxy service is not available due to the way the host is
2196 * configured (at present, that means that usbfs and hal/DBus are not
2197 * available on a Linux host) or E_FAIL and a corresponding error message
2198 * otherwise. Intended to be used by methods that rely on the Proxy Service
2199 * availability.
2200 *
2201 * @note This method may return a warning result code. It is recommended to use
2202 * MultiError to store the return value.
2203 *
2204 * @note Locks this object for reading.
2205 */
2206HRESULT Host::checkUSBProxyService()
2207{
2208 AutoWriteLock alock (this);
2209 CHECK_READY();
2210
2211 AssertReturn (mUSBProxyService, E_FAIL);
2212 if (!mUSBProxyService->isActive())
2213 {
2214 /* disable the USB controller completely to avoid assertions if the
2215 * USB proxy service could not start. */
2216
2217 if (mUSBProxyService->getLastError() == VERR_FILE_NOT_FOUND)
2218 return setWarning (E_FAIL,
2219 tr ("Could not load the Host USB Proxy Service (%Rrc). "
2220 "The service might not be installed on the host computer"),
2221 mUSBProxyService->getLastError());
2222 if (mUSBProxyService->getLastError() == VINF_SUCCESS)
2223#ifdef RT_OS_LINUX
2224 return setWarning (VBOX_E_HOST_ERROR,
2225# ifdef VBOX_WITH_DBUS
2226 tr ("The USB Proxy Service could not be started, because neither the USB file system (usbfs) nor the hardware information service (hal) is available")
2227# else
2228 tr ("The USB Proxy Service could not be started, because the USB file system (usbfs) is not available")
2229# endif
2230 );
2231#else /* !RT_OS_LINUX */
2232 return setWarning (E_FAIL,
2233 tr ("The USB Proxy Service has not yet been ported to this host"));
2234#endif /* !RT_OS_LINUX */
2235 return setWarning (E_FAIL,
2236 tr ("Could not load the Host USB Proxy service (%Rrc)"),
2237 mUSBProxyService->getLastError());
2238 }
2239
2240 return S_OK;
2241}
2242#endif /* VBOX_WITH_USB */
2243
2244#ifdef VBOX_WITH_RESOURCE_USAGE_API
2245void Host::registerMetrics (PerformanceCollector *aCollector)
2246{
2247 pm::CollectorHAL *hal = aCollector->getHAL();
2248 /* Create sub metrics */
2249 pm::SubMetric *cpuLoadUser = new pm::SubMetric ("CPU/Load/User",
2250 "Percentage of processor time spent in user mode.");
2251 pm::SubMetric *cpuLoadKernel = new pm::SubMetric ("CPU/Load/Kernel",
2252 "Percentage of processor time spent in kernel mode.");
2253 pm::SubMetric *cpuLoadIdle = new pm::SubMetric ("CPU/Load/Idle",
2254 "Percentage of processor time spent idling.");
2255 pm::SubMetric *cpuMhzSM = new pm::SubMetric ("CPU/MHz",
2256 "Average of current frequency of all processors.");
2257 pm::SubMetric *ramUsageTotal = new pm::SubMetric ("RAM/Usage/Total",
2258 "Total physical memory installed.");
2259 pm::SubMetric *ramUsageUsed = new pm::SubMetric ("RAM/Usage/Used",
2260 "Physical memory currently occupied.");
2261 pm::SubMetric *ramUsageFree = new pm::SubMetric ("RAM/Usage/Free",
2262 "Physical memory currently available to applications.");
2263 /* Create and register base metrics */
2264 IUnknown *objptr;
2265 ComObjPtr <Host> tmp = this;
2266 tmp.queryInterfaceTo (&objptr);
2267 pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw (hal, objptr, cpuLoadUser, cpuLoadKernel,
2268 cpuLoadIdle);
2269 aCollector->registerBaseMetric (cpuLoad);
2270 pm::BaseMetric *cpuMhz = new pm::HostCpuMhz (hal, objptr, cpuMhzSM);
2271 aCollector->registerBaseMetric (cpuMhz);
2272 pm::BaseMetric *ramUsage = new pm::HostRamUsage (hal, objptr, ramUsageTotal, ramUsageUsed,
2273 ramUsageFree);
2274 aCollector->registerBaseMetric (ramUsage);
2275
2276 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser, 0));
2277 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser,
2278 new pm::AggregateAvg()));
2279 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser,
2280 new pm::AggregateMin()));
2281 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadUser,
2282 new pm::AggregateMax()));
2283
2284 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel, 0));
2285 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel,
2286 new pm::AggregateAvg()));
2287 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel,
2288 new pm::AggregateMin()));
2289 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadKernel,
2290 new pm::AggregateMax()));
2291
2292 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle, 0));
2293 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle,
2294 new pm::AggregateAvg()));
2295 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle,
2296 new pm::AggregateMin()));
2297 aCollector->registerMetric (new pm::Metric(cpuLoad, cpuLoadIdle,
2298 new pm::AggregateMax()));
2299
2300 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM, 0));
2301 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM,
2302 new pm::AggregateAvg()));
2303 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM,
2304 new pm::AggregateMin()));
2305 aCollector->registerMetric (new pm::Metric(cpuMhz, cpuMhzSM,
2306 new pm::AggregateMax()));
2307
2308 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal, 0));
2309 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal,
2310 new pm::AggregateAvg()));
2311 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal,
2312 new pm::AggregateMin()));
2313 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageTotal,
2314 new pm::AggregateMax()));
2315
2316 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed, 0));
2317 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed,
2318 new pm::AggregateAvg()));
2319 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed,
2320 new pm::AggregateMin()));
2321 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageUsed,
2322 new pm::AggregateMax()));
2323
2324 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree, 0));
2325 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree,
2326 new pm::AggregateAvg()));
2327 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree,
2328 new pm::AggregateMin()));
2329 aCollector->registerMetric (new pm::Metric(ramUsage, ramUsageFree,
2330 new pm::AggregateMax()));
2331};
2332
2333void Host::unregisterMetrics (PerformanceCollector *aCollector)
2334{
2335 aCollector->unregisterMetricsFor (this);
2336 aCollector->unregisterBaseMetricsFor (this);
2337};
2338#endif /* VBOX_WITH_RESOURCE_USAGE_API */
2339
2340STDMETHODIMP Host::FindHostDVDDrive(IN_BSTR aName, IHostDVDDrive **aDrive)
2341{
2342 CheckComArgNotNull(aName);
2343 CheckComArgOutPointerValid(aDrive);
2344
2345 *aDrive = NULL;
2346
2347 SafeIfaceArray <IHostDVDDrive> drivevec;
2348 HRESULT rc = COMGETTER(DVDDrives) (ComSafeArrayAsOutParam(drivevec));
2349 CheckComRCReturnRC (rc);
2350
2351 for (size_t i = 0; i < drivevec.size(); ++i)
2352 {
2353 Bstr name;
2354 rc = drivevec[i]->COMGETTER(Name) (name.asOutParam());
2355 CheckComRCReturnRC (rc);
2356 if (name == aName)
2357 {
2358 ComObjPtr<HostDVDDrive> found;
2359 found.createObject();
2360 Bstr udi, description;
2361 rc = drivevec[i]->COMGETTER(Udi) (udi.asOutParam());
2362 CheckComRCReturnRC (rc);
2363 rc = drivevec[i]->COMGETTER(Description) (description.asOutParam());
2364 CheckComRCReturnRC (rc);
2365 found->init(name, udi, description);
2366 return found.queryInterfaceTo(aDrive);
2367 }
2368 }
2369
2370 return setError (VBOX_E_OBJECT_NOT_FOUND, HostDVDDrive::tr (
2371 "The host DVD drive named '%ls' could not be found"), aName);
2372}
2373
2374STDMETHODIMP Host::FindHostFloppyDrive(IN_BSTR aName, IHostFloppyDrive **aDrive)
2375{
2376 CheckComArgNotNull(aName);
2377 CheckComArgOutPointerValid(aDrive);
2378
2379 *aDrive = NULL;
2380
2381 SafeIfaceArray <IHostFloppyDrive> drivevec;
2382 HRESULT rc = COMGETTER(FloppyDrives) (ComSafeArrayAsOutParam(drivevec));
2383 CheckComRCReturnRC (rc);
2384
2385 for (size_t i = 0; i < drivevec.size(); ++i)
2386 {
2387 Bstr name;
2388 rc = drivevec[i]->COMGETTER(Name) (name.asOutParam());
2389 CheckComRCReturnRC (rc);
2390 if (name == aName)
2391 {
2392 ComObjPtr<HostFloppyDrive> found;
2393 found.createObject();
2394 Bstr udi, description;
2395 rc = drivevec[i]->COMGETTER(Udi) (udi.asOutParam());
2396 CheckComRCReturnRC (rc);
2397 rc = drivevec[i]->COMGETTER(Description) (description.asOutParam());
2398 CheckComRCReturnRC (rc);
2399 found->init(name, udi, description);
2400 return found.queryInterfaceTo(aDrive);
2401 }
2402 }
2403
2404 return setError (VBOX_E_OBJECT_NOT_FOUND, HostFloppyDrive::tr (
2405 "The host floppy drive named '%ls' could not be found"), aName);
2406}
2407
2408STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInterface **networkInterface)
2409{
2410#ifndef VBOX_WITH_HOSTNETIF_API
2411 return E_NOTIMPL;
2412#else
2413 if (!name)
2414 return E_INVALIDARG;
2415 if (!networkInterface)
2416 return E_POINTER;
2417
2418 *networkInterface = NULL;
2419 ComObjPtr <HostNetworkInterface> found;
2420 std::list <ComObjPtr <HostNetworkInterface> > list;
2421 int rc = NetIfList(list);
2422 if (RT_FAILURE(rc))
2423 {
2424 Log(("Failed to get host network interface list with rc=%Vrc\n", rc));
2425 return E_FAIL;
2426 }
2427 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
2428 for (it = list.begin(); it != list.end(); ++it)
2429 {
2430 Bstr n;
2431 (*it)->COMGETTER(Name) (n.asOutParam());
2432 if (n == name)
2433 found = *it;
2434 }
2435
2436 if (!found)
2437 return setError (E_INVALIDARG, HostNetworkInterface::tr (
2438 "The host network interface with the given name could not be found"));
2439
2440 found->setVirtualBox(mParent);
2441
2442 return found.queryInterfaceTo (networkInterface);
2443#endif
2444}
2445
2446STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_GUID id, IHostNetworkInterface **networkInterface)
2447{
2448#ifndef VBOX_WITH_HOSTNETIF_API
2449 return E_NOTIMPL;
2450#else
2451 if (Guid(id).isEmpty())
2452 return E_INVALIDARG;
2453 if (!networkInterface)
2454 return E_POINTER;
2455
2456 *networkInterface = NULL;
2457 ComObjPtr <HostNetworkInterface> found;
2458 std::list <ComObjPtr <HostNetworkInterface> > list;
2459 int rc = NetIfList(list);
2460 if (RT_FAILURE(rc))
2461 {
2462 Log(("Failed to get host network interface list with rc=%Vrc\n", rc));
2463 return E_FAIL;
2464 }
2465 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
2466 for (it = list.begin(); it != list.end(); ++it)
2467 {
2468 Guid g;
2469 (*it)->COMGETTER(Id) (g.asOutParam());
2470 if (g == Guid(id))
2471 found = *it;
2472 }
2473
2474 if (!found)
2475 return setError (E_INVALIDARG, HostNetworkInterface::tr (
2476 "The host network interface with the given GUID could not be found"));
2477
2478 found->setVirtualBox(mParent);
2479
2480 return found.queryInterfaceTo (networkInterface);
2481#endif
2482}
2483
2484STDMETHODIMP Host::FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_T type, ComSafeArrayOut (IHostNetworkInterface *, aNetworkInterfaces))
2485{
2486 std::list <ComObjPtr <HostNetworkInterface> > allList;
2487 int rc = NetIfList(allList);
2488 if(RT_FAILURE(rc))
2489 return E_FAIL;
2490
2491 std::list <ComObjPtr <HostNetworkInterface> > resultList;
2492
2493 std::list <ComObjPtr <HostNetworkInterface> >::iterator it;
2494 for (it = allList.begin(); it != allList.end(); ++it)
2495 {
2496 HostNetworkInterfaceType_T t;
2497 HRESULT hr = (*it)->COMGETTER(InterfaceType)(&t);
2498 if(FAILED(hr))
2499 return hr;
2500
2501 if(t == type)
2502 {
2503 (*it)->setVirtualBox(mParent);
2504 resultList.push_back (*it);
2505 }
2506 }
2507
2508 SafeIfaceArray <IHostNetworkInterface> filteredNetworkInterfaces (resultList);
2509 filteredNetworkInterfaces.detachTo (ComSafeArrayOutArg (aNetworkInterfaces));
2510
2511 return S_OK;
2512}
2513
2514
2515/* 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