VirtualBox

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

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

iprt/param.h for RTPATH_MAX.

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