VirtualBox

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

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

showvminfo: Started converting the code into using macros for showing the standard typed properties. Still much to do.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette