VirtualBox

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

Last change on this file was 103594, checked in by vboxsync, 2 months ago

VBoxManage: For showvminfo --machinereadable show the NVRAM file following the naming rules (which don't allow spaces).

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

© 2023 Oracle
ContactPrivacy policyTerms of Use