VirtualBox

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

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

Main/Machine+BIOSSettings: bare bones NVRAM logic, many parts missing (no snapshot handling, no move VM handling, no remove VM handling).
Main/Settings: adaptions to store NVRAM config in the settings file
Frontends/VBoxManage: support enabling and showing state

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