VirtualBox

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

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

VMM,Main,++: Retired the unfinished FTM component.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use