VirtualBox

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

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

bugref:9381. Fixed a regression bug after 120461.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use