VirtualBox

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

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

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 114.2 KB
Line 
1/* $Id: VBoxManageInfo.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'showvminfo' command and helper routines.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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
1460#endif
1461#ifdef VBOX_WITH_VIRTIO_NET_1_0
1462 case NetworkAdapterType_Virtio_1_0: pszNICType = "virtio_1.0"; break;
1463#endif
1464 default: AssertFailed(); pszNICType = "unknown"; break;
1465 }
1466
1467 /* reported line speed */
1468 ULONG ulLineSpeed;
1469 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1470
1471 /* boot priority of the adapter */
1472 ULONG ulBootPriority;
1473 nic->COMGETTER(BootPriority)(&ulBootPriority);
1474
1475 /* bandwidth group */
1476 ComObjPtr<IBandwidthGroup> pBwGroup;
1477 Bstr strBwGroup;
1478 nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());
1479 if (!pBwGroup.isNull())
1480 pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam());
1481
1482 if (details == VMINFO_MACHINEREADABLE)
1483 {
1484 RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw());
1485 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1486 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str());
1487 RTPrintf("nictype%d=\"%s\"\n", currentNIC + 1, pszNICType);
1488 RTPrintf("nicspeed%d=\"%d\"\n", currentNIC + 1, ulLineSpeed);
1489 }
1490 else
1491 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",
1492 szNm, strMACAddress.raw(), strAttachment.c_str(),
1493 fConnected ? "on" : "off",
1494 fTraceEnabled ? "on" : "off",
1495 traceFile.isEmpty() ? Bstr("none").raw() : traceFile.raw(),
1496 pszNICType,
1497 ulLineSpeed / 1000,
1498 (int)ulBootPriority,
1499 pszPromiscuousGuestPolicy,
1500 strBwGroup.isEmpty() ? Bstr("none").raw() : strBwGroup.raw());
1501 if (strNatSettings.length())
1502 RTPrintf(strNatSettings.c_str());
1503 if (strNatForwardings.length())
1504 RTPrintf(strNatForwardings.c_str());
1505 }
1506 }
1507 }
1508
1509 /* Pointing device information */
1510 PointingHIDType_T aPointingHID;
1511 const char *pszHID = "Unknown";
1512 const char *pszMrHID = "unknown";
1513 machine->COMGETTER(PointingHIDType)(&aPointingHID);
1514 switch (aPointingHID)
1515 {
1516 case PointingHIDType_None:
1517 pszHID = "None";
1518 pszMrHID = "none";
1519 break;
1520 case PointingHIDType_PS2Mouse:
1521 pszHID = "PS/2 Mouse";
1522 pszMrHID = "ps2mouse";
1523 break;
1524 case PointingHIDType_USBMouse:
1525 pszHID = "USB Mouse";
1526 pszMrHID = "usbmouse";
1527 break;
1528 case PointingHIDType_USBTablet:
1529 pszHID = "USB Tablet";
1530 pszMrHID = "usbtablet";
1531 break;
1532 case PointingHIDType_ComboMouse:
1533 pszHID = "USB Tablet and PS/2 Mouse";
1534 pszMrHID = "combomouse";
1535 break;
1536 case PointingHIDType_USBMultiTouch:
1537 pszHID = "USB Multi-Touch";
1538 pszMrHID = "usbmultitouch";
1539 break;
1540 default:
1541 break;
1542 }
1543 SHOW_UTF8_STRING("hidpointing", "Pointing Device:", details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
1544
1545 /* Keyboard device information */
1546 KeyboardHIDType_T aKeyboardHID;
1547 machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID);
1548 pszHID = "Unknown";
1549 pszMrHID = "unknown";
1550 switch (aKeyboardHID)
1551 {
1552 case KeyboardHIDType_None:
1553 pszHID = "None";
1554 pszMrHID = "none";
1555 break;
1556 case KeyboardHIDType_PS2Keyboard:
1557 pszHID = "PS/2 Keyboard";
1558 pszMrHID = "ps2kbd";
1559 break;
1560 case KeyboardHIDType_USBKeyboard:
1561 pszHID = "USB Keyboard";
1562 pszMrHID = "usbkbd";
1563 break;
1564 case KeyboardHIDType_ComboKeyboard:
1565 pszHID = "USB and PS/2 Keyboard";
1566 pszMrHID = "combokbd";
1567 break;
1568 default:
1569 break;
1570 }
1571 SHOW_UTF8_STRING("hidkeyboard", "Keyboard Device:", details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
1572
1573 ComPtr<ISystemProperties> sysProps;
1574 pVirtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
1575
1576 /* get the maximum amount of UARTs */
1577 ULONG maxUARTs = 0;
1578 sysProps->COMGETTER(SerialPortCount)(&maxUARTs);
1579 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
1580 {
1581 ComPtr<ISerialPort> uart;
1582 rc = machine->GetSerialPort(currentUART, uart.asOutParam());
1583 if (SUCCEEDED(rc) && uart)
1584 {
1585 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "uart%u" : "UART %u:", currentUART + 1);
1586
1587 /* show the config of this UART */
1588 BOOL fEnabled;
1589 uart->COMGETTER(Enabled)(&fEnabled);
1590 if (!fEnabled)
1591 {
1592 if (details == VMINFO_MACHINEREADABLE)
1593 RTPrintf("%s=\"off\"\n", szNm);
1594 else
1595 RTPrintf("%-28s disabled\n", szNm);
1596 }
1597 else
1598 {
1599 ULONG ulIRQ, ulIOBase;
1600 PortMode_T HostMode;
1601 Bstr path;
1602 BOOL fServer;
1603 UartType_T UartType;
1604 uart->COMGETTER(IRQ)(&ulIRQ);
1605 uart->COMGETTER(IOBase)(&ulIOBase);
1606 uart->COMGETTER(Path)(path.asOutParam());
1607 uart->COMGETTER(Server)(&fServer);
1608 uart->COMGETTER(HostMode)(&HostMode);
1609 uart->COMGETTER(UartType)(&UartType);
1610
1611 if (details == VMINFO_MACHINEREADABLE)
1612 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
1613 else
1614 RTPrintf("%-28s I/O base: %#06x, IRQ: %d", szNm, ulIOBase, ulIRQ);
1615 switch (HostMode)
1616 {
1617 default:
1618 case PortMode_Disconnected:
1619 if (details == VMINFO_MACHINEREADABLE)
1620 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
1621 else
1622 RTPrintf(", disconnected");
1623 break;
1624 case PortMode_RawFile:
1625 if (details == VMINFO_MACHINEREADABLE)
1626 RTPrintf("uartmode%d=\"file,%ls\"\n", currentUART + 1,
1627 path.raw());
1628 else
1629 RTPrintf(", attached to raw file '%ls'\n",
1630 path.raw());
1631 break;
1632 case PortMode_TCP:
1633 if (details == VMINFO_MACHINEREADABLE)
1634 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
1635 fServer ? "tcpserver" : "tcpclient", path.raw());
1636 else
1637 RTPrintf(", attached to tcp (%s) '%ls'",
1638 fServer ? "server" : "client", path.raw());
1639 break;
1640 case PortMode_HostPipe:
1641 if (details == VMINFO_MACHINEREADABLE)
1642 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
1643 fServer ? "server" : "client", path.raw());
1644 else
1645 RTPrintf(", attached to pipe (%s) '%ls'",
1646 fServer ? "server" : "client", path.raw());
1647 break;
1648 case PortMode_HostDevice:
1649 if (details == VMINFO_MACHINEREADABLE)
1650 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
1651 path.raw());
1652 else
1653 RTPrintf(", attached to device '%ls'", path.raw());
1654 break;
1655 }
1656 switch (UartType)
1657 {
1658 default:
1659 case UartType_U16450:
1660 if (details == VMINFO_MACHINEREADABLE)
1661 RTPrintf("uarttype%d=\"16450\"\n", currentUART + 1);
1662 else
1663 RTPrintf(", 16450\n");
1664 break;
1665 case UartType_U16550A:
1666 if (details == VMINFO_MACHINEREADABLE)
1667 RTPrintf("uarttype%d=\"16550A\"\n", currentUART + 1);
1668 else
1669 RTPrintf(", 16550A\n");
1670 break;
1671 case UartType_U16750:
1672 if (details == VMINFO_MACHINEREADABLE)
1673 RTPrintf("uarttype%d=\"16750\"\n", currentUART + 1);
1674 else
1675 RTPrintf(", 16750\n");
1676 break;
1677 }
1678 }
1679 }
1680 }
1681
1682 /* get the maximum amount of LPTs */
1683 ULONG maxLPTs = 0;
1684 sysProps->COMGETTER(ParallelPortCount)(&maxLPTs);
1685 for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++)
1686 {
1687 ComPtr<IParallelPort> lpt;
1688 rc = machine->GetParallelPort(currentLPT, lpt.asOutParam());
1689 if (SUCCEEDED(rc) && lpt)
1690 {
1691 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "lpt%u" : "LPT %u:", currentLPT + 1);
1692
1693 /* show the config of this LPT */
1694 BOOL fEnabled;
1695 lpt->COMGETTER(Enabled)(&fEnabled);
1696 if (!fEnabled)
1697 {
1698 if (details == VMINFO_MACHINEREADABLE)
1699 RTPrintf("%s=\"off\"\n", szNm);
1700 else
1701 RTPrintf("%-28s disabled\n", szNm);
1702 }
1703 else
1704 {
1705 ULONG ulIRQ, ulIOBase;
1706 Bstr path;
1707 lpt->COMGETTER(IRQ)(&ulIRQ);
1708 lpt->COMGETTER(IOBase)(&ulIOBase);
1709 lpt->COMGETTER(Path)(path.asOutParam());
1710
1711 if (details == VMINFO_MACHINEREADABLE)
1712 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
1713 else
1714 RTPrintf("%-28s I/O base: %#06x, IRQ: %d", szNm, ulIOBase, ulIRQ);
1715 if (details == VMINFO_MACHINEREADABLE)
1716 RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1, path.raw());
1717 else
1718 RTPrintf(", attached to device '%ls'\n", path.raw());
1719 }
1720 }
1721 }
1722
1723 ComPtr<IAudioAdapter> AudioAdapter;
1724 rc = machine->COMGETTER(AudioAdapter)(AudioAdapter.asOutParam());
1725 if (SUCCEEDED(rc))
1726 {
1727 const char *pszDrv = "Unknown";
1728 const char *pszCtrl = "Unknown";
1729 const char *pszCodec = "Unknown";
1730 BOOL fEnabled;
1731 rc = AudioAdapter->COMGETTER(Enabled)(&fEnabled);
1732 if (SUCCEEDED(rc) && fEnabled)
1733 {
1734 AudioDriverType_T enmDrvType;
1735 rc = AudioAdapter->COMGETTER(AudioDriver)(&enmDrvType);
1736 switch (enmDrvType)
1737 {
1738 case AudioDriverType_Null:
1739 if (details == VMINFO_MACHINEREADABLE)
1740 pszDrv = "null";
1741 else
1742 pszDrv = "Null";
1743 break;
1744 case AudioDriverType_WinMM:
1745 if (details == VMINFO_MACHINEREADABLE)
1746 pszDrv = "winmm";
1747 else
1748 pszDrv = "WINMM";
1749 break;
1750 case AudioDriverType_DirectSound:
1751 if (details == VMINFO_MACHINEREADABLE)
1752 pszDrv = "dsound";
1753 else
1754 pszDrv = "DSOUND";
1755 break;
1756 case AudioDriverType_OSS:
1757 if (details == VMINFO_MACHINEREADABLE)
1758 pszDrv = "oss";
1759 else
1760 pszDrv = "OSS";
1761 break;
1762 case AudioDriverType_ALSA:
1763 if (details == VMINFO_MACHINEREADABLE)
1764 pszDrv = "alsa";
1765 else
1766 pszDrv = "ALSA";
1767 break;
1768 case AudioDriverType_Pulse:
1769 if (details == VMINFO_MACHINEREADABLE)
1770 pszDrv = "pulse";
1771 else
1772 pszDrv = "PulseAudio";
1773 break;
1774 case AudioDriverType_CoreAudio:
1775 if (details == VMINFO_MACHINEREADABLE)
1776 pszDrv = "coreaudio";
1777 else
1778 pszDrv = "CoreAudio";
1779 break;
1780 case AudioDriverType_SolAudio:
1781 if (details == VMINFO_MACHINEREADABLE)
1782 pszDrv = "solaudio";
1783 else
1784 pszDrv = "SolAudio";
1785 break;
1786 default:
1787 if (details == VMINFO_MACHINEREADABLE)
1788 pszDrv = "unknown";
1789 break;
1790 }
1791 AudioControllerType_T enmCtrlType;
1792 rc = AudioAdapter->COMGETTER(AudioController)(&enmCtrlType);
1793 switch (enmCtrlType)
1794 {
1795 case AudioControllerType_AC97:
1796 if (details == VMINFO_MACHINEREADABLE)
1797 pszCtrl = "ac97";
1798 else
1799 pszCtrl = "AC97";
1800 break;
1801 case AudioControllerType_SB16:
1802 if (details == VMINFO_MACHINEREADABLE)
1803 pszCtrl = "sb16";
1804 else
1805 pszCtrl = "SB16";
1806 break;
1807 case AudioControllerType_HDA:
1808 if (details == VMINFO_MACHINEREADABLE)
1809 pszCtrl = "hda";
1810 else
1811 pszCtrl = "HDA";
1812 break;
1813 default:
1814 break;
1815 }
1816 AudioCodecType_T enmCodecType;
1817 rc = AudioAdapter->COMGETTER(AudioCodec)(&enmCodecType);
1818 switch (enmCodecType)
1819 {
1820 case AudioCodecType_SB16:
1821 pszCodec = "SB16";
1822 break;
1823 case AudioCodecType_STAC9700:
1824 pszCodec = "STAC9700";
1825 break;
1826 case AudioCodecType_AD1980:
1827 pszCodec = "AD1980";
1828 break;
1829 case AudioCodecType_STAC9221:
1830 pszCodec = "STAC9221";
1831 break;
1832 case AudioCodecType_Null: break; /* Shut up MSC. */
1833 default: break;
1834 }
1835 }
1836 else
1837 fEnabled = FALSE;
1838
1839 if (details == VMINFO_MACHINEREADABLE)
1840 RTPrintf("audio=\"%s\"\n", fEnabled ? pszDrv : "none");
1841 else
1842 {
1843 RTPrintf("%-28s %s", "Audio:", fEnabled ? "enabled" : "disabled");
1844 if (fEnabled)
1845 RTPrintf(" (Driver: %s, Controller: %s, Codec: %s)", pszDrv, pszCtrl, pszCodec);
1846 RTPrintf("\n");
1847 }
1848 SHOW_BOOLEAN_PROP(AudioAdapter, EnabledOut, "audio_out", "Audio playback:");
1849 SHOW_BOOLEAN_PROP(AudioAdapter, EnabledIn, "audio_in", "Audio capture:");
1850 }
1851
1852 /* Shared clipboard */
1853 {
1854 const char *psz;
1855 ClipboardMode_T enmMode = (ClipboardMode_T)0;
1856 rc = machine->COMGETTER(ClipboardMode)(&enmMode);
1857 switch (enmMode)
1858 {
1859 case ClipboardMode_Disabled:
1860 psz = "disabled";
1861 break;
1862 case ClipboardMode_HostToGuest:
1863 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : "HostToGuest";
1864 break;
1865 case ClipboardMode_GuestToHost:
1866 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : "GuestToHost";
1867 break;
1868 case ClipboardMode_Bidirectional:
1869 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : "Bidirectional";
1870 break;
1871 default:
1872 psz = details == VMINFO_MACHINEREADABLE ? "unknown" : "Unknown";
1873 break;
1874 }
1875 SHOW_UTF8_STRING("clipboard", "Clipboard Mode:", psz);
1876#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
1877 SHOW_BOOLEAN_PROP(machine, ClipboardFileTransfersEnabled, "clipboard_file_transfers", "Clipboard file transfers:");
1878#endif
1879 }
1880
1881 /* Drag and drop */
1882 {
1883 const char *psz;
1884 DnDMode_T enmMode;
1885 rc = machine->COMGETTER(DnDMode)(&enmMode);
1886 switch (enmMode)
1887 {
1888 case DnDMode_Disabled:
1889 psz = "disabled";
1890 break;
1891 case DnDMode_HostToGuest:
1892 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : "HostToGuest";
1893 break;
1894 case DnDMode_GuestToHost:
1895 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : "GuestToHost";
1896 break;
1897 case DnDMode_Bidirectional:
1898 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : "Bidirectional";
1899 break;
1900 default:
1901 psz = details == VMINFO_MACHINEREADABLE ? "unknown" : "Unknown";
1902 break;
1903 }
1904 SHOW_UTF8_STRING("draganddrop", "Drag and drop Mode:", psz);
1905 }
1906
1907 {
1908 SessionState_T sessState;
1909 rc = machine->COMGETTER(SessionState)(&sessState);
1910 if (SUCCEEDED(rc) && sessState != SessionState_Unlocked)
1911 {
1912 Bstr sessName;
1913 rc = machine->COMGETTER(SessionName)(sessName.asOutParam());
1914 if (SUCCEEDED(rc) && !sessName.isEmpty())
1915 SHOW_BSTR_STRING("SessionName", "Session name:", sessName);
1916 }
1917 }
1918
1919 if (pConsole)
1920 {
1921 do
1922 {
1923 ComPtr<IDisplay> display;
1924 rc = pConsole->COMGETTER(Display)(display.asOutParam());
1925 if (rc == E_ACCESSDENIED || display.isNull())
1926 break; /* VM not powered up */
1927 if (FAILED(rc))
1928 {
1929 com::GlueHandleComError(pConsole, "COMGETTER(Display)(display.asOutParam())", rc, __FILE__, __LINE__);
1930 return rc;
1931 }
1932 ULONG xRes, yRes, bpp;
1933 LONG xOrigin, yOrigin;
1934 GuestMonitorStatus_T monitorStatus;
1935 rc = display->GetScreenResolution(0, &xRes, &yRes, &bpp, &xOrigin, &yOrigin, &monitorStatus);
1936 if (rc == E_ACCESSDENIED)
1937 break; /* VM not powered up */
1938 if (FAILED(rc))
1939 {
1940 com::ErrorInfo info(display, COM_IIDOF(IDisplay));
1941 GluePrintErrorInfo(info);
1942 return rc;
1943 }
1944 if (details == VMINFO_MACHINEREADABLE)
1945 RTPrintf("VideoMode=\"%d,%d,%d\"@%d,%d %d\n", xRes, yRes, bpp, xOrigin, yOrigin, monitorStatus);
1946 else
1947 {
1948 const char *pszMonitorStatus = "unknown status";
1949 switch (monitorStatus)
1950 {
1951 case GuestMonitorStatus_Blank: pszMonitorStatus = "blank"; break;
1952 case GuestMonitorStatus_Enabled: pszMonitorStatus = "enabled"; break;
1953 case GuestMonitorStatus_Disabled: pszMonitorStatus = "disabled"; break;
1954 default: break;
1955 }
1956 RTPrintf("%-28s %dx%dx%d at %d,%d %s\n", "Video mode:", xRes, yRes, bpp, xOrigin, yOrigin, pszMonitorStatus);
1957 }
1958 }
1959 while (0);
1960 }
1961
1962 /*
1963 * Remote Desktop
1964 */
1965 ComPtr<IVRDEServer> vrdeServer;
1966 rc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam());
1967 if (SUCCEEDED(rc) && vrdeServer)
1968 {
1969 BOOL fEnabled = false;
1970 vrdeServer->COMGETTER(Enabled)(&fEnabled);
1971 if (fEnabled)
1972 {
1973 LONG currentPort = -1;
1974 Bstr ports;
1975 vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam());
1976 Bstr address;
1977 vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam());
1978 BOOL fMultiCon;
1979 vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
1980 BOOL fReuseCon;
1981 vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon);
1982 Bstr videoChannel;
1983 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam());
1984 BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0)
1985 || (videoChannel == "1");
1986 Bstr videoChannelQuality;
1987 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam());
1988 AuthType_T authType = (AuthType_T)0;
1989 const char *strAuthType;
1990 vrdeServer->COMGETTER(AuthType)(&authType);
1991 switch (authType)
1992 {
1993 case AuthType_Null:
1994 strAuthType = "null";
1995 break;
1996 case AuthType_External:
1997 strAuthType = "external";
1998 break;
1999 case AuthType_Guest:
2000 strAuthType = "guest";
2001 break;
2002 default:
2003 strAuthType = "unknown";
2004 break;
2005 }
2006 if (pConsole)
2007 {
2008 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2009 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2010 if (!vrdeServerInfo.isNull())
2011 {
2012 rc = vrdeServerInfo->COMGETTER(Port)(&currentPort);
2013 if (rc == E_ACCESSDENIED)
2014 {
2015 currentPort = -1; /* VM not powered up */
2016 }
2017 else if (FAILED(rc))
2018 {
2019 com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo));
2020 GluePrintErrorInfo(info);
2021 return rc;
2022 }
2023 }
2024 }
2025 if (details == VMINFO_MACHINEREADABLE)
2026 {
2027 RTPrintf("vrde=\"on\"\n");
2028 RTPrintf("vrdeport=%d\n", currentPort);
2029 RTPrintf("vrdeports=\"%ls\"\n", ports.raw());
2030 RTPrintf("vrdeaddress=\"%ls\"\n", address.raw());
2031 RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType);
2032 RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off");
2033 RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off");
2034 RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off");
2035 if (fVideoChannel)
2036 RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw());
2037 }
2038 else
2039 {
2040 if (address.isEmpty())
2041 address = "0.0.0.0";
2042 RTPrintf("%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n",
2043 "VRDE:", address.raw(), ports.raw(), fMultiCon ? "on" : "off", fReuseCon ? "on" : "off", strAuthType);
2044 if (pConsole && currentPort != -1 && currentPort != 0)
2045 RTPrintf("%-28s %d\n", "VRDE port:", currentPort);
2046 if (fVideoChannel)
2047 RTPrintf("%-28s enabled (Quality %ls)\n", "Video redirection:", videoChannelQuality.raw());
2048 else
2049 RTPrintf("%-28s disabled\n", "Video redirection:");
2050 }
2051 com::SafeArray<BSTR> aProperties;
2052 if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties))))
2053 {
2054 unsigned i;
2055 for (i = 0; i < aProperties.size(); ++i)
2056 {
2057 Bstr value;
2058 vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam());
2059 if (details == VMINFO_MACHINEREADABLE)
2060 {
2061 if (value.isEmpty())
2062 RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]);
2063 else
2064 RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw());
2065 }
2066 else
2067 {
2068 if (value.isEmpty())
2069 RTPrintf("%-28s: %-10lS = <not set>\n", "VRDE property", aProperties[i]);
2070 else
2071 RTPrintf("%-28s: %-10lS = \"%ls\"\n", "VRDE property", aProperties[i], value.raw());
2072 }
2073 }
2074 }
2075 }
2076 else
2077 {
2078 if (details == VMINFO_MACHINEREADABLE)
2079 RTPrintf("vrde=\"off\"\n");
2080 else
2081 RTPrintf("%-28s disabled\n", "VRDE:");
2082 }
2083 }
2084
2085 /*
2086 * USB.
2087 */
2088 SafeIfaceArray<IUSBController> USBCtlColl;
2089 rc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl));
2090 if (SUCCEEDED(rc))
2091 {
2092 bool fOhciEnabled = false;
2093 bool fEhciEnabled = false;
2094 bool fXhciEnabled = false;
2095
2096 for (unsigned i = 0; i < USBCtlColl.size(); i++)
2097 {
2098 USBControllerType_T enmType;
2099
2100 rc = USBCtlColl[i]->COMGETTER(Type)(&enmType);
2101 if (SUCCEEDED(rc))
2102 {
2103 switch (enmType)
2104 {
2105 case USBControllerType_OHCI:
2106 fOhciEnabled = true;
2107 break;
2108 case USBControllerType_EHCI:
2109 fEhciEnabled = true;
2110 break;
2111 case USBControllerType_XHCI:
2112 fXhciEnabled = true;
2113 break;
2114 default:
2115 break;
2116 }
2117 }
2118 }
2119
2120 SHOW_BOOL_VALUE("usb", "OHCI USB:", fOhciEnabled);
2121 SHOW_BOOL_VALUE("ehci", "EHCI USB:", fEhciEnabled);
2122 SHOW_BOOL_VALUE("xhci", "xHCI USB:", fXhciEnabled);
2123 }
2124
2125 ComPtr<IUSBDeviceFilters> USBFlts;
2126 rc = machine->COMGETTER(USBDeviceFilters)(USBFlts.asOutParam());
2127 if (SUCCEEDED(rc))
2128 {
2129 SafeIfaceArray <IUSBDeviceFilter> Coll;
2130 rc = USBFlts->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll));
2131 if (SUCCEEDED(rc))
2132 {
2133 if (details != VMINFO_MACHINEREADABLE)
2134 RTPrintf("\nUSB Device Filters:\n\n");
2135
2136 if (Coll.size() == 0)
2137 {
2138 if (details != VMINFO_MACHINEREADABLE)
2139 RTPrintf("<none>\n\n");
2140 }
2141 else
2142 {
2143 for (size_t index = 0; index < Coll.size(); ++index)
2144 {
2145 ComPtr<IUSBDeviceFilter> DevPtr = Coll[index];
2146
2147 if (details != VMINFO_MACHINEREADABLE)
2148 SHOW_UTF8_STRING("index", "Index:", FmtNm(szNm, "%zu", index));
2149 SHOW_BOOLEAN_PROP_EX(DevPtr, Active, FmtNm(szNm, "USBFilterActive%zu", index + 1), "Active:", "yes", "no");
2150 SHOW_STRING_PROP(DevPtr, Name, FmtNm(szNm, "USBFilterName%zu", index + 1), "Name:");
2151 SHOW_STRING_PROP(DevPtr, VendorId, FmtNm(szNm, "USBFilterVendorId%zu", index + 1), "VendorId:");
2152 SHOW_STRING_PROP(DevPtr, ProductId, FmtNm(szNm, "USBFilterProductId%zu", index + 1), "ProductId:");
2153 SHOW_STRING_PROP(DevPtr, Revision, FmtNm(szNm, "USBFilterRevision%zu", index + 1), "Revision:");
2154 SHOW_STRING_PROP(DevPtr, Manufacturer, FmtNm(szNm, "USBFilterManufacturer%zu", index + 1), "Manufacturer:");
2155 SHOW_STRING_PROP(DevPtr, Product, FmtNm(szNm, "USBFilterProduct%zu", index + 1), "Product:");
2156 SHOW_STRING_PROP(DevPtr, Remote, FmtNm(szNm, "USBFilterRemote%zu", index + 1), "Remote:");
2157 SHOW_STRING_PROP(DevPtr, SerialNumber, FmtNm(szNm, "USBFilterSerialNumber%zu", index + 1), "Serial Number:");
2158 if (details != VMINFO_MACHINEREADABLE)
2159 {
2160 ULONG fMaskedIfs;
2161 CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), rc);
2162 if (fMaskedIfs)
2163 RTPrintf("%-28s %#010x\n", "Masked Interfaces:", fMaskedIfs);
2164 RTPrintf("\n");
2165 }
2166 }
2167 }
2168 }
2169
2170 if (pConsole)
2171 {
2172 /* scope */
2173 {
2174 if (details != VMINFO_MACHINEREADABLE)
2175 RTPrintf("Available remote USB devices:\n\n");
2176
2177 SafeIfaceArray <IHostUSBDevice> coll;
2178 CHECK_ERROR_RET(pConsole, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), rc);
2179
2180 if (coll.size() == 0)
2181 {
2182 if (details != VMINFO_MACHINEREADABLE)
2183 RTPrintf("<none>\n\n");
2184 }
2185 else
2186 {
2187 /* This code is duplicated below, with USBAttach as prefix. */
2188 const char *pszPfx = "USBRemote";
2189 for (size_t i = 0; i < coll.size(); ++i)
2190 {
2191 ComPtr<IHostUSBDevice> dev = coll[i];
2192
2193 SHOW_STRING_PROP(dev, Id, FmtNm(szNm, "%sActive%zu", pszPfx, i + 1), "UUID:");
2194 SHOW_USHORT_PROP_EX2(dev, VendorId, FmtNm(szNm, "%sVendorId%zu", pszPfx, i + 1), "VendorId:", "", "%#06x", "%#06x (%04X)");
2195 SHOW_USHORT_PROP_EX2(dev, ProductId, FmtNm(szNm, "%sProductId%zu", pszPfx, i + 1), "ProductId:", "", "%#06x", "%#06x (%04X)");
2196
2197 USHORT bcdRevision;
2198 CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), rc);
2199 if (details == VMINFO_MACHINEREADABLE)
2200 RTStrPrintf(szValue, sizeof(szValue), "%#04x%02x", bcdRevision >> 8, bcdRevision & 0xff);
2201 else
2202 RTStrPrintf(szValue, sizeof(szValue), "%u.%u (%02u%02u)\n",
2203 bcdRevision >> 8, bcdRevision & 0xff, bcdRevision >> 8, bcdRevision & 0xff);
2204 SHOW_UTF8_STRING(FmtNm(szNm, "%sRevision%zu", pszPfx, i + 1), "Revision:", szValue);
2205
2206 SHOW_STRING_PROP_NOT_EMPTY(dev, Manufacturer, FmtNm(szNm, "%sManufacturer%zu", pszPfx, i + 1), "Manufacturer:");
2207 SHOW_STRING_PROP_NOT_EMPTY(dev, Product, FmtNm(szNm, "%sProduct%zu", pszPfx, i + 1), "Product:");
2208 SHOW_STRING_PROP_NOT_EMPTY(dev, SerialNumber, FmtNm(szNm, "%sSerialNumber%zu", pszPfx, i + 1), "SerialNumber:");
2209 SHOW_STRING_PROP_NOT_EMPTY(dev, Address, FmtNm(szNm, "%sAddress%zu", pszPfx, i + 1), "Address:");
2210
2211 if (details != VMINFO_MACHINEREADABLE)
2212 RTPrintf("\n");
2213 }
2214 }
2215 }
2216
2217 /* scope */
2218 {
2219 if (details != VMINFO_MACHINEREADABLE)
2220 RTPrintf("Currently Attached USB Devices:\n\n");
2221
2222 SafeIfaceArray <IUSBDevice> coll;
2223 CHECK_ERROR_RET(pConsole, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), rc);
2224
2225 if (coll.size() == 0)
2226 {
2227 if (details != VMINFO_MACHINEREADABLE)
2228 RTPrintf("<none>\n\n");
2229 }
2230 else
2231 {
2232 /* This code is duplicated below, with USBAttach as prefix. */
2233 const char *pszPfx = "USBAttach";
2234 for (size_t i = 0; i < coll.size(); ++i)
2235 {
2236 ComPtr<IUSBDevice> dev = coll[i];
2237
2238 SHOW_STRING_PROP(dev, Id, FmtNm(szNm, "%sActive%zu", pszPfx, i + 1), "UUID:");
2239 SHOW_USHORT_PROP_EX2(dev, VendorId, FmtNm(szNm, "%sVendorId%zu", pszPfx, i + 1), "VendorId:", "", "%#06x", "%#06x (%04X)");
2240 SHOW_USHORT_PROP_EX2(dev, ProductId, FmtNm(szNm, "%sProductId%zu", pszPfx, i + 1), "ProductId:", "", "%#06x", "%#06x (%04X)");
2241
2242 USHORT bcdRevision;
2243 CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), rc);
2244 if (details == VMINFO_MACHINEREADABLE)
2245 RTStrPrintf(szValue, sizeof(szValue), "%#04x%02x", bcdRevision >> 8, bcdRevision & 0xff);
2246 else
2247 RTStrPrintf(szValue, sizeof(szValue), "%u.%u (%02u%02u)\n",
2248 bcdRevision >> 8, bcdRevision & 0xff, bcdRevision >> 8, bcdRevision & 0xff);
2249 SHOW_UTF8_STRING(FmtNm(szNm, "%sRevision%zu", pszPfx, i + 1), "Revision:", szValue);
2250
2251 SHOW_STRING_PROP_NOT_EMPTY(dev, Manufacturer, FmtNm(szNm, "%sManufacturer%zu", pszPfx, i + 1), "Manufacturer:");
2252 SHOW_STRING_PROP_NOT_EMPTY(dev, Product, FmtNm(szNm, "%sProduct%zu", pszPfx, i + 1), "Product:");
2253 SHOW_STRING_PROP_NOT_EMPTY(dev, SerialNumber, FmtNm(szNm, "%sSerialNumber%zu", pszPfx, i + 1), "SerialNumber:");
2254 SHOW_STRING_PROP_NOT_EMPTY(dev, Address, FmtNm(szNm, "%sAddress%zu", pszPfx, i + 1), "Address:");
2255
2256 if (details != VMINFO_MACHINEREADABLE)
2257 RTPrintf("\n");
2258 }
2259 }
2260 }
2261 }
2262 } /* USB */
2263
2264#ifdef VBOX_WITH_PCI_PASSTHROUGH
2265 /* Host PCI passthrough devices */
2266 {
2267 SafeIfaceArray <IPCIDeviceAttachment> assignments;
2268 rc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
2269 if (SUCCEEDED(rc))
2270 {
2271 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2272 {
2273 RTPrintf("\nAttached physical PCI devices:\n\n");
2274 }
2275
2276 for (size_t index = 0; index < assignments.size(); ++index)
2277 {
2278 ComPtr<IPCIDeviceAttachment> Assignment = assignments[index];
2279 char szHostPCIAddress[32], szGuestPCIAddress[32];
2280 LONG iHostPCIAddress = -1, iGuestPCIAddress = -1;
2281 Bstr DevName;
2282
2283 Assignment->COMGETTER(Name)(DevName.asOutParam());
2284 Assignment->COMGETTER(HostAddress)(&iHostPCIAddress);
2285 Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress);
2286 PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress));
2287 PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress));
2288
2289 if (details == VMINFO_MACHINEREADABLE)
2290 RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress);
2291 else
2292 RTPrintf(" Host device %ls at %s attached as %s\n", DevName.raw(), szHostPCIAddress, szGuestPCIAddress);
2293 }
2294
2295 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2296 {
2297 RTPrintf("\n");
2298 }
2299 }
2300 }
2301 /* Host PCI passthrough devices */
2302#endif
2303
2304 /*
2305 * Bandwidth groups
2306 */
2307 if (details != VMINFO_MACHINEREADABLE)
2308 RTPrintf("Bandwidth groups: ");
2309 {
2310 ComPtr<IBandwidthControl> bwCtrl;
2311 CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), rc);
2312
2313 rc = showBandwidthGroups(bwCtrl, details);
2314 }
2315
2316
2317 /*
2318 * Shared folders
2319 */
2320 if (details != VMINFO_MACHINEREADABLE)
2321 RTPrintf("Shared folders:");
2322 uint32_t numSharedFolders = 0;
2323#if 0 // not yet implemented
2324 /* globally shared folders first */
2325 {
2326 SafeIfaceArray <ISharedFolder> sfColl;
2327 CHECK_ERROR_RET(pVirtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(sfColl)), rc);
2328 for (size_t i = 0; i < sfColl.size(); ++i)
2329 {
2330 ComPtr<ISharedFolder> sf = sfColl[i];
2331 showSharedFolder(sf, details, "global mapping", "GlobalMapping", i + 1, numSharedFolders == 0);
2332 ++numSharedFolders;
2333 }
2334 }
2335#endif
2336 /* now VM mappings */
2337 {
2338 com::SafeIfaceArray <ISharedFolder> folders;
2339 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2340 for (size_t i = 0; i < folders.size(); ++i)
2341 {
2342 ComPtr<ISharedFolder> sf = folders[i];
2343 showSharedFolder(sf, details, "machine mapping", "MachineMapping", i + 1, numSharedFolders == 0);
2344 ++numSharedFolders;
2345 }
2346 }
2347 /* transient mappings */
2348 if (pConsole)
2349 {
2350 com::SafeIfaceArray <ISharedFolder> folders;
2351 CHECK_ERROR_RET(pConsole, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2352 for (size_t i = 0; i < folders.size(); ++i)
2353 {
2354 ComPtr<ISharedFolder> sf = folders[i];
2355 showSharedFolder(sf, details, "transient mapping", "TransientMapping", i + 1, numSharedFolders == 0);
2356 ++numSharedFolders;
2357 }
2358 }
2359 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
2360 RTPrintf("<none>\n");
2361 if (details != VMINFO_MACHINEREADABLE)
2362 RTPrintf("\n");
2363
2364 if (pConsole)
2365 {
2366 /*
2367 * Live VRDE info.
2368 */
2369 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2370 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2371 BOOL fActive = FALSE;
2372 ULONG cNumberOfClients = 0;
2373 LONG64 BeginTime = 0;
2374 LONG64 EndTime = 0;
2375 LONG64 BytesSent = 0;
2376 LONG64 BytesSentTotal = 0;
2377 LONG64 BytesReceived = 0;
2378 LONG64 BytesReceivedTotal = 0;
2379 Bstr User;
2380 Bstr Domain;
2381 Bstr ClientName;
2382 Bstr ClientIP;
2383 ULONG ClientVersion = 0;
2384 ULONG EncryptionStyle = 0;
2385
2386 if (!vrdeServerInfo.isNull())
2387 {
2388 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&fActive), rc);
2389 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&cNumberOfClients), rc);
2390 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), rc);
2391 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), rc);
2392 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), rc);
2393 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), rc);
2394 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), rc);
2395 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), rc);
2396 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), rc);
2397 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), rc);
2398 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), rc);
2399 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), rc);
2400 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), rc);
2401 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), rc);
2402 }
2403
2404 SHOW_BOOL_VALUE_EX("VRDEActiveConnection", "VRDE Connection:", fActive, "active", "not active");
2405 SHOW_ULONG_VALUE("VRDEClients=", "Clients so far:", cNumberOfClients, "");
2406
2407 if (cNumberOfClients > 0)
2408 {
2409 char szTimeValue[128];
2410 makeTimeStr(szTimeValue, sizeof(szTimeValue), BeginTime);
2411 if (fActive)
2412 SHOW_UTF8_STRING("VRDEStartTime", "Start time:", szTimeValue);
2413 else
2414 {
2415 SHOW_UTF8_STRING("VRDELastStartTime", "Last started:", szTimeValue);
2416 makeTimeStr(szTimeValue, sizeof(szTimeValue), EndTime);
2417 SHOW_UTF8_STRING("VRDELastEndTime", "Last ended:", szTimeValue);
2418 }
2419
2420 int64_t ThroughputSend = 0;
2421 int64_t ThroughputReceive = 0;
2422 if (EndTime != BeginTime)
2423 {
2424 ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime);
2425 ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime);
2426 }
2427 SHOW_LONG64_VALUE("VRDEBytesSent", "Sent:", BytesSent, "Bytes");
2428 SHOW_LONG64_VALUE("VRDEThroughputSend", "Average speed:", ThroughputSend, "B/s");
2429 SHOW_LONG64_VALUE("VRDEBytesSentTotal", "Sent total:", BytesSentTotal, "Bytes");
2430
2431 SHOW_LONG64_VALUE("VRDEBytesReceived", "Received:", BytesReceived, "Bytes");
2432 SHOW_LONG64_VALUE("VRDEThroughputReceive", "Speed:", ThroughputReceive, "B/s");
2433 SHOW_LONG64_VALUE("VRDEBytesReceivedTotal", "Received total:", BytesReceivedTotal, "Bytes");
2434
2435 if (fActive)
2436 {
2437 SHOW_BSTR_STRING("VRDEUserName", "User name:", User);
2438 SHOW_BSTR_STRING("VRDEDomain", "Domain:", Domain);
2439 SHOW_BSTR_STRING("VRDEClientName", "Client name:", ClientName);
2440 SHOW_BSTR_STRING("VRDEClientIP", "Client IP:", ClientIP);
2441 SHOW_ULONG_VALUE("VRDEClientVersion", "Client version:", ClientVersion, "");
2442 SHOW_UTF8_STRING("VRDEEncryption", "Encryption:", EncryptionStyle == 0 ? "RDP4" : "RDP5 (X.509)");
2443 }
2444 }
2445
2446 if (details != VMINFO_MACHINEREADABLE)
2447 RTPrintf("\n");
2448 }
2449
2450#ifdef VBOX_WITH_RECORDING
2451 {
2452 /* Video capture */
2453 BOOL fCaptureVideo = FALSE;
2454# ifdef VBOX_WITH_AUDIO_RECORDING
2455 BOOL fCaptureAudio = FALSE;
2456# endif
2457
2458 ComPtr<IRecordingSettings> recordingSettings;
2459 CHECK_ERROR_RET(machine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam()), rc);
2460
2461 SafeIfaceArray <IRecordingScreenSettings> saRecordingScreenScreens;
2462 CHECK_ERROR_RET(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saRecordingScreenScreens)), rc);
2463
2464 /* For now all screens have the same configuration; so take screen 0 and work with that. */
2465 ULONG fFeatures;
2466 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Features)(&fFeatures), rc);
2467 ULONG Width;
2468 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoWidth)(&Width), rc);
2469 ULONG Height;
2470 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoHeight)(&Height), rc);
2471 ULONG Rate;
2472 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoRate)(&Rate), rc);
2473 ULONG Fps;
2474 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoFPS)(&Fps), rc);
2475 Bstr bstrFile;
2476 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Filename)(bstrFile.asOutParam()), rc);
2477 Bstr bstrOptions;
2478 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Options)(bstrOptions.asOutParam()), rc);
2479
2480 Utf8Str strOptions(bstrOptions);
2481 size_t pos = 0;
2482 com::Utf8Str key, value;
2483 while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos)
2484 {
2485 if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0)
2486 {
2487 fCaptureVideo = value.compare("true", Utf8Str::CaseInsensitive) == 0;
2488 }
2489 else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0)
2490 {
2491# ifdef VBOX_WITH_AUDIO_RECORDING
2492 fCaptureAudio = value.compare("true", Utf8Str::CaseInsensitive) == 0;
2493# endif
2494 }
2495 }
2496
2497 SHOW_BOOL_VALUE_EX("videocap", "Capturing:", fCaptureVideo, "active", "not active");
2498# ifdef VBOX_WITH_AUDIO_RECORDING
2499 SHOW_BOOL_VALUE_EX("videocapaudio", "Capture audio:", fCaptureAudio, "active", "not active");
2500# endif
2501 szValue[0] = '\0';
2502 for (size_t i = 0, off = 0; i < saRecordingScreenScreens.size(); i++)
2503 {
2504 BOOL fEnabled;
2505 CHECK_ERROR_RET(saRecordingScreenScreens[i], COMGETTER(Enabled)(&fEnabled), rc);
2506 if (fEnabled && off < sizeof(szValue) - 3)
2507 off += RTStrPrintf(&szValue[off], sizeof(szValue) - off, off ? ",%zu" : "%zu", i);
2508 }
2509 SHOW_UTF8_STRING("capturescreens", "Capture screens:", szValue);
2510 SHOW_BSTR_STRING("capturefilename", "Capture file:", bstrFile);
2511 RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height);
2512 SHOW_UTF8_STRING("captureres", "Capture dimensions:", szValue);
2513 SHOW_ULONG_VALUE("capturevideorate", "Capture rate:", Rate, "kbps");
2514 SHOW_ULONG_VALUE("capturevideofps", "Capture FPS:", Fps, "kbps");
2515 SHOW_BSTR_STRING("captureopts", "Capture options:", bstrOptions);
2516
2517 if (details != VMINFO_MACHINEREADABLE)
2518 RTPrintf("\n");
2519 /** @todo Add more audio capturing profile / information here. */
2520 }
2521#endif /* VBOX_WITH_RECORDING */
2522
2523 if ( details == VMINFO_STANDARD
2524 || details == VMINFO_FULL
2525 || details == VMINFO_MACHINEREADABLE)
2526 {
2527 Bstr description;
2528 machine->COMGETTER(Description)(description.asOutParam());
2529 if (!description.isEmpty())
2530 {
2531 if (details == VMINFO_MACHINEREADABLE)
2532 outputMachineReadableString("description", &description);
2533 else
2534 RTPrintf("Description:\n%ls\n", description.raw());
2535 }
2536 }
2537
2538 if (details != VMINFO_MACHINEREADABLE)
2539 RTPrintf("Guest:\n\n");
2540
2541 SHOW_ULONG_PROP(machine, MemoryBalloonSize, "GuestMemoryBalloon", "Configured memory balloon size:", "MB");
2542
2543 if (pConsole)
2544 {
2545 ComPtr<IGuest> guest;
2546 rc = pConsole->COMGETTER(Guest)(guest.asOutParam());
2547 if (SUCCEEDED(rc) && !guest.isNull())
2548 {
2549 SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", "OS type:");
2550
2551 AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */
2552 rc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel);
2553 if (SUCCEEDED(rc))
2554 SHOW_ULONG_VALUE("GuestAdditionsRunLevel", "Additions run level:", (ULONG)guestRunLevel, "");
2555
2556 Bstr guestString;
2557 rc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam());
2558 if ( SUCCEEDED(rc)
2559 && !guestString.isEmpty())
2560 {
2561 ULONG uRevision;
2562 rc = guest->COMGETTER(AdditionsRevision)(&uRevision);
2563 if (FAILED(rc))
2564 uRevision = 0;
2565 RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision);
2566 SHOW_UTF8_STRING("GuestAdditionsVersion", "Additions version:", szValue);
2567 }
2568
2569 if (details != VMINFO_MACHINEREADABLE)
2570 RTPrintf("\nGuest Facilities:\n\n");
2571
2572 /* Print information about known Guest Additions facilities: */
2573 SafeIfaceArray <IAdditionsFacility> collFac;
2574 CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), rc);
2575 LONG64 lLastUpdatedMS;
2576 char szLastUpdated[32];
2577 AdditionsFacilityStatus_T curStatus;
2578 for (size_t index = 0; index < collFac.size(); ++index)
2579 {
2580 ComPtr<IAdditionsFacility> fac = collFac[index];
2581 if (fac)
2582 {
2583 CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), rc);
2584 if (!guestString.isEmpty())
2585 {
2586 CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), rc);
2587 CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), rc);
2588 if (details == VMINFO_MACHINEREADABLE)
2589 RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n",
2590 guestString.raw(), curStatus, lLastUpdatedMS);
2591 else
2592 {
2593 makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
2594 RTPrintf("Facility \"%ls\": %s (last update: %s)\n",
2595 guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated);
2596 }
2597 }
2598 else
2599 AssertMsgFailed(("Facility with undefined name retrieved!\n"));
2600 }
2601 else
2602 AssertMsgFailed(("Invalid facility returned!\n"));
2603 }
2604 if (!collFac.size() && details != VMINFO_MACHINEREADABLE)
2605 RTPrintf("No active facilities.\n");
2606 }
2607 }
2608
2609 if (details != VMINFO_MACHINEREADABLE)
2610 RTPrintf("\n");
2611
2612 /*
2613 * snapshots
2614 */
2615 ComPtr<ISnapshot> snapshot;
2616 rc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam());
2617 if (SUCCEEDED(rc) && snapshot)
2618 {
2619 ComPtr<ISnapshot> currentSnapshot;
2620 rc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam());
2621 if (SUCCEEDED(rc))
2622 {
2623 if (details != VMINFO_MACHINEREADABLE)
2624 RTPrintf("Snapshots:\n\n");
2625 showSnapshots(snapshot, currentSnapshot, details);
2626 }
2627 }
2628
2629 if (details != VMINFO_MACHINEREADABLE)
2630 RTPrintf("\n");
2631 return S_OK;
2632}
2633
2634#if defined(_MSC_VER)
2635# pragma optimize("", on)
2636# pragma warning(pop)
2637#endif
2638
2639static const RTGETOPTDEF g_aShowVMInfoOptions[] =
2640{
2641 { "--details", 'D', RTGETOPT_REQ_NOTHING },
2642 { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated
2643 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
2644 { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated
2645 { "--log", 'l', RTGETOPT_REQ_UINT32 },
2646};
2647
2648RTEXITCODE handleShowVMInfo(HandlerArg *a)
2649{
2650 HRESULT rc;
2651 const char *VMNameOrUuid = NULL;
2652 bool fLog = false;
2653 uint32_t uLogIdx = 0;
2654 bool fDetails = false;
2655 bool fMachinereadable = false;
2656
2657 int c;
2658 RTGETOPTUNION ValueUnion;
2659 RTGETOPTSTATE GetState;
2660 // start at 0 because main() has hacked both the argc and argv given to us
2661 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions),
2662 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2663 while ((c = RTGetOpt(&GetState, &ValueUnion)))
2664 {
2665 switch (c)
2666 {
2667 case 'D': // --details
2668 fDetails = true;
2669 break;
2670
2671 case 'M': // --machinereadable
2672 fMachinereadable = true;
2673 break;
2674
2675 case 'l': // --log
2676 fLog = true;
2677 uLogIdx = ValueUnion.u32;
2678 break;
2679
2680 case VINF_GETOPT_NOT_OPTION:
2681 if (!VMNameOrUuid)
2682 VMNameOrUuid = ValueUnion.psz;
2683 else
2684 return errorSyntax(USAGE_SHOWVMINFO, "Invalid parameter '%s'", ValueUnion.psz);
2685 break;
2686
2687 default:
2688 return errorGetOpt(USAGE_SHOWVMINFO, c, &ValueUnion);
2689 }
2690 }
2691
2692 /* check for required options */
2693 if (!VMNameOrUuid)
2694 return errorSyntax(USAGE_SHOWVMINFO, "VM name or UUID required");
2695
2696 /* try to find the given machine */
2697 ComPtr<IMachine> machine;
2698 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(),
2699 machine.asOutParam()));
2700 if (FAILED(rc))
2701 return RTEXITCODE_FAILURE;
2702
2703 /* Printing the log is exclusive. */
2704 if (fLog && (fMachinereadable || fDetails))
2705 return errorSyntax(USAGE_SHOWVMINFO, "Option --log is exclusive");
2706
2707 if (fLog)
2708 {
2709 ULONG64 uOffset = 0;
2710 SafeArray<BYTE> aLogData;
2711 size_t cbLogData;
2712 while (true)
2713 {
2714 /* Reset the array */
2715 aLogData.setNull();
2716 /* Fetch a chunk of the log file */
2717 CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, uOffset, _1M,
2718 ComSafeArrayAsOutParam(aLogData)));
2719 cbLogData = aLogData.size();
2720 if (cbLogData == 0)
2721 break;
2722 /* aLogData has a platform dependent line ending, standardize on
2723 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
2724 * Windows. Otherwise we end up with CR/CR/LF on Windows. */
2725 size_t cbLogDataPrint = cbLogData;
2726 for (BYTE *s = aLogData.raw(), *d = s;
2727 s - aLogData.raw() < (ssize_t)cbLogData;
2728 s++, d++)
2729 {
2730 if (*s == '\r')
2731 {
2732 /* skip over CR, adjust destination */
2733 d--;
2734 cbLogDataPrint--;
2735 }
2736 else if (s != d)
2737 *d = *s;
2738 }
2739 RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint);
2740 uOffset += cbLogData;
2741 }
2742 }
2743 else
2744 {
2745 /* 2nd option can be -details or -argdump */
2746 VMINFO_DETAILS details = VMINFO_NONE;
2747 if (fMachinereadable)
2748 details = VMINFO_MACHINEREADABLE;
2749 else if (fDetails)
2750 details = VMINFO_FULL;
2751 else
2752 details = VMINFO_STANDARD;
2753
2754 /* open an existing session for the VM */
2755 rc = machine->LockMachine(a->session, LockType_Shared);
2756 if (SUCCEEDED(rc))
2757 /* get the session machine */
2758 rc = a->session->COMGETTER(Machine)(machine.asOutParam());
2759
2760 rc = showVMInfo(a->virtualBox, machine, a->session, details);
2761
2762 a->session->UnlockMachine();
2763 }
2764
2765 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
2766}
2767
2768#endif /* !VBOX_ONLY_DOCS */
2769/* 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