VirtualBox

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

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

Query VT capabilities from the support driver.

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