VirtualBox

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

Last change on this file since 9809 was 9809, checked in by vboxsync, 16 years ago

Main: save and reload the guest/host registry in extra data at machine startup and shutdown

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