VirtualBox

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

Last change on this file since 40673 was 40548, checked in by vboxsync, 13 years ago

Frontends/VBoxManage: display parallel port config for "showvminfo"

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