VirtualBox

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

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

introduced VBoxManage modifyvm --rtcuseutc

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