VirtualBox

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

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

refined r51666

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