VirtualBox

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

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

Solaris

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