VirtualBox

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

Last change on this file since 108699 was 108641, checked in by vboxsync, 8 weeks ago

Removed 2D video acceleration (aka VHWA / VBOX_WITH_VIDEOHWACCEL). bugref:10756

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 140.9 KB
Line 
1/* $Id: VBoxManageInfo.cpp 108641 2025-03-20 12:48:42Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'showvminfo' command and helper routines.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.215389.xyz.
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, (size_t)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, (size_t)(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
801static const char *symlinkPolicyToName(SymlinkPolicy_T enmSymlinkPolicy)
802{
803 switch (enmSymlinkPolicy)
804 {
805 case SymlinkPolicy_AllowedToAnyTarget:
806 return ("any");
807 case SymlinkPolicy_AllowedInShareSubtree:
808 return ("subtree");
809 case SymlinkPolicy_AllowedToRelativeTargets:
810 return ("relative");
811 case SymlinkPolicy_Forbidden:
812 return("forbidden");
813 default:
814 return("none");
815 }
816}
817
818/** Shows a shared folder. */
819static HRESULT showSharedFolder(ComPtr<ISharedFolder> &sf, VMINFO_DETAILS details, const char *pszDesc,
820 const char *pszMrInfix, size_t idxMr, bool fFirst)
821{
822 Bstr name, hostPath, bstrAutoMountPoint;
823 BOOL writable = FALSE, fAutoMount = FALSE;
824 SymlinkPolicy_T enmSymlinkPolicy = SymlinkPolicy_None;
825 CHECK_ERROR2I_RET(sf, COMGETTER(Name)(name.asOutParam()), hrcCheck);
826 CHECK_ERROR2I_RET(sf, COMGETTER(HostPath)(hostPath.asOutParam()), hrcCheck);
827 CHECK_ERROR2I_RET(sf, COMGETTER(Writable)(&writable), hrcCheck);
828 CHECK_ERROR2I_RET(sf, COMGETTER(AutoMount)(&fAutoMount), hrcCheck);
829 CHECK_ERROR2I_RET(sf, COMGETTER(AutoMountPoint)(bstrAutoMountPoint.asOutParam()), hrcCheck);
830 CHECK_ERROR2I_RET(sf, COMGETTER(SymlinkPolicy)(&enmSymlinkPolicy), hrcCheck);
831
832 if (fFirst && details != VMINFO_MACHINEREADABLE)
833 RTPrintf("\n\n");
834 if (details == VMINFO_MACHINEREADABLE)
835 {
836 char szNm[80];
837 outputMachineReadableString(FmtNm(szNm, "SharedFolderName%s%zu", pszMrInfix, idxMr), &name);
838 outputMachineReadableString(FmtNm(szNm, "SharedFolderPath%s%zu", pszMrInfix, idxMr), &hostPath);
839 }
840 else
841 {
842 RTPrintf(Info::tr("Name: '%ls', Host path: '%ls' (%s), %s%s"),
843 name.raw(), hostPath.raw(), pszDesc, writable ? Info::tr("writable") : Info::tr("readonly"),
844 fAutoMount ? Info::tr(", auto-mount") : "");
845 if (enmSymlinkPolicy != SymlinkPolicy_None)
846 RTPrintf(Info::tr(", symlink-policy: %s"), symlinkPolicyToName(enmSymlinkPolicy));
847 if (bstrAutoMountPoint.isNotEmpty())
848 RTPrintf(Info::tr(", mount-point: '%ls'\n"), bstrAutoMountPoint.raw());
849 else
850 RTPrintf("\n");
851 }
852 return S_OK;
853}
854
855/** Displays a list of IUSBDevices or IHostUSBDevices. */
856template <class IUSBDeviceType>
857static HRESULT showUsbDevices(SafeIfaceArray<IUSBDeviceType> &coll, const char *pszPfx,
858 const char *pszName, VMINFO_DETAILS details)
859{
860 if (coll.size() > 0)
861 {
862 if (details != VMINFO_MACHINEREADABLE)
863 RTPrintf("%-28s\n\n", pszName);
864 for (size_t i = 0; i < coll.size(); ++i)
865 {
866 ComPtr<IUSBDeviceType> dev = coll[i];
867 char szValue[128];
868 char szNm[80];
869
870 SHOW_STRING_PROP(dev, Id, FmtNm(szNm, "%sActive%zu", pszPfx, i + 1), "UUID:");
871 SHOW_USHORT_PROP_EX2(dev, VendorId, FmtNm(szNm, "%sVendorId%zu", pszPfx, i + 1), Info::tr("VendorId:"), "", "%#06x", "%#06x (%04X)");
872 SHOW_USHORT_PROP_EX2(dev, ProductId, FmtNm(szNm, "%sProductId%zu", pszPfx, i + 1), Info::tr("ProductId:"), "", "%#06x", "%#06x (%04X)");
873
874 USHORT bcdRevision;
875 CHECK_ERROR2I_RET(dev, COMGETTER(Revision)(&bcdRevision), hrcCheck);
876 if (details == VMINFO_MACHINEREADABLE)
877 RTStrPrintf(szValue, sizeof(szValue), "%#04x%02x", bcdRevision >> 8, bcdRevision & 0xff);
878 else
879 RTStrPrintf(szValue, sizeof(szValue), "%u.%u (%02u%02u)\n",
880 bcdRevision >> 8, bcdRevision & 0xff, bcdRevision >> 8, bcdRevision & 0xff);
881 SHOW_UTF8_STRING(FmtNm(szNm, "%sRevision%zu", pszPfx, i + 1), Info::tr("Revision:"), szValue);
882
883 SHOW_STRING_PROP_NOT_EMPTY(dev, Manufacturer, FmtNm(szNm, "%sManufacturer%zu", pszPfx, i + 1), Info::tr("Manufacturer:"));
884 SHOW_STRING_PROP_NOT_EMPTY(dev, Product, FmtNm(szNm, "%sProduct%zu", pszPfx, i + 1), Info::tr("Product:"));
885 SHOW_STRING_PROP_NOT_EMPTY(dev, SerialNumber, FmtNm(szNm, "%sSerialNumber%zu", pszPfx, i + 1), Info::tr("SerialNumber:"));
886 SHOW_STRING_PROP_NOT_EMPTY(dev, Address, FmtNm(szNm, "%sAddress%zu", pszPfx, i + 1), Info::tr("Address:"));
887
888 if (details != VMINFO_MACHINEREADABLE)
889 RTPrintf("\n");
890 }
891 }
892 else if (details != VMINFO_MACHINEREADABLE)
893 RTPrintf("%-28s %s\n", pszName, Info::tr("<none>"));
894 return S_OK;
895}
896
897/** Displays the medium attachments of the given controller. */
898static HRESULT showMediumAttachments(ComPtr<IMachine> &machine, ComPtr<IStorageController> ptrStorageCtl, VMINFO_DETAILS details)
899{
900 Bstr bstrStorageCtlName;
901 CHECK_ERROR2I_RET(ptrStorageCtl, COMGETTER(Name)(bstrStorageCtlName.asOutParam()), hrcCheck);
902 ULONG cDevices;
903 CHECK_ERROR2I_RET(ptrStorageCtl, COMGETTER(MaxDevicesPerPortCount)(&cDevices), hrcCheck);
904 ULONG cPorts;
905 CHECK_ERROR2I_RET(ptrStorageCtl, COMGETTER(PortCount)(&cPorts), hrcCheck);
906
907 for (ULONG i = 0; i < cPorts; ++ i)
908 {
909 for (ULONG k = 0; k < cDevices; ++ k)
910 {
911 ComPtr<IMediumAttachment> mediumAttach;
912 HRESULT hrc = machine->GetMediumAttachment(bstrStorageCtlName.raw(), (LONG)i, (LONG)k, mediumAttach.asOutParam());
913 if (!SUCCEEDED(hrc) && hrc != VBOX_E_OBJECT_NOT_FOUND)
914 {
915 com::GlueHandleComError(machine, "GetMediumAttachment", hrc, __FILE__, __LINE__);
916 return hrc;
917 }
918
919 BOOL fIsEjected = FALSE;
920 BOOL fTempEject = FALSE;
921 BOOL fHotPlug = FALSE;
922 BOOL fNonRotational = FALSE;
923 BOOL fDiscard = FALSE;
924 DeviceType_T devType = DeviceType_Null;
925 if (mediumAttach)
926 {
927 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(TemporaryEject)(&fTempEject), hrcCheck);
928 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(IsEjected)(&fIsEjected), hrcCheck);
929 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(Type)(&devType), hrcCheck);
930 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(HotPluggable)(&fHotPlug), hrcCheck);
931 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(NonRotational)(&fNonRotational), hrcCheck);
932 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(Discard)(&fDiscard), hrcCheck);
933 }
934
935 ComPtr<IMedium> medium;
936 hrc = machine->GetMedium(bstrStorageCtlName.raw(), (LONG)i, (LONG)k, medium.asOutParam());
937 if (SUCCEEDED(hrc) && medium)
938 {
939 BOOL fPassthrough = FALSE;
940 if (mediumAttach)
941 {
942 CHECK_ERROR2I_RET(mediumAttach, COMGETTER(Passthrough)(&fPassthrough), hrcCheck);
943 }
944
945 Bstr bstrFilePath;
946 CHECK_ERROR2I_RET(medium, COMGETTER(Location)(bstrFilePath.asOutParam()), hrcCheck);
947 Bstr bstrUuid;
948 CHECK_ERROR2I_RET(medium, COMGETTER(Id)(bstrUuid.asOutParam()), hrcCheck);
949
950 if (details != VMINFO_MACHINEREADABLE)
951 RTPrintf(Info::tr(" Port %u, Unit %u: UUID: %ls%s%s%s%s%s%s\n Location: \"%ls\"\n"),
952 i, k, bstrUuid.raw(),
953 fPassthrough ? Info::tr(", passthrough enabled") : "",
954 fTempEject ? Info::tr(", temp eject") : "",
955 fIsEjected ? Info::tr(", ejected") : "",
956 fHotPlug ? Info::tr(", hot-pluggable") : "",
957 fNonRotational ? Info::tr(", non-rotational (SSD)") : "",
958 fDiscard ? Info::tr(", discards unused blocks") : "",
959 bstrFilePath.raw());
960 else
961 {
962 /* Note! dvdpassthough, tempeject and IsEjected was all missed the port
963 and unit bits prior to VBox 7.0. */
964 /** @todo This would look better on the "%ls-%d-%d-{tag}" form! */
965 outputMachineReadableStringWithFmtName(&bstrFilePath,
966 true, "%ls-%d-%d", bstrStorageCtlName.raw(), i, k);
967 outputMachineReadableStringWithFmtName(&bstrUuid,
968 true, "%ls-ImageUUID-%d-%d", bstrStorageCtlName.raw(), i, k);
969
970 if (fPassthrough)
971 outputMachineReadableStringWithFmtName("on",
972 true, "%ls-dvdpassthrough-%d-%d", bstrStorageCtlName.raw(), i, k);
973 if (devType == DeviceType_DVD)
974 {
975 outputMachineReadableStringWithFmtName(fTempEject ? "on" : "off",
976 true, "%ls-tempeject-%d-%d", bstrStorageCtlName.raw(), i, k);
977 outputMachineReadableStringWithFmtName(fIsEjected ? "on" : "off",
978 true, "%ls-IsEjected-%d-%d", bstrStorageCtlName.raw(), i, k);
979 }
980
981 if ( bstrStorageCtlName.compare(Bstr("SATA"), Bstr::CaseInsensitive)== 0
982 || bstrStorageCtlName.compare(Bstr("USB"), Bstr::CaseInsensitive)== 0)
983 outputMachineReadableStringWithFmtName(fHotPlug ? "on" : "off",
984 true, "%ls-hot-pluggable-%d-%d", bstrStorageCtlName.raw(),
985 i, k);
986
987 outputMachineReadableStringWithFmtName(fNonRotational ? "on" : "off",
988 true, "%ls-nonrotational-%d-%d", bstrStorageCtlName.raw(), i, k);
989 outputMachineReadableStringWithFmtName(fDiscard ? "on" : "off",
990 true, "%ls-discard-%d-%d", bstrStorageCtlName.raw(), i, k);
991 }
992 }
993 else if (SUCCEEDED(hrc))
994 {
995 if (details != VMINFO_MACHINEREADABLE)
996 RTPrintf(Info::tr(" Port %u, Unit %u: Empty%s%s\n"), i, k,
997 fTempEject ? Info::tr(", temp eject") : "",
998 fIsEjected ? Info::tr(", ejected") : "");
999 else
1000 {
1001 outputMachineReadableStringWithFmtName("emptydrive", true, "%ls-%d-%d", bstrStorageCtlName.raw(), i, k);
1002 if (devType == DeviceType_DVD)
1003 outputMachineReadableStringWithFmtName(fIsEjected ? "on" : "off",
1004 true, "%ls-IsEjected-%d-%d", bstrStorageCtlName.raw(), i, k);
1005 }
1006 }
1007 else if (details == VMINFO_MACHINEREADABLE)
1008 outputMachineReadableStringWithFmtName("none", true, "%ls-%d-%d", bstrStorageCtlName.raw(), i, k);
1009 else if (hrc != VBOX_E_OBJECT_NOT_FOUND)
1010 RTPrintf(Info::tr(" Port %u, Unit %u: GetMedium failed: %Rhrc\n"), i, k, hrc);
1011
1012 }
1013 }
1014 return S_OK;
1015}
1016
1017
1018#ifdef VBOX_WITH_IOMMU_AMD
1019static const char *iommuTypeToString(IommuType_T iommuType, VMINFO_DETAILS details)
1020{
1021 switch (iommuType)
1022 {
1023 case IommuType_None:
1024 if (details == VMINFO_MACHINEREADABLE)
1025 return "none";
1026 return Info::tr("None");
1027
1028 case IommuType_Automatic:
1029 if (details == VMINFO_MACHINEREADABLE)
1030 return "automatic";
1031 return Info::tr("Automatic");
1032
1033 case IommuType_AMD:
1034 if (details == VMINFO_MACHINEREADABLE)
1035 return "amd";
1036 return "AMD";
1037
1038 case IommuType_Intel:
1039 if (details == VMINFO_MACHINEREADABLE)
1040 return "intel";
1041 return "Intel";
1042
1043 default:
1044 if (details == VMINFO_MACHINEREADABLE)
1045 return "unknown";
1046 return Info::tr("Unknown");
1047 }
1048}
1049#endif
1050
1051static const char *paravirtProviderToString(ParavirtProvider_T provider, VMINFO_DETAILS details)
1052{
1053 switch (provider)
1054 {
1055 case ParavirtProvider_None:
1056 if (details == VMINFO_MACHINEREADABLE)
1057 return "none";
1058 return Info::tr("None");
1059
1060 case ParavirtProvider_Default:
1061 if (details == VMINFO_MACHINEREADABLE)
1062 return "default";
1063 return Info::tr("Default");
1064
1065 case ParavirtProvider_Legacy:
1066 if (details == VMINFO_MACHINEREADABLE)
1067 return "legacy";
1068 return Info::tr("Legacy");
1069
1070 case ParavirtProvider_Minimal:
1071 if (details == VMINFO_MACHINEREADABLE)
1072 return "minimal";
1073 return Info::tr("Minimal");
1074
1075 case ParavirtProvider_HyperV:
1076 if (details == VMINFO_MACHINEREADABLE)
1077 return "hyperv";
1078 return "HyperV";
1079
1080 case ParavirtProvider_KVM:
1081 if (details == VMINFO_MACHINEREADABLE)
1082 return "kvm";
1083 return "KVM";
1084
1085 default:
1086 if (details == VMINFO_MACHINEREADABLE)
1087 return "unknown";
1088 return Info::tr("Unknown");
1089 }
1090}
1091
1092
1093/* Disable global optimizations for MSC 8.0/64 to make it compile in reasonable
1094 time. MSC 7.1/32 doesn't have quite as much trouble with it, but still
1095 sufficient to qualify for this hack as well since this code isn't performance
1096 critical and probably won't gain much from the extra optimizing in real life. */
1097#if defined(_MSC_VER)
1098# pragma optimize("g", off)
1099# pragma warning(push)
1100# if _MSC_VER < RT_MSC_VER_VC120
1101# pragma warning(disable: 4748)
1102# endif
1103#endif
1104
1105HRESULT showVMInfo(ComPtr<IVirtualBox> pVirtualBox,
1106 ComPtr<IMachine> machine,
1107 ComPtr<ISession> pSession,
1108 VMINFO_DETAILS details /*= VMINFO_NONE*/)
1109{
1110 HRESULT hrc;
1111 ComPtr<IConsole> pConsole;
1112 if (pSession)
1113 pSession->COMGETTER(Console)(pConsole.asOutParam());
1114
1115 char szNm[80];
1116 char szValue[256];
1117
1118 /*
1119 * The rules for output in -argdump format:
1120 * 1) the key part (the [0-9a-zA-Z_\-]+ string before the '=' delimiter)
1121 * is all lowercase for "VBoxManage modifyvm" parameters. Any
1122 * other values printed are in CamelCase.
1123 * 2) strings (anything non-decimal) are printed surrounded by
1124 * double quotes '"'. If the strings themselves contain double
1125 * quotes, these characters are escaped by '\'. Any '\' character
1126 * in the original string is also escaped by '\'.
1127 * 3) numbers (containing just [0-9\-]) are written out unchanged.
1128 */
1129
1130 BOOL fAccessible;
1131 CHECK_ERROR2I_RET(machine, COMGETTER(Accessible)(&fAccessible), hrcCheck);
1132 if (!fAccessible)
1133 {
1134 Bstr uuid;
1135 machine->COMGETTER(Id)(uuid.asOutParam());
1136 if (details == VMINFO_COMPACT)
1137 RTPrintf(Info::tr("\"<inaccessible>\" {%s}\n"), Utf8Str(uuid).c_str());
1138 else
1139 {
1140 if (details == VMINFO_MACHINEREADABLE)
1141 RTPrintf("name=\"<inaccessible>\"\n");
1142 else
1143 RTPrintf(Info::tr("Name: <inaccessible!>\n"));
1144 if (details == VMINFO_MACHINEREADABLE)
1145 RTPrintf("UUID=\"%s\"\n", Utf8Str(uuid).c_str());
1146 else
1147 RTPrintf("UUID: %s\n", Utf8Str(uuid).c_str());
1148 if (details != VMINFO_MACHINEREADABLE)
1149 {
1150 Bstr settingsFilePath("<Error>");
1151 CHECK_ERROR(machine, COMGETTER(SettingsFilePath)(settingsFilePath.asOutParam()));
1152 RTPrintf(Info::tr("Config file: %ls\n"), settingsFilePath.raw());
1153
1154 Bstr strCipher;
1155 Bstr strPasswordId;
1156 HRESULT hrc2 = machine->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam());
1157 if (SUCCEEDED(hrc2))
1158 {
1159 RTPrintf("Encryption: enabled\n");
1160 RTPrintf("Cipher: %ls\n", strCipher.raw());
1161 RTPrintf("Password ID: %ls\n", strPasswordId.raw());
1162 }
1163 else
1164 RTPrintf("Encryption: disabled\n");
1165
1166 ComPtr<IVirtualBoxErrorInfo> accessError;
1167 CHECK_ERROR(machine, COMGETTER(AccessError)(accessError.asOutParam()));
1168 if (SUCCEEDED(hrc))
1169 {
1170 RTPrintf(Info::tr("Access error details:\n"));
1171 ErrorInfo ei(accessError);
1172 GluePrintErrorInfo(ei);
1173 RTPrintf("\n");
1174 }
1175 }
1176 }
1177 return S_OK;
1178 }
1179
1180 ComPtr<IPlatform> platform;
1181 CHECK_ERROR_RET(machine, COMGETTER(Platform)(platform.asOutParam()), hrc);
1182 ComPtr<IPlatformProperties> platformProperties;
1183 CHECK_ERROR_RET(platform, COMGETTER(Properties)(platformProperties.asOutParam()), hrc);
1184
1185 PlatformArchitecture_T platformArch;
1186 CHECK_ERROR_RET(platform, COMGETTER(Architecture)(&platformArch), hrc);
1187
1188 ComPtr<IFirmwareSettings> firmwareSettings;
1189 CHECK_ERROR_RET(machine, COMGETTER(FirmwareSettings)(firmwareSettings.asOutParam()), hrc);
1190
1191 if (details == VMINFO_COMPACT)
1192 {
1193 Bstr machineName;
1194 machine->COMGETTER(Name)(machineName.asOutParam());
1195 Bstr uuid;
1196 machine->COMGETTER(Id)(uuid.asOutParam());
1197
1198 RTPrintf("\"%ls\" {%s}\n", machineName.raw(), Utf8Str(uuid).c_str());
1199 return S_OK;
1200 }
1201
1202 SHOW_STRING_PROP( machine, Name, "name", Info::tr("Name:"));
1203 {
1204 Bstr strCipher;
1205 Bstr strPasswordId;
1206 HRESULT hrc2 = machine->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam());
1207
1208 SHOW_UTF8_STRING( "encryption", Info::tr("Encryption:"),
1209 SUCCEEDED(hrc2) ? "enabled" : "disabled");
1210 if (SUCCEEDED(hrc2))
1211 {
1212 SHOW_BSTR_STRING( "enc_cipher", Info::tr("Cipher:"), strCipher);
1213 SHOW_BSTR_STRING( "enc_password_id", Info::tr("Password ID:"), strPasswordId);
1214 }
1215 }
1216 SHOW_STRINGARRAY_PROP( machine, Groups, "groups", Info::tr("Groups:"));
1217 SHOW_UTF8_STRING( "platformArchitecture", Info::tr("Platform Architecture:"),
1218 platformArch == PlatformArchitecture_x86 ? "x86" : "ARM");
1219 Bstr osTypeId;
1220 CHECK_ERROR2I_RET(machine, COMGETTER(OSTypeId)(osTypeId.asOutParam()), hrcCheck);
1221 ComPtr<IGuestOSType> osType;
1222 pVirtualBox->GetGuestOSType(osTypeId.raw(), osType.asOutParam());
1223 if (!osType.isNull())
1224 SHOW_STRING_PROP( osType, Description, "ostype", Info::tr("Guest OS:"));
1225 else
1226 SHOW_STRING_PROP( machine, OSTypeId, "ostype", Info::tr("Guest OS:"));
1227 SHOW_UUID_PROP( machine, Id, "UUID", "UUID:");
1228 SHOW_STRING_PROP( machine, SettingsFilePath, "CfgFile", Info::tr("Config file:"));
1229 SHOW_STRING_PROP( machine, SnapshotFolder, "SnapFldr", Info::tr("Snapshot folder:"));
1230 SHOW_STRING_PROP( machine, LogFolder, "LogFldr", Info::tr("Log folder:"));
1231 SHOW_UUID_PROP( machine, HardwareUUID, "hardwareuuid", Info::tr("Hardware UUID:"));
1232 SHOW_ULONG_PROP( machine, MemorySize, "memory", Info::tr("Memory size:"), "MB");
1233 SHOW_BOOLEAN_PROP( machine, PageFusionEnabled, "pagefusion", Info::tr("Page Fusion:"));
1234 ComPtr<IGraphicsAdapter> pGraphicsAdapter;
1235 machine->COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam());
1236 SHOW_ULONG_PROP(pGraphicsAdapter, VRAMSize, "vram", Info::tr("VRAM size:"), "MB");
1237 SHOW_ULONG_PROP( machine, CPUExecutionCap, "cpuexecutioncap", Info::tr("CPU exec cap:"), "%");
1238 SHOW_STRING_PROP_MAJ( machine, CPUProfile, "cpu-profile", Info::tr("CPUProfile:"), "host", 6);
1239
1240 ChipsetType_T chipsetType;
1241 CHECK_ERROR2I_RET(platform, COMGETTER(ChipsetType)(&chipsetType), hrcCheck);
1242 const char *pszChipsetType;
1243 switch (chipsetType)
1244 {
1245 case ChipsetType_Null:
1246 if (details == VMINFO_MACHINEREADABLE)
1247 pszChipsetType = "invalid";
1248 else
1249 pszChipsetType = Info::tr("invalid");
1250 break;
1251 case ChipsetType_PIIX3: pszChipsetType = "piix3"; break;
1252 case ChipsetType_ICH9: pszChipsetType = "ich9"; break;
1253 case ChipsetType_ARMv8Virtual: pszChipsetType = "armv8virtual"; break;
1254 default:
1255 AssertFailed();
1256 if (details == VMINFO_MACHINEREADABLE)
1257 pszChipsetType = "unknown";
1258 else
1259 pszChipsetType = Info::tr("unknown");
1260 break;
1261 }
1262 SHOW_UTF8_STRING("chipset", Info::tr("Chipset:"), pszChipsetType);
1263
1264 FirmwareType_T firmwareType;
1265 CHECK_ERROR2I_RET(firmwareSettings, COMGETTER(FirmwareType)(&firmwareType), hrcCheck);
1266 const char *pszFirmwareType;
1267 switch (firmwareType)
1268 {
1269 case FirmwareType_BIOS: pszFirmwareType = "BIOS"; break;
1270 case FirmwareType_EFI: pszFirmwareType = "EFI"; break;
1271 case FirmwareType_EFI32: pszFirmwareType = "EFI32"; break;
1272 case FirmwareType_EFI64: pszFirmwareType = "EFI64"; break;
1273 case FirmwareType_EFIDUAL: pszFirmwareType = "EFIDUAL"; break;
1274 default:
1275 AssertFailed();
1276 if (details == VMINFO_MACHINEREADABLE)
1277 pszFirmwareType = "unknown";
1278 else
1279 pszFirmwareType = Info::tr("unknown");
1280 break;
1281 }
1282 SHOW_UTF8_STRING("firmware", Info::tr("Firmware:"), pszFirmwareType);
1283
1284 SHOW_ULONG_PROP( machine, CPUCount, "cpus", Info::tr("Number of CPUs:"), "");
1285
1286 switch (platformArch)
1287 {
1288 case PlatformArchitecture_x86:
1289 {
1290 ComPtr<IPlatformX86> platformX86;
1291 CHECK_ERROR_RET(platform, COMGETTER(X86)(platformX86.asOutParam()), hrc);
1292
1293 SHOW_BOOLEAN_PROP( platformX86, HPETEnabled, "hpet", Info::tr("HPET:"));
1294 SHOW_BOOLEAN_METHOD( platformX86, GetCPUProperty(CPUPropertyTypeX86_PAE, &f), "pae", "PAE:");
1295 SHOW_BOOLEAN_METHOD( platformX86, GetCPUProperty(CPUPropertyTypeX86_LongMode, &f), "longmode", Info::tr("Long Mode:"));
1296 SHOW_BOOLEAN_METHOD( platformX86, GetCPUProperty(CPUPropertyTypeX86_TripleFaultReset, &f), "triplefaultreset", Info::tr("Triple Fault Reset:"));
1297 SHOW_BOOLEAN_METHOD( platformX86, GetCPUProperty(CPUPropertyTypeX86_APIC, &f), "apic", "APIC:");
1298 SHOW_BOOLEAN_METHOD( platformX86, GetCPUProperty(CPUPropertyTypeX86_X2APIC, &f), "x2apic", "X2APIC:");
1299 SHOW_BOOLEAN_METHOD( platformX86, GetCPUProperty(CPUPropertyTypeX86_HWVirt, &f), "nested-hw-virt", Info::tr("Nested VT-x/AMD-V:"));
1300
1301 if (details != VMINFO_MACHINEREADABLE)
1302 RTPrintf("%-28s ", Info::tr("CPUID overrides:"));
1303 ULONG uOrdinal = 0;
1304 for (uOrdinal = 0; uOrdinal < _4K; uOrdinal++)
1305 {
1306 ULONG uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX;
1307 hrc = platformX86->GetCPUIDLeafByOrdinal(uOrdinal, &uLeaf, &uSubLeaf, &uEAX, &uEBX, &uECX, &uEDX);
1308 if (SUCCEEDED(hrc))
1309 {
1310 if (details == VMINFO_MACHINEREADABLE)
1311 RTPrintf("cpuid=%08x,%08x,%08x,%08x,%08x,%08x", uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX);
1312 else
1313 {
1314 if (!uOrdinal)
1315 RTPrintf(Info::tr("Leaf no. EAX EBX ECX EDX\n"));
1316 RTPrintf("%-28s %08x/%03x %08x %08x %08x %08x\n", "", uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX);
1317 }
1318 }
1319 else
1320 {
1321 if (hrc != E_INVALIDARG)
1322 com::GlueHandleComError(machine, "GetCPUIDLeaf", hrc, __FILE__, __LINE__);
1323 break;
1324 }
1325 }
1326 if (!uOrdinal && details != VMINFO_MACHINEREADABLE)
1327 RTPrintf(Info::tr("None\n"));
1328
1329 SHOW_BOOLEAN_METHOD(platformX86, GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &f), "hwvirtex", Info::tr("Hardware Virtualization:"));
1330 SHOW_BOOLEAN_METHOD(platformX86, GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &f),"nestedpaging", Info::tr("Nested Paging:"));
1331 SHOW_BOOLEAN_METHOD(platformX86, GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &f), "largepages", Info::tr("Large Pages:"));
1332 SHOW_BOOLEAN_METHOD(platformX86, GetHWVirtExProperty(HWVirtExPropertyType_VPID, &f), "vtxvpid", "VT-x VPID:");
1333 SHOW_BOOLEAN_METHOD(platformX86, GetHWVirtExProperty(HWVirtExPropertyType_UnrestrictedExecution, &f), "vtxux", Info::tr("VT-x Unrestricted Exec.:"));
1334 SHOW_BOOLEAN_METHOD(platformX86, GetHWVirtExProperty(HWVirtExPropertyType_VirtVmsaveVmload, &f), "virtvmsavevmload", Info::tr("AMD-V Virt. Vmsave/Vmload:"));
1335 break;
1336 }
1337
1338 case PlatformArchitecture_ARM:
1339 {
1340 /** @todo BUGBUG ARM stuff here */
1341 break;
1342 }
1343
1344 default:
1345 AssertFailed();
1346 break;
1347 }
1348
1349 SHOW_ULONG_PROP( machine, CPUIDPortabilityLevel, "cpuid-portability-level", Info::tr("CPUID Portability Level:"), "");
1350
1351 ComPtr<INvramStore> nvramStore;
1352 CHECK_ERROR2I_RET(machine, COMGETTER(NonVolatileStore)(nvramStore.asOutParam()), hrcCheck);
1353
1354 FirmwareBootMenuMode_T enmBootMenuMode;
1355 CHECK_ERROR2I_RET(firmwareSettings, COMGETTER(BootMenuMode)(&enmBootMenuMode), hrcCheck);
1356 const char *pszBootMenu;
1357 switch (enmBootMenuMode)
1358 {
1359 case FirmwareBootMenuMode_Disabled:
1360 if (details == VMINFO_MACHINEREADABLE)
1361 pszBootMenu = "disabled";
1362 else
1363 pszBootMenu = Info::tr("disabled");
1364 break;
1365 case FirmwareBootMenuMode_MenuOnly:
1366 if (details == VMINFO_MACHINEREADABLE)
1367 pszBootMenu = "menuonly";
1368 else
1369 pszBootMenu = Info::tr("menu only");
1370 break;
1371 default:
1372 if (details == VMINFO_MACHINEREADABLE)
1373 pszBootMenu = "messageandmenu";
1374 else
1375 pszBootMenu = Info::tr("message and menu");
1376 }
1377 SHOW_UTF8_STRING("bootmenu", Info::tr("Boot menu mode:"), pszBootMenu);
1378
1379 ComPtr<ISystemProperties> systemProperties;
1380 CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), hrcCheck);
1381 ULONG maxBootPosition = 0;
1382 CHECK_ERROR2I_RET(platformProperties, COMGETTER(MaxBootPosition)(&maxBootPosition), hrcCheck);
1383 for (ULONG i = 1; i <= maxBootPosition; i++)
1384 {
1385 DeviceType_T bootOrder;
1386 CHECK_ERROR2I_RET(machine, GetBootOrder(i, &bootOrder), hrcCheck);
1387 const char *pszDevice;
1388 if (bootOrder == DeviceType_Floppy)
1389 pszDevice = details == VMINFO_MACHINEREADABLE ? "floppy" : Info::tr("Floppy");
1390 else if (bootOrder == DeviceType_DVD)
1391 pszDevice = details == VMINFO_MACHINEREADABLE ? "dvd" : "DVD";
1392 else if (bootOrder == DeviceType_HardDisk)
1393 pszDevice = details == VMINFO_MACHINEREADABLE ? "disk" : Info::tr("HardDisk");
1394 else if (bootOrder == DeviceType_Network)
1395 pszDevice = details == VMINFO_MACHINEREADABLE ? "net" : Info::tr("Network");
1396 else if (bootOrder == DeviceType_USB)
1397 pszDevice = details == VMINFO_MACHINEREADABLE ? "usb" : "USB";
1398 else if (bootOrder == DeviceType_SharedFolder)
1399 pszDevice = details == VMINFO_MACHINEREADABLE ? "sharedfolder" : Info::tr("Shared Folder");
1400 else
1401 pszDevice = details == VMINFO_MACHINEREADABLE ? "none" : Info::tr("Not Assigned");
1402 SHOW_UTF8_STRING(FmtNm(szNm, "boot%u", i), FmtNm(szNm, Info::tr("Boot Device %u:"), i), pszDevice);
1403 }
1404
1405 SHOW_BOOLEAN_PROP(firmwareSettings, ACPIEnabled, "acpi", "ACPI:");
1406 SHOW_BOOLEAN_PROP(firmwareSettings, IOAPICEnabled, "ioapic", "IOAPIC:");
1407
1408 APICMode_T apicMode;
1409 CHECK_ERROR2I_RET(firmwareSettings, COMGETTER(APICMode)(&apicMode), hrcCheck);
1410 const char *pszAPIC;
1411 switch (apicMode)
1412 {
1413 case APICMode_Disabled:
1414 if (details == VMINFO_MACHINEREADABLE)
1415 pszAPIC = "disabled";
1416 else
1417 pszAPIC = Info::tr("disabled");
1418 break;
1419 case APICMode_APIC:
1420 default:
1421 if (details == VMINFO_MACHINEREADABLE)
1422 pszAPIC = "apic";
1423 else
1424 pszAPIC = "APIC";
1425 break;
1426 case APICMode_X2APIC:
1427 if (details == VMINFO_MACHINEREADABLE)
1428 pszAPIC = "x2apic";
1429 else
1430 pszAPIC = "x2APIC";
1431 break;
1432 }
1433 SHOW_UTF8_STRING("biosapic", Info::tr("BIOS APIC mode:"), pszAPIC);
1434
1435 SHOW_LONG64_PROP(firmwareSettings, TimeOffset, "biossystemtimeoffset", Info::tr("Time offset:"), Info::tr("ms"));
1436 Bstr bstrNVRAMFile;
1437 CHECK_ERROR2I_RET(nvramStore, COMGETTER(NonVolatileStorageFile)(bstrNVRAMFile.asOutParam()), hrcCheck);
1438 if (bstrNVRAMFile.isNotEmpty())
1439 SHOW_BSTR_STRING("NvramFile", Info::tr("BIOS NVRAM File:"), bstrNVRAMFile);
1440 if ( firmwareType == FirmwareType_EFI || firmwareType == FirmwareType_EFI32
1441 || firmwareType == FirmwareType_EFI64 || firmwareType == FirmwareType_EFIDUAL)
1442 {
1443 ComPtr<IUefiVariableStore> uefiVarStore;
1444 hrc = nvramStore->COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam());
1445 if (SUCCEEDED(hrc))
1446 SHOW_BOOLEAN_PROP(uefiVarStore, SecureBootEnabled, "SecureBoot", Info::tr("UEFI Secure Boot:"));
1447 }
1448 SHOW_BOOLEAN_PROP_EX(platform, RTCUseUTC, "rtcuseutc", Info::tr("RTC:"), "UTC", Info::tr("local time"));
1449
1450#ifdef VBOX_WITH_IOMMU_AMD /** @todo BUGBUG Do we set / needs this for ARM as well? */
1451 IommuType_T iommuType;
1452 CHECK_ERROR2I_RET(platform, COMGETTER(IommuType)(&iommuType), hrcCheck);
1453 const char *pszIommuType = iommuTypeToString(iommuType, details);
1454 SHOW_UTF8_STRING("iommu", "IOMMU:", pszIommuType);
1455#endif
1456
1457 ParavirtProvider_T paravirtProvider;
1458 CHECK_ERROR2I_RET(machine, COMGETTER(ParavirtProvider)(&paravirtProvider), hrcCheck);
1459 const char *pszParavirtProvider = paravirtProviderToString(paravirtProvider, details);
1460 SHOW_UTF8_STRING("paravirtprovider", Info::tr("Paravirt. Provider:"), pszParavirtProvider);
1461
1462 ParavirtProvider_T effParavirtProvider;
1463 CHECK_ERROR2I_RET(machine, GetEffectiveParavirtProvider(&effParavirtProvider), hrcCheck);
1464 const char *pszEffParavirtProvider = paravirtProviderToString(effParavirtProvider, details);
1465 SHOW_UTF8_STRING("effparavirtprovider", Info::tr("Effective Paravirt. Prov.:"), pszEffParavirtProvider);
1466
1467 Bstr paravirtDebug;
1468 CHECK_ERROR2I_RET(machine, COMGETTER(ParavirtDebug)(paravirtDebug.asOutParam()), hrcCheck);
1469 if (paravirtDebug.isNotEmpty())
1470 SHOW_BSTR_STRING("paravirtdebug", Info::tr("Paravirt. Debug:"), paravirtDebug);
1471
1472 MachineState_T machineState;
1473 CHECK_ERROR2I_RET(machine, COMGETTER(State)(&machineState), hrcCheck);
1474 const char *pszState = machineStateToName(machineState, details == VMINFO_MACHINEREADABLE /*=fShort*/);
1475
1476 LONG64 stateSince;
1477 machine->COMGETTER(LastStateChange)(&stateSince);
1478 RTTIMESPEC timeSpec;
1479 RTTimeSpecSetMilli(&timeSpec, stateSince);
1480 char pszTime[30] = {0};
1481 RTTimeSpecToString(&timeSpec, pszTime, sizeof(pszTime));
1482 if (details == VMINFO_MACHINEREADABLE)
1483 {
1484 RTPrintf("VMState=\"%s\"\n", pszState);
1485 RTPrintf("VMStateChangeTime=\"%s\"\n", pszTime);
1486
1487 Bstr stateFile;
1488 machine->COMGETTER(StateFilePath)(stateFile.asOutParam());
1489 if (!stateFile.isEmpty())
1490 RTPrintf("VMStateFile=\"%ls\"\n", stateFile.raw());
1491 }
1492 else
1493 RTPrintf(Info::tr("%-28s %s (since %s)\n"), Info::tr("State:"), pszState, pszTime);
1494
1495 GraphicsControllerType_T enmGraphics;
1496 hrc = pGraphicsAdapter->COMGETTER(GraphicsControllerType)(&enmGraphics);
1497 if (SUCCEEDED(hrc))
1498 {
1499 const char *pszCtrl;
1500 switch (enmGraphics)
1501 {
1502 case GraphicsControllerType_Null:
1503 if (details == VMINFO_MACHINEREADABLE)
1504 pszCtrl = "null";
1505 else
1506 pszCtrl = Info::tr("Null");
1507 break;
1508 case GraphicsControllerType_VBoxVGA:
1509 if (details == VMINFO_MACHINEREADABLE)
1510 pszCtrl = "vboxvga";
1511 else
1512 pszCtrl = "VBoxVGA";
1513 break;
1514 case GraphicsControllerType_VMSVGA:
1515 if (details == VMINFO_MACHINEREADABLE)
1516 pszCtrl = "vmsvga";
1517 else
1518 pszCtrl = "VMSVGA";
1519 break;
1520 case GraphicsControllerType_VBoxSVGA:
1521 if (details == VMINFO_MACHINEREADABLE)
1522 pszCtrl = "vboxsvga";
1523 else
1524 pszCtrl = "VBoxSVGA";
1525 break;
1526 case GraphicsControllerType_QemuRamFB:
1527 if (details == VMINFO_MACHINEREADABLE)
1528 pszCtrl = "qemuramfb";
1529 else
1530 pszCtrl = "QemuRamFB";
1531 break;
1532
1533 default:
1534 if (details == VMINFO_MACHINEREADABLE)
1535 pszCtrl = "unknown";
1536 else
1537 pszCtrl = Info::tr("Unknown");
1538 break;
1539 }
1540
1541 if (details == VMINFO_MACHINEREADABLE)
1542 RTPrintf("graphicscontroller=\"%s\"\n", pszCtrl);
1543 else
1544 RTPrintf("%-28s %s\n", Info::tr("Graphics Controller:"), pszCtrl);
1545 }
1546
1547 SHOW_ULONG_PROP(pGraphicsAdapter, MonitorCount, "monitorcount", Info::tr("Monitor count:"), "");
1548 SHOW_BOOLEAN_METHOD(pGraphicsAdapter, IsFeatureEnabled(GraphicsFeature_Acceleration3D, &f), "accelerate3d", "3D Acceleration:");
1549 SHOW_BOOLEAN_PROP( machine, TeleporterEnabled, "teleporterenabled", Info::tr("Teleporter Enabled:"));
1550 SHOW_ULONG_PROP( machine, TeleporterPort, "teleporterport", Info::tr("Teleporter Port:"), "");
1551 SHOW_STRING_PROP( machine, TeleporterAddress, "teleporteraddress", Info::tr("Teleporter Address:"));
1552 SHOW_STRING_PROP( machine, TeleporterPassword, "teleporterpassword", Info::tr("Teleporter Password:"));
1553 SHOW_BOOLEAN_PROP( machine, TracingEnabled, "tracing-enabled", Info::tr("Tracing Enabled:"));
1554 SHOW_BOOLEAN_PROP( machine, AllowTracingToAccessVM, "tracing-allow-vm-access", Info::tr("Allow Tracing to Access VM:"));
1555 SHOW_STRING_PROP( machine, TracingConfig, "tracing-config", Info::tr("Tracing Configuration:"));
1556 SHOW_BOOLEAN_PROP( machine, AutostartEnabled, "autostart-enabled", Info::tr("Autostart Enabled:"));
1557 SHOW_ULONG_PROP( machine, AutostartDelay, "autostart-delay", Info::tr("Autostart Delay:"), "");
1558 SHOW_STRING_PROP( machine, DefaultFrontend, "defaultfrontend", Info::tr("Default Frontend:"));
1559
1560 VMProcPriority_T enmVMProcPriority;
1561 CHECK_ERROR2I_RET(machine, COMGETTER(VMProcessPriority)(&enmVMProcPriority), hrcCheck);
1562 const char *pszVMProcPriority;
1563 switch (enmVMProcPriority)
1564 {
1565 case VMProcPriority_Flat:
1566 if (details == VMINFO_MACHINEREADABLE)
1567 pszVMProcPriority = "flat";
1568 else
1569 pszVMProcPriority = Info::tr("flat");
1570 break;
1571 case VMProcPriority_Low:
1572 if (details == VMINFO_MACHINEREADABLE)
1573 pszVMProcPriority = "low";
1574 else
1575 pszVMProcPriority = Info::tr("low");
1576 break;
1577 case VMProcPriority_Normal:
1578 if (details == VMINFO_MACHINEREADABLE)
1579 pszVMProcPriority = "normal";
1580 else
1581 pszVMProcPriority = Info::tr("normal");
1582 break;
1583 case VMProcPriority_High:
1584 if (details == VMINFO_MACHINEREADABLE)
1585 pszVMProcPriority = "high";
1586 else
1587 pszVMProcPriority = Info::tr("high");
1588 break;
1589 default:
1590 if (details == VMINFO_MACHINEREADABLE)
1591 pszVMProcPriority = "default";
1592 else
1593 pszVMProcPriority = Info::tr("default");
1594 break;
1595 }
1596 SHOW_UTF8_STRING("vmprocpriority", Info::tr("VM process priority:"), pszVMProcPriority);
1597
1598/** @todo Convert the remainder of the function to SHOW_XXX macros and add error
1599 * checking where missing. */
1600 /*
1601 * Storage Controllers and their attached Mediums.
1602 */
1603 com::SafeIfaceArray<IStorageController> storageCtls;
1604 CHECK_ERROR(machine, COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(storageCtls)));
1605 if (storageCtls.size() > 0)
1606 {
1607 if (details != VMINFO_MACHINEREADABLE)
1608 RTPrintf("%s\n", Info::tr("Storage Controllers:"));
1609
1610 for (size_t i = 0; i < storageCtls.size(); ++i)
1611 {
1612 ComPtr<IStorageController> storageCtl = storageCtls[i];
1613
1614 Bstr bstrName;
1615 CHECK_ERROR2I_RET(storageCtl, COMGETTER(Name)(bstrName.asOutParam()), hrcCheck);
1616 StorageControllerType_T enmCtlType = StorageControllerType_Null;
1617 CHECK_ERROR2I_RET(storageCtl, COMGETTER(ControllerType)(&enmCtlType), hrcCheck);
1618 ULONG uInstance = 0;
1619 CHECK_ERROR2I_RET(storageCtl, COMGETTER(Instance)(&uInstance), hrcCheck);
1620 ULONG cMaxPorts = 0;
1621 CHECK_ERROR2I_RET(storageCtl, COMGETTER(MaxPortCount)(&cMaxPorts), hrcCheck);
1622 ULONG cPorts = 0;
1623 CHECK_ERROR2I_RET(storageCtl, COMGETTER(PortCount)(&cPorts), hrcCheck);
1624 BOOL fBootable = FALSE;
1625 CHECK_ERROR2I_RET(storageCtl, COMGETTER(Bootable)(&fBootable), hrcCheck);
1626 if (details == VMINFO_MACHINEREADABLE)
1627 {
1628 outputMachineReadableString(FmtNm(szNm, "storagecontrollername%u", i), &bstrName);
1629 outputMachineReadableString(FmtNm(szNm, "storagecontrollertype%u", i),
1630 storageControllerTypeToName(enmCtlType, true));
1631 RTPrintf("storagecontrollerinstance%u=\"%u\"\n", i, uInstance);
1632 RTPrintf("storagecontrollermaxportcount%u=\"%u\"\n", i, cMaxPorts);
1633 RTPrintf("storagecontrollerportcount%u=\"%u\"\n", i, cPorts);
1634 RTPrintf("storagecontrollerbootable%u=\"%s\"\n", i, fBootable ? "on" : "off");
1635 }
1636 else
1637 {
1638 RTPrintf(Info::tr("#%u: '%ls', Type: %s, Instance: %u, Ports: %u (max %u), %s\n"), i, bstrName.raw(),
1639 storageControllerTypeToName(enmCtlType, false), uInstance, cPorts, cMaxPorts,
1640 fBootable ? Info::tr("Bootable") : Info::tr("Not bootable"));
1641 hrc = showMediumAttachments(machine, storageCtl, details);
1642 if (FAILED(hrc))
1643 return hrc;
1644 }
1645 }
1646 }
1647 else if (details != VMINFO_MACHINEREADABLE)
1648 RTPrintf("%-28s %s\n", Info::tr("Storage Controllers:"), Info::tr("<none>"));
1649
1650 if (details == VMINFO_MACHINEREADABLE)
1651 for (size_t j = 0; j < storageCtls.size(); ++ j)
1652 {
1653 hrc = showMediumAttachments(machine, storageCtls[j], details);
1654 if (FAILED(hrc))
1655 return hrc;
1656 }
1657
1658 /* get the maximum amount of NICS */
1659 ULONG maxNICs = getMaxNics(machine);
1660
1661 for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++)
1662 {
1663 ComPtr<INetworkAdapter> nic;
1664 hrc = machine->GetNetworkAdapter(currentNIC, nic.asOutParam());
1665 if (SUCCEEDED(hrc) && nic)
1666 {
1667 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "nic%u" : Info::tr("NIC %u:"), currentNIC + 1);
1668
1669 BOOL fEnabled;
1670 nic->COMGETTER(Enabled)(&fEnabled);
1671 if (!fEnabled)
1672 {
1673 if (details == VMINFO_MACHINEREADABLE)
1674 RTPrintf("%s=\"none\"\n", szNm);
1675 else
1676 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
1677 }
1678 else
1679 {
1680 Bstr strMACAddress;
1681 nic->COMGETTER(MACAddress)(strMACAddress.asOutParam());
1682 Utf8Str strAttachment;
1683 Utf8Str strNatSettings;
1684 Utf8Str strNatForwardings;
1685 NetworkAttachmentType_T attachment;
1686 nic->COMGETTER(AttachmentType)(&attachment);
1687 switch (attachment)
1688 {
1689 case NetworkAttachmentType_Null:
1690 if (details == VMINFO_MACHINEREADABLE)
1691 strAttachment = "null";
1692 else
1693 strAttachment = Info::tr("none");
1694 break;
1695
1696 case NetworkAttachmentType_NAT:
1697 {
1698 Bstr strNetwork;
1699 ComPtr<INATEngine> engine;
1700 nic->COMGETTER(NATEngine)(engine.asOutParam());
1701 engine->COMGETTER(Network)(strNetwork.asOutParam());
1702 com::SafeArray<BSTR> forwardings;
1703 engine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(forwardings));
1704 strNatForwardings = "";
1705 for (size_t i = 0; i < forwardings.size(); ++i)
1706 {
1707 bool fSkip = false;
1708 BSTR r = forwardings[i];
1709 Utf8Str utf = Utf8Str(r);
1710 Utf8Str strName;
1711 Utf8Str strProto;
1712 Utf8Str strHostPort;
1713 Utf8Str strHostIP;
1714 Utf8Str strGuestPort;
1715 Utf8Str strGuestIP;
1716 size_t pos, ppos;
1717 pos = ppos = 0;
1718#define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \
1719 do { \
1720 pos = str.find(",", ppos); \
1721 if (pos == Utf8Str::npos) \
1722 { \
1723 Log(( #res " extracting from %s is failed\n", str.c_str())); \
1724 fSkip = true; \
1725 } \
1726 res = str.substr(ppos, pos - ppos); \
1727 Log2((#res " %s pos:%d, ppos:%d\n", res.c_str(), pos, ppos)); \
1728 ppos = pos + 1; \
1729 } while (0)
1730 ITERATE_TO_NEXT_TERM(strName, utf, pos, ppos);
1731 if (fSkip) continue;
1732 ITERATE_TO_NEXT_TERM(strProto, utf, pos, ppos);
1733 if (fSkip) continue;
1734 ITERATE_TO_NEXT_TERM(strHostIP, utf, pos, ppos);
1735 if (fSkip) continue;
1736 ITERATE_TO_NEXT_TERM(strHostPort, utf, pos, ppos);
1737 if (fSkip) continue;
1738 ITERATE_TO_NEXT_TERM(strGuestIP, utf, pos, ppos);
1739 if (fSkip) continue;
1740 strGuestPort = utf.substr(ppos, utf.length() - ppos);
1741#undef ITERATE_TO_NEXT_TERM
1742 switch (strProto.toUInt32())
1743 {
1744 case NATProtocol_TCP:
1745 strProto = "tcp";
1746 break;
1747 case NATProtocol_UDP:
1748 strProto = "udp";
1749 break;
1750 default:
1751 strProto = "unk";
1752 break;
1753 }
1754 if (details == VMINFO_MACHINEREADABLE)
1755 /** @todo r=bird: This probably isn't good enough wrt escaping. */
1756 strNatForwardings.appendPrintf("Forwarding(%d)=\"%s,%s,%s,%s,%s,%s\"\n",
1757 i, strName.c_str(), strProto.c_str(),
1758 strHostIP.c_str(), strHostPort.c_str(),
1759 strGuestIP.c_str(), strGuestPort.c_str());
1760 else
1761 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"),
1762 currentNIC + 1, i, strName.c_str(),
1763 strProto.c_str(), strHostIP.c_str(), strHostPort.c_str(),
1764 strGuestIP.c_str(), strGuestPort.c_str());
1765 }
1766 ULONG mtu = 0;
1767 ULONG sockSnd = 0;
1768 ULONG sockRcv = 0;
1769 ULONG tcpSnd = 0;
1770 ULONG tcpRcv = 0;
1771 engine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv);
1772
1773/** @todo r=klaus dnsproxy etc needs to be dumped, too */
1774 if (details == VMINFO_MACHINEREADABLE)
1775 {
1776 RTPrintf("natnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.length() ? strNetwork.raw(): Bstr("nat").raw());
1777 strAttachment = "nat";
1778 strNatSettings.printf("mtu=\"%d\"\nsockSnd=\"%d\"\nsockRcv=\"%d\"\ntcpWndSnd=\"%d\"\ntcpWndRcv=\"%d\"\n",
1779 mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1780 }
1781 else
1782 {
1783 strAttachment = "NAT";
1784 strNatSettings.printf(Info::tr("NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d)\n"),
1785 currentNIC + 1, mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1786 }
1787 break;
1788 }
1789
1790 case NetworkAttachmentType_Bridged:
1791 {
1792 Bstr strBridgeAdp;
1793 nic->COMGETTER(BridgedInterface)(strBridgeAdp.asOutParam());
1794 if (details == VMINFO_MACHINEREADABLE)
1795 {
1796 RTPrintf("bridgeadapter%d=\"%ls\"\n", currentNIC + 1, strBridgeAdp.raw());
1797 strAttachment = "bridged";
1798 }
1799 else
1800 strAttachment.printf(Info::tr("Bridged Interface '%ls'"), strBridgeAdp.raw());
1801 break;
1802 }
1803
1804 case NetworkAttachmentType_Internal:
1805 {
1806 Bstr strNetwork;
1807 nic->COMGETTER(InternalNetwork)(strNetwork.asOutParam());
1808 if (details == VMINFO_MACHINEREADABLE)
1809 {
1810 RTPrintf("intnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1811 strAttachment = "intnet";
1812 }
1813 else
1814 strAttachment.printf(Info::tr("Internal Network '%s'"), Utf8Str(strNetwork).c_str());
1815 break;
1816 }
1817
1818 case NetworkAttachmentType_HostOnly:
1819 {
1820 Bstr strHostonlyAdp;
1821 nic->COMGETTER(HostOnlyInterface)(strHostonlyAdp.asOutParam());
1822 if (details == VMINFO_MACHINEREADABLE)
1823 {
1824 RTPrintf("hostonlyadapter%d=\"%ls\"\n", currentNIC + 1, strHostonlyAdp.raw());
1825 strAttachment = "hostonly";
1826 }
1827 else
1828 strAttachment.printf(Info::tr("Host-only Interface '%ls'"), strHostonlyAdp.raw());
1829 break;
1830 }
1831
1832 case NetworkAttachmentType_Generic:
1833 {
1834 Bstr strGenericDriver;
1835 nic->COMGETTER(GenericDriver)(strGenericDriver.asOutParam());
1836 if (details == VMINFO_MACHINEREADABLE)
1837 {
1838 RTPrintf("generic%d=\"%ls\"\n", currentNIC + 1, strGenericDriver.raw());
1839 strAttachment = "Generic";
1840 }
1841 else
1842 {
1843 strAttachment.printf(Info::tr("Generic '%ls'"), strGenericDriver.raw());
1844
1845 // show the generic properties
1846 com::SafeArray<BSTR> aProperties;
1847 com::SafeArray<BSTR> aValues;
1848 hrc = nic->GetProperties(NULL,
1849 ComSafeArrayAsOutParam(aProperties),
1850 ComSafeArrayAsOutParam(aValues));
1851 if (SUCCEEDED(hrc))
1852 {
1853 strAttachment += " { ";
1854 for (unsigned i = 0; i < aProperties.size(); ++i)
1855 strAttachment.appendPrintf(!i ? "%ls='%ls'" : ", %ls='%ls'", aProperties[i], aValues[i]);
1856 strAttachment += " }";
1857 }
1858 }
1859 break;
1860 }
1861
1862 case NetworkAttachmentType_NATNetwork:
1863 {
1864 Bstr strNetwork;
1865 nic->COMGETTER(NATNetwork)(strNetwork.asOutParam());
1866 if (details == VMINFO_MACHINEREADABLE)
1867 {
1868 RTPrintf("nat-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1869 strAttachment = "natnetwork";
1870 }
1871 else
1872 strAttachment.printf(Info::tr("NAT Network '%s'"), Utf8Str(strNetwork).c_str());
1873 break;
1874 }
1875
1876#ifdef VBOX_WITH_VMNET
1877 case NetworkAttachmentType_HostOnlyNetwork:
1878 {
1879 Bstr strNetwork;
1880 nic->COMGETTER(HostOnlyNetwork)(strNetwork.asOutParam());
1881 if (details == VMINFO_MACHINEREADABLE)
1882 {
1883 RTPrintf("hostonly-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1884 strAttachment = "hostonlynetwork";
1885 }
1886 else
1887 strAttachment.printf(Info::tr("Host Only Network '%s'"), Utf8Str(strNetwork).c_str());
1888 break;
1889 }
1890#endif /* VBOX_WITH_VMNET */
1891
1892#ifdef VBOX_WITH_CLOUD_NET
1893 case NetworkAttachmentType_Cloud:
1894 {
1895 Bstr strNetwork;
1896 nic->COMGETTER(CloudNetwork)(strNetwork.asOutParam());
1897 if (details == VMINFO_MACHINEREADABLE)
1898 {
1899 RTPrintf("cloud-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1900 strAttachment = "cloudnetwork";
1901 }
1902 else
1903 strAttachment.printf(Info::tr("Cloud Network '%s'"), Utf8Str(strNetwork).c_str());
1904 break;
1905 }
1906#endif /* VBOX_WITH_CLOUD_NET */
1907
1908 default:
1909 if (details == VMINFO_MACHINEREADABLE)
1910 strAttachment = "unknown";
1911 else
1912 strAttachment = Info::tr("unknown");
1913 break;
1914 }
1915
1916 /* cable connected */
1917 BOOL fConnected;
1918 nic->COMGETTER(CableConnected)(&fConnected);
1919
1920 /* promisc policy */
1921 NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy;
1922 CHECK_ERROR2I_RET(nic, COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy), hrcCheck);
1923 const char *pszPromiscuousGuestPolicy;
1924 switch (enmPromiscModePolicy)
1925 {
1926 case NetworkAdapterPromiscModePolicy_Deny: pszPromiscuousGuestPolicy = Info::tr("deny"); break;
1927 case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = Info::tr("allow-vms"); break;
1928 case NetworkAdapterPromiscModePolicy_AllowAll: pszPromiscuousGuestPolicy = Info::tr("allow-all"); break;
1929 default: AssertFailedReturn(E_INVALIDARG);
1930 }
1931
1932 /* trace stuff */
1933 BOOL fTraceEnabled;
1934 nic->COMGETTER(TraceEnabled)(&fTraceEnabled);
1935 Bstr traceFile;
1936 nic->COMGETTER(TraceFile)(traceFile.asOutParam());
1937
1938 /* NIC type */
1939 NetworkAdapterType_T NICType;
1940 nic->COMGETTER(AdapterType)(&NICType);
1941 const char *pszNICType;
1942 switch (NICType)
1943 {
1944 case NetworkAdapterType_Am79C970A: pszNICType = "Am79C970A"; break;
1945 case NetworkAdapterType_Am79C973: pszNICType = "Am79C973"; break;
1946 case NetworkAdapterType_Am79C960: pszNICType = "Am79C960"; break;
1947#ifdef VBOX_WITH_E1000
1948 case NetworkAdapterType_I82540EM: pszNICType = "82540EM"; break;
1949 case NetworkAdapterType_I82543GC: pszNICType = "82543GC"; break;
1950 case NetworkAdapterType_I82545EM: pszNICType = "82545EM"; break;
1951#endif
1952#ifdef VBOX_WITH_VIRTIO
1953 case NetworkAdapterType_Virtio: pszNICType = "virtio"; break;
1954#endif
1955 case NetworkAdapterType_NE1000: pszNICType = "NE1000"; break;
1956 case NetworkAdapterType_NE2000: pszNICType = "NE2000"; break;
1957 case NetworkAdapterType_WD8003: pszNICType = "WD8003"; break;
1958 case NetworkAdapterType_WD8013: pszNICType = "WD8013"; break;
1959 case NetworkAdapterType_ELNK2: pszNICType = "3C503"; break;
1960 case NetworkAdapterType_ELNK1: pszNICType = "3C501"; break;
1961 case NetworkAdapterType_UsbNet: pszNICType = "usbnet"; break;
1962 default:
1963 AssertFailed();
1964 if (details == VMINFO_MACHINEREADABLE)
1965 pszNICType = "unknown";
1966 else
1967 pszNICType = Info::tr("unknown");
1968 break;
1969 }
1970
1971 /* reported line speed */
1972 ULONG ulLineSpeed;
1973 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1974
1975 /* boot priority of the adapter */
1976 ULONG ulBootPriority;
1977 nic->COMGETTER(BootPriority)(&ulBootPriority);
1978
1979 /* bandwidth group */
1980 ComObjPtr<IBandwidthGroup> pBwGroup;
1981 Bstr strBwGroup;
1982 nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());
1983 if (!pBwGroup.isNull())
1984 pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam());
1985
1986 if (details == VMINFO_MACHINEREADABLE)
1987 {
1988 RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw());
1989 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1990 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str());
1991 RTPrintf("nictype%d=\"%s\"\n", currentNIC + 1, pszNICType);
1992 RTPrintf("nicspeed%d=\"%d\"\n", currentNIC + 1, ulLineSpeed);
1993 }
1994 else
1995 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"),
1996 szNm, strMACAddress.raw(), strAttachment.c_str(),
1997 fConnected ? Info::tr("on") : Info::tr("off"),
1998 fTraceEnabled ? Info::tr("on") : Info::tr("off"),
1999 traceFile.isEmpty() ? Bstr(Info::tr("none")).raw() : traceFile.raw(),
2000 pszNICType,
2001 ulLineSpeed / 1000,
2002 (int)ulBootPriority,
2003 pszPromiscuousGuestPolicy,
2004 strBwGroup.isEmpty() ? Bstr(Info::tr("none")).raw() : strBwGroup.raw());
2005 if (strNatSettings.length())
2006 RTPrintf(strNatSettings.c_str());
2007 if (strNatForwardings.length())
2008 RTPrintf(strNatForwardings.c_str());
2009 }
2010 }
2011 }
2012
2013 /* Pointing device information */
2014 PointingHIDType_T aPointingHID;
2015 const char *pszHID = Info::tr("Unknown");
2016 const char *pszMrHID = "unknown";
2017 machine->COMGETTER(PointingHIDType)(&aPointingHID);
2018 switch (aPointingHID)
2019 {
2020 case PointingHIDType_None:
2021 pszHID = Info::tr("None");
2022 pszMrHID = "none";
2023 break;
2024 case PointingHIDType_PS2Mouse:
2025 pszHID = Info::tr("PS/2 Mouse");
2026 pszMrHID = "ps2mouse";
2027 break;
2028 case PointingHIDType_USBMouse:
2029 pszHID = Info::tr("USB Mouse");
2030 pszMrHID = "usbmouse";
2031 break;
2032 case PointingHIDType_USBTablet:
2033 pszHID = Info::tr("USB Tablet");
2034 pszMrHID = "usbtablet";
2035 break;
2036 case PointingHIDType_ComboMouse:
2037 pszHID = Info::tr("USB Tablet and PS/2 Mouse");
2038 pszMrHID = "combomouse";
2039 break;
2040 case PointingHIDType_USBMultiTouch:
2041 pszHID = Info::tr("USB Multi-Touch");
2042 pszMrHID = "usbmultitouch";
2043 break;
2044 default:
2045 break;
2046 }
2047 SHOW_UTF8_STRING("hidpointing", Info::tr("Pointing Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
2048
2049 /* Keyboard device information */
2050 KeyboardHIDType_T aKeyboardHID;
2051 machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID);
2052 pszHID = Info::tr("Unknown");
2053 pszMrHID = "unknown";
2054 switch (aKeyboardHID)
2055 {
2056 case KeyboardHIDType_None:
2057 pszHID = Info::tr("None");
2058 pszMrHID = "none";
2059 break;
2060 case KeyboardHIDType_PS2Keyboard:
2061 pszHID = Info::tr("PS/2 Keyboard");
2062 pszMrHID = "ps2kbd";
2063 break;
2064 case KeyboardHIDType_USBKeyboard:
2065 pszHID = Info::tr("USB Keyboard");
2066 pszMrHID = "usbkbd";
2067 break;
2068 case KeyboardHIDType_ComboKeyboard:
2069 pszHID = Info::tr("USB and PS/2 Keyboard");
2070 pszMrHID = "combokbd";
2071 break;
2072 default:
2073 break;
2074 }
2075 SHOW_UTF8_STRING("hidkeyboard", Info::tr("Keyboard Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
2076
2077 ComPtr<ISystemProperties> sysProps;
2078 pVirtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
2079
2080 /* get the maximum amount of UARTs */
2081 ULONG maxUARTs = 0;
2082 platformProperties->COMGETTER(SerialPortCount)(&maxUARTs);
2083 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
2084 {
2085 ComPtr<ISerialPort> uart;
2086 hrc = machine->GetSerialPort(currentUART, uart.asOutParam());
2087 if (SUCCEEDED(hrc) && uart)
2088 {
2089 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "uart%u" : Info::tr("UART %u:"), currentUART + 1);
2090
2091 /* show the config of this UART */
2092 BOOL fEnabled;
2093 uart->COMGETTER(Enabled)(&fEnabled);
2094 if (!fEnabled)
2095 {
2096 if (details == VMINFO_MACHINEREADABLE)
2097 RTPrintf("%s=\"off\"\n", szNm);
2098 else
2099 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
2100 }
2101 else
2102 {
2103 ULONG ulIRQ, ulIOAddress;
2104 PortMode_T HostMode;
2105 Bstr path;
2106 BOOL fServer;
2107 UartType_T UartType;
2108 uart->COMGETTER(IRQ)(&ulIRQ);
2109 uart->COMGETTER(IOAddress)(&ulIOAddress);
2110 uart->COMGETTER(Path)(path.asOutParam());
2111 uart->COMGETTER(Server)(&fServer);
2112 uart->COMGETTER(HostMode)(&HostMode);
2113 uart->COMGETTER(UartType)(&UartType);
2114
2115 if (details == VMINFO_MACHINEREADABLE)
2116 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOAddress, ulIRQ);
2117 else
2118 RTPrintf(Info::tr("%-28s I/O address: %#06x, IRQ: %d"), szNm, ulIOAddress, ulIRQ);
2119 switch (HostMode)
2120 {
2121 default:
2122 case PortMode_Disconnected:
2123 if (details == VMINFO_MACHINEREADABLE)
2124 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
2125 else
2126 RTPrintf(Info::tr(", disconnected"));
2127 break;
2128 case PortMode_RawFile:
2129 if (details == VMINFO_MACHINEREADABLE)
2130 RTPrintf("uartmode%d=\"file,%ls\"\n", currentUART + 1,
2131 path.raw());
2132 else
2133 RTPrintf(Info::tr(", attached to raw file '%ls'\n"),
2134 path.raw());
2135 break;
2136 case PortMode_TCP:
2137 if (details == VMINFO_MACHINEREADABLE)
2138 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
2139 fServer ? "tcpserver" : "tcpclient", path.raw());
2140 else
2141 RTPrintf(Info::tr(", attached to tcp (%s) '%ls'"),
2142 fServer ? Info::tr("server") : Info::tr("client"), path.raw());
2143 break;
2144 case PortMode_HostPipe:
2145 if (details == VMINFO_MACHINEREADABLE)
2146 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
2147 fServer ? "server" : "client", path.raw());
2148 else
2149 RTPrintf(Info::tr(", attached to pipe (%s) '%ls'"),
2150 fServer ? Info::tr("server") : Info::tr("client"), path.raw());
2151 break;
2152 case PortMode_HostDevice:
2153 if (details == VMINFO_MACHINEREADABLE)
2154 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
2155 path.raw());
2156 else
2157 RTPrintf(Info::tr(", attached to device '%ls'"), path.raw());
2158 break;
2159 }
2160 switch (UartType)
2161 {
2162 default:
2163 case UartType_U16450:
2164 if (details == VMINFO_MACHINEREADABLE)
2165 RTPrintf("uarttype%d=\"16450\"\n", currentUART + 1);
2166 else
2167 RTPrintf(", 16450\n");
2168 break;
2169 case UartType_U16550A:
2170 if (details == VMINFO_MACHINEREADABLE)
2171 RTPrintf("uarttype%d=\"16550A\"\n", currentUART + 1);
2172 else
2173 RTPrintf(", 16550A\n");
2174 break;
2175 case UartType_U16750:
2176 if (details == VMINFO_MACHINEREADABLE)
2177 RTPrintf("uarttype%d=\"16750\"\n", currentUART + 1);
2178 else
2179 RTPrintf(", 16750\n");
2180 break;
2181 }
2182 }
2183 }
2184 }
2185
2186 /* get the maximum amount of LPTs */
2187 ULONG maxLPTs = 0;
2188 platformProperties->COMGETTER(ParallelPortCount)(&maxLPTs);
2189 for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++)
2190 {
2191 ComPtr<IParallelPort> lpt;
2192 hrc = machine->GetParallelPort(currentLPT, lpt.asOutParam());
2193 if (SUCCEEDED(hrc) && lpt)
2194 {
2195 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "lpt%u" : Info::tr("LPT %u:"), currentLPT + 1);
2196
2197 /* show the config of this LPT */
2198 BOOL fEnabled;
2199 lpt->COMGETTER(Enabled)(&fEnabled);
2200 if (!fEnabled)
2201 {
2202 if (details == VMINFO_MACHINEREADABLE)
2203 RTPrintf("%s=\"off\"\n", szNm);
2204 else
2205 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
2206 }
2207 else
2208 {
2209 ULONG ulIRQ, ulIOBase;
2210 Bstr path;
2211 lpt->COMGETTER(IRQ)(&ulIRQ);
2212 lpt->COMGETTER(IOBase)(&ulIOBase);
2213 lpt->COMGETTER(Path)(path.asOutParam());
2214
2215 if (details == VMINFO_MACHINEREADABLE)
2216 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
2217 else
2218 RTPrintf(Info::tr("%-28s I/O base: %#06x, IRQ: %d"), szNm, ulIOBase, ulIRQ);
2219 if (details == VMINFO_MACHINEREADABLE)
2220 RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1, path.raw());
2221 else
2222 RTPrintf(Info::tr(", attached to device '%ls'\n"), path.raw());
2223 }
2224 }
2225 }
2226
2227 ComPtr<IAudioSettings> audioSettings;
2228 ComPtr<IAudioAdapter> audioAdapter;
2229 hrc = machine->COMGETTER(AudioSettings)(audioSettings.asOutParam());
2230 if (SUCCEEDED(hrc))
2231 hrc = audioSettings->COMGETTER(Adapter)(audioAdapter.asOutParam());
2232 if (SUCCEEDED(hrc))
2233 {
2234 const char *pszDrv = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2235 const char *pszCtrl = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2236 const char *pszCodec = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2237 BOOL fEnabled;
2238 hrc = audioAdapter->COMGETTER(Enabled)(&fEnabled);
2239 if (SUCCEEDED(hrc) && fEnabled)
2240 {
2241 AudioDriverType_T enmDrvType;
2242 hrc = audioAdapter->COMGETTER(AudioDriver)(&enmDrvType);
2243 if (SUCCEEDED(hrc))
2244 {
2245 switch (enmDrvType)
2246 {
2247 case AudioDriverType_Default:
2248 if (details == VMINFO_MACHINEREADABLE)
2249 pszDrv = "default";
2250 else
2251 pszDrv = Info::tr("Default");
2252 break;
2253 case AudioDriverType_Null:
2254 if (details == VMINFO_MACHINEREADABLE)
2255 pszDrv = "null";
2256 else
2257 pszDrv = Info::tr("Null");
2258 break;
2259 case AudioDriverType_OSS:
2260 if (details == VMINFO_MACHINEREADABLE)
2261 pszDrv = "oss";
2262 else
2263 pszDrv = "OSS";
2264 break;
2265 case AudioDriverType_ALSA:
2266 if (details == VMINFO_MACHINEREADABLE)
2267 pszDrv = "alsa";
2268 else
2269 pszDrv = "ALSA";
2270 break;
2271 case AudioDriverType_Pulse:
2272 if (details == VMINFO_MACHINEREADABLE)
2273 pszDrv = "pulse";
2274 else
2275 pszDrv = "PulseAudio";
2276 break;
2277 case AudioDriverType_WinMM:
2278 /* Deprecated; not (ever) supported; leave this in for backwards compatibility. See @bugref{10845} */
2279 if (details == VMINFO_MACHINEREADABLE)
2280 pszDrv = "winmm";
2281 else
2282 pszDrv = "WINMM";
2283 break;
2284 case AudioDriverType_DirectSound:
2285 if (details == VMINFO_MACHINEREADABLE)
2286 pszDrv = "dsound";
2287 else
2288 pszDrv = "DirectSound";
2289 break;
2290 case AudioDriverType_WAS:
2291 if (details == VMINFO_MACHINEREADABLE)
2292 pszDrv = "was";
2293 else
2294 pszDrv = "Windows Audio Session (WAS)";
2295 break;
2296 case AudioDriverType_CoreAudio:
2297 if (details == VMINFO_MACHINEREADABLE)
2298 pszDrv = "coreaudio";
2299 else
2300 pszDrv = "CoreAudio";
2301 break;
2302 case AudioDriverType_SolAudio:
2303 if (details == VMINFO_MACHINEREADABLE)
2304 pszDrv = "solaudio";
2305 else
2306 pszDrv = "SolAudio";
2307 break;
2308 default:
2309 if (details == VMINFO_MACHINEREADABLE)
2310 pszDrv = "unknown";
2311 break;
2312 }
2313 }
2314
2315 AudioControllerType_T enmCtrlType;
2316 hrc = audioAdapter->COMGETTER(AudioController)(&enmCtrlType);
2317 if (SUCCEEDED(hrc))
2318 {
2319 switch (enmCtrlType)
2320 {
2321 case AudioControllerType_AC97:
2322 if (details == VMINFO_MACHINEREADABLE)
2323 pszCtrl = "ac97";
2324 else
2325 pszCtrl = "AC97";
2326 break;
2327 case AudioControllerType_SB16:
2328 if (details == VMINFO_MACHINEREADABLE)
2329 pszCtrl = "sb16";
2330 else
2331 pszCtrl = "SB16";
2332 break;
2333 case AudioControllerType_HDA:
2334 if (details == VMINFO_MACHINEREADABLE)
2335 pszCtrl = "hda";
2336 else
2337 pszCtrl = "HDA";
2338 break;
2339 default:
2340 break;
2341 }
2342 }
2343
2344 AudioCodecType_T enmCodecType;
2345 hrc = audioAdapter->COMGETTER(AudioCodec)(&enmCodecType);
2346 if (SUCCEEDED(hrc))
2347 {
2348 switch (enmCodecType)
2349 {
2350 case AudioCodecType_SB16:
2351 pszCodec = "SB16";
2352 break;
2353 case AudioCodecType_STAC9700:
2354 pszCodec = "STAC9700";
2355 break;
2356 case AudioCodecType_AD1980:
2357 pszCodec = "AD1980";
2358 break;
2359 case AudioCodecType_STAC9221:
2360 pszCodec = "STAC9221";
2361 break;
2362 case AudioCodecType_Null: break; /* Shut up MSC. */
2363 default: break;
2364 }
2365 }
2366 }
2367 else
2368 fEnabled = FALSE;
2369
2370 if (details == VMINFO_MACHINEREADABLE)
2371 RTPrintf("audio=\"%s\"\n", fEnabled ? pszDrv : "none");
2372 else
2373 {
2374 RTPrintf("%-28s %s", Info::tr("Audio:"), fEnabled ? Info::tr("enabled") : Info::tr("disabled"));
2375 if (fEnabled)
2376 RTPrintf(Info::tr(" (Driver: %s, Controller: %s, Codec: %s)"), pszDrv, pszCtrl, pszCodec);
2377 RTPrintf("\n");
2378 }
2379 SHOW_BOOLEAN_PROP(audioAdapter, EnabledOut, "audio_out", Info::tr("Audio playback:"));
2380 SHOW_BOOLEAN_PROP(audioAdapter, EnabledIn, "audio_in", Info::tr("Audio capture:"));
2381
2382 /** @todo Add printing run-time host audio device selection(s) here. */
2383 }
2384
2385 /* Shared clipboard */
2386 {
2387 const char *psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2388 ClipboardMode_T enmMode;
2389 hrc = machine->COMGETTER(ClipboardMode)(&enmMode);
2390 if (SUCCEEDED(hrc))
2391 {
2392 switch (enmMode)
2393 {
2394 case ClipboardMode_Disabled:
2395 psz = "disabled";
2396 break;
2397 case ClipboardMode_HostToGuest:
2398 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest");
2399 break;
2400 case ClipboardMode_GuestToHost:
2401 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost");
2402 break;
2403 case ClipboardMode_Bidirectional:
2404 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional");
2405 break;
2406 default:
2407 break;
2408 }
2409 }
2410 SHOW_UTF8_STRING("clipboard", Info::tr("Clipboard Mode:"), psz);
2411#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
2412 SHOW_BOOLEAN_PROP(machine, ClipboardFileTransfersEnabled, "clipboard_file_transfers", Info::tr("Clipboard file transfers:"));
2413#endif
2414 }
2415
2416 /* Drag and drop */
2417 {
2418 const char *psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2419 DnDMode_T enmMode;
2420 hrc = machine->COMGETTER(DnDMode)(&enmMode);
2421 if (SUCCEEDED(hrc))
2422 {
2423 switch (enmMode)
2424 {
2425 case DnDMode_Disabled:
2426 psz = "disabled";
2427 break;
2428 case DnDMode_HostToGuest:
2429 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest");
2430 break;
2431 case DnDMode_GuestToHost:
2432 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost");
2433 break;
2434 case DnDMode_Bidirectional:
2435 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional");
2436 break;
2437 default:
2438 break;
2439 }
2440 }
2441 SHOW_UTF8_STRING("draganddrop", Info::tr("Drag and drop Mode:"), psz);
2442 }
2443
2444 {
2445 SessionState_T sessState;
2446 hrc = machine->COMGETTER(SessionState)(&sessState);
2447 if (SUCCEEDED(hrc) && sessState != SessionState_Unlocked)
2448 {
2449 Bstr sessName;
2450 hrc = machine->COMGETTER(SessionName)(sessName.asOutParam());
2451 if (SUCCEEDED(hrc) && !sessName.isEmpty())
2452 SHOW_BSTR_STRING("SessionName", Info::tr("Session name:"), sessName);
2453 }
2454 }
2455
2456 if (pConsole)
2457 {
2458 do
2459 {
2460 ComPtr<IDisplay> display;
2461 hrc = pConsole->COMGETTER(Display)(display.asOutParam());
2462 if (hrc == E_ACCESSDENIED || display.isNull())
2463 break; /* VM not powered up */
2464 if (FAILED(hrc))
2465 {
2466 com::GlueHandleComError(pConsole, "COMGETTER(Display)(display.asOutParam())", hrc, __FILE__, __LINE__);
2467 return hrc;
2468 }
2469 ULONG xRes, yRes, bpp;
2470 LONG xOrigin, yOrigin;
2471 GuestMonitorStatus_T monitorStatus;
2472 hrc = display->GetScreenResolution(0, &xRes, &yRes, &bpp, &xOrigin, &yOrigin, &monitorStatus);
2473 if (hrc == E_ACCESSDENIED)
2474 break; /* VM not powered up */
2475 if (FAILED(hrc))
2476 {
2477 com::ErrorInfo info(display, COM_IIDOF(IDisplay));
2478 GluePrintErrorInfo(info);
2479 return hrc;
2480 }
2481 if (details == VMINFO_MACHINEREADABLE)
2482 RTPrintf("VideoMode=\"%d,%d,%d\"@%d,%d %d\n", xRes, yRes, bpp, xOrigin, yOrigin, monitorStatus);
2483 else
2484 {
2485 const char *pszMonitorStatus = Info::tr("unknown status");
2486 switch (monitorStatus)
2487 {
2488 case GuestMonitorStatus_Blank: pszMonitorStatus = Info::tr("blank"); break;
2489 case GuestMonitorStatus_Enabled: pszMonitorStatus = Info::tr("enabled"); break;
2490 case GuestMonitorStatus_Disabled: pszMonitorStatus = Info::tr("disabled"); break;
2491 default: break;
2492 }
2493 RTPrintf("%-28s %dx%dx%d at %d,%d %s\n", Info::tr("Video mode:"), xRes, yRes, bpp, xOrigin, yOrigin, pszMonitorStatus);
2494 }
2495 }
2496 while (0);
2497 }
2498
2499 /*
2500 * Remote Desktop
2501 */
2502 ComPtr<IVRDEServer> vrdeServer;
2503 hrc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam());
2504 if (SUCCEEDED(hrc) && vrdeServer)
2505 {
2506 BOOL fEnabled = false;
2507 vrdeServer->COMGETTER(Enabled)(&fEnabled);
2508 if (fEnabled)
2509 {
2510 LONG currentPort = -1;
2511 Bstr ports;
2512 vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam());
2513 Bstr address;
2514 vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam());
2515 BOOL fMultiCon;
2516 vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
2517 BOOL fReuseCon;
2518 vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon);
2519 Bstr videoChannel;
2520 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam());
2521 BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0)
2522 || (videoChannel == "1");
2523 Bstr videoChannelQuality;
2524 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam());
2525 AuthType_T authType = (AuthType_T)0;
2526 const char *strAuthType;
2527 vrdeServer->COMGETTER(AuthType)(&authType);
2528 switch (authType)
2529 {
2530 case AuthType_Null:
2531 if (details == VMINFO_MACHINEREADABLE)
2532 strAuthType = "null";
2533 else
2534 strAuthType = Info::tr("null");
2535 break;
2536 case AuthType_External:
2537 if (details == VMINFO_MACHINEREADABLE)
2538 strAuthType = "external";
2539 else
2540 strAuthType = Info::tr("external");
2541 break;
2542 case AuthType_Guest:
2543 if (details == VMINFO_MACHINEREADABLE)
2544 strAuthType = "guest";
2545 else
2546 strAuthType = Info::tr("guest");
2547 break;
2548 default:
2549 if (details == VMINFO_MACHINEREADABLE)
2550 strAuthType = "unknown";
2551 else
2552 strAuthType = Info::tr("unknown");
2553 break;
2554 }
2555 if (pConsole)
2556 {
2557 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2558 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), hrc);
2559 if (!vrdeServerInfo.isNull())
2560 {
2561 hrc = vrdeServerInfo->COMGETTER(Port)(&currentPort);
2562 if (hrc == E_ACCESSDENIED)
2563 {
2564 currentPort = -1; /* VM not powered up */
2565 }
2566 else if (FAILED(hrc))
2567 {
2568 com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo));
2569 GluePrintErrorInfo(info);
2570 return hrc;
2571 }
2572 }
2573 }
2574 if (details == VMINFO_MACHINEREADABLE)
2575 {
2576 RTPrintf("vrde=\"on\"\n");
2577 RTPrintf("vrdeport=%d\n", currentPort);
2578 RTPrintf("vrdeports=\"%ls\"\n", ports.raw());
2579 RTPrintf("vrdeaddress=\"%ls\"\n", address.raw());
2580 RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType);
2581 RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off");
2582 RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off");
2583 RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off");
2584 if (fVideoChannel)
2585 RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw());
2586 }
2587 else
2588 {
2589 if (address.isEmpty())
2590 address = "0.0.0.0";
2591 RTPrintf(Info::tr("%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n"),
2592 "VRDE:", address.raw(), ports.raw(), fMultiCon ? Info::tr("on") : Info::tr("off"),
2593 fReuseCon ? Info::tr("on") : Info::tr("off"), strAuthType);
2594 if (pConsole && currentPort != -1 && currentPort != 0)
2595 RTPrintf("%-28s %d\n", Info::tr("VRDE port:"), currentPort);
2596 if (fVideoChannel)
2597 RTPrintf(Info::tr("%-28s enabled (Quality %ls)\n"), Info::tr("Video redirection:"), videoChannelQuality.raw());
2598 else
2599 RTPrintf(Info::tr("%-28s disabled\n"), Info::tr("Video redirection:"));
2600 }
2601 com::SafeArray<BSTR> aProperties;
2602 if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties))))
2603 {
2604 unsigned i;
2605 for (i = 0; i < aProperties.size(); ++i)
2606 {
2607 Bstr value;
2608 vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam());
2609 if (details == VMINFO_MACHINEREADABLE)
2610 {
2611 if (value.isEmpty())
2612 RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]);
2613 else
2614 RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw());
2615 }
2616 else
2617 {
2618 if (value.isEmpty())
2619 RTPrintf(Info::tr("%-28s: %-10lS = <not set>\n"), Info::tr("VRDE property"), aProperties[i]);
2620 else
2621 RTPrintf("%-28s: %-10lS = \"%ls\"\n", Info::tr("VRDE property"), aProperties[i], value.raw());
2622 }
2623 }
2624 }
2625 }
2626 else
2627 {
2628 if (details == VMINFO_MACHINEREADABLE)
2629 RTPrintf("vrde=\"off\"\n");
2630 else
2631 RTPrintf(Info::tr("%-28s disabled\n"), "VRDE:");
2632 }
2633 }
2634
2635 /*
2636 * USB.
2637 */
2638 SafeIfaceArray<IUSBController> USBCtlColl;
2639 hrc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl));
2640 if (SUCCEEDED(hrc))
2641 {
2642 bool fOhciEnabled = false;
2643 bool fEhciEnabled = false;
2644 bool fXhciEnabled = false;
2645
2646 for (unsigned i = 0; i < USBCtlColl.size(); i++)
2647 {
2648 USBControllerType_T enmType;
2649
2650 hrc = USBCtlColl[i]->COMGETTER(Type)(&enmType);
2651 if (SUCCEEDED(hrc))
2652 {
2653 switch (enmType)
2654 {
2655 case USBControllerType_OHCI:
2656 fOhciEnabled = true;
2657 break;
2658 case USBControllerType_EHCI:
2659 fEhciEnabled = true;
2660 break;
2661 case USBControllerType_XHCI:
2662 fXhciEnabled = true;
2663 break;
2664 default:
2665 break;
2666 }
2667 }
2668 }
2669
2670 SHOW_BOOL_VALUE("usb", "OHCI USB:", fOhciEnabled);
2671 SHOW_BOOL_VALUE("ehci", "EHCI USB:", fEhciEnabled);
2672 SHOW_BOOL_VALUE("xhci", "xHCI USB:", fXhciEnabled);
2673 }
2674
2675 ComPtr<IUSBDeviceFilters> USBFlts;
2676 hrc = machine->COMGETTER(USBDeviceFilters)(USBFlts.asOutParam());
2677 if (SUCCEEDED(hrc))
2678 {
2679 SafeIfaceArray <IUSBDeviceFilter> Coll;
2680 hrc = USBFlts->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll));
2681 if (SUCCEEDED(hrc))
2682 {
2683 if (Coll.size() > 0)
2684 {
2685 if (details != VMINFO_MACHINEREADABLE)
2686 RTPrintf(Info::tr("USB Device Filters:\n"));
2687 for (size_t index = 0; index < Coll.size(); ++index)
2688 {
2689 ComPtr<IUSBDeviceFilter> DevPtr = Coll[index];
2690
2691 if (details != VMINFO_MACHINEREADABLE)
2692 SHOW_UTF8_STRING("index", Info::tr("Index:"), FmtNm(szNm, "%zu", index));
2693 SHOW_BOOLEAN_PROP_EX(DevPtr, Active, FmtNm(szNm, "USBFilterActive%zu", index + 1), Info::tr(" Active:"), Info::tr("yes"), Info::tr("no"));
2694 SHOW_STRING_PROP(DevPtr, Name, FmtNm(szNm, "USBFilterName%zu", index + 1), Info::tr(" Name:"));
2695 SHOW_STRING_PROP(DevPtr, VendorId, FmtNm(szNm, "USBFilterVendorId%zu", index + 1), Info::tr(" VendorId:"));
2696 SHOW_STRING_PROP(DevPtr, ProductId, FmtNm(szNm, "USBFilterProductId%zu", index + 1), Info::tr(" ProductId:"));
2697 SHOW_STRING_PROP(DevPtr, Revision, FmtNm(szNm, "USBFilterRevision%zu", index + 1), Info::tr(" Revision:"));
2698 SHOW_STRING_PROP(DevPtr, Manufacturer, FmtNm(szNm, "USBFilterManufacturer%zu", index + 1), Info::tr(" Manufacturer:"));
2699 SHOW_STRING_PROP(DevPtr, Product, FmtNm(szNm, "USBFilterProduct%zu", index + 1), Info::tr(" Product:"));
2700 SHOW_STRING_PROP(DevPtr, Remote, FmtNm(szNm, "USBFilterRemote%zu", index + 1), Info::tr(" Remote:"));
2701 SHOW_STRING_PROP(DevPtr, SerialNumber, FmtNm(szNm, "USBFilterSerialNumber%zu", index + 1), Info::tr(" Serial Number:"));
2702 if (details != VMINFO_MACHINEREADABLE)
2703 {
2704 ULONG fMaskedIfs;
2705 CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), hrc);
2706 if (fMaskedIfs)
2707 RTPrintf("%-28s %#010x\n", Info::tr("Masked Interfaces:"), fMaskedIfs);
2708 }
2709 }
2710 }
2711 else if (details != VMINFO_MACHINEREADABLE)
2712 RTPrintf("%-28s %s\n", Info::tr("USB Device Filters:"), Info::tr("<none>"));
2713 }
2714
2715 if (pConsole)
2716 {
2717 {
2718 SafeIfaceArray<IHostUSBDevice> coll;
2719 CHECK_ERROR_RET(pConsole, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), hrc);
2720 hrc = showUsbDevices(coll, "USBRemote", Info::tr("Available remote USB devices:"), details);
2721 if (FAILED(hrc))
2722 return hrc;
2723 }
2724
2725 {
2726 SafeIfaceArray<IUSBDevice> coll;
2727 CHECK_ERROR_RET(pConsole, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), hrc);
2728 showUsbDevices(coll, "USBAttach", Info::tr("Currently attached USB devices:"), details);
2729 if (FAILED(hrc))
2730 return hrc;
2731 }
2732 }
2733 } /* USB */
2734
2735#ifdef VBOX_WITH_PCI_PASSTHROUGH
2736 /* Host PCI passthrough devices */
2737 {
2738 SafeIfaceArray <IPCIDeviceAttachment> assignments;
2739 hrc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
2740 if (SUCCEEDED(hrc))
2741 {
2742 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2743 {
2744 RTPrintf(Info::tr("\nAttached physical PCI devices:\n\n"));
2745 }
2746
2747 for (size_t index = 0; index < assignments.size(); ++index)
2748 {
2749 ComPtr<IPCIDeviceAttachment> Assignment = assignments[index];
2750 char szHostPCIAddress[32], szGuestPCIAddress[32];
2751 LONG iHostPCIAddress = -1, iGuestPCIAddress = -1;
2752 Bstr DevName;
2753
2754 Assignment->COMGETTER(Name)(DevName.asOutParam());
2755 Assignment->COMGETTER(HostAddress)(&iHostPCIAddress);
2756 Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress);
2757 PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress));
2758 PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress));
2759
2760 if (details == VMINFO_MACHINEREADABLE)
2761 RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress);
2762 else
2763 RTPrintf(Info::tr(" Host device %ls at %s attached as %s\n"), DevName.raw(), szHostPCIAddress, szGuestPCIAddress);
2764 }
2765
2766 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2767 {
2768 RTPrintf("\n");
2769 }
2770 }
2771 }
2772 /* Host PCI passthrough devices */
2773#endif
2774
2775 /*
2776 * Bandwidth groups
2777 */
2778 if (details != VMINFO_MACHINEREADABLE)
2779 RTPrintf("%-28s ", Info::tr("Bandwidth groups:"));
2780 {
2781 ComPtr<IBandwidthControl> bwCtrl;
2782 CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), hrc);
2783 showBandwidthGroups(bwCtrl, details);
2784 }
2785
2786 /*
2787 * Shared folders
2788 */
2789 if (details != VMINFO_MACHINEREADABLE)
2790 RTPrintf("%-28s ", Info::tr("Shared folders:"));
2791 uint32_t numSharedFolders = 0;
2792 /* globally shared folders first */
2793 {
2794 com::SafeIfaceArray <ISharedFolder> folders;
2795 CHECK_ERROR_RET(pVirtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc);
2796 for (size_t i = 0; i < folders.size(); ++i)
2797 {
2798 ComPtr<ISharedFolder> sf = folders[i];
2799 showSharedFolder(sf, details, Info::tr("global mapping"), "GlobalMapping", i + 1, numSharedFolders == 0);
2800 ++numSharedFolders;
2801 }
2802 }
2803 /* now VM mappings */
2804 {
2805 com::SafeIfaceArray <ISharedFolder> folders;
2806 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc);
2807 for (size_t i = 0; i < folders.size(); ++i)
2808 {
2809 ComPtr<ISharedFolder> sf = folders[i];
2810 showSharedFolder(sf, details, Info::tr("machine mapping"), "MachineMapping", i + 1, numSharedFolders == 0);
2811 ++numSharedFolders;
2812 }
2813 }
2814 /* transient mappings */
2815 if (pConsole)
2816 {
2817 com::SafeIfaceArray <ISharedFolder> folders;
2818 CHECK_ERROR_RET(pConsole, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc);
2819 for (size_t i = 0; i < folders.size(); ++i)
2820 {
2821 ComPtr<ISharedFolder> sf = folders[i];
2822 showSharedFolder(sf, details, Info::tr("transient mapping"), "TransientMapping", i + 1, numSharedFolders == 0);
2823 ++numSharedFolders;
2824 }
2825 }
2826 if (details != VMINFO_MACHINEREADABLE)
2827 {
2828 if (!numSharedFolders)
2829 RTPrintf(Info::tr("<none>\n"));
2830 else
2831 RTPrintf("\n");
2832 }
2833
2834 if (pConsole)
2835 {
2836 /*
2837 * Live VRDE info.
2838 */
2839 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2840 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), hrc);
2841 BOOL fActive = FALSE;
2842 ULONG cNumberOfClients = 0;
2843 LONG64 BeginTime = 0;
2844 LONG64 EndTime = 0;
2845 LONG64 BytesSent = 0;
2846 LONG64 BytesSentTotal = 0;
2847 LONG64 BytesReceived = 0;
2848 LONG64 BytesReceivedTotal = 0;
2849 Bstr User;
2850 Bstr Domain;
2851 Bstr ClientName;
2852 Bstr ClientIP;
2853 ULONG ClientVersion = 0;
2854 ULONG EncryptionStyle = 0;
2855
2856 if (!vrdeServerInfo.isNull())
2857 {
2858 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&fActive), hrc);
2859 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&cNumberOfClients), hrc);
2860 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), hrc);
2861 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), hrc);
2862 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), hrc);
2863 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), hrc);
2864 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), hrc);
2865 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), hrc);
2866 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), hrc);
2867 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), hrc);
2868 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), hrc);
2869 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), hrc);
2870 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), hrc);
2871 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), hrc);
2872 }
2873
2874 SHOW_BOOL_VALUE_EX("VRDEActiveConnection", Info::tr("VRDE Connection:"), fActive, Info::tr("active"), Info::tr("not active"));
2875 SHOW_ULONG_VALUE("VRDEClients=", Info::tr("Clients so far:"), cNumberOfClients, "");
2876
2877 if (cNumberOfClients > 0)
2878 {
2879 char szTimeValue[128];
2880 makeTimeStr(szTimeValue, sizeof(szTimeValue), BeginTime);
2881 if (fActive)
2882 SHOW_UTF8_STRING("VRDEStartTime", Info::tr("Start time:"), szTimeValue);
2883 else
2884 {
2885 SHOW_UTF8_STRING("VRDELastStartTime", Info::tr("Last started:"), szTimeValue);
2886 makeTimeStr(szTimeValue, sizeof(szTimeValue), EndTime);
2887 SHOW_UTF8_STRING("VRDELastEndTime", Info::tr("Last ended:"), szTimeValue);
2888 }
2889
2890 int64_t ThroughputSend = 0;
2891 int64_t ThroughputReceive = 0;
2892 if (EndTime != BeginTime)
2893 {
2894 ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime);
2895 ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime);
2896 }
2897 SHOW_LONG64_VALUE("VRDEBytesSent", Info::tr("Sent:"), BytesSent, Info::tr("Bytes"));
2898 SHOW_LONG64_VALUE("VRDEThroughputSend", Info::tr("Average speed:"), ThroughputSend, Info::tr("B/s"));
2899 SHOW_LONG64_VALUE("VRDEBytesSentTotal", Info::tr("Sent total:"), BytesSentTotal, Info::tr("Bytes"));
2900
2901 SHOW_LONG64_VALUE("VRDEBytesReceived", Info::tr("Received:"), BytesReceived, Info::tr("Bytes"));
2902 SHOW_LONG64_VALUE("VRDEThroughputReceive", Info::tr("Speed:"), ThroughputReceive, Info::tr("B/s"));
2903 SHOW_LONG64_VALUE("VRDEBytesReceivedTotal", Info::tr("Received total:"), BytesReceivedTotal, Info::tr("Bytes"));
2904
2905 if (fActive)
2906 {
2907 SHOW_BSTR_STRING("VRDEUserName", Info::tr("User name:"), User);
2908 SHOW_BSTR_STRING("VRDEDomain", Info::tr("Domain:"), Domain);
2909 SHOW_BSTR_STRING("VRDEClientName", Info::tr("Client name:"), ClientName);
2910 SHOW_BSTR_STRING("VRDEClientIP", Info::tr("Client IP:"), ClientIP);
2911 SHOW_ULONG_VALUE("VRDEClientVersion", Info::tr("Client version:"), ClientVersion, "");
2912 SHOW_UTF8_STRING("VRDEEncryption", Info::tr("Encryption:"), EncryptionStyle == 0 ? "RDP4" : "RDP5 (X.509)");
2913 }
2914 }
2915 }
2916
2917#ifdef VBOX_WITH_RECORDING
2918 {
2919 ComPtr<IRecordingSettings> recordingSettings;
2920 CHECK_ERROR_RET(machine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam()), hrc);
2921
2922 BOOL fStarted = FALSE;
2923 ComPtr<IProgress> progress;
2924 hrc = recordingSettings->COMGETTER(Progress)(progress.asOutParam());
2925 if (SUCCEEDED(hrc))
2926 {
2927 hrc = progress->COMGETTER(Completed)(&fStarted);
2928 if (SUCCEEDED(hrc))
2929 fStarted = !fStarted;
2930 }
2931 SHOW_BOOL_VALUE_EX("recording_started", Info::tr("Recording status:"), fStarted, Info::tr("started"), Info::tr("stopped"));
2932
2933 BOOL fEnabled;
2934 CHECK_ERROR_RET(recordingSettings, COMGETTER(Enabled)(&fEnabled), hrc);
2935 SHOW_BOOL_VALUE_EX("recording_enabled", Info::tr("Recording enabled:"), fEnabled, Info::tr("yes"), Info::tr("no"));
2936
2937 SafeIfaceArray <IRecordingScreenSettings> saScreenSettings;
2938 CHECK_ERROR_RET(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saScreenSettings)), hrc);
2939
2940 SHOW_ULONG_VALUE("recording_screens", Info::tr("Recording screens:"), saScreenSettings.size(), "");
2941
2942 for (size_t i = 0; i < saScreenSettings.size(); ++i)
2943 {
2944 ComPtr<IRecordingScreenSettings> screenSettings = saScreenSettings[i];
2945
2946 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "rec_screen%zu" : Info::tr("Screen %u:"), i);
2947 RTPrintf(Info::tr(" %s\n"), szNm);
2948
2949 CHECK_ERROR_RET(screenSettings, COMGETTER(Enabled)(&fEnabled), hrc);
2950 ULONG idScreen;
2951 CHECK_ERROR_RET(screenSettings, COMGETTER(Id)(&idScreen), hrc);
2952 com::SafeArray<RecordingFeature_T> vecFeatures;
2953 CHECK_ERROR_RET(screenSettings, COMGETTER(Features)(ComSafeArrayAsOutParam(vecFeatures)), hrc);
2954 ULONG Width;
2955 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoWidth)(&Width), hrc);
2956 ULONG Height;
2957 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoHeight)(&Height), hrc);
2958 ULONG Rate;
2959 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoRate)(&Rate), hrc);
2960 ULONG Fps;
2961 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoFPS)(&Fps), hrc);
2962 RecordingDestination_T enmDst;
2963 CHECK_ERROR_RET(screenSettings, COMGETTER(Destination)(&enmDst), hrc);
2964 Bstr bstrFile;
2965 CHECK_ERROR_RET(screenSettings, COMGETTER(Filename)(bstrFile.asOutParam()), hrc);
2966 Bstr bstrOptions;
2967 CHECK_ERROR_RET(screenSettings, COMGETTER(Options)(bstrOptions.asOutParam()), hrc);
2968
2969 BOOL fRecordVideo = FALSE;
2970# ifdef VBOX_WITH_AUDIO_RECORDING
2971 BOOL fRecordAudio = FALSE;
2972# endif
2973 for (size_t f = 0; f < vecFeatures.size(); ++f)
2974 {
2975 if (vecFeatures[f] == RecordingFeature_Video)
2976 fRecordVideo = TRUE;
2977# ifdef VBOX_WITH_AUDIO_RECORDING
2978 else if (vecFeatures[f] == RecordingFeature_Audio)
2979 fRecordAudio = TRUE;
2980# endif
2981 }
2982
2983 SHOW_BOOL_VALUE_EX("rec_screen_enabled", Info::tr(" Enabled:"), fEnabled,
2984 Info::tr("yes"), Info::tr("no"));
2985 SHOW_ULONG_VALUE ("rec_screen_id", Info::tr(" ID:"), idScreen, "");
2986 SHOW_BOOL_VALUE_EX("rec_screen_video_enabled", Info::tr(" Record video:"), fRecordVideo,
2987 Info::tr("yes"), Info::tr("no"));
2988# ifdef VBOX_WITH_AUDIO_RECORDING
2989 SHOW_BOOL_VALUE_EX("rec_screen_audio_enabled", Info::tr(" Record audio:"), fRecordAudio,
2990 Info::tr("yes"), Info::tr("no"));
2991# endif
2992 SHOW_UTF8_STRING("rec_screen_dest", Info::tr(" Destination:"),
2993 enmDst == RecordingDestination_File
2994 ? Info::tr("File") : Info::tr("Unknown"));
2995 /** @todo Implement other destinations. */
2996 if (enmDst == RecordingDestination_File)
2997 SHOW_BSTR_STRING("rec_screen_dest_filename", Info::tr(" File:"), bstrFile);
2998
2999 SHOW_BSTR_STRING ("rec_screen_opts", Info::tr(" Options:"), bstrOptions);
3000
3001 /* Video properties. */
3002 RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height);
3003 SHOW_UTF8_STRING ("rec_screen_video_res_xy", Info::tr(" Video dimensions:"), szValue);
3004 SHOW_ULONG_VALUE ("rec_screen_video_rate_kbps", Info::tr(" Video rate:"), Rate, Info::tr("kbps"));
3005 SHOW_ULONG_VALUE ("rec_screen_video_fps", Info::tr(" Video FPS:"), Fps, Info::tr("fps"));
3006
3007 /** @todo Add more audio capturing profile / information here. */
3008 }
3009 }
3010#endif /* VBOX_WITH_RECORDING */
3011
3012 if ( details == VMINFO_STANDARD
3013 || details == VMINFO_FULL
3014 || details == VMINFO_MACHINEREADABLE)
3015 {
3016 Bstr description;
3017 machine->COMGETTER(Description)(description.asOutParam());
3018 if (!description.isEmpty())
3019 {
3020 if (details == VMINFO_MACHINEREADABLE)
3021 outputMachineReadableString("description", &description);
3022 else
3023 RTPrintf(Info::tr("Description:\n%ls\n"), description.raw());
3024 }
3025 }
3026
3027 /* VMMDev testing config (extra data) */
3028 if (details != VMINFO_MACHINEREADABLE)
3029 {
3030 Bstr bstr;
3031 CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled").raw(),
3032 bstr.asOutParam()), hrcCheck);
3033 int const fEnabled = parseCfgmBool(&bstr);
3034
3035 CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO").raw(),
3036 bstr.asOutParam()), hrcCheck);
3037 int const fMmio = parseCfgmBool(&bstr);
3038 if (fEnabled || fMmio)
3039 {
3040 RTPrintf("%-28s %s, %s %s\n",
3041 Info::tr("VMMDev Testing"),
3042 fEnabled > 0 ? Info::tr("enabled") : fEnabled == 0 ? Info::tr("disabled") : Info::tr("misconfigured"),
3043 "MMIO:",
3044 fMmio > 0 ? Info::tr("enabled") : fMmio == 0 ? Info::tr("disabled") : Info::tr("misconfigured"));
3045 for (uint32_t i = 0; i < 10; i++)
3046 {
3047 BstrFmt bstrName("VBoxInternal/Devices/VMMDev/0/Config/TestingCfgDword%u", i);
3048 CHECK_ERROR2I_RET(machine, GetExtraData(bstrName.raw(), bstr.asOutParam()), hrcCheck);
3049 if (bstr.isNotEmpty())
3050 RTPrintf("%-28s %ls\n", FmtNm(szNm, "VMMDev Testing Cfg Dword%u:", i), bstr.raw());
3051 }
3052 }
3053 }
3054
3055 /*
3056 * Snapshots.
3057 */
3058 ComPtr<ISnapshot> snapshot;
3059 hrc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam());
3060 if (SUCCEEDED(hrc) && snapshot)
3061 {
3062 ComPtr<ISnapshot> currentSnapshot;
3063 hrc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam());
3064 if (SUCCEEDED(hrc))
3065 {
3066 if (details != VMINFO_MACHINEREADABLE)
3067 RTPrintf(Info::tr("* Snapshots:\n"));
3068 showSnapshots(snapshot, currentSnapshot, details);
3069 }
3070 }
3071
3072 /*
3073 * Guest stuff (mainly interesting when running).
3074 */
3075 if (details != VMINFO_MACHINEREADABLE)
3076 RTPrintf(Info::tr("* Guest:\n"));
3077
3078 SHOW_ULONG_PROP(machine, MemoryBalloonSize, "GuestMemoryBalloon",
3079 Info::tr("Configured memory balloon:"), Info::tr("MB"));
3080
3081 if (pConsole)
3082 {
3083 ComPtr<IGuest> guest;
3084 hrc = pConsole->COMGETTER(Guest)(guest.asOutParam());
3085 if (SUCCEEDED(hrc) && !guest.isNull())
3086 {
3087 SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", Info::tr("OS type:"));
3088
3089 AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */
3090 hrc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel);
3091 if (SUCCEEDED(hrc))
3092 SHOW_ULONG_VALUE("GuestAdditionsRunLevel", Info::tr("Additions run level:"), (ULONG)guestRunLevel, "");
3093
3094 Bstr guestString;
3095 hrc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam());
3096 if ( SUCCEEDED(hrc)
3097 && !guestString.isEmpty())
3098 {
3099 ULONG uRevision;
3100 hrc = guest->COMGETTER(AdditionsRevision)(&uRevision);
3101 if (FAILED(hrc))
3102 uRevision = 0;
3103 RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision);
3104 SHOW_UTF8_STRING("GuestAdditionsVersion", Info::tr("Additions version:"), szValue);
3105 }
3106
3107 /* Print information about known Guest Additions facilities: */
3108 SafeIfaceArray <IAdditionsFacility> collFac;
3109 CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), hrc);
3110 if (collFac.size() > 0)
3111 {
3112 if (details != VMINFO_MACHINEREADABLE)
3113 RTPrintf("%s\n", Info::tr("Guest Facilities:"));
3114 LONG64 lLastUpdatedMS;
3115 char szLastUpdated[32];
3116 AdditionsFacilityStatus_T curStatus;
3117 for (size_t index = 0; index < collFac.size(); ++index)
3118 {
3119 ComPtr<IAdditionsFacility> fac = collFac[index];
3120 if (fac)
3121 {
3122 CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), hrc);
3123 if (!guestString.isEmpty())
3124 {
3125 CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), hrc);
3126 CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), hrc);
3127 if (details == VMINFO_MACHINEREADABLE)
3128 RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n",
3129 guestString.raw(), curStatus, lLastUpdatedMS);
3130 else
3131 {
3132 makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
3133 RTPrintf(Info::tr("Facility \"%ls\": %s (last update: %s)\n"),
3134 guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated);
3135 }
3136 }
3137 else
3138 AssertMsgFailed(("Facility with undefined name retrieved!\n"));
3139 }
3140 else
3141 AssertMsgFailed(("Invalid facility returned!\n"));
3142 }
3143 }
3144 else if (details != VMINFO_MACHINEREADABLE)
3145 RTPrintf("%-28s %s\n", Info::tr("Guest Facilities:"), Info::tr("<none>"));
3146 }
3147 }
3148
3149 if (details != VMINFO_MACHINEREADABLE)
3150 RTPrintf("\n");
3151 return S_OK;
3152}
3153
3154#if defined(_MSC_VER)
3155# pragma optimize("", on)
3156# pragma warning(pop)
3157#endif
3158
3159static const RTGETOPTDEF g_aShowVMInfoOptions[] =
3160{
3161 { "--details", 'D', RTGETOPT_REQ_NOTHING },
3162 { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated
3163 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
3164 { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated
3165 { "--log", 'l', RTGETOPT_REQ_UINT32 },
3166 { "--password-id", 'i', RTGETOPT_REQ_STRING },
3167 { "-password-id", 'i', RTGETOPT_REQ_STRING },
3168 { "--password", 'w', RTGETOPT_REQ_STRING },
3169 { "-password", 'w', RTGETOPT_REQ_STRING },
3170};
3171
3172RTEXITCODE handleShowVMInfo(HandlerArg *a)
3173{
3174 HRESULT hrc;
3175 const char *VMNameOrUuid = NULL;
3176 bool fLog = false;
3177 uint32_t uLogIdx = 0;
3178 bool fDetails = false;
3179 bool fMachinereadable = false;
3180 Bstr bstrPasswordId;
3181 const char *pszPassword = NULL;
3182
3183 int c;
3184 RTGETOPTUNION ValueUnion;
3185 RTGETOPTSTATE GetState;
3186 // start at 0 because main() has hacked both the argc and argv given to us
3187 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions),
3188 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
3189 while ((c = RTGetOpt(&GetState, &ValueUnion)))
3190 {
3191 switch (c)
3192 {
3193 case 'D': // --details
3194 fDetails = true;
3195 break;
3196
3197 case 'M': // --machinereadable
3198 fMachinereadable = true;
3199 break;
3200
3201 case 'l': // --log
3202 fLog = true;
3203 uLogIdx = ValueUnion.u32;
3204 break;
3205
3206 case 'i': // --password-id
3207 bstrPasswordId = ValueUnion.psz;
3208 break;
3209
3210 case 'w': // --password
3211 pszPassword = ValueUnion.psz;
3212 break;
3213
3214 case VINF_GETOPT_NOT_OPTION:
3215 if (!VMNameOrUuid)
3216 VMNameOrUuid = ValueUnion.psz;
3217 else
3218 return errorSyntax(Info::tr("Invalid parameter '%s'"), ValueUnion.psz);
3219 break;
3220
3221 default:
3222 return errorGetOpt(c, &ValueUnion);
3223 }
3224 }
3225
3226 /* check for required options */
3227 if (!VMNameOrUuid)
3228 return errorSyntax(Info::tr("VM name or UUID required"));
3229
3230 /* try to find the given machine */
3231 ComPtr<IMachine> machine;
3232 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(),
3233 machine.asOutParam()));
3234 if (FAILED(hrc))
3235 return RTEXITCODE_FAILURE;
3236
3237 /* Printing the log is exclusive. */
3238 if (fLog && (fMachinereadable || fDetails))
3239 return errorSyntax(Info::tr("Option --log is exclusive"));
3240
3241 /* add VM password if required */
3242 if (pszPassword && bstrPasswordId.isNotEmpty())
3243 {
3244 Utf8Str strPassword;
3245 if (!RTStrCmp(pszPassword, "-"))
3246 {
3247 /* Get password from console. */
3248 RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:");
3249 if (rcExit == RTEXITCODE_FAILURE)
3250 return rcExit;
3251 }
3252 else
3253 {
3254 RTEXITCODE rcExit = readPasswordFile(pszPassword, &strPassword);
3255 if (rcExit == RTEXITCODE_FAILURE)
3256 {
3257 RTMsgError("Failed to read new password from file");
3258 return rcExit;
3259 }
3260 }
3261 CHECK_ERROR(machine, AddEncryptionPassword(bstrPasswordId.raw(), Bstr(strPassword).raw()));
3262 }
3263
3264 if (fLog)
3265 {
3266 ULONG64 uOffset = 0;
3267 SafeArray<BYTE> aLogData;
3268 size_t cbLogData;
3269 while (true)
3270 {
3271 /* Reset the array */
3272 aLogData.setNull();
3273 /* Fetch a chunk of the log file */
3274 CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, (LONG64)uOffset, _1M,
3275 ComSafeArrayAsOutParam(aLogData)));
3276 cbLogData = aLogData.size();
3277 if (cbLogData == 0)
3278 break;
3279 /* aLogData has a platform dependent line ending, standardize on
3280 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
3281 * Windows. Otherwise we end up with CR/CR/LF on Windows. */
3282 size_t cbLogDataPrint = cbLogData;
3283 for (BYTE *s = aLogData.raw(), *d = s;
3284 s - aLogData.raw() < (ssize_t)cbLogData;
3285 s++, d++)
3286 {
3287 if (*s == '\r')
3288 {
3289 /* skip over CR, adjust destination */
3290 d--;
3291 cbLogDataPrint--;
3292 }
3293 else if (s != d)
3294 *d = *s;
3295 }
3296 RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint);
3297 uOffset += cbLogData;
3298 }
3299 }
3300 else
3301 {
3302 /* 2nd option can be -details or -argdump */
3303 VMINFO_DETAILS details = VMINFO_NONE;
3304 if (fMachinereadable)
3305 details = VMINFO_MACHINEREADABLE;
3306 else if (fDetails)
3307 details = VMINFO_FULL;
3308 else
3309 details = VMINFO_STANDARD;
3310
3311 /* open an existing session for the VM */
3312 CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared));
3313 if (SUCCEEDED(hrc))
3314 {
3315 /* get the session machine */
3316 CHECK_ERROR(a->session, COMGETTER(Machine)(machine.asOutParam()));
3317 if (SUCCEEDED(hrc))
3318 hrc = showVMInfo(a->virtualBox, machine, a->session, details);
3319
3320 CHECK_ERROR(a->session, UnlockMachine());
3321 }
3322 }
3323
3324 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
3325}
3326
3327/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette