VirtualBox

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

Last change on this file since 23236 was 23236, checked in by vboxsync, 15 years ago

medium-merge: fix osx

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