VirtualBox

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

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

Main/GraphicsAdapter: Split off a few attributes from Machine interface, which affects quite a few other interfaces.
Frontends/VirtualBox+VBoxManage+VBoxSDL+VBoxShell: Adapt accordingly.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 114.1 KB
Line 
1/* $Id: VBoxManageInfo.cpp 81964 2019-11-18 20:42:02Z 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 ComPtr<IGraphicsAdapter> pGraphicsAdapter;
726 machine->COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam());
727 SHOW_ULONG_PROP(pGraphicsAdapter, VRAMSize, "vram", "VRAM size:", "MB");
728 SHOW_ULONG_PROP( machine, CPUExecutionCap, "cpuexecutioncap", "CPU exec cap:", "%");
729 SHOW_BOOLEAN_PROP( machine, HPETEnabled, "hpet", "HPET:");
730 SHOW_STRING_PROP_MAJ( machine, CPUProfile, "cpu-profile", "CPUProfile:", "host", 6);
731
732 ChipsetType_T chipsetType;
733 CHECK_ERROR2I_RET(machine, COMGETTER(ChipsetType)(&chipsetType), hrcCheck);
734 const char *pszChipsetType;
735 switch (chipsetType)
736 {
737 case ChipsetType_Null: pszChipsetType = "invalid"; break;
738 case ChipsetType_PIIX3: pszChipsetType = "piix3"; break;
739 case ChipsetType_ICH9: pszChipsetType = "ich9"; break;
740 default: AssertFailed(); pszChipsetType = "unknown"; break;
741 }
742 SHOW_UTF8_STRING("chipset", "Chipset:", pszChipsetType);
743
744 FirmwareType_T firmwareType;
745 CHECK_ERROR2I_RET(machine, COMGETTER(FirmwareType)(&firmwareType), hrcCheck);
746 const char *pszFirmwareType;
747 switch (firmwareType)
748 {
749 case FirmwareType_BIOS: pszFirmwareType = "BIOS"; break;
750 case FirmwareType_EFI: pszFirmwareType = "EFI"; break;
751 case FirmwareType_EFI32: pszFirmwareType = "EFI32"; break;
752 case FirmwareType_EFI64: pszFirmwareType = "EFI64"; break;
753 case FirmwareType_EFIDUAL: pszFirmwareType = "EFIDUAL"; break;
754 default: AssertFailed(); pszFirmwareType = "unknown"; break;
755 }
756 SHOW_UTF8_STRING("firmware", "Firmware:", pszFirmwareType);
757
758 SHOW_ULONG_PROP( machine, CPUCount, "cpus", "Number of CPUs:", "");
759 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_PAE, &f), "pae", "PAE:");
760 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_LongMode, &f), "longmode", "Long Mode:");
761 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_TripleFaultReset, &f), "triplefaultreset", "Triple Fault Reset:");
762 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_APIC, &f), "apic", "APIC:");
763 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_X2APIC, &f), "x2apic", "X2APIC:");
764 SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_HWVirt, &f), "nested-hw-virt", "Nested VT-x/AMD-V:");
765 SHOW_ULONG_PROP( machine, CPUIDPortabilityLevel, "cpuid-portability-level", "CPUID Portability Level:", "");
766
767 if (details != VMINFO_MACHINEREADABLE)
768 RTPrintf("%-28s ", "CPUID overrides:");
769 ULONG uOrdinal = 0;
770 for (uOrdinal = 0; uOrdinal < _4K; uOrdinal++)
771 {
772 ULONG uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX;
773 rc = machine->GetCPUIDLeafByOrdinal(uOrdinal, &uLeaf, &uSubLeaf, &uEAX, &uEBX, &uECX, &uEDX);
774 if (SUCCEEDED(rc))
775 {
776 if (details == VMINFO_MACHINEREADABLE)
777 RTPrintf("cpuid=%08x,%08x,%08x,%08x,%08x,%08x", uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX);
778 else
779 {
780 if (!uOrdinal)
781 RTPrintf("Leaf no. EAX EBX ECX EDX\n");
782 RTPrintf("%-28s %08x/%03x %08x %08x %08x %08x\n", "", uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX);
783 }
784 }
785 else
786 {
787 if (rc != E_INVALIDARG)
788 com::GlueHandleComError(machine, "GetCPUIDLeaf", rc, __FILE__, __LINE__);
789 break;
790 }
791 }
792 if (!uOrdinal && details != VMINFO_MACHINEREADABLE)
793 RTPrintf("None\n");
794
795 ComPtr<IBIOSSettings> biosSettings;
796 CHECK_ERROR2I_RET(machine, COMGETTER(BIOSSettings)(biosSettings.asOutParam()), hrcCheck);
797
798 BIOSBootMenuMode_T bootMenuMode;
799 CHECK_ERROR2I_RET(biosSettings, COMGETTER(BootMenuMode)(&bootMenuMode), hrcCheck);
800 const char *pszBootMenu;
801 switch (bootMenuMode)
802 {
803 case BIOSBootMenuMode_Disabled:
804 pszBootMenu = "disabled";
805 break;
806 case BIOSBootMenuMode_MenuOnly:
807 if (details == VMINFO_MACHINEREADABLE)
808 pszBootMenu = "menuonly";
809 else
810 pszBootMenu = "menu only";
811 break;
812 default:
813 if (details == VMINFO_MACHINEREADABLE)
814 pszBootMenu = "messageandmenu";
815 else
816 pszBootMenu = "message and menu";
817 }
818 SHOW_UTF8_STRING("bootmenu", "Boot menu mode:", pszBootMenu);
819
820 ComPtr<ISystemProperties> systemProperties;
821 CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), hrcCheck);
822 ULONG maxBootPosition = 0;
823 CHECK_ERROR2I_RET(systemProperties, COMGETTER(MaxBootPosition)(&maxBootPosition), hrcCheck);
824 for (ULONG i = 1; i <= maxBootPosition; i++)
825 {
826 DeviceType_T bootOrder;
827 CHECK_ERROR2I_RET(machine, GetBootOrder(i, &bootOrder), hrcCheck);
828 const char *pszDevice;
829 if (bootOrder == DeviceType_Floppy)
830 pszDevice = details == VMINFO_MACHINEREADABLE ? "floppy" : "Floppy";
831 else if (bootOrder == DeviceType_DVD)
832 pszDevice = details == VMINFO_MACHINEREADABLE ? "dvd" : "DVD";
833 else if (bootOrder == DeviceType_HardDisk)
834 pszDevice = details == VMINFO_MACHINEREADABLE ? "disk" : "HardDisk";
835 else if (bootOrder == DeviceType_Network)
836 pszDevice = details == VMINFO_MACHINEREADABLE ? "net" : "Network";
837 else if (bootOrder == DeviceType_USB)
838 pszDevice = details == VMINFO_MACHINEREADABLE ? "usb" : "USB";
839 else if (bootOrder == DeviceType_SharedFolder)
840 pszDevice = details == VMINFO_MACHINEREADABLE ? "sharedfolder" : "Shared Folder";
841 else
842 pszDevice = details == VMINFO_MACHINEREADABLE ? "none" : "Not Assigned";
843 SHOW_UTF8_STRING(FmtNm(szNm, "boot%u", i), FmtNm(szNm, "Boot Device %u:", i), pszDevice);
844 }
845
846 SHOW_BOOLEAN_PROP(biosSettings, ACPIEnabled, "acpi", "ACPI:");
847 SHOW_BOOLEAN_PROP(biosSettings, IOAPICEnabled, "ioapic", "IOAPIC:");
848
849 APICMode_T apicMode;
850 CHECK_ERROR2I_RET(biosSettings, COMGETTER(APICMode)(&apicMode), hrcCheck);
851 const char *pszAPIC;
852 switch (apicMode)
853 {
854 case APICMode_Disabled:
855 pszAPIC = "disabled";
856 break;
857 case APICMode_APIC:
858 default:
859 if (details == VMINFO_MACHINEREADABLE)
860 pszAPIC = "apic";
861 else
862 pszAPIC = "APIC";
863 break;
864 case APICMode_X2APIC:
865 if (details == VMINFO_MACHINEREADABLE)
866 pszAPIC = "x2apic";
867 else
868 pszAPIC = "x2APIC";
869 break;
870 }
871 SHOW_UTF8_STRING("biosapic", "BIOS APIC mode:", pszAPIC);
872
873 SHOW_LONG64_PROP(biosSettings, TimeOffset, "biossystemtimeoffset", "Time offset:", "ms");
874 Bstr bstrNVRAMFile;
875 CHECK_ERROR2I_RET(biosSettings, COMGETTER(NonVolatileStorageFile)(bstrNVRAMFile.asOutParam()), hrcCheck);
876 if (bstrNVRAMFile.isNotEmpty())
877 SHOW_BSTR_STRING("BIOS NVRAM File", "BIOS NVRAM File:", bstrNVRAMFile);
878 SHOW_BOOLEAN_PROP_EX(machine, RTCUseUTC, "rtcuseutc", "RTC:", "UTC", "local time");
879 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &f), "hwvirtex", "Hardware Virtualization:");
880 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &f),"nestedpaging", "Nested Paging:");
881 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &f), "largepages", "Large Pages:");
882 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_VPID, &f), "vtxvpid", "VT-x VPID:");
883 SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_UnrestrictedExecution, &f), "vtxux", "VT-x Unrestricted Exec.:");
884
885 ParavirtProvider_T paravirtProvider;
886 CHECK_ERROR2I_RET(machine, COMGETTER(ParavirtProvider)(&paravirtProvider), hrcCheck);
887 const char *pszParavirtProvider = paravirtProviderToString(paravirtProvider, details);
888 SHOW_UTF8_STRING("paravirtprovider", "Paravirt. Provider:", pszParavirtProvider);
889
890 ParavirtProvider_T effParavirtProvider;
891 CHECK_ERROR2I_RET(machine, GetEffectiveParavirtProvider(&effParavirtProvider), hrcCheck);
892 const char *pszEffParavirtProvider = paravirtProviderToString(effParavirtProvider, details);
893 SHOW_UTF8_STRING("effparavirtprovider", "Effective Paravirt. Prov.:", pszEffParavirtProvider);
894
895 Bstr paravirtDebug;
896 CHECK_ERROR2I_RET(machine, COMGETTER(ParavirtDebug)(paravirtDebug.asOutParam()), hrcCheck);
897 if (paravirtDebug.isNotEmpty())
898 SHOW_BSTR_STRING("paravirtdebug", "Paravirt. Debug:", paravirtDebug);
899
900 MachineState_T machineState;
901 CHECK_ERROR2I_RET(machine, COMGETTER(State)(&machineState), hrcCheck);
902 const char *pszState = machineStateToName(machineState, details == VMINFO_MACHINEREADABLE /*=fShort*/);
903
904 LONG64 stateSince;
905 machine->COMGETTER(LastStateChange)(&stateSince);
906 RTTIMESPEC timeSpec;
907 RTTimeSpecSetMilli(&timeSpec, stateSince);
908 char pszTime[30] = {0};
909 RTTimeSpecToString(&timeSpec, pszTime, sizeof(pszTime));
910 if (details == VMINFO_MACHINEREADABLE)
911 {
912 RTPrintf("VMState=\"%s\"\n", pszState);
913 RTPrintf("VMStateChangeTime=\"%s\"\n", pszTime);
914
915 Bstr stateFile;
916 machine->COMGETTER(StateFilePath)(stateFile.asOutParam());
917 if (!stateFile.isEmpty())
918 RTPrintf("VMStateFile=\"%ls\"\n", stateFile.raw());
919 }
920 else
921 RTPrintf("%-28s %s (since %s)\n", "State:", pszState, pszTime);
922
923 GraphicsControllerType_T enmGraphics;
924 rc = pGraphicsAdapter->COMGETTER(GraphicsControllerType)(&enmGraphics);
925 if (SUCCEEDED(rc))
926 {
927 const char *pszCtrl = "Unknown";
928 switch (enmGraphics)
929 {
930 case GraphicsControllerType_Null:
931 if (details == VMINFO_MACHINEREADABLE)
932 pszCtrl = "null";
933 else
934 pszCtrl = "Null";
935 break;
936 case GraphicsControllerType_VBoxVGA:
937 if (details == VMINFO_MACHINEREADABLE)
938 pszCtrl = "vboxvga";
939 else
940 pszCtrl = "VBoxVGA";
941 break;
942 case GraphicsControllerType_VMSVGA:
943 if (details == VMINFO_MACHINEREADABLE)
944 pszCtrl = "vmsvga";
945 else
946 pszCtrl = "VMSVGA";
947 break;
948 case GraphicsControllerType_VBoxSVGA:
949 if (details == VMINFO_MACHINEREADABLE)
950 pszCtrl = "vboxsvga";
951 else
952 pszCtrl = "VBoxSVGA";
953 break;
954 default:
955 if (details == VMINFO_MACHINEREADABLE)
956 pszCtrl = "unknown";
957 break;
958 }
959
960 if (details == VMINFO_MACHINEREADABLE)
961 RTPrintf("graphicscontroller=\"%s\"\n", pszCtrl);
962 else
963 RTPrintf("%-28s %s\n", "Graphics Controller:", pszCtrl);
964 }
965
966 SHOW_ULONG_PROP(pGraphicsAdapter, MonitorCount, "monitorcount", "Monitor count:", "");
967 SHOW_BOOLEAN_PROP(pGraphicsAdapter, Accelerate3DEnabled, "accelerate3d", "3D Acceleration:");
968#ifdef VBOX_WITH_VIDEOHWACCEL
969 SHOW_BOOLEAN_PROP(pGraphicsAdapter, Accelerate2DVideoEnabled, "accelerate2dvideo", "2D Video Acceleration:");
970#endif
971 SHOW_BOOLEAN_PROP( machine, TeleporterEnabled, "teleporterenabled", "Teleporter Enabled:");
972 SHOW_ULONG_PROP( machine, TeleporterPort, "teleporterport", "Teleporter Port:", "");
973 SHOW_STRING_PROP( machine, TeleporterAddress, "teleporteraddress", "Teleporter Address:");
974 SHOW_STRING_PROP( machine, TeleporterPassword, "teleporterpassword", "Teleporter Password:");
975 SHOW_BOOLEAN_PROP( machine, TracingEnabled, "tracing-enabled", "Tracing Enabled:");
976 SHOW_BOOLEAN_PROP( machine, AllowTracingToAccessVM, "tracing-allow-vm-access", "Allow Tracing to Access VM:");
977 SHOW_STRING_PROP( machine, TracingConfig, "tracing-config", "Tracing Configuration:");
978 SHOW_BOOLEAN_PROP( machine, AutostartEnabled, "autostart-enabled", "Autostart Enabled:");
979 SHOW_ULONG_PROP( machine, AutostartDelay, "autostart-delay", "Autostart Delay:", "");
980 SHOW_STRING_PROP( machine, DefaultFrontend, "defaultfrontend", "Default Frontend:");
981
982 VMProcPriority_T enmVMProcPriority;
983 CHECK_ERROR2I_RET(machine, COMGETTER(VMProcessPriority)(&enmVMProcPriority), hrcCheck);
984 const char *pszVMProcPriority;
985 switch (enmVMProcPriority)
986 {
987 case VMProcPriority_Flat:
988 pszVMProcPriority = "flat";
989 break;
990 case VMProcPriority_Low:
991 pszVMProcPriority = "low";
992 break;
993 case VMProcPriority_Normal:
994 pszVMProcPriority = "normal";
995 break;
996 case VMProcPriority_High:
997 pszVMProcPriority = "high";
998 break;
999 default:
1000 pszVMProcPriority = "default";
1001 break;
1002 }
1003 SHOW_UTF8_STRING("vmprocpriority", "VM process priority:", pszVMProcPriority);
1004
1005/** @todo Convert the remainder of the function to SHOW_XXX macros and add error
1006 * checking where missing. */
1007 /*
1008 * Storage Controllers and their attached Mediums.
1009 */
1010 com::SafeIfaceArray<IStorageController> storageCtls;
1011 CHECK_ERROR(machine, COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(storageCtls)));
1012 for (size_t i = 0; i < storageCtls.size(); ++ i)
1013 {
1014 ComPtr<IStorageController> storageCtl = storageCtls[i];
1015 StorageControllerType_T enmCtlType = StorageControllerType_Null;
1016 const char *pszCtl = NULL;
1017 ULONG ulValue = 0;
1018 BOOL fBootable = FALSE;
1019 Bstr storageCtlName;
1020
1021 storageCtl->COMGETTER(Name)(storageCtlName.asOutParam());
1022 if (details == VMINFO_MACHINEREADABLE)
1023 RTPrintf("storagecontrollername%u=\"%ls\"\n", i, storageCtlName.raw());
1024 else
1025 RTPrintf("Storage Controller Name (%u): %ls\n", i, storageCtlName.raw());
1026
1027 storageCtl->COMGETTER(ControllerType)(&enmCtlType);
1028 switch (enmCtlType)
1029 {
1030 case StorageControllerType_LsiLogic:
1031 pszCtl = "LsiLogic";
1032 break;
1033 case StorageControllerType_LsiLogicSas:
1034 pszCtl = "LsiLogicSas";
1035 break;
1036 case StorageControllerType_BusLogic:
1037 pszCtl = "BusLogic";
1038 break;
1039 case StorageControllerType_IntelAhci:
1040 pszCtl = "IntelAhci";
1041 break;
1042 case StorageControllerType_PIIX3:
1043 pszCtl = "PIIX3";
1044 break;
1045 case StorageControllerType_PIIX4:
1046 pszCtl = "PIIX4";
1047 break;
1048 case StorageControllerType_ICH6:
1049 pszCtl = "ICH6";
1050 break;
1051 case StorageControllerType_I82078:
1052 pszCtl = "I82078";
1053 break;
1054 case StorageControllerType_USB:
1055 pszCtl = "USB";
1056 break;
1057
1058 default:
1059 pszCtl = "unknown";
1060 }
1061 if (details == VMINFO_MACHINEREADABLE)
1062 RTPrintf("storagecontrollertype%u=\"%s\"\n", i, pszCtl);
1063 else
1064 RTPrintf("Storage Controller Type (%u): %s\n", i, pszCtl);
1065
1066 storageCtl->COMGETTER(Instance)(&ulValue);
1067 if (details == VMINFO_MACHINEREADABLE)
1068 RTPrintf("storagecontrollerinstance%u=\"%lu\"\n", i, ulValue);
1069 else
1070 RTPrintf("Storage Controller Instance Number (%u): %lu\n", i, ulValue);
1071
1072 storageCtl->COMGETTER(MaxPortCount)(&ulValue);
1073 if (details == VMINFO_MACHINEREADABLE)
1074 RTPrintf("storagecontrollermaxportcount%u=\"%lu\"\n", i, ulValue);
1075 else
1076 RTPrintf("Storage Controller Max Port Count (%u): %lu\n", i, ulValue);
1077
1078 storageCtl->COMGETTER(PortCount)(&ulValue);
1079 if (details == VMINFO_MACHINEREADABLE)
1080 RTPrintf("storagecontrollerportcount%u=\"%lu\"\n", i, ulValue);
1081 else
1082 RTPrintf("Storage Controller Port Count (%u): %lu\n", i, ulValue);
1083
1084 storageCtl->COMGETTER(Bootable)(&fBootable);
1085 if (details == VMINFO_MACHINEREADABLE)
1086 RTPrintf("storagecontrollerbootable%u=\"%s\"\n", i, fBootable ? "on" : "off");
1087 else
1088 RTPrintf("Storage Controller Bootable (%u): %s\n", i, fBootable ? "on" : "off");
1089 }
1090
1091 for (size_t j = 0; j < storageCtls.size(); ++ j)
1092 {
1093 ComPtr<IStorageController> storageCtl = storageCtls[j];
1094 ComPtr<IMedium> medium;
1095 Bstr storageCtlName;
1096 Bstr filePath;
1097 ULONG cDevices;
1098 ULONG cPorts;
1099
1100 storageCtl->COMGETTER(Name)(storageCtlName.asOutParam());
1101 storageCtl->COMGETTER(MaxDevicesPerPortCount)(&cDevices);
1102 storageCtl->COMGETTER(PortCount)(&cPorts);
1103
1104 for (ULONG i = 0; i < cPorts; ++ i)
1105 {
1106 for (ULONG k = 0; k < cDevices; ++ k)
1107 {
1108 ComPtr<IMediumAttachment> mediumAttach;
1109 machine->GetMediumAttachment(storageCtlName.raw(),
1110 i, k,
1111 mediumAttach.asOutParam());
1112 BOOL fIsEjected = FALSE;
1113 BOOL fTempEject = FALSE;
1114 DeviceType_T devType = DeviceType_Null;
1115 if (mediumAttach)
1116 {
1117 mediumAttach->COMGETTER(TemporaryEject)(&fTempEject);
1118 mediumAttach->COMGETTER(IsEjected)(&fIsEjected);
1119 mediumAttach->COMGETTER(Type)(&devType);
1120 }
1121 rc = machine->GetMedium(storageCtlName.raw(), i, k,
1122 medium.asOutParam());
1123 if (SUCCEEDED(rc) && medium)
1124 {
1125 BOOL fPassthrough = FALSE;
1126
1127 if (mediumAttach)
1128 mediumAttach->COMGETTER(Passthrough)(&fPassthrough);
1129
1130 medium->COMGETTER(Location)(filePath.asOutParam());
1131 Bstr uuid;
1132 medium->COMGETTER(Id)(uuid.asOutParam());
1133
1134 if (details == VMINFO_MACHINEREADABLE)
1135 {
1136 RTPrintf("\"%ls-%d-%d\"=\"%ls\"\n", storageCtlName.raw(),
1137 i, k, filePath.raw());
1138 RTPrintf("\"%ls-ImageUUID-%d-%d\"=\"%s\"\n",
1139 storageCtlName.raw(), i, k, Utf8Str(uuid).c_str());
1140 if (fPassthrough)
1141 RTPrintf("\"%ls-dvdpassthrough\"=\"%s\"\n", storageCtlName.raw(),
1142 fPassthrough ? "on" : "off");
1143 if (devType == DeviceType_DVD)
1144 {
1145 RTPrintf("\"%ls-tempeject\"=\"%s\"\n", storageCtlName.raw(),
1146 fTempEject ? "on" : "off");
1147 RTPrintf("\"%ls-IsEjected\"=\"%s\"\n", storageCtlName.raw(),
1148 fIsEjected ? "on" : "off");
1149 }
1150 }
1151 else
1152 {
1153 RTPrintf("%ls (%d, %d): %ls (UUID: %s)",
1154 storageCtlName.raw(), i, k, filePath.raw(),
1155 Utf8Str(uuid).c_str());
1156 if (fPassthrough)
1157 RTPrintf(" (passthrough enabled)");
1158 if (fTempEject)
1159 RTPrintf(" (temp eject)");
1160 if (fIsEjected)
1161 RTPrintf(" (ejected)");
1162 RTPrintf("\n");
1163 }
1164 }
1165 else if (SUCCEEDED(rc))
1166 {
1167 if (details == VMINFO_MACHINEREADABLE)
1168 {
1169 RTPrintf("\"%ls-%d-%d\"=\"emptydrive\"\n", storageCtlName.raw(), i, k);
1170 if (devType == DeviceType_DVD)
1171 RTPrintf("\"%ls-IsEjected\"=\"%s\"\n", storageCtlName.raw(),
1172 fIsEjected ? "on" : "off");
1173 }
1174 else
1175 {
1176 RTPrintf("%ls (%d, %d): Empty", storageCtlName.raw(), i, k);
1177 if (fTempEject)
1178 RTPrintf(" (temp eject)");
1179 if (fIsEjected)
1180 RTPrintf(" (ejected)");
1181 RTPrintf("\n");
1182 }
1183 }
1184 else
1185 {
1186 if (details == VMINFO_MACHINEREADABLE)
1187 RTPrintf("\"%ls-%d-%d\"=\"none\"\n", storageCtlName.raw(), i, k);
1188 }
1189 }
1190 }
1191 }
1192
1193 /* get the maximum amount of NICS */
1194 ULONG maxNICs = getMaxNics(pVirtualBox, machine);
1195
1196 for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++)
1197 {
1198 ComPtr<INetworkAdapter> nic;
1199 rc = machine->GetNetworkAdapter(currentNIC, nic.asOutParam());
1200 if (SUCCEEDED(rc) && nic)
1201 {
1202 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "nic%u" : "NIC %u:", currentNIC + 1);
1203
1204 BOOL fEnabled;
1205 nic->COMGETTER(Enabled)(&fEnabled);
1206 if (!fEnabled)
1207 {
1208 if (details == VMINFO_MACHINEREADABLE)
1209 RTPrintf("%s=\"none\"\n", szNm);
1210 else
1211 RTPrintf("%-28s disabled\n", szNm);
1212 }
1213 else
1214 {
1215 Bstr strMACAddress;
1216 nic->COMGETTER(MACAddress)(strMACAddress.asOutParam());
1217 Utf8Str strAttachment;
1218 Utf8Str strNatSettings = "";
1219 Utf8Str strNatForwardings = "";
1220 NetworkAttachmentType_T attachment;
1221 nic->COMGETTER(AttachmentType)(&attachment);
1222 switch (attachment)
1223 {
1224 case NetworkAttachmentType_Null:
1225 if (details == VMINFO_MACHINEREADABLE)
1226 strAttachment = "null";
1227 else
1228 strAttachment = "none";
1229 break;
1230
1231 case NetworkAttachmentType_NAT:
1232 {
1233 Bstr strNetwork;
1234 ComPtr<INATEngine> engine;
1235 nic->COMGETTER(NATEngine)(engine.asOutParam());
1236 engine->COMGETTER(Network)(strNetwork.asOutParam());
1237 com::SafeArray<BSTR> forwardings;
1238 engine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(forwardings));
1239 strNatForwardings = "";
1240 for (size_t i = 0; i < forwardings.size(); ++i)
1241 {
1242 bool fSkip = false;
1243 BSTR r = forwardings[i];
1244 Utf8Str utf = Utf8Str(r);
1245 Utf8Str strName;
1246 Utf8Str strProto;
1247 Utf8Str strHostPort;
1248 Utf8Str strHostIP;
1249 Utf8Str strGuestPort;
1250 Utf8Str strGuestIP;
1251 size_t pos, ppos;
1252 pos = ppos = 0;
1253 #define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \
1254 do { \
1255 pos = str.find(",", ppos); \
1256 if (pos == Utf8Str::npos) \
1257 { \
1258 Log(( #res " extracting from %s is failed\n", str.c_str())); \
1259 fSkip = true; \
1260 } \
1261 res = str.substr(ppos, pos - ppos); \
1262 Log2((#res " %s pos:%d, ppos:%d\n", res.c_str(), pos, ppos)); \
1263 ppos = pos + 1; \
1264 } while (0)
1265 ITERATE_TO_NEXT_TERM(strName, utf, pos, ppos);
1266 if (fSkip) continue;
1267 ITERATE_TO_NEXT_TERM(strProto, utf, pos, ppos);
1268 if (fSkip) continue;
1269 ITERATE_TO_NEXT_TERM(strHostIP, utf, pos, ppos);
1270 if (fSkip) continue;
1271 ITERATE_TO_NEXT_TERM(strHostPort, utf, pos, ppos);
1272 if (fSkip) continue;
1273 ITERATE_TO_NEXT_TERM(strGuestIP, utf, pos, ppos);
1274 if (fSkip) continue;
1275 strGuestPort = utf.substr(ppos, utf.length() - ppos);
1276 #undef ITERATE_TO_NEXT_TERM
1277 switch (strProto.toUInt32())
1278 {
1279 case NATProtocol_TCP:
1280 strProto = "tcp";
1281 break;
1282 case NATProtocol_UDP:
1283 strProto = "udp";
1284 break;
1285 default:
1286 strProto = "unk";
1287 break;
1288 }
1289 if (details == VMINFO_MACHINEREADABLE)
1290 {
1291 strNatForwardings = Utf8StrFmt("%sForwarding(%d)=\"%s,%s,%s,%s,%s,%s\"\n",
1292 strNatForwardings.c_str(), i, strName.c_str(), strProto.c_str(),
1293 strHostIP.c_str(), strHostPort.c_str(),
1294 strGuestIP.c_str(), strGuestPort.c_str());
1295 }
1296 else
1297 {
1298 strNatForwardings = Utf8StrFmt("%sNIC %d Rule(%d): name = %s, protocol = %s,"
1299 " host ip = %s, host port = %s, guest ip = %s, guest port = %s\n",
1300 strNatForwardings.c_str(), currentNIC + 1, i, strName.c_str(), strProto.c_str(),
1301 strHostIP.c_str(), strHostPort.c_str(),
1302 strGuestIP.c_str(), strGuestPort.c_str());
1303 }
1304 }
1305 ULONG mtu = 0;
1306 ULONG sockSnd = 0;
1307 ULONG sockRcv = 0;
1308 ULONG tcpSnd = 0;
1309 ULONG tcpRcv = 0;
1310 engine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv);
1311
1312/** @todo r=klaus dnsproxy etc needs to be dumped, too */
1313 if (details == VMINFO_MACHINEREADABLE)
1314 {
1315 RTPrintf("natnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.length() ? strNetwork.raw(): Bstr("nat").raw());
1316 strAttachment = "nat";
1317 strNatSettings = Utf8StrFmt("mtu=\"%d\"\nsockSnd=\"%d\"\nsockRcv=\"%d\"\ntcpWndSnd=\"%d\"\ntcpWndRcv=\"%d\"\n",
1318 mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1319 }
1320 else
1321 {
1322 strAttachment = "NAT";
1323 strNatSettings = Utf8StrFmt("NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d)\n",
1324 currentNIC + 1, mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1325 }
1326 break;
1327 }
1328
1329 case NetworkAttachmentType_Bridged:
1330 {
1331 Bstr strBridgeAdp;
1332 nic->COMGETTER(BridgedInterface)(strBridgeAdp.asOutParam());
1333 if (details == VMINFO_MACHINEREADABLE)
1334 {
1335 RTPrintf("bridgeadapter%d=\"%ls\"\n", currentNIC + 1, strBridgeAdp.raw());
1336 strAttachment = "bridged";
1337 }
1338 else
1339 strAttachment = Utf8StrFmt("Bridged Interface '%ls'", strBridgeAdp.raw());
1340 break;
1341 }
1342
1343 case NetworkAttachmentType_Internal:
1344 {
1345 Bstr strNetwork;
1346 nic->COMGETTER(InternalNetwork)(strNetwork.asOutParam());
1347 if (details == VMINFO_MACHINEREADABLE)
1348 {
1349 RTPrintf("intnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1350 strAttachment = "intnet";
1351 }
1352 else
1353 strAttachment = Utf8StrFmt("Internal Network '%s'", Utf8Str(strNetwork).c_str());
1354 break;
1355 }
1356
1357 case NetworkAttachmentType_HostOnly:
1358 {
1359 Bstr strHostonlyAdp;
1360 nic->COMGETTER(HostOnlyInterface)(strHostonlyAdp.asOutParam());
1361 if (details == VMINFO_MACHINEREADABLE)
1362 {
1363 RTPrintf("hostonlyadapter%d=\"%ls\"\n", currentNIC + 1, strHostonlyAdp.raw());
1364 strAttachment = "hostonly";
1365 }
1366 else
1367 strAttachment = Utf8StrFmt("Host-only Interface '%ls'", strHostonlyAdp.raw());
1368 break;
1369 }
1370
1371 case NetworkAttachmentType_Generic:
1372 {
1373 Bstr strGenericDriver;
1374 nic->COMGETTER(GenericDriver)(strGenericDriver.asOutParam());
1375 if (details == VMINFO_MACHINEREADABLE)
1376 {
1377 RTPrintf("generic%d=\"%ls\"\n", currentNIC + 1, strGenericDriver.raw());
1378 strAttachment = "Generic";
1379 }
1380 else
1381 {
1382 strAttachment = Utf8StrFmt("Generic '%ls'", strGenericDriver.raw());
1383
1384 // show the generic properties
1385 com::SafeArray<BSTR> aProperties;
1386 com::SafeArray<BSTR> aValues;
1387 rc = nic->GetProperties(NULL,
1388 ComSafeArrayAsOutParam(aProperties),
1389 ComSafeArrayAsOutParam(aValues));
1390 if (SUCCEEDED(rc))
1391 {
1392 strAttachment += " { ";
1393 for (unsigned i = 0; i < aProperties.size(); ++i)
1394 strAttachment += Utf8StrFmt(!i ? "%ls='%ls'" : ", %ls='%ls'",
1395 aProperties[i], aValues[i]);
1396 strAttachment += " }";
1397 }
1398 }
1399 break;
1400 }
1401
1402 case NetworkAttachmentType_NATNetwork:
1403 {
1404 Bstr strNetwork;
1405 nic->COMGETTER(NATNetwork)(strNetwork.asOutParam());
1406 if (details == VMINFO_MACHINEREADABLE)
1407 {
1408 RTPrintf("nat-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1409 strAttachment = "natnetwork";
1410 }
1411 else
1412 strAttachment = Utf8StrFmt("NAT Network '%s'", Utf8Str(strNetwork).c_str());
1413 break;
1414 }
1415
1416 default:
1417 strAttachment = "unknown";
1418 break;
1419 }
1420
1421 /* cable connected */
1422 BOOL fConnected;
1423 nic->COMGETTER(CableConnected)(&fConnected);
1424
1425 /* promisc policy */
1426 NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy;
1427 CHECK_ERROR2I_RET(nic, COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy), hrcCheck);
1428 const char *pszPromiscuousGuestPolicy;
1429 switch (enmPromiscModePolicy)
1430 {
1431 case NetworkAdapterPromiscModePolicy_Deny: pszPromiscuousGuestPolicy = "deny"; break;
1432 case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = "allow-vms"; break;
1433 case NetworkAdapterPromiscModePolicy_AllowAll: pszPromiscuousGuestPolicy = "allow-all"; break;
1434 default: AssertFailedReturn(E_INVALIDARG);
1435 }
1436
1437 /* trace stuff */
1438 BOOL fTraceEnabled;
1439 nic->COMGETTER(TraceEnabled)(&fTraceEnabled);
1440 Bstr traceFile;
1441 nic->COMGETTER(TraceFile)(traceFile.asOutParam());
1442
1443 /* NIC type */
1444 NetworkAdapterType_T NICType;
1445 nic->COMGETTER(AdapterType)(&NICType);
1446 const char *pszNICType;
1447 switch (NICType)
1448 {
1449 case NetworkAdapterType_Am79C970A: pszNICType = "Am79C970A"; break;
1450 case NetworkAdapterType_Am79C973: pszNICType = "Am79C973"; break;
1451 case NetworkAdapterType_Am79C960: pszNICType = "Am79C960"; break;
1452#ifdef VBOX_WITH_E1000
1453 case NetworkAdapterType_I82540EM: pszNICType = "82540EM"; break;
1454 case NetworkAdapterType_I82543GC: pszNICType = "82543GC"; break;
1455 case NetworkAdapterType_I82545EM: pszNICType = "82545EM"; break;
1456#endif
1457#ifdef VBOX_WITH_VIRTIO
1458 case NetworkAdapterType_Virtio: pszNICType = "virtio"; break;
1459#endif
1460 default: AssertFailed(); pszNICType = "unknown"; break;
1461 }
1462
1463 /* reported line speed */
1464 ULONG ulLineSpeed;
1465 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1466
1467 /* boot priority of the adapter */
1468 ULONG ulBootPriority;
1469 nic->COMGETTER(BootPriority)(&ulBootPriority);
1470
1471 /* bandwidth group */
1472 ComObjPtr<IBandwidthGroup> pBwGroup;
1473 Bstr strBwGroup;
1474 nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());
1475 if (!pBwGroup.isNull())
1476 pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam());
1477
1478 if (details == VMINFO_MACHINEREADABLE)
1479 {
1480 RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw());
1481 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1482 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str());
1483 RTPrintf("nictype%d=\"%s\"\n", currentNIC + 1, pszNICType);
1484 RTPrintf("nicspeed%d=\"%d\"\n", currentNIC + 1, ulLineSpeed);
1485 }
1486 else
1487 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",
1488 szNm, strMACAddress.raw(), strAttachment.c_str(),
1489 fConnected ? "on" : "off",
1490 fTraceEnabled ? "on" : "off",
1491 traceFile.isEmpty() ? Bstr("none").raw() : traceFile.raw(),
1492 pszNICType,
1493 ulLineSpeed / 1000,
1494 (int)ulBootPriority,
1495 pszPromiscuousGuestPolicy,
1496 strBwGroup.isEmpty() ? Bstr("none").raw() : strBwGroup.raw());
1497 if (strNatSettings.length())
1498 RTPrintf(strNatSettings.c_str());
1499 if (strNatForwardings.length())
1500 RTPrintf(strNatForwardings.c_str());
1501 }
1502 }
1503 }
1504
1505 /* Pointing device information */
1506 PointingHIDType_T aPointingHID;
1507 const char *pszHID = "Unknown";
1508 const char *pszMrHID = "unknown";
1509 machine->COMGETTER(PointingHIDType)(&aPointingHID);
1510 switch (aPointingHID)
1511 {
1512 case PointingHIDType_None:
1513 pszHID = "None";
1514 pszMrHID = "none";
1515 break;
1516 case PointingHIDType_PS2Mouse:
1517 pszHID = "PS/2 Mouse";
1518 pszMrHID = "ps2mouse";
1519 break;
1520 case PointingHIDType_USBMouse:
1521 pszHID = "USB Mouse";
1522 pszMrHID = "usbmouse";
1523 break;
1524 case PointingHIDType_USBTablet:
1525 pszHID = "USB Tablet";
1526 pszMrHID = "usbtablet";
1527 break;
1528 case PointingHIDType_ComboMouse:
1529 pszHID = "USB Tablet and PS/2 Mouse";
1530 pszMrHID = "combomouse";
1531 break;
1532 case PointingHIDType_USBMultiTouch:
1533 pszHID = "USB Multi-Touch";
1534 pszMrHID = "usbmultitouch";
1535 break;
1536 default:
1537 break;
1538 }
1539 SHOW_UTF8_STRING("hidpointing", "Pointing Device:", details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
1540
1541 /* Keyboard device information */
1542 KeyboardHIDType_T aKeyboardHID;
1543 machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID);
1544 pszHID = "Unknown";
1545 pszMrHID = "unknown";
1546 switch (aKeyboardHID)
1547 {
1548 case KeyboardHIDType_None:
1549 pszHID = "None";
1550 pszMrHID = "none";
1551 break;
1552 case KeyboardHIDType_PS2Keyboard:
1553 pszHID = "PS/2 Keyboard";
1554 pszMrHID = "ps2kbd";
1555 break;
1556 case KeyboardHIDType_USBKeyboard:
1557 pszHID = "USB Keyboard";
1558 pszMrHID = "usbkbd";
1559 break;
1560 case KeyboardHIDType_ComboKeyboard:
1561 pszHID = "USB and PS/2 Keyboard";
1562 pszMrHID = "combokbd";
1563 break;
1564 default:
1565 break;
1566 }
1567 SHOW_UTF8_STRING("hidkeyboard", "Keyboard Device:", details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
1568
1569 ComPtr<ISystemProperties> sysProps;
1570 pVirtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
1571
1572 /* get the maximum amount of UARTs */
1573 ULONG maxUARTs = 0;
1574 sysProps->COMGETTER(SerialPortCount)(&maxUARTs);
1575 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
1576 {
1577 ComPtr<ISerialPort> uart;
1578 rc = machine->GetSerialPort(currentUART, uart.asOutParam());
1579 if (SUCCEEDED(rc) && uart)
1580 {
1581 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "uart%u" : "UART %u:", currentUART + 1);
1582
1583 /* show the config of this UART */
1584 BOOL fEnabled;
1585 uart->COMGETTER(Enabled)(&fEnabled);
1586 if (!fEnabled)
1587 {
1588 if (details == VMINFO_MACHINEREADABLE)
1589 RTPrintf("%s=\"off\"\n", szNm);
1590 else
1591 RTPrintf("%-28s disabled\n", szNm);
1592 }
1593 else
1594 {
1595 ULONG ulIRQ, ulIOBase;
1596 PortMode_T HostMode;
1597 Bstr path;
1598 BOOL fServer;
1599 UartType_T UartType;
1600 uart->COMGETTER(IRQ)(&ulIRQ);
1601 uart->COMGETTER(IOBase)(&ulIOBase);
1602 uart->COMGETTER(Path)(path.asOutParam());
1603 uart->COMGETTER(Server)(&fServer);
1604 uart->COMGETTER(HostMode)(&HostMode);
1605 uart->COMGETTER(UartType)(&UartType);
1606
1607 if (details == VMINFO_MACHINEREADABLE)
1608 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
1609 else
1610 RTPrintf("%-28s I/O base: %#06x, IRQ: %d", szNm, ulIOBase, ulIRQ);
1611 switch (HostMode)
1612 {
1613 default:
1614 case PortMode_Disconnected:
1615 if (details == VMINFO_MACHINEREADABLE)
1616 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
1617 else
1618 RTPrintf(", disconnected");
1619 break;
1620 case PortMode_RawFile:
1621 if (details == VMINFO_MACHINEREADABLE)
1622 RTPrintf("uartmode%d=\"file,%ls\"\n", currentUART + 1,
1623 path.raw());
1624 else
1625 RTPrintf(", attached to raw file '%ls'\n",
1626 path.raw());
1627 break;
1628 case PortMode_TCP:
1629 if (details == VMINFO_MACHINEREADABLE)
1630 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
1631 fServer ? "tcpserver" : "tcpclient", path.raw());
1632 else
1633 RTPrintf(", attached to tcp (%s) '%ls'",
1634 fServer ? "server" : "client", path.raw());
1635 break;
1636 case PortMode_HostPipe:
1637 if (details == VMINFO_MACHINEREADABLE)
1638 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
1639 fServer ? "server" : "client", path.raw());
1640 else
1641 RTPrintf(", attached to pipe (%s) '%ls'",
1642 fServer ? "server" : "client", path.raw());
1643 break;
1644 case PortMode_HostDevice:
1645 if (details == VMINFO_MACHINEREADABLE)
1646 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
1647 path.raw());
1648 else
1649 RTPrintf(", attached to device '%ls'", path.raw());
1650 break;
1651 }
1652 switch (UartType)
1653 {
1654 default:
1655 case UartType_U16450:
1656 if (details == VMINFO_MACHINEREADABLE)
1657 RTPrintf("uarttype%d=\"16450\"\n", currentUART + 1);
1658 else
1659 RTPrintf(", 16450\n");
1660 break;
1661 case UartType_U16550A:
1662 if (details == VMINFO_MACHINEREADABLE)
1663 RTPrintf("uarttype%d=\"16550A\"\n", currentUART + 1);
1664 else
1665 RTPrintf(", 16550A\n");
1666 break;
1667 case UartType_U16750:
1668 if (details == VMINFO_MACHINEREADABLE)
1669 RTPrintf("uarttype%d=\"16750\"\n", currentUART + 1);
1670 else
1671 RTPrintf(", 16750\n");
1672 break;
1673 }
1674 }
1675 }
1676 }
1677
1678 /* get the maximum amount of LPTs */
1679 ULONG maxLPTs = 0;
1680 sysProps->COMGETTER(ParallelPortCount)(&maxLPTs);
1681 for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++)
1682 {
1683 ComPtr<IParallelPort> lpt;
1684 rc = machine->GetParallelPort(currentLPT, lpt.asOutParam());
1685 if (SUCCEEDED(rc) && lpt)
1686 {
1687 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "lpt%u" : "LPT %u:", currentLPT + 1);
1688
1689 /* show the config of this LPT */
1690 BOOL fEnabled;
1691 lpt->COMGETTER(Enabled)(&fEnabled);
1692 if (!fEnabled)
1693 {
1694 if (details == VMINFO_MACHINEREADABLE)
1695 RTPrintf("%s=\"off\"\n", szNm);
1696 else
1697 RTPrintf("%-28s disabled\n", szNm);
1698 }
1699 else
1700 {
1701 ULONG ulIRQ, ulIOBase;
1702 Bstr path;
1703 lpt->COMGETTER(IRQ)(&ulIRQ);
1704 lpt->COMGETTER(IOBase)(&ulIOBase);
1705 lpt->COMGETTER(Path)(path.asOutParam());
1706
1707 if (details == VMINFO_MACHINEREADABLE)
1708 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
1709 else
1710 RTPrintf("%-28s I/O base: %#06x, IRQ: %d", szNm, ulIOBase, ulIRQ);
1711 if (details == VMINFO_MACHINEREADABLE)
1712 RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1, path.raw());
1713 else
1714 RTPrintf(", attached to device '%ls'\n", path.raw());
1715 }
1716 }
1717 }
1718
1719 ComPtr<IAudioAdapter> AudioAdapter;
1720 rc = machine->COMGETTER(AudioAdapter)(AudioAdapter.asOutParam());
1721 if (SUCCEEDED(rc))
1722 {
1723 const char *pszDrv = "Unknown";
1724 const char *pszCtrl = "Unknown";
1725 const char *pszCodec = "Unknown";
1726 BOOL fEnabled;
1727 rc = AudioAdapter->COMGETTER(Enabled)(&fEnabled);
1728 if (SUCCEEDED(rc) && fEnabled)
1729 {
1730 AudioDriverType_T enmDrvType;
1731 rc = AudioAdapter->COMGETTER(AudioDriver)(&enmDrvType);
1732 switch (enmDrvType)
1733 {
1734 case AudioDriverType_Null:
1735 if (details == VMINFO_MACHINEREADABLE)
1736 pszDrv = "null";
1737 else
1738 pszDrv = "Null";
1739 break;
1740 case AudioDriverType_WinMM:
1741 if (details == VMINFO_MACHINEREADABLE)
1742 pszDrv = "winmm";
1743 else
1744 pszDrv = "WINMM";
1745 break;
1746 case AudioDriverType_DirectSound:
1747 if (details == VMINFO_MACHINEREADABLE)
1748 pszDrv = "dsound";
1749 else
1750 pszDrv = "DSOUND";
1751 break;
1752 case AudioDriverType_OSS:
1753 if (details == VMINFO_MACHINEREADABLE)
1754 pszDrv = "oss";
1755 else
1756 pszDrv = "OSS";
1757 break;
1758 case AudioDriverType_ALSA:
1759 if (details == VMINFO_MACHINEREADABLE)
1760 pszDrv = "alsa";
1761 else
1762 pszDrv = "ALSA";
1763 break;
1764 case AudioDriverType_Pulse:
1765 if (details == VMINFO_MACHINEREADABLE)
1766 pszDrv = "pulse";
1767 else
1768 pszDrv = "PulseAudio";
1769 break;
1770 case AudioDriverType_CoreAudio:
1771 if (details == VMINFO_MACHINEREADABLE)
1772 pszDrv = "coreaudio";
1773 else
1774 pszDrv = "CoreAudio";
1775 break;
1776 case AudioDriverType_SolAudio:
1777 if (details == VMINFO_MACHINEREADABLE)
1778 pszDrv = "solaudio";
1779 else
1780 pszDrv = "SolAudio";
1781 break;
1782 default:
1783 if (details == VMINFO_MACHINEREADABLE)
1784 pszDrv = "unknown";
1785 break;
1786 }
1787 AudioControllerType_T enmCtrlType;
1788 rc = AudioAdapter->COMGETTER(AudioController)(&enmCtrlType);
1789 switch (enmCtrlType)
1790 {
1791 case AudioControllerType_AC97:
1792 if (details == VMINFO_MACHINEREADABLE)
1793 pszCtrl = "ac97";
1794 else
1795 pszCtrl = "AC97";
1796 break;
1797 case AudioControllerType_SB16:
1798 if (details == VMINFO_MACHINEREADABLE)
1799 pszCtrl = "sb16";
1800 else
1801 pszCtrl = "SB16";
1802 break;
1803 case AudioControllerType_HDA:
1804 if (details == VMINFO_MACHINEREADABLE)
1805 pszCtrl = "hda";
1806 else
1807 pszCtrl = "HDA";
1808 break;
1809 default:
1810 break;
1811 }
1812 AudioCodecType_T enmCodecType;
1813 rc = AudioAdapter->COMGETTER(AudioCodec)(&enmCodecType);
1814 switch (enmCodecType)
1815 {
1816 case AudioCodecType_SB16:
1817 pszCodec = "SB16";
1818 break;
1819 case AudioCodecType_STAC9700:
1820 pszCodec = "STAC9700";
1821 break;
1822 case AudioCodecType_AD1980:
1823 pszCodec = "AD1980";
1824 break;
1825 case AudioCodecType_STAC9221:
1826 pszCodec = "STAC9221";
1827 break;
1828 case AudioCodecType_Null: break; /* Shut up MSC. */
1829 default: break;
1830 }
1831 }
1832 else
1833 fEnabled = FALSE;
1834
1835 if (details == VMINFO_MACHINEREADABLE)
1836 RTPrintf("audio=\"%s\"\n", fEnabled ? pszDrv : "none");
1837 else
1838 {
1839 RTPrintf("%-28s %s", "Audio:", fEnabled ? "enabled" : "disabled");
1840 if (fEnabled)
1841 RTPrintf(" (Driver: %s, Controller: %s, Codec: %s)", pszDrv, pszCtrl, pszCodec);
1842 RTPrintf("\n");
1843 }
1844 SHOW_BOOLEAN_PROP(AudioAdapter, EnabledOut, "audio_out", "Audio playback:");
1845 SHOW_BOOLEAN_PROP(AudioAdapter, EnabledIn, "audio_in", "Audio capture:");
1846 }
1847
1848 /* Shared clipboard */
1849 {
1850 const char *psz;
1851 ClipboardMode_T enmMode = (ClipboardMode_T)0;
1852 rc = machine->COMGETTER(ClipboardMode)(&enmMode);
1853 switch (enmMode)
1854 {
1855 case ClipboardMode_Disabled:
1856 psz = "disabled";
1857 break;
1858 case ClipboardMode_HostToGuest:
1859 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : "HostToGuest";
1860 break;
1861 case ClipboardMode_GuestToHost:
1862 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : "GuestToHost";
1863 break;
1864 case ClipboardMode_Bidirectional:
1865 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : "Bidirectional";
1866 break;
1867 default:
1868 psz = details == VMINFO_MACHINEREADABLE ? "unknown" : "Unknown";
1869 break;
1870 }
1871 SHOW_UTF8_STRING("clipboard", "Clipboard Mode:", psz);
1872#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
1873 SHOW_BOOLEAN_PROP(machine, ClipboardFileTransfersEnabled, "clipboard_file_transfers", "Clipboard file transfers:");
1874#endif
1875 }
1876
1877 /* Drag and drop */
1878 {
1879 const char *psz;
1880 DnDMode_T enmMode;
1881 rc = machine->COMGETTER(DnDMode)(&enmMode);
1882 switch (enmMode)
1883 {
1884 case DnDMode_Disabled:
1885 psz = "disabled";
1886 break;
1887 case DnDMode_HostToGuest:
1888 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : "HostToGuest";
1889 break;
1890 case DnDMode_GuestToHost:
1891 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : "GuestToHost";
1892 break;
1893 case DnDMode_Bidirectional:
1894 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : "Bidirectional";
1895 break;
1896 default:
1897 psz = details == VMINFO_MACHINEREADABLE ? "unknown" : "Unknown";
1898 break;
1899 }
1900 SHOW_UTF8_STRING("draganddrop", "Drag and drop Mode:", psz);
1901 }
1902
1903 {
1904 SessionState_T sessState;
1905 rc = machine->COMGETTER(SessionState)(&sessState);
1906 if (SUCCEEDED(rc) && sessState != SessionState_Unlocked)
1907 {
1908 Bstr sessName;
1909 rc = machine->COMGETTER(SessionName)(sessName.asOutParam());
1910 if (SUCCEEDED(rc) && !sessName.isEmpty())
1911 SHOW_BSTR_STRING("SessionName", "Session name:", sessName);
1912 }
1913 }
1914
1915 if (pConsole)
1916 {
1917 do
1918 {
1919 ComPtr<IDisplay> display;
1920 rc = pConsole->COMGETTER(Display)(display.asOutParam());
1921 if (rc == E_ACCESSDENIED || display.isNull())
1922 break; /* VM not powered up */
1923 if (FAILED(rc))
1924 {
1925 com::GlueHandleComError(pConsole, "COMGETTER(Display)(display.asOutParam())", rc, __FILE__, __LINE__);
1926 return rc;
1927 }
1928 ULONG xRes, yRes, bpp;
1929 LONG xOrigin, yOrigin;
1930 GuestMonitorStatus_T monitorStatus;
1931 rc = display->GetScreenResolution(0, &xRes, &yRes, &bpp, &xOrigin, &yOrigin, &monitorStatus);
1932 if (rc == E_ACCESSDENIED)
1933 break; /* VM not powered up */
1934 if (FAILED(rc))
1935 {
1936 com::ErrorInfo info(display, COM_IIDOF(IDisplay));
1937 GluePrintErrorInfo(info);
1938 return rc;
1939 }
1940 if (details == VMINFO_MACHINEREADABLE)
1941 RTPrintf("VideoMode=\"%d,%d,%d\"@%d,%d %d\n", xRes, yRes, bpp, xOrigin, yOrigin, monitorStatus);
1942 else
1943 {
1944 const char *pszMonitorStatus = "unknown status";
1945 switch (monitorStatus)
1946 {
1947 case GuestMonitorStatus_Blank: pszMonitorStatus = "blank"; break;
1948 case GuestMonitorStatus_Enabled: pszMonitorStatus = "enabled"; break;
1949 case GuestMonitorStatus_Disabled: pszMonitorStatus = "disabled"; break;
1950 default: break;
1951 }
1952 RTPrintf("%-28s %dx%dx%d at %d,%d %s\n", "Video mode:", xRes, yRes, bpp, xOrigin, yOrigin, pszMonitorStatus);
1953 }
1954 }
1955 while (0);
1956 }
1957
1958 /*
1959 * Remote Desktop
1960 */
1961 ComPtr<IVRDEServer> vrdeServer;
1962 rc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam());
1963 if (SUCCEEDED(rc) && vrdeServer)
1964 {
1965 BOOL fEnabled = false;
1966 vrdeServer->COMGETTER(Enabled)(&fEnabled);
1967 if (fEnabled)
1968 {
1969 LONG currentPort = -1;
1970 Bstr ports;
1971 vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam());
1972 Bstr address;
1973 vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam());
1974 BOOL fMultiCon;
1975 vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
1976 BOOL fReuseCon;
1977 vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon);
1978 Bstr videoChannel;
1979 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam());
1980 BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0)
1981 || (videoChannel == "1");
1982 Bstr videoChannelQuality;
1983 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam());
1984 AuthType_T authType = (AuthType_T)0;
1985 const char *strAuthType;
1986 vrdeServer->COMGETTER(AuthType)(&authType);
1987 switch (authType)
1988 {
1989 case AuthType_Null:
1990 strAuthType = "null";
1991 break;
1992 case AuthType_External:
1993 strAuthType = "external";
1994 break;
1995 case AuthType_Guest:
1996 strAuthType = "guest";
1997 break;
1998 default:
1999 strAuthType = "unknown";
2000 break;
2001 }
2002 if (pConsole)
2003 {
2004 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2005 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2006 if (!vrdeServerInfo.isNull())
2007 {
2008 rc = vrdeServerInfo->COMGETTER(Port)(&currentPort);
2009 if (rc == E_ACCESSDENIED)
2010 {
2011 currentPort = -1; /* VM not powered up */
2012 }
2013 else if (FAILED(rc))
2014 {
2015 com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo));
2016 GluePrintErrorInfo(info);
2017 return rc;
2018 }
2019 }
2020 }
2021 if (details == VMINFO_MACHINEREADABLE)
2022 {
2023 RTPrintf("vrde=\"on\"\n");
2024 RTPrintf("vrdeport=%d\n", currentPort);
2025 RTPrintf("vrdeports=\"%ls\"\n", ports.raw());
2026 RTPrintf("vrdeaddress=\"%ls\"\n", address.raw());
2027 RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType);
2028 RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off");
2029 RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off");
2030 RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off");
2031 if (fVideoChannel)
2032 RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw());
2033 }
2034 else
2035 {
2036 if (address.isEmpty())
2037 address = "0.0.0.0";
2038 RTPrintf("%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n",
2039 "VRDE:", address.raw(), ports.raw(), fMultiCon ? "on" : "off", fReuseCon ? "on" : "off", strAuthType);
2040 if (pConsole && currentPort != -1 && currentPort != 0)
2041 RTPrintf("%-28s %d\n", "VRDE port:", currentPort);
2042 if (fVideoChannel)
2043 RTPrintf("%-28s enabled (Quality %ls)\n", "Video redirection:", videoChannelQuality.raw());
2044 else
2045 RTPrintf("%-28s disabled\n", "Video redirection:");
2046 }
2047 com::SafeArray<BSTR> aProperties;
2048 if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties))))
2049 {
2050 unsigned i;
2051 for (i = 0; i < aProperties.size(); ++i)
2052 {
2053 Bstr value;
2054 vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam());
2055 if (details == VMINFO_MACHINEREADABLE)
2056 {
2057 if (value.isEmpty())
2058 RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]);
2059 else
2060 RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw());
2061 }
2062 else
2063 {
2064 if (value.isEmpty())
2065 RTPrintf("%-28s: %-10lS = <not set>\n", "VRDE property", aProperties[i]);
2066 else
2067 RTPrintf("%-28s: %-10lS = \"%ls\"\n", "VRDE property", aProperties[i], value.raw());
2068 }
2069 }
2070 }
2071 }
2072 else
2073 {
2074 if (details == VMINFO_MACHINEREADABLE)
2075 RTPrintf("vrde=\"off\"\n");
2076 else
2077 RTPrintf("%-28s disabled\n", "VRDE:");
2078 }
2079 }
2080
2081 /*
2082 * USB.
2083 */
2084 SafeIfaceArray<IUSBController> USBCtlColl;
2085 rc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl));
2086 if (SUCCEEDED(rc))
2087 {
2088 bool fOhciEnabled = false;
2089 bool fEhciEnabled = false;
2090 bool fXhciEnabled = false;
2091
2092 for (unsigned i = 0; i < USBCtlColl.size(); i++)
2093 {
2094 USBControllerType_T enmType;
2095
2096 rc = USBCtlColl[i]->COMGETTER(Type)(&enmType);
2097 if (SUCCEEDED(rc))
2098 {
2099 switch (enmType)
2100 {
2101 case USBControllerType_OHCI:
2102 fOhciEnabled = true;
2103 break;
2104 case USBControllerType_EHCI:
2105 fEhciEnabled = true;
2106 break;
2107 case USBControllerType_XHCI:
2108 fXhciEnabled = true;
2109 break;
2110 default:
2111 break;
2112 }
2113 }
2114 }
2115
2116 SHOW_BOOL_VALUE("usb", "OHCI USB:", fOhciEnabled);
2117 SHOW_BOOL_VALUE("ehci", "EHCI USB:", fEhciEnabled);
2118 SHOW_BOOL_VALUE("xhci", "xHCI USB:", fXhciEnabled);
2119 }
2120
2121 ComPtr<IUSBDeviceFilters> USBFlts;
2122 rc = machine->COMGETTER(USBDeviceFilters)(USBFlts.asOutParam());
2123 if (SUCCEEDED(rc))
2124 {
2125 SafeIfaceArray <IUSBDeviceFilter> Coll;
2126 rc = USBFlts->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll));
2127 if (SUCCEEDED(rc))
2128 {
2129 if (details != VMINFO_MACHINEREADABLE)
2130 RTPrintf("\nUSB Device Filters:\n\n");
2131
2132 if (Coll.size() == 0)
2133 {
2134 if (details != VMINFO_MACHINEREADABLE)
2135 RTPrintf("<none>\n\n");
2136 }
2137 else
2138 {
2139 for (size_t index = 0; index < Coll.size(); ++index)
2140 {
2141 ComPtr<IUSBDeviceFilter> DevPtr = Coll[index];
2142
2143 if (details != VMINFO_MACHINEREADABLE)
2144 SHOW_UTF8_STRING("index", "Index:", FmtNm(szNm, "%zu", index));
2145 SHOW_BOOLEAN_PROP_EX(DevPtr, Active, FmtNm(szNm, "USBFilterActive%zu", index + 1), "Active:", "yes", "no");
2146 SHOW_STRING_PROP(DevPtr, Name, FmtNm(szNm, "USBFilterName%zu", index + 1), "Name:");
2147 SHOW_STRING_PROP(DevPtr, VendorId, FmtNm(szNm, "USBFilterVendorId%zu", index + 1), "VendorId:");
2148 SHOW_STRING_PROP(DevPtr, ProductId, FmtNm(szNm, "USBFilterProductId%zu", index + 1), "ProductId:");
2149 SHOW_STRING_PROP(DevPtr, Revision, FmtNm(szNm, "USBFilterRevision%zu", index + 1), "Revision:");
2150 SHOW_STRING_PROP(DevPtr, Manufacturer, FmtNm(szNm, "USBFilterManufacturer%zu", index + 1), "Manufacturer:");
2151 SHOW_STRING_PROP(DevPtr, Product, FmtNm(szNm, "USBFilterProduct%zu", index + 1), "Product:");
2152 SHOW_STRING_PROP(DevPtr, Remote, FmtNm(szNm, "USBFilterRemote%zu", index + 1), "Remote:");
2153 SHOW_STRING_PROP(DevPtr, SerialNumber, FmtNm(szNm, "USBFilterSerialNumber%zu", index + 1), "Serial Number:");
2154 if (details != VMINFO_MACHINEREADABLE)
2155 {
2156 ULONG fMaskedIfs;
2157 CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), rc);
2158 if (fMaskedIfs)
2159 RTPrintf("%-28s %#010x\n", "Masked Interfaces:", fMaskedIfs);
2160 RTPrintf("\n");
2161 }
2162 }
2163 }
2164 }
2165
2166 if (pConsole)
2167 {
2168 /* scope */
2169 {
2170 if (details != VMINFO_MACHINEREADABLE)
2171 RTPrintf("Available remote USB devices:\n\n");
2172
2173 SafeIfaceArray <IHostUSBDevice> coll;
2174 CHECK_ERROR_RET(pConsole, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), rc);
2175
2176 if (coll.size() == 0)
2177 {
2178 if (details != VMINFO_MACHINEREADABLE)
2179 RTPrintf("<none>\n\n");
2180 }
2181 else
2182 {
2183 /* This code is duplicated below, with USBAttach as prefix. */
2184 const char *pszPfx = "USBRemote";
2185 for (size_t i = 0; i < coll.size(); ++i)
2186 {
2187 ComPtr<IHostUSBDevice> dev = coll[i];
2188
2189 SHOW_STRING_PROP(dev, Id, FmtNm(szNm, "%sActive%zu", pszPfx, i + 1), "UUID:");
2190 SHOW_USHORT_PROP_EX2(dev, VendorId, FmtNm(szNm, "%sVendorId%zu", pszPfx, i + 1), "VendorId:", "", "%#06x", "%#06x (%04X)");
2191 SHOW_USHORT_PROP_EX2(dev, ProductId, FmtNm(szNm, "%sProductId%zu", pszPfx, i + 1), "ProductId:", "", "%#06x", "%#06x (%04X)");
2192
2193 USHORT bcdRevision;
2194 CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), rc);
2195 if (details == VMINFO_MACHINEREADABLE)
2196 RTStrPrintf(szValue, sizeof(szValue), "%#04x%02x", bcdRevision >> 8, bcdRevision & 0xff);
2197 else
2198 RTStrPrintf(szValue, sizeof(szValue), "%u.%u (%02u%02u)\n",
2199 bcdRevision >> 8, bcdRevision & 0xff, bcdRevision >> 8, bcdRevision & 0xff);
2200 SHOW_UTF8_STRING(FmtNm(szNm, "%sRevision%zu", pszPfx, i + 1), "Revision:", szValue);
2201
2202 SHOW_STRING_PROP_NOT_EMPTY(dev, Manufacturer, FmtNm(szNm, "%sManufacturer%zu", pszPfx, i + 1), "Manufacturer:");
2203 SHOW_STRING_PROP_NOT_EMPTY(dev, Product, FmtNm(szNm, "%sProduct%zu", pszPfx, i + 1), "Product:");
2204 SHOW_STRING_PROP_NOT_EMPTY(dev, SerialNumber, FmtNm(szNm, "%sSerialNumber%zu", pszPfx, i + 1), "SerialNumber:");
2205 SHOW_STRING_PROP_NOT_EMPTY(dev, Address, FmtNm(szNm, "%sAddress%zu", pszPfx, i + 1), "Address:");
2206
2207 if (details != VMINFO_MACHINEREADABLE)
2208 RTPrintf("\n");
2209 }
2210 }
2211 }
2212
2213 /* scope */
2214 {
2215 if (details != VMINFO_MACHINEREADABLE)
2216 RTPrintf("Currently Attached USB Devices:\n\n");
2217
2218 SafeIfaceArray <IUSBDevice> coll;
2219 CHECK_ERROR_RET(pConsole, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), rc);
2220
2221 if (coll.size() == 0)
2222 {
2223 if (details != VMINFO_MACHINEREADABLE)
2224 RTPrintf("<none>\n\n");
2225 }
2226 else
2227 {
2228 /* This code is duplicated below, with USBAttach as prefix. */
2229 const char *pszPfx = "USBAttach";
2230 for (size_t i = 0; i < coll.size(); ++i)
2231 {
2232 ComPtr<IUSBDevice> dev = coll[i];
2233
2234 SHOW_STRING_PROP(dev, Id, FmtNm(szNm, "%sActive%zu", pszPfx, i + 1), "UUID:");
2235 SHOW_USHORT_PROP_EX2(dev, VendorId, FmtNm(szNm, "%sVendorId%zu", pszPfx, i + 1), "VendorId:", "", "%#06x", "%#06x (%04X)");
2236 SHOW_USHORT_PROP_EX2(dev, ProductId, FmtNm(szNm, "%sProductId%zu", pszPfx, i + 1), "ProductId:", "", "%#06x", "%#06x (%04X)");
2237
2238 USHORT bcdRevision;
2239 CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), rc);
2240 if (details == VMINFO_MACHINEREADABLE)
2241 RTStrPrintf(szValue, sizeof(szValue), "%#04x%02x", bcdRevision >> 8, bcdRevision & 0xff);
2242 else
2243 RTStrPrintf(szValue, sizeof(szValue), "%u.%u (%02u%02u)\n",
2244 bcdRevision >> 8, bcdRevision & 0xff, bcdRevision >> 8, bcdRevision & 0xff);
2245 SHOW_UTF8_STRING(FmtNm(szNm, "%sRevision%zu", pszPfx, i + 1), "Revision:", szValue);
2246
2247 SHOW_STRING_PROP_NOT_EMPTY(dev, Manufacturer, FmtNm(szNm, "%sManufacturer%zu", pszPfx, i + 1), "Manufacturer:");
2248 SHOW_STRING_PROP_NOT_EMPTY(dev, Product, FmtNm(szNm, "%sProduct%zu", pszPfx, i + 1), "Product:");
2249 SHOW_STRING_PROP_NOT_EMPTY(dev, SerialNumber, FmtNm(szNm, "%sSerialNumber%zu", pszPfx, i + 1), "SerialNumber:");
2250 SHOW_STRING_PROP_NOT_EMPTY(dev, Address, FmtNm(szNm, "%sAddress%zu", pszPfx, i + 1), "Address:");
2251
2252 if (details != VMINFO_MACHINEREADABLE)
2253 RTPrintf("\n");
2254 }
2255 }
2256 }
2257 }
2258 } /* USB */
2259
2260#ifdef VBOX_WITH_PCI_PASSTHROUGH
2261 /* Host PCI passthrough devices */
2262 {
2263 SafeIfaceArray <IPCIDeviceAttachment> assignments;
2264 rc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
2265 if (SUCCEEDED(rc))
2266 {
2267 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2268 {
2269 RTPrintf("\nAttached physical PCI devices:\n\n");
2270 }
2271
2272 for (size_t index = 0; index < assignments.size(); ++index)
2273 {
2274 ComPtr<IPCIDeviceAttachment> Assignment = assignments[index];
2275 char szHostPCIAddress[32], szGuestPCIAddress[32];
2276 LONG iHostPCIAddress = -1, iGuestPCIAddress = -1;
2277 Bstr DevName;
2278
2279 Assignment->COMGETTER(Name)(DevName.asOutParam());
2280 Assignment->COMGETTER(HostAddress)(&iHostPCIAddress);
2281 Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress);
2282 PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress));
2283 PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress));
2284
2285 if (details == VMINFO_MACHINEREADABLE)
2286 RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress);
2287 else
2288 RTPrintf(" Host device %ls at %s attached as %s\n", DevName.raw(), szHostPCIAddress, szGuestPCIAddress);
2289 }
2290
2291 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2292 {
2293 RTPrintf("\n");
2294 }
2295 }
2296 }
2297 /* Host PCI passthrough devices */
2298#endif
2299
2300 /*
2301 * Bandwidth groups
2302 */
2303 if (details != VMINFO_MACHINEREADABLE)
2304 RTPrintf("Bandwidth groups: ");
2305 {
2306 ComPtr<IBandwidthControl> bwCtrl;
2307 CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), rc);
2308
2309 rc = showBandwidthGroups(bwCtrl, details);
2310 }
2311
2312
2313 /*
2314 * Shared folders
2315 */
2316 if (details != VMINFO_MACHINEREADABLE)
2317 RTPrintf("Shared folders:");
2318 uint32_t numSharedFolders = 0;
2319#if 0 // not yet implemented
2320 /* globally shared folders first */
2321 {
2322 SafeIfaceArray <ISharedFolder> sfColl;
2323 CHECK_ERROR_RET(pVirtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(sfColl)), rc);
2324 for (size_t i = 0; i < sfColl.size(); ++i)
2325 {
2326 ComPtr<ISharedFolder> sf = sfColl[i];
2327 showSharedFolder(sf, details, "global mapping", "GlobalMapping", i + 1, numSharedFolders == 0);
2328 ++numSharedFolders;
2329 }
2330 }
2331#endif
2332 /* now VM mappings */
2333 {
2334 com::SafeIfaceArray <ISharedFolder> folders;
2335 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2336 for (size_t i = 0; i < folders.size(); ++i)
2337 {
2338 ComPtr<ISharedFolder> sf = folders[i];
2339 showSharedFolder(sf, details, "machine mapping", "MachineMapping", i + 1, numSharedFolders == 0);
2340 ++numSharedFolders;
2341 }
2342 }
2343 /* transient mappings */
2344 if (pConsole)
2345 {
2346 com::SafeIfaceArray <ISharedFolder> folders;
2347 CHECK_ERROR_RET(pConsole, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2348 for (size_t i = 0; i < folders.size(); ++i)
2349 {
2350 ComPtr<ISharedFolder> sf = folders[i];
2351 showSharedFolder(sf, details, "transient mapping", "TransientMapping", i + 1, numSharedFolders == 0);
2352 ++numSharedFolders;
2353 }
2354 }
2355 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
2356 RTPrintf("<none>\n");
2357 if (details != VMINFO_MACHINEREADABLE)
2358 RTPrintf("\n");
2359
2360 if (pConsole)
2361 {
2362 /*
2363 * Live VRDE info.
2364 */
2365 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2366 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2367 BOOL fActive = FALSE;
2368 ULONG cNumberOfClients = 0;
2369 LONG64 BeginTime = 0;
2370 LONG64 EndTime = 0;
2371 LONG64 BytesSent = 0;
2372 LONG64 BytesSentTotal = 0;
2373 LONG64 BytesReceived = 0;
2374 LONG64 BytesReceivedTotal = 0;
2375 Bstr User;
2376 Bstr Domain;
2377 Bstr ClientName;
2378 Bstr ClientIP;
2379 ULONG ClientVersion = 0;
2380 ULONG EncryptionStyle = 0;
2381
2382 if (!vrdeServerInfo.isNull())
2383 {
2384 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&fActive), rc);
2385 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&cNumberOfClients), rc);
2386 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), rc);
2387 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), rc);
2388 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), rc);
2389 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), rc);
2390 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), rc);
2391 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), rc);
2392 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), rc);
2393 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), rc);
2394 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), rc);
2395 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), rc);
2396 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), rc);
2397 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), rc);
2398 }
2399
2400 SHOW_BOOL_VALUE_EX("VRDEActiveConnection", "VRDE Connection:", fActive, "active", "not active");
2401 SHOW_ULONG_VALUE("VRDEClients=", "Clients so far:", cNumberOfClients, "");
2402
2403 if (cNumberOfClients > 0)
2404 {
2405 char szTimeValue[128];
2406 makeTimeStr(szTimeValue, sizeof(szTimeValue), BeginTime);
2407 if (fActive)
2408 SHOW_UTF8_STRING("VRDEStartTime", "Start time:", szTimeValue);
2409 else
2410 {
2411 SHOW_UTF8_STRING("VRDELastStartTime", "Last started:", szTimeValue);
2412 makeTimeStr(szTimeValue, sizeof(szTimeValue), EndTime);
2413 SHOW_UTF8_STRING("VRDELastEndTime", "Last ended:", szTimeValue);
2414 }
2415
2416 int64_t ThroughputSend = 0;
2417 int64_t ThroughputReceive = 0;
2418 if (EndTime != BeginTime)
2419 {
2420 ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime);
2421 ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime);
2422 }
2423 SHOW_LONG64_VALUE("VRDEBytesSent", "Sent:", BytesSent, "Bytes");
2424 SHOW_LONG64_VALUE("VRDEThroughputSend", "Average speed:", ThroughputSend, "B/s");
2425 SHOW_LONG64_VALUE("VRDEBytesSentTotal", "Sent total:", BytesSentTotal, "Bytes");
2426
2427 SHOW_LONG64_VALUE("VRDEBytesReceived", "Received:", BytesReceived, "Bytes");
2428 SHOW_LONG64_VALUE("VRDEThroughputReceive", "Speed:", ThroughputReceive, "B/s");
2429 SHOW_LONG64_VALUE("VRDEBytesReceivedTotal", "Received total:", BytesReceivedTotal, "Bytes");
2430
2431 if (fActive)
2432 {
2433 SHOW_BSTR_STRING("VRDEUserName", "User name:", User);
2434 SHOW_BSTR_STRING("VRDEDomain", "Domain:", Domain);
2435 SHOW_BSTR_STRING("VRDEClientName", "Client name:", ClientName);
2436 SHOW_BSTR_STRING("VRDEClientIP", "Client IP:", ClientIP);
2437 SHOW_ULONG_VALUE("VRDEClientVersion", "Client version:", ClientVersion, "");
2438 SHOW_UTF8_STRING("VRDEEncryption", "Encryption:", EncryptionStyle == 0 ? "RDP4" : "RDP5 (X.509)");
2439 }
2440 }
2441
2442 if (details != VMINFO_MACHINEREADABLE)
2443 RTPrintf("\n");
2444 }
2445
2446#ifdef VBOX_WITH_RECORDING
2447 {
2448 /* Video capture */
2449 BOOL fCaptureVideo = FALSE;
2450# ifdef VBOX_WITH_AUDIO_RECORDING
2451 BOOL fCaptureAudio = FALSE;
2452# endif
2453
2454 ComPtr<IRecordingSettings> recordingSettings;
2455 CHECK_ERROR_RET(machine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam()), rc);
2456
2457 SafeIfaceArray <IRecordingScreenSettings> saRecordingScreenScreens;
2458 CHECK_ERROR_RET(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saRecordingScreenScreens)), rc);
2459
2460 /* For now all screens have the same configuration; so take screen 0 and work with that. */
2461 ULONG fFeatures;
2462 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Features)(&fFeatures), rc);
2463 ULONG Width;
2464 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoWidth)(&Width), rc);
2465 ULONG Height;
2466 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoHeight)(&Height), rc);
2467 ULONG Rate;
2468 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoRate)(&Rate), rc);
2469 ULONG Fps;
2470 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoFPS)(&Fps), rc);
2471 Bstr bstrFile;
2472 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Filename)(bstrFile.asOutParam()), rc);
2473 Bstr bstrOptions;
2474 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Options)(bstrOptions.asOutParam()), rc);
2475
2476 Utf8Str strOptions(bstrOptions);
2477 size_t pos = 0;
2478 com::Utf8Str key, value;
2479 while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos)
2480 {
2481 if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0)
2482 {
2483 fCaptureVideo = value.compare("true", Utf8Str::CaseInsensitive) == 0;
2484 }
2485 else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0)
2486 {
2487# ifdef VBOX_WITH_AUDIO_RECORDING
2488 fCaptureAudio = value.compare("true", Utf8Str::CaseInsensitive) == 0;
2489# endif
2490 }
2491 }
2492
2493 SHOW_BOOL_VALUE_EX("videocap", "Capturing:", fCaptureVideo, "active", "not active");
2494# ifdef VBOX_WITH_AUDIO_RECORDING
2495 SHOW_BOOL_VALUE_EX("videocapaudio", "Capture audio:", fCaptureAudio, "active", "not active");
2496# endif
2497 szValue[0] = '\0';
2498 for (size_t i = 0, off = 0; i < saRecordingScreenScreens.size(); i++)
2499 {
2500 BOOL fEnabled;
2501 CHECK_ERROR_RET(saRecordingScreenScreens[i], COMGETTER(Enabled)(&fEnabled), rc);
2502 if (fEnabled && off < sizeof(szValue) - 3)
2503 off += RTStrPrintf(&szValue[off], sizeof(szValue) - off, off ? ",%zu" : "%zu", i);
2504 }
2505 SHOW_UTF8_STRING("capturescreens", "Capture screens:", szValue);
2506 SHOW_BSTR_STRING("capturefilename", "Capture file:", bstrFile);
2507 RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height);
2508 SHOW_UTF8_STRING("captureres", "Capture dimensions:", szValue);
2509 SHOW_ULONG_VALUE("capturevideorate", "Capture rate:", Rate, "kbps");
2510 SHOW_ULONG_VALUE("capturevideofps", "Capture FPS:", Fps, "kbps");
2511 SHOW_BSTR_STRING("captureopts", "Capture options:", bstrOptions);
2512
2513 if (details != VMINFO_MACHINEREADABLE)
2514 RTPrintf("\n");
2515 /** @todo Add more audio capturing profile / information here. */
2516 }
2517#endif /* VBOX_WITH_RECORDING */
2518
2519 if ( details == VMINFO_STANDARD
2520 || details == VMINFO_FULL
2521 || details == VMINFO_MACHINEREADABLE)
2522 {
2523 Bstr description;
2524 machine->COMGETTER(Description)(description.asOutParam());
2525 if (!description.isEmpty())
2526 {
2527 if (details == VMINFO_MACHINEREADABLE)
2528 outputMachineReadableString("description", &description);
2529 else
2530 RTPrintf("Description:\n%ls\n", description.raw());
2531 }
2532 }
2533
2534 if (details != VMINFO_MACHINEREADABLE)
2535 RTPrintf("Guest:\n\n");
2536
2537 SHOW_ULONG_PROP(machine, MemoryBalloonSize, "GuestMemoryBalloon", "Configured memory balloon size:", "MB");
2538
2539 if (pConsole)
2540 {
2541 ComPtr<IGuest> guest;
2542 rc = pConsole->COMGETTER(Guest)(guest.asOutParam());
2543 if (SUCCEEDED(rc) && !guest.isNull())
2544 {
2545 SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", "OS type:");
2546
2547 AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */
2548 rc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel);
2549 if (SUCCEEDED(rc))
2550 SHOW_ULONG_VALUE("GuestAdditionsRunLevel", "Additions run level:", (ULONG)guestRunLevel, "");
2551
2552 Bstr guestString;
2553 rc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam());
2554 if ( SUCCEEDED(rc)
2555 && !guestString.isEmpty())
2556 {
2557 ULONG uRevision;
2558 rc = guest->COMGETTER(AdditionsRevision)(&uRevision);
2559 if (FAILED(rc))
2560 uRevision = 0;
2561 RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision);
2562 SHOW_UTF8_STRING("GuestAdditionsVersion", "Additions version:", szValue);
2563 }
2564
2565 if (details != VMINFO_MACHINEREADABLE)
2566 RTPrintf("\nGuest Facilities:\n\n");
2567
2568 /* Print information about known Guest Additions facilities: */
2569 SafeIfaceArray <IAdditionsFacility> collFac;
2570 CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), rc);
2571 LONG64 lLastUpdatedMS;
2572 char szLastUpdated[32];
2573 AdditionsFacilityStatus_T curStatus;
2574 for (size_t index = 0; index < collFac.size(); ++index)
2575 {
2576 ComPtr<IAdditionsFacility> fac = collFac[index];
2577 if (fac)
2578 {
2579 CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), rc);
2580 if (!guestString.isEmpty())
2581 {
2582 CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), rc);
2583 CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), rc);
2584 if (details == VMINFO_MACHINEREADABLE)
2585 RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n",
2586 guestString.raw(), curStatus, lLastUpdatedMS);
2587 else
2588 {
2589 makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
2590 RTPrintf("Facility \"%ls\": %s (last update: %s)\n",
2591 guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated);
2592 }
2593 }
2594 else
2595 AssertMsgFailed(("Facility with undefined name retrieved!\n"));
2596 }
2597 else
2598 AssertMsgFailed(("Invalid facility returned!\n"));
2599 }
2600 if (!collFac.size() && details != VMINFO_MACHINEREADABLE)
2601 RTPrintf("No active facilities.\n");
2602 }
2603 }
2604
2605 if (details != VMINFO_MACHINEREADABLE)
2606 RTPrintf("\n");
2607
2608 /*
2609 * snapshots
2610 */
2611 ComPtr<ISnapshot> snapshot;
2612 rc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam());
2613 if (SUCCEEDED(rc) && snapshot)
2614 {
2615 ComPtr<ISnapshot> currentSnapshot;
2616 rc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam());
2617 if (SUCCEEDED(rc))
2618 {
2619 if (details != VMINFO_MACHINEREADABLE)
2620 RTPrintf("Snapshots:\n\n");
2621 showSnapshots(snapshot, currentSnapshot, details);
2622 }
2623 }
2624
2625 if (details != VMINFO_MACHINEREADABLE)
2626 RTPrintf("\n");
2627 return S_OK;
2628}
2629
2630#if defined(_MSC_VER)
2631# pragma optimize("", on)
2632# pragma warning(pop)
2633#endif
2634
2635static const RTGETOPTDEF g_aShowVMInfoOptions[] =
2636{
2637 { "--details", 'D', RTGETOPT_REQ_NOTHING },
2638 { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated
2639 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
2640 { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated
2641 { "--log", 'l', RTGETOPT_REQ_UINT32 },
2642};
2643
2644RTEXITCODE handleShowVMInfo(HandlerArg *a)
2645{
2646 HRESULT rc;
2647 const char *VMNameOrUuid = NULL;
2648 bool fLog = false;
2649 uint32_t uLogIdx = 0;
2650 bool fDetails = false;
2651 bool fMachinereadable = false;
2652
2653 int c;
2654 RTGETOPTUNION ValueUnion;
2655 RTGETOPTSTATE GetState;
2656 // start at 0 because main() has hacked both the argc and argv given to us
2657 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions),
2658 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2659 while ((c = RTGetOpt(&GetState, &ValueUnion)))
2660 {
2661 switch (c)
2662 {
2663 case 'D': // --details
2664 fDetails = true;
2665 break;
2666
2667 case 'M': // --machinereadable
2668 fMachinereadable = true;
2669 break;
2670
2671 case 'l': // --log
2672 fLog = true;
2673 uLogIdx = ValueUnion.u32;
2674 break;
2675
2676 case VINF_GETOPT_NOT_OPTION:
2677 if (!VMNameOrUuid)
2678 VMNameOrUuid = ValueUnion.psz;
2679 else
2680 return errorSyntax(USAGE_SHOWVMINFO, "Invalid parameter '%s'", ValueUnion.psz);
2681 break;
2682
2683 default:
2684 return errorGetOpt(USAGE_SHOWVMINFO, c, &ValueUnion);
2685 }
2686 }
2687
2688 /* check for required options */
2689 if (!VMNameOrUuid)
2690 return errorSyntax(USAGE_SHOWVMINFO, "VM name or UUID required");
2691
2692 /* try to find the given machine */
2693 ComPtr<IMachine> machine;
2694 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(),
2695 machine.asOutParam()));
2696 if (FAILED(rc))
2697 return RTEXITCODE_FAILURE;
2698
2699 /* Printing the log is exclusive. */
2700 if (fLog && (fMachinereadable || fDetails))
2701 return errorSyntax(USAGE_SHOWVMINFO, "Option --log is exclusive");
2702
2703 if (fLog)
2704 {
2705 ULONG64 uOffset = 0;
2706 SafeArray<BYTE> aLogData;
2707 size_t cbLogData;
2708 while (true)
2709 {
2710 /* Reset the array */
2711 aLogData.setNull();
2712 /* Fetch a chunk of the log file */
2713 CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, uOffset, _1M,
2714 ComSafeArrayAsOutParam(aLogData)));
2715 cbLogData = aLogData.size();
2716 if (cbLogData == 0)
2717 break;
2718 /* aLogData has a platform dependent line ending, standardize on
2719 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
2720 * Windows. Otherwise we end up with CR/CR/LF on Windows. */
2721 size_t cbLogDataPrint = cbLogData;
2722 for (BYTE *s = aLogData.raw(), *d = s;
2723 s - aLogData.raw() < (ssize_t)cbLogData;
2724 s++, d++)
2725 {
2726 if (*s == '\r')
2727 {
2728 /* skip over CR, adjust destination */
2729 d--;
2730 cbLogDataPrint--;
2731 }
2732 else if (s != d)
2733 *d = *s;
2734 }
2735 RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint);
2736 uOffset += cbLogData;
2737 }
2738 }
2739 else
2740 {
2741 /* 2nd option can be -details or -argdump */
2742 VMINFO_DETAILS details = VMINFO_NONE;
2743 if (fMachinereadable)
2744 details = VMINFO_MACHINEREADABLE;
2745 else if (fDetails)
2746 details = VMINFO_FULL;
2747 else
2748 details = VMINFO_STANDARD;
2749
2750 /* open an existing session for the VM */
2751 rc = machine->LockMachine(a->session, LockType_Shared);
2752 if (SUCCEEDED(rc))
2753 /* get the session machine */
2754 rc = a->session->COMGETTER(Machine)(machine.asOutParam());
2755
2756 rc = showVMInfo(a->virtualBox, machine, a->session, details);
2757
2758 a->session->UnlockMachine();
2759 }
2760
2761 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2762}
2763
2764#endif /* !VBOX_ONLY_DOCS */
2765/* 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