VirtualBox

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

Last change on this file since 5528 was 5361, checked in by vboxsync, 17 years ago

Added option to emulate PIIX4 IDE controller. Defaults to PIIX4 for new VMs
and to PIIX3 when no setting is present in XML.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.6 KB
Line 
1/** $Id: ConsoleImpl2.cpp 5361 2007-10-17 17:11:26Z 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
6 * finds problematic to optimize so we can disable optimizations
7 * and later, perhaps, find a real solution for it.
8 */
9
10/*
11 * Copyright (C) 2006-2007 innotek GmbH
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License as published by the Free Software Foundation,
17 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
18 * distribution. VirtualBox OSE is distributed in the hope that it will
19 * be useful, but WITHOUT ANY WARRANTY of any kind.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#include "ConsoleImpl.h"
26#include "DisplayImpl.h"
27#include "VMMDev.h"
28
29// generated header
30#include "SchemaDefs.h"
31
32#include "Logging.h"
33
34#include <iprt/string.h>
35#include <iprt/path.h>
36#include <iprt/dir.h>
37#include <iprt/param.h>
38
39#include <VBox/vmapi.h>
40#include <VBox/err.h>
41#include <VBox/version.h>
42#include <VBox/HostServices/VBoxClipboardSvc.h>
43
44
45/*
46 * VC++ 8 / amd64 has some serious trouble with this function.
47 * As a temporary measure, we'll drop global optimizations.
48 */
49#if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
50# pragma optimize("g", off)
51#endif
52
53/**
54 * Construct the VM configuration tree (CFGM).
55 *
56 * This is a callback for VMR3Create() call. It is called from CFGMR3Init()
57 * in the emulation thread (EMT). Any per thread COM/XPCOM initialization
58 * is done here.
59 *
60 * @param pVM VM handle.
61 * @param pvConsole Pointer to the VMPowerUpTask object.
62 * @return VBox status code.
63 *
64 * @note Locks the Console object for writing.
65 */
66DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
67{
68 LogFlowFuncEnter();
69
70#if defined(RT_OS_WINDOWS)
71 {
72 /* initialize COM */
73 HRESULT hrc = CoInitializeEx(NULL,
74 COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE |
75 COINIT_SPEED_OVER_MEMORY);
76 LogFlow (("Console::configConstructor(): CoInitializeEx()=%08X\n", hrc));
77 AssertComRCReturn (hrc, VERR_GENERAL_FAILURE);
78 }
79#endif
80
81 AssertReturn (pvConsole, VERR_GENERAL_FAILURE);
82 ComObjPtr <Console> pConsole = static_cast <Console *> (pvConsole);
83
84 AutoCaller autoCaller (pConsole);
85 AssertComRCReturn (autoCaller.rc(), VERR_ACCESS_DENIED);
86
87 /* lock the console because we widely use internal fields and methods */
88 AutoLock alock (pConsole);
89
90 ComPtr <IMachine> pMachine = pConsole->machine();
91
92 int rc;
93 HRESULT hrc;
94 char *psz = NULL;
95 BSTR str = NULL;
96 unsigned i;
97
98#define STR_CONV() do { rc = RTStrUcs2ToUtf8(&psz, str); RC_CHECK(); } while (0)
99#define STR_FREE() do { if (str) { SysFreeString(str); str = NULL; } if (psz) { RTStrFree(psz); psz = NULL; } } while (0)
100#define RC_CHECK() do { if (VBOX_FAILURE(rc)) { AssertMsgFailed(("rc=%Vrc\n", rc)); STR_FREE(); return rc; } } while (0)
101#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%#x\n", hrc)); STR_FREE(); return VERR_GENERAL_FAILURE; } } while (0)
102
103 /*
104 * Get necessary objects and frequently used parameters.
105 */
106 ComPtr<IVirtualBox> virtualBox;
107 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
108
109 ComPtr<IHost> host;
110 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
111
112 ComPtr <ISystemProperties> systemProperties;
113 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
114
115 ComPtr<IBIOSSettings> biosSettings;
116 hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
117
118 Guid uuid;
119 hrc = pMachine->COMGETTER(Id)(uuid.asOutParam()); H();
120 PCRTUUID pUuid = uuid.raw();
121
122 ULONG cRamMBs;
123 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
124
125
126 /*
127 * Get root node first.
128 * This is the only node in the tree.
129 */
130 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
131 Assert(pRoot);
132
133 /*
134 * Set the root level values.
135 */
136 hrc = pMachine->COMGETTER(Name)(&str); H();
137 STR_CONV();
138 rc = CFGMR3InsertString(pRoot, "Name", psz); RC_CHECK();
139 STR_FREE();
140 rc = CFGMR3InsertBytes(pRoot, "UUID", pUuid, sizeof(*pUuid)); RC_CHECK();
141 rc = CFGMR3InsertInteger(pRoot, "RamSize", cRamMBs * _1M); RC_CHECK();
142 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); RC_CHECK();
143 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); /* boolean */ RC_CHECK();
144 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); /* boolean */ RC_CHECK();
145 /** @todo Config: RawR0, PATMEnabled and CASMEnabled needs attention later. */
146 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); /* boolean */ RC_CHECK();
147 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); /* boolean */ RC_CHECK();
148
149 /* hardware virtualization extensions */
150 TriStateBool_T hwVirtExEnabled;
151 BOOL fHWVirtExEnabled;
152 hrc = pMachine->COMGETTER(HWVirtExEnabled)(&hwVirtExEnabled); H();
153 if (hwVirtExEnabled == TriStateBool_Default)
154 {
155 /* check the default value */
156 hrc = systemProperties->COMGETTER(HWVirtExEnabled)(&fHWVirtExEnabled); H();
157 }
158 else
159 fHWVirtExEnabled = (hwVirtExEnabled == TriStateBool_True);
160#ifndef RT_OS_DARWIN /** @todo Implement HWVirtExt on darwin. See #1865. */
161 if (fHWVirtExEnabled)
162 {
163 PCFGMNODE pHWVirtExt;
164 rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHWVirtExt); RC_CHECK();
165 rc = CFGMR3InsertInteger(pHWVirtExt, "Enabled", 1); RC_CHECK();
166 }
167#endif
168
169 BOOL fIOAPIC;
170 hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
171
172 BOOL fPXEDebug;
173 hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
174
175 /*
176 * Virtual IDE controller type.
177 */
178 IDEControllerType_T controllerType;
179 BOOL fPIIX4;
180 hrc = biosSettings->COMGETTER(IDEControllerType)(&controllerType); H();
181 switch (controllerType)
182 {
183 case IDEControllerType_IDEControllerPIIX3:
184 fPIIX4 = FALSE;
185 break;
186 case IDEControllerType_IDEControllerPIIX4:
187 fPIIX4 = TRUE;
188 break;
189 default:
190 AssertMsgFailed(("Invalid IDE controller type '%d'", controllerType));
191 return VERR_INVALID_PARAMETER;
192 }
193
194 /*
195 * PDM config.
196 * Load drivers in VBoxC.[so|dll]
197 */
198 PCFGMNODE pPDM;
199 PCFGMNODE pDrivers;
200 PCFGMNODE pMod;
201 rc = CFGMR3InsertNode(pRoot, "PDM", &pPDM); RC_CHECK();
202 rc = CFGMR3InsertNode(pPDM, "Drivers", &pDrivers); RC_CHECK();
203 rc = CFGMR3InsertNode(pDrivers, "VBoxC", &pMod); RC_CHECK();
204#ifdef VBOX_WITH_XPCOM
205 // VBoxC is located in the components subdirectory
206 char szPathVBoxC[RTPATH_MAX];
207 rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc);
208 strcat(szPathVBoxC, "/components/VBoxC");
209 rc = CFGMR3InsertString(pMod, "Path", szPathVBoxC); RC_CHECK();
210#else
211 rc = CFGMR3InsertString(pMod, "Path", "VBoxC"); RC_CHECK();
212#endif
213
214 /*
215 * Devices
216 */
217 PCFGMNODE pDevices = NULL; /* /Devices */
218 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
219 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
220 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
221 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
222 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
223 PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
224
225 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); RC_CHECK();
226
227 /*
228 * PC Arch.
229 */
230 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); RC_CHECK();
231 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
232 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
233 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
234
235 /*
236 * PC Bios.
237 */
238 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); RC_CHECK();
239 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
240 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
241 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
242 rc = CFGMR3InsertInteger(pCfg, "RamSize", cRamMBs * _1M); RC_CHECK();
243 rc = CFGMR3InsertString(pCfg, "HardDiskDevice", "piix3ide"); RC_CHECK();
244 rc = CFGMR3InsertString(pCfg, "FloppyDevice", "i82078"); RC_CHECK();
245 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
246 rc = CFGMR3InsertInteger(pCfg, "PXEDebug", fPXEDebug); RC_CHECK();
247 rc = CFGMR3InsertBytes(pCfg, "UUID", pUuid, sizeof(*pUuid)); RC_CHECK();
248
249 DeviceType_T bootDevice;
250 if (SchemaDefs::MaxBootPosition > 9)
251 {
252 AssertMsgFailed (("Too many boot devices %d\n",
253 SchemaDefs::MaxBootPosition));
254 return VERR_INVALID_PARAMETER;
255 }
256
257 for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; pos ++)
258 {
259 hrc = pMachine->GetBootOrder(pos, &bootDevice); H();
260
261 char szParamName[] = "BootDeviceX";
262 szParamName[sizeof (szParamName) - 2] = ((char (pos - 1)) + '0');
263
264 const char *pszBootDevice;
265 switch (bootDevice)
266 {
267 case DeviceType_NoDevice:
268 pszBootDevice = "NONE";
269 break;
270 case DeviceType_HardDiskDevice:
271 pszBootDevice = "IDE";
272 break;
273 case DeviceType_DVDDevice:
274 pszBootDevice = "DVD";
275 break;
276 case DeviceType_FloppyDevice:
277 pszBootDevice = "FLOPPY";
278 break;
279 case DeviceType_NetworkDevice:
280 pszBootDevice = "LAN";
281 break;
282 default:
283 AssertMsgFailed(("Invalid bootDevice=%d\n", bootDevice));
284 return VERR_INVALID_PARAMETER;
285 }
286 rc = CFGMR3InsertString(pCfg, szParamName, pszBootDevice); RC_CHECK();
287 }
288
289 /*
290 * BIOS logo
291 */
292 BOOL fFadeIn;
293 hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H();
294 rc = CFGMR3InsertInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0); RC_CHECK();
295 BOOL fFadeOut;
296 hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H();
297 rc = CFGMR3InsertInteger(pCfg, "FadeOut", fFadeOut ? 1: 0); RC_CHECK();
298 ULONG logoDisplayTime;
299 hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H();
300 rc = CFGMR3InsertInteger(pCfg, "LogoTime", logoDisplayTime); RC_CHECK();
301 Bstr logoImagePath;
302 hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H();
303 rc = CFGMR3InsertString(pCfg, "LogoFile", logoImagePath ? Utf8Str(logoImagePath) : ""); RC_CHECK();
304
305 /*
306 * Boot menu
307 */
308 BIOSBootMenuMode_T bootMenuMode;
309 int value;
310 biosSettings->COMGETTER(BootMenuMode)(&bootMenuMode);
311 switch (bootMenuMode)
312 {
313 case BIOSBootMenuMode_Disabled:
314 value = 0;
315 break;
316 case BIOSBootMenuMode_MenuOnly:
317 value = 1;
318 break;
319 default:
320 value = 2;
321 }
322 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", value); RC_CHECK();
323
324 /*
325 * The time offset
326 */
327 LONG64 timeOffset;
328 hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H();
329 PCFGMNODE pTMNode;
330 rc = CFGMR3InsertNode(pRoot, "TM", &pTMNode); RC_CHECK();
331 rc = CFGMR3InsertInteger(pTMNode, "UTCOffset", timeOffset * 1000000); RC_CHECK();
332
333 /*
334 * ACPI
335 */
336 BOOL fACPI;
337 hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI); H();
338 if (fACPI)
339 {
340 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); RC_CHECK();
341 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
342 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
343 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
344 rc = CFGMR3InsertInteger(pCfg, "RamSize", cRamMBs * _1M); RC_CHECK();
345 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
346 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); RC_CHECK();
347 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
348
349 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
350 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); RC_CHECK();
351 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
352 }
353
354 /*
355 * DMA
356 */
357 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); RC_CHECK();
358 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
359 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
360
361 /*
362 * PCI bus.
363 */
364 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ RC_CHECK();
365 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
366 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
367 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
368 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
369
370 /*
371 * PS/2 keyboard & mouse.
372 */
373 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); RC_CHECK();
374 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
375 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
376 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
377
378 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
379 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); RC_CHECK();
380 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
381 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); RC_CHECK();
382
383 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
384 rc = CFGMR3InsertString(pLunL1, "Driver", "MainKeyboard"); RC_CHECK();
385 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
386 Keyboard *pKeyboard = pConsole->mKeyboard;
387 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pKeyboard); RC_CHECK();
388
389 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); RC_CHECK();
390 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); RC_CHECK();
391 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
392 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); RC_CHECK();
393
394 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
395 rc = CFGMR3InsertString(pLunL1, "Driver", "MainMouse"); RC_CHECK();
396 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
397 Mouse *pMouse = pConsole->mMouse;
398 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pMouse); RC_CHECK();
399
400 /*
401 * i82078 Floppy drive controller
402 */
403 ComPtr<IFloppyDrive> floppyDrive;
404 hrc = pMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam()); H();
405 BOOL fFloppyEnabled;
406 hrc = floppyDrive->COMGETTER(Enabled)(&fFloppyEnabled); H();
407 if (fFloppyEnabled)
408 {
409 rc = CFGMR3InsertNode(pDevices, "i82078", &pDev); RC_CHECK();
410 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
411 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); RC_CHECK();
412 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
413 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); RC_CHECK();
414 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); RC_CHECK();
415 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); RC_CHECK();
416 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); RC_CHECK();
417
418 /* Attach the status driver */
419 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
420 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
421 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
422 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapFDLeds[0]); RC_CHECK();
423 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
424 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
425
426 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
427
428 ComPtr<IFloppyImage> floppyImage;
429 hrc = floppyDrive->GetImage(floppyImage.asOutParam()); H();
430 if (floppyImage)
431 {
432 pConsole->meFloppyState = DriveState_ImageMounted;
433 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
434 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
435 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
436 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
437
438 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
439 rc = CFGMR3InsertString(pLunL1, "Driver", "RawImage"); RC_CHECK();
440 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
441 hrc = floppyImage->COMGETTER(FilePath)(&str); H();
442 STR_CONV();
443 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
444 STR_FREE();
445 }
446 else
447 {
448 ComPtr<IHostFloppyDrive> hostFloppyDrive;
449 hrc = floppyDrive->GetHostDrive(hostFloppyDrive.asOutParam()); H();
450 if (hostFloppyDrive)
451 {
452 pConsole->meFloppyState = DriveState_HostDriveCaptured;
453 rc = CFGMR3InsertString(pLunL0, "Driver", "HostFloppy"); RC_CHECK();
454 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
455 hrc = hostFloppyDrive->COMGETTER(Name)(&str); H();
456 STR_CONV();
457 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
458 STR_FREE();
459 }
460 else
461 {
462 pConsole->meFloppyState = DriveState_NotMounted;
463 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
464 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
465 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
466 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
467 }
468 }
469 }
470
471 /*
472 * i8254 Programmable Interval Timer And Dummy Speaker
473 */
474 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); RC_CHECK();
475 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
476 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
477#ifdef DEBUG
478 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
479#endif
480
481 /*
482 * i8259 Programmable Interrupt Controller.
483 */
484 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); RC_CHECK();
485 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
486 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
487 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
488
489 /*
490 * Advanced Programmable Interrupt Controller.
491 */
492 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); RC_CHECK();
493 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
494 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
495 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
496 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
497
498 if (fIOAPIC)
499 {
500 /*
501 * I/O Advanced Programmable Interrupt Controller.
502 */
503 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); RC_CHECK();
504 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
505 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
506 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
507 }
508
509 /*
510 * RTC MC146818.
511 */
512 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); RC_CHECK();
513 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
514 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
515
516 /*
517 * VGA.
518 */
519 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); RC_CHECK();
520 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
521 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
522 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); RC_CHECK();
523 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
524 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
525 hrc = pMachine->COMGETTER(VRAMSize)(&cRamMBs); H();
526 rc = CFGMR3InsertInteger(pCfg, "VRamSize", cRamMBs * _1M); RC_CHECK();
527
528 /* Custom VESA mode list */
529 unsigned cModes = 0;
530 for (unsigned iMode = 1; iMode <= 16; iMode++)
531 {
532 char szExtraDataKey[sizeof("CustomVideoModeXX")];
533 RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%d", iMode);
534 hrc = pMachine->GetExtraData(Bstr(szExtraDataKey), &str); H();
535 if (!str || !*str)
536 break;
537 STR_CONV();
538 rc = CFGMR3InsertString(pCfg, szExtraDataKey, psz);
539 STR_FREE();
540 cModes++;
541 }
542 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", cModes);
543
544 /* VESA height reduction */
545 ULONG ulHeightReduction;
546 IFramebuffer *pFramebuffer = pConsole->getDisplay()->getFramebuffer();
547 if (pFramebuffer)
548 {
549 hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction); H();
550 }
551 else
552 {
553 /* If framebuffer is not available, there is no height reduction. */
554 ulHeightReduction = 0;
555 }
556 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", ulHeightReduction); RC_CHECK();
557
558 /* Attach the display. */
559 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
560 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); RC_CHECK();
561 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
562 Display *pDisplay = pConsole->mDisplay;
563 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pDisplay); RC_CHECK();
564
565 /*
566 * IDE (update this when the main interface changes)
567 */
568 rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */ RC_CHECK();
569 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
570 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
571 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); RC_CHECK();
572 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 1); RC_CHECK();
573 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
574 rc = CFGMR3InsertInteger(pCfg, "PIIX4", fPIIX4); /* boolean */ RC_CHECK();
575
576 /* Attach the status driver */
577 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
578 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
579 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
580 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapIDELeds[0]);RC_CHECK();
581 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
582 rc = CFGMR3InsertInteger(pCfg, "Last", 3); RC_CHECK();
583
584 /* Attach the harddisks */
585 ComPtr<IHardDiskAttachmentCollection> hdaColl;
586 hrc = pMachine->COMGETTER(HardDiskAttachments)(hdaColl.asOutParam()); H();
587 ComPtr<IHardDiskAttachmentEnumerator> hdaEnum;
588 hrc = hdaColl->Enumerate(hdaEnum.asOutParam()); H();
589
590 BOOL fMore = FALSE;
591 while ( SUCCEEDED(hrc = hdaEnum->HasMore(&fMore))
592 && fMore)
593 {
594 ComPtr<IHardDiskAttachment> hda;
595 hrc = hdaEnum->GetNext(hda.asOutParam()); H();
596 ComPtr<IHardDisk> hardDisk;
597 hrc = hda->COMGETTER(HardDisk)(hardDisk.asOutParam()); H();
598 DiskControllerType_T enmCtl;
599 hrc = hda->COMGETTER(Controller)(&enmCtl); H();
600 LONG lDev;
601 hrc = hda->COMGETTER(DeviceNumber)(&lDev); H();
602
603 switch (enmCtl)
604 {
605 case DiskControllerType_IDE0Controller:
606 i = 0;
607 break;
608 case DiskControllerType_IDE1Controller:
609 i = 2;
610 break;
611 default:
612 AssertMsgFailed(("invalid disk controller type: %d\n", enmCtl));
613 return VERR_GENERAL_FAILURE;
614 }
615
616 if (lDev < 0 || lDev >= 2)
617 {
618 AssertMsgFailed(("invalid controller device number: %d\n", lDev));
619 return VERR_GENERAL_FAILURE;
620 }
621
622 i = i + lDev;
623
624 char szLUN[16];
625 RTStrPrintf(szLUN, sizeof(szLUN), "LUN#%d", i);
626 rc = CFGMR3InsertNode(pInst, szLUN, &pLunL0); RC_CHECK();
627 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
628 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
629 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); RC_CHECK();
630 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); RC_CHECK();
631
632 HardDiskStorageType_T hddType;
633 hardDisk->COMGETTER(StorageType)(&hddType);
634 if (hddType == HardDiskStorageType_VirtualDiskImage)
635 {
636 ComPtr<IVirtualDiskImage> vdiDisk = hardDisk;
637 AssertBreak (!vdiDisk.isNull(), hrc = E_FAIL);
638
639 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
640 rc = CFGMR3InsertString(pLunL1, "Driver", "VBoxHDD"); RC_CHECK();
641 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
642 hrc = vdiDisk->COMGETTER(FilePath)(&str); H();
643 STR_CONV();
644 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
645 STR_FREE();
646
647 /* Create an inversed tree of parents. */
648 ComPtr<IHardDisk> parentHardDisk = hardDisk;
649 for (PCFGMNODE pParent = pCfg;;)
650 {
651 ComPtr<IHardDisk> curHardDisk;
652 hrc = parentHardDisk->COMGETTER(Parent)(curHardDisk.asOutParam()); H();
653 if (!curHardDisk)
654 break;
655
656 vdiDisk = curHardDisk;
657 AssertBreak (!vdiDisk.isNull(), hrc = E_FAIL);
658
659 PCFGMNODE pCur;
660 rc = CFGMR3InsertNode(pParent, "Parent", &pCur); RC_CHECK();
661 hrc = vdiDisk->COMGETTER(FilePath)(&str); H();
662 STR_CONV();
663 rc = CFGMR3InsertString(pCur, "Path", psz); RC_CHECK();
664 STR_FREE();
665 rc = CFGMR3InsertInteger(pCur, "ReadOnly", 1); RC_CHECK();
666
667 /* next */
668 pParent = pCur;
669 parentHardDisk = curHardDisk;
670 }
671 }
672 else if (hddType == HardDiskStorageType_ISCSIHardDisk)
673 {
674 ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;
675 AssertBreak (!iSCSIDisk.isNull(), hrc = E_FAIL);
676
677 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
678 rc = CFGMR3InsertString(pLunL1, "Driver", "iSCSI"); RC_CHECK();
679 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
680
681 /* Set up the iSCSI initiator driver configuration. */
682 hrc = iSCSIDisk->COMGETTER(Target)(&str); H();
683 STR_CONV();
684 rc = CFGMR3InsertString(pCfg, "TargetName", psz); RC_CHECK();
685 STR_FREE();
686
687 // @todo currently there is no Initiator name config.
688 rc = CFGMR3InsertString(pCfg, "InitiatorName", "iqn.2006-02.de.innotek.initiator"); RC_CHECK();
689
690 ULONG64 lun;
691 hrc = iSCSIDisk->COMGETTER(Lun)(&lun); H();
692 rc = CFGMR3InsertInteger(pCfg, "LUN", lun); RC_CHECK();
693
694 hrc = iSCSIDisk->COMGETTER(Server)(&str); H();
695 STR_CONV();
696 USHORT port;
697 hrc = iSCSIDisk->COMGETTER(Port)(&port); H();
698 if (port != 0)
699 {
700 char *pszTN;
701 RTStrAPrintf(&pszTN, "%s:%u", psz, port);
702 rc = CFGMR3InsertString(pCfg, "TargetAddress", pszTN); RC_CHECK();
703 RTStrFree(pszTN);
704 }
705 else
706 {
707 rc = CFGMR3InsertString(pCfg, "TargetAddress", psz); RC_CHECK();
708 }
709 STR_FREE();
710
711 hrc = iSCSIDisk->COMGETTER(UserName)(&str); H();
712 if (str)
713 {
714 STR_CONV();
715 rc = CFGMR3InsertString(pCfg, "InitiatorUsername", psz); RC_CHECK();
716 STR_FREE();
717 }
718
719 hrc = iSCSIDisk->COMGETTER(Password)(&str); H();
720 if (str)
721 {
722 STR_CONV();
723 rc = CFGMR3InsertString(pCfg, "InitiatorSecret", psz); RC_CHECK();
724 STR_FREE();
725 }
726
727 // @todo currently there is no target username config.
728 //rc = CFGMR3InsertString(pCfg, "TargetUsername", ""); RC_CHECK();
729
730 // @todo currently there is no target password config.
731 //rc = CFGMR3InsertString(pCfg, "TargetSecret", ""); RC_CHECK();
732
733 /* The iSCSI initiator needs an attached iSCSI transport driver. */
734 rc = CFGMR3InsertNode(pLunL1, "AttachedDriver", &pLunL2); RC_CHECK();
735 rc = CFGMR3InsertString(pLunL2, "Driver", "iSCSITCP"); RC_CHECK();
736 /* Currently the transport driver has no config options. */
737 }
738 else if (hddType == HardDiskStorageType_VMDKImage)
739 {
740 ComPtr<IVMDKImage> vmdkDisk = hardDisk;
741 AssertBreak (!vmdkDisk.isNull(), hrc = E_FAIL);
742
743 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
744#if 1 /* Enable new VD container code (and new VMDK), as the bugs are fixed. */
745 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK();
746#else
747 rc = CFGMR3InsertString(pLunL1, "Driver", "VmdkHDD"); RC_CHECK();
748#endif
749 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
750 hrc = vmdkDisk->COMGETTER(FilePath)(&str); H();
751 STR_CONV();
752 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
753 STR_FREE();
754 }
755 else if (hddType == HardDiskStorageType_CustomHardDisk)
756 {
757 ComPtr<ICustomHardDisk> customHardDisk = hardDisk;
758 AssertBreak (!customHardDisk.isNull(), hrc = E_FAIL);
759
760 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
761 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK();
762 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
763 hrc = customHardDisk->COMGETTER(Location)(&str); H();
764 STR_CONV();
765 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
766 STR_FREE();
767 hrc = customHardDisk->COMGETTER(Format)(&str); H();
768 STR_CONV();
769 rc = CFGMR3InsertString(pCfg, "Format", psz); RC_CHECK();
770 STR_FREE();
771 }
772 else
773 AssertFailed();
774 }
775 H();
776
777 ComPtr<IDVDDrive> dvdDrive;
778 hrc = pMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam()); H();
779 if (dvdDrive)
780 {
781 // ASSUME: DVD drive is always attached to LUN#2 (i.e. secondary IDE master)
782 rc = CFGMR3InsertNode(pInst, "LUN#2", &pLunL0); RC_CHECK();
783 ComPtr<IHostDVDDrive> hostDvdDrive;
784 hrc = dvdDrive->GetHostDrive(hostDvdDrive.asOutParam()); H();
785 if (hostDvdDrive)
786 {
787 pConsole->meDVDState = DriveState_HostDriveCaptured;
788 rc = CFGMR3InsertString(pLunL0, "Driver", "HostDVD"); RC_CHECK();
789 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
790 hrc = hostDvdDrive->COMGETTER(Name)(&str); H();
791 STR_CONV();
792 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
793 STR_FREE();
794 BOOL fPassthrough;
795 hrc = dvdDrive->COMGETTER(Passthrough)(&fPassthrough); H();
796 rc = CFGMR3InsertInteger(pCfg, "Passthrough", !!fPassthrough); RC_CHECK();
797 }
798 else
799 {
800 pConsole->meDVDState = DriveState_NotMounted;
801 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
802 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
803 rc = CFGMR3InsertString(pCfg, "Type", "DVD"); RC_CHECK();
804 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
805
806 ComPtr<IDVDImage> dvdImage;
807 hrc = dvdDrive->GetImage(dvdImage.asOutParam()); H();
808 if (dvdImage)
809 {
810 pConsole->meDVDState = DriveState_ImageMounted;
811 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
812 rc = CFGMR3InsertString(pLunL1, "Driver", "MediaISO"); RC_CHECK();
813 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
814 hrc = dvdImage->COMGETTER(FilePath)(&str); H();
815 STR_CONV();
816 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
817 STR_FREE();
818 }
819 }
820 }
821
822 /*
823 * Network adapters
824 */
825 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDev); RC_CHECK();
826 //rc = CFGMR3InsertNode(pDevices, "ne2000", &pDev); RC_CHECK();
827 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ulInstance++)
828 {
829 ComPtr<INetworkAdapter> networkAdapter;
830 hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H();
831 BOOL fEnabled = FALSE;
832 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabled); H();
833 if (!fEnabled)
834 continue;
835
836 char szInstance[4]; Assert(ulInstance <= 999);
837 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
838 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
839 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
840 /* the first network card gets the PCI ID 3, the followings starting from 8 */
841 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", !ulInstance ? 3 : ulInstance - 1 + 8); RC_CHECK();
842 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
843 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
844
845 /*
846 * The virtual hardware type.
847 */
848 NetworkAdapterType_T adapterType;
849 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H();
850 switch (adapterType)
851 {
852 case NetworkAdapterType_NetworkAdapterAm79C970A:
853 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 0); RC_CHECK();
854 break;
855 case NetworkAdapterType_NetworkAdapterAm79C973:
856 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 1); RC_CHECK();
857 break;
858 default:
859 AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'",
860 adapterType, ulInstance));
861 return VERR_GENERAL_FAILURE;
862 }
863
864 /*
865 * Get the MAC address and convert it to binary representation
866 */
867 Bstr macAddr;
868 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H();
869 Assert(macAddr);
870 Utf8Str macAddrUtf8 = macAddr;
871 char *macStr = (char*)macAddrUtf8.raw();
872 Assert(strlen(macStr) == 12);
873 PDMMAC Mac;
874 memset(&Mac, 0, sizeof(Mac));
875 char *pMac = (char*)&Mac;
876 for (uint32_t i = 0; i < 6; i++)
877 {
878 char c1 = *macStr++ - '0';
879 if (c1 > 9)
880 c1 -= 7;
881 char c2 = *macStr++ - '0';
882 if (c2 > 9)
883 c2 -= 7;
884 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
885 }
886 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK();
887
888 /*
889 * Check if the cable is supposed to be unplugged
890 */
891 BOOL fCableConnected;
892 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H();
893 rc = CFGMR3InsertInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0); RC_CHECK();
894
895 /*
896 * Line speed to report from custom drivers
897 */
898 ULONG ulLineSpeed;
899 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H();
900 rc = CFGMR3InsertInteger(pCfg, "LineSpeed", ulLineSpeed); RC_CHECK();
901
902 /*
903 * Attach the status driver.
904 */
905 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
906 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
907 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
908 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapNetworkLeds[ulInstance]); RC_CHECK();
909
910 /*
911 * Enable the packet sniffer if requested.
912 */
913 BOOL fSniffer;
914 hrc = networkAdapter->COMGETTER(TraceEnabled)(&fSniffer); H();
915 if (fSniffer)
916 {
917 /* insert the sniffer filter driver. */
918 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
919 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK();
920 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
921 hrc = networkAdapter->COMGETTER(TraceFile)(&str); H();
922 if (str) /* check convention for indicating default file. */
923 {
924 STR_CONV();
925 rc = CFGMR3InsertString(pCfg, "File", psz); RC_CHECK();
926 STR_FREE();
927 }
928 }
929
930 NetworkAttachmentType_T networkAttachment;
931 hrc = networkAdapter->COMGETTER(AttachmentType)(&networkAttachment); H();
932 switch (networkAttachment)
933 {
934 case NetworkAttachmentType_NoNetworkAttachment:
935 break;
936
937 case NetworkAttachmentType_NATNetworkAttachment:
938 {
939 if (fSniffer)
940 {
941 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
942 }
943 else
944 {
945 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
946 }
947 rc = CFGMR3InsertString(pLunL0, "Driver", "NAT"); RC_CHECK();
948 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
949 /* (Port forwarding goes here.) */
950
951 /* Configure TFTP prefix and boot filename. */
952 hrc = virtualBox->COMGETTER(HomeFolder)(&str); H();
953 STR_CONV();
954 if (psz && *psz)
955 {
956 char *pszTFTPPrefix = NULL;
957 RTStrAPrintf(&pszTFTPPrefix, "%s%c%s", psz, RTPATH_DELIMITER, "TFTP");
958 rc = CFGMR3InsertString(pCfg, "TFTPPrefix", pszTFTPPrefix); RC_CHECK();
959 RTStrFree(pszTFTPPrefix);
960 }
961 STR_FREE();
962 hrc = pMachine->COMGETTER(Name)(&str); H();
963 STR_CONV();
964 char *pszBootFile = NULL;
965 RTStrAPrintf(&pszBootFile, "%s.pxe", psz);
966 STR_FREE();
967 rc = CFGMR3InsertString(pCfg, "BootFile", pszBootFile); RC_CHECK();
968 RTStrFree(pszBootFile);
969 break;
970 }
971
972 case NetworkAttachmentType_HostInterfaceNetworkAttachment:
973 {
974 /*
975 * Perform the attachment if required (don't return on error!)
976 */
977 hrc = pConsole->attachToHostInterface(networkAdapter);
978 if (SUCCEEDED(hrc))
979 {
980#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
981 Assert (pConsole->maTapFD[ulInstance] >= 0);
982 if (pConsole->maTapFD[ulInstance] >= 0)
983 {
984 if (fSniffer)
985 {
986 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
987 }
988 else
989 {
990 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
991 }
992 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
993 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
994# if defined(RT_OS_SOLARIS)
995 /* Device name/number is required for Solaris as we need it for TAP PPA. */
996 Bstr tapDeviceName;
997 networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam());
998 if (!tapDeviceName.isEmpty())
999 rc = CFGMR3InsertString(pCfg, "Device", Utf8Str(tapDeviceName)); RC_CHECK();
1000
1001 /* TAP setup application/script */
1002 Bstr tapSetupApp;
1003 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApp.asOutParam());
1004 if (!tapSetupApp.isEmpty())
1005 rc = CFGMR3InsertString(pCfg, "TAPSetupApplication", Utf8Str(tapSetupApp)); RC_CHECK();
1006
1007 /* TAP terminate application/script */
1008 Bstr tapTerminateApp;
1009 networkAdapter->COMGETTER(TAPTerminateApplication)(tapTerminateApp.asOutParam());
1010 if (!tapTerminateApp.isEmpty())
1011 rc = CFGMR3InsertString(pCfg, "TAPTerminateApplication", Utf8Str(tapTerminateApp)); RC_CHECK();
1012
1013 /* "FileHandle" must NOT be inserted here, it is done in DrvTAP.cpp */
1014
1015# else
1016 rc = CFGMR3InsertInteger(pCfg, "FileHandle", pConsole->maTapFD[ulInstance]); RC_CHECK();
1017# endif
1018 }
1019#elif defined(RT_OS_WINDOWS)
1020 if (fSniffer)
1021 {
1022 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1023 }
1024 else
1025 {
1026 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1027 }
1028 Bstr hostInterfaceName;
1029 hrc = networkAdapter->COMGETTER(HostInterface)(hostInterfaceName.asOutParam()); H();
1030 ComPtr<IHostNetworkInterfaceCollection> coll;
1031 hrc = host->COMGETTER(NetworkInterfaces)(coll.asOutParam()); H();
1032 ComPtr<IHostNetworkInterface> hostInterface;
1033 rc = coll->FindByName(hostInterfaceName, hostInterface.asOutParam());
1034 if (!SUCCEEDED(rc))
1035 {
1036 AssertMsgFailed(("Cannot get GUID for host interface '%ls'\n", hostInterfaceName));
1037 hrc = networkAdapter->Detach(); H();
1038 }
1039 else
1040 {
1041 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
1042 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1043 rc = CFGMR3InsertString(pCfg, "HostInterfaceName", Utf8Str(hostInterfaceName)); RC_CHECK();
1044 Guid hostIFGuid;
1045 hrc = hostInterface->COMGETTER(Id)(hostIFGuid.asOutParam()); H();
1046 char szDriverGUID[256] = {0};
1047 /* add curly brackets */
1048 szDriverGUID[0] = '{';
1049 strcpy(szDriverGUID + 1, hostIFGuid.toString().raw());
1050 strcat(szDriverGUID, "}");
1051 rc = CFGMR3InsertBytes(pCfg, "GUID", szDriverGUID, sizeof(szDriverGUID)); RC_CHECK();
1052 }
1053#else
1054# error "Port me"
1055#endif
1056 }
1057 else
1058 {
1059 switch (hrc)
1060 {
1061#ifdef RT_OS_LINUX
1062 case VERR_ACCESS_DENIED:
1063 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
1064 "Failed to open '/dev/net/tun' for read/write access. Please check the "
1065 "permissions of that node. Either do 'chmod 0666 /dev/net/tun' or "
1066 "change the group of that node and get member of that group. Make "
1067 "sure that these changes are permanently in particular if you are "
1068 "using udev"));
1069#endif /* RT_OS_LINUX */
1070 default:
1071 AssertMsgFailed(("Could not attach to host interface! Bad!\n"));
1072 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
1073 "Failed to initialize Host Interface Networking"));
1074 }
1075 }
1076 break;
1077 }
1078
1079 case NetworkAttachmentType_InternalNetworkAttachment:
1080 {
1081 hrc = networkAdapter->COMGETTER(InternalNetwork)(&str); H();
1082 STR_CONV();
1083 if (psz && *psz)
1084 {
1085 if (fSniffer)
1086 {
1087 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1088 }
1089 else
1090 {
1091 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1092 }
1093 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
1094 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1095 rc = CFGMR3InsertString(pCfg, "Network", psz); RC_CHECK();
1096 }
1097 STR_FREE();
1098 break;
1099 }
1100
1101 default:
1102 AssertMsgFailed(("should not get here!\n"));
1103 break;
1104 }
1105 }
1106
1107 /*
1108 * Serial (UART) Ports
1109 */
1110 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); RC_CHECK();
1111 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ulInstance++)
1112 {
1113 ComPtr<ISerialPort> serialPort;
1114 hrc = pMachine->GetSerialPort (ulInstance, serialPort.asOutParam()); H();
1115 BOOL fEnabled = FALSE;
1116 if (serialPort)
1117 hrc = serialPort->COMGETTER(Enabled)(&fEnabled); H();
1118 if (!fEnabled)
1119 continue;
1120
1121 char szInstance[4]; Assert(ulInstance <= 999);
1122 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1123
1124 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
1125 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1126
1127 ULONG ulIRQ, ulIOBase;
1128 PortMode_T HostMode;
1129 Bstr path;
1130 BOOL fServer;
1131 hrc = serialPort->COMGETTER(HostMode)(&HostMode); H();
1132 hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H();
1133 hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H();
1134 hrc = serialPort->COMGETTER(Path)(path.asOutParam()); H();
1135 hrc = serialPort->COMGETTER(Server)(&fServer); H();
1136 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1137 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1138 if (HostMode != PortMode_DisconnectedPort)
1139 {
1140 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1141 if (HostMode == PortMode_HostPipePort)
1142 {
1143 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK();
1144 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1145 rc = CFGMR3InsertString(pLunL1, "Driver", "NamedPipe"); RC_CHECK();
1146 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK();
1147 rc = CFGMR3InsertString(pLunL2, "Location", Utf8Str(path)); RC_CHECK();
1148 rc = CFGMR3InsertInteger(pLunL2, "IsServer", fServer); RC_CHECK();
1149 }
1150 else if (HostMode == PortMode_HostDevicePort)
1151 {
1152 rc = CFGMR3InsertString(pLunL0, "Driver", "Host Serial"); RC_CHECK();
1153 rc = CFGMR3InsertNode(pLunL0, "Config", &pLunL1); RC_CHECK();
1154 rc = CFGMR3InsertString(pLunL1, "DevicePath", Utf8Str(path)); RC_CHECK();
1155 }
1156 }
1157 }
1158
1159 /*
1160 * Parallel (LPT) Ports
1161 */
1162 rc = CFGMR3InsertNode(pDevices, "parallel", &pDev); RC_CHECK();
1163 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ulInstance++)
1164 {
1165 ComPtr<IParallelPort> parallelPort;
1166 hrc = pMachine->GetParallelPort (ulInstance, parallelPort.asOutParam()); H();
1167 BOOL fEnabled = FALSE;
1168 if (parallelPort)
1169 hrc = parallelPort->COMGETTER(Enabled)(&fEnabled); H();
1170 if (!fEnabled)
1171 continue;
1172
1173 char szInstance[4]; Assert(ulInstance <= 999);
1174 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1175
1176 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
1177 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1178
1179 ULONG ulIRQ, ulIOBase;
1180 Bstr DevicePath;
1181 hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ); H();
1182 hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase); H();
1183 hrc = parallelPort->COMGETTER(Path)(DevicePath.asOutParam()); H();
1184 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1185 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1186 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1187 rc = CFGMR3InsertString(pLunL0, "Driver", "HostParallel"); RC_CHECK();
1188 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1189 rc = CFGMR3InsertString(pLunL1, "DevicePath", Utf8Str(DevicePath)); RC_CHECK();
1190 }
1191
1192 /*
1193 * VMM Device
1194 */
1195 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); RC_CHECK();
1196 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1197 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1198 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1199 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); RC_CHECK();
1200 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1201
1202 /* the VMM device's Main driver */
1203 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1204 rc = CFGMR3InsertString(pLunL0, "Driver", "MainVMMDev"); RC_CHECK();
1205 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1206 VMMDev *pVMMDev = pConsole->mVMMDev;
1207 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pVMMDev); RC_CHECK();
1208
1209 /*
1210 * Attach the status driver.
1211 */
1212 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1213 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1214 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1215 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSharedFolderLed); RC_CHECK();
1216 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1217 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1218
1219 /*
1220 * Audio Sniffer Device
1221 */
1222 rc = CFGMR3InsertNode(pDevices, "AudioSniffer", &pDev); RC_CHECK();
1223 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1224 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1225
1226 /* the Audio Sniffer device's Main driver */
1227 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1228 rc = CFGMR3InsertString(pLunL0, "Driver", "MainAudioSniffer"); RC_CHECK();
1229 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1230 AudioSniffer *pAudioSniffer = pConsole->mAudioSniffer;
1231 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); RC_CHECK();
1232
1233 /*
1234 * AC'97 ICH audio
1235 */
1236 ComPtr<IAudioAdapter> audioAdapter;
1237 hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H();
1238 BOOL enabled = FALSE;
1239 if (audioAdapter)
1240 {
1241 hrc = audioAdapter->COMGETTER(Enabled)(&enabled); H();
1242 }
1243 if (enabled)
1244 {
1245 rc = CFGMR3InsertNode(pDevices, "ichac97", &pDev); /* ichac97 */
1246 rc = CFGMR3InsertNode(pDev, "0", &pInst);
1247 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1248 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 5); RC_CHECK();
1249 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1250 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
1251
1252 /* the Audio driver */
1253 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1254 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
1255 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1256 AudioDriverType_T audioDriver;
1257 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H();
1258 switch (audioDriver)
1259 {
1260 case AudioDriverType_NullAudioDriver:
1261 {
1262 rc = CFGMR3InsertString(pCfg, "AudioDriver", "null"); RC_CHECK();
1263 break;
1264 }
1265#ifdef RT_OS_WINDOWS
1266#ifdef VBOX_WITH_WINMM
1267 case AudioDriverType_WINMMAudioDriver:
1268 {
1269 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); RC_CHECK();
1270 break;
1271 }
1272#endif
1273 case AudioDriverType_DSOUNDAudioDriver:
1274 {
1275 rc = CFGMR3InsertString(pCfg, "AudioDriver", "dsound"); RC_CHECK();
1276 break;
1277 }
1278#endif /* RT_OS_WINDOWS */
1279#ifdef RT_OS_LINUX
1280 case AudioDriverType_OSSAudioDriver:
1281 {
1282 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); RC_CHECK();
1283 break;
1284 }
1285# ifdef VBOX_WITH_ALSA
1286 case AudioDriverType_ALSAAudioDriver:
1287 {
1288 rc = CFGMR3InsertString(pCfg, "AudioDriver", "alsa"); RC_CHECK();
1289 break;
1290 }
1291# endif
1292#endif /* RT_OS_LINUX */
1293#ifdef RT_OS_DARWIN
1294 case AudioDriverType_CoreAudioDriver:
1295 {
1296 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); RC_CHECK();
1297 break;
1298 }
1299#endif
1300 }
1301 }
1302
1303 /*
1304 * The USB Controller.
1305 */
1306 ComPtr<IUSBController> USBCtlPtr;
1307 hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam());
1308 if (USBCtlPtr)
1309 {
1310 BOOL fEnabled;
1311 hrc = USBCtlPtr->COMGETTER(Enabled)(&fEnabled); H();
1312 if (fEnabled)
1313 {
1314 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); RC_CHECK();
1315 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1316 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1317 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1318 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); RC_CHECK();
1319 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1320
1321 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1322 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1323 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1324
1325 /*
1326 * Attach the status driver.
1327 */
1328 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1329 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1330 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1331 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed);RC_CHECK();
1332 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1333 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1334 }
1335 }
1336
1337 /*
1338 * Clipboard
1339 */
1340 {
1341 ClipboardMode_T mode = ClipboardMode_ClipDisabled;
1342 hrc = pMachine->COMGETTER(ClipboardMode) (&mode); H();
1343
1344 if (mode != ClipboardMode_ClipDisabled)
1345 {
1346 /* Load the service */
1347 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedClipboard", "VBoxSharedClipboard");
1348
1349 if (VBOX_FAILURE (rc))
1350 {
1351 LogRel(("VBoxSharedClipboard is not available. rc = %Vrc\n", rc));
1352 /* That is not a fatal failure. */
1353 rc = VINF_SUCCESS;
1354 }
1355 else
1356 {
1357 /* Setup the service. */
1358 VBOXHGCMSVCPARM parm;
1359
1360 parm.type = VBOX_HGCM_SVC_PARM_32BIT;
1361
1362 switch (mode)
1363 {
1364 default:
1365 case ClipboardMode_ClipDisabled:
1366 {
1367 LogRel(("VBoxSharedClipboard mode: Off\n"));
1368 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
1369 break;
1370 }
1371 case ClipboardMode_ClipGuestToHost:
1372 {
1373 LogRel(("VBoxSharedClipboard mode: Guest to Host\n"));
1374 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
1375 break;
1376 }
1377 case ClipboardMode_ClipHostToGuest:
1378 {
1379 LogRel(("VBoxSharedClipboard mode: Host to Guest\n"));
1380 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
1381 break;
1382 }
1383 case ClipboardMode_ClipBidirectional:
1384 {
1385 LogRel(("VBoxSharedClipboard mode: Bidirectional\n"));
1386 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
1387 break;
1388 }
1389 }
1390
1391 pConsole->mVMMDev->hgcmHostCall ("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
1392
1393 Log(("Set VBoxSharedClipboard mode\n"));
1394 }
1395 }
1396 }
1397
1398 /*
1399 * CFGM overlay handling.
1400 *
1401 * Here we check the extra data entries for CFGM values
1402 * and create the nodes and insert the values on the fly. Existing
1403 * values will be removed and reinserted. If a value is a valid number,
1404 * it will be inserted as a number, otherwise as a string.
1405 *
1406 * We first perform a run on global extra data, then on the machine
1407 * extra data to support global settings with local overrides.
1408 *
1409 */
1410 Bstr strExtraDataKey;
1411 bool fGlobalExtraData = true;
1412 for (;;)
1413 {
1414 Bstr strNextExtraDataKey;
1415 Bstr strExtraDataValue;
1416
1417 /* get the next key */
1418 if (fGlobalExtraData)
1419 hrc = virtualBox->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
1420 strExtraDataValue.asOutParam());
1421 else
1422 hrc = pMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
1423 strExtraDataValue.asOutParam());
1424
1425 /* stop if for some reason there's nothing more to request */
1426 if (FAILED(hrc) || !strNextExtraDataKey)
1427 {
1428 /* if we're out of global keys, continue with machine, otherwise we're done */
1429 if (fGlobalExtraData)
1430 {
1431 fGlobalExtraData = false;
1432 strExtraDataKey.setNull();
1433 continue;
1434 }
1435 break;
1436 }
1437
1438 strExtraDataKey = strNextExtraDataKey;
1439 Utf8Str strExtraDataKeyUtf8 = Utf8Str(strExtraDataKey);
1440
1441 /* we only care about keys starting with "VBoxInternal/" */
1442 if (strncmp(strExtraDataKeyUtf8.raw(), "VBoxInternal/", 13) != 0)
1443 continue;
1444 char *pszExtraDataKey = (char*)strExtraDataKeyUtf8.raw() + 13;
1445
1446 /* the key will be in the format "Node1/Node2/Value" or simply "Value". */
1447 PCFGMNODE pNode;
1448 char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
1449 if (pszCFGMValueName)
1450 {
1451 /* terminate the node and advance to the value */
1452 *pszCFGMValueName = '\0';
1453 pszCFGMValueName++;
1454
1455 /* does the node already exist? */
1456 pNode = CFGMR3GetChild(pRoot, pszExtraDataKey);
1457 if (pNode)
1458 {
1459 /* the value might already exist, remove it to be safe */
1460 CFGMR3RemoveValue(pNode, pszCFGMValueName);
1461 }
1462 else
1463 {
1464 /* create the node */
1465 rc = CFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode);
1466 AssertMsgRC(rc, ("failed to insert node '%s'\n", pszExtraDataKey));
1467 if (VBOX_FAILURE(rc) || !pNode)
1468 continue;
1469 }
1470 }
1471 else
1472 {
1473 pNode = pRoot;
1474 pszCFGMValueName = pszExtraDataKey;
1475 pszExtraDataKey--;
1476
1477 /* the value might already exist, remove it to be safe */
1478 CFGMR3RemoveValue(pNode, pszCFGMValueName);
1479 }
1480
1481 /* now let's have a look at the value */
1482 Utf8Str strCFGMValueUtf8 = Utf8Str(strExtraDataValue);
1483 const char *pszCFGMValue = strCFGMValueUtf8.raw();
1484 /* empty value means remove value which we've already done */
1485 if (pszCFGMValue && *pszCFGMValue)
1486 {
1487 /* if it's a valid number, we'll insert it as such, otherwise string */
1488 uint64_t u64Value;
1489 if (RTStrToUInt64Ex(pszCFGMValue, NULL, 0, &u64Value) == VINF_SUCCESS)
1490 {
1491 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
1492 }
1493 else
1494 {
1495 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue);
1496 }
1497 AssertMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszExtraDataKey));
1498 }
1499 }
1500
1501#undef H
1502#undef RC_CHECK
1503#undef STR_FREE
1504#undef STR_CONV
1505
1506 /* Register VM state change handler */
1507 int rc2 = VMR3AtStateRegister (pVM, Console::vmstateChangeCallback, pConsole);
1508 AssertRC (rc2);
1509 if (VBOX_SUCCESS (rc))
1510 rc = rc2;
1511
1512 /* Register VM runtime error handler */
1513 rc2 = VMR3AtRuntimeErrorRegister (pVM, Console::setVMRuntimeErrorCallback, pConsole);
1514 AssertRC (rc2);
1515 if (VBOX_SUCCESS (rc))
1516 rc = rc2;
1517
1518 /* Save the VM pointer in the machine object */
1519 pConsole->mpVM = pVM;
1520
1521 LogFlowFunc (("vrc = %Vrc\n", rc));
1522 LogFlowFuncLeave();
1523
1524 return rc;
1525}
1526
1527
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