VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp@ 43421

Last change on this file since 43421 was 43421, checked in by vboxsync, 12 years ago

VBoxManage: showvminfo --machinereadable the actual fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 104.8 KB
Line 
1/* $Id: VBoxManageInfo.cpp 43421 2012-09-25 07:00:32Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'showvminfo' command and helper routines.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_ONLY_DOCS
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include <VBox/com/com.h>
24#include <VBox/com/string.h>
25#include <VBox/com/Guid.h>
26#include <VBox/com/array.h>
27#include <VBox/com/ErrorInfo.h>
28#include <VBox/com/errorprint.h>
29
30#include <VBox/com/VirtualBox.h>
31
32#ifdef VBOX_WITH_PCI_PASSTHROUGH
33#include <VBox/pci.h>
34#endif
35
36#include <VBox/log.h>
37#include <iprt/stream.h>
38#include <iprt/time.h>
39#include <iprt/string.h>
40#include <iprt/getopt.h>
41#include <iprt/ctype.h>
42
43#include "VBoxManage.h"
44using namespace com;
45
46
47// funcs
48///////////////////////////////////////////////////////////////////////////////
49
50HRESULT showSnapshots(ComPtr<ISnapshot> &rootSnapshot,
51 ComPtr<ISnapshot> &currentSnapshot,
52 VMINFO_DETAILS details,
53 const Bstr &prefix /* = ""*/,
54 int level /*= 0*/)
55{
56 /* start with the root */
57 Bstr name;
58 Bstr uuid;
59 CHECK_ERROR2_RET(rootSnapshot,COMGETTER(Name)(name.asOutParam()), hrcCheck);
60 CHECK_ERROR2_RET(rootSnapshot,COMGETTER(Id)(uuid.asOutParam()), hrcCheck);
61 if (details == VMINFO_MACHINEREADABLE)
62 {
63 /* print with hierarchical numbering */
64 RTPrintf("SnapshotName%ls=\"%ls\"\n", prefix.raw(), name.raw());
65 RTPrintf("SnapshotUUID%ls=\"%s\"\n", prefix.raw(), Utf8Str(uuid).c_str());
66 }
67 else
68 {
69 /* print with indentation */
70 bool fCurrent = (rootSnapshot == currentSnapshot);
71 RTPrintf(" %lsName: %ls (UUID: %s)%s\n",
72 prefix.raw(),
73 name.raw(),
74 Utf8Str(uuid).c_str(),
75 (fCurrent) ? " *" : "");
76 }
77
78 /* get the children */
79 HRESULT hrc = S_OK;
80 SafeIfaceArray <ISnapshot> coll;
81 CHECK_ERROR2_RET(rootSnapshot,COMGETTER(Children)(ComSafeArrayAsOutParam(coll)), hrcCheck);
82 if (!coll.isNull())
83 {
84 for (size_t index = 0; index < coll.size(); ++index)
85 {
86 ComPtr<ISnapshot> snapshot = coll[index];
87 if (snapshot)
88 {
89 Bstr newPrefix;
90 if (details == VMINFO_MACHINEREADABLE)
91 newPrefix = Utf8StrFmt("%ls-%d", prefix.raw(), index + 1);
92 else
93 {
94 newPrefix = Utf8StrFmt("%ls ", prefix.raw());
95 }
96
97 /* recursive call */
98 HRESULT hrc2 = showSnapshots(snapshot, currentSnapshot, details, newPrefix, level + 1);
99 if (FAILED(hrc2))
100 hrc = hrc2;
101 }
102 }
103 }
104 return hrc;
105}
106
107static void makeTimeStr(char *s, int cb, int64_t millies)
108{
109 RTTIME t;
110 RTTIMESPEC ts;
111
112 RTTimeSpecSetMilli(&ts, millies);
113
114 RTTimeExplode(&t, &ts);
115
116 RTStrPrintf(s, cb, "%04d/%02d/%02d %02d:%02d:%02d UTC",
117 t.i32Year, t.u8Month, t.u8MonthDay,
118 t.u8Hour, t.u8Minute, t.u8Second);
119}
120
121const char *machineStateToName(MachineState_T machineState, bool fShort)
122{
123 switch (machineState)
124 {
125 case MachineState_PoweredOff:
126 return fShort ? "poweroff" : "powered off";
127 case MachineState_Saved:
128 return "saved";
129 case MachineState_Aborted:
130 return "aborted";
131 case MachineState_Teleported:
132 return "teleported";
133 case MachineState_Running:
134 return "running";
135 case MachineState_Paused:
136 return "paused";
137 case MachineState_Stuck:
138 return fShort ? "gurumeditation" : "guru meditation";
139 case MachineState_LiveSnapshotting:
140 return fShort ? "livesnapshotting" : "live snapshotting";
141 case MachineState_Teleporting:
142 return "teleporting";
143 case MachineState_Starting:
144 return "starting";
145 case MachineState_Stopping:
146 return "stopping";
147 case MachineState_Saving:
148 return "saving";
149 case MachineState_Restoring:
150 return "restoring";
151 case MachineState_TeleportingPausedVM:
152 return fShort ? "teleportingpausedvm" : "teleporting paused vm";
153 case MachineState_TeleportingIn:
154 return fShort ? "teleportingin" : "teleporting (incoming)";
155 case MachineState_RestoringSnapshot:
156 return fShort ? "restoringsnapshot" : "restoring snapshot";
157 case MachineState_DeletingSnapshot:
158 return fShort ? "deletingsnapshot" : "deleting snapshot";
159 case MachineState_DeletingSnapshotOnline:
160 return fShort ? "deletingsnapshotlive" : "deleting snapshot live";
161 case MachineState_DeletingSnapshotPaused:
162 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";
163 case MachineState_SettingUp:
164 return fShort ? "settingup" : "setting up";
165 default:
166 break;
167 }
168 return "unknown";
169}
170
171const char *facilityStateToName(AdditionsFacilityStatus_T faStatus, bool fShort)
172{
173 switch (faStatus)
174 {
175 case AdditionsFacilityStatus_Inactive:
176 return fShort ? "inactive" : "not active";
177 case AdditionsFacilityStatus_Paused:
178 return "paused";
179 case AdditionsFacilityStatus_PreInit:
180 return fShort ? "preinit" : "pre-initializing";
181 case AdditionsFacilityStatus_Init:
182 return fShort ? "init" : "initializing";
183 case AdditionsFacilityStatus_Active:
184 return fShort ? "active" : "active/running";
185 case AdditionsFacilityStatus_Terminating:
186 return "terminating";
187 case AdditionsFacilityStatus_Terminated:
188 return "terminated";
189 case AdditionsFacilityStatus_Failed:
190 return "failed";
191 case AdditionsFacilityStatus_Unknown:
192 default:
193 break;
194 }
195 return "unknown";
196}
197
198/**
199 * This takes care of escaping double quotes and slashes that the string might
200 * contain.
201 *
202 * @param pszName The variable name.
203 * @param pbstrValue The value.
204 */
205static void outputMachineReadableString(const char *pszName, Bstr const *pbstrValue)
206{
207 Assert(strpbrk(pszName, "\"\\") == NULL);
208
209 com::Utf8Str strValue(*pbstrValue);
210 if ( strValue.isEmpty()
211 || ( !strValue.count('"')
212 && !strValue.count('\\')))
213 RTPrintf("%s=\"%s\"\n", pszName, strValue.c_str());
214 else
215 {
216 /* The value needs escaping. */
217 RTPrintf("%s=\"", pszName);
218 const char *psz = strValue.c_str();
219 for (;;)
220 {
221 const char *pszNext = strpbrk(psz, "\"\\");
222 if (!pszNext)
223 {
224 RTPrintf("%s", psz);
225 break;
226 }
227 RTPrintf("%.*s\\%c", pszNext - psz, psz, *pszNext);
228 psz = pszNext + 1;
229 }
230 RTPrintf("\"\n");
231 }
232}
233
234/**
235 * Converts bandwidth group type to a string.
236 * @returns String representation.
237 * @param enmType Bandwidth control group type.
238 */
239inline const char * bwGroupTypeToString(BandwidthGroupType_T enmType)
240{
241 switch (enmType)
242 {
243 case BandwidthGroupType_Disk: return "Disk";
244 case BandwidthGroupType_Network: return "Network";
245 }
246 return "unknown";
247}
248
249HRESULT showBandwidthGroups(ComPtr<IBandwidthControl> &bwCtrl,
250 VMINFO_DETAILS details)
251{
252 int rc = S_OK;
253 SafeIfaceArray<IBandwidthGroup> bwGroups;
254
255 CHECK_ERROR_RET(bwCtrl, GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)), rc);
256
257 if (bwGroups.size() && details != VMINFO_MACHINEREADABLE)
258 RTPrintf("\n\n");
259 for (size_t i = 0; i < bwGroups.size(); i++)
260 {
261 Bstr strName;
262 LONG64 cMaxBytesPerSec;
263 BandwidthGroupType_T enmType;
264
265 CHECK_ERROR_RET(bwGroups[i], COMGETTER(Name)(strName.asOutParam()), rc);
266 CHECK_ERROR_RET(bwGroups[i], COMGETTER(Type)(&enmType), rc);
267 CHECK_ERROR_RET(bwGroups[i], COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec), rc);
268
269 const char *pszType = bwGroupTypeToString(enmType);
270 if (details == VMINFO_MACHINEREADABLE)
271 RTPrintf("BandwidthGroup%zu=%ls,%s,%lld\n", i, strName.raw(), pszType, cMaxBytesPerSec);
272 else
273 {
274 const char *pszUnits = "";
275 LONG64 cBytes = cMaxBytesPerSec;
276 if (cBytes == 0)
277 {
278 RTPrintf("Name: '%ls', Type: %s, Limit: none (disabled)\n", strName.raw(), pszType);
279 continue;
280 }
281 else if (!(cBytes % _1G))
282 {
283 pszUnits = "G";
284 cBytes /= _1G;
285 }
286 else if (!(cBytes % _1M))
287 {
288 pszUnits = "M";
289 cBytes /= _1M;
290 }
291 else if (!(cBytes % _1K))
292 {
293 pszUnits = "K";
294 cBytes /= _1K;
295 }
296 const char *pszNetUnits = NULL;
297 if (enmType == BandwidthGroupType_Network)
298 {
299 /*
300 * We want to report network rate limit in bits/s, not bytes.
301 * Only if it cannot be express it in kilobits we will fall
302 * back to reporting it in bytes.
303 */
304 LONG64 cBits = cMaxBytesPerSec;
305 if (!(cBits % 125))
306 {
307 cBits /= 125;
308 pszNetUnits = "k";
309 if (!(cBits % 1000000))
310 {
311 cBits /= 1000000;
312 pszNetUnits = "g";
313 }
314 else if (!(cBits % 1000))
315 {
316 cBits /= 1000;
317 pszNetUnits = "m";
318 }
319 RTPrintf("Name: '%ls', Type: %s, Limit: %lld %sbits/sec (%lld %sbytes/sec)\n", strName.raw(), pszType, cBits, pszNetUnits, cBytes, pszUnits);
320 }
321 }
322 if (!pszNetUnits)
323 RTPrintf("Name: '%ls', Type: %s, Limit: %lld %sbytes/sec\n", strName.raw(), pszType, cBytes, pszUnits);
324 }
325 }
326 if (details != VMINFO_MACHINEREADABLE)
327 RTPrintf(bwGroups.size() != 0 ? "\n" : "<none>\n\n");
328
329 return rc;
330}
331
332
333/* Disable global optimizations for MSC 8.0/64 to make it compile in reasonable
334 time. MSC 7.1/32 doesn't have quite as much trouble with it, but still
335 sufficient to qualify for this hack as well since this code isn't performance
336 critical and probably won't gain much from the extra optimizing in real life. */
337#if defined(_MSC_VER)
338# pragma optimize("g", off)
339#endif
340
341HRESULT showVMInfo(ComPtr<IVirtualBox> virtualBox,
342 ComPtr<IMachine> machine,
343 VMINFO_DETAILS details /*= VMINFO_NONE*/,
344 ComPtr<IConsole> console /*= ComPtr <IConsole> ()*/)
345{
346 HRESULT rc;
347
348#define SHOW_BOOLEAN_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman) \
349 SHOW_BOOLEAN_PROP_EX(a_pObj, a_Prop, a_szMachine, a_szHuman, "on", "off")
350
351#define SHOW_BOOLEAN_PROP_EX(a_pObj, a_Prop, a_szMachine, a_szHuman, a_szTrue, a_szFalse) \
352 do \
353 { \
354 BOOL f; \
355 CHECK_ERROR2_RET(a_pObj, COMGETTER(a_Prop)(&f), hrcCheck); \
356 if (details == VMINFO_MACHINEREADABLE) \
357 RTPrintf( a_szMachine "=\"%s\"\n", f ? "on" : "off"); \
358 else \
359 RTPrintf("%-16s %s\n", a_szHuman ":", f ? a_szTrue : a_szFalse); \
360 } while (0)
361
362#define SHOW_BOOLEAN_METHOD(a_pObj, a_Invocation, a_szMachine, a_szHuman) \
363 do \
364 { \
365 BOOL f; \
366 CHECK_ERROR2_RET(a_pObj, a_Invocation, hrcCheck); \
367 if (details == VMINFO_MACHINEREADABLE) \
368 RTPrintf( a_szMachine "=\"%s\"\n", f ? "on" : "off"); \
369 else \
370 RTPrintf("%-16s %s\n", a_szHuman ":", f ? "on" : "off"); \
371 } while (0)
372
373#define SHOW_STRING_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman) \
374 do \
375 { \
376 Bstr bstr; \
377 CHECK_ERROR2_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \
378 if (details == VMINFO_MACHINEREADABLE) \
379 outputMachineReadableString(a_szMachine, &bstr); \
380 else \
381 RTPrintf("%-16s %ls\n", a_szHuman ":", bstr.raw()); \
382 } while (0)
383
384#define SHOW_STRINGARRAY_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman) \
385 do \
386 { \
387 SafeArray<BSTR> array; \
388 CHECK_ERROR2_RET(a_pObj, COMGETTER(a_Prop)(ComSafeArrayAsOutParam(array)), hrcCheck); \
389 Utf8Str str; \
390 for (size_t i = 0; i < array.size(); i++) \
391 { \
392 if (i != 0) \
393 str.append(","); \
394 str.append(Utf8Str(array[i]).c_str()); \
395 } \
396 Bstr bstr(str); \
397 if (details == VMINFO_MACHINEREADABLE) \
398 outputMachineReadableString(a_szMachine, &bstr); \
399 else \
400 RTPrintf("%-16s %ls\n", a_szHuman ":", bstr.raw()); \
401 } while (0)
402
403#define SHOW_UUID_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman) \
404 SHOW_STRING_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman)
405
406#define SHOW_ULONG_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman, a_szUnit) \
407 do \
408 { \
409 ULONG u32; \
410 CHECK_ERROR2_RET(a_pObj, COMGETTER(a_Prop)(&u32), hrcCheck); \
411 if (details == VMINFO_MACHINEREADABLE) \
412 RTPrintf(a_szMachine "=%u\n", u32); \
413 else \
414 RTPrintf("%-16s %u" a_szUnit "\n", a_szHuman ":", u32); \
415 } while (0)
416
417#define SHOW_LONG64_PROP(a_pObj, a_Prop, a_szMachine, a_szHuman, a_szUnit) \
418 do \
419 { \
420 LONG64 i64; \
421 CHECK_ERROR2_RET(a_pObj, COMGETTER(a_Prop)(&i64), hrcCheck); \
422 if (details == VMINFO_MACHINEREADABLE) \
423 RTPrintf(a_szHuman "=%lld", i64); \
424 else \
425 RTPrintf("%-16s %'lld" a_szUnit "\n", a_szHuman ":", i64); \
426 } while (0)
427
428 /*
429 * The rules for output in -argdump format:
430 * 1) the key part (the [0-9a-zA-Z_\-]+ string before the '=' delimiter)
431 * is all lowercase for "VBoxManage modifyvm" parameters. Any
432 * other values printed are in CamelCase.
433 * 2) strings (anything non-decimal) are printed surrounded by
434 * double quotes '"'. If the strings themselves contain double
435 * quotes, these characters are escaped by '\'. Any '\' character
436 * in the original string is also escaped by '\'.
437 * 3) numbers (containing just [0-9\-]) are written out unchanged.
438 */
439
440 BOOL fAccessible;
441 CHECK_ERROR2_RET(machine, COMGETTER(Accessible)(&fAccessible), hrcCheck);
442 if (!fAccessible)
443 {
444 Bstr uuid;
445 machine->COMGETTER(Id)(uuid.asOutParam());
446 if (details == VMINFO_COMPACT)
447 RTPrintf("\"<inaccessible>\" {%s}\n", Utf8Str(uuid).c_str());
448 else
449 {
450 if (details == VMINFO_MACHINEREADABLE)
451 RTPrintf("name=\"<inaccessible>\"\n");
452 else
453 RTPrintf("Name: <inaccessible!>\n");
454 if (details == VMINFO_MACHINEREADABLE)
455 RTPrintf("UUID=\"%s\"\n", Utf8Str(uuid).c_str());
456 else
457 RTPrintf("UUID: %s\n", Utf8Str(uuid).c_str());
458 if (details != VMINFO_MACHINEREADABLE)
459 {
460 Bstr settingsFilePath;
461 rc = machine->COMGETTER(SettingsFilePath)(settingsFilePath.asOutParam());
462 RTPrintf("Config file: %ls\n", settingsFilePath.raw());
463 ComPtr<IVirtualBoxErrorInfo> accessError;
464 rc = machine->COMGETTER(AccessError)(accessError.asOutParam());
465 RTPrintf("Access error details:\n");
466 ErrorInfo ei(accessError);
467 GluePrintErrorInfo(ei);
468 RTPrintf("\n");
469 }
470 }
471 return S_OK;
472 }
473
474 if (details == VMINFO_COMPACT)
475 {
476 Bstr machineName;
477 machine->COMGETTER(Name)(machineName.asOutParam());
478 Bstr uuid;
479 machine->COMGETTER(Id)(uuid.asOutParam());
480
481 RTPrintf("\"%ls\" {%s}\n", machineName.raw(), Utf8Str(uuid).c_str());
482 return S_OK;
483 }
484
485 SHOW_STRING_PROP( machine, Name, "name", "Name");
486
487 Bstr osTypeId;
488 CHECK_ERROR2_RET(machine, COMGETTER(OSTypeId)(osTypeId.asOutParam()), hrcCheck);
489 ComPtr<IGuestOSType> osType;
490 CHECK_ERROR2_RET(virtualBox, GetGuestOSType(osTypeId.raw(), osType.asOutParam()), hrcCheck);
491 SHOW_STRINGARRAY_PROP( machine, Groups, "groups", "Groups");
492 SHOW_STRING_PROP( osType, Description, "ostype", "Guest OS");
493 SHOW_UUID_PROP( machine, Id, "UUID", "UUID");
494 SHOW_STRING_PROP( machine, SettingsFilePath, "CfgFile", "Config file");
495 SHOW_STRING_PROP( machine, SnapshotFolder, "SnapFldr", "Snapshot folder");
496 SHOW_STRING_PROP( machine, LogFolder, "LogFldr", "Log folder");
497 SHOW_UUID_PROP( machine, HardwareUUID, "hardwareuuid", "Hardware UUID");
498 SHOW_ULONG_PROP( machine, MemorySize, "memory", "Memory size", "MB");
499 SHOW_BOOLEAN_PROP( machine, PageFusionEnabled, "pagefusion", "Page Fusion");
500 SHOW_ULONG_PROP( machine, VRAMSize, "vram", "VRAM size", "MB");
501 SHOW_ULONG_PROP( machine, CPUExecutionCap, "cpuexecutioncap", "CPU exec cap", "%%");
502 SHOW_BOOLEAN_PROP( machine, PageFusionEnabled, "hpet", "HPET");
503
504 ChipsetType_T chipsetType;
505 CHECK_ERROR2_RET(machine, COMGETTER(ChipsetType)(&chipsetType), hrcCheck);
506 const char *pszChipsetType;
507 switch (chipsetType)
508 {
509 case ChipsetType_Null: pszChipsetType = "invalid"; break;
510 case ChipsetType_PIIX3: pszChipsetType = "piix3"; break;
511 case ChipsetType_ICH9: pszChipsetType = "ich9"; break;
512 default: AssertFailed(); pszChipsetType = "unknown"; break;
513 }
514 if (details == VMINFO_MACHINEREADABLE)
515 RTPrintf("chipset=\"%s\"\n", pszChipsetType);
516 else
517 RTPrintf("Chipset: %s\n", pszChipsetType);
518
519 FirmwareType_T firmwareType;
520 CHECK_ERROR2_RET(machine, COMGETTER(FirmwareType)(&firmwareType), hrcCheck);
521 const char *pszFirmwareType;
522 switch (firmwareType)
523 {
524 case FirmwareType_BIOS: pszFirmwareType = "BIOS"; break;
525 case FirmwareType_EFI: pszFirmwareType = "EFI"; break;
526 case FirmwareType_EFI32: pszFirmwareType = "EFI32"; break;
527 case FirmwareType_EFI64: pszFirmwareType = "EFI64"; break;
528 case FirmwareType_EFIDUAL: pszFirmwareType = "EFIDUAL"; break;
529 default: AssertFailed(); pszFirmwareType = "unknown"; break;
530 }
531 if (details == VMINFO_MACHINEREADABLE)
532 RTPrintf("firmware=\"%s\"\n", pszFirmwareType);
533 else
534 RTPrintf("Firmware: %s\n", pszFirmwareType);
535
536 SHOW_ULONG_PROP( machine, CPUCount, "cpus", "Number of CPUs", "");
537 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_Synthetic, &f), "synthcpu", "Synthetic Cpu");
538
539 if (details != VMINFO_MACHINEREADABLE)
540 RTPrintf("CPUID overrides: ");
541 ULONG cFound = 0;
542 static uint32_t const s_auCpuIdRanges[] =
543 {
544 UINT32_C(0x00000000), UINT32_C(0x0000000a),
545 UINT32_C(0x80000000), UINT32_C(0x8000000a)
546 };
547 for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2)
548 for (uint32_t uLeaf = s_auCpuIdRanges[i]; uLeaf < s_auCpuIdRanges[i + 1]; uLeaf++)
549 {
550 ULONG uEAX, uEBX, uECX, uEDX;
551 rc = machine->GetCPUIDLeaf(uLeaf, &uEAX, &uEBX, &uECX, &uEDX);
552 if (SUCCEEDED(rc))
553 {
554 if (details == VMINFO_MACHINEREADABLE)
555 RTPrintf("cpuid=%08x,%08x,%08x,%08x,%08x", uLeaf, uEAX, uEBX, uECX, uEDX);
556 else
557 {
558 if (!cFound)
559 RTPrintf("Leaf no. EAX EBX ECX EDX\n");
560 RTPrintf(" %08x %08x %08x %08x %08x\n", uLeaf, uEAX, uEBX, uECX, uEDX);
561 }
562 cFound++;
563 }
564 }
565 if (!cFound && details != VMINFO_MACHINEREADABLE)
566 RTPrintf("None\n");
567
568 ComPtr <IBIOSSettings> biosSettings;
569 CHECK_ERROR2_RET(machine, COMGETTER(BIOSSettings)(biosSettings.asOutParam()), hrcCheck);
570
571 BIOSBootMenuMode_T bootMenuMode;
572 CHECK_ERROR2_RET(biosSettings, COMGETTER(BootMenuMode)(&bootMenuMode), hrcCheck);
573 const char *pszBootMenu;
574 switch (bootMenuMode)
575 {
576 case BIOSBootMenuMode_Disabled:
577 pszBootMenu = "disabled";
578 break;
579 case BIOSBootMenuMode_MenuOnly:
580 if (details == VMINFO_MACHINEREADABLE)
581 pszBootMenu = "menuonly";
582 else
583 pszBootMenu = "menu only";
584 break;
585 default:
586 if (details == VMINFO_MACHINEREADABLE)
587 pszBootMenu = "messageandmenu";
588 else
589 pszBootMenu = "message and menu";
590 }
591 if (details == VMINFO_MACHINEREADABLE)
592 RTPrintf("bootmenu=\"%s\"\n", pszBootMenu);
593 else
594 RTPrintf("Boot menu mode: %s\n", pszBootMenu);
595
596 ComPtr<ISystemProperties> systemProperties;
597 CHECK_ERROR2_RET(virtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), hrcCheck);
598 ULONG maxBootPosition = 0;
599 CHECK_ERROR2_RET(systemProperties, COMGETTER(MaxBootPosition)(&maxBootPosition), hrcCheck);
600 for (ULONG i = 1; i <= maxBootPosition; i++)
601 {
602 DeviceType_T bootOrder;
603 CHECK_ERROR2_RET(machine, GetBootOrder(i, &bootOrder), hrcCheck);
604 if (bootOrder == DeviceType_Floppy)
605 {
606 if (details == VMINFO_MACHINEREADABLE)
607 RTPrintf("boot%d=\"floppy\"\n", i);
608 else
609 RTPrintf("Boot Device (%d): Floppy\n", i);
610 }
611 else if (bootOrder == DeviceType_DVD)
612 {
613 if (details == VMINFO_MACHINEREADABLE)
614 RTPrintf("boot%d=\"dvd\"\n", i);
615 else
616 RTPrintf("Boot Device (%d): DVD\n", i);
617 }
618 else if (bootOrder == DeviceType_HardDisk)
619 {
620 if (details == VMINFO_MACHINEREADABLE)
621 RTPrintf("boot%d=\"disk\"\n", i);
622 else
623 RTPrintf("Boot Device (%d): HardDisk\n", i);
624 }
625 else if (bootOrder == DeviceType_Network)
626 {
627 if (details == VMINFO_MACHINEREADABLE)
628 RTPrintf("boot%d=\"net\"\n", i);
629 else
630 RTPrintf("Boot Device (%d): Network\n", i);
631 }
632 else if (bootOrder == DeviceType_USB)
633 {
634 if (details == VMINFO_MACHINEREADABLE)
635 RTPrintf("boot%d=\"usb\"\n", i);
636 else
637 RTPrintf("Boot Device (%d): USB\n", i);
638 }
639 else if (bootOrder == DeviceType_SharedFolder)
640 {
641 if (details == VMINFO_MACHINEREADABLE)
642 RTPrintf("boot%d=\"sharedfolder\"\n", i);
643 else
644 RTPrintf("Boot Device (%d): Shared Folder\n", i);
645 }
646 else
647 {
648 if (details == VMINFO_MACHINEREADABLE)
649 RTPrintf("boot%d=\"none\"\n", i);
650 else
651 RTPrintf("Boot Device (%d): Not Assigned\n", i);
652 }
653 }
654
655 SHOW_BOOLEAN_PROP(biosSettings, ACPIEnabled, "acpi", "ACPI");
656 SHOW_BOOLEAN_PROP(biosSettings, IOAPICEnabled, "ioapic", "IOAPIC");
657 SHOW_BOOLEAN_METHOD(machine, GetCPUProperty(CPUPropertyType_PAE, &f), "pae", "PAE");
658 SHOW_LONG64_PROP(biosSettings, TimeOffset, "biossystemtimeoffset", "Time offset", "ms");
659 SHOW_BOOLEAN_PROP_EX(machine, RTCUseUTC, "rtcuseutc", "RTC", "UTC", "local time");
660 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &f), "hwvirtex", "Hardw. virt.ext");
661 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_Exclusive, &f), "hwvirtexexcl", "Hardw. virt.ext exclusive");
662 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &f),"nestedpaging", "Nested Paging");
663 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &f), "largepages", "Large Pages");
664 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_VPID, &f), "vtxvpid", "VT-x VPID");
665
666 MachineState_T machineState;
667 CHECK_ERROR2_RET(machine, COMGETTER(State)(&machineState), hrcCheck);
668 const char *pszState = machineStateToName(machineState, details == VMINFO_MACHINEREADABLE /*=fShort*/);
669
670 LONG64 stateSince;
671 machine->COMGETTER(LastStateChange)(&stateSince);
672 RTTIMESPEC timeSpec;
673 RTTimeSpecSetMilli(&timeSpec, stateSince);
674 char pszTime[30] = {0};
675 RTTimeSpecToString(&timeSpec, pszTime, sizeof(pszTime));
676 if (details == VMINFO_MACHINEREADABLE)
677 {
678 RTPrintf("VMState=\"%s\"\n", pszState);
679 RTPrintf("VMStateChangeTime=\"%s\"\n", pszTime);
680
681 Bstr stateFile;
682 machine->COMGETTER(StateFilePath)(stateFile.asOutParam());
683 if (!stateFile.isEmpty())
684 RTPrintf("VMStateFile=\"%ls\"\n", stateFile.raw());
685 }
686 else
687 RTPrintf("State: %s (since %s)\n", pszState, pszTime);
688
689 SHOW_ULONG_PROP( machine, MonitorCount, "monitorcount", "Monitor count", "");
690 SHOW_BOOLEAN_PROP( machine, Accelerate3DEnabled, "accelerate3d", "3D Acceleration");
691#ifdef VBOX_WITH_VIDEOHWACCEL
692 SHOW_BOOLEAN_PROP( machine, Accelerate2DVideoEnabled, "accelerate2dvideo", "2D Video Acceleration");
693#endif
694 SHOW_BOOLEAN_PROP( machine, TeleporterEnabled, "teleporterenabled", "Teleporter Enabled");
695 SHOW_ULONG_PROP( machine, TeleporterPort, "teleporterport", "Teleporter Port", "");
696 SHOW_STRING_PROP( machine, TeleporterAddress, "teleporteraddress", "Teleporter Address");
697 SHOW_STRING_PROP( machine, TeleporterPassword, "teleporterpassword", "Teleporter Password");
698 SHOW_BOOLEAN_PROP( machine, TracingEnabled, "tracing-enabled", "Tracing Enabled");
699 SHOW_BOOLEAN_PROP( machine, AllowTracingToAccessVM, "tracing-allow-vm-access", "Allow Tracing to Access VM");
700 SHOW_STRING_PROP( machine, TracingConfig, "tracing-config", "Tracing Configuration");
701 SHOW_BOOLEAN_PROP( machine, AutostartEnabled, "autostart-enabled", "Autostart Enabled");
702 SHOW_ULONG_PROP( machine, AutostartDelay, "autostart-delay", "Autostart Delay", "");
703
704/** @todo Convert the remainder of the function to SHOW_XXX macros and add error
705 * checking where missing. */
706 /*
707 * Storage Controllers and their attached Mediums.
708 */
709 com::SafeIfaceArray<IStorageController> storageCtls;
710 CHECK_ERROR(machine, COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(storageCtls)));
711 for (size_t i = 0; i < storageCtls.size(); ++ i)
712 {
713 ComPtr<IStorageController> storageCtl = storageCtls[i];
714 StorageControllerType_T enmCtlType = StorageControllerType_Null;
715 const char *pszCtl = NULL;
716 ULONG ulValue = 0;
717 BOOL fBootable = FALSE;
718 Bstr storageCtlName;
719
720 storageCtl->COMGETTER(Name)(storageCtlName.asOutParam());
721 if (details == VMINFO_MACHINEREADABLE)
722 RTPrintf("storagecontrollername%u=\"%ls\"\n", i, storageCtlName.raw());
723 else
724 RTPrintf("Storage Controller Name (%u): %ls\n", i, storageCtlName.raw());
725
726 storageCtl->COMGETTER(ControllerType)(&enmCtlType);
727 switch (enmCtlType)
728 {
729 case StorageControllerType_LsiLogic:
730 pszCtl = "LsiLogic";
731 break;
732 case StorageControllerType_BusLogic:
733 pszCtl = "BusLogic";
734 break;
735 case StorageControllerType_IntelAhci:
736 pszCtl = "IntelAhci";
737 break;
738 case StorageControllerType_PIIX3:
739 pszCtl = "PIIX3";
740 break;
741 case StorageControllerType_PIIX4:
742 pszCtl = "PIIX4";
743 break;
744 case StorageControllerType_ICH6:
745 pszCtl = "ICH6";
746 break;
747 case StorageControllerType_I82078:
748 pszCtl = "I82078";
749 break;
750
751 default:
752 pszCtl = "unknown";
753 }
754 if (details == VMINFO_MACHINEREADABLE)
755 RTPrintf("storagecontrollertype%u=\"%s\"\n", i, pszCtl);
756 else
757 RTPrintf("Storage Controller Type (%u): %s\n", i, pszCtl);
758
759 storageCtl->COMGETTER(Instance)(&ulValue);
760 if (details == VMINFO_MACHINEREADABLE)
761 RTPrintf("storagecontrollerinstance%u=\"%lu\"\n", i, ulValue);
762 else
763 RTPrintf("Storage Controller Instance Number (%u): %lu\n", i, ulValue);
764
765 storageCtl->COMGETTER(MaxPortCount)(&ulValue);
766 if (details == VMINFO_MACHINEREADABLE)
767 RTPrintf("storagecontrollermaxportcount%u=\"%lu\"\n", i, ulValue);
768 else
769 RTPrintf("Storage Controller Max Port Count (%u): %lu\n", i, ulValue);
770
771 storageCtl->COMGETTER(PortCount)(&ulValue);
772 if (details == VMINFO_MACHINEREADABLE)
773 RTPrintf("storagecontrollerportcount%u=\"%lu\"\n", i, ulValue);
774 else
775 RTPrintf("Storage Controller Port Count (%u): %lu\n", i, ulValue);
776
777 storageCtl->COMGETTER(Bootable)(&fBootable);
778 if (details == VMINFO_MACHINEREADABLE)
779 RTPrintf("storagecontrollerbootable%u=\"%s\"\n", i, fBootable ? "on" : "off");
780 else
781 RTPrintf("Storage Controller Bootable (%u): %s\n", i, fBootable ? "on" : "off");
782 }
783
784 for (size_t j = 0; j < storageCtls.size(); ++ j)
785 {
786 ComPtr<IStorageController> storageCtl = storageCtls[j];
787 ComPtr<IMedium> medium;
788 Bstr storageCtlName;
789 Bstr filePath;
790 ULONG cDevices;
791 ULONG cPorts;
792
793 storageCtl->COMGETTER(Name)(storageCtlName.asOutParam());
794 storageCtl->COMGETTER(MaxDevicesPerPortCount)(&cDevices);
795 storageCtl->COMGETTER(PortCount)(&cPorts);
796
797 for (ULONG i = 0; i < cPorts; ++ i)
798 {
799 for (ULONG k = 0; k < cDevices; ++ k)
800 {
801 ComPtr<IMediumAttachment> mediumAttach;
802 machine->GetMediumAttachment(storageCtlName.raw(),
803 i, k,
804 mediumAttach.asOutParam());
805 BOOL fIsEjected = FALSE;
806 BOOL fTempEject = FALSE;
807 DeviceType_T devType = DeviceType_Null;
808 if (mediumAttach)
809 {
810 mediumAttach->COMGETTER(TemporaryEject)(&fTempEject);
811 mediumAttach->COMGETTER(IsEjected)(&fIsEjected);
812 mediumAttach->COMGETTER(Type)(&devType);
813 }
814 rc = machine->GetMedium(storageCtlName.raw(), i, k,
815 medium.asOutParam());
816 if (SUCCEEDED(rc) && medium)
817 {
818 BOOL fPassthrough = FALSE;
819
820 if (mediumAttach)
821 mediumAttach->COMGETTER(Passthrough)(&fPassthrough);
822
823 medium->COMGETTER(Location)(filePath.asOutParam());
824 Bstr uuid;
825 medium->COMGETTER(Id)(uuid.asOutParam());
826
827 if (details == VMINFO_MACHINEREADABLE)
828 {
829 RTPrintf("\"%ls-%d-%d\"=\"%ls\"\n", storageCtlName.raw(),
830 i, k, filePath.raw());
831 RTPrintf("\"%ls-ImageUUID-%d-%d\"=\"%s\"\n",
832 storageCtlName.raw(), i, k, Utf8Str(uuid).c_str());
833 if (fPassthrough)
834 RTPrintf("\"%ls-dvdpassthrough\"=\"%s\"\n", storageCtlName.raw(),
835 fPassthrough ? "on" : "off");
836 if (devType == DeviceType_DVD)
837 {
838 RTPrintf("\"%ls-tempeject\"=\"%s\"\n", storageCtlName.raw(),
839 fTempEject ? "on" : "off");
840 RTPrintf("\"%ls-IsEjected\"=\"%s\"\n", storageCtlName.raw(),
841 fIsEjected ? "on" : "off");
842 }
843 }
844 else
845 {
846 RTPrintf("%ls (%d, %d): %ls (UUID: %s)",
847 storageCtlName.raw(), i, k, filePath.raw(),
848 Utf8Str(uuid).c_str());
849 if (fPassthrough)
850 RTPrintf(" (passthrough enabled)");
851 if (fTempEject)
852 RTPrintf(" (temp eject)");
853 if (fIsEjected)
854 RTPrintf(" (ejected)");
855 RTPrintf("\n");
856 }
857 }
858 else if (SUCCEEDED(rc))
859 {
860 if (details == VMINFO_MACHINEREADABLE)
861 {
862 RTPrintf("\"%ls-%d-%d\"=\"emptydrive\"\n", storageCtlName.raw(), i, k);
863 if (devType == DeviceType_DVD)
864 RTPrintf("\"%ls-IsEjected\"=\"%s\"\n", storageCtlName.raw(),
865 fIsEjected ? "on" : "off");
866 }
867 else
868 {
869 RTPrintf("%ls (%d, %d): Empty", storageCtlName.raw(), i, k);
870 if (fTempEject)
871 RTPrintf(" (temp eject)");
872 if (fIsEjected)
873 RTPrintf(" (ejected)");
874 RTPrintf("\n");
875 }
876 }
877 else
878 {
879 if (details == VMINFO_MACHINEREADABLE)
880 RTPrintf("\"%ls-%d-%d\"=\"none\"\n", storageCtlName.raw(), i, k);
881 }
882 }
883 }
884 }
885
886 /* get the maximum amount of NICS */
887 ULONG maxNICs = getMaxNics(virtualBox, machine);
888
889 for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++)
890 {
891 ComPtr<INetworkAdapter> nic;
892 rc = machine->GetNetworkAdapter(currentNIC, nic.asOutParam());
893 if (SUCCEEDED(rc) && nic)
894 {
895 BOOL fEnabled;
896 nic->COMGETTER(Enabled)(&fEnabled);
897 if (!fEnabled)
898 {
899 if (details == VMINFO_MACHINEREADABLE)
900 RTPrintf("nic%d=\"none\"\n", currentNIC + 1);
901 else
902 RTPrintf("NIC %d: disabled\n", currentNIC + 1);
903 }
904 else
905 {
906 Bstr strMACAddress;
907 nic->COMGETTER(MACAddress)(strMACAddress.asOutParam());
908 Utf8Str strAttachment;
909 Utf8Str strNatSettings = "";
910 Utf8Str strNatForwardings = "";
911 NetworkAttachmentType_T attachment;
912 nic->COMGETTER(AttachmentType)(&attachment);
913 switch (attachment)
914 {
915 case NetworkAttachmentType_Null:
916 if (details == VMINFO_MACHINEREADABLE)
917 strAttachment = "null";
918 else
919 strAttachment = "none";
920 break;
921
922 case NetworkAttachmentType_NAT:
923 {
924 Bstr strNetwork;
925 ComPtr<INATEngine> engine;
926 nic->COMGETTER(NATEngine)(engine.asOutParam());
927 engine->COMGETTER(Network)(strNetwork.asOutParam());
928 com::SafeArray<BSTR> forwardings;
929 engine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(forwardings));
930 strNatForwardings = "";
931 for (size_t i = 0; i < forwardings.size(); ++i)
932 {
933 bool fSkip = false;
934 uint16_t port = 0;
935 BSTR r = forwardings[i];
936 Utf8Str utf = Utf8Str(r);
937 Utf8Str strName;
938 Utf8Str strProto;
939 Utf8Str strHostPort;
940 Utf8Str strHostIP;
941 Utf8Str strGuestPort;
942 Utf8Str strGuestIP;
943 size_t pos, ppos;
944 pos = ppos = 0;
945 #define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \
946 do { \
947 pos = str.find(",", ppos); \
948 if (pos == Utf8Str::npos) \
949 { \
950 Log(( #res " extracting from %s is failed\n", str.c_str())); \
951 fSkip = true; \
952 } \
953 res = str.substr(ppos, pos - ppos); \
954 Log2((#res " %s pos:%d, ppos:%d\n", res.c_str(), pos, ppos)); \
955 ppos = pos + 1; \
956 } while (0)
957 ITERATE_TO_NEXT_TERM(strName, utf, pos, ppos);
958 if (fSkip) continue;
959 ITERATE_TO_NEXT_TERM(strProto, utf, pos, ppos);
960 if (fSkip) continue;
961 ITERATE_TO_NEXT_TERM(strHostIP, utf, pos, ppos);
962 if (fSkip) continue;
963 ITERATE_TO_NEXT_TERM(strHostPort, utf, pos, ppos);
964 if (fSkip) continue;
965 ITERATE_TO_NEXT_TERM(strGuestIP, utf, pos, ppos);
966 if (fSkip) continue;
967 strGuestPort = utf.substr(ppos, utf.length() - ppos);
968 #undef ITERATE_TO_NEXT_TERM
969 switch (strProto.toUInt32())
970 {
971 case NATProtocol_TCP:
972 strProto = "tcp";
973 break;
974 case NATProtocol_UDP:
975 strProto = "udp";
976 break;
977 default:
978 strProto = "unk";
979 break;
980 }
981 if (details == VMINFO_MACHINEREADABLE)
982 {
983 strNatForwardings = Utf8StrFmt("%sForwarding(%d)=\"%s,%s,%s,%s,%s,%s\"\n",
984 strNatForwardings.c_str(), i, strName.c_str(), strProto.c_str(),
985 strHostIP.c_str(), strHostPort.c_str(),
986 strGuestIP.c_str(), strGuestPort.c_str());
987 }
988 else
989 {
990 strNatForwardings = Utf8StrFmt("%sNIC %d Rule(%d): name = %s, protocol = %s,"
991 " host ip = %s, host port = %s, guest ip = %s, guest port = %s\n",
992 strNatForwardings.c_str(), currentNIC + 1, i, strName.c_str(), strProto.c_str(),
993 strHostIP.c_str(), strHostPort.c_str(),
994 strGuestIP.c_str(), strGuestPort.c_str());
995 }
996 }
997 ULONG mtu = 0;
998 ULONG sockSnd = 0;
999 ULONG sockRcv = 0;
1000 ULONG tcpSnd = 0;
1001 ULONG tcpRcv = 0;
1002 engine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv);
1003
1004 if (details == VMINFO_MACHINEREADABLE)
1005 {
1006 RTPrintf("natnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.length() ? strNetwork.raw(): Bstr("nat").raw());
1007 strAttachment = "nat";
1008 strNatSettings = Utf8StrFmt("mtu=\"%d\"\nsockSnd=\"%d\"\nsockRcv=\"%d\"\ntcpWndSnd=\"%d\"\ntcpWndRcv=\"%d\"\n",
1009 mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64 , tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1010 }
1011 else
1012 {
1013 strAttachment = "NAT";
1014 strNatSettings = Utf8StrFmt("NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d)\n",
1015 currentNIC + 1, mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64 , tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1016 }
1017 break;
1018 }
1019
1020 case NetworkAttachmentType_Bridged:
1021 {
1022 Bstr strBridgeAdp;
1023 nic->COMGETTER(BridgedInterface)(strBridgeAdp.asOutParam());
1024 if (details == VMINFO_MACHINEREADABLE)
1025 {
1026 RTPrintf("bridgeadapter%d=\"%ls\"\n", currentNIC + 1, strBridgeAdp.raw());
1027 strAttachment = "bridged";
1028 }
1029 else
1030 strAttachment = Utf8StrFmt("Bridged Interface '%ls'", strBridgeAdp.raw());
1031 break;
1032 }
1033
1034 case NetworkAttachmentType_Internal:
1035 {
1036 Bstr strNetwork;
1037 nic->COMGETTER(InternalNetwork)(strNetwork.asOutParam());
1038 if (details == VMINFO_MACHINEREADABLE)
1039 {
1040 RTPrintf("intnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1041 strAttachment = "intnet";
1042 }
1043 else
1044 strAttachment = Utf8StrFmt("Internal Network '%s'", Utf8Str(strNetwork).c_str());
1045 break;
1046 }
1047
1048 case NetworkAttachmentType_HostOnly:
1049 {
1050 Bstr strHostonlyAdp;
1051 nic->COMGETTER(HostOnlyInterface)(strHostonlyAdp.asOutParam());
1052 if (details == VMINFO_MACHINEREADABLE)
1053 {
1054 RTPrintf("hostonlyadapter%d=\"%ls\"\n", currentNIC + 1, strHostonlyAdp.raw());
1055 strAttachment = "hostonly";
1056 }
1057 else
1058 strAttachment = Utf8StrFmt("Host-only Interface '%ls'", strHostonlyAdp.raw());
1059 break;
1060 }
1061 case NetworkAttachmentType_Generic:
1062 {
1063 Bstr strGenericDriver;
1064 nic->COMGETTER(GenericDriver)(strGenericDriver.asOutParam());
1065 if (details == VMINFO_MACHINEREADABLE)
1066 {
1067 RTPrintf("generic%d=\"%ls\"\n", currentNIC + 1, strGenericDriver.raw());
1068 strAttachment = "Generic";
1069 }
1070 else
1071 {
1072 strAttachment = Utf8StrFmt("Generic '%ls'", strGenericDriver.raw());
1073
1074 // show the generic properties
1075 com::SafeArray<BSTR> aProperties;
1076 com::SafeArray<BSTR> aValues;
1077 rc = nic->GetProperties(NULL,
1078 ComSafeArrayAsOutParam(aProperties),
1079 ComSafeArrayAsOutParam(aValues));
1080 if (SUCCEEDED(rc))
1081 {
1082 strAttachment += " { ";
1083 for (unsigned i = 0; i < aProperties.size(); ++i)
1084 strAttachment += Utf8StrFmt(!i ? "%ls='%ls'" : ", %ls='%ls'",
1085 aProperties[i], aValues[i]);
1086 strAttachment += " }";
1087 }
1088 }
1089 break;
1090 }
1091 default:
1092 strAttachment = "unknown";
1093 break;
1094 }
1095
1096 /* cable connected */
1097 BOOL fConnected;
1098 nic->COMGETTER(CableConnected)(&fConnected);
1099
1100 /* promisc policy */
1101 NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy;
1102 CHECK_ERROR2_RET(nic, COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy), hrcCheck);
1103 const char *pszPromiscuousGuestPolicy;
1104 switch (enmPromiscModePolicy)
1105 {
1106 case NetworkAdapterPromiscModePolicy_Deny: pszPromiscuousGuestPolicy = "deny"; break;
1107 case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = "allow-vms"; break;
1108 case NetworkAdapterPromiscModePolicy_AllowAll: pszPromiscuousGuestPolicy = "allow-all"; break;
1109 default: AssertFailedReturn(VERR_INTERNAL_ERROR_4);
1110 }
1111
1112 /* trace stuff */
1113 BOOL fTraceEnabled;
1114 nic->COMGETTER(TraceEnabled)(&fTraceEnabled);
1115 Bstr traceFile;
1116 nic->COMGETTER(TraceFile)(traceFile.asOutParam());
1117
1118 /* NIC type */
1119 NetworkAdapterType_T NICType;
1120 nic->COMGETTER(AdapterType)(&NICType);
1121 const char *pszNICType;
1122 switch (NICType)
1123 {
1124 case NetworkAdapterType_Am79C970A: pszNICType = "Am79C970A"; break;
1125 case NetworkAdapterType_Am79C973: pszNICType = "Am79C973"; break;
1126#ifdef VBOX_WITH_E1000
1127 case NetworkAdapterType_I82540EM: pszNICType = "82540EM"; break;
1128 case NetworkAdapterType_I82543GC: pszNICType = "82543GC"; break;
1129 case NetworkAdapterType_I82545EM: pszNICType = "82545EM"; break;
1130#endif
1131#ifdef VBOX_WITH_VIRTIO
1132 case NetworkAdapterType_Virtio: pszNICType = "virtio"; break;
1133#endif
1134 default: AssertFailed(); pszNICType = "unknown"; break;
1135 }
1136
1137 /* reported line speed */
1138 ULONG ulLineSpeed;
1139 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1140
1141 /* boot priority of the adapter */
1142 ULONG ulBootPriority;
1143 nic->COMGETTER(BootPriority)(&ulBootPriority);
1144
1145 /* bandwidth group */
1146 ComObjPtr<IBandwidthGroup> pBwGroup;
1147 Bstr strBwGroup;
1148 nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());
1149 if (!pBwGroup.isNull())
1150 pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam());
1151
1152 if (details == VMINFO_MACHINEREADABLE)
1153 {
1154 RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw());
1155 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1156 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str());
1157 }
1158 else
1159 RTPrintf("NIC %u: MAC: %ls, Attachment: %s, Cable connected: %s, Trace: %s (file: %ls), Type: %s, Reported speed: %d Mbps, Boot priority: %d, Promisc Policy: %s, Bandwidth group: %ls\n",
1160 currentNIC + 1, strMACAddress.raw(), strAttachment.c_str(),
1161 fConnected ? "on" : "off",
1162 fTraceEnabled ? "on" : "off",
1163 traceFile.isEmpty() ? Bstr("none").raw() : traceFile.raw(),
1164 pszNICType,
1165 ulLineSpeed / 1000,
1166 (int)ulBootPriority,
1167 pszPromiscuousGuestPolicy,
1168 strBwGroup.isEmpty() ? Bstr("none").raw() : strBwGroup.raw());
1169 if (strNatSettings.length())
1170 RTPrintf(strNatSettings.c_str());
1171 if (strNatForwardings.length())
1172 RTPrintf(strNatForwardings.c_str());
1173 }
1174 }
1175 }
1176
1177 /* Pointing device information */
1178 PointingHIDType_T aPointingHID;
1179 const char *pszHID = "Unknown";
1180 const char *pszMrHID = "unknown";
1181 machine->COMGETTER(PointingHIDType)(&aPointingHID);
1182 switch (aPointingHID)
1183 {
1184 case PointingHIDType_None:
1185 pszHID = "None";
1186 pszMrHID = "none";
1187 break;
1188 case PointingHIDType_PS2Mouse:
1189 pszHID = "PS/2 Mouse";
1190 pszMrHID = "ps2mouse";
1191 break;
1192 case PointingHIDType_USBMouse:
1193 pszHID = "USB Mouse";
1194 pszMrHID = "usbmouse";
1195 break;
1196 case PointingHIDType_USBTablet:
1197 pszHID = "USB Tablet";
1198 pszMrHID = "usbtablet";
1199 break;
1200 case PointingHIDType_ComboMouse:
1201 pszHID = "USB Tablet and PS/2 Mouse";
1202 pszMrHID = "combomouse";
1203 break;
1204 default:
1205 break;
1206 }
1207 if (details == VMINFO_MACHINEREADABLE)
1208 RTPrintf("hidpointing=\"%s\"\n", pszMrHID);
1209 else
1210 RTPrintf("Pointing Device: %s\n", pszHID);
1211
1212 /* Keyboard device information */
1213 KeyboardHIDType_T aKeyboardHID;
1214 machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID);
1215 pszHID = "Unknown";
1216 pszMrHID = "unknown";
1217 switch (aKeyboardHID)
1218 {
1219 case KeyboardHIDType_None:
1220 pszHID = "None";
1221 pszMrHID = "none";
1222 break;
1223 case KeyboardHIDType_PS2Keyboard:
1224 pszHID = "PS/2 Keyboard";
1225 pszMrHID = "ps2kbd";
1226 break;
1227 case KeyboardHIDType_USBKeyboard:
1228 pszHID = "USB Keyboard";
1229 pszMrHID = "usbkbd";
1230 break;
1231 case KeyboardHIDType_ComboKeyboard:
1232 pszHID = "USB and PS/2 Keyboard";
1233 pszMrHID = "combokbd";
1234 break;
1235 default:
1236 break;
1237 }
1238 if (details == VMINFO_MACHINEREADABLE)
1239 RTPrintf("hidkeyboard=\"%s\"\n", pszMrHID);
1240 else
1241 RTPrintf("Keyboard Device: %s\n", pszHID);
1242
1243 ComPtr<ISystemProperties> sysProps;
1244 virtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
1245
1246 /* get the maximum amount of UARTs */
1247 ULONG maxUARTs = 0;
1248 sysProps->COMGETTER(SerialPortCount)(&maxUARTs);
1249 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
1250 {
1251 ComPtr<ISerialPort> uart;
1252 rc = machine->GetSerialPort(currentUART, uart.asOutParam());
1253 if (SUCCEEDED(rc) && uart)
1254 {
1255 /* show the config of this UART */
1256 BOOL fEnabled;
1257 uart->COMGETTER(Enabled)(&fEnabled);
1258 if (!fEnabled)
1259 {
1260 if (details == VMINFO_MACHINEREADABLE)
1261 RTPrintf("uart%d=\"off\"\n", currentUART + 1);
1262 else
1263 RTPrintf("UART %d: disabled\n", currentUART + 1);
1264 }
1265 else
1266 {
1267 ULONG ulIRQ, ulIOBase;
1268 PortMode_T HostMode;
1269 Bstr path;
1270 BOOL fServer;
1271 uart->COMGETTER(IRQ)(&ulIRQ);
1272 uart->COMGETTER(IOBase)(&ulIOBase);
1273 uart->COMGETTER(Path)(path.asOutParam());
1274 uart->COMGETTER(Server)(&fServer);
1275 uart->COMGETTER(HostMode)(&HostMode);
1276
1277 if (details == VMINFO_MACHINEREADABLE)
1278 RTPrintf("uart%d=\"%#06x,%d\"\n", currentUART + 1,
1279 ulIOBase, ulIRQ);
1280 else
1281 RTPrintf("UART %d: I/O base: %#06x, IRQ: %d",
1282 currentUART + 1, ulIOBase, ulIRQ);
1283 switch (HostMode)
1284 {
1285 default:
1286 case PortMode_Disconnected:
1287 if (details == VMINFO_MACHINEREADABLE)
1288 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
1289 else
1290 RTPrintf(", disconnected\n");
1291 break;
1292 case PortMode_RawFile:
1293 if (details == VMINFO_MACHINEREADABLE)
1294 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
1295 path.raw());
1296 else
1297 RTPrintf(", attached to raw file '%ls'\n",
1298 path.raw());
1299 break;
1300 case PortMode_HostPipe:
1301 if (details == VMINFO_MACHINEREADABLE)
1302 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
1303 fServer ? "server" : "client", path.raw());
1304 else
1305 RTPrintf(", attached to pipe (%s) '%ls'\n",
1306 fServer ? "server" : "client", path.raw());
1307 break;
1308 case PortMode_HostDevice:
1309 if (details == VMINFO_MACHINEREADABLE)
1310 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
1311 path.raw());
1312 else
1313 RTPrintf(", attached to device '%ls'\n", path.raw());
1314 break;
1315 }
1316 }
1317 }
1318 }
1319
1320 /* get the maximum amount of LPTs */
1321 ULONG maxLPTs = 0;
1322 sysProps->COMGETTER(ParallelPortCount)(&maxLPTs);
1323 for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++)
1324 {
1325 ComPtr<IParallelPort> lpt;
1326 rc = machine->GetParallelPort(currentLPT, lpt.asOutParam());
1327 if (SUCCEEDED(rc) && lpt)
1328 {
1329 /* show the config of this LPT */
1330 BOOL fEnabled;
1331 lpt->COMGETTER(Enabled)(&fEnabled);
1332 if (!fEnabled)
1333 {
1334 if (details == VMINFO_MACHINEREADABLE)
1335 RTPrintf("lpt%d=\"off\"\n", currentLPT + 1);
1336 else
1337 RTPrintf("LPT %d: disabled\n", currentLPT + 1);
1338 }
1339 else
1340 {
1341 ULONG ulIRQ, ulIOBase;
1342 Bstr path;
1343 lpt->COMGETTER(IRQ)(&ulIRQ);
1344 lpt->COMGETTER(IOBase)(&ulIOBase);
1345 lpt->COMGETTER(Path)(path.asOutParam());
1346
1347 if (details == VMINFO_MACHINEREADABLE)
1348 RTPrintf("lpt%d=\"%#06x,%d\"\n", currentLPT + 1,
1349 ulIOBase, ulIRQ);
1350 else
1351 RTPrintf("LPT %d: I/O base: %#06x, IRQ: %d",
1352 currentLPT + 1, ulIOBase, ulIRQ);
1353 if (details == VMINFO_MACHINEREADABLE)
1354 RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1,
1355 path.raw());
1356 else
1357 RTPrintf(", attached to device '%ls'\n", path.raw());
1358 }
1359 }
1360 }
1361
1362 ComPtr<IAudioAdapter> AudioAdapter;
1363 rc = machine->COMGETTER(AudioAdapter)(AudioAdapter.asOutParam());
1364 if (SUCCEEDED(rc))
1365 {
1366 const char *pszDrv = "Unknown";
1367 const char *pszCtrl = "Unknown";
1368 BOOL fEnabled;
1369 rc = AudioAdapter->COMGETTER(Enabled)(&fEnabled);
1370 if (SUCCEEDED(rc) && fEnabled)
1371 {
1372 AudioDriverType_T enmDrvType;
1373 rc = AudioAdapter->COMGETTER(AudioDriver)(&enmDrvType);
1374 switch (enmDrvType)
1375 {
1376 case AudioDriverType_Null:
1377 if (details == VMINFO_MACHINEREADABLE)
1378 pszDrv = "null";
1379 else
1380 pszDrv = "Null";
1381 break;
1382 case AudioDriverType_WinMM:
1383 if (details == VMINFO_MACHINEREADABLE)
1384 pszDrv = "winmm";
1385 else
1386 pszDrv = "WINMM";
1387 break;
1388 case AudioDriverType_DirectSound:
1389 if (details == VMINFO_MACHINEREADABLE)
1390 pszDrv = "dsound";
1391 else
1392 pszDrv = "DSOUND";
1393 break;
1394 case AudioDriverType_OSS:
1395 if (details == VMINFO_MACHINEREADABLE)
1396 pszDrv = "oss";
1397 else
1398 pszDrv = "OSS";
1399 break;
1400 case AudioDriverType_ALSA:
1401 if (details == VMINFO_MACHINEREADABLE)
1402 pszDrv = "alsa";
1403 else
1404 pszDrv = "ALSA";
1405 break;
1406 case AudioDriverType_Pulse:
1407 if (details == VMINFO_MACHINEREADABLE)
1408 pszDrv = "pulse";
1409 else
1410 pszDrv = "PulseAudio";
1411 break;
1412 case AudioDriverType_CoreAudio:
1413 if (details == VMINFO_MACHINEREADABLE)
1414 pszDrv = "coreaudio";
1415 else
1416 pszDrv = "CoreAudio";
1417 break;
1418 case AudioDriverType_SolAudio:
1419 if (details == VMINFO_MACHINEREADABLE)
1420 pszDrv = "solaudio";
1421 else
1422 pszDrv = "SolAudio";
1423 break;
1424 default:
1425 if (details == VMINFO_MACHINEREADABLE)
1426 pszDrv = "unknown";
1427 break;
1428 }
1429 AudioControllerType_T enmCtrlType;
1430 rc = AudioAdapter->COMGETTER(AudioController)(&enmCtrlType);
1431 switch (enmCtrlType)
1432 {
1433 case AudioControllerType_AC97:
1434 if (details == VMINFO_MACHINEREADABLE)
1435 pszCtrl = "ac97";
1436 else
1437 pszCtrl = "AC97";
1438 break;
1439 case AudioControllerType_SB16:
1440 if (details == VMINFO_MACHINEREADABLE)
1441 pszCtrl = "sb16";
1442 else
1443 pszCtrl = "SB16";
1444 break;
1445 case AudioControllerType_HDA:
1446 if (details == VMINFO_MACHINEREADABLE)
1447 pszCtrl = "hda";
1448 else
1449 pszCtrl = "HDA";
1450 break;
1451 }
1452 }
1453 else
1454 fEnabled = FALSE;
1455 if (details == VMINFO_MACHINEREADABLE)
1456 {
1457 if (fEnabled)
1458 RTPrintf("audio=\"%s\"\n", pszDrv);
1459 else
1460 RTPrintf("audio=\"none\"\n");
1461 }
1462 else
1463 {
1464 RTPrintf("Audio: %s",
1465 fEnabled ? "enabled" : "disabled");
1466 if (fEnabled)
1467 RTPrintf(" (Driver: %s, Controller: %s)",
1468 pszDrv, pszCtrl);
1469 RTPrintf("\n");
1470 }
1471 }
1472
1473 /* Shared clipboard */
1474 {
1475 const char *psz = "Unknown";
1476 ClipboardMode_T enmMode;
1477 rc = machine->COMGETTER(ClipboardMode)(&enmMode);
1478 switch (enmMode)
1479 {
1480 case ClipboardMode_Disabled:
1481 if (details == VMINFO_MACHINEREADABLE)
1482 psz = "disabled";
1483 else
1484 psz = "disabled";
1485 break;
1486 case ClipboardMode_HostToGuest:
1487 if (details == VMINFO_MACHINEREADABLE)
1488 psz = "hosttoguest";
1489 else
1490 psz = "HostToGuest";
1491 break;
1492 case ClipboardMode_GuestToHost:
1493 if (details == VMINFO_MACHINEREADABLE)
1494 psz = "guesttohost";
1495 else
1496 psz = "GuestToHost";
1497 break;
1498 case ClipboardMode_Bidirectional:
1499 if (details == VMINFO_MACHINEREADABLE)
1500 psz = "bidirectional";
1501 else
1502 psz = "Bidirectional";
1503 break;
1504 default:
1505 if (details == VMINFO_MACHINEREADABLE)
1506 psz = "unknown";
1507 break;
1508 }
1509 if (details == VMINFO_MACHINEREADABLE)
1510 RTPrintf("clipboard=\"%s\"\n", psz);
1511 else
1512 RTPrintf("Clipboard Mode: %s\n", psz);
1513 }
1514
1515 /* Drag'n'drop */
1516 {
1517 const char *psz = "Unknown";
1518 DragAndDropMode_T enmMode;
1519 rc = machine->COMGETTER(DragAndDropMode)(&enmMode);
1520 switch (enmMode)
1521 {
1522 case DragAndDropMode_Disabled:
1523 if (details == VMINFO_MACHINEREADABLE)
1524 psz = "disabled";
1525 else
1526 psz = "disabled";
1527 break;
1528 case DragAndDropMode_HostToGuest:
1529 if (details == VMINFO_MACHINEREADABLE)
1530 psz = "hosttoguest";
1531 else
1532 psz = "HostToGuest";
1533 break;
1534 case DragAndDropMode_GuestToHost:
1535 if (details == VMINFO_MACHINEREADABLE)
1536 psz = "guesttohost";
1537 else
1538 psz = "GuestToHost";
1539 break;
1540 case DragAndDropMode_Bidirectional:
1541 if (details == VMINFO_MACHINEREADABLE)
1542 psz = "bidirectional";
1543 else
1544 psz = "Bidirectional";
1545 break;
1546 default:
1547 if (details == VMINFO_MACHINEREADABLE)
1548 psz = "unknown";
1549 break;
1550 }
1551 if (details == VMINFO_MACHINEREADABLE)
1552 RTPrintf("draganddrop=\"%s\"\n", psz);
1553 else
1554 RTPrintf("Drag'n'drop Mode: %s\n", psz);
1555 }
1556
1557 if (console)
1558 {
1559 do
1560 {
1561 ComPtr<IDisplay> display;
1562 rc = console->COMGETTER(Display)(display.asOutParam());
1563 if (rc == E_ACCESSDENIED || display.isNull())
1564 break; /* VM not powered up */
1565 if (FAILED(rc))
1566 {
1567 com::GlueHandleComError(console, "COMGETTER(Display)(display.asOutParam())", rc, __FILE__, __LINE__);
1568 return rc;
1569 }
1570 ULONG xRes, yRes, bpp;
1571 rc = display->GetScreenResolution(0, &xRes, &yRes, &bpp);
1572 if (rc == E_ACCESSDENIED)
1573 break; /* VM not powered up */
1574 if (FAILED(rc))
1575 {
1576 com::ErrorInfo info(display, COM_IIDOF(IDisplay));
1577 GluePrintErrorInfo(info);
1578 return rc;
1579 }
1580 if (details == VMINFO_MACHINEREADABLE)
1581 RTPrintf("VideoMode=\"%d,%d,%d\"\n", xRes, yRes, bpp);
1582 else
1583 RTPrintf("Video mode: %dx%dx%d\n", xRes, yRes, bpp);
1584 }
1585 while (0);
1586 }
1587
1588 /*
1589 * Remote Desktop
1590 */
1591 ComPtr<IVRDEServer> vrdeServer;
1592 rc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam());
1593 if (SUCCEEDED(rc) && vrdeServer)
1594 {
1595 BOOL fEnabled = false;
1596 vrdeServer->COMGETTER(Enabled)(&fEnabled);
1597 if (fEnabled)
1598 {
1599 LONG currentPort = -1;
1600 Bstr ports;
1601 vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam());
1602 Bstr address;
1603 vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam());
1604 BOOL fMultiCon;
1605 vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
1606 BOOL fReuseCon;
1607 vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon);
1608 Bstr videoChannel;
1609 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam());
1610 BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0)
1611 || (videoChannel == "1");
1612 Bstr videoChannelQuality;
1613 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam());
1614 AuthType_T authType;
1615 const char *strAuthType;
1616 vrdeServer->COMGETTER(AuthType)(&authType);
1617 switch (authType)
1618 {
1619 case AuthType_Null:
1620 strAuthType = "null";
1621 break;
1622 case AuthType_External:
1623 strAuthType = "external";
1624 break;
1625 case AuthType_Guest:
1626 strAuthType = "guest";
1627 break;
1628 default:
1629 strAuthType = "unknown";
1630 break;
1631 }
1632 if (console)
1633 {
1634 ComPtr<IVRDEServerInfo> vrdeServerInfo;
1635 CHECK_ERROR_RET(console, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
1636 if (!vrdeServerInfo.isNull())
1637 {
1638 rc = vrdeServerInfo->COMGETTER(Port)(&currentPort);
1639 if (rc == E_ACCESSDENIED)
1640 {
1641 currentPort = -1; /* VM not powered up */
1642 }
1643 if (FAILED(rc))
1644 {
1645 com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo));
1646 GluePrintErrorInfo(info);
1647 return rc;
1648 }
1649 }
1650 }
1651 if (details == VMINFO_MACHINEREADABLE)
1652 {
1653 RTPrintf("vrde=\"on\"\n");
1654 RTPrintf("vrdeport=%d\n", currentPort);
1655 RTPrintf("vrdeports=\"%ls\"\n", ports.raw());
1656 RTPrintf("vrdeaddress=\"%ls\"\n", address.raw());
1657 RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType);
1658 RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off");
1659 RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off");
1660 RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off");
1661 if (fVideoChannel)
1662 RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw());
1663 }
1664 else
1665 {
1666 if (address.isEmpty())
1667 address = "0.0.0.0";
1668 RTPrintf("VRDE: enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n", address.raw(), ports.raw(), fMultiCon ? "on" : "off", fReuseCon ? "on" : "off", strAuthType);
1669 if (console && currentPort != -1 && currentPort != 0)
1670 RTPrintf("VRDE port: %d\n", currentPort);
1671 if (fVideoChannel)
1672 RTPrintf("Video redirection: enabled (Quality %ls)\n", videoChannelQuality.raw());
1673 else
1674 RTPrintf("Video redirection: disabled\n");
1675 }
1676 com::SafeArray<BSTR> aProperties;
1677 if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties))))
1678 {
1679 unsigned i;
1680 for (i = 0; i < aProperties.size(); ++i)
1681 {
1682 Bstr value;
1683 vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam());
1684 if (details == VMINFO_MACHINEREADABLE)
1685 {
1686 if (value.isEmpty())
1687 RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]);
1688 else
1689 RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw());
1690 }
1691 else
1692 {
1693 if (value.isEmpty())
1694 RTPrintf("VRDE property: %-10lS = <not set>\n", aProperties[i]);
1695 else
1696 RTPrintf("VRDE property: %-10lS = \"%ls\"\n", aProperties[i], value.raw());
1697 }
1698 }
1699 }
1700 }
1701 else
1702 {
1703 if (details == VMINFO_MACHINEREADABLE)
1704 RTPrintf("vrde=\"off\"\n");
1705 else
1706 RTPrintf("VRDE: disabled\n");
1707 }
1708 }
1709
1710 /*
1711 * USB.
1712 */
1713 ComPtr<IUSBController> USBCtl;
1714 rc = machine->COMGETTER(USBController)(USBCtl.asOutParam());
1715 if (SUCCEEDED(rc))
1716 {
1717 BOOL fEnabled;
1718 BOOL fEHCIEnabled;
1719 rc = USBCtl->COMGETTER(Enabled)(&fEnabled);
1720 if (FAILED(rc))
1721 fEnabled = false;
1722 if (details == VMINFO_MACHINEREADABLE)
1723 RTPrintf("usb=\"%s\"\n", fEnabled ? "on" : "off");
1724 else
1725 RTPrintf("USB: %s\n", fEnabled ? "enabled" : "disabled");
1726
1727 rc = USBCtl->COMGETTER(EnabledEHCI)(&fEHCIEnabled);
1728 if (FAILED(rc))
1729 fEHCIEnabled = false;
1730 if (details == VMINFO_MACHINEREADABLE)
1731 RTPrintf("ehci=\"%s\"\n", fEHCIEnabled ? "on" : "off");
1732 else
1733 RTPrintf("EHCI: %s\n", fEHCIEnabled ? "enabled" : "disabled");
1734
1735 SafeIfaceArray <IUSBDeviceFilter> Coll;
1736 rc = USBCtl->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll));
1737 if (SUCCEEDED(rc))
1738 {
1739 if (details != VMINFO_MACHINEREADABLE)
1740 RTPrintf("\nUSB Device Filters:\n\n");
1741
1742 if (Coll.size() == 0)
1743 {
1744 if (details != VMINFO_MACHINEREADABLE)
1745 RTPrintf("<none>\n\n");
1746 }
1747 else
1748 {
1749 for (size_t index = 0; index < Coll.size(); ++index)
1750 {
1751 ComPtr<IUSBDeviceFilter> DevPtr = Coll[index];
1752
1753 /* Query info. */
1754
1755 if (details != VMINFO_MACHINEREADABLE)
1756 RTPrintf("Index: %zu\n", index);
1757
1758 BOOL bActive = FALSE;
1759 CHECK_ERROR_RET(DevPtr, COMGETTER(Active)(&bActive), rc);
1760 if (details == VMINFO_MACHINEREADABLE)
1761 RTPrintf("USBFilterActive%zu=\"%s\"\n", index + 1, bActive ? "on" : "off");
1762 else
1763 RTPrintf("Active: %s\n", bActive ? "yes" : "no");
1764
1765 Bstr bstr;
1766 CHECK_ERROR_RET(DevPtr, COMGETTER(Name)(bstr.asOutParam()), rc);
1767 if (details == VMINFO_MACHINEREADABLE)
1768 RTPrintf("USBFilterName%zu=\"%ls\"\n", index + 1, bstr.raw());
1769 else
1770 RTPrintf("Name: %ls\n", bstr.raw());
1771 CHECK_ERROR_RET(DevPtr, COMGETTER(VendorId)(bstr.asOutParam()), rc);
1772 if (details == VMINFO_MACHINEREADABLE)
1773 RTPrintf("USBFilterVendorId%zu=\"%ls\"\n", index + 1, bstr.raw());
1774 else
1775 RTPrintf("VendorId: %ls\n", bstr.raw());
1776 CHECK_ERROR_RET(DevPtr, COMGETTER(ProductId)(bstr.asOutParam()), rc);
1777 if (details == VMINFO_MACHINEREADABLE)
1778 RTPrintf("USBFilterProductId%zu=\"%ls\"\n", index + 1, bstr.raw());
1779 else
1780 RTPrintf("ProductId: %ls\n", bstr.raw());
1781 CHECK_ERROR_RET(DevPtr, COMGETTER(Revision)(bstr.asOutParam()), rc);
1782 if (details == VMINFO_MACHINEREADABLE)
1783 RTPrintf("USBFilterRevision%zu=\"%ls\"\n", index + 1, bstr.raw());
1784 else
1785 RTPrintf("Revision: %ls\n", bstr.raw());
1786 CHECK_ERROR_RET(DevPtr, COMGETTER(Manufacturer)(bstr.asOutParam()), rc);
1787 if (details == VMINFO_MACHINEREADABLE)
1788 RTPrintf("USBFilterManufacturer%zu=\"%ls\"\n", index + 1, bstr.raw());
1789 else
1790 RTPrintf("Manufacturer: %ls\n", bstr.raw());
1791 CHECK_ERROR_RET(DevPtr, COMGETTER(Product)(bstr.asOutParam()), rc);
1792 if (details == VMINFO_MACHINEREADABLE)
1793 RTPrintf("USBFilterProduct%zu=\"%ls\"\n", index + 1, bstr.raw());
1794 else
1795 RTPrintf("Product: %ls\n", bstr.raw());
1796 CHECK_ERROR_RET(DevPtr, COMGETTER(Remote)(bstr.asOutParam()), rc);
1797 if (details == VMINFO_MACHINEREADABLE)
1798 RTPrintf("USBFilterRemote%zu=\"%ls\"\n", index + 1, bstr.raw());
1799 else
1800 RTPrintf("Remote: %ls\n", bstr.raw());
1801 CHECK_ERROR_RET(DevPtr, COMGETTER(SerialNumber)(bstr.asOutParam()), rc);
1802 if (details == VMINFO_MACHINEREADABLE)
1803 RTPrintf("USBFilterSerialNumber%zu=\"%ls\"\n", index + 1, bstr.raw());
1804 else
1805 RTPrintf("Serial Number: %ls\n", bstr.raw());
1806 if (details != VMINFO_MACHINEREADABLE)
1807 {
1808 ULONG fMaskedIfs;
1809 CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), rc);
1810 if (fMaskedIfs)
1811 RTPrintf("Masked Interfaces: %#010x\n", fMaskedIfs);
1812 RTPrintf("\n");
1813 }
1814 }
1815 }
1816 }
1817
1818 if (console)
1819 {
1820 /* scope */
1821 {
1822 if (details != VMINFO_MACHINEREADABLE)
1823 RTPrintf("Available remote USB devices:\n\n");
1824
1825 SafeIfaceArray <IHostUSBDevice> coll;
1826 CHECK_ERROR_RET(console, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), rc);
1827
1828 if (coll.size() == 0)
1829 {
1830 if (details != VMINFO_MACHINEREADABLE)
1831 RTPrintf("<none>\n\n");
1832 }
1833 else
1834 {
1835 for (size_t index = 0; index < coll.size(); ++index)
1836 {
1837 ComPtr <IHostUSBDevice> dev = coll[index];
1838
1839 /* Query info. */
1840 Bstr id;
1841 CHECK_ERROR_RET(dev, COMGETTER(Id)(id.asOutParam()), rc);
1842 USHORT usVendorId;
1843 CHECK_ERROR_RET(dev, COMGETTER(VendorId)(&usVendorId), rc);
1844 USHORT usProductId;
1845 CHECK_ERROR_RET(dev, COMGETTER(ProductId)(&usProductId), rc);
1846 USHORT bcdRevision;
1847 CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), rc);
1848
1849 if (details == VMINFO_MACHINEREADABLE)
1850 RTPrintf("USBRemoteUUID%zu=\"%s\"\n"
1851 "USBRemoteVendorId%zu=\"%#06x\"\n"
1852 "USBRemoteProductId%zu=\"%#06x\"\n"
1853 "USBRemoteRevision%zu=\"%#04x%02x\"\n",
1854 index + 1, Utf8Str(id).c_str(),
1855 index + 1, usVendorId,
1856 index + 1, usProductId,
1857 index + 1, bcdRevision >> 8, bcdRevision & 0xff);
1858 else
1859 RTPrintf("UUID: %s\n"
1860 "VendorId: %#06x (%04X)\n"
1861 "ProductId: %#06x (%04X)\n"
1862 "Revision: %u.%u (%02u%02u)\n",
1863 Utf8Str(id).c_str(),
1864 usVendorId, usVendorId, usProductId, usProductId,
1865 bcdRevision >> 8, bcdRevision & 0xff,
1866 bcdRevision >> 8, bcdRevision & 0xff);
1867
1868 /* optional stuff. */
1869 Bstr bstr;
1870 CHECK_ERROR_RET(dev, COMGETTER(Manufacturer)(bstr.asOutParam()), rc);
1871 if (!bstr.isEmpty())
1872 {
1873 if (details == VMINFO_MACHINEREADABLE)
1874 RTPrintf("USBRemoteManufacturer%zu=\"%ls\"\n", index + 1, bstr.raw());
1875 else
1876 RTPrintf("Manufacturer: %ls\n", bstr.raw());
1877 }
1878 CHECK_ERROR_RET(dev, COMGETTER(Product)(bstr.asOutParam()), rc);
1879 if (!bstr.isEmpty())
1880 {
1881 if (details == VMINFO_MACHINEREADABLE)
1882 RTPrintf("USBRemoteProduct%zu=\"%ls\"\n", index + 1, bstr.raw());
1883 else
1884 RTPrintf("Product: %ls\n", bstr.raw());
1885 }
1886 CHECK_ERROR_RET(dev, COMGETTER(SerialNumber)(bstr.asOutParam()), rc);
1887 if (!bstr.isEmpty())
1888 {
1889 if (details == VMINFO_MACHINEREADABLE)
1890 RTPrintf("USBRemoteSerialNumber%zu=\"%ls\"\n", index + 1, bstr.raw());
1891 else
1892 RTPrintf("SerialNumber: %ls\n", bstr.raw());
1893 }
1894 CHECK_ERROR_RET(dev, COMGETTER(Address)(bstr.asOutParam()), rc);
1895 if (!bstr.isEmpty())
1896 {
1897 if (details == VMINFO_MACHINEREADABLE)
1898 RTPrintf("USBRemoteAddress%zu=\"%ls\"\n", index + 1, bstr.raw());
1899 else
1900 RTPrintf("Address: %ls\n", bstr.raw());
1901 }
1902
1903 if (details != VMINFO_MACHINEREADABLE)
1904 RTPrintf("\n");
1905 }
1906 }
1907 }
1908
1909 /* scope */
1910 {
1911 if (details != VMINFO_MACHINEREADABLE)
1912 RTPrintf("Currently Attached USB Devices:\n\n");
1913
1914 SafeIfaceArray <IUSBDevice> coll;
1915 CHECK_ERROR_RET(console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), rc);
1916
1917 if (coll.size() == 0)
1918 {
1919 if (details != VMINFO_MACHINEREADABLE)
1920 RTPrintf("<none>\n\n");
1921 }
1922 else
1923 {
1924 for (size_t index = 0; index < coll.size(); ++index)
1925 {
1926 ComPtr <IUSBDevice> dev = coll[index];
1927
1928 /* Query info. */
1929 Bstr id;
1930 CHECK_ERROR_RET(dev, COMGETTER(Id)(id.asOutParam()), rc);
1931 USHORT usVendorId;
1932 CHECK_ERROR_RET(dev, COMGETTER(VendorId)(&usVendorId), rc);
1933 USHORT usProductId;
1934 CHECK_ERROR_RET(dev, COMGETTER(ProductId)(&usProductId), rc);
1935 USHORT bcdRevision;
1936 CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), rc);
1937
1938 if (details == VMINFO_MACHINEREADABLE)
1939 RTPrintf("USBAttachedUUID%zu=\"%s\"\n"
1940 "USBAttachedVendorId%zu=\"%#06x\"\n"
1941 "USBAttachedProductId%zu=\"%#06x\"\n"
1942 "USBAttachedRevision%zu=\"%#04x%02x\"\n",
1943 index + 1, Utf8Str(id).c_str(),
1944 index + 1, usVendorId,
1945 index + 1, usProductId,
1946 index + 1, bcdRevision >> 8, bcdRevision & 0xff);
1947 else
1948 RTPrintf("UUID: %s\n"
1949 "VendorId: %#06x (%04X)\n"
1950 "ProductId: %#06x (%04X)\n"
1951 "Revision: %u.%u (%02u%02u)\n",
1952 Utf8Str(id).c_str(),
1953 usVendorId, usVendorId, usProductId, usProductId,
1954 bcdRevision >> 8, bcdRevision & 0xff,
1955 bcdRevision >> 8, bcdRevision & 0xff);
1956
1957 /* optional stuff. */
1958 Bstr bstr;
1959 CHECK_ERROR_RET(dev, COMGETTER(Manufacturer)(bstr.asOutParam()), rc);
1960 if (!bstr.isEmpty())
1961 {
1962 if (details == VMINFO_MACHINEREADABLE)
1963 RTPrintf("USBAttachedManufacturer%zu=\"%ls\"\n", index + 1, bstr.raw());
1964 else
1965 RTPrintf("Manufacturer: %ls\n", bstr.raw());
1966 }
1967 CHECK_ERROR_RET(dev, COMGETTER(Product)(bstr.asOutParam()), rc);
1968 if (!bstr.isEmpty())
1969 {
1970 if (details == VMINFO_MACHINEREADABLE)
1971 RTPrintf("USBAttachedProduct%zu=\"%ls\"\n", index + 1, bstr.raw());
1972 else
1973 RTPrintf("Product: %ls\n", bstr.raw());
1974 }
1975 CHECK_ERROR_RET(dev, COMGETTER(SerialNumber)(bstr.asOutParam()), rc);
1976 if (!bstr.isEmpty())
1977 {
1978 if (details == VMINFO_MACHINEREADABLE)
1979 RTPrintf("USBAttachedSerialNumber%zu=\"%ls\"\n", index + 1, bstr.raw());
1980 else
1981 RTPrintf("SerialNumber: %ls\n", bstr.raw());
1982 }
1983 CHECK_ERROR_RET(dev, COMGETTER(Address)(bstr.asOutParam()), rc);
1984 if (!bstr.isEmpty())
1985 {
1986 if (details == VMINFO_MACHINEREADABLE)
1987 RTPrintf("USBAttachedAddress%zu=\"%ls\"\n", index + 1, bstr.raw());
1988 else
1989 RTPrintf("Address: %ls\n", bstr.raw());
1990 }
1991
1992 if (details != VMINFO_MACHINEREADABLE)
1993 RTPrintf("\n");
1994 }
1995 }
1996 }
1997 }
1998 } /* USB */
1999
2000#ifdef VBOX_WITH_PCI_PASSTHROUGH
2001 /* Host PCI passthrough devices */
2002 {
2003 SafeIfaceArray <IPCIDeviceAttachment> assignments;
2004 rc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
2005 if (SUCCEEDED(rc))
2006 {
2007 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2008 {
2009 RTPrintf("\nAttached physical PCI devices:\n\n");
2010 }
2011
2012 for (size_t index = 0; index < assignments.size(); ++index)
2013 {
2014 ComPtr<IPCIDeviceAttachment> Assignment = assignments[index];
2015 char szHostPCIAddress[32], szGuestPCIAddress[32];
2016 LONG iHostPCIAddress = -1, iGuestPCIAddress = -1;
2017 Bstr DevName;
2018
2019 Assignment->COMGETTER(Name)(DevName.asOutParam());
2020 Assignment->COMGETTER(HostAddress)(&iHostPCIAddress);
2021 Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress);
2022 PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress));
2023 PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress));
2024
2025 if (details == VMINFO_MACHINEREADABLE)
2026 RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress);
2027 else
2028 RTPrintf(" Host device %ls at %s attached as %s\n", DevName.raw(), szHostPCIAddress, szGuestPCIAddress);
2029 }
2030
2031 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2032 {
2033 RTPrintf("\n");
2034 }
2035 }
2036 }
2037 /* Host PCI passthrough devices */
2038#endif
2039
2040 /*
2041 * Bandwidth groups
2042 */
2043 if (details != VMINFO_MACHINEREADABLE)
2044 RTPrintf("Bandwidth groups: ");
2045 {
2046 ComPtr<IBandwidthControl> bwCtrl;
2047 CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), rc);
2048
2049 rc = showBandwidthGroups(bwCtrl, details);
2050 }
2051
2052
2053 /*
2054 * Shared folders
2055 */
2056 if (details != VMINFO_MACHINEREADABLE)
2057 RTPrintf("Shared folders: ");
2058 uint32_t numSharedFolders = 0;
2059#if 0 // not yet implemented
2060 /* globally shared folders first */
2061 {
2062 SafeIfaceArray <ISharedFolder> sfColl;
2063 CHECK_ERROR_RET(virtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(sfColl)), rc);
2064 for (size_t i = 0; i < sfColl.size(); ++i)
2065 {
2066 ComPtr<ISharedFolder> sf = sfColl[i];
2067 Bstr name, hostPath;
2068 sf->COMGETTER(Name)(name.asOutParam());
2069 sf->COMGETTER(HostPath)(hostPath.asOutParam());
2070 RTPrintf("Name: '%ls', Host path: '%ls' (global mapping)\n", name.raw(), hostPath.raw());
2071 ++numSharedFolders;
2072 }
2073 }
2074#endif
2075 /* now VM mappings */
2076 {
2077 com::SafeIfaceArray <ISharedFolder> folders;
2078
2079 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2080
2081 for (size_t i = 0; i < folders.size(); ++i)
2082 {
2083 ComPtr <ISharedFolder> sf = folders[i];
2084
2085 Bstr name, hostPath;
2086 BOOL writable;
2087 sf->COMGETTER(Name)(name.asOutParam());
2088 sf->COMGETTER(HostPath)(hostPath.asOutParam());
2089 sf->COMGETTER(Writable)(&writable);
2090 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
2091 RTPrintf("\n\n");
2092 if (details == VMINFO_MACHINEREADABLE)
2093 {
2094 RTPrintf("SharedFolderNameMachineMapping%zu=\"%ls\"\n", i + 1,
2095 name.raw());
2096 RTPrintf("SharedFolderPathMachineMapping%zu=\"%ls\"\n", i + 1,
2097 hostPath.raw());
2098 }
2099 else
2100 RTPrintf("Name: '%ls', Host path: '%ls' (machine mapping), %s\n",
2101 name.raw(), hostPath.raw(), writable ? "writable" : "readonly");
2102 ++numSharedFolders;
2103 }
2104 }
2105 /* transient mappings */
2106 if (console)
2107 {
2108 com::SafeIfaceArray <ISharedFolder> folders;
2109
2110 CHECK_ERROR_RET(console, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2111
2112 for (size_t i = 0; i < folders.size(); ++i)
2113 {
2114 ComPtr <ISharedFolder> sf = folders[i];
2115
2116 Bstr name, hostPath;
2117 sf->COMGETTER(Name)(name.asOutParam());
2118 sf->COMGETTER(HostPath)(hostPath.asOutParam());
2119 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
2120 RTPrintf("\n\n");
2121 if (details == VMINFO_MACHINEREADABLE)
2122 {
2123 RTPrintf("SharedFolderNameTransientMapping%zu=\"%ls\"\n", i + 1,
2124 name.raw());
2125 RTPrintf("SharedFolderPathTransientMapping%zu=\"%ls\"\n", i + 1,
2126 hostPath.raw());
2127 }
2128 else
2129 RTPrintf("Name: '%ls', Host path: '%ls' (transient mapping)\n", name.raw(), hostPath.raw());
2130 ++numSharedFolders;
2131 }
2132 }
2133 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
2134 RTPrintf("<none>\n");
2135 if (details != VMINFO_MACHINEREADABLE)
2136 RTPrintf("\n");
2137
2138 if (console)
2139 {
2140 /*
2141 * Live VRDE info.
2142 */
2143 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2144 CHECK_ERROR_RET(console, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2145 BOOL Active = FALSE;
2146 ULONG NumberOfClients = 0;
2147 LONG64 BeginTime = 0;
2148 LONG64 EndTime = 0;
2149 LONG64 BytesSent = 0;
2150 LONG64 BytesSentTotal = 0;
2151 LONG64 BytesReceived = 0;
2152 LONG64 BytesReceivedTotal = 0;
2153 Bstr User;
2154 Bstr Domain;
2155 Bstr ClientName;
2156 Bstr ClientIP;
2157 ULONG ClientVersion = 0;
2158 ULONG EncryptionStyle = 0;
2159
2160 if (!vrdeServerInfo.isNull())
2161 {
2162 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&Active), rc);
2163 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&NumberOfClients), rc);
2164 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), rc);
2165 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), rc);
2166 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), rc);
2167 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), rc);
2168 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), rc);
2169 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), rc);
2170 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), rc);
2171 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), rc);
2172 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), rc);
2173 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), rc);
2174 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), rc);
2175 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), rc);
2176 }
2177
2178 if (details == VMINFO_MACHINEREADABLE)
2179 RTPrintf("VRDEActiveConnection=\"%s\"\n", Active ? "on": "off");
2180 else
2181 RTPrintf("VRDE Connection: %s\n", Active? "active": "not active");
2182
2183 if (details == VMINFO_MACHINEREADABLE)
2184 RTPrintf("VRDEClients=%d\n", NumberOfClients);
2185 else
2186 RTPrintf("Clients so far: %d\n", NumberOfClients);
2187
2188 if (NumberOfClients > 0)
2189 {
2190 char timestr[128];
2191
2192 if (Active)
2193 {
2194 makeTimeStr(timestr, sizeof(timestr), BeginTime);
2195 if (details == VMINFO_MACHINEREADABLE)
2196 RTPrintf("VRDEStartTime=\"%s\"\n", timestr);
2197 else
2198 RTPrintf("Start time: %s\n", timestr);
2199 }
2200 else
2201 {
2202 makeTimeStr(timestr, sizeof(timestr), BeginTime);
2203 if (details == VMINFO_MACHINEREADABLE)
2204 RTPrintf("VRDELastStartTime=\"%s\"\n", timestr);
2205 else
2206 RTPrintf("Last started: %s\n", timestr);
2207 makeTimeStr(timestr, sizeof(timestr), EndTime);
2208 if (details == VMINFO_MACHINEREADABLE)
2209 RTPrintf("VRDELastEndTime=\"%s\"\n", timestr);
2210 else
2211 RTPrintf("Last ended: %s\n", timestr);
2212 }
2213
2214 int64_t ThroughputSend = 0;
2215 int64_t ThroughputReceive = 0;
2216 if (EndTime != BeginTime)
2217 {
2218 ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime);
2219 ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime);
2220 }
2221
2222 if (details == VMINFO_MACHINEREADABLE)
2223 {
2224 RTPrintf("VRDEBytesSent=%lld\n", BytesSent);
2225 RTPrintf("VRDEThroughputSend=%lld\n", ThroughputSend);
2226 RTPrintf("VRDEBytesSentTotal=%lld\n", BytesSentTotal);
2227
2228 RTPrintf("VRDEBytesReceived=%lld\n", BytesReceived);
2229 RTPrintf("VRDEThroughputReceive=%lld\n", ThroughputReceive);
2230 RTPrintf("VRDEBytesReceivedTotal=%lld\n", BytesReceivedTotal);
2231 }
2232 else
2233 {
2234 RTPrintf("Sent: %lld Bytes\n", BytesSent);
2235 RTPrintf("Average speed: %lld B/s\n", ThroughputSend);
2236 RTPrintf("Sent total: %lld Bytes\n", BytesSentTotal);
2237
2238 RTPrintf("Received: %lld Bytes\n", BytesReceived);
2239 RTPrintf("Speed: %lld B/s\n", ThroughputReceive);
2240 RTPrintf("Received total: %lld Bytes\n", BytesReceivedTotal);
2241 }
2242
2243 if (Active)
2244 {
2245 if (details == VMINFO_MACHINEREADABLE)
2246 {
2247 RTPrintf("VRDEUserName=\"%ls\"\n", User.raw());
2248 RTPrintf("VRDEDomain=\"%ls\"\n", Domain.raw());
2249 RTPrintf("VRDEClientName=\"%ls\"\n", ClientName.raw());
2250 RTPrintf("VRDEClientIP=\"%ls\"\n", ClientIP.raw());
2251 RTPrintf("VRDEClientVersion=%d\n", ClientVersion);
2252 RTPrintf("VRDEEncryption=\"%s\"\n", EncryptionStyle == 0? "RDP4": "RDP5 (X.509)");
2253 }
2254 else
2255 {
2256 RTPrintf("User name: %ls\n", User.raw());
2257 RTPrintf("Domain: %ls\n", Domain.raw());
2258 RTPrintf("Client name: %ls\n", ClientName.raw());
2259 RTPrintf("Client IP: %ls\n", ClientIP.raw());
2260 RTPrintf("Client version: %d\n", ClientVersion);
2261 RTPrintf("Encryption: %s\n", EncryptionStyle == 0? "RDP4": "RDP5 (X.509)");
2262 }
2263 }
2264 }
2265
2266 if (details != VMINFO_MACHINEREADABLE)
2267 RTPrintf("\n");
2268 }
2269
2270 if ( details == VMINFO_STANDARD
2271 || details == VMINFO_FULL
2272 || details == VMINFO_MACHINEREADABLE)
2273 {
2274 Bstr description;
2275 machine->COMGETTER(Description)(description.asOutParam());
2276 if (!description.isEmpty())
2277 {
2278 if (details == VMINFO_MACHINEREADABLE)
2279 RTPrintf("description=\"%ls\"\n", description.raw());
2280 else
2281 RTPrintf("Description:\n%ls\n", description.raw());
2282 }
2283 }
2284
2285
2286 if (details != VMINFO_MACHINEREADABLE)
2287 RTPrintf("Guest:\n\n");
2288
2289 ULONG guestVal;
2290 rc = machine->COMGETTER(MemoryBalloonSize)(&guestVal);
2291 if (SUCCEEDED(rc))
2292 {
2293 if (details == VMINFO_MACHINEREADABLE)
2294 RTPrintf("GuestMemoryBalloon=%d\n", guestVal);
2295 else
2296 RTPrintf("Configured memory balloon size: %d MB\n", guestVal);
2297 }
2298
2299 if (console)
2300 {
2301 ComPtr<IGuest> guest;
2302 rc = console->COMGETTER(Guest)(guest.asOutParam());
2303 if (SUCCEEDED(rc) && !guest.isNull())
2304 {
2305 Bstr guestString;
2306 rc = guest->COMGETTER(OSTypeId)(guestString.asOutParam());
2307 if ( SUCCEEDED(rc)
2308 && !guestString.isEmpty())
2309 {
2310 if (details == VMINFO_MACHINEREADABLE)
2311 RTPrintf("GuestOSType=\"%ls\"\n", guestString.raw());
2312 else
2313 RTPrintf("OS type: %ls\n", guestString.raw());
2314 }
2315
2316 AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */
2317 rc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel);
2318 if (SUCCEEDED(rc))
2319 {
2320 if (details == VMINFO_MACHINEREADABLE)
2321 RTPrintf("GuestAdditionsRunLevel=%u\n", guestRunLevel);
2322 else
2323 RTPrintf("Additions run level: %u\n", guestRunLevel);
2324 }
2325
2326 rc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam());
2327 if ( SUCCEEDED(rc)
2328 && !guestString.isEmpty())
2329 {
2330 ULONG uRevision;
2331 rc = guest->COMGETTER(AdditionsRevision)(&uRevision);
2332 if (FAILED(rc))
2333 uRevision = 0;
2334
2335 if (details == VMINFO_MACHINEREADABLE)
2336 RTPrintf("GuestAdditionsVersion=\"%ls r%u\"\n", guestString.raw(), uRevision);
2337 else
2338 RTPrintf("Additions version: %ls r%u\n\n", guestString.raw(), uRevision);
2339 }
2340
2341 if (details != VMINFO_MACHINEREADABLE)
2342 RTPrintf("\nGuest Facilities:\n\n");
2343
2344 /* Print information about known Guest Additions facilities: */
2345 SafeIfaceArray <IAdditionsFacility> collFac;
2346 CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), rc);
2347 LONG64 lLastUpdatedMS;
2348 char szLastUpdated[32];
2349 AdditionsFacilityStatus_T curStatus;
2350 for (size_t index = 0; index < collFac.size(); ++index)
2351 {
2352 ComPtr<IAdditionsFacility> fac = collFac[index];
2353 if (fac)
2354 {
2355 CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), rc);
2356 if (!guestString.isEmpty())
2357 {
2358 CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), rc);
2359 CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), rc);
2360 if (details == VMINFO_MACHINEREADABLE)
2361 RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n",
2362 guestString.raw(), curStatus, lLastUpdatedMS);
2363 else
2364 {
2365 makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
2366 RTPrintf("Facility \"%ls\": %s (last update: %s)\n",
2367 guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated);
2368 }
2369 }
2370 else
2371 AssertMsgFailed(("Facility with undefined name retrieved!\n"));
2372 }
2373 else
2374 AssertMsgFailed(("Invalid facility returned!\n"));
2375 }
2376 if (!collFac.size() && details != VMINFO_MACHINEREADABLE)
2377 RTPrintf("No active facilities.\n");
2378 }
2379 }
2380
2381 if (details != VMINFO_MACHINEREADABLE)
2382 RTPrintf("\n");
2383
2384 /*
2385 * snapshots
2386 */
2387 ComPtr<ISnapshot> snapshot;
2388 rc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam());
2389 if (SUCCEEDED(rc) && snapshot)
2390 {
2391 ComPtr<ISnapshot> currentSnapshot;
2392 rc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam());
2393 if (SUCCEEDED(rc))
2394 {
2395 if (details != VMINFO_MACHINEREADABLE)
2396 RTPrintf("Snapshots:\n\n");
2397 showSnapshots(snapshot, currentSnapshot, details);
2398 }
2399 }
2400
2401 if (details != VMINFO_MACHINEREADABLE)
2402 RTPrintf("\n");
2403 return S_OK;
2404}
2405
2406#if defined(_MSC_VER)
2407# pragma optimize("", on)
2408#endif
2409
2410static const RTGETOPTDEF g_aShowVMInfoOptions[] =
2411{
2412 { "--details", 'D', RTGETOPT_REQ_NOTHING },
2413 { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated
2414 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
2415 { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated
2416 { "--log", 'l', RTGETOPT_REQ_UINT32 },
2417};
2418
2419int handleShowVMInfo(HandlerArg *a)
2420{
2421 HRESULT rc;
2422 const char *VMNameOrUuid = NULL;
2423 bool fLog = false;
2424 uint32_t uLogIdx = 0;
2425 bool fDetails = false;
2426 bool fMachinereadable = false;
2427
2428 int c;
2429 RTGETOPTUNION ValueUnion;
2430 RTGETOPTSTATE GetState;
2431 // start at 0 because main() has hacked both the argc and argv given to us
2432 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions),
2433 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2434 while ((c = RTGetOpt(&GetState, &ValueUnion)))
2435 {
2436 switch (c)
2437 {
2438 case 'D': // --details
2439 fDetails = true;
2440 break;
2441
2442 case 'M': // --machinereadable
2443 fMachinereadable = true;
2444 break;
2445
2446 case 'l': // --log
2447 fLog = true;
2448 uLogIdx = ValueUnion.u32;
2449 break;
2450
2451 case VINF_GETOPT_NOT_OPTION:
2452 if (!VMNameOrUuid)
2453 VMNameOrUuid = ValueUnion.psz;
2454 else
2455 return errorSyntax(USAGE_SHOWVMINFO, "Invalid parameter '%s'", ValueUnion.psz);
2456 break;
2457
2458 default:
2459 if (c > 0)
2460 {
2461 if (RT_C_IS_PRINT(c))
2462 return errorSyntax(USAGE_SHOWVMINFO, "Invalid option -%c", c);
2463 else
2464 return errorSyntax(USAGE_SHOWVMINFO, "Invalid option case %i", c);
2465 }
2466 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
2467 return errorSyntax(USAGE_SHOWVMINFO, "unknown option: %s\n", ValueUnion.psz);
2468 else if (ValueUnion.pDef)
2469 return errorSyntax(USAGE_SHOWVMINFO, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
2470 else
2471 return errorSyntax(USAGE_SHOWVMINFO, "error: %Rrs", c);
2472 }
2473 }
2474
2475 /* check for required options */
2476 if (!VMNameOrUuid)
2477 return errorSyntax(USAGE_SHOWVMINFO, "VM name or UUID required");
2478
2479 /* try to find the given machine */
2480 ComPtr <IMachine> machine;
2481 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(),
2482 machine.asOutParam()));
2483 if (FAILED(rc))
2484 return 1;
2485
2486 /* Printing the log is exclusive. */
2487 if (fLog && (fMachinereadable || fDetails))
2488 return errorSyntax(USAGE_SHOWVMINFO, "Option --log is exclusive");
2489
2490 if (fLog)
2491 {
2492 ULONG64 uOffset = 0;
2493 SafeArray<BYTE> aLogData;
2494 ULONG cbLogData;
2495 while (true)
2496 {
2497 /* Reset the array */
2498 aLogData.setNull();
2499 /* Fetch a chunk of the log file */
2500 CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, uOffset, _1M,
2501 ComSafeArrayAsOutParam(aLogData)));
2502 cbLogData = aLogData.size();
2503 if (cbLogData == 0)
2504 break;
2505 /* aLogData has a platform dependent line ending, standardize on
2506 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
2507 * Windows. Otherwise we end up with CR/CR/LF on Windows. */
2508 ULONG cbLogDataPrint = cbLogData;
2509 for (BYTE *s = aLogData.raw(), *d = s;
2510 s - aLogData.raw() < (ssize_t)cbLogData;
2511 s++, d++)
2512 {
2513 if (*s == '\r')
2514 {
2515 /* skip over CR, adjust destination */
2516 d--;
2517 cbLogDataPrint--;
2518 }
2519 else if (s != d)
2520 *d = *s;
2521 }
2522 RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint);
2523 uOffset += cbLogData;
2524 }
2525 }
2526 else
2527 {
2528 /* 2nd option can be -details or -argdump */
2529 VMINFO_DETAILS details = VMINFO_NONE;
2530 if (fMachinereadable)
2531 details = VMINFO_MACHINEREADABLE;
2532 else if (fDetails)
2533 details = VMINFO_FULL;
2534 else
2535 details = VMINFO_STANDARD;
2536
2537 ComPtr<IConsole> console;
2538
2539 /* open an existing session for the VM */
2540 rc = machine->LockMachine(a->session, LockType_Shared);
2541 if (SUCCEEDED(rc))
2542 /* get the session machine */
2543 rc = a->session->COMGETTER(Machine)(machine.asOutParam());
2544 if (SUCCEEDED(rc))
2545 /* get the session console */
2546 rc = a->session->COMGETTER(Console)(console.asOutParam());
2547
2548 rc = showVMInfo(a->virtualBox, machine, details, console);
2549
2550 if (console)
2551 a->session->UnlockMachine();
2552 }
2553
2554 return SUCCEEDED(rc) ? 0 : 1;
2555}
2556
2557#endif /* !VBOX_ONLY_DOCS */
2558/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use