VirtualBox

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

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

Main: bugref:9618 Added Main/API support for AMD-V Virtualized VMSAVE/VMLOAD hardware virtualization feature.

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