VirtualBox

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

Last change on this file since 75341 was 75341, checked in by vboxsync, 6 years ago

Recording: Renaming APIs ICapture* -> IRecord* and other terminology to better distinguish from features like mouse capturing and stuff.

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