VirtualBox

source: vbox/trunk/src/VBox/Main/ConsoleImpl2.cpp@ 24416

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

Fixed bugs in VBoxManage list hostcpuids and the cpuid part of the showvminfo output. Use the s_auCpuIdRanges thing more places.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 131.3 KB
Line 
1/* $Id: ConsoleImpl2.cpp 24416 2009-11-05 21:17:56Z vboxsync $ */
2/** @file
3 * VBox Console COM Class implementation
4 *
5 * @remark We've split out the code that the 64-bit VC++ v8 compiler finds
6 * problematic to optimize so we can disable optimizations and later,
7 * perhaps, find a real solution for it (like rewriting the code and
8 * to stop resemble a tonne of spaghetti).
9 */
10
11/*
12 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
13 *
14 * This file is part of VirtualBox Open Source Edition (OSE), as
15 * available from http://www.virtualbox.org. This file is free software;
16 * you can redistribute it and/or modify it under the terms of the GNU
17 * General Public License (GPL) as published by the Free Software
18 * Foundation, in version 2 as it comes in the "COPYING" file of the
19 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
20 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
21 *
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
23 * Clara, CA 95054 USA or visit http://www.sun.com if you need
24 * additional information or have any questions.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include "ConsoleImpl.h"
31#include "DisplayImpl.h"
32#include "VMMDev.h"
33
34// generated header
35#include "SchemaDefs.h"
36
37#include "Logging.h"
38
39#include <iprt/buildconfig.h>
40#include <iprt/string.h>
41#include <iprt/path.h>
42#include <iprt/dir.h>
43#include <iprt/param.h>
44#if 0 /* enable to play with lots of memory. */
45# include <iprt/env.h>
46#endif
47
48#include <VBox/vmapi.h>
49#include <VBox/err.h>
50#include <VBox/version.h>
51#include <VBox/HostServices/VBoxClipboardSvc.h>
52#ifdef VBOX_WITH_CROGL
53#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
54#endif
55#ifdef VBOX_WITH_GUEST_PROPS
56# include <VBox/HostServices/GuestPropertySvc.h>
57# include <VBox/com/defs.h>
58# include <VBox/com/array.h>
59# include <hgcm/HGCM.h> /** @todo it should be possible to register a service
60 * extension using a VMMDev callback. */
61# include <vector>
62#endif /* VBOX_WITH_GUEST_PROPS */
63#include <VBox/intnet.h>
64
65#include <VBox/com/string.h>
66#include <VBox/com/array.h>
67
68#if defined(RT_OS_SOLARIS) && defined(VBOX_WITH_NETFLT)
69# include <zone.h>
70#endif
71
72#if defined(RT_OS_LINUX) && defined(VBOX_WITH_NETFLT)
73# include <unistd.h>
74# include <sys/ioctl.h>
75# include <sys/socket.h>
76# include <linux/types.h>
77# include <linux/if.h>
78# include <linux/wireless.h>
79#endif
80
81#if defined(RT_OS_FREEBSD) && defined(VBOX_WITH_NETFLT)
82# include <unistd.h>
83# include <sys/types.h>
84# include <sys/ioctl.h>
85# include <sys/socket.h>
86# include <net/if.h>
87#endif
88
89#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
90# include <VBox/WinNetConfig.h>
91# include <Ntddndis.h>
92# include <devguid.h>
93#endif
94
95#if !defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
96# include <HostNetworkInterfaceImpl.h>
97# include <netif.h>
98#endif
99
100#include "DHCPServerRunner.h"
101
102#include <VBox/param.h>
103
104/* Comment out the following line to remove VMWare compatibility hack. */
105#define VMWARE_NET_IN_SLOT_11
106
107/**
108 * Translate IDE StorageControllerType_T to string representation.
109 */
110const char* controllerString(StorageControllerType_T enmType)
111{
112 switch (enmType)
113 {
114 case StorageControllerType_PIIX3:
115 return "PIIX3";
116 case StorageControllerType_PIIX4:
117 return "PIIX4";
118 case StorageControllerType_ICH6:
119 return "ICH6";
120 default:
121 return "Unknown";
122 }
123}
124
125/*
126 * VC++ 8 / amd64 has some serious trouble with this function.
127 * As a temporary measure, we'll drop global optimizations.
128 */
129#if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
130# pragma optimize("g", off)
131#endif
132
133/**
134 * Construct the VM configuration tree (CFGM).
135 *
136 * This is a callback for VMR3Create() call. It is called from CFGMR3Init()
137 * in the emulation thread (EMT). Any per thread COM/XPCOM initialization
138 * is done here.
139 *
140 * @param pVM VM handle.
141 * @param pvConsole Pointer to the VMPowerUpTask object.
142 * @return VBox status code.
143 *
144 * @note Locks the Console object for writing.
145 */
146DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
147{
148 LogFlowFuncEnter();
149 /* Note: hardcoded assumption about number of slots; see rom bios */
150 bool afPciDeviceNo[32] = {false};
151 bool fFdcEnabled = false;
152
153#if !defined (VBOX_WITH_XPCOM)
154 {
155 /* initialize COM */
156 HRESULT hrc = CoInitializeEx(NULL,
157 COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE |
158 COINIT_SPEED_OVER_MEMORY);
159 LogFlow (("Console::configConstructor(): CoInitializeEx()=%08X\n", hrc));
160 AssertComRCReturn (hrc, VERR_GENERAL_FAILURE);
161 }
162#endif
163
164 AssertReturn(pvConsole, VERR_GENERAL_FAILURE);
165 ComObjPtr<Console> pConsole = static_cast <Console *> (pvConsole);
166
167 AutoCaller autoCaller(pConsole);
168 AssertComRCReturn (autoCaller.rc(), VERR_ACCESS_DENIED);
169
170 /* lock the console because we widely use internal fields and methods */
171 AutoWriteLock alock(pConsole);
172
173 /* Save the VM pointer in the machine object */
174 pConsole->mpVM = pVM;
175
176 ComPtr<IMachine> pMachine = pConsole->machine();
177
178 int rc;
179 HRESULT hrc;
180 BSTR str = NULL;
181
182#define STR_FREE() do { if (str) { SysFreeString(str); str = NULL; } } while (0)
183#define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); STR_FREE(); return rc; } } while (0)
184#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%#x\n", hrc)); STR_FREE(); return VERR_GENERAL_FAILURE; } } while (0)
185
186 /*
187 * Get necessary objects and frequently used parameters.
188 */
189 ComPtr<IVirtualBox> virtualBox;
190 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
191
192 ComPtr<IHost> host;
193 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
194
195 ComPtr<ISystemProperties> systemProperties;
196 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
197
198 ComPtr<IBIOSSettings> biosSettings;
199 hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
200
201 hrc = pMachine->COMGETTER(HardwareUUID)(&str); H();
202 RTUUID HardwareUuid;
203 rc = RTUuidFromUtf16(&HardwareUuid, str); RC_CHECK();
204 STR_FREE();
205
206 ULONG cRamMBs;
207 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
208#if 0 /* enable to play with lots of memory. */
209 if (RTEnvExist("VBOX_RAM_SIZE"))
210 cRamMBs = RTStrToUInt64(RTEnvGet("VBOX_RAM_SIZE"));
211#endif
212 uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
213 uint32_t const cbRamHole = MM_RAM_HOLE_SIZE_DEFAULT;
214
215 ULONG cCpus = 1;
216 hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
217
218 Bstr osTypeId;
219 hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
220
221 BOOL fIOAPIC;
222 hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
223
224 /*
225 * Get root node first.
226 * This is the only node in the tree.
227 */
228 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
229 Assert(pRoot);
230
231 /*
232 * Set the root (and VMM) level values.
233 */
234 hrc = pMachine->COMGETTER(Name)(&str); H();
235 rc = CFGMR3InsertStringW(pRoot, "Name", str); RC_CHECK();
236 rc = CFGMR3InsertBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid)); RC_CHECK();
237 rc = CFGMR3InsertInteger(pRoot, "RamSize", cbRam); RC_CHECK();
238 rc = CFGMR3InsertInteger(pRoot, "RamHoleSize", cbRamHole); RC_CHECK();
239 rc = CFGMR3InsertInteger(pRoot, "NumCPUs", cCpus); RC_CHECK();
240 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); RC_CHECK();
241 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); /* boolean */ RC_CHECK();
242 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); /* boolean */ RC_CHECK();
243 /** @todo Config: RawR0, PATMEnabled and CSAMEnabled needs attention later. */
244 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); /* boolean */ RC_CHECK();
245 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); /* boolean */ RC_CHECK();
246
247 /* cpuid leaf overrides. */
248 static uint32_t const s_auCpuIdRanges[] =
249 {
250 UINT32_C(0x00000000), UINT32_C(0x0000000a),
251 UINT32_C(0x80000000), UINT32_C(0x8000000a)
252 };
253 for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2)
254 for (uint32_t uLeaf = s_auCpuIdRanges[i]; uLeaf < s_auCpuIdRanges[i + 1]; uLeaf++)
255 {
256 ULONG ulEax, ulEbx, ulEcx, ulEdx;
257 hrc = pMachine->GetCpuIdLeaf(uLeaf, &ulEax, &ulEbx, &ulEcx, &ulEdx);
258 if (SUCCEEDED(hrc))
259 {
260 PCFGMNODE pLeaf;
261 rc = CFGMR3InsertNodeF(pRoot, &pLeaf, "CPUM/HostCPUID/%RX32", uLeaf); RC_CHECK();
262
263 rc = CFGMR3InsertInteger(pLeaf, "eax", ulEax); RC_CHECK();
264 rc = CFGMR3InsertInteger(pLeaf, "ebx", ulEbx); RC_CHECK();
265 rc = CFGMR3InsertInteger(pLeaf, "ecx", ulEcx); RC_CHECK();
266 rc = CFGMR3InsertInteger(pLeaf, "edx", ulEdx); RC_CHECK();
267 }
268 else if (hrc != E_INVALIDARG) H();
269 }
270
271 if (osTypeId == "WindowsNT4")
272 {
273 /*
274 * We must limit CPUID count for Windows NT 4, as otherwise it stops
275 * with error 0x3e (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED).
276 */
277 LogRel(("Limiting CPUID leaf count for NT4 guests\n"));
278 PCFGMNODE pCPUM;
279 rc = CFGMR3InsertNode(pRoot, "CPUM", &pCPUM); RC_CHECK();
280 rc = CFGMR3InsertInteger(pCPUM, "NT4LeafLimit", true); RC_CHECK();
281 }
282
283 /* hardware virtualization extensions */
284 BOOL fHWVirtExEnabled;
285 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHWVirtExEnabled); H();
286 if (cCpus > 1) /** @todo SMP: This isn't nice, but things won't work on mac otherwise. */
287 fHWVirtExEnabled = TRUE;
288
289#ifdef RT_OS_DARWIN
290 rc = CFGMR3InsertInteger(pRoot, "HwVirtExtForced", fHWVirtExEnabled); RC_CHECK();
291#else
292 /* - With more than 4GB PGM will use different RAMRANGE sizes for raw
293 mode and hv mode to optimize lookup times.
294 - With more than one virtual CPU, raw-mode isn't a fallback option. */
295 BOOL fHwVirtExtForced = fHWVirtExEnabled
296 && ( cbRam > (_4G - cbRamHole)
297 || cCpus > 1);
298 rc = CFGMR3InsertInteger(pRoot, "HwVirtExtForced", fHwVirtExtForced); RC_CHECK();
299#endif
300
301 PCFGMNODE pHWVirtExt;
302 rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHWVirtExt); RC_CHECK();
303 if (fHWVirtExEnabled)
304 {
305 rc = CFGMR3InsertInteger(pHWVirtExt, "Enabled", 1); RC_CHECK();
306
307 /* Indicate whether 64-bit guests are supported or not. */
308 /** @todo This is currently only forced off on 32-bit hosts only because it
309 * makes a lof of difference there (REM and Solaris performance).
310 */
311
312 ComPtr<IGuestOSType> guestOSType;
313 hrc = virtualBox->GetGuestOSType(osTypeId, guestOSType.asOutParam()); H();
314
315 BOOL fSupportsLongMode = false;
316 hrc = host->GetProcessorFeature(ProcessorFeature_LongMode,
317 &fSupportsLongMode); H();
318 BOOL fIs64BitGuest = false;
319 hrc = guestOSType->COMGETTER(Is64Bit)(&fIs64BitGuest); H();
320
321 if (fSupportsLongMode && fIs64BitGuest)
322 {
323 rc = CFGMR3InsertInteger(pHWVirtExt, "64bitEnabled", 1); RC_CHECK();
324#if ARCH_BITS == 32 /* The recompiler must use VBoxREM64 (32-bit host only). */
325 PCFGMNODE pREM;
326 rc = CFGMR3InsertNode(pRoot, "REM", &pREM); RC_CHECK();
327 rc = CFGMR3InsertInteger(pREM, "64bitEnabled", 1); RC_CHECK();
328#endif
329 }
330#if ARCH_BITS == 32 /* 32-bit guests only. */
331 else
332 {
333 rc = CFGMR3InsertInteger(pHWVirtExt, "64bitEnabled", 0); RC_CHECK();
334 }
335#endif
336
337 /* @todo Not exactly pretty to check strings; VBOXOSTYPE would be better, but that requires quite a bit of API change in Main. */
338 if ( !fIs64BitGuest
339 && fIOAPIC
340 && ( osTypeId == "WindowsNT4"
341 || osTypeId == "Windows2000"
342 || osTypeId == "WindowsXP"
343 || osTypeId == "Windows2003"))
344 {
345 /* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode)
346 * We may want to consider adding more guest OSes (Solaris) later on.
347 */
348 rc = CFGMR3InsertInteger(pHWVirtExt, "TPRPatchingEnabled", 1); RC_CHECK();
349 }
350 }
351
352 /* HWVirtEx exclusive mode */
353 BOOL fHWVirtExExclusive = true;
354 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Exclusive, &fHWVirtExExclusive); H();
355 rc = CFGMR3InsertInteger(pHWVirtExt, "Exclusive", fHWVirtExExclusive); RC_CHECK();
356
357 /* Nested paging (VT-x/AMD-V) */
358 BOOL fEnableNestedPaging = false;
359 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &fEnableNestedPaging); H();
360 rc = CFGMR3InsertInteger(pHWVirtExt, "EnableNestedPaging", fEnableNestedPaging); RC_CHECK();
361
362 /* VPID (VT-x) */
363 BOOL fEnableVPID = false;
364 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_VPID, &fEnableVPID); H();
365 rc = CFGMR3InsertInteger(pHWVirtExt, "EnableVPID", fEnableVPID); RC_CHECK();
366
367 /* Physical Address Extension (PAE) */
368 BOOL fEnablePAE = false;
369 hrc = pMachine->GetCpuProperty(CpuPropertyType_PAE, &fEnablePAE); H();
370 rc = CFGMR3InsertInteger(pRoot, "EnablePAE", fEnablePAE); RC_CHECK();
371
372 /* Synthetic CPU */
373 BOOL fSyntheticCpu = false;
374 hrc = pMachine->GetCpuProperty(CpuPropertyType_Synthetic, &fSyntheticCpu); H();
375 rc = CFGMR3InsertInteger(pRoot, "SyntheticCpu", fSyntheticCpu); RC_CHECK();
376
377 BOOL fPXEDebug;
378 hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
379
380 /*
381 * PDM config.
382 * Load drivers in VBoxC.[so|dll]
383 */
384 PCFGMNODE pPDM;
385 PCFGMNODE pDrivers;
386 PCFGMNODE pMod;
387 rc = CFGMR3InsertNode(pRoot, "PDM", &pPDM); RC_CHECK();
388 rc = CFGMR3InsertNode(pPDM, "Drivers", &pDrivers); RC_CHECK();
389 rc = CFGMR3InsertNode(pDrivers, "VBoxC", &pMod); RC_CHECK();
390#ifdef VBOX_WITH_XPCOM
391 // VBoxC is located in the components subdirectory
392 char szPathVBoxC[RTPATH_MAX];
393 rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc);
394 strcat(szPathVBoxC, "/components/VBoxC");
395 rc = CFGMR3InsertString(pMod, "Path", szPathVBoxC); RC_CHECK();
396#else
397 rc = CFGMR3InsertString(pMod, "Path", "VBoxC"); RC_CHECK();
398#endif
399
400 /*
401 * Devices
402 */
403 PCFGMNODE pDevices = NULL; /* /Devices */
404 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
405 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
406 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
407 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
408 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
409 PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
410 PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */
411
412 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); RC_CHECK();
413
414 /*
415 * PC Arch.
416 */
417 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); RC_CHECK();
418 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
419 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
420 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
421
422 /*
423 * The time offset
424 */
425 LONG64 timeOffset;
426 hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H();
427 PCFGMNODE pTMNode;
428 rc = CFGMR3InsertNode(pRoot, "TM", &pTMNode); RC_CHECK();
429 rc = CFGMR3InsertInteger(pTMNode, "UTCOffset", timeOffset * 1000000); RC_CHECK();
430
431 /*
432 * DMA
433 */
434 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); RC_CHECK();
435 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
436 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
437
438 /*
439 * PCI buses.
440 */
441 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ RC_CHECK();
442 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
443 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
444 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
445 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
446
447#if 0 /* enable this to test PCI bridging */
448 rc = CFGMR3InsertNode(pDevices, "pcibridge", &pDev); RC_CHECK();
449 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
450 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
451 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
452 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 14); RC_CHECK();
453 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
454 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 0);/* -> pci[0] */ RC_CHECK();
455
456 rc = CFGMR3InsertNode(pDev, "1", &pInst); RC_CHECK();
457 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
458 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
459 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); RC_CHECK();
460 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
461 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK();
462
463 rc = CFGMR3InsertNode(pDev, "2", &pInst); RC_CHECK();
464 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
465 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
466 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 3); RC_CHECK();
467 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
468 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK();
469#endif
470
471 /*
472 * Temporary hack for enabling the next three devices and various ACPI features.
473 */
474 Bstr tmpStr2;
475 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/SupportExtHwProfile"), tmpStr2.asOutParam()); H();
476 BOOL fExtProfile = tmpStr2 == Bstr("on");
477
478 /*
479 * High Precision Event Timer (HPET)
480 */
481 BOOL fHpetEnabled;
482#ifdef VBOX_WITH_HPET
483 fHpetEnabled = fExtProfile;
484#else
485 fHpetEnabled = false;
486#endif
487 if (fHpetEnabled)
488 {
489 rc = CFGMR3InsertNode(pDevices, "hpet", &pDev); RC_CHECK();
490 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
491 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
492 }
493
494 /*
495 * System Management Controller (SMC)
496 */
497 BOOL fSmcEnabled;
498#ifdef VBOX_WITH_SMC
499 fSmcEnabled = fExtProfile;
500#else
501 fSmcEnabled = false;
502#endif
503 if (fSmcEnabled)
504 {
505 rc = CFGMR3InsertNode(pDevices, "smc", &pDev); RC_CHECK();
506 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
507 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
508 }
509
510 /*
511 * Low Pin Count (LPC) bus
512 */
513 BOOL fLpcEnabled;
514 /** @todo: implement appropriate getter */
515#ifdef VBOX_WITH_LPC
516 fLpcEnabled = fExtProfile;
517#else
518 fLpcEnabled = false;
519#endif
520 if (fLpcEnabled)
521 {
522 rc = CFGMR3InsertNode(pDevices, "lpc", &pDev); RC_CHECK();
523 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
524 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
525 }
526
527 /*
528 * PS/2 keyboard & mouse.
529 */
530 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); RC_CHECK();
531 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
532 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
533 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
534
535 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
536 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); RC_CHECK();
537 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
538 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); RC_CHECK();
539
540 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
541 rc = CFGMR3InsertString(pLunL1, "Driver", "MainKeyboard"); RC_CHECK();
542 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
543 Keyboard *pKeyboard = pConsole->mKeyboard;
544 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pKeyboard); RC_CHECK();
545
546 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); RC_CHECK();
547 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); RC_CHECK();
548 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
549 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); RC_CHECK();
550
551 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
552 rc = CFGMR3InsertString(pLunL1, "Driver", "MainMouse"); RC_CHECK();
553 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
554 Mouse *pMouse = pConsole->mMouse;
555 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pMouse); RC_CHECK();
556
557 /*
558 * i8254 Programmable Interval Timer And Dummy Speaker
559 */
560 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); RC_CHECK();
561 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
562 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
563#ifdef DEBUG
564 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
565#endif
566
567 /*
568 * i8259 Programmable Interrupt Controller.
569 */
570 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); RC_CHECK();
571 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
572 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
573 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
574
575 /*
576 * Advanced Programmable Interrupt Controller.
577 * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states,
578 * thus only single insert
579 */
580 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); RC_CHECK();
581 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
582 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
583 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
584 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
585 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK();
586
587 if (fIOAPIC)
588 {
589 /*
590 * I/O Advanced Programmable Interrupt Controller.
591 */
592 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); RC_CHECK();
593 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
594 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
595 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
596 }
597
598 /*
599 * RTC MC146818.
600 */
601 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); RC_CHECK();
602 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
603 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
604
605 /*
606 * VGA.
607 */
608 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); RC_CHECK();
609 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
610 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
611 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); RC_CHECK();
612 Assert(!afPciDeviceNo[2]);
613 afPciDeviceNo[2] = true;
614 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
615 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
616 ULONG cVRamMBs;
617 hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H();
618 rc = CFGMR3InsertInteger(pCfg, "VRamSize", cVRamMBs * _1M); RC_CHECK();
619 ULONG cMonitorCount;
620 hrc = pMachine->COMGETTER(MonitorCount)(&cMonitorCount); H();
621 rc = CFGMR3InsertInteger(pCfg, "MonitorCount", cMonitorCount); RC_CHECK();
622#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */ /** @todo this needs fixing !!! No wonder VGA is slooooooooow on 32-bit darwin! */
623 rc = CFGMR3InsertInteger(pCfg, "R0Enabled", fHWVirtExEnabled); RC_CHECK();
624#endif
625
626 /*
627 * BIOS logo
628 */
629 BOOL fFadeIn;
630 hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H();
631 rc = CFGMR3InsertInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0); RC_CHECK();
632 BOOL fFadeOut;
633 hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H();
634 rc = CFGMR3InsertInteger(pCfg, "FadeOut", fFadeOut ? 1: 0); RC_CHECK();
635 ULONG logoDisplayTime;
636 hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H();
637 rc = CFGMR3InsertInteger(pCfg, "LogoTime", logoDisplayTime); RC_CHECK();
638 Bstr logoImagePath;
639 hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H();
640 rc = CFGMR3InsertString(pCfg, "LogoFile", logoImagePath ? Utf8Str(logoImagePath).c_str() : ""); RC_CHECK();
641
642 /*
643 * Boot menu
644 */
645 BIOSBootMenuMode_T eBootMenuMode;
646 int iShowBootMenu;
647 biosSettings->COMGETTER(BootMenuMode)(&eBootMenuMode);
648 switch (eBootMenuMode)
649 {
650 case BIOSBootMenuMode_Disabled: iShowBootMenu = 0; break;
651 case BIOSBootMenuMode_MenuOnly: iShowBootMenu = 1; break;
652 default: iShowBootMenu = 2; break;
653 }
654 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", iShowBootMenu); RC_CHECK();
655
656 /* Custom VESA mode list */
657 unsigned cModes = 0;
658 for (unsigned iMode = 1; iMode <= 16; ++iMode)
659 {
660 char szExtraDataKey[sizeof("CustomVideoModeXX")];
661 RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%u", iMode);
662 hrc = pMachine->GetExtraData(Bstr(szExtraDataKey), &str); H();
663 if (!str || !*str)
664 break;
665 rc = CFGMR3InsertStringW(pCfg, szExtraDataKey, str); RC_CHECK();
666 STR_FREE();
667 ++cModes;
668 }
669 STR_FREE();
670 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", cModes);
671
672 /* VESA height reduction */
673 ULONG ulHeightReduction;
674 IFramebuffer *pFramebuffer = pConsole->getDisplay()->getFramebuffer();
675 if (pFramebuffer)
676 {
677 hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction); H();
678 }
679 else
680 {
681 /* If framebuffer is not available, there is no height reduction. */
682 ulHeightReduction = 0;
683 }
684 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", ulHeightReduction); RC_CHECK();
685
686 /* Attach the display. */
687 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
688 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); RC_CHECK();
689 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
690 Display *pDisplay = pConsole->mDisplay;
691 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pDisplay); RC_CHECK();
692
693
694 /*
695 * Firmware.
696 */
697#ifdef VBOX_WITH_EFI
698 Bstr tmpStr1;
699 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/UseEFI"), tmpStr1.asOutParam()); H();
700 BOOL fEfiEnabled = !tmpStr1.isEmpty();
701
702 /**
703 * @todo: VBoxInternal2/UseEFI extradata will go away soon, and we'll
704 * just use this code
705 */
706 if (!fEfiEnabled)
707 {
708 FirmwareType_T eType = FirmwareType_BIOS;
709 hrc = pMachine->COMGETTER(FirmwareType)(&eType); H();
710 fEfiEnabled = (eType == FirmwareType_EFI);
711 }
712#else
713 BOOL fEfiEnabled = false;
714#endif
715 if (!fEfiEnabled)
716 {
717 /*
718 * PC Bios.
719 */
720 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); RC_CHECK();
721 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
722 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
723 rc = CFGMR3InsertNode(pInst, "Config", &pBiosCfg); RC_CHECK();
724 rc = CFGMR3InsertInteger(pBiosCfg, "RamSize", cbRam); RC_CHECK();
725 rc = CFGMR3InsertInteger(pBiosCfg, "RamHoleSize", cbRamHole); RC_CHECK();
726 rc = CFGMR3InsertInteger(pBiosCfg, "NumCPUs", cCpus); RC_CHECK();
727 rc = CFGMR3InsertString(pBiosCfg, "HardDiskDevice", "piix3ide"); RC_CHECK();
728 rc = CFGMR3InsertString(pBiosCfg, "FloppyDevice", "i82078"); RC_CHECK();
729 rc = CFGMR3InsertInteger(pBiosCfg, "IOAPIC", fIOAPIC); RC_CHECK();
730 rc = CFGMR3InsertInteger(pBiosCfg, "PXEDebug", fPXEDebug); RC_CHECK();
731 rc = CFGMR3InsertBytes(pBiosCfg, "UUID", &HardwareUuid,sizeof(HardwareUuid));RC_CHECK();
732
733 DeviceType_T bootDevice;
734 if (SchemaDefs::MaxBootPosition > 9)
735 {
736 AssertMsgFailed (("Too many boot devices %d\n",
737 SchemaDefs::MaxBootPosition));
738 return VERR_INVALID_PARAMETER;
739 }
740
741 for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; ++pos)
742 {
743 hrc = pMachine->GetBootOrder(pos, &bootDevice); H();
744
745 char szParamName[] = "BootDeviceX";
746 szParamName[sizeof (szParamName) - 2] = ((char (pos - 1)) + '0');
747
748 const char *pszBootDevice;
749 switch (bootDevice)
750 {
751 case DeviceType_Null:
752 pszBootDevice = "NONE";
753 break;
754 case DeviceType_HardDisk:
755 pszBootDevice = "IDE";
756 break;
757 case DeviceType_DVD:
758 pszBootDevice = "DVD";
759 break;
760 case DeviceType_Floppy:
761 pszBootDevice = "FLOPPY";
762 break;
763 case DeviceType_Network:
764 pszBootDevice = "LAN";
765 break;
766 default:
767 AssertMsgFailed(("Invalid bootDevice=%d\n", bootDevice));
768 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
769 N_("Invalid boot device '%d'"), bootDevice);
770 }
771 rc = CFGMR3InsertString(pBiosCfg, szParamName, pszBootDevice); RC_CHECK();
772 }
773 }
774 else
775 {
776 /*
777 * EFI.
778 */
779 rc = CFGMR3InsertNode(pDevices, "efi", &pDev); RC_CHECK();
780 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
781 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
782 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
783 rc = CFGMR3InsertInteger(pCfg, "RamSize", cbRam); RC_CHECK();
784 rc = CFGMR3InsertInteger(pCfg, "RamHoleSize", cbRamHole); RC_CHECK();
785 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK();
786 }
787
788 /*
789 * Storage controllers.
790 */
791 com::SafeIfaceArray<IStorageController> ctrls;
792 PCFGMNODE aCtrlNodes[StorageControllerType_I82078 + 1] = {};
793 hrc = pMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); H();
794
795 for (size_t i = 0; i < ctrls.size(); ++ i)
796 {
797 StorageControllerType_T enmCtrlType;
798 rc = ctrls[i]->COMGETTER(ControllerType)(&enmCtrlType); H();
799 AssertRelease((unsigned)enmCtrlType < RT_ELEMENTS(aCtrlNodes));
800
801 StorageBus_T enmBus;
802 rc = ctrls[i]->COMGETTER(Bus)(&enmBus); H();
803
804 Bstr controllerName;
805 rc = ctrls[i]->COMGETTER(Name)(controllerName.asOutParam()); H();
806
807 ULONG ulInstance = 999;
808 rc = ctrls[i]->COMGETTER(Instance)(&ulInstance); H();
809
810 /* /Devices/<ctrldev>/ */
811 const char *pszCtrlDev = pConsole->controllerTypeToDev(enmCtrlType);
812 pDev = aCtrlNodes[enmCtrlType];
813 if (!pDev)
814 {
815 rc = CFGMR3InsertNode(pDevices, pszCtrlDev, &pDev); RC_CHECK();
816 aCtrlNodes[enmCtrlType] = pDev; /* IDE variants are handled in the switch */
817 }
818
819 /* /Devices/<ctrldev>/<instance>/ */
820 PCFGMNODE pCtlInst = NULL;
821 rc = CFGMR3InsertNodeF(pDev, &pCtlInst, "%u", ulInstance); RC_CHECK();
822
823 /* Device config: /Devices/<ctrldev>/<instance>/<values> & /ditto/Config/<values> */
824 rc = CFGMR3InsertInteger(pCtlInst, "Trusted", 1); RC_CHECK();
825 rc = CFGMR3InsertNode(pCtlInst, "Config", &pCfg); RC_CHECK();
826
827 bool fSCSI = false;
828 switch (enmCtrlType)
829 {
830 case StorageControllerType_LsiLogic:
831 {
832 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 20); RC_CHECK();
833 Assert(!afPciDeviceNo[20]);
834 afPciDeviceNo[20] = true;
835 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK();
836 fSCSI = true;
837
838 /* Attach the status driver */
839 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK();
840 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
841 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
842 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSCSILeds[0]); RC_CHECK();
843 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
844 rc = CFGMR3InsertInteger(pCfg, "Last", 15); RC_CHECK();
845 break;
846 }
847
848 case StorageControllerType_BusLogic:
849 {
850 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 21); RC_CHECK();
851 Assert(!afPciDeviceNo[21]);
852 afPciDeviceNo[21] = true;
853 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK();
854 fSCSI = true;
855
856 /* Attach the status driver */
857 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK();
858 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
859 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
860 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSCSILeds[0]); RC_CHECK();
861 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
862 rc = CFGMR3InsertInteger(pCfg, "Last", 15); RC_CHECK();
863 break;
864 }
865
866 case StorageControllerType_IntelAhci:
867 {
868 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 13); RC_CHECK();
869 Assert(!afPciDeviceNo[13]);
870 afPciDeviceNo[13] = true;
871 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK();
872
873 ULONG cPorts = 0;
874 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H();
875 rc = CFGMR3InsertInteger(pCfg, "PortCount", cPorts); RC_CHECK();
876
877 /* Needed configuration values for the bios. */
878 if (pBiosCfg)
879 {
880 rc = CFGMR3InsertString(pBiosCfg, "SataHardDiskDevice", "ahci"); RC_CHECK();
881 }
882
883 for (uint32_t j = 0; j < 4; ++j)
884 {
885 static const char * const s_apszConfig[4] =
886 { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
887 static const char * const s_apszBiosConfig[4] =
888 { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" };
889
890 LONG lPortNumber = -1;
891 hrc = ctrls[i]->GetIDEEmulationPort(j, &lPortNumber); H();
892 rc = CFGMR3InsertInteger(pCfg, s_apszConfig[j], lPortNumber); RC_CHECK();
893 if (pBiosCfg)
894 {
895 rc = CFGMR3InsertInteger(pBiosCfg, s_apszBiosConfig[j], lPortNumber); RC_CHECK();
896 }
897 }
898
899 /* Attach the status driver */
900 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK();
901 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
902 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
903 AssertRelease(cPorts <= RT_ELEMENTS(pConsole->mapSATALeds));
904 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSATALeds[0]); RC_CHECK();
905 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
906 rc = CFGMR3InsertInteger(pCfg, "Last", cPorts - 1); RC_CHECK();
907 break;
908 }
909
910 case StorageControllerType_PIIX3:
911 case StorageControllerType_PIIX4:
912 case StorageControllerType_ICH6:
913 {
914 /*
915 * IDE (update this when the main interface changes)
916 */
917 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 1); RC_CHECK();
918 Assert(!afPciDeviceNo[1]);
919 afPciDeviceNo[1] = true;
920 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 1); RC_CHECK();
921 rc = CFGMR3InsertString(pCfg, "Type", controllerString(enmCtrlType)); RC_CHECK();
922
923 /* Attach the status driver */
924 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK();
925 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
926 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
927 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapIDELeds[0]);RC_CHECK();
928 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
929 rc = CFGMR3InsertInteger(pCfg, "Last", 3); RC_CHECK();
930
931 /* IDE flavors */
932 aCtrlNodes[StorageControllerType_PIIX3] = pDev;
933 aCtrlNodes[StorageControllerType_PIIX4] = pDev;
934 aCtrlNodes[StorageControllerType_ICH6] = pDev;
935 break;
936 }
937
938 case StorageControllerType_I82078:
939 {
940 /*
941 * i82078 Floppy drive controller
942 */
943 fFdcEnabled = true;
944 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); RC_CHECK();
945 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); RC_CHECK();
946 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); RC_CHECK();
947 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); RC_CHECK();
948
949 /* Attach the status driver */
950 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK();
951 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
952 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
953 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapFDLeds[0]); RC_CHECK();
954 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
955 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
956 break;
957 }
958
959 default:
960 AssertMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_GENERAL_FAILURE);
961 }
962
963 /* Attach the hard disks. */
964 com::SafeIfaceArray<IMediumAttachment> atts;
965 hrc = pMachine->GetMediumAttachmentsOfController(controllerName,
966 ComSafeArrayAsOutParam(atts)); H();
967
968 for (size_t j = 0; j < atts.size(); ++j)
969 {
970 ComPtr<IMedium> medium;
971 hrc = atts [j]->COMGETTER(Medium)(medium.asOutParam()); H();
972 LONG lDev;
973 hrc = atts[j]->COMGETTER(Device)(&lDev); H();
974 LONG lPort;
975 hrc = atts[j]->COMGETTER(Port)(&lPort); H();
976 DeviceType_T lType;
977 hrc = atts[j]->COMGETTER(Type)(&lType); H();
978
979 unsigned uLUN;
980 hrc = pConsole->convertBusPortDeviceToLun(enmBus, lPort, lDev, uLUN); H();
981 rc = CFGMR3InsertNodeF(pCtlInst, &pLunL0, "LUN#%u", uLUN); RC_CHECK();
982
983 /* SCSI has a another driver between device and block. */
984 if (fSCSI)
985 {
986 rc = CFGMR3InsertString(pLunL0, "Driver", "SCSI"); RC_CHECK();
987 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
988
989 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
990 }
991
992 BOOL fHostDrive = FALSE;
993 if (!medium.isNull())
994 {
995 hrc = medium->COMGETTER(HostDrive)(&fHostDrive); H();
996 }
997
998 if (fHostDrive)
999 {
1000 Assert(!medium.isNull());
1001 if (lType == DeviceType_DVD)
1002 {
1003 rc = CFGMR3InsertString(pLunL0, "Driver", "HostDVD"); RC_CHECK();
1004 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1005
1006 hrc = medium->COMGETTER(Location)(&str); H();
1007 rc = CFGMR3InsertStringW(pCfg, "Path", str); RC_CHECK();
1008 STR_FREE();
1009
1010 BOOL fPassthrough;
1011 hrc = atts[j]->COMGETTER(Passthrough)(&fPassthrough); H();
1012 rc = CFGMR3InsertInteger(pCfg, "Passthrough", !!fPassthrough); RC_CHECK();
1013 }
1014 else if (lType == DeviceType_Floppy)
1015 {
1016 rc = CFGMR3InsertString(pLunL0, "Driver", "HostFloppy"); RC_CHECK();
1017 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1018
1019 hrc = medium->COMGETTER(Location)(&str); H();
1020 rc = CFGMR3InsertStringW(pCfg, "Path", str); RC_CHECK();
1021 STR_FREE();
1022 }
1023 }
1024 else
1025 {
1026 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
1027 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1028 switch (lType)
1029 {
1030 case DeviceType_DVD:
1031 rc = CFGMR3InsertString(pCfg, "Type", "DVD"); RC_CHECK();
1032 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
1033 break;
1034 case DeviceType_Floppy:
1035 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
1036 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
1037 break;
1038 case DeviceType_HardDisk:
1039 default:
1040 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); RC_CHECK();
1041 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); RC_CHECK();
1042 }
1043
1044 if (!medium.isNull())
1045 {
1046 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1047 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK();
1048 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
1049
1050 hrc = medium->COMGETTER(Location)(&str); H();
1051 rc = CFGMR3InsertStringW(pCfg, "Path", str); RC_CHECK();
1052 STR_FREE();
1053
1054 hrc = medium->COMGETTER(Format)(&str); H();
1055 rc = CFGMR3InsertStringW(pCfg, "Format", str); RC_CHECK();
1056 STR_FREE();
1057
1058 /* DVDs are always readonly */
1059 if (lType == DeviceType_DVD)
1060 {
1061 rc = CFGMR3InsertInteger(pCfg, "ReadOnly", 1); RC_CHECK();
1062 }
1063
1064 /* Pass all custom parameters. */
1065 bool fHostIP = true;
1066 SafeArray<BSTR> names;
1067 SafeArray<BSTR> values;
1068 hrc = medium->GetProperties(NULL,
1069 ComSafeArrayAsOutParam(names),
1070 ComSafeArrayAsOutParam(values)); H();
1071
1072 if (names.size() != 0)
1073 {
1074 PCFGMNODE pVDC;
1075 rc = CFGMR3InsertNode(pCfg, "VDConfig", &pVDC); RC_CHECK();
1076 for (size_t ii = 0; ii < names.size(); ++ii)
1077 {
1078 if (values[ii] && *values[ii])
1079 {
1080 Utf8Str name = names[ii];
1081 Utf8Str value = values[ii];
1082 rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str()); AssertRC(rc); /** @todo r=bird: why not RC_CHECK() here? (I added the AssertRC.)*/
1083 if ( name.compare("HostIPStack") == 0
1084 && value.compare("0") == 0)
1085 fHostIP = false;
1086 }
1087 }
1088 }
1089
1090 /* Create an inversed tree of parents. */
1091 ComPtr<IMedium> parentMedium = medium;
1092 for (PCFGMNODE pParent = pCfg;;)
1093 {
1094 hrc = parentMedium->COMGETTER(Parent)(medium.asOutParam()); H();
1095 if (medium.isNull())
1096 break;
1097
1098 PCFGMNODE pCur;
1099 rc = CFGMR3InsertNode(pParent, "Parent", &pCur); RC_CHECK();
1100 hrc = medium->COMGETTER(Location)(&str); H();
1101 rc = CFGMR3InsertStringW(pCur, "Path", str); RC_CHECK();
1102 STR_FREE();
1103
1104 hrc = medium->COMGETTER(Format)(&str); H();
1105 rc = CFGMR3InsertStringW(pCur, "Format", str); RC_CHECK();
1106 STR_FREE();
1107
1108 /* Pass all custom parameters. */
1109 SafeArray<BSTR> names;
1110 SafeArray<BSTR> values;
1111 hrc = medium->GetProperties(NULL,
1112 ComSafeArrayAsOutParam(names),
1113 ComSafeArrayAsOutParam(values)); H();
1114
1115 if (names.size() != 0)
1116 {
1117 PCFGMNODE pVDC;
1118 rc = CFGMR3InsertNode(pCur, "VDConfig", &pVDC); RC_CHECK();
1119 for (size_t ii = 0; ii < names.size(); ++ii)
1120 {
1121 if (values[ii])
1122 {
1123 Utf8Str name = names[ii];
1124 Utf8Str value = values[ii];
1125 rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str()); AssertRC(rc); /** @todo r=bird: why not RC_HCECK here? (I added the AssertRC.)*/
1126 if ( name.compare("HostIPStack") == 0
1127 && value.compare("0") == 0)
1128 fHostIP = false;
1129 }
1130 }
1131 }
1132
1133 /* Custom code: put marker to not use host IP stack to driver
1134 * configuration node. Simplifies life of DrvVD a bit. */
1135 if (!fHostIP)
1136 {
1137 rc = CFGMR3InsertInteger(pCfg, "HostIPStack", 0); RC_CHECK();
1138 }
1139
1140 /* next */
1141 pParent = pCur;
1142 parentMedium = medium;
1143 }
1144 }
1145 }
1146 }
1147 H();
1148 }
1149 H();
1150
1151 /*
1152 * Network adapters
1153 */
1154#ifdef VMWARE_NET_IN_SLOT_11
1155 bool fSwapSlots3and11 = false;
1156#endif
1157 PCFGMNODE pDevPCNet = NULL; /* PCNet-type devices */
1158 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDevPCNet); RC_CHECK();
1159#ifdef VBOX_WITH_E1000
1160 PCFGMNODE pDevE1000 = NULL; /* E1000-type devices */
1161 rc = CFGMR3InsertNode(pDevices, "e1000", &pDevE1000); RC_CHECK();
1162#endif
1163#ifdef VBOX_WITH_VIRTIO
1164 PCFGMNODE pDevVirtioNet = NULL; /* Virtio network devices */
1165 rc = CFGMR3InsertNode(pDevices, "virtio-net", &pDevVirtioNet); RC_CHECK();
1166#endif /* VBOX_WITH_VIRTIO */
1167 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ++ulInstance)
1168 {
1169 ComPtr<INetworkAdapter> networkAdapter;
1170 hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H();
1171 BOOL fEnabled = FALSE;
1172 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabled); H();
1173 if (!fEnabled)
1174 continue;
1175
1176 /*
1177 * The virtual hardware type. Create appropriate device first.
1178 */
1179 const char *pszAdapterName = "pcnet";
1180 NetworkAdapterType_T adapterType;
1181 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H();
1182 switch (adapterType)
1183 {
1184 case NetworkAdapterType_Am79C970A:
1185 case NetworkAdapterType_Am79C973:
1186 pDev = pDevPCNet;
1187 break;
1188#ifdef VBOX_WITH_E1000
1189 case NetworkAdapterType_I82540EM:
1190 case NetworkAdapterType_I82543GC:
1191 case NetworkAdapterType_I82545EM:
1192 pDev = pDevE1000;
1193 pszAdapterName = "e1000";
1194 break;
1195#endif
1196#ifdef VBOX_WITH_VIRTIO
1197 case NetworkAdapterType_Virtio:
1198 pDev = pDevVirtioNet;
1199 pszAdapterName = "virtio";
1200 break;
1201#endif /* VBOX_WITH_VIRTIO */
1202 default:
1203 AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'",
1204 adapterType, ulInstance));
1205 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
1206 N_("Invalid network adapter type '%d' for slot '%d'"),
1207 adapterType, ulInstance);
1208 }
1209
1210 rc = CFGMR3InsertNodeF(pDev, &pInst, "%u", ulInstance); RC_CHECK();
1211 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1212 /* the first network card gets the PCI ID 3, the next 3 gets 8..10,
1213 * next 4 get 16..19. */
1214 unsigned iPciDeviceNo = 3;
1215 if (ulInstance)
1216 {
1217 if (ulInstance < 4)
1218 iPciDeviceNo = ulInstance - 1 + 8;
1219 else
1220 iPciDeviceNo = ulInstance - 4 + 16;
1221 }
1222#ifdef VMWARE_NET_IN_SLOT_11
1223 /*
1224 * Dirty hack for PCI slot compatibility with VMWare,
1225 * it assigns slot 11 to the first network controller.
1226 */
1227 if (iPciDeviceNo == 3 && adapterType == NetworkAdapterType_I82545EM)
1228 {
1229 iPciDeviceNo = 0x11;
1230 fSwapSlots3and11 = true;
1231 }
1232 else if (iPciDeviceNo == 0x11 && fSwapSlots3and11)
1233 iPciDeviceNo = 3;
1234#endif
1235 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", iPciDeviceNo); RC_CHECK();
1236 Assert(!afPciDeviceNo[iPciDeviceNo]);
1237 afPciDeviceNo[iPciDeviceNo] = true;
1238 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1239 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1240#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */
1241 if (pDev == pDevPCNet)
1242 {
1243 rc = CFGMR3InsertInteger(pCfg, "R0Enabled", false); RC_CHECK();
1244 }
1245#endif
1246
1247 /*
1248 * The virtual hardware type. PCNet supports two types.
1249 */
1250 switch (adapterType)
1251 {
1252 case NetworkAdapterType_Am79C970A:
1253 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 0); RC_CHECK();
1254 break;
1255 case NetworkAdapterType_Am79C973:
1256 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 1); RC_CHECK();
1257 break;
1258 case NetworkAdapterType_I82540EM:
1259 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 0); RC_CHECK();
1260 break;
1261 case NetworkAdapterType_I82543GC:
1262 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 1); RC_CHECK();
1263 break;
1264 case NetworkAdapterType_I82545EM:
1265 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 2); RC_CHECK();
1266 break;
1267 }
1268
1269 /*
1270 * Get the MAC address and convert it to binary representation
1271 */
1272 Bstr macAddr;
1273 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H();
1274 Assert(macAddr);
1275 Utf8Str macAddrUtf8 = macAddr;
1276 char *macStr = (char*)macAddrUtf8.raw();
1277 Assert(strlen(macStr) == 12);
1278 RTMAC Mac;
1279 memset(&Mac, 0, sizeof(Mac));
1280 char *pMac = (char*)&Mac;
1281 for (uint32_t i = 0; i < 6; ++i)
1282 {
1283 char c1 = *macStr++ - '0';
1284 if (c1 > 9)
1285 c1 -= 7;
1286 char c2 = *macStr++ - '0';
1287 if (c2 > 9)
1288 c2 -= 7;
1289 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
1290 }
1291 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK();
1292
1293 /*
1294 * Check if the cable is supposed to be unplugged
1295 */
1296 BOOL fCableConnected;
1297 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H();
1298 rc = CFGMR3InsertInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0); RC_CHECK();
1299
1300 /*
1301 * Line speed to report from custom drivers
1302 */
1303 ULONG ulLineSpeed;
1304 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H();
1305 rc = CFGMR3InsertInteger(pCfg, "LineSpeed", ulLineSpeed); RC_CHECK();
1306
1307 /*
1308 * Attach the status driver.
1309 */
1310 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1311 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1312 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1313 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapNetworkLeds[ulInstance]); RC_CHECK();
1314
1315 /*
1316 * Configure the network card now
1317 */
1318 rc = configNetwork(pConsole, pszAdapterName, ulInstance, 0, networkAdapter,
1319 pCfg, pLunL0, pInst, false /*fAttachDetach*/); RC_CHECK();
1320 }
1321
1322 /*
1323 * Serial (UART) Ports
1324 */
1325 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); RC_CHECK();
1326 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ++ulInstance)
1327 {
1328 ComPtr<ISerialPort> serialPort;
1329 hrc = pMachine->GetSerialPort (ulInstance, serialPort.asOutParam()); H();
1330 BOOL fEnabled = FALSE;
1331 if (serialPort)
1332 hrc = serialPort->COMGETTER(Enabled)(&fEnabled); H();
1333 if (!fEnabled)
1334 continue;
1335
1336 rc = CFGMR3InsertNodeF(pDev, &pInst, "%u", ulInstance); RC_CHECK();
1337 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1338
1339 ULONG ulIRQ;
1340 hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H();
1341 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1342 ULONG ulIOBase;
1343 hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H();
1344 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1345 BOOL fServer;
1346 hrc = serialPort->COMGETTER(Server)(&fServer); H();
1347 hrc = serialPort->COMGETTER(Path)(&str); H();
1348 PortMode_T eHostMode;
1349 hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H();
1350 if (eHostMode != PortMode_Disconnected)
1351 {
1352 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1353 if (eHostMode == PortMode_HostPipe)
1354 {
1355 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK();
1356 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1357 rc = CFGMR3InsertString(pLunL1, "Driver", "NamedPipe"); RC_CHECK();
1358 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK();
1359 rc = CFGMR3InsertStringW(pLunL2, "Location", str); RC_CHECK();
1360 rc = CFGMR3InsertInteger(pLunL2, "IsServer", fServer); RC_CHECK();
1361 }
1362 else if (eHostMode == PortMode_HostDevice)
1363 {
1364 rc = CFGMR3InsertString(pLunL0, "Driver", "Host Serial"); RC_CHECK();
1365 rc = CFGMR3InsertNode(pLunL0, "Config", &pLunL1); RC_CHECK();
1366 rc = CFGMR3InsertStringW(pLunL1, "DevicePath", str); RC_CHECK();
1367 }
1368 else if (eHostMode == PortMode_RawFile)
1369 {
1370 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK();
1371 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1372 rc = CFGMR3InsertString(pLunL1, "Driver", "RawFile"); RC_CHECK();
1373 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK();
1374 rc = CFGMR3InsertStringW(pLunL2, "Location", str); RC_CHECK();
1375 }
1376 }
1377 STR_FREE();
1378 }
1379
1380 /*
1381 * Parallel (LPT) Ports
1382 */
1383 rc = CFGMR3InsertNode(pDevices, "parallel", &pDev); RC_CHECK();
1384 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ++ulInstance)
1385 {
1386 ComPtr<IParallelPort> parallelPort;
1387 hrc = pMachine->GetParallelPort(ulInstance, parallelPort.asOutParam()); H();
1388 BOOL fEnabled = FALSE;
1389 if (parallelPort)
1390 {
1391 hrc = parallelPort->COMGETTER(Enabled)(&fEnabled); H();
1392 }
1393 if (!fEnabled)
1394 continue;
1395
1396 rc = CFGMR3InsertNodeF(pDev, &pInst, "%u", ulInstance); RC_CHECK();
1397 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1398
1399 ULONG ulIRQ;
1400 hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ); H();
1401 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1402 ULONG ulIOBase;
1403 hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase); H();
1404 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1405 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1406 rc = CFGMR3InsertString(pLunL0, "Driver", "HostParallel"); RC_CHECK();
1407 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1408 hrc = parallelPort->COMGETTER(Path)(&str); H();
1409 rc = CFGMR3InsertStringW(pLunL1, "DevicePath", str); RC_CHECK();
1410 STR_FREE();
1411 }
1412
1413 /*
1414 * VMM Device
1415 */
1416 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); RC_CHECK();
1417 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1418 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1419 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1420 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); RC_CHECK();
1421 Assert(!afPciDeviceNo[4]);
1422 afPciDeviceNo[4] = true;
1423 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1424 Bstr hwVersion;
1425 hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam()); H();
1426 if (hwVersion.compare(Bstr("1")) == 0) /* <= 2.0.x */
1427 {
1428 CFGMR3InsertInteger(pCfg, "HeapEnabled", 0); RC_CHECK();
1429 }
1430
1431 /* the VMM device's Main driver */
1432 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1433 rc = CFGMR3InsertString(pLunL0, "Driver", "HGCM"); RC_CHECK();
1434 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1435 VMMDev *pVMMDev = pConsole->mVMMDev;
1436 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pVMMDev); RC_CHECK();
1437
1438 /*
1439 * Attach the status driver.
1440 */
1441 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1442 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1443 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1444 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSharedFolderLed); RC_CHECK();
1445 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1446 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1447
1448 /*
1449 * Audio Sniffer Device
1450 */
1451 rc = CFGMR3InsertNode(pDevices, "AudioSniffer", &pDev); RC_CHECK();
1452 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1453 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1454
1455 /* the Audio Sniffer device's Main driver */
1456 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1457 rc = CFGMR3InsertString(pLunL0, "Driver", "MainAudioSniffer"); RC_CHECK();
1458 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1459 AudioSniffer *pAudioSniffer = pConsole->mAudioSniffer;
1460 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); RC_CHECK();
1461
1462 /*
1463 * AC'97 ICH / SoundBlaster16 audio
1464 */
1465 BOOL enabled;
1466 ComPtr<IAudioAdapter> audioAdapter;
1467 hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H();
1468 if (audioAdapter)
1469 hrc = audioAdapter->COMGETTER(Enabled)(&enabled); H();
1470
1471 if (enabled)
1472 {
1473 AudioControllerType_T audioController;
1474 hrc = audioAdapter->COMGETTER(AudioController)(&audioController); H();
1475 switch (audioController)
1476 {
1477 case AudioControllerType_AC97:
1478 {
1479 /* default: ICH AC97 */
1480 rc = CFGMR3InsertNode(pDevices, "ichac97", &pDev); RC_CHECK();
1481 rc = CFGMR3InsertNode(pDev, "0", &pInst);
1482 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK();
1483 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 5); RC_CHECK();
1484 Assert(!afPciDeviceNo[5]);
1485 afPciDeviceNo[5] = true;
1486 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1487 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1488 break;
1489 }
1490 case AudioControllerType_SB16:
1491 {
1492 /* legacy SoundBlaster16 */
1493 rc = CFGMR3InsertNode(pDevices, "sb16", &pDev); RC_CHECK();
1494 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1495 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK();
1496 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1497 rc = CFGMR3InsertInteger(pCfg, "IRQ", 5); RC_CHECK();
1498 rc = CFGMR3InsertInteger(pCfg, "DMA", 1); RC_CHECK();
1499 rc = CFGMR3InsertInteger(pCfg, "DMA16", 5); RC_CHECK();
1500 rc = CFGMR3InsertInteger(pCfg, "Port", 0x220); RC_CHECK();
1501 rc = CFGMR3InsertInteger(pCfg, "Version", 0x0405); RC_CHECK();
1502 break;
1503 }
1504 }
1505
1506 /* the Audio driver */
1507 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1508 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
1509 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1510
1511 AudioDriverType_T audioDriver;
1512 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H();
1513 switch (audioDriver)
1514 {
1515 case AudioDriverType_Null:
1516 {
1517 rc = CFGMR3InsertString(pCfg, "AudioDriver", "null"); RC_CHECK();
1518 break;
1519 }
1520#ifdef RT_OS_WINDOWS
1521#ifdef VBOX_WITH_WINMM
1522 case AudioDriverType_WinMM:
1523 {
1524 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); RC_CHECK();
1525 break;
1526 }
1527#endif
1528 case AudioDriverType_DirectSound:
1529 {
1530 rc = CFGMR3InsertString(pCfg, "AudioDriver", "dsound"); RC_CHECK();
1531 break;
1532 }
1533#endif /* RT_OS_WINDOWS */
1534#ifdef RT_OS_SOLARIS
1535 case AudioDriverType_SolAudio:
1536 {
1537 rc = CFGMR3InsertString(pCfg, "AudioDriver", "solaudio"); RC_CHECK();
1538 break;
1539 }
1540#endif
1541#ifdef RT_OS_LINUX
1542# ifdef VBOX_WITH_ALSA
1543 case AudioDriverType_ALSA:
1544 {
1545 rc = CFGMR3InsertString(pCfg, "AudioDriver", "alsa"); RC_CHECK();
1546 break;
1547 }
1548# endif
1549# ifdef VBOX_WITH_PULSE
1550 case AudioDriverType_Pulse:
1551 {
1552 rc = CFGMR3InsertString(pCfg, "AudioDriver", "pulse"); RC_CHECK();
1553 break;
1554 }
1555# endif
1556#endif /* RT_OS_LINUX */
1557#if defined (RT_OS_LINUX) || defined (RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)
1558 case AudioDriverType_OSS:
1559 {
1560 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); RC_CHECK();
1561 break;
1562 }
1563#endif
1564#ifdef RT_OS_DARWIN
1565 case AudioDriverType_CoreAudio:
1566 {
1567 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); RC_CHECK();
1568 break;
1569 }
1570#endif
1571 }
1572 hrc = pMachine->COMGETTER(Name)(&str); H();
1573 rc = CFGMR3InsertStringW(pCfg, "StreamName", str); RC_CHECK();
1574 STR_FREE();
1575 }
1576
1577 /*
1578 * The USB Controller.
1579 */
1580 ComPtr<IUSBController> USBCtlPtr;
1581 hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam());
1582 if (USBCtlPtr)
1583 {
1584 BOOL fEnabled;
1585 hrc = USBCtlPtr->COMGETTER(Enabled)(&fEnabled); H();
1586 if (fEnabled)
1587 {
1588 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); RC_CHECK();
1589 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1590 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1591 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1592 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); RC_CHECK();
1593 Assert(!afPciDeviceNo[6]);
1594 afPciDeviceNo[6] = true;
1595 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1596
1597 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1598 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1599 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1600
1601 /*
1602 * Attach the status driver.
1603 */
1604 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1605 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1606 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1607 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[0]);RC_CHECK();
1608 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1609 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1610
1611#ifdef VBOX_WITH_EHCI
1612 hrc = USBCtlPtr->COMGETTER(EnabledEhci)(&fEnabled); H();
1613 if (fEnabled)
1614 {
1615 rc = CFGMR3InsertNode(pDevices, "usb-ehci", &pDev); RC_CHECK();
1616 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1617 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1618 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK();
1619 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 11); RC_CHECK();
1620 Assert(!afPciDeviceNo[11]);
1621 afPciDeviceNo[11] = true;
1622 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1623
1624 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1625 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1626 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1627
1628 /*
1629 * Attach the status driver.
1630 */
1631 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1632 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1633 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1634 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[1]);RC_CHECK();
1635 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1636 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1637 }
1638 else
1639#endif
1640 {
1641 /*
1642 * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
1643 * on a per device level now.
1644 */
1645 rc = CFGMR3InsertNode(pRoot, "USB", &pCfg); RC_CHECK();
1646 rc = CFGMR3InsertNode(pCfg, "USBProxy", &pCfg); RC_CHECK();
1647 rc = CFGMR3InsertNode(pCfg, "GlobalConfig", &pCfg); RC_CHECK();
1648 // This globally enables the 2.0 -> 1.1 device morphing of proxied devies to keep windows quiet.
1649 //rc = CFGMR3InsertInteger(pCfg, "Force11Device", true); RC_CHECK();
1650 // The following breaks stuff, but it makes MSDs work in vista. (I include it here so
1651 // that it's documented somewhere.) Users needing it can use:
1652 // VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
1653 //rc = CFGMR3InsertInteger(pCfg, "Force11PacketSize", true); RC_CHECK();
1654 }
1655 }
1656 }
1657
1658 /*
1659 * Clipboard
1660 */
1661 {
1662 ClipboardMode_T mode = ClipboardMode_Disabled;
1663 hrc = pMachine->COMGETTER(ClipboardMode)(&mode); H();
1664
1665 if (mode != ClipboardMode_Disabled)
1666 {
1667 /* Load the service */
1668 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedClipboard", "VBoxSharedClipboard");
1669
1670 if (RT_FAILURE(rc))
1671 {
1672 LogRel(("VBoxSharedClipboard is not available. rc = %Rrc\n", rc));
1673 /* That is not a fatal failure. */
1674 rc = VINF_SUCCESS;
1675 }
1676 else
1677 {
1678 /* Setup the service. */
1679 VBOXHGCMSVCPARM parm;
1680
1681 parm.type = VBOX_HGCM_SVC_PARM_32BIT;
1682
1683 switch (mode)
1684 {
1685 default:
1686 case ClipboardMode_Disabled:
1687 {
1688 LogRel(("VBoxSharedClipboard mode: Off\n"));
1689 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
1690 break;
1691 }
1692 case ClipboardMode_GuestToHost:
1693 {
1694 LogRel(("VBoxSharedClipboard mode: Guest to Host\n"));
1695 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
1696 break;
1697 }
1698 case ClipboardMode_HostToGuest:
1699 {
1700 LogRel(("VBoxSharedClipboard mode: Host to Guest\n"));
1701 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
1702 break;
1703 }
1704 case ClipboardMode_Bidirectional:
1705 {
1706 LogRel(("VBoxSharedClipboard mode: Bidirectional\n"));
1707 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
1708 break;
1709 }
1710 }
1711
1712 pConsole->mVMMDev->hgcmHostCall ("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
1713
1714 Log(("Set VBoxSharedClipboard mode\n"));
1715 }
1716 }
1717 }
1718
1719#ifdef VBOX_WITH_CROGL
1720 /*
1721 * crOpenGL
1722 */
1723 {
1724 BOOL fEnabled = false;
1725 hrc = pMachine->COMGETTER(Accelerate3DEnabled)(&fEnabled); H();
1726
1727 if (fEnabled)
1728 {
1729 /* Load the service */
1730 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedCrOpenGL", "VBoxSharedCrOpenGL");
1731 if (RT_FAILURE(rc))
1732 {
1733 LogRel(("Failed to load Shared OpenGL service %Rrc\n", rc));
1734 /* That is not a fatal failure. */
1735 rc = VINF_SUCCESS;
1736 }
1737 else
1738 {
1739 LogRel(("Shared crOpenGL service loaded.\n"));
1740
1741 /* Setup the service. */
1742 VBOXHGCMSVCPARM parm;
1743 parm.type = VBOX_HGCM_SVC_PARM_PTR;
1744
1745 parm.u.pointer.addr = pConsole->getDisplay()->getFramebuffer();
1746 parm.u.pointer.size = sizeof(IFramebuffer *);
1747
1748 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_FRAMEBUFFER, 1, &parm);
1749 if (!RT_SUCCESS(rc))
1750 AssertMsgFailed(("SHCRGL_HOST_FN_SET_FRAMEBUFFER failed with %Rrc\n", rc));
1751
1752 parm.u.pointer.addr = pVM;
1753 parm.u.pointer.size = sizeof(pVM);
1754 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VM, 1, &parm);
1755 if (!RT_SUCCESS(rc))
1756 AssertMsgFailed(("SHCRGL_HOST_FN_SET_VM failed with %Rrc\n", rc));
1757 }
1758
1759 }
1760 }
1761#endif
1762
1763#ifdef VBOX_WITH_GUEST_PROPS
1764 /*
1765 * Guest property service
1766 */
1767
1768 rc = configGuestProperties(pConsole);
1769#endif /* VBOX_WITH_GUEST_PROPS defined */
1770
1771 /*
1772 * CFGM overlay handling.
1773 *
1774 * Here we check the extra data entries for CFGM values
1775 * and create the nodes and insert the values on the fly. Existing
1776 * values will be removed and reinserted. CFGM is typed, so by default
1777 * we will guess whether it's a string or an integer (byte arrays are
1778 * not currently supported). It's possible to override this autodetection
1779 * by adding "string:", "integer:" or "bytes:" (future).
1780 *
1781 * We first perform a run on global extra data, then on the machine
1782 * extra data to support global settings with local overrides.
1783 *
1784 */
1785 /** @todo add support for removing nodes and byte blobs. */
1786 SafeArray<BSTR> aGlobalExtraDataKeys;
1787 SafeArray<BSTR> aMachineExtraDataKeys;
1788 /*
1789 * Get the next key
1790 */
1791 if (FAILED(hrc = virtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys))))
1792 AssertMsgFailed(("VirtualBox::GetExtraDataKeys failed with %Rrc\n", hrc));
1793
1794 // remember the no. of global values so we can call the correct method below
1795 size_t cGlobalValues = aGlobalExtraDataKeys.size();
1796
1797 if (FAILED(hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys))))
1798 AssertMsgFailed(("IMachine::GetExtraDataKeys failed with %Rrc\n", hrc));
1799
1800 // build a combined list from global keys...
1801 std::list<Utf8Str> llExtraDataKeys;
1802 size_t i = 0;
1803
1804 for (i = 0; i < aGlobalExtraDataKeys.size(); ++i)
1805 llExtraDataKeys.push_back(Utf8Str(aGlobalExtraDataKeys[i]));
1806 // ... and machine keys
1807 for (i = 0; i < aMachineExtraDataKeys.size(); ++i)
1808 llExtraDataKeys.push_back(Utf8Str(aMachineExtraDataKeys[i]));
1809
1810 i = 0;
1811 for (std::list<Utf8Str>::const_iterator it = llExtraDataKeys.begin();
1812 it != llExtraDataKeys.end();
1813 ++it, ++i)
1814 {
1815 const Utf8Str &strKey = *it;
1816
1817 /*
1818 * We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:")
1819 */
1820 if (!strKey.startsWith("VBoxInternal/"))
1821 continue;
1822
1823 const char *pszExtraDataKey = strKey.raw() + sizeof("VBoxInternal/") - 1;
1824
1825 // get the value
1826 Bstr strExtraDataValue;
1827 if (i < cGlobalValues)
1828 // this is still one of the global values:
1829 hrc = virtualBox->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam());
1830 else
1831 hrc = pMachine->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam());
1832 if (FAILED(hrc))
1833 LogRel(("Warning: Cannot get extra data key %s, rc = %Rrc\n", strKey.raw(), hrc));
1834
1835 /*
1836 * The key will be in the format "Node1/Node2/Value" or simply "Value".
1837 * Split the two and get the node, delete the value and create the node
1838 * if necessary.
1839 */
1840 PCFGMNODE pNode;
1841 const char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
1842 if (pszCFGMValueName)
1843 {
1844 /* terminate the node and advance to the value (Utf8Str might not
1845 offically like this but wtf) */
1846 *(char*)pszCFGMValueName = '\0';
1847 ++pszCFGMValueName;
1848
1849 /* does the node already exist? */
1850 pNode = CFGMR3GetChild(pRoot, pszExtraDataKey);
1851 if (pNode)
1852 CFGMR3RemoveValue(pNode, pszCFGMValueName);
1853 else
1854 {
1855 /* create the node */
1856 rc = CFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode);
1857 if (RT_FAILURE(rc))
1858 {
1859 AssertLogRelMsgRC(rc, ("failed to insert node '%s'\n", pszExtraDataKey));
1860 continue;
1861 }
1862 Assert(pNode);
1863 }
1864 }
1865 else
1866 {
1867 /* root value (no node path). */
1868 pNode = pRoot;
1869 pszCFGMValueName = pszExtraDataKey;
1870 pszExtraDataKey--;
1871 CFGMR3RemoveValue(pNode, pszCFGMValueName);
1872 }
1873
1874 /*
1875 * Now let's have a look at the value.
1876 * Empty strings means that we should remove the value, which we've
1877 * already done above.
1878 */
1879 Utf8Str strCFGMValueUtf8(strExtraDataValue);
1880 const char *pszCFGMValue = strCFGMValueUtf8.raw();
1881 if ( pszCFGMValue
1882 && *pszCFGMValue)
1883 {
1884 uint64_t u64Value;
1885
1886 /* check for type prefix first. */
1887 if (!strncmp(pszCFGMValue, "string:", sizeof("string:") - 1))
1888 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue + sizeof("string:") - 1);
1889 else if (!strncmp(pszCFGMValue, "integer:", sizeof("integer:") - 1))
1890 {
1891 rc = RTStrToUInt64Full(pszCFGMValue + sizeof("integer:") - 1, 0, &u64Value);
1892 if (RT_SUCCESS(rc))
1893 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
1894 }
1895 else if (!strncmp(pszCFGMValue, "bytes:", sizeof("bytes:") - 1))
1896 rc = VERR_NOT_IMPLEMENTED;
1897 /* auto detect type. */
1898 else if (RT_SUCCESS(RTStrToUInt64Full(pszCFGMValue, 0, &u64Value)))
1899 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
1900 else
1901 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue);
1902 AssertLogRelMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszExtraDataKey));
1903 }
1904 }
1905
1906 /*
1907 * ACPI
1908 */
1909 BOOL fACPI;
1910 hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI); H();
1911 if (fACPI)
1912 {
1913 BOOL fShowCpu = fExtProfile;
1914 /* Always show the CPU leafs when we have multiple VCPUs or when the IO-APIC is enabled.
1915 * The Windows SMP kernel needs a CPU leaf or else its idle loop will burn cpu cycles; the
1916 * intelppm driver refuses to register an idle state handler.
1917 */
1918 if ((cCpus > 1) || fIOAPIC)
1919 fShowCpu = true;
1920
1921 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); RC_CHECK();
1922 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1923 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1924 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1925 rc = CFGMR3InsertInteger(pCfg, "RamSize", cbRam); RC_CHECK();
1926 rc = CFGMR3InsertInteger(pCfg, "RamHoleSize", cbRamHole); RC_CHECK();
1927 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK();
1928
1929 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
1930 rc = CFGMR3InsertInteger(pCfg, "FdcEnabled", fFdcEnabled); RC_CHECK();
1931#ifdef VBOX_WITH_HPET
1932 rc = CFGMR3InsertInteger(pCfg, "HpetEnabled", fHpetEnabled); RC_CHECK();
1933#endif
1934#ifdef VBOX_WITH_SMC
1935 rc = CFGMR3InsertInteger(pCfg, "SmcEnabled", fSmcEnabled); RC_CHECK();
1936#endif
1937 rc = CFGMR3InsertInteger(pCfg, "ShowRtc", fExtProfile); RC_CHECK();
1938
1939 rc = CFGMR3InsertInteger(pCfg, "ShowCpu", fShowCpu); RC_CHECK();
1940 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); RC_CHECK();
1941 Assert(!afPciDeviceNo[7]);
1942 afPciDeviceNo[7] = true;
1943 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1944
1945 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1946 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); RC_CHECK();
1947 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1948 }
1949
1950#undef STR_FREE
1951#undef H
1952#undef RC_CHECK
1953
1954 /* Register VM state change handler */
1955 int rc2 = VMR3AtStateRegister (pVM, Console::vmstateChangeCallback, pConsole);
1956 AssertRC (rc2);
1957 if (RT_SUCCESS(rc))
1958 rc = rc2;
1959
1960 /* Register VM runtime error handler */
1961 rc2 = VMR3AtRuntimeErrorRegister (pVM, Console::setVMRuntimeErrorCallback, pConsole);
1962 AssertRC (rc2);
1963 if (RT_SUCCESS(rc))
1964 rc = rc2;
1965
1966 LogFlowFunc (("vrc = %Rrc\n", rc));
1967 LogFlowFuncLeave();
1968
1969 return rc;
1970}
1971
1972/**
1973 * Ellipsis to va_list wrapper for calling setVMRuntimeErrorCallback.
1974 */
1975/*static*/ void Console::setVMRuntimeErrorCallbackF(PVM pVM, void *pvConsole, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
1976{
1977 va_list va;
1978 va_start(va, pszFormat);
1979 setVMRuntimeErrorCallback(pVM, pvConsole, fFlags, pszErrorId, pszFormat, va);
1980 va_end(va);
1981}
1982
1983/**
1984 * Construct the Network configuration tree
1985 *
1986 * @returns VBox status code.
1987 *
1988 * @param pThis Pointer to the Console object.
1989 * @param pszDevice The PDM device name.
1990 * @param uInstance The PDM device instance.
1991 * @param uLun The PDM LUN number of the drive.
1992 * @param aNetworkAdapter The network adapter whose attachment needs to be changed
1993 * @param pCfg Configuration node for the device
1994 * @param pLunL0 To store the pointer to the LUN#0.
1995 * @param pInst The instance CFGM node
1996 * @param fAttachDetach To determine if the network attachment should
1997 * be attached/detached after/before
1998 * configuration.
1999 *
2000 * @note Locks the Console object for writing.
2001 */
2002/*static*/ int Console::configNetwork(Console *pThis, const char *pszDevice,
2003 unsigned uInstance, unsigned uLun,
2004 INetworkAdapter *aNetworkAdapter,
2005 PCFGMNODE pCfg, PCFGMNODE pLunL0,
2006 PCFGMNODE pInst, bool fAttachDetach)
2007{
2008 int rc = VINF_SUCCESS;
2009
2010 AutoCaller autoCaller(pThis);
2011 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
2012
2013 /*
2014 * Locking the object before doing VMR3* calls is quite safe here, since
2015 * we're on EMT. Write lock is necessary because we indirectly modify the
2016 * meAttachmentType member.
2017 */
2018 AutoWriteLock alock(pThis);
2019
2020 PVM pVM = pThis->mpVM;
2021 BSTR str = NULL;
2022
2023#define STR_FREE() do { if (str) { SysFreeString(str); str = NULL; } } while (0)
2024#define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); STR_FREE(); return rc; } } while (0)
2025#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%#x\n", hrc)); STR_FREE(); return VERR_GENERAL_FAILURE; } } while (0)
2026
2027 HRESULT hrc;
2028 ComPtr<IMachine> pMachine = pThis->machine();
2029
2030 ComPtr<IVirtualBox> virtualBox;
2031 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam());
2032 H();
2033
2034 ComPtr<IHost> host;
2035 hrc = virtualBox->COMGETTER(Host)(host.asOutParam());
2036 H();
2037
2038 BOOL fSniffer;
2039 hrc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fSniffer);
2040 H();
2041
2042 if (fAttachDetach && fSniffer)
2043 {
2044 const char *pszNetDriver = "IntNet";
2045 if (pThis->meAttachmentType[uInstance] == NetworkAttachmentType_NAT)
2046 pszNetDriver = "NAT";
2047#if !defined(VBOX_WITH_NETFLT) && defined(RT_OS_LINUX)
2048 if (pThis->meAttachmentType[uInstance] == NetworkAttachmentType_Bridged)
2049 pszNetDriver = "HostInterface";
2050#endif
2051
2052 rc = PDMR3DriverDetach(pVM, pszDevice, uInstance, uLun, pszNetDriver, 0, 0 /*fFlags*/);
2053 if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN)
2054 rc = VINF_SUCCESS;
2055 AssertLogRelRCReturn(rc, rc);
2056
2057 pLunL0 = CFGMR3GetChildF(pInst, "LUN#%u", uLun);
2058 PCFGMNODE pLunAD = CFGMR3GetChildF(pLunL0, "AttachedDriver");
2059 if (pLunAD)
2060 {
2061 CFGMR3RemoveNode(pLunAD);
2062 }
2063 else
2064 {
2065 CFGMR3RemoveNode(pLunL0);
2066 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
2067 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK();
2068 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2069 hrc = aNetworkAdapter->COMGETTER(TraceFile)(&str); H();
2070 if (str) /* check convention for indicating default file. */
2071 {
2072 rc = CFGMR3InsertStringW(pCfg, "File", str); RC_CHECK();
2073 }
2074 STR_FREE();
2075 }
2076 }
2077 else if (fAttachDetach && !fSniffer)
2078 {
2079 rc = PDMR3DeviceDetach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/);
2080 if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN)
2081 rc = VINF_SUCCESS;
2082 AssertLogRelRCReturn(rc, rc);
2083
2084 /* nuke anything which might have been left behind. */
2085 CFGMR3RemoveNode(CFGMR3GetChildF(pInst, "LUN#%u", uLun));
2086 }
2087 else if (!fAttachDetach && fSniffer)
2088 {
2089 /* insert the sniffer filter driver. */
2090 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
2091 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK();
2092 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2093 hrc = aNetworkAdapter->COMGETTER(TraceFile)(&str); H();
2094 if (str) /* check convention for indicating default file. */
2095 {
2096 rc = CFGMR3InsertStringW(pCfg, "File", str); RC_CHECK();
2097 }
2098 STR_FREE();
2099 }
2100
2101 Bstr networkName, trunkName, trunkType;
2102 NetworkAttachmentType_T eAttachmentType;
2103 hrc = aNetworkAdapter->COMGETTER(AttachmentType)(&eAttachmentType); H();
2104 switch (eAttachmentType)
2105 {
2106 case NetworkAttachmentType_Null:
2107 break;
2108
2109 case NetworkAttachmentType_NAT:
2110 {
2111 if (fSniffer)
2112 {
2113 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
2114 }
2115 else
2116 {
2117 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
2118 }
2119 rc = CFGMR3InsertString(pLunL0, "Driver", "NAT"); RC_CHECK();
2120 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2121
2122 /* Configure TFTP prefix and boot filename. */
2123 hrc = virtualBox->COMGETTER(HomeFolder)(&str); H();
2124 if (str && *str)
2125 {
2126 rc = CFGMR3InsertStringF(pCfg, "TFTPPrefix", "%ls%c%s", str, RTPATH_DELIMITER, "TFTP"); RC_CHECK();
2127 }
2128 STR_FREE();
2129 hrc = pMachine->COMGETTER(Name)(&str); H();
2130 rc = CFGMR3InsertStringF(pCfg, "BootFile", "%ls.pxe", str); RC_CHECK();
2131 STR_FREE();
2132
2133 hrc = aNetworkAdapter->COMGETTER(NATNetwork)(&str); H();
2134 if (str && *str)
2135 {
2136 rc = CFGMR3InsertStringW(pCfg, "Network", str); RC_CHECK();
2137 /* NAT uses its own DHCP implementation */
2138 //networkName = Bstr(psz);
2139 }
2140 STR_FREE();
2141 break;
2142 }
2143
2144 case NetworkAttachmentType_Bridged:
2145 {
2146#if (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)) && !defined(VBOX_WITH_NETFLT)
2147 hrc = pThis->attachToTapInterface(aNetworkAdapter);
2148 if (FAILED(hrc))
2149 {
2150 switch (hrc)
2151 {
2152 case VERR_ACCESS_DENIED:
2153 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
2154 "Failed to open '/dev/net/tun' for read/write access. Please check the "
2155 "permissions of that node. Either run 'chmod 0666 /dev/net/tun' or "
2156 "change the group of that node and make yourself a member of that group. Make "
2157 "sure that these changes are permanent, especially if you are "
2158 "using udev"));
2159 default:
2160 AssertMsgFailed(("Could not attach to host interface! Bad!\n"));
2161 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
2162 "Failed to initialize Host Interface Networking"));
2163 }
2164 }
2165
2166 Assert ((int)pThis->maTapFD[uInstance] >= 0);
2167 if ((int)pThis->maTapFD[uInstance] >= 0)
2168 {
2169 if (fSniffer)
2170 {
2171 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
2172 }
2173 else
2174 {
2175 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
2176 }
2177 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
2178 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2179 rc = CFGMR3InsertInteger(pCfg, "FileHandle", pThis->maTapFD[uInstance]); RC_CHECK();
2180 }
2181
2182#elif defined(VBOX_WITH_NETFLT)
2183 /*
2184 * This is the new VBoxNetFlt+IntNet stuff.
2185 */
2186 if (fSniffer)
2187 {
2188 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
2189 }
2190 else
2191 {
2192 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
2193 }
2194
2195 Bstr HifName;
2196 hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam());
2197 if (FAILED(hrc))
2198 {
2199 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(HostInterface) failed, hrc (0x%x)", hrc));
2200 H();
2201 }
2202
2203 Utf8Str HifNameUtf8(HifName);
2204 const char *pszHifName = HifNameUtf8.raw();
2205
2206# if defined(RT_OS_DARWIN)
2207 /* The name is on the form 'ifX: long name', chop it off at the colon. */
2208 char szTrunk[8];
2209 strncpy(szTrunk, pszHifName, sizeof(szTrunk));
2210 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
2211 if (!pszColon)
2212 {
2213 hrc = aNetworkAdapter->Detach(); H();
2214 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
2215 N_("Malformed host interface networking name '%ls'"),
2216 HifName.raw());
2217 }
2218 *pszColon = '\0';
2219 const char *pszTrunk = szTrunk;
2220
2221# elif defined(RT_OS_SOLARIS)
2222 /* The name is on the form format 'ifX[:1] - long name, chop it off at space. */
2223 char szTrunk[256];
2224 strlcpy(szTrunk, pszHifName, sizeof(szTrunk));
2225 char *pszSpace = (char *)memchr(szTrunk, ' ', sizeof(szTrunk));
2226
2227 /*
2228 * Currently don't bother about malformed names here for the sake of people using
2229 * VBoxManage and setting only the NIC name from there. If there is a space we
2230 * chop it off and proceed, otherwise just use whatever we've got.
2231 */
2232 if (pszSpace)
2233 *pszSpace = '\0';
2234
2235 /* Chop it off at the colon (zone naming eg: e1000g:1 we need only the e1000g) */
2236 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
2237 if (pszColon)
2238 *pszColon = '\0';
2239
2240 const char *pszTrunk = szTrunk;
2241
2242# elif defined(RT_OS_WINDOWS)
2243 ComPtr<IHostNetworkInterface> hostInterface;
2244 hrc = host->FindHostNetworkInterfaceByName(HifName, hostInterface.asOutParam());
2245 if (!SUCCEEDED(hrc))
2246 {
2247 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: FindByName failed, rc=%Rhrc (0x%x)", hrc, hrc));
2248 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
2249 N_("Inexistent host networking interface, name '%ls'"),
2250 HifName.raw());
2251 }
2252
2253 HostNetworkInterfaceType_T eIfType;
2254 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType);
2255 if (FAILED(hrc))
2256 {
2257 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(InterfaceType) failed, hrc (0x%x)", hrc));
2258 H();
2259 }
2260
2261 if (eIfType != HostNetworkInterfaceType_Bridged)
2262 {
2263 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
2264 N_("Interface ('%ls') is not a Bridged Adapter interface"),
2265 HifName.raw());
2266 }
2267
2268 hrc = hostInterface->COMGETTER(Id)(&str);
2269 if (FAILED(hrc))
2270 {
2271 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(Id) failed, hrc (0x%x)", hrc));
2272 H();
2273 }
2274 Guid hostIFGuid(str);
2275 STR_FREE();
2276
2277 INetCfg *pNc;
2278 ComPtr<INetCfgComponent> pAdaptorComponent;
2279 LPWSTR pszApp;
2280 int rc = VERR_INTNET_FLT_IF_NOT_FOUND;
2281
2282 hrc = VBoxNetCfgWinQueryINetCfg(FALSE /*fGetWriteLock*/,
2283 L"VirtualBox",
2284 &pNc,
2285 &pszApp);
2286 Assert(hrc == S_OK);
2287 if (hrc == S_OK)
2288 {
2289 /* get the adapter's INetCfgComponent*/
2290 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), pAdaptorComponent.asOutParam());
2291 if (hrc != S_OK)
2292 {
2293 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2294 LogRel(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc));
2295 H();
2296 }
2297 }
2298#define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"
2299 char szTrunkName[INTNET_MAX_TRUNK_NAME];
2300 char *pszTrunkName = szTrunkName;
2301 wchar_t * pswzBindName;
2302 hrc = pAdaptorComponent->GetBindName(&pswzBindName);
2303 Assert(hrc == S_OK);
2304 if (hrc == S_OK)
2305 {
2306 int cwBindName = (int)wcslen(pswzBindName) + 1;
2307 int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);
2308 if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName)
2309 {
2310 strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX);
2311 pszTrunkName += cbFullBindNamePrefix-1;
2312 if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName,
2313 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL))
2314 {
2315 DWORD err = GetLastError();
2316 hrc = HRESULT_FROM_WIN32(err);
2317 AssertMsgFailed(("%hrc=%Rhrc %#x\n", hrc, hrc));
2318 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err));
2319 }
2320 }
2321 else
2322 {
2323 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: insufficient szTrunkName buffer space\n"));
2324 /** @todo set appropriate error code */
2325 hrc = E_FAIL;
2326 }
2327
2328 if (hrc != S_OK)
2329 {
2330 AssertFailed();
2331 CoTaskMemFree(pswzBindName);
2332 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2333 H();
2334 }
2335
2336 /* we're not freeing the bind name since we'll use it later for detecting wireless*/
2337 }
2338 else
2339 {
2340 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2341 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc));
2342 H();
2343 }
2344 const char *pszTrunk = szTrunkName;
2345 /* we're not releasing the INetCfg stuff here since we use it later to figure out whether it is wireless */
2346
2347# elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
2348 /** @todo Check for malformed names. */
2349 const char *pszTrunk = pszHifName;
2350
2351 /* Issue a warning if the interface is down */
2352 {
2353 int iSock = socket(AF_INET, SOCK_DGRAM, 0);
2354 if (iSock >= 0)
2355 {
2356 struct ifreq Req;
2357
2358 memset(&Req, 0, sizeof(Req));
2359 strncpy(Req.ifr_name, pszHifName, sizeof(Req.ifr_name) - 1);
2360 if (ioctl(iSock, SIOCGIFFLAGS, &Req) >= 0)
2361 if ((Req.ifr_flags & IFF_UP) == 0)
2362 {
2363 setVMRuntimeErrorCallbackF(pVM, pThis, 0, "BridgedInterfaceDown", "Bridged interface %s is down. Guest will not be able to use this interface", pszHifName);
2364 }
2365
2366 close(iSock);
2367 }
2368 }
2369
2370# else
2371# error "PORTME (VBOX_WITH_NETFLT)"
2372# endif
2373
2374 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
2375 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2376 rc = CFGMR3InsertString(pCfg, "Trunk", pszTrunk); RC_CHECK();
2377 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt);
2378 RC_CHECK();
2379 char szNetwork[INTNET_MAX_NETWORK_NAME];
2380 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName);
2381 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();
2382 networkName = Bstr(szNetwork);
2383 trunkName = Bstr(pszTrunk);
2384 trunkType = Bstr(TRUNKTYPE_NETFLT);
2385
2386# if defined(RT_OS_DARWIN)
2387 /** @todo Come up with a better deal here. Problem is that IHostNetworkInterface is completely useless here. */
2388 if ( strstr(pszHifName, "Wireless")
2389 || strstr(pszHifName, "AirPort" ))
2390 {
2391 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK();
2392 }
2393# elif defined(RT_OS_LINUX)
2394 int iSock = socket(AF_INET, SOCK_DGRAM, 0);
2395 if (iSock >= 0)
2396 {
2397 struct iwreq WRq;
2398
2399 memset(&WRq, 0, sizeof(WRq));
2400 strncpy(WRq.ifr_name, pszHifName, IFNAMSIZ);
2401 bool fSharedMacOnWire = ioctl(iSock, SIOCGIWNAME, &WRq) >= 0;
2402 close(iSock);
2403 if (fSharedMacOnWire)
2404 {
2405 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true);
2406 RC_CHECK();
2407 Log(("Set SharedMacOnWire\n"));
2408 }
2409 else
2410 Log(("Failed to get wireless name\n"));
2411 }
2412 else
2413 Log(("Failed to open wireless socket\n"));
2414# elif defined(RT_OS_WINDOWS)
2415# define DEVNAME_PREFIX L"\\\\.\\"
2416 /* we are getting the medium type via IOCTL_NDIS_QUERY_GLOBAL_STATS Io Control
2417 * there is a pretty long way till there though since we need to obtain the symbolic link name
2418 * for the adapter device we are going to query given the device Guid */
2419
2420
2421 /* prepend the "\\\\.\\" to the bind name to obtain the link name */
2422
2423 wchar_t FileName[MAX_PATH];
2424 wcscpy(FileName, DEVNAME_PREFIX);
2425 wcscpy((wchar_t*)(((char*)FileName) + sizeof(DEVNAME_PREFIX) - sizeof(FileName[0])), pswzBindName);
2426
2427 /* open the device */
2428 HANDLE hDevice = CreateFile(FileName,
2429 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2430 NULL,
2431 OPEN_EXISTING,
2432 FILE_ATTRIBUTE_NORMAL,
2433 NULL);
2434
2435 if (hDevice != INVALID_HANDLE_VALUE)
2436 {
2437 bool fSharedMacOnWire = false;
2438
2439 /* now issue the OID_GEN_PHYSICAL_MEDIUM query */
2440 DWORD Oid = OID_GEN_PHYSICAL_MEDIUM;
2441 NDIS_PHYSICAL_MEDIUM PhMedium;
2442 DWORD cbResult;
2443 if (DeviceIoControl(hDevice,
2444 IOCTL_NDIS_QUERY_GLOBAL_STATS,
2445 &Oid,
2446 sizeof(Oid),
2447 &PhMedium,
2448 sizeof(PhMedium),
2449 &cbResult,
2450 NULL))
2451 {
2452 /* that was simple, now examine PhMedium */
2453 if ( PhMedium == NdisPhysicalMediumWirelessWan
2454 || PhMedium == NdisPhysicalMediumWirelessLan
2455 || PhMedium == NdisPhysicalMediumNative802_11
2456 || PhMedium == NdisPhysicalMediumBluetooth)
2457 fSharedMacOnWire = true;
2458 }
2459 else
2460 {
2461 int winEr = GetLastError();
2462 LogRel(("Console::configConstructor: DeviceIoControl failed, err (0x%x), ignoring\n", winEr));
2463 Assert(winEr == ERROR_INVALID_PARAMETER || winEr == ERROR_NOT_SUPPORTED || winEr == ERROR_BAD_COMMAND);
2464 }
2465 CloseHandle(hDevice);
2466
2467 if (fSharedMacOnWire)
2468 {
2469 Log(("this is a wireless adapter"));
2470 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK();
2471 Log(("Set SharedMacOnWire\n"));
2472 }
2473 else
2474 Log(("this is NOT a wireless adapter"));
2475 }
2476 else
2477 {
2478 int winEr = GetLastError();
2479 AssertLogRelMsgFailed(("Console::configConstructor: CreateFile failed, err (0x%x), ignoring\n", winEr));
2480 }
2481
2482 CoTaskMemFree(pswzBindName);
2483
2484 pAdaptorComponent.setNull();
2485 /* release the pNc finally */
2486 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2487# else
2488 /** @todo PORTME: wireless detection */
2489# endif
2490
2491# if defined(RT_OS_SOLARIS)
2492# if 0 /* bird: this is a bit questionable and might cause more trouble than its worth. */
2493 /* Zone access restriction, don't allow snopping the global zone. */
2494 zoneid_t ZoneId = getzoneid();
2495 if (ZoneId != GLOBAL_ZONEID)
2496 {
2497 rc = CFGMR3InsertInteger(pCfg, "IgnoreAllPromisc", true); RC_CHECK();
2498 }
2499# endif
2500# endif
2501
2502#elif defined(RT_OS_WINDOWS) /* not defined NetFlt */
2503 /* NOTHING TO DO HERE */
2504#elif defined(RT_OS_LINUX)
2505/// @todo aleksey: is there anything to be done here?
2506#elif defined(RT_OS_FREEBSD)
2507/** @todo FreeBSD: Check out this later (HIF networking). */
2508#else
2509# error "Port me"
2510#endif
2511 break;
2512 }
2513
2514 case NetworkAttachmentType_Internal:
2515 {
2516 hrc = aNetworkAdapter->COMGETTER(InternalNetwork)(&str); H();
2517 if (str && *str)
2518 {
2519 if (fSniffer)
2520 {
2521 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0);
2522 RC_CHECK();
2523 }
2524 else
2525 {
2526 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0);
2527 RC_CHECK();
2528 }
2529 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
2530 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2531 rc = CFGMR3InsertStringW(pCfg, "Network", str); RC_CHECK();
2532 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_WhateverNone); RC_CHECK();
2533 networkName = str;
2534 trunkType = Bstr(TRUNKTYPE_WHATEVER);
2535 }
2536 STR_FREE();
2537 break;
2538 }
2539
2540 case NetworkAttachmentType_HostOnly:
2541 {
2542 if (fSniffer)
2543 {
2544 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0);
2545 RC_CHECK();
2546 }
2547 else
2548 {
2549 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0);
2550 RC_CHECK();
2551 }
2552
2553 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
2554 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
2555
2556 Bstr HifName;
2557 hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam());
2558 if (FAILED(hrc))
2559 {
2560 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostInterface) failed, hrc (0x%x)\n", hrc));
2561 H();
2562 }
2563
2564 Utf8Str HifNameUtf8(HifName);
2565 const char *pszHifName = HifNameUtf8.raw();
2566 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostInterface): %s\n", pszHifName));
2567 ComPtr<IHostNetworkInterface> hostInterface;
2568 rc = host->FindHostNetworkInterfaceByName(HifName, hostInterface.asOutParam());
2569 if (!SUCCEEDED(rc))
2570 {
2571 LogRel(("NetworkAttachmentType_HostOnly: FindByName failed, rc (0x%x)\n", rc));
2572 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
2573 N_("Inexistent host networking interface, name '%ls'"),
2574 HifName.raw());
2575 }
2576
2577 char szNetwork[INTNET_MAX_NETWORK_NAME];
2578 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName);
2579
2580#if defined(RT_OS_WINDOWS)
2581# ifndef VBOX_WITH_NETFLT
2582 hrc = E_NOTIMPL;
2583 LogRel(("NetworkAttachmentType_HostOnly: Not Implemented\n"));
2584 H();
2585# else /* defined VBOX_WITH_NETFLT*/
2586 /** @todo r=bird: Put this in a function. */
2587
2588 HostNetworkInterfaceType_T eIfType;
2589 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType);
2590 if (FAILED(hrc))
2591 {
2592 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(InterfaceType) failed, hrc (0x%x)\n", hrc));
2593 H();
2594 }
2595
2596 if (eIfType != HostNetworkInterfaceType_HostOnly)
2597 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
2598 N_("Interface ('%ls') is not a Host-Only Adapter interface"),
2599 HifName.raw());
2600
2601 hrc = hostInterface->COMGETTER(Id)(&str);
2602 if (FAILED(hrc))
2603 {
2604 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(Id) failed, hrc (0x%x)\n", hrc));
2605 H();
2606 }
2607 Guid hostIFGuid(str);
2608 STR_FREE();
2609
2610 INetCfg *pNc;
2611 ComPtr<INetCfgComponent> pAdaptorComponent;
2612 LPWSTR pszApp;
2613 rc = VERR_INTNET_FLT_IF_NOT_FOUND;
2614
2615 hrc = VBoxNetCfgWinQueryINetCfg(FALSE,
2616 L"VirtualBox",
2617 &pNc,
2618 &pszApp);
2619 Assert(hrc == S_OK);
2620 if (hrc == S_OK)
2621 {
2622 /* get the adapter's INetCfgComponent*/
2623 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), pAdaptorComponent.asOutParam());
2624 if (hrc != S_OK)
2625 {
2626 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2627 LogRel(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));
2628 H();
2629 }
2630 }
2631#define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"
2632 char szTrunkName[INTNET_MAX_TRUNK_NAME];
2633 char *pszTrunkName = szTrunkName;
2634 wchar_t * pswzBindName;
2635 hrc = pAdaptorComponent->GetBindName(&pswzBindName);
2636 Assert(hrc == S_OK);
2637 if (hrc == S_OK)
2638 {
2639 int cwBindName = (int)wcslen(pswzBindName) + 1;
2640 int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);
2641 if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName)
2642 {
2643 strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX);
2644 pszTrunkName += cbFullBindNamePrefix-1;
2645 if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName,
2646 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL))
2647 {
2648 DWORD err = GetLastError();
2649 hrc = HRESULT_FROM_WIN32(err);
2650 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err));
2651 }
2652 }
2653 else
2654 {
2655 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: insufficient szTrunkName buffer space\n"));
2656 /** @todo set appropriate error code */
2657 hrc = E_FAIL;
2658 }
2659
2660 if (hrc != S_OK)
2661 {
2662 AssertFailed();
2663 CoTaskMemFree(pswzBindName);
2664 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2665 H();
2666 }
2667 }
2668 else
2669 {
2670 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2671 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));
2672 H();
2673 }
2674
2675
2676 CoTaskMemFree(pswzBindName);
2677
2678 pAdaptorComponent.setNull();
2679 /* release the pNc finally */
2680 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);
2681
2682 const char *pszTrunk = szTrunkName;
2683
2684 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); RC_CHECK();
2685 rc = CFGMR3InsertString(pCfg, "Trunk", pszTrunk); RC_CHECK();
2686 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();
2687 networkName = Bstr(szNetwork);
2688 trunkName = Bstr(pszTrunk);
2689 trunkType = TRUNKTYPE_NETADP;
2690# endif /* defined VBOX_WITH_NETFLT*/
2691#elif defined(RT_OS_DARWIN)
2692 rc = CFGMR3InsertString(pCfg, "Trunk", pszHifName); RC_CHECK();
2693 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();
2694 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); RC_CHECK();
2695 networkName = Bstr(szNetwork);
2696 trunkName = Bstr(pszHifName);
2697 trunkType = TRUNKTYPE_NETADP;
2698#else
2699 rc = CFGMR3InsertString(pCfg, "Trunk", pszHifName); RC_CHECK();
2700 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();
2701 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); RC_CHECK();
2702 networkName = Bstr(szNetwork);
2703 trunkName = Bstr(pszHifName);
2704 trunkType = TRUNKTYPE_NETFLT;
2705#endif
2706#if !defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
2707
2708 Bstr tmpAddr, tmpMask;
2709
2710 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress", pszHifName), tmpAddr.asOutParam());
2711 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty())
2712 {
2713 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask", pszHifName), tmpMask.asOutParam());
2714 if (SUCCEEDED(hrc) && !tmpMask.isEmpty())
2715 hrc = hostInterface->EnableStaticIpConfig(tmpAddr, tmpMask);
2716 else
2717 hrc = hostInterface->EnableStaticIpConfig(tmpAddr,
2718 Bstr(VBOXNET_IPV4MASK_DEFAULT));
2719 }
2720 else
2721 hrc = hostInterface->EnableStaticIpConfig(Bstr(VBOXNET_IPV4ADDR_DEFAULT),
2722 Bstr(VBOXNET_IPV4MASK_DEFAULT));
2723 ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */
2724
2725 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address", pszHifName), tmpAddr.asOutParam());
2726 if (SUCCEEDED(hrc))
2727 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", pszHifName), tmpMask.asOutParam());
2728 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty() && !tmpMask.isEmpty())
2729 {
2730 hrc = hostInterface->EnableStaticIpConfigV6(tmpAddr, Utf8Str(tmpMask).toUInt32());
2731 ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */
2732 }
2733#endif
2734 break;
2735 }
2736
2737 default:
2738 AssertMsgFailed(("should not get here!\n"));
2739 break;
2740 }
2741
2742 /*
2743 * Attempt to attach the driver.
2744 */
2745 switch (eAttachmentType)
2746 {
2747 case NetworkAttachmentType_Null:
2748 break;
2749
2750 case NetworkAttachmentType_Bridged:
2751 case NetworkAttachmentType_Internal:
2752 case NetworkAttachmentType_HostOnly:
2753 case NetworkAttachmentType_NAT:
2754 {
2755 if (SUCCEEDED(hrc) && SUCCEEDED(rc))
2756 {
2757 if (fAttachDetach)
2758 {
2759 rc = PDMR3DriverAttach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/, NULL /* ppBase */);
2760 AssertRC(rc);
2761 }
2762
2763 {
2764 /** @todo pritesh: get the dhcp server name from the
2765 * previous network configuration and then stop the server
2766 * else it may conflict with the dhcp server running with
2767 * the current attachment type
2768 */
2769 /* Stop the hostonly DHCP Server */
2770 }
2771
2772 if (!networkName.isNull())
2773 {
2774 /*
2775 * Until we implement service reference counters DHCP Server will be stopped
2776 * by DHCPServerRunner destructor.
2777 */
2778 ComPtr<IDHCPServer> dhcpServer;
2779 hrc = virtualBox->FindDHCPServerByNetworkName(networkName.mutableRaw(), dhcpServer.asOutParam());
2780 if (SUCCEEDED(hrc))
2781 {
2782 /* there is a DHCP server available for this network */
2783 BOOL fEnabled;
2784 hrc = dhcpServer->COMGETTER(Enabled)(&fEnabled);
2785 if (FAILED(hrc))
2786 {
2787 LogRel(("DHCP svr: COMGETTER(Enabled) failed, hrc (%Rhrc)", hrc));
2788 H();
2789 }
2790
2791 if (fEnabled)
2792 hrc = dhcpServer->Start(networkName, trunkName, trunkType);
2793 }
2794 else
2795 hrc = S_OK;
2796 }
2797 }
2798
2799 break;
2800 }
2801
2802 default:
2803 AssertMsgFailed(("should not get here!\n"));
2804 break;
2805 }
2806
2807 pThis->meAttachmentType[uInstance] = eAttachmentType;
2808
2809#undef STR_FREE
2810#undef H
2811#undef RC_CHECK
2812
2813 return VINF_SUCCESS;
2814}
2815
2816#ifdef VBOX_WITH_GUEST_PROPS
2817/**
2818 * Set an array of guest properties
2819 */
2820static void configSetProperties(VMMDev * const pVMMDev, void *names,
2821 void *values, void *timestamps, void *flags)
2822{
2823 VBOXHGCMSVCPARM parms[4];
2824
2825 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
2826 parms[0].u.pointer.addr = names;
2827 parms[0].u.pointer.size = 0; /* We don't actually care. */
2828 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
2829 parms[1].u.pointer.addr = values;
2830 parms[1].u.pointer.size = 0; /* We don't actually care. */
2831 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
2832 parms[2].u.pointer.addr = timestamps;
2833 parms[2].u.pointer.size = 0; /* We don't actually care. */
2834 parms[3].type = VBOX_HGCM_SVC_PARM_PTR;
2835 parms[3].u.pointer.addr = flags;
2836 parms[3].u.pointer.size = 0; /* We don't actually care. */
2837
2838 pVMMDev->hgcmHostCall ("VBoxGuestPropSvc", guestProp::SET_PROPS_HOST, 4,
2839 &parms[0]);
2840}
2841
2842/**
2843 * Set a single guest property
2844 */
2845static void configSetProperty(VMMDev * const pVMMDev, const char *pszName,
2846 const char *pszValue, const char *pszFlags)
2847{
2848 VBOXHGCMSVCPARM parms[4];
2849
2850 AssertPtrReturnVoid(pszName);
2851 AssertPtrReturnVoid(pszValue);
2852 AssertPtrReturnVoid(pszFlags);
2853 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
2854 parms[0].u.pointer.addr = (void *)pszName;
2855 parms[0].u.pointer.size = strlen(pszName) + 1;
2856 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
2857 parms[1].u.pointer.addr = (void *)pszValue;
2858 parms[1].u.pointer.size = strlen(pszValue) + 1;
2859 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
2860 parms[2].u.pointer.addr = (void *)pszFlags;
2861 parms[2].u.pointer.size = strlen(pszFlags) + 1;
2862 pVMMDev->hgcmHostCall ("VBoxGuestPropSvc", guestProp::SET_PROP_HOST, 3,
2863 &parms[0]);
2864}
2865#endif /* VBOX_WITH_GUEST_PROPS */
2866
2867/**
2868 * Set up the Guest Property service, populate it with properties read from
2869 * the machine XML and set a couple of initial properties.
2870 */
2871/* static */ int Console::configGuestProperties(void *pvConsole)
2872{
2873#ifdef VBOX_WITH_GUEST_PROPS
2874 AssertReturn(pvConsole, VERR_GENERAL_FAILURE);
2875 ComObjPtr<Console> pConsole = static_cast <Console *> (pvConsole);
2876
2877 /* Load the service */
2878 int rc = pConsole->mVMMDev->hgcmLoadService ("VBoxGuestPropSvc", "VBoxGuestPropSvc");
2879
2880 if (RT_FAILURE(rc))
2881 {
2882 LogRel(("VBoxGuestPropSvc is not available. rc = %Rrc\n", rc));
2883 /* That is not a fatal failure. */
2884 rc = VINF_SUCCESS;
2885 }
2886 else
2887 {
2888 /*
2889 * Initialize built-in properties that can be changed and saved.
2890 *
2891 * These are typically transient properties that the guest cannot
2892 * change.
2893 */
2894
2895 /* Sysprep execution by VBoxService. */
2896 configSetProperty(pConsole->mVMMDev,
2897 "/VirtualBox/HostGuest/SysprepExec", "",
2898 "TRANSIENT, RDONLYGUEST");
2899 configSetProperty(pConsole->mVMMDev,
2900 "/VirtualBox/HostGuest/SysprepArgs", "",
2901 "TRANSIENT, RDONLYGUEST");
2902
2903 /*
2904 * Pull over the properties from the server.
2905 */
2906 SafeArray<BSTR> namesOut;
2907 SafeArray<BSTR> valuesOut;
2908 SafeArray<ULONG64> timestampsOut;
2909 SafeArray<BSTR> flagsOut;
2910 HRESULT hrc = pConsole->mControl->PullGuestProperties
2911 (ComSafeArrayAsOutParam(namesOut),
2912 ComSafeArrayAsOutParam(valuesOut),
2913 ComSafeArrayAsOutParam(timestampsOut),
2914 ComSafeArrayAsOutParam(flagsOut));
2915 AssertMsgReturn(SUCCEEDED(hrc), ("hrc=%#x\n", hrc),
2916 VERR_GENERAL_FAILURE);
2917 size_t cProps = namesOut.size();
2918 size_t cAlloc = cProps + 1;
2919 if ( valuesOut.size() != cProps
2920 || timestampsOut.size() != cProps
2921 || flagsOut.size() != cProps
2922 )
2923 AssertFailedReturn(VERR_INVALID_PARAMETER);
2924
2925 char **papszNames, **papszValues, **papszFlags;
2926 char szEmpty[] = "";
2927 ULONG64 *pau64Timestamps;
2928 papszNames = (char **)RTMemTmpAllocZ(sizeof(void *) * cAlloc);
2929 papszValues = (char **)RTMemTmpAllocZ(sizeof(void *) * cAlloc);
2930 pau64Timestamps = (ULONG64 *)RTMemTmpAllocZ(sizeof(ULONG64) * cAlloc);
2931 papszFlags = (char **)RTMemTmpAllocZ(sizeof(void *) * cAlloc);
2932 if (papszNames && papszValues && pau64Timestamps && papszFlags)
2933 {
2934 for (unsigned i = 0; RT_SUCCESS(rc) && i < cProps; ++i)
2935 {
2936 AssertPtrReturn(namesOut[i], VERR_INVALID_PARAMETER);
2937 rc = RTUtf16ToUtf8(namesOut[i], &papszNames[i]);
2938 if (RT_FAILURE(rc))
2939 break;
2940 if (valuesOut[i])
2941 rc = RTUtf16ToUtf8(valuesOut[i], &papszValues[i]);
2942 else
2943 papszValues[i] = szEmpty;
2944 if (RT_FAILURE(rc))
2945 break;
2946 pau64Timestamps[i] = timestampsOut[i];
2947 if (flagsOut[i])
2948 rc = RTUtf16ToUtf8(flagsOut[i], &papszFlags[i]);
2949 else
2950 papszFlags[i] = szEmpty;
2951 }
2952 if (RT_SUCCESS(rc))
2953 configSetProperties(pConsole->mVMMDev,
2954 (void *)papszNames,
2955 (void *)papszValues,
2956 (void *)pau64Timestamps,
2957 (void *)papszFlags);
2958 for (unsigned i = 0; i < cProps; ++i)
2959 {
2960 RTStrFree(papszNames[i]);
2961 if (valuesOut[i])
2962 RTStrFree(papszValues[i]);
2963 if (flagsOut[i])
2964 RTStrFree(papszFlags[i]);
2965 }
2966 }
2967 else
2968 rc = VERR_NO_MEMORY;
2969 RTMemTmpFree(papszNames);
2970 RTMemTmpFree(papszValues);
2971 RTMemTmpFree(pau64Timestamps);
2972 RTMemTmpFree(papszFlags);
2973 AssertRCReturn(rc, rc);
2974
2975 /*
2976 * These properties have to be set before pulling over the properties
2977 * from the machine XML, to ensure that properties saved in the XML
2978 * will override them.
2979 */
2980 /* Set the VBox version string as a guest property */
2981 configSetProperty(pConsole->mVMMDev, "/VirtualBox/HostInfo/VBoxVer",
2982 VBOX_VERSION_STRING, "TRANSIENT, RDONLYGUEST");
2983 /* Set the VBox SVN revision as a guest property */
2984 configSetProperty(pConsole->mVMMDev, "/VirtualBox/HostInfo/VBoxRev",
2985 RTBldCfgRevisionStr(), "TRANSIENT, RDONLYGUEST");
2986
2987 /*
2988 * Register the host notification callback
2989 */
2990 HGCMSVCEXTHANDLE hDummy;
2991 HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestPropSvc",
2992 Console::doGuestPropNotification,
2993 pvConsole);
2994
2995 Log(("Set VBoxGuestPropSvc property store\n"));
2996 }
2997 return VINF_SUCCESS;
2998#else /* !VBOX_WITH_GUEST_PROPS */
2999 return VERR_NOT_SUPPORTED;
3000#endif /* !VBOX_WITH_GUEST_PROPS */
3001}
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