VirtualBox

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

Last change on this file since 81299 was 81299, checked in by vboxsync, 5 years ago

Main/Machine+BIOSSettings: simplify NVRAM handling, do everything in backwards c
ompatible way
Frontends/VBoxManage: adapt to API change

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