VirtualBox

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

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

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 100.1 KB
Line 
1/* $Id: ConsoleImpl2.cpp 14772 2008-11-28 12:41:22Z 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_CROGL
48#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
49#endif
50#ifdef VBOX_WITH_GUEST_PROPS
51# include <VBox/HostServices/GuestPropertySvc.h>
52# include <VBox/com/defs.h>
53# include <VBox/com/array.h>
54# include <hgcm/HGCM.h> /** @todo it should be possible to register a service
55 * extension using a VMMDev callback. */
56# include <vector>
57#endif /* VBOX_WITH_GUEST_PROPS */
58#include <VBox/intnet.h>
59
60#include <VBox/com/string.h>
61#include <VBox/com/array.h>
62
63#if defined(RT_OS_SOLARIS) && defined(VBOX_WITH_NETFLT)
64# include <zone.h>
65#endif
66
67#if defined(RT_OS_LINUX) && defined(VBOX_WITH_NETFLT)
68# include <unistd.h>
69# include <sys/ioctl.h>
70# include <sys/socket.h>
71# include <linux/types.h>
72# include <linux/if.h>
73# include <linux/wireless.h>
74#endif
75
76#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
77# include <VBox/WinNetConfig.h>
78# include <Ntddndis.h>
79# include <devguid.h>
80#endif
81
82
83/*
84 * VC++ 8 / amd64 has some serious trouble with this function.
85 * As a temporary measure, we'll drop global optimizations.
86 */
87#if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
88# pragma optimize("g", off)
89#endif
90
91/**
92 * Construct the VM configuration tree (CFGM).
93 *
94 * This is a callback for VMR3Create() call. It is called from CFGMR3Init()
95 * in the emulation thread (EMT). Any per thread COM/XPCOM initialization
96 * is done here.
97 *
98 * @param pVM VM handle.
99 * @param pvConsole Pointer to the VMPowerUpTask object.
100 * @return VBox status code.
101 *
102 * @note Locks the Console object for writing.
103 */
104DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
105{
106 LogFlowFuncEnter();
107 /* Note: hardcoded assumption about number of slots; see rom bios */
108 bool afPciDeviceNo[15] = {false};
109
110#if !defined (VBOX_WITH_XPCOM)
111 {
112 /* initialize COM */
113 HRESULT hrc = CoInitializeEx(NULL,
114 COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE |
115 COINIT_SPEED_OVER_MEMORY);
116 LogFlow (("Console::configConstructor(): CoInitializeEx()=%08X\n", hrc));
117 AssertComRCReturn (hrc, VERR_GENERAL_FAILURE);
118 }
119#endif
120
121 AssertReturn (pvConsole, VERR_GENERAL_FAILURE);
122 ComObjPtr <Console> pConsole = static_cast <Console *> (pvConsole);
123
124 AutoCaller autoCaller (pConsole);
125 AssertComRCReturn (autoCaller.rc(), VERR_ACCESS_DENIED);
126
127 /* lock the console because we widely use internal fields and methods */
128 AutoWriteLock alock (pConsole);
129
130 ComPtr <IMachine> pMachine = pConsole->machine();
131
132 int rc;
133 HRESULT hrc;
134 char *psz = NULL;
135 BSTR str = NULL;
136
137 Bstr bstr; /* use this bstr when calling COM methods instead
138 of str as it manages memory! */
139
140#define STR_CONV() do { rc = RTUtf16ToUtf8(str, &psz); RC_CHECK(); } while (0)
141#define STR_FREE() do { if (str) { SysFreeString(str); str = NULL; } if (psz) { RTStrFree(psz); psz = NULL; } } while (0)
142#define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); STR_FREE(); return rc; } } while (0)
143#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%#x\n", hrc)); STR_FREE(); return VERR_GENERAL_FAILURE; } } while (0)
144
145 /*
146 * Get necessary objects and frequently used parameters.
147 */
148 ComPtr<IVirtualBox> virtualBox;
149 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
150
151 ComPtr<IHost> host;
152 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
153
154 ComPtr <ISystemProperties> systemProperties;
155 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
156
157 ComPtr<IBIOSSettings> biosSettings;
158 hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
159
160 Guid uuid;
161 hrc = pMachine->COMGETTER(Id)(uuid.asOutParam()); H();
162 PCRTUUID pUuid = uuid.raw();
163
164 ULONG cRamMBs;
165 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
166
167 ULONG cCpus = 1;
168#ifdef VBOX_WITH_SMP_GUESTS
169 hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
170#endif
171
172 /*
173 * Get root node first.
174 * This is the only node in the tree.
175 */
176 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
177 Assert(pRoot);
178
179 /*
180 * Set the root level values.
181 */
182 hrc = pMachine->COMGETTER(Name)(&str); H();
183 STR_CONV();
184 rc = CFGMR3InsertString(pRoot, "Name", psz); RC_CHECK();
185 STR_FREE();
186 rc = CFGMR3InsertBytes(pRoot, "UUID", pUuid, sizeof(*pUuid)); RC_CHECK();
187 rc = CFGMR3InsertInteger(pRoot, "RamSize", cRamMBs * _1M); RC_CHECK();
188 rc = CFGMR3InsertInteger(pRoot, "NumCPUs", cCpus); RC_CHECK();
189 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); RC_CHECK();
190 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); /* boolean */ RC_CHECK();
191 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); /* boolean */ RC_CHECK();
192 /** @todo Config: RawR0, PATMEnabled and CASMEnabled needs attention later. */
193 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); /* boolean */ RC_CHECK();
194 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); /* boolean */ RC_CHECK();
195
196 /* hardware virtualization extensions */
197 TSBool_T hwVirtExEnabled;
198 BOOL fHWVirtExEnabled;
199 hrc = pMachine->COMGETTER(HWVirtExEnabled)(&hwVirtExEnabled); H();
200 if (hwVirtExEnabled == TSBool_Default)
201 {
202 /* check the default value */
203 hrc = systemProperties->COMGETTER(HWVirtExEnabled)(&fHWVirtExEnabled); H();
204 }
205 else
206 fHWVirtExEnabled = (hwVirtExEnabled == TSBool_True);
207#ifdef RT_OS_DARWIN
208 rc = CFGMR3InsertInteger(pRoot, "HwVirtExtForced", fHWVirtExEnabled); RC_CHECK();
209#else
210 rc = CFGMR3InsertInteger(pRoot, "HwVirtExtForced", 0); RC_CHECK();
211#endif
212 if (fHWVirtExEnabled)
213 {
214 PCFGMNODE pHWVirtExt;
215 rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHWVirtExt); RC_CHECK();
216 rc = CFGMR3InsertInteger(pHWVirtExt, "Enabled", 1); RC_CHECK();
217 }
218
219 /* Nested paging (VT-x/AMD-V) */
220 BOOL fEnableNestedPaging = false;
221 hrc = pMachine->COMGETTER(HWVirtExNestedPagingEnabled)(&fEnableNestedPaging); H();
222 rc = CFGMR3InsertInteger(pRoot, "EnableNestedPaging", fEnableNestedPaging); RC_CHECK();
223
224 /* VPID (VT-x) */
225 BOOL fEnableVPID = false;
226 hrc = pMachine->COMGETTER(HWVirtExVPIDEnabled)(&fEnableVPID); H();
227 rc = CFGMR3InsertInteger(pRoot, "EnableVPID", fEnableVPID); RC_CHECK();
228
229 /* Physical Address Extension (PAE) */
230 BOOL fEnablePAE = false;
231 hrc = pMachine->COMGETTER(PAEEnabled)(&fEnablePAE); H();
232 rc = CFGMR3InsertInteger(pRoot, "EnablePAE", fEnablePAE); RC_CHECK();
233
234 BOOL fIOAPIC;
235 hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
236
237 BOOL fPXEDebug;
238 hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
239
240 /*
241 * Virtual IDE controller type.
242 */
243 IDEControllerType_T controllerType;
244 BOOL fPIIX4;
245 hrc = biosSettings->COMGETTER(IDEControllerType)(&controllerType); H();
246 switch (controllerType)
247 {
248 case IDEControllerType_PIIX3:
249 fPIIX4 = FALSE;
250 break;
251 case IDEControllerType_PIIX4:
252 fPIIX4 = TRUE;
253 break;
254 default:
255 AssertMsgFailed(("Invalid IDE controller type '%d'", controllerType));
256 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
257 N_("Invalid IDE controller type '%d'"), controllerType);
258 }
259
260 /*
261 * PDM config.
262 * Load drivers in VBoxC.[so|dll]
263 */
264 PCFGMNODE pPDM;
265 PCFGMNODE pDrivers;
266 PCFGMNODE pMod;
267 rc = CFGMR3InsertNode(pRoot, "PDM", &pPDM); RC_CHECK();
268 rc = CFGMR3InsertNode(pPDM, "Drivers", &pDrivers); RC_CHECK();
269 rc = CFGMR3InsertNode(pDrivers, "VBoxC", &pMod); RC_CHECK();
270#ifdef VBOX_WITH_XPCOM
271 // VBoxC is located in the components subdirectory
272 char szPathVBoxC[RTPATH_MAX];
273 rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc);
274 strcat(szPathVBoxC, "/components/VBoxC");
275 rc = CFGMR3InsertString(pMod, "Path", szPathVBoxC); RC_CHECK();
276#else
277 rc = CFGMR3InsertString(pMod, "Path", "VBoxC"); RC_CHECK();
278#endif
279
280 /*
281 * Devices
282 */
283 PCFGMNODE pDevices = NULL; /* /Devices */
284 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
285 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
286 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
287 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
288 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
289 PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
290 PCFGMNODE pIdeInst = NULL; /* /Devices/piix3ide/0/ */
291 PCFGMNODE pSataInst = NULL; /* /Devices/ahci/0/ */
292 PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */
293
294 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); RC_CHECK();
295
296 /*
297 * PC Arch.
298 */
299 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); RC_CHECK();
300 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
301 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
302 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
303
304 /*
305 * PC Bios.
306 */
307 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); RC_CHECK();
308 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
309 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
310 rc = CFGMR3InsertNode(pInst, "Config", &pBiosCfg); RC_CHECK();
311 rc = CFGMR3InsertInteger(pBiosCfg, "RamSize", cRamMBs * _1M); RC_CHECK();
312 rc = CFGMR3InsertInteger(pBiosCfg, "NumCPUs", cCpus); RC_CHECK();
313 rc = CFGMR3InsertString(pBiosCfg, "HardDiskDevice", "piix3ide"); RC_CHECK();
314 rc = CFGMR3InsertString(pBiosCfg, "FloppyDevice", "i82078"); RC_CHECK();
315 rc = CFGMR3InsertInteger(pBiosCfg, "IOAPIC", fIOAPIC); RC_CHECK();
316 rc = CFGMR3InsertInteger(pBiosCfg, "PXEDebug", fPXEDebug); RC_CHECK();
317 rc = CFGMR3InsertBytes(pBiosCfg, "UUID", pUuid, sizeof(*pUuid)); RC_CHECK();
318
319 DeviceType_T bootDevice;
320 if (SchemaDefs::MaxBootPosition > 9)
321 {
322 AssertMsgFailed (("Too many boot devices %d\n",
323 SchemaDefs::MaxBootPosition));
324 return VERR_INVALID_PARAMETER;
325 }
326
327 for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; pos ++)
328 {
329 hrc = pMachine->GetBootOrder(pos, &bootDevice); H();
330
331 char szParamName[] = "BootDeviceX";
332 szParamName[sizeof (szParamName) - 2] = ((char (pos - 1)) + '0');
333
334 const char *pszBootDevice;
335 switch (bootDevice)
336 {
337 case DeviceType_Null:
338 pszBootDevice = "NONE";
339 break;
340 case DeviceType_HardDisk:
341 pszBootDevice = "IDE";
342 break;
343 case DeviceType_DVD:
344 pszBootDevice = "DVD";
345 break;
346 case DeviceType_Floppy:
347 pszBootDevice = "FLOPPY";
348 break;
349 case DeviceType_Network:
350 pszBootDevice = "LAN";
351 break;
352 default:
353 AssertMsgFailed(("Invalid bootDevice=%d\n", bootDevice));
354 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
355 N_("Invalid boot device '%d'"), bootDevice);
356 }
357 rc = CFGMR3InsertString(pBiosCfg, szParamName, pszBootDevice); RC_CHECK();
358 }
359
360 /*
361 * The time offset
362 */
363 LONG64 timeOffset;
364 hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H();
365 PCFGMNODE pTMNode;
366 rc = CFGMR3InsertNode(pRoot, "TM", &pTMNode); RC_CHECK();
367 rc = CFGMR3InsertInteger(pTMNode, "UTCOffset", timeOffset * 1000000); RC_CHECK();
368
369 /*
370 * DMA
371 */
372 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); RC_CHECK();
373 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
374 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
375
376 /*
377 * PCI buses.
378 */
379 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ RC_CHECK();
380 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
381 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
382 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
383 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
384
385#if 0 /* enable this to test PCI bridging */
386 rc = CFGMR3InsertNode(pDevices, "pcibridge", &pDev); RC_CHECK();
387 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
388 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
389 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
390 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 14); RC_CHECK();
391 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
392 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 0);/* -> pci[0] */ RC_CHECK();
393
394 rc = CFGMR3InsertNode(pDev, "1", &pInst); RC_CHECK();
395 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
396 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
397 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); RC_CHECK();
398 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
399 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK();
400
401 rc = CFGMR3InsertNode(pDev, "2", &pInst); RC_CHECK();
402 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
403 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
404 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 3); RC_CHECK();
405 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
406 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK();
407#endif
408
409 /*
410 * PS/2 keyboard & mouse.
411 */
412 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); RC_CHECK();
413 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
414 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
415 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
416
417 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
418 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); RC_CHECK();
419 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
420 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); RC_CHECK();
421
422 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
423 rc = CFGMR3InsertString(pLunL1, "Driver", "MainKeyboard"); RC_CHECK();
424 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
425 Keyboard *pKeyboard = pConsole->mKeyboard;
426 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pKeyboard); RC_CHECK();
427
428 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); RC_CHECK();
429 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); RC_CHECK();
430 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
431 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); RC_CHECK();
432
433 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
434 rc = CFGMR3InsertString(pLunL1, "Driver", "MainMouse"); RC_CHECK();
435 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
436 Mouse *pMouse = pConsole->mMouse;
437 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pMouse); RC_CHECK();
438
439 /*
440 * i82078 Floppy drive controller
441 */
442 ComPtr<IFloppyDrive> floppyDrive;
443 hrc = pMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam()); H();
444 BOOL fFdcEnabled;
445 hrc = floppyDrive->COMGETTER(Enabled)(&fFdcEnabled); H();
446 if (fFdcEnabled)
447 {
448 rc = CFGMR3InsertNode(pDevices, "i82078", &pDev); RC_CHECK();
449 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
450 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); RC_CHECK();
451 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
452 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); RC_CHECK();
453 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); RC_CHECK();
454 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); RC_CHECK();
455 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); RC_CHECK();
456
457 /* Attach the status driver */
458 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
459 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
460 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
461 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapFDLeds[0]); RC_CHECK();
462 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
463 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
464
465 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
466
467 ComPtr<IFloppyImage2> floppyImage;
468 hrc = floppyDrive->GetImage(floppyImage.asOutParam()); H();
469 if (floppyImage)
470 {
471 pConsole->meFloppyState = DriveState_ImageMounted;
472 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
473 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
474 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
475 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
476
477 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
478 rc = CFGMR3InsertString(pLunL1, "Driver", "RawImage"); RC_CHECK();
479 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
480 hrc = floppyImage->COMGETTER(Location)(&str); H();
481 STR_CONV();
482 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
483 STR_FREE();
484 }
485 else
486 {
487 ComPtr<IHostFloppyDrive> hostFloppyDrive;
488 hrc = floppyDrive->GetHostDrive(hostFloppyDrive.asOutParam()); H();
489 if (hostFloppyDrive)
490 {
491 pConsole->meFloppyState = DriveState_HostDriveCaptured;
492 rc = CFGMR3InsertString(pLunL0, "Driver", "HostFloppy"); RC_CHECK();
493 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
494 hrc = hostFloppyDrive->COMGETTER(Name)(&str); H();
495 STR_CONV();
496 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
497 STR_FREE();
498 }
499 else
500 {
501 pConsole->meFloppyState = DriveState_NotMounted;
502 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
503 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
504 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
505 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
506 }
507 }
508 }
509
510 /*
511 * ACPI
512 */
513 BOOL fACPI;
514 hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI); H();
515 if (fACPI)
516 {
517 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); RC_CHECK();
518 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
519 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
520 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
521 rc = CFGMR3InsertInteger(pCfg, "RamSize", cRamMBs * _1M); RC_CHECK();
522 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK();
523
524 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
525 rc = CFGMR3InsertInteger(pCfg, "FdcEnabled", fFdcEnabled); RC_CHECK();
526 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); RC_CHECK();
527 Assert(!afPciDeviceNo[7]);
528 afPciDeviceNo[7] = true;
529 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
530
531 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
532 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); RC_CHECK();
533 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
534 }
535
536 /*
537 * i8254 Programmable Interval Timer And Dummy Speaker
538 */
539 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); RC_CHECK();
540 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
541 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
542#ifdef DEBUG
543 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
544#endif
545
546 /*
547 * i8259 Programmable Interrupt Controller.
548 */
549 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); RC_CHECK();
550 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
551 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
552 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
553
554 /*
555 * Advanced Programmable Interrupt Controller.
556 * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states,
557 * thus only single insert
558 */
559 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); RC_CHECK();
560 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
561 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
562 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
563 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
564 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK();
565
566 /* SMP: @todo: IOAPIC may be required for SMP configs */
567 if (fIOAPIC)
568 {
569 /*
570 * I/O Advanced Programmable Interrupt Controller.
571 */
572 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); RC_CHECK();
573 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
574 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
575 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
576 }
577
578 /*
579 * RTC MC146818.
580 */
581 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); RC_CHECK();
582 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
583 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
584
585 /*
586 * VGA.
587 */
588 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); RC_CHECK();
589 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
590 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
591 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); RC_CHECK();
592 Assert(!afPciDeviceNo[2]);
593 afPciDeviceNo[2] = true;
594 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
595 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
596 hrc = pMachine->COMGETTER(VRAMSize)(&cRamMBs); H();
597 rc = CFGMR3InsertInteger(pCfg, "VRamSize", cRamMBs * _1M); RC_CHECK();
598#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */
599 rc = CFGMR3InsertInteger(pCfg, "R0Enabled", false); RC_CHECK();
600#endif
601
602 /*
603 * BIOS logo
604 */
605 BOOL fFadeIn;
606 hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H();
607 rc = CFGMR3InsertInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0); RC_CHECK();
608 BOOL fFadeOut;
609 hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H();
610 rc = CFGMR3InsertInteger(pCfg, "FadeOut", fFadeOut ? 1: 0); RC_CHECK();
611 ULONG logoDisplayTime;
612 hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H();
613 rc = CFGMR3InsertInteger(pCfg, "LogoTime", logoDisplayTime); RC_CHECK();
614 Bstr logoImagePath;
615 hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H();
616 rc = CFGMR3InsertString(pCfg, "LogoFile", logoImagePath ? Utf8Str(logoImagePath) : ""); RC_CHECK();
617
618 /*
619 * Boot menu
620 */
621 BIOSBootMenuMode_T bootMenuMode;
622 int value;
623 biosSettings->COMGETTER(BootMenuMode)(&bootMenuMode);
624 switch (bootMenuMode)
625 {
626 case BIOSBootMenuMode_Disabled:
627 value = 0;
628 break;
629 case BIOSBootMenuMode_MenuOnly:
630 value = 1;
631 break;
632 default:
633 value = 2;
634 }
635 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", value); RC_CHECK();
636
637 /* Custom VESA mode list */
638 unsigned cModes = 0;
639 for (unsigned iMode = 1; iMode <= 16; iMode++)
640 {
641 char szExtraDataKey[sizeof("CustomVideoModeXX")];
642 RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%d", iMode);
643 hrc = pMachine->GetExtraData(Bstr(szExtraDataKey), &str); H();
644 if (!str || !*str)
645 break;
646 STR_CONV();
647 rc = CFGMR3InsertString(pCfg, szExtraDataKey, psz);
648 STR_FREE();
649 cModes++;
650 }
651 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", cModes);
652
653 /* VESA height reduction */
654 ULONG ulHeightReduction;
655 IFramebuffer *pFramebuffer = pConsole->getDisplay()->getFramebuffer();
656 if (pFramebuffer)
657 {
658 hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction); H();
659 }
660 else
661 {
662 /* If framebuffer is not available, there is no height reduction. */
663 ulHeightReduction = 0;
664 }
665 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", ulHeightReduction); RC_CHECK();
666
667 /* Attach the display. */
668 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
669 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); RC_CHECK();
670 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
671 Display *pDisplay = pConsole->mDisplay;
672 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pDisplay); RC_CHECK();
673
674 /*
675 * IDE (update this when the main interface changes)
676 */
677 rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */ RC_CHECK();
678 rc = CFGMR3InsertNode(pDev, "0", &pIdeInst); RC_CHECK();
679 rc = CFGMR3InsertInteger(pIdeInst, "Trusted", 1); /* boolean */ RC_CHECK();
680 rc = CFGMR3InsertInteger(pIdeInst, "PCIDeviceNo", 1); RC_CHECK();
681 Assert(!afPciDeviceNo[1]);
682 afPciDeviceNo[1] = true;
683 rc = CFGMR3InsertInteger(pIdeInst, "PCIFunctionNo", 1); RC_CHECK();
684 rc = CFGMR3InsertNode(pIdeInst, "Config", &pCfg); RC_CHECK();
685 rc = CFGMR3InsertInteger(pCfg, "PIIX4", fPIIX4); /* boolean */ RC_CHECK();
686
687 /* Attach the status driver */
688 rc = CFGMR3InsertNode(pIdeInst, "LUN#999", &pLunL0); RC_CHECK();
689 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
690 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
691 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapIDELeds[0]);RC_CHECK();
692 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
693 rc = CFGMR3InsertInteger(pCfg, "Last", 3); RC_CHECK();
694
695 /*
696 * SATA controller
697 */
698 ComPtr<ISATAController> sataController;
699 hrc = pMachine->COMGETTER(SATAController)(sataController.asOutParam());
700 BOOL enabled = FALSE;
701
702 if (sataController)
703 {
704 hrc = sataController->COMGETTER(Enabled)(&enabled); H();
705
706 if (enabled)
707 {
708 rc = CFGMR3InsertNode(pDevices, "ahci", &pDev); RC_CHECK();
709 rc = CFGMR3InsertNode(pDev, "0", &pSataInst); RC_CHECK();
710 rc = CFGMR3InsertInteger(pSataInst, "Trusted", 1); RC_CHECK();
711 rc = CFGMR3InsertInteger(pSataInst, "PCIDeviceNo", 13); RC_CHECK();
712 Assert(!afPciDeviceNo[13]);
713 afPciDeviceNo[13] = true;
714 rc = CFGMR3InsertInteger(pSataInst, "PCIFunctionNo", 0); RC_CHECK();
715 rc = CFGMR3InsertNode(pSataInst, "Config", &pCfg); RC_CHECK();
716
717 ULONG cPorts = 0;
718 hrc = sataController->COMGETTER(PortCount)(&cPorts); H();
719 rc = CFGMR3InsertInteger(pCfg, "PortCount", cPorts); RC_CHECK();
720
721 /* Needed configuration values for the bios. */
722 rc = CFGMR3InsertString(pBiosCfg, "SataHardDiskDevice", "ahci"); RC_CHECK();
723
724 for (uint32_t i = 0; i < 4; i++)
725 {
726 static const char *s_apszConfig[4] =
727 { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
728 static const char *s_apszBiosConfig[4] =
729 { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" };
730
731 LONG lPortNumber = -1;
732 hrc = sataController->GetIDEEmulationPort(i, &lPortNumber); H();
733 rc = CFGMR3InsertInteger(pCfg, s_apszConfig[i], lPortNumber); RC_CHECK();
734 rc = CFGMR3InsertInteger(pBiosCfg, s_apszBiosConfig[i], lPortNumber); RC_CHECK();
735 }
736
737 /* Attach the status driver */
738 rc = CFGMR3InsertNode(pSataInst,"LUN#999", &pLunL0); RC_CHECK();
739 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
740 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
741 AssertRelease(cPorts <= RT_ELEMENTS(pConsole->mapSATALeds));
742 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSATALeds[0]); RC_CHECK();
743 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
744 rc = CFGMR3InsertInteger(pCfg, "Last", cPorts - 1); RC_CHECK();
745 }
746 }
747
748 /* Attach the hard disks */
749 {
750 com::SafeIfaceArray <IHardDisk2Attachment> atts;
751 hrc = pMachine->
752 COMGETTER(HardDisk2Attachments) (ComSafeArrayAsOutParam (atts)); H();
753
754 for (size_t i = 0; i < atts.size(); ++ i)
755 {
756 ComPtr <IHardDisk2> hardDisk;
757 hrc = atts [i]->COMGETTER(HardDisk) (hardDisk.asOutParam()); H();
758 StorageBus_T enmBus;
759 hrc = atts [i]->COMGETTER(Bus) (&enmBus); H();
760 LONG lDev;
761 hrc = atts [i]->COMGETTER(Device) (&lDev); H();
762 LONG lChannel;
763 hrc = atts [i]->COMGETTER(Channel) (&lChannel); H();
764
765 PCFGMNODE pHardDiskCtl = NULL;
766 int iLUN = 0;
767
768 switch (enmBus)
769 {
770 case StorageBus_IDE:
771 {
772 if (lChannel >= 2 || lChannel < 0)
773 {
774 AssertMsgFailed (("invalid controller channel number: "
775 "%d\n", lChannel));
776 return VERR_GENERAL_FAILURE;
777 }
778
779 if (lDev >= 2 || lDev < 0)
780 {
781 AssertMsgFailed (("invalid controller device number: "
782 "%d\n", lDev));
783 return VERR_GENERAL_FAILURE;
784 }
785
786 iLUN = 2 * lChannel + lDev;
787 pHardDiskCtl = pIdeInst;
788
789 break;
790 }
791 case StorageBus_SATA:
792 {
793 iLUN = lChannel;
794 pHardDiskCtl = enabled ? pSataInst : NULL;
795 break;
796 }
797 default:
798 {
799 AssertMsgFailed (("invalid disk controller type: "
800 "%d\n", enmBus));
801 return VERR_GENERAL_FAILURE;
802 }
803 }
804
805 /* Can be NULL if SATA controller is not enabled and current hard
806 * disk is attached to SATA controller. */
807 if (pHardDiskCtl == NULL)
808 continue;
809
810 char szLUN[16];
811 RTStrPrintf (szLUN, sizeof(szLUN), "LUN#%d", iLUN);
812
813 rc = CFGMR3InsertNode (pHardDiskCtl, szLUN, &pLunL0); RC_CHECK();
814 rc = CFGMR3InsertString (pLunL0, "Driver", "Block"); RC_CHECK();
815 rc = CFGMR3InsertNode (pLunL0, "Config", &pCfg); RC_CHECK();
816 rc = CFGMR3InsertString (pCfg, "Type", "HardDisk"); RC_CHECK();
817 rc = CFGMR3InsertInteger (pCfg, "Mountable", 0); RC_CHECK();
818
819 rc = CFGMR3InsertNode (pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
820 rc = CFGMR3InsertString (pLunL1, "Driver", "VD"); RC_CHECK();
821 rc = CFGMR3InsertNode (pLunL1, "Config", &pCfg); RC_CHECK();
822
823 hrc = hardDisk->COMGETTER(Location) (bstr.asOutParam()); H();
824 rc = CFGMR3InsertString (pCfg, "Path", Utf8Str (bstr)); RC_CHECK();
825
826 hrc = hardDisk->COMGETTER(Format) (bstr.asOutParam()); H();
827 rc = CFGMR3InsertString (pCfg, "Format", Utf8Str (bstr)); RC_CHECK();
828
829#if defined(VBOX_WITH_PDM_ASYNC_COMPLETION)
830 if (bstr == L"VMDK")
831 {
832 /* Create cfgm nodes for async transport driver because VMDK is
833 * currently the only one which may support async I/O. This has
834 * to be made generic based on the capabiliy flags when the new
835 * HardDisk interface is merged.
836 */
837 rc = CFGMR3InsertNode (pLunL1, "AttachedDriver", &pLunL2); RC_CHECK();
838 rc = CFGMR3InsertString (pLunL2, "Driver", "TransportAsync"); RC_CHECK();
839 /* The async transport driver has no config options yet. */
840 }
841#endif
842
843 /* Create an inversed tree of parents. */
844 ComPtr <IHardDisk2> parentHardDisk = hardDisk;
845 for (PCFGMNODE pParent = pCfg;;)
846 {
847 hrc = parentHardDisk->
848 COMGETTER(Parent) (hardDisk.asOutParam()); H();
849 if (hardDisk.isNull())
850 break;
851
852 PCFGMNODE pCur;
853 rc = CFGMR3InsertNode (pParent, "Parent", &pCur); RC_CHECK();
854 hrc = hardDisk->COMGETTER(Location) (bstr.asOutParam()); H();
855 rc = CFGMR3InsertString (pCur, "Path", Utf8Str (bstr)); RC_CHECK();
856
857 hrc = hardDisk->COMGETTER(Format) (bstr.asOutParam()); H();
858 rc = CFGMR3InsertString (pCur, "Format", Utf8Str (bstr)); RC_CHECK();
859
860 /* next */
861 pParent = pCur;
862 parentHardDisk = hardDisk;
863 }
864 }
865 }
866 H();
867
868 ComPtr<IDVDDrive> dvdDrive;
869 hrc = pMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam()); H();
870 if (dvdDrive)
871 {
872 // ASSUME: DVD drive is always attached to LUN#2 (i.e. secondary IDE master)
873 rc = CFGMR3InsertNode(pIdeInst, "LUN#2", &pLunL0); RC_CHECK();
874 ComPtr<IHostDVDDrive> hostDvdDrive;
875 hrc = dvdDrive->GetHostDrive(hostDvdDrive.asOutParam()); H();
876 if (hostDvdDrive)
877 {
878 pConsole->meDVDState = DriveState_HostDriveCaptured;
879 rc = CFGMR3InsertString(pLunL0, "Driver", "HostDVD"); RC_CHECK();
880 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
881 hrc = hostDvdDrive->COMGETTER(Name)(&str); H();
882 STR_CONV();
883 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
884 STR_FREE();
885 BOOL fPassthrough;
886 hrc = dvdDrive->COMGETTER(Passthrough)(&fPassthrough); H();
887 rc = CFGMR3InsertInteger(pCfg, "Passthrough", !!fPassthrough); RC_CHECK();
888 }
889 else
890 {
891 pConsole->meDVDState = DriveState_NotMounted;
892 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
893 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
894 rc = CFGMR3InsertString(pCfg, "Type", "DVD"); RC_CHECK();
895 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
896
897 ComPtr<IDVDImage2> dvdImage;
898 hrc = dvdDrive->GetImage(dvdImage.asOutParam()); H();
899 if (dvdImage)
900 {
901 pConsole->meDVDState = DriveState_ImageMounted;
902 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
903 rc = CFGMR3InsertString(pLunL1, "Driver", "MediaISO"); RC_CHECK();
904 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
905 hrc = dvdImage->COMGETTER(Location)(&str); H();
906 STR_CONV();
907 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
908 STR_FREE();
909 }
910 }
911 }
912
913 /*
914 * Network adapters
915 */
916 PCFGMNODE pDevPCNet = NULL; /* PCNet-type devices */
917 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDevPCNet); RC_CHECK();
918#ifdef VBOX_WITH_E1000
919 PCFGMNODE pDevE1000 = NULL; /* E1000-type devices */
920 rc = CFGMR3InsertNode(pDevices, "e1000", &pDevE1000); RC_CHECK();
921#endif
922 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ulInstance++)
923 {
924 ComPtr<INetworkAdapter> networkAdapter;
925 hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H();
926 BOOL fEnabled = FALSE;
927 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabled); H();
928 if (!fEnabled)
929 continue;
930
931 /*
932 * The virtual hardware type. Create appropriate device first.
933 */
934 NetworkAdapterType_T adapterType;
935 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H();
936 switch (adapterType)
937 {
938 case NetworkAdapterType_Am79C970A:
939 case NetworkAdapterType_Am79C973:
940 pDev = pDevPCNet;
941 break;
942#ifdef VBOX_WITH_E1000
943 case NetworkAdapterType_I82540EM:
944 case NetworkAdapterType_I82543GC:
945 pDev = pDevE1000;
946 break;
947#endif
948 default:
949 AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'",
950 adapterType, ulInstance));
951 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
952 N_("Invalid network adapter type '%d' for slot '%d'"),
953 adapterType, ulInstance);
954 }
955
956 char szInstance[4]; Assert(ulInstance <= 999);
957 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
958 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
959 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
960 /* the first network card gets the PCI ID 3, the next 3 gets 8..10. */
961 const unsigned iPciDeviceNo = !ulInstance ? 3 : ulInstance - 1 + 8;
962 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", iPciDeviceNo); RC_CHECK();
963 Assert(!afPciDeviceNo[iPciDeviceNo]);
964 afPciDeviceNo[iPciDeviceNo] = true;
965 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
966 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
967#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */
968 if (pDev == pDevPCNet)
969 {
970 rc = CFGMR3InsertInteger(pCfg, "R0Enabled", false); RC_CHECK();
971 }
972#endif
973
974 /*
975 * The virtual hardware type. PCNet supports two types.
976 */
977 switch (adapterType)
978 {
979 case NetworkAdapterType_Am79C970A:
980 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 0); RC_CHECK();
981 break;
982 case NetworkAdapterType_Am79C973:
983 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 1); RC_CHECK();
984 break;
985 case NetworkAdapterType_I82540EM:
986 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 0); RC_CHECK();
987 break;
988 case NetworkAdapterType_I82543GC:
989 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 1); RC_CHECK();
990 break;
991 }
992
993 /*
994 * Get the MAC address and convert it to binary representation
995 */
996 Bstr macAddr;
997 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H();
998 Assert(macAddr);
999 Utf8Str macAddrUtf8 = macAddr;
1000 char *macStr = (char*)macAddrUtf8.raw();
1001 Assert(strlen(macStr) == 12);
1002 RTMAC Mac;
1003 memset(&Mac, 0, sizeof(Mac));
1004 char *pMac = (char*)&Mac;
1005 for (uint32_t i = 0; i < 6; i++)
1006 {
1007 char c1 = *macStr++ - '0';
1008 if (c1 > 9)
1009 c1 -= 7;
1010 char c2 = *macStr++ - '0';
1011 if (c2 > 9)
1012 c2 -= 7;
1013 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
1014 }
1015 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK();
1016
1017 /*
1018 * Check if the cable is supposed to be unplugged
1019 */
1020 BOOL fCableConnected;
1021 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H();
1022 rc = CFGMR3InsertInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0); RC_CHECK();
1023
1024 /*
1025 * Line speed to report from custom drivers
1026 */
1027 ULONG ulLineSpeed;
1028 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H();
1029 rc = CFGMR3InsertInteger(pCfg, "LineSpeed", ulLineSpeed); RC_CHECK();
1030
1031 /*
1032 * Attach the status driver.
1033 */
1034 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1035 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1036 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1037 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapNetworkLeds[ulInstance]); RC_CHECK();
1038
1039 /*
1040 * Enable the packet sniffer if requested.
1041 */
1042 BOOL fSniffer;
1043 hrc = networkAdapter->COMGETTER(TraceEnabled)(&fSniffer); H();
1044 if (fSniffer)
1045 {
1046 /* insert the sniffer filter driver. */
1047 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1048 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK();
1049 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1050 hrc = networkAdapter->COMGETTER(TraceFile)(&str); H();
1051 if (str) /* check convention for indicating default file. */
1052 {
1053 STR_CONV();
1054 rc = CFGMR3InsertString(pCfg, "File", psz); RC_CHECK();
1055 STR_FREE();
1056 }
1057 }
1058
1059 NetworkAttachmentType_T networkAttachment;
1060 hrc = networkAdapter->COMGETTER(AttachmentType)(&networkAttachment); H();
1061 switch (networkAttachment)
1062 {
1063 case NetworkAttachmentType_Null:
1064 break;
1065
1066 case NetworkAttachmentType_NAT:
1067 {
1068 if (fSniffer)
1069 {
1070 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1071 }
1072 else
1073 {
1074 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1075 }
1076 rc = CFGMR3InsertString(pLunL0, "Driver", "NAT"); RC_CHECK();
1077 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1078 /* (Port forwarding goes here.) */
1079
1080 /* Configure TFTP prefix and boot filename. */
1081 hrc = virtualBox->COMGETTER(HomeFolder)(&str); H();
1082 STR_CONV();
1083 if (psz && *psz)
1084 {
1085 char *pszTFTPPrefix = NULL;
1086 RTStrAPrintf(&pszTFTPPrefix, "%s%c%s", psz, RTPATH_DELIMITER, "TFTP");
1087 rc = CFGMR3InsertString(pCfg, "TFTPPrefix", pszTFTPPrefix); RC_CHECK();
1088 RTStrFree(pszTFTPPrefix);
1089 }
1090 STR_FREE();
1091 hrc = pMachine->COMGETTER(Name)(&str); H();
1092 STR_CONV();
1093 char *pszBootFile = NULL;
1094 RTStrAPrintf(&pszBootFile, "%s.pxe", psz);
1095 STR_FREE();
1096 rc = CFGMR3InsertString(pCfg, "BootFile", pszBootFile); RC_CHECK();
1097 RTStrFree(pszBootFile);
1098
1099 hrc = networkAdapter->COMGETTER(NATNetwork)(&str); H();
1100 if (str)
1101 {
1102 STR_CONV();
1103 if (psz && *psz)
1104 rc = CFGMR3InsertString(pCfg, "Network", psz); RC_CHECK();
1105 STR_FREE();
1106 }
1107 break;
1108 }
1109
1110 case NetworkAttachmentType_HostInterface:
1111 {
1112 /*
1113 * Perform the attachment if required (don't return on error!)
1114 */
1115 hrc = pConsole->attachToHostInterface(networkAdapter);
1116 if (SUCCEEDED(hrc))
1117 {
1118#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
1119 Assert ((int)pConsole->maTapFD[ulInstance] >= 0);
1120 if ((int)pConsole->maTapFD[ulInstance] >= 0)
1121 {
1122 if (fSniffer)
1123 {
1124 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1125 }
1126 else
1127 {
1128 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1129 }
1130 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
1131 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1132# if defined(RT_OS_SOLARIS)
1133 /* Device name/number is required for Solaris as we need it for TAP PPA. */
1134 Bstr tapDeviceName;
1135 networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam());
1136 if (!tapDeviceName.isEmpty())
1137 rc = CFGMR3InsertString(pCfg, "Device", Utf8Str(tapDeviceName)); RC_CHECK();
1138
1139 /* TAP setup application/script */
1140 Bstr tapSetupApp;
1141 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApp.asOutParam());
1142 if (!tapSetupApp.isEmpty())
1143 rc = CFGMR3InsertString(pCfg, "TAPSetupApplication", Utf8Str(tapSetupApp)); RC_CHECK();
1144
1145 /* TAP terminate application/script */
1146 Bstr tapTerminateApp;
1147 networkAdapter->COMGETTER(TAPTerminateApplication)(tapTerminateApp.asOutParam());
1148 if (!tapTerminateApp.isEmpty())
1149 rc = CFGMR3InsertString(pCfg, "TAPTerminateApplication", Utf8Str(tapTerminateApp)); RC_CHECK();
1150
1151 /* "FileHandle" must NOT be inserted here, it is done in DrvTAP.cpp */
1152
1153# ifdef VBOX_WITH_CROSSBOW
1154 /* Crossbow: needs the MAC address for setting up TAP. */
1155 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK();
1156# endif
1157# else
1158 rc = CFGMR3InsertInteger(pCfg, "FileHandle", pConsole->maTapFD[ulInstance]); RC_CHECK();
1159# endif
1160 }
1161
1162#elif defined(VBOX_WITH_NETFLT)
1163 /*
1164 * This is the new VBoxNetFlt+IntNet stuff.
1165 */
1166 if (fSniffer)
1167 {
1168 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1169 }
1170 else
1171 {
1172 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1173 }
1174
1175 Bstr HifName;
1176 hrc = networkAdapter->COMGETTER(HostInterface)(HifName.asOutParam());
1177 if(FAILED(hrc))
1178 {
1179 LogRel(("NetworkAttachmentType_HostInterface: COMGETTER(HostInterface) failed, hrc (0x%x)", hrc));
1180 H();
1181 }
1182
1183 Utf8Str HifNameUtf8(HifName);
1184 const char *pszHifName = HifNameUtf8.raw();
1185
1186# if defined(RT_OS_DARWIN)
1187 /* The name is on the form 'ifX: long name', chop it off at the colon. */
1188 char szTrunk[8];
1189 strncpy(szTrunk, pszHifName, sizeof(szTrunk));
1190 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
1191 if (!pszColon)
1192 {
1193 hrc = networkAdapter->Detach(); H();
1194 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
1195 N_("Malformed host interface networking name '%ls'"),
1196 HifName.raw());
1197 }
1198 *pszColon = '\0';
1199 const char *pszTrunk = szTrunk;
1200
1201# elif defined(RT_OS_SOLARIS)
1202 /* The name is on the form format 'ifX[:1] - long name, chop it off at space. */
1203 char szTrunk[256];
1204 strlcpy(szTrunk, pszHifName, sizeof(szTrunk));
1205 char *pszSpace = (char *)memchr(szTrunk, ' ', sizeof(szTrunk));
1206
1207 /*
1208 * Currently don't bother about malformed names here for the sake of people using
1209 * VBoxManage and setting only the NIC name from there. If there is a space we
1210 * chop it off and proceed, otherwise just use whatever we've got.
1211 */
1212 if (pszSpace)
1213 *pszSpace = '\0';
1214
1215 /* Chop it off at the colon (zone naming eg: e1000g:1 we need only the e1000g) */
1216 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
1217 if (pszColon)
1218 *pszColon = '\0';
1219
1220 const char *pszTrunk = szTrunk;
1221
1222# elif defined(RT_OS_WINDOWS)
1223 ComPtr<IHostNetworkInterfaceCollection> coll;
1224 hrc = host->COMGETTER(NetworkInterfaces)(coll.asOutParam());
1225 if(FAILED(hrc))
1226 {
1227 LogRel(("NetworkAttachmentType_HostInterface: COMGETTER(NetworkInterfaces) failed, hrc (0x%x)", hrc));
1228 H();
1229 }
1230 ComPtr<IHostNetworkInterface> hostInterface;
1231 rc = coll->FindByName(HifName, hostInterface.asOutParam());
1232 if (!SUCCEEDED(rc))
1233 {
1234 AssertBreakpoint();
1235 LogRel(("NetworkAttachmentType_HostInterface: FindByName failed, rc (0x%x)", rc));
1236 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
1237 N_("Inexistent host networking interface, name '%ls'"),
1238 HifName.raw());
1239 }
1240
1241 Guid hostIFGuid;
1242 hrc = hostInterface->COMGETTER(Id)(hostIFGuid.asOutParam());
1243 if(FAILED(hrc))
1244 {
1245 LogRel(("NetworkAttachmentType_HostInterface: COMGETTER(Id) failed, hrc (0x%x)", hrc));
1246 H();
1247 }
1248 char szDriverGUID[RTUUID_STR_LENGTH];
1249 strcpy(szDriverGUID , hostIFGuid.toString().raw());
1250 const char *pszTrunk = szDriverGUID;
1251# elif defined(RT_OS_LINUX)
1252 /* @todo Check for malformed names. */
1253 const char *pszTrunk = pszHifName;
1254
1255# else
1256# error "PORTME (VBOX_WITH_NETFLT)"
1257# endif
1258
1259 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
1260 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1261 rc = CFGMR3InsertString(pCfg, "Trunk", pszTrunk); RC_CHECK();
1262 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); RC_CHECK();
1263 char szNetwork[80];
1264 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName);
1265 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();
1266
1267# if defined(RT_OS_DARWIN)
1268 /** @todo Come up with a better deal here. Problem is that IHostNetworkInterface is completely useless here. */
1269 if ( strstr(pszHifName, "Wireless")
1270 || strstr(pszHifName, "AirPort" ))
1271 {
1272 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK();
1273 }
1274# elif defined(RT_OS_LINUX)
1275 int iSock = socket(AF_INET, SOCK_DGRAM, 0);
1276 if (iSock >= 0)
1277 {
1278 struct iwreq WRq;
1279
1280 memset(&WRq, 0, sizeof(WRq));
1281 strncpy(WRq.ifr_name, pszHifName, IFNAMSIZ);
1282 if (ioctl(iSock, SIOCGIWNAME, &WRq) >= 0)
1283 {
1284 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK();
1285 Log(("Set SharedMacOnWire\n"));
1286 }
1287 else
1288 {
1289 Log(("Failed to get wireless name\n"));
1290 }
1291 close(iSock);
1292 }
1293 else
1294 {
1295 Log(("Failed to open wireless socket\n"));
1296 }
1297# elif defined(RT_OS_WINDOWS)
1298# define DEVNAME_PREFIX L"\\\\.\\"
1299 INetCfg *pNc;
1300 LPWSTR lpszApp;
1301 HRESULT hr;
1302 int rc = VERR_INTNET_FLT_IF_NOT_FOUND;
1303
1304 /* we are getting the medium type via IOCTL_NDIS_QUERY_GLOBAL_STATS Io Control
1305 * there is a pretty long way till there though since we need to obtain the symbolic link name
1306 * for the adapter device we are going to query given the device Guid */
1307 hr = VBoxNetCfgWinQueryINetCfg( FALSE,
1308 L"VirtualBox",
1309 &pNc,
1310 &lpszApp );
1311 Assert(hr == S_OK);
1312 if(hr == S_OK)
1313 {
1314 /* get the adapter's INetCfgComponent*/
1315 INetCfgComponent *pAdaptorComponent;
1316 hr = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), &pAdaptorComponent);
1317 Assert(hr == S_OK);
1318 if(hr == S_OK)
1319 {
1320 /* now get the bind name */
1321 LPWSTR pName;
1322 hr = pAdaptorComponent->GetBindName(&pName);
1323 Assert(hr == S_OK);
1324 if(hr == S_OK)
1325 {
1326 /* prepend the "\\\\.\\" to the bind name to obtain the link name */
1327 wchar_t FileName[MAX_PATH];
1328 wcscpy(FileName, DEVNAME_PREFIX);
1329 wcscpy((wchar_t*)(((char*)FileName) + sizeof(DEVNAME_PREFIX) - sizeof(FileName[0])), pName);
1330
1331 /* open the device */
1332 HANDLE hDevice = CreateFile(FileName,
1333 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
1334 NULL,
1335 OPEN_EXISTING,
1336 FILE_ATTRIBUTE_NORMAL,
1337 NULL);
1338 if (hDevice != INVALID_HANDLE_VALUE)
1339 {
1340 /* now issue the OID_GEN_PHYSICAL_MEDIUM query */
1341 DWORD Oid = OID_GEN_PHYSICAL_MEDIUM;
1342 NDIS_PHYSICAL_MEDIUM PhMedium;
1343 DWORD cbResult;
1344 if (DeviceIoControl(hDevice, IOCTL_NDIS_QUERY_GLOBAL_STATS, &Oid, sizeof(Oid), &PhMedium, sizeof(PhMedium), &cbResult, NULL))
1345 {
1346 /* that was simple, now examine PhMedium */
1347 if(PhMedium == NdisPhysicalMediumWirelessWan
1348 || PhMedium == NdisPhysicalMediumWirelessLan
1349 || PhMedium == NdisPhysicalMediumNative802_11
1350 || PhMedium == NdisPhysicalMediumBluetooth
1351 /*|| PhMedium == NdisPhysicalMediumWiMax*/
1352 )
1353 {
1354 Log(("this is a wireles adapter"));
1355 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK();
1356 Log(("Set SharedMacOnWire\n"));
1357 }
1358 else
1359 {
1360 Log(("this is NOT a wireles adapter"));
1361 }
1362 }
1363 else
1364 {
1365 int winEr = GetLastError();
1366 LogRel(("Console::configConstructor: DeviceIoControl failed, err (0x%x), ignoring\n", winEr));
1367 AssertBreakpoint();
1368 }
1369
1370 CloseHandle(hDevice);
1371 }
1372 else
1373 {
1374 int winEr = GetLastError();
1375 LogRel(("Console::configConstructor: CreateFile failed, err (0x%x), ignoring\n", winEr));
1376 AssertBreakpoint();
1377 }
1378 CoTaskMemFree(pName);
1379 }
1380 VBoxNetCfgWinReleaseRef(pAdaptorComponent);
1381 }
1382 VBoxNetCfgWinReleaseINetCfg( pNc, FALSE );
1383 }
1384# else
1385 /** @todo PORTME: wireless detection */
1386# endif
1387
1388# if defined(RT_OS_SOLARIS)
1389# if 0 /* bird: this is a bit questionable and might cause more trouble than its worth. */
1390 /* Zone access restriction, don't allow snopping the global zone. */
1391 zoneid_t ZoneId = getzoneid();
1392 if (ZoneId != GLOBAL_ZONEID)
1393 {
1394 rc = CFGMR3InsertInteger(pCfg, "IgnoreAllPromisc", true); RC_CHECK();
1395 }
1396# endif
1397# endif
1398
1399#elif defined(RT_OS_WINDOWS)
1400 if (fSniffer)
1401 {
1402 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1403 }
1404 else
1405 {
1406 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1407 }
1408 Bstr hostInterfaceName;
1409 hrc = networkAdapter->COMGETTER(HostInterface)(hostInterfaceName.asOutParam()); H();
1410 ComPtr<IHostNetworkInterfaceCollection> coll;
1411 hrc = host->COMGETTER(NetworkInterfaces)(coll.asOutParam()); H();
1412 ComPtr<IHostNetworkInterface> hostInterface;
1413 rc = coll->FindByName(hostInterfaceName, hostInterface.asOutParam());
1414 if (!SUCCEEDED(rc))
1415 {
1416 AssertMsgFailed(("Cannot get GUID for host interface '%ls'\n", hostInterfaceName));
1417 hrc = networkAdapter->Detach(); H();
1418 }
1419 else
1420 {
1421# ifndef VBOX_WITH_NETFLT
1422 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
1423 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1424 rc = CFGMR3InsertString(pCfg, "HostInterfaceName", Utf8Str(hostInterfaceName)); RC_CHECK();
1425# else
1426 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
1427 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1428 rc = CFGMR3InsertString(pCfg, "Trunk", Utf8Str(hostInterfaceName)); RC_CHECK();
1429 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); RC_CHECK();
1430# endif
1431 Guid hostIFGuid;
1432 hrc = hostInterface->COMGETTER(Id)(hostIFGuid.asOutParam()); H();
1433 char szDriverGUID[256] = {0};
1434 /* add curly brackets */
1435 szDriverGUID[0] = '{';
1436 strcpy(szDriverGUID + 1, hostIFGuid.toString().raw());
1437 strcat(szDriverGUID, "}");
1438 rc = CFGMR3InsertBytes(pCfg, "GUID", szDriverGUID, sizeof(szDriverGUID)); RC_CHECK();
1439 }
1440#elif defined(RT_OS_LINUX)
1441/// @todo aleksey: is there anything to be done here?
1442#else
1443# error "Port me"
1444#endif
1445 }
1446 else
1447 {
1448 switch (hrc)
1449 {
1450#ifdef RT_OS_LINUX
1451 case VERR_ACCESS_DENIED:
1452 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
1453 "Failed to open '/dev/net/tun' for read/write access. Please check the "
1454 "permissions of that node. Either run 'chmod 0666 /dev/net/tun' or "
1455 "change the group of that node and make yourself a member of that group. Make "
1456 "sure that these changes are permanent, especially if you are "
1457 "using udev"));
1458#endif /* RT_OS_LINUX */
1459 default:
1460 AssertMsgFailed(("Could not attach to host interface! Bad!\n"));
1461 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
1462 "Failed to initialize Host Interface Networking"));
1463 }
1464 }
1465 break;
1466 }
1467
1468 case NetworkAttachmentType_Internal:
1469 {
1470 hrc = networkAdapter->COMGETTER(InternalNetwork)(&str); H();
1471 if (str)
1472 {
1473 STR_CONV();
1474 if (psz && *psz)
1475 {
1476 if (fSniffer)
1477 {
1478 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1479 }
1480 else
1481 {
1482 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1483 }
1484 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
1485 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1486 rc = CFGMR3InsertString(pCfg, "Network", psz); RC_CHECK();
1487 }
1488 STR_FREE();
1489 }
1490 break;
1491 }
1492
1493 default:
1494 AssertMsgFailed(("should not get here!\n"));
1495 break;
1496 }
1497 }
1498
1499 /*
1500 * Serial (UART) Ports
1501 */
1502 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); RC_CHECK();
1503 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ulInstance++)
1504 {
1505 ComPtr<ISerialPort> serialPort;
1506 hrc = pMachine->GetSerialPort (ulInstance, serialPort.asOutParam()); H();
1507 BOOL fEnabled = FALSE;
1508 if (serialPort)
1509 hrc = serialPort->COMGETTER(Enabled)(&fEnabled); H();
1510 if (!fEnabled)
1511 continue;
1512
1513 char szInstance[4]; Assert(ulInstance <= 999);
1514 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1515
1516 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
1517 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1518
1519 ULONG ulIRQ, ulIOBase;
1520 PortMode_T HostMode;
1521 Bstr path;
1522 BOOL fServer;
1523 hrc = serialPort->COMGETTER(HostMode)(&HostMode); H();
1524 hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H();
1525 hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H();
1526 hrc = serialPort->COMGETTER(Path)(path.asOutParam()); H();
1527 hrc = serialPort->COMGETTER(Server)(&fServer); H();
1528 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1529 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1530 if (HostMode != PortMode_Disconnected)
1531 {
1532 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1533 if (HostMode == PortMode_HostPipe)
1534 {
1535 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK();
1536 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1537 rc = CFGMR3InsertString(pLunL1, "Driver", "NamedPipe"); RC_CHECK();
1538 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK();
1539 rc = CFGMR3InsertString(pLunL2, "Location", Utf8Str(path)); RC_CHECK();
1540 rc = CFGMR3InsertInteger(pLunL2, "IsServer", fServer); RC_CHECK();
1541 }
1542 else if (HostMode == PortMode_HostDevice)
1543 {
1544 rc = CFGMR3InsertString(pLunL0, "Driver", "Host Serial"); RC_CHECK();
1545 rc = CFGMR3InsertNode(pLunL0, "Config", &pLunL1); RC_CHECK();
1546 rc = CFGMR3InsertString(pLunL1, "DevicePath", Utf8Str(path)); RC_CHECK();
1547 }
1548 }
1549 }
1550
1551 /*
1552 * Parallel (LPT) Ports
1553 */
1554 rc = CFGMR3InsertNode(pDevices, "parallel", &pDev); RC_CHECK();
1555 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ulInstance++)
1556 {
1557 ComPtr<IParallelPort> parallelPort;
1558 hrc = pMachine->GetParallelPort (ulInstance, parallelPort.asOutParam()); H();
1559 BOOL fEnabled = FALSE;
1560 if (parallelPort)
1561 hrc = parallelPort->COMGETTER(Enabled)(&fEnabled); H();
1562 if (!fEnabled)
1563 continue;
1564
1565 char szInstance[4]; Assert(ulInstance <= 999);
1566 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1567
1568 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
1569 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1570
1571 ULONG ulIRQ, ulIOBase;
1572 Bstr DevicePath;
1573 hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ); H();
1574 hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase); H();
1575 hrc = parallelPort->COMGETTER(Path)(DevicePath.asOutParam()); H();
1576 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1577 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1578 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1579 rc = CFGMR3InsertString(pLunL0, "Driver", "HostParallel"); RC_CHECK();
1580 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1581 rc = CFGMR3InsertString(pLunL1, "DevicePath", Utf8Str(DevicePath)); RC_CHECK();
1582 }
1583
1584 /*
1585 * VMM Device
1586 */
1587 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); RC_CHECK();
1588 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1589 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1590 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1591 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); RC_CHECK();
1592 Assert(!afPciDeviceNo[4]);
1593 afPciDeviceNo[4] = true;
1594 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1595
1596 /* the VMM device's Main driver */
1597 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1598 rc = CFGMR3InsertString(pLunL0, "Driver", "MainVMMDev"); RC_CHECK();
1599 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1600 VMMDev *pVMMDev = pConsole->mVMMDev;
1601 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pVMMDev); RC_CHECK();
1602
1603 /*
1604 * Attach the status driver.
1605 */
1606 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1607 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1608 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1609 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSharedFolderLed); RC_CHECK();
1610 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1611 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1612
1613 /*
1614 * Audio Sniffer Device
1615 */
1616 rc = CFGMR3InsertNode(pDevices, "AudioSniffer", &pDev); RC_CHECK();
1617 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1618 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1619
1620 /* the Audio Sniffer device's Main driver */
1621 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1622 rc = CFGMR3InsertString(pLunL0, "Driver", "MainAudioSniffer"); RC_CHECK();
1623 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1624 AudioSniffer *pAudioSniffer = pConsole->mAudioSniffer;
1625 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); RC_CHECK();
1626
1627 /*
1628 * AC'97 ICH / SoundBlaster16 audio
1629 */
1630 ComPtr<IAudioAdapter> audioAdapter;
1631 hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H();
1632 if (audioAdapter)
1633 hrc = audioAdapter->COMGETTER(Enabled)(&enabled); H();
1634
1635 if (enabled)
1636 {
1637 AudioControllerType_T audioController;
1638 hrc = audioAdapter->COMGETTER(AudioController)(&audioController); H();
1639 switch (audioController)
1640 {
1641 case AudioControllerType_AC97:
1642 {
1643 /* default: ICH AC97 */
1644 rc = CFGMR3InsertNode(pDevices, "ichac97", &pDev); RC_CHECK();
1645 rc = CFGMR3InsertNode(pDev, "0", &pInst);
1646 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK();
1647 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 5); RC_CHECK();
1648 Assert(!afPciDeviceNo[5]);
1649 afPciDeviceNo[5] = true;
1650 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1651 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1652 break;
1653 }
1654 case AudioControllerType_SB16:
1655 {
1656 /* legacy SoundBlaster16 */
1657 rc = CFGMR3InsertNode(pDevices, "sb16", &pDev); RC_CHECK();
1658 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1659 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK();
1660 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1661 rc = CFGMR3InsertInteger(pCfg, "IRQ", 5); RC_CHECK();
1662 rc = CFGMR3InsertInteger(pCfg, "DMA", 1); RC_CHECK();
1663 rc = CFGMR3InsertInteger(pCfg, "DMA16", 5); RC_CHECK();
1664 rc = CFGMR3InsertInteger(pCfg, "Port", 0x220); RC_CHECK();
1665 rc = CFGMR3InsertInteger(pCfg, "Version", 0x0405); RC_CHECK();
1666 break;
1667 }
1668 }
1669
1670 /* the Audio driver */
1671 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1672 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
1673 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1674
1675 AudioDriverType_T audioDriver;
1676 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H();
1677 switch (audioDriver)
1678 {
1679 case AudioDriverType_Null:
1680 {
1681 rc = CFGMR3InsertString(pCfg, "AudioDriver", "null"); RC_CHECK();
1682 break;
1683 }
1684#ifdef RT_OS_WINDOWS
1685#ifdef VBOX_WITH_WINMM
1686 case AudioDriverType_WinMM:
1687 {
1688 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); RC_CHECK();
1689 break;
1690 }
1691#endif
1692 case AudioDriverType_DirectSound:
1693 {
1694 rc = CFGMR3InsertString(pCfg, "AudioDriver", "dsound"); RC_CHECK();
1695 break;
1696 }
1697#endif /* RT_OS_WINDOWS */
1698#ifdef RT_OS_SOLARIS
1699 case AudioDriverType_SolAudio:
1700 {
1701 rc = CFGMR3InsertString(pCfg, "AudioDriver", "solaudio"); RC_CHECK();
1702 break;
1703 }
1704#endif
1705#ifdef RT_OS_LINUX
1706 case AudioDriverType_OSS:
1707 {
1708 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); RC_CHECK();
1709 break;
1710 }
1711# ifdef VBOX_WITH_ALSA
1712 case AudioDriverType_ALSA:
1713 {
1714 rc = CFGMR3InsertString(pCfg, "AudioDriver", "alsa"); RC_CHECK();
1715 break;
1716 }
1717# endif
1718# ifdef VBOX_WITH_PULSE
1719 case AudioDriverType_Pulse:
1720 {
1721 rc = CFGMR3InsertString(pCfg, "AudioDriver", "pulse"); RC_CHECK();
1722 break;
1723 }
1724# endif
1725#endif /* RT_OS_LINUX */
1726#ifdef RT_OS_DARWIN
1727 case AudioDriverType_CoreAudio:
1728 {
1729 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); RC_CHECK();
1730 break;
1731 }
1732#endif
1733 }
1734 hrc = pMachine->COMGETTER(Name)(&str); H();
1735 STR_CONV();
1736 rc = CFGMR3InsertString(pCfg, "StreamName", psz); RC_CHECK();
1737 STR_FREE();
1738 }
1739
1740 /*
1741 * The USB Controller.
1742 */
1743 ComPtr<IUSBController> USBCtlPtr;
1744 hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam());
1745 if (USBCtlPtr)
1746 {
1747 BOOL fEnabled;
1748 hrc = USBCtlPtr->COMGETTER(Enabled)(&fEnabled); H();
1749 if (fEnabled)
1750 {
1751 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); RC_CHECK();
1752 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1753 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1754 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1755 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); RC_CHECK();
1756 Assert(!afPciDeviceNo[6]);
1757 afPciDeviceNo[6] = true;
1758 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1759
1760 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1761 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1762 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1763
1764 /*
1765 * Attach the status driver.
1766 */
1767 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1768 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1769 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1770 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[0]);RC_CHECK();
1771 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1772 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1773
1774#ifdef VBOX_WITH_EHCI
1775 hrc = USBCtlPtr->COMGETTER(EnabledEhci)(&fEnabled); H();
1776 if (fEnabled)
1777 {
1778 rc = CFGMR3InsertNode(pDevices, "usb-ehci", &pDev); RC_CHECK();
1779 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1780 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1781 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK();
1782 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 11); RC_CHECK();
1783 Assert(!afPciDeviceNo[11]);
1784 afPciDeviceNo[11] = true;
1785 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1786
1787 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1788 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1789 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1790
1791 /*
1792 * Attach the status driver.
1793 */
1794 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1795 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1796 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1797 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[1]);RC_CHECK();
1798 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1799 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1800 }
1801 else
1802#endif
1803 {
1804 /*
1805 * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
1806 * on a per device level now.
1807 */
1808 rc = CFGMR3InsertNode(pRoot, "USB", &pCfg); RC_CHECK();
1809 rc = CFGMR3InsertNode(pCfg, "USBProxy", &pCfg); RC_CHECK();
1810 rc = CFGMR3InsertNode(pCfg, "GlobalConfig", &pCfg); RC_CHECK();
1811 // This globally enables the 2.0 -> 1.1 device morphing of proxied devies to keep windows quiet.
1812 //rc = CFGMR3InsertInteger(pCfg, "Force11Device", true); RC_CHECK();
1813 // The following breaks stuff, but it makes MSDs work in vista. (I include it here so
1814 // that it's documented somewhere.) Users needing it can use:
1815 // VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
1816 //rc = CFGMR3InsertInteger(pCfg, "Force11PacketSize", true); RC_CHECK();
1817 }
1818 }
1819 }
1820
1821 /*
1822 * Clipboard
1823 */
1824 {
1825 ClipboardMode_T mode = ClipboardMode_Disabled;
1826 hrc = pMachine->COMGETTER(ClipboardMode) (&mode); H();
1827
1828 if (mode != ClipboardMode_Disabled)
1829 {
1830 /* Load the service */
1831 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedClipboard", "VBoxSharedClipboard");
1832
1833 if (RT_FAILURE (rc))
1834 {
1835 LogRel(("VBoxSharedClipboard is not available. rc = %Rrc\n", rc));
1836 /* That is not a fatal failure. */
1837 rc = VINF_SUCCESS;
1838 }
1839 else
1840 {
1841 /* Setup the service. */
1842 VBOXHGCMSVCPARM parm;
1843
1844 parm.type = VBOX_HGCM_SVC_PARM_32BIT;
1845
1846 switch (mode)
1847 {
1848 default:
1849 case ClipboardMode_Disabled:
1850 {
1851 LogRel(("VBoxSharedClipboard mode: Off\n"));
1852 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
1853 break;
1854 }
1855 case ClipboardMode_GuestToHost:
1856 {
1857 LogRel(("VBoxSharedClipboard mode: Guest to Host\n"));
1858 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
1859 break;
1860 }
1861 case ClipboardMode_HostToGuest:
1862 {
1863 LogRel(("VBoxSharedClipboard mode: Host to Guest\n"));
1864 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
1865 break;
1866 }
1867 case ClipboardMode_Bidirectional:
1868 {
1869 LogRel(("VBoxSharedClipboard mode: Bidirectional\n"));
1870 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
1871 break;
1872 }
1873 }
1874
1875 pConsole->mVMMDev->hgcmHostCall ("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
1876
1877 Log(("Set VBoxSharedClipboard mode\n"));
1878 }
1879 }
1880 }
1881
1882#ifdef VBOX_WITH_CROGL
1883 /*
1884 * crOpenGL
1885 */
1886 {
1887 BOOL fEnabled = false;
1888 hrc = pMachine->COMGETTER(Accelerate3DEnabled) (&fEnabled); H();
1889
1890 if (fEnabled)
1891 {
1892 /* Load the service */
1893 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedCrOpenGL", "VBoxSharedCrOpenGL");
1894 if (RT_FAILURE(rc))
1895 {
1896 LogRel(("Failed to load Shared OpenGL service %Rrc\n", rc));
1897 /* That is not a fatal failure. */
1898 rc = VINF_SUCCESS;
1899 }
1900 else
1901 {
1902 LogRel(("Shared crOpenGL service loaded.\n"));
1903
1904 /* Setup the service. */
1905 VBOXHGCMSVCPARM parm;
1906 parm.type = VBOX_HGCM_SVC_PARM_PTR;
1907
1908 //parm.u.pointer.addr = static_cast <IConsole *> (pData->pVMMDev->getParent());
1909 parm.u.pointer.addr = pConsole->mVMMDev->getParent()->getDisplay()->getFramebuffer();
1910 parm.u.pointer.size = sizeof(IFramebuffer *);
1911
1912 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_FRAMEBUFFER, 1, &parm);
1913 if (!RT_SUCCESS(rc))
1914 AssertMsgFailed(("SHCRGL_HOST_FN_SET_FRAMEBUFFER failed with %Rrc\n", rc));
1915 }
1916 }
1917 }
1918#endif
1919
1920#ifdef VBOX_WITH_GUEST_PROPS
1921 /*
1922 * Guest property service
1923 */
1924 {
1925 /* Load the service */
1926 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxGuestPropSvc", "VBoxGuestPropSvc");
1927
1928 if (RT_FAILURE (rc))
1929 {
1930 LogRel(("VBoxGuestPropSvc is not available. rc = %Rrc\n", rc));
1931 /* That is not a fatal failure. */
1932 rc = VINF_SUCCESS;
1933 }
1934 else
1935 {
1936 /* Pull over the properties from the server. */
1937 SafeArray <BSTR> namesOut;
1938 SafeArray <BSTR> valuesOut;
1939 SafeArray <ULONG64> timestampsOut;
1940 SafeArray <BSTR> flagsOut;
1941 hrc = pConsole->mControl->PullGuestProperties(ComSafeArrayAsOutParam(namesOut),
1942 ComSafeArrayAsOutParam(valuesOut),
1943 ComSafeArrayAsOutParam(timestampsOut),
1944 ComSafeArrayAsOutParam(flagsOut)); H();
1945 size_t cProps = namesOut.size();
1946 if ( valuesOut.size() != cProps
1947 || timestampsOut.size() != cProps
1948 || flagsOut.size() != cProps
1949 )
1950 rc = VERR_INVALID_PARAMETER;
1951
1952 std::vector <Utf8Str> utf8Names, utf8Values, utf8Flags;
1953 std::vector <char *> names, values, flags;
1954 std::vector <ULONG64> timestamps;
1955 for (unsigned i = 0; i < cProps && RT_SUCCESS(rc); ++i)
1956 if ( !VALID_PTR(namesOut[i])
1957 || !VALID_PTR(valuesOut[i])
1958 || !VALID_PTR(flagsOut[i])
1959 )
1960 rc = VERR_INVALID_POINTER;
1961 for (unsigned i = 0; i < cProps && RT_SUCCESS(rc); ++i)
1962 {
1963 utf8Names.push_back(Bstr(namesOut[i]));
1964 utf8Values.push_back(Bstr(valuesOut[i]));
1965 timestamps.push_back(timestampsOut[i]);
1966 utf8Flags.push_back(Bstr(flagsOut[i]));
1967 if ( utf8Names.back().isNull()
1968 || utf8Values.back().isNull()
1969 || utf8Flags.back().isNull()
1970 )
1971 throw std::bad_alloc();
1972 }
1973 for (unsigned i = 0; i < cProps && RT_SUCCESS(rc); ++i)
1974 {
1975 names.push_back(utf8Names[i].mutableRaw());
1976 values.push_back(utf8Values[i].mutableRaw());
1977 flags.push_back(utf8Flags[i].mutableRaw());
1978 }
1979 names.push_back(NULL);
1980 values.push_back(NULL);
1981 timestamps.push_back(0);
1982 flags.push_back(NULL);
1983
1984 /* Setup the service. */
1985 VBOXHGCMSVCPARM parms[4];
1986
1987 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
1988 parms[0].u.pointer.addr = &names.front();
1989 parms[0].u.pointer.size = 0; /* We don't actually care. */
1990 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
1991 parms[1].u.pointer.addr = &values.front();
1992 parms[1].u.pointer.size = 0; /* We don't actually care. */
1993 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
1994 parms[2].u.pointer.addr = &timestamps.front();
1995 parms[2].u.pointer.size = 0; /* We don't actually care. */
1996 parms[3].type = VBOX_HGCM_SVC_PARM_PTR;
1997 parms[3].u.pointer.addr = &flags.front();
1998 parms[3].u.pointer.size = 0; /* We don't actually care. */
1999
2000 pConsole->mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", guestProp::SET_PROPS_HOST, 4, &parms[0]);
2001
2002 /* Register the host notification callback */
2003 HGCMSVCEXTHANDLE hDummy;
2004 HGCMHostRegisterServiceExtension (&hDummy, "VBoxGuestPropSvc",
2005 Console::doGuestPropNotification,
2006 pvConsole);
2007
2008 Log(("Set VBoxGuestPropSvc property store\n"));
2009 }
2010 }
2011#endif /* VBOX_WITH_GUEST_PROPS defined */
2012
2013 /*
2014 * CFGM overlay handling.
2015 *
2016 * Here we check the extra data entries for CFGM values
2017 * and create the nodes and insert the values on the fly. Existing
2018 * values will be removed and reinserted. CFGM is typed, so by default
2019 * we will guess whether it's a string or an integer (byte arrays are
2020 * not currently supported). It's possible to override this autodetection
2021 * by adding "string:", "integer:" or "bytes:" (future).
2022 *
2023 * We first perform a run on global extra data, then on the machine
2024 * extra data to support global settings with local overrides.
2025 *
2026 */
2027 /** @todo add support for removing nodes and byte blobs. */
2028 Bstr strExtraDataKey;
2029 bool fGlobalExtraData = true;
2030 for (;;)
2031 {
2032 /*
2033 * Get the next key
2034 */
2035 Bstr strNextExtraDataKey;
2036 Bstr strExtraDataValue;
2037 if (fGlobalExtraData)
2038 hrc = virtualBox->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
2039 strExtraDataValue.asOutParam());
2040 else
2041 hrc = pMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
2042 strExtraDataValue.asOutParam());
2043
2044 /* stop if for some reason there's nothing more to request */
2045 if (FAILED(hrc) || !strNextExtraDataKey)
2046 {
2047 /* if we're out of global keys, continue with machine, otherwise we're done */
2048 if (fGlobalExtraData)
2049 {
2050 fGlobalExtraData = false;
2051 strExtraDataKey.setNull();
2052 continue;
2053 }
2054 break;
2055 }
2056 strExtraDataKey = strNextExtraDataKey;
2057
2058 /*
2059 * We only care about keys starting with "VBoxInternal/"
2060 */
2061 Utf8Str strExtraDataKeyUtf8(strExtraDataKey);
2062 char *pszExtraDataKey = (char *)strExtraDataKeyUtf8.raw();
2063 if (strncmp(pszExtraDataKey, "VBoxInternal/", sizeof("VBoxInternal/") - 1) != 0)
2064 continue;
2065 pszExtraDataKey += sizeof("VBoxInternal/") - 1;
2066
2067 /*
2068 * The key will be in the format "Node1/Node2/Value" or simply "Value".
2069 * Split the two and get the node, delete the value and create the node
2070 * if necessary.
2071 */
2072 PCFGMNODE pNode;
2073 char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
2074 if (pszCFGMValueName)
2075 {
2076 /* terminate the node and advance to the value (Utf8Str might not
2077 offically like this but wtf) */
2078 *pszCFGMValueName = '\0';
2079 pszCFGMValueName++;
2080
2081 /* does the node already exist? */
2082 pNode = CFGMR3GetChild(pRoot, pszExtraDataKey);
2083 if (pNode)
2084 CFGMR3RemoveValue(pNode, pszCFGMValueName);
2085 else
2086 {
2087 /* create the node */
2088 rc = CFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode);
2089 if (RT_FAILURE(rc))
2090 {
2091 AssertLogRelMsgRC(rc, ("failed to insert node '%s'\n", pszExtraDataKey));
2092 continue;
2093 }
2094 Assert(pNode);
2095 }
2096 }
2097 else
2098 {
2099 /* root value (no node path). */
2100 pNode = pRoot;
2101 pszCFGMValueName = pszExtraDataKey;
2102 pszExtraDataKey--;
2103 CFGMR3RemoveValue(pNode, pszCFGMValueName);
2104 }
2105
2106 /*
2107 * Now let's have a look at the value.
2108 * Empty strings means that we should remove the value, which we've
2109 * already done above.
2110 */
2111 Utf8Str strCFGMValueUtf8(strExtraDataValue);
2112 const char *pszCFGMValue = strCFGMValueUtf8.raw();
2113 if ( pszCFGMValue
2114 && *pszCFGMValue)
2115 {
2116 uint64_t u64Value;
2117
2118 /* check for type prefix first. */
2119 if (!strncmp(pszCFGMValue, "string:", sizeof("string:") - 1))
2120 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue + sizeof("string:") - 1);
2121 else if (!strncmp(pszCFGMValue, "integer:", sizeof("integer:") - 1))
2122 {
2123 rc = RTStrToUInt64Full(pszCFGMValue + sizeof("integer:") - 1, 0, &u64Value);
2124 if (RT_SUCCESS(rc))
2125 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
2126 }
2127 else if (!strncmp(pszCFGMValue, "bytes:", sizeof("bytes:") - 1))
2128 rc = VERR_NOT_IMPLEMENTED;
2129 /* auto detect type. */
2130 else if (RT_SUCCESS(RTStrToUInt64Full(pszCFGMValue, 0, &u64Value)))
2131 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
2132 else
2133 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue);
2134 AssertLogRelMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszExtraDataKey));
2135 }
2136 }
2137
2138#undef H
2139#undef RC_CHECK
2140#undef STR_FREE
2141#undef STR_CONV
2142
2143 /* Register VM state change handler */
2144 int rc2 = VMR3AtStateRegister (pVM, Console::vmstateChangeCallback, pConsole);
2145 AssertRC (rc2);
2146 if (RT_SUCCESS (rc))
2147 rc = rc2;
2148
2149 /* Register VM runtime error handler */
2150 rc2 = VMR3AtRuntimeErrorRegister (pVM, Console::setVMRuntimeErrorCallback, pConsole);
2151 AssertRC (rc2);
2152 if (RT_SUCCESS (rc))
2153 rc = rc2;
2154
2155 /* Save the VM pointer in the machine object */
2156 pConsole->mpVM = pVM;
2157
2158 LogFlowFunc (("vrc = %Rrc\n", rc));
2159 LogFlowFuncLeave();
2160
2161 return rc;
2162}
2163/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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