VirtualBox

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

Last change on this file since 107745 was 107745, checked in by vboxsync, 5 weeks ago

src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp: Fixed warnings found by Parfait (unused assignment) [build fix]. jiraref:VBP-1424

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 140.7 KB
Line 
1/* $Id: VBoxManageInfo.cpp 107745 2025-01-14 10:11:28Z 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.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/com/com.h>
33#include <VBox/com/string.h>
34#include <VBox/com/Guid.h>
35#include <VBox/com/array.h>
36#include <VBox/com/ErrorInfo.h>
37#include <VBox/com/errorprint.h>
38
39#include <VBox/com/VirtualBox.h>
40
41#ifdef VBOX_WITH_PCI_PASSTHROUGH
42#include <VBox/pci.h>
43#endif
44
45#include <VBox/log.h>
46#include <VBox/version.h>
47#include <iprt/stream.h>
48#include <iprt/time.h>
49#include <iprt/string.h>
50#include <iprt/getopt.h>
51#include <iprt/ctype.h>
52
53#include "VBoxManage.h"
54#include "VBoxManageUtils.h"
55
56using namespace com;
57
58DECLARE_TRANSLATION_CONTEXT(Info);
59
60
61/*********************************************************************************************************************************
62* Defined Constants And Macros *
63*********************************************************************************************************************************/
64#define SHOW_UTF8_STRING(a_pszMachine, a_pszHuman, a_szValue) \
65 do \
66 { \
67 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
68 if (details == VMINFO_MACHINEREADABLE) \
69 outputMachineReadableString(a_pszMachine, a_szValue); \
70 else \
71 RTPrintf("%-28s %s\n", a_pszHuman, a_szValue); \
72 } while (0)
73
74#define SHOW_BSTR_STRING(a_pszMachine, a_pszHuman, a_bstrValue) \
75 do \
76 { \
77 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
78 if (details == VMINFO_MACHINEREADABLE) \
79 outputMachineReadableString(a_pszMachine, &a_bstrValue); \
80 else \
81 RTPrintf("%-28s %ls\n", a_pszHuman, a_bstrValue.raw()); \
82 } while (0)
83
84#define SHOW_BOOL_VALUE_EX(a_pszMachine, a_pszHuman, a_fValue, a_szTrue, a_szFalse) \
85 do \
86 { \
87 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
88 if (details == VMINFO_MACHINEREADABLE) \
89 outputMachineReadableString(a_pszMachine, a_fValue ? "on" : "off"); \
90 else \
91 RTPrintf("%-28s %s\n", a_pszHuman, a_fValue ? a_szTrue: a_szFalse); \
92 } while (0)
93
94#define SHOW_BOOL_VALUE(a_pszMachine, a_pszHuman, a_fValue) \
95 SHOW_BOOL_VALUE_EX(a_pszMachine, a_pszHuman, a_fValue, Info::tr("enabled"), Info::tr("disabled"))
96
97#define SHOW_ULONG_VALUE(a_pszMachine, a_pszHuman, a_uValue, a_pszUnit) \
98 do \
99 { \
100 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
101 if (details == VMINFO_MACHINEREADABLE) \
102 RTPrintf("%s=%u\n", a_pszMachine, a_uValue); \
103 else \
104 RTPrintf("%-28s %u%s\n", a_pszHuman, a_uValue, a_pszUnit); \
105 } while (0)
106
107#define SHOW_LONG64_VALUE(a_pszMachine, a_pszHuman, a_llValue, a_pszUnit) \
108 do \
109 { \
110 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
111 if (details == VMINFO_MACHINEREADABLE) \
112 RTPrintf("%s=%lld\n", a_pszMachine, a_llValue); \
113 else \
114 RTPrintf("%-28s %lld%s\n", a_pszHuman, a_llValue, a_pszUnit); \
115 } while (0)
116
117#define SHOW_BOOLEAN_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \
118 SHOW_BOOLEAN_PROP_EX(a_pObj, a_Prop, a_pszMachine, a_pszHuman, Info::tr("enabled"), Info::tr("disabled"))
119
120#define SHOW_BOOLEAN_PROP_EX(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_szTrue, a_szFalse) \
121 do \
122 { \
123 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
124 BOOL f; \
125 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&f), hrcCheck); \
126 if (details == VMINFO_MACHINEREADABLE) \
127 outputMachineReadableString(a_pszMachine, f ? "on" : "off"); \
128 else \
129 RTPrintf("%-28s %s\n", a_pszHuman, f ? a_szTrue : a_szFalse); \
130 } while (0)
131
132#define SHOW_BOOLEAN_METHOD(a_pObj, a_Invocation, a_pszMachine, a_pszHuman) \
133 do \
134 { \
135 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
136 BOOL f; \
137 CHECK_ERROR2I_RET(a_pObj, a_Invocation, hrcCheck); \
138 if (details == VMINFO_MACHINEREADABLE) \
139 outputMachineReadableString(a_pszMachine, f ? "on" : "off"); \
140 else \
141 RTPrintf("%-28s %s\n", a_pszHuman, f ? Info::tr("enabled") : Info::tr("disabled")); \
142 } while (0)
143
144#define SHOW_STRING_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \
145 do \
146 { \
147 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
148 Bstr bstr; \
149 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \
150 if (details == VMINFO_MACHINEREADABLE) \
151 outputMachineReadableString(a_pszMachine, &bstr); \
152 else \
153 RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \
154 } while (0)
155
156#define SHOW_STRING_PROP_NOT_EMPTY(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \
157 do \
158 { \
159 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
160 Bstr bstr; \
161 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \
162 if (bstr.isNotEmpty()) \
163 { \
164 if (details == VMINFO_MACHINEREADABLE) \
165 outputMachineReadableString(a_pszMachine, &bstr); \
166 else \
167 RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \
168 } \
169 } while (0)
170
171 /** @def SHOW_STRING_PROP_MAJ
172 * For not breaking the output in a dot release we don't show default values. */
173#define SHOW_STRING_PROP_MAJ(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnless, a_uMajorVer) \
174 do \
175 { \
176 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
177 Bstr bstr; \
178 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \
179 if ((a_uMajorVer) <= VBOX_VERSION_MAJOR || !bstr.equals(a_pszUnless)) \
180 { \
181 if (details == VMINFO_MACHINEREADABLE)\
182 outputMachineReadableString(a_pszMachine, &bstr); \
183 else \
184 RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \
185 } \
186 } while (0)
187
188#define SHOW_STRINGARRAY_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \
189 do \
190 { \
191 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
192 SafeArray<BSTR> array; \
193 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(ComSafeArrayAsOutParam(array)), hrcCheck); \
194 Utf8Str str; \
195 for (size_t i = 0; i < array.size(); i++) \
196 { \
197 if (i != 0) \
198 str.append(","); \
199 str.append(Utf8Str(array[i]).c_str()); \
200 } \
201 Bstr bstr(str); \
202 if (details == VMINFO_MACHINEREADABLE) \
203 outputMachineReadableString(a_pszMachine, &bstr); \
204 else \
205 RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \
206 } while (0)
207
208#define SHOW_UUID_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \
209 SHOW_STRING_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman)
210
211#define SHOW_USHORT_PROP_EX2(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnit, a_szFmtMachine, a_szFmtHuman) \
212 do \
213 { \
214 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
215 USHORT u16 = 0; \
216 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&u16), hrcCheck); \
217 if (details == VMINFO_MACHINEREADABLE) \
218 RTPrintf("%s=" a_szFmtMachine "\n", a_pszMachine, u16); \
219 else \
220 RTPrintf("%-28s " a_szFmtHuman "%s\n", a_pszHuman, u16, u16, a_pszUnit); \
221 } while (0)
222
223#define SHOW_ULONG_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnit) \
224 do \
225 { \
226 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
227 ULONG u32 = 0; \
228 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&u32), hrcCheck); \
229 if (details == VMINFO_MACHINEREADABLE) \
230 RTPrintf("%s=%u\n", a_pszMachine, u32); \
231 else \
232 RTPrintf("%-28s %u%s\n", a_pszHuman, u32, a_pszUnit); \
233 } while (0)
234
235#define SHOW_LONG64_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnit) \
236 do \
237 { \
238 Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \
239 LONG64 i64 = 0; \
240 CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&i64), hrcCheck); \
241 if (details == VMINFO_MACHINEREADABLE) \
242 RTPrintf("%s=%lld\n", a_pszMachine, i64); \
243 else \
244 RTPrintf("%-28s %'lld%s\n", a_pszHuman, i64, a_pszUnit); \
245 } while (0)
246
247
248// funcs
249///////////////////////////////////////////////////////////////////////////////
250
251/**
252 * Helper for formatting an indexed name or some such thing.
253 */
254static const char *FmtNm(char psz[80], const char *pszFormat, ...)
255{
256 va_list va;
257 va_start(va, pszFormat);
258 RTStrPrintfV(psz, 80, pszFormat, va);
259 va_end(va);
260 return psz;
261}
262
263HRESULT showSnapshots(ComPtr<ISnapshot> &rootSnapshot,
264 ComPtr<ISnapshot> &currentSnapshot,
265 VMINFO_DETAILS details,
266 const Utf8Str &prefix /* = ""*/,
267 int level /*= 0*/)
268{
269 /* start with the root */
270 Bstr name;
271 Bstr uuid;
272 Bstr description;
273 CHECK_ERROR2I_RET(rootSnapshot, COMGETTER(Name)(name.asOutParam()), hrcCheck);
274 CHECK_ERROR2I_RET(rootSnapshot, COMGETTER(Id)(uuid.asOutParam()), hrcCheck);
275 CHECK_ERROR2I_RET(rootSnapshot, COMGETTER(Description)(description.asOutParam()), hrcCheck);
276 bool fCurrent = (rootSnapshot == currentSnapshot);
277 if (details == VMINFO_MACHINEREADABLE)
278 {
279 /* print with hierarchical numbering */
280 RTPrintf("SnapshotName%s=\"%ls\"\n", prefix.c_str(), name.raw());
281 RTPrintf("SnapshotUUID%s=\"%s\"\n", prefix.c_str(), Utf8Str(uuid).c_str());
282 if (!description.isEmpty())
283 RTPrintf("SnapshotDescription%s=\"%ls\"\n", prefix.c_str(), description.raw());
284 if (fCurrent)
285 {
286 RTPrintf("CurrentSnapshotName=\"%ls\"\n", name.raw());
287 RTPrintf("CurrentSnapshotUUID=\"%s\"\n", Utf8Str(uuid).c_str());
288 RTPrintf("CurrentSnapshotNode=\"SnapshotName%s\"\n", prefix.c_str());
289 }
290 }
291 else
292 {
293 /* print with indentation */
294 RTPrintf(Info::tr(" %sName: %ls (UUID: %s)%s\n"),
295 prefix.c_str(),
296 name.raw(),
297 Utf8Str(uuid).c_str(),
298 (fCurrent) ? " *" : "");
299 if (!description.isEmpty() && RTUtf16Chr(description.raw(), '\n') == NULL)
300 RTPrintf(Info::tr(" %sDescription: %ls\n"), prefix.c_str(), description.raw());
301 else if (!description.isEmpty())
302 RTPrintf(Info::tr(" %sDescription:\n%ls\n"), prefix.c_str(), description.raw());
303 }
304
305 /* get the children */
306 HRESULT hrc = S_OK;
307 SafeIfaceArray <ISnapshot> coll;
308 CHECK_ERROR2I_RET(rootSnapshot,COMGETTER(Children)(ComSafeArrayAsOutParam(coll)), hrcCheck);
309 if (!coll.isNull())
310 {
311 for (size_t index = 0; index < coll.size(); ++index)
312 {
313 ComPtr<ISnapshot> snapshot = coll[index];
314 if (snapshot)
315 {
316 Utf8Str newPrefix;
317 if (details == VMINFO_MACHINEREADABLE)
318 newPrefix.printf("%s-%d", prefix.c_str(), index + 1);
319 else
320 newPrefix.printf("%s ", prefix.c_str());
321
322 /* recursive call */
323 HRESULT hrc2 = showSnapshots(snapshot, currentSnapshot, details, newPrefix, level + 1);
324 if (FAILED(hrc2))
325 hrc = hrc2;
326 }
327 }
328 }
329 return hrc;
330}
331
332static void makeTimeStr(char *s, int cb, int64_t millies)
333{
334 RTTIME t;
335 RTTIMESPEC ts;
336
337 RTTimeSpecSetMilli(&ts, millies);
338
339 RTTimeExplode(&t, &ts);
340
341 RTStrPrintf(s, cb, "%04d/%02d/%02d %02d:%02d:%02d UTC",
342 t.i32Year, t.u8Month, t.u8MonthDay,
343 t.u8Hour, t.u8Minute, t.u8Second);
344}
345
346const char *machineStateToName(MachineState_T machineState, bool fShort)
347{
348 switch (machineState)
349 {
350 case MachineState_PoweredOff:
351 return fShort ? "poweroff" : Info::tr("powered off");
352 case MachineState_Saved:
353 return fShort ? "saved" : Info::tr("saved");
354 case MachineState_Teleported:
355 return fShort ? "teleported" : Info::tr("teleported");
356 case MachineState_Aborted:
357 return fShort ? "aborted" : Info::tr("aborted");
358 case MachineState_AbortedSaved:
359 return fShort ? "aborted-saved" : Info::tr("aborted-saved");
360 case MachineState_Running:
361 return fShort ? "running" : Info::tr("running");
362 case MachineState_Paused:
363 return fShort ? "paused" : Info::tr("paused");
364 case MachineState_Stuck:
365 return fShort ? "gurumeditation" : Info::tr("guru meditation");
366 case MachineState_Teleporting:
367 return fShort ? "teleporting" : Info::tr("teleporting");
368 case MachineState_LiveSnapshotting:
369 return fShort ? "livesnapshotting" : Info::tr("live snapshotting");
370 case MachineState_Starting:
371 return fShort ? "starting" : Info::tr("starting");
372 case MachineState_Stopping:
373 return fShort ? "stopping" : Info::tr("stopping");
374 case MachineState_Saving:
375 return fShort ? "saving" : Info::tr("saving");
376 case MachineState_Restoring:
377 return fShort ? "restoring" : Info::tr("restoring");
378 case MachineState_TeleportingPausedVM:
379 return fShort ? "teleportingpausedvm" : Info::tr("teleporting paused vm");
380 case MachineState_TeleportingIn:
381 return fShort ? "teleportingin" : Info::tr("teleporting (incoming)");
382 case MachineState_DeletingSnapshotOnline:
383 return fShort ? "deletingsnapshotlive" : Info::tr("deleting snapshot live");
384 case MachineState_DeletingSnapshotPaused:
385 return fShort ? "deletingsnapshotlivepaused" : Info::tr("deleting snapshot live paused");
386 case MachineState_OnlineSnapshotting:
387 return fShort ? "onlinesnapshotting" : Info::tr("online snapshotting");
388 case MachineState_RestoringSnapshot:
389 return fShort ? "restoringsnapshot" : Info::tr("restoring snapshot");
390 case MachineState_DeletingSnapshot:
391 return fShort ? "deletingsnapshot" : Info::tr("deleting snapshot");
392 case MachineState_SettingUp:
393 return fShort ? "settingup" : Info::tr("setting up");
394 case MachineState_Snapshotting:
395 return fShort ? "snapshotting" : Info::tr("offline snapshotting");
396 default:
397 break;
398 }
399 return Info::tr("unknown");
400}
401
402static const char *facilityStateToName(AdditionsFacilityStatus_T faStatus, bool fShort)
403{
404 switch (faStatus)
405 {
406 case AdditionsFacilityStatus_Inactive:
407 return fShort ? "inactive" : Info::tr("not active");
408 case AdditionsFacilityStatus_Paused:
409 return fShort ? "paused" : Info::tr("paused");
410 case AdditionsFacilityStatus_PreInit:
411 return fShort ? "preinit" : Info::tr("pre-initializing");
412 case AdditionsFacilityStatus_Init:
413 return fShort ? "init" : Info::tr("initializing");
414 case AdditionsFacilityStatus_Active:
415 return fShort ? "active" : Info::tr("active/running");
416 case AdditionsFacilityStatus_Terminating:
417 return fShort ? "terminating" : Info::tr("terminating");
418 case AdditionsFacilityStatus_Terminated:
419 return fShort ? "terminated" : Info::tr("terminated");
420 case AdditionsFacilityStatus_Failed:
421 return fShort ? "failed" : Info::tr("failed");
422 case AdditionsFacilityStatus_Unknown:
423 default:
424 break;
425 }
426 return Info::tr("unknown");
427}
428
429static const char *storageControllerTypeToName(StorageControllerType_T enmCtlType, bool fMachineReadable = false)
430{
431 switch (enmCtlType)
432 {
433 case StorageControllerType_LsiLogic:
434 return "LsiLogic";
435 case StorageControllerType_LsiLogicSas:
436 return "LsiLogicSas";
437 case StorageControllerType_BusLogic:
438 return "BusLogic";
439 case StorageControllerType_IntelAhci:
440 return "IntelAhci";
441 case StorageControllerType_PIIX3:
442 return "PIIX3";
443 case StorageControllerType_PIIX4:
444 return "PIIX4";
445 case StorageControllerType_ICH6:
446 return "ICH6";
447 case StorageControllerType_I82078:
448 return "I82078";
449 case StorageControllerType_USB:
450 return "USB";
451 case StorageControllerType_NVMe:
452 return "NVMe";
453 case StorageControllerType_VirtioSCSI:
454 return "VirtioSCSI";
455 default:
456 return fMachineReadable ? "unknown" : Info::tr("unknown");
457 }
458}
459
460
461DECLINLINE(bool) doesMachineReadableStringNeedEscaping(const char *psz)
462{
463 return psz == NULL
464 || *psz == '\0'
465 || strchr(psz, '"') != NULL
466 || strchr(psz, '\\') != NULL;
467}
468
469
470/**
471 * This simply outputs the string adding necessary escaping and nothing else.
472 */
473static void outputMachineReadableStringWorker(const char *psz)
474{
475 for (;;)
476 {
477 const char *pszDoubleQuote = strchr(psz, '"');
478 const char *pszSlash = strchr(psz, '\\');
479 const char *pszNext;
480 if (pszSlash)
481 pszNext = !pszDoubleQuote || (uintptr_t)pszSlash < (uintptr_t)pszDoubleQuote ? pszSlash : pszDoubleQuote;
482 else if (pszDoubleQuote)
483 pszNext = pszDoubleQuote;
484 else
485 {
486 RTStrmWrite(g_pStdOut, psz, strlen(psz));
487 break;
488 }
489 RTStrmWrite(g_pStdOut, psz, pszNext - psz);
490 char const szTmp[2] = { '\\', *pszNext };
491 RTStrmWrite(g_pStdOut, szTmp, sizeof(szTmp));
492
493 psz = pszNext + 1;
494 }
495}
496
497
498/**
499 * This takes care of escaping double quotes and slashes that the string might
500 * contain.
501 *
502 * @param pszName The variable name.
503 * @param pszValue The value.
504 * @param fQuoteName Whether to unconditionally quote the name or not.
505 * @param fNewline Whether to automatically add a newline after the value.
506 */
507void outputMachineReadableString(const char *pszName, const char *pszValue, bool fQuoteName /*=false*/, bool fNewline /*=true*/)
508{
509 if (!fQuoteName)
510 fQuoteName = strchr(pszName, '=') != NULL;
511 bool const fEscapeName = doesMachineReadableStringNeedEscaping(pszName);
512 bool const fEscapeValue = doesMachineReadableStringNeedEscaping(pszValue);
513 if (!fEscapeName && !fEscapeValue)
514 {
515 if (fNewline)
516 RTPrintf(!fQuoteName ? "%s=\"%s\"\n" : "\"%s\"=\"%s\"\n", pszName, pszValue);
517 else
518 RTPrintf(!fQuoteName ? "%s=\"%s\"" : "\"%s\"=\"%s\"", pszName, pszValue);
519 }
520 else
521 {
522 /* The name and string quotation: */
523 if (!fEscapeName)
524 RTPrintf(fQuoteName ? "\"%s\"=\"" : "%s=\"", pszName);
525 else
526 {
527 if (fQuoteName)
528 RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\""));
529 outputMachineReadableStringWorker(pszName);
530 if (fQuoteName)
531 RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\"=\""));
532 else
533 RTStrmWrite(g_pStdOut, RT_STR_TUPLE("=\""));
534 }
535
536 /* the value and the closing quotation */
537 outputMachineReadableStringWorker(pszValue);
538 if (fNewline)
539 RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\"\n"));
540 else
541 RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\""));
542 }
543}
544
545
546/**
547 * This takes care of escaping double quotes and slashes that the string might
548 * contain.
549 *
550 * @param pszName The variable name.
551 * @param pbstrValue The value.
552 * @param fQuoteName Whether to unconditionally quote the name or not.
553 * @param fNewline Whether to automatically add a newline after the value.
554 */
555void outputMachineReadableString(const char *pszName, Bstr const *pbstrValue, bool fQuoteName /*=false*/, bool fNewline /*=true*/)
556{
557 com::Utf8Str strValue(*pbstrValue);
558 outputMachineReadableString(pszName, strValue.c_str(), fQuoteName, fNewline);
559}
560
561
562/**
563 * Variant that allows formatting the name string, C string value.
564 *
565 * @param pszValue The value.
566 * @param fQuoteName Whether to unconditionally quote the name or not.
567 * @param pszNameFmt The variable name.
568 */
569void outputMachineReadableStringWithFmtName(const char *pszValue, bool fQuoteName, const char *pszNameFmt, ...)
570{
571 com::Utf8Str strName;
572 va_list va;
573 va_start(va, pszNameFmt);
574 strName.printfV(pszNameFmt, va);
575 va_end(va);
576
577 outputMachineReadableString(strName.c_str(), pszValue, fQuoteName);
578}
579
580
581/**
582 * Variant that allows formatting the name string, Bstr value.
583 *
584 * @param pbstrValue The value.
585 * @param fQuoteName Whether to unconditionally quote the name or not.
586 * @param pszNameFmt The variable name.
587 */
588void outputMachineReadableStringWithFmtName(com::Bstr const *pbstrValue, bool fQuoteName, const char *pszNameFmt, ...)
589{
590 com::Utf8Str strName;
591 va_list va;
592 va_start(va, pszNameFmt);
593 strName.printfV(pszNameFmt, va);
594 va_end(va);
595
596 outputMachineReadableString(strName.c_str(), pbstrValue, fQuoteName);
597}
598
599
600/**
601 * Machine readable outputting of a boolean value.
602 */
603void outputMachineReadableBool(const char *pszName, BOOL const *pfValue)
604{
605 RTPrintf("%s=\"%s\"\n", pszName, *pfValue ? "on" : "off");
606}
607
608
609/**
610 * Machine readable outputting of a boolean value.
611 */
612void outputMachineReadableBool(const char *pszName, bool const *pfValue)
613{
614 RTPrintf("%s=\"%s\"\n", pszName, *pfValue ? "on" : "off");
615}
616
617
618/**
619 * Machine readable outputting of a ULONG value.
620 */
621void outputMachineReadableULong(const char *pszName, ULONG *puValue)
622{
623 RTPrintf("%s=\"%u\"\n", pszName, *puValue);
624}
625
626
627/**
628 * Machine readable outputting of a LONG64 value.
629 */
630void outputMachineReadableLong64(const char *pszName, LONG64 *puValue)
631{
632 RTPrintf("%s=\"%llu\"\n", pszName, *puValue);
633}
634
635
636/**
637 * Helper for parsing extra data config.
638 * @returns true, false, or -1 if invalid.
639 */
640static int parseCfgmBool(Bstr const *pbstr)
641{
642 /* GetExtraData returns empty strings if the requested data wasn't
643 found, so fend that off first: */
644 size_t cwcLeft = pbstr->length();
645 if (!cwcLeft)
646 return false;
647 PCRTUTF16 pwch = pbstr->raw();
648
649 /* Skip type prefix: */
650 if ( cwcLeft >= 8
651 && pwch[0] == 'i'
652 && pwch[1] == 'n'
653 && pwch[2] == 't'
654 && pwch[3] == 'e'
655 && pwch[4] == 'g'
656 && pwch[5] == 'e'
657 && pwch[6] == 'r'
658 && pwch[7] == ':')
659 {
660 pwch += 8;
661 cwcLeft -= 8;
662 }
663
664 /* Hex prefix? */
665 bool fHex = false;
666 if ( cwcLeft >= 2
667 && pwch[0] == '0'
668 && (pwch[1] == 'x' || pwch[1] == 'X'))
669 {
670 pwch += 2;
671 cwcLeft -= 2;
672 fHex = true;
673 }
674
675 /* Empty string is wrong: */
676 if (cwcLeft == 0)
677 return -1;
678
679 /* Check that it's all digits and return when we find a non-zero
680 one or reaches the end: */
681 do
682 {
683 RTUTF16 const wc = *pwch++;
684 if (!RT_C_IS_DIGIT(wc) && (!fHex || !RT_C_IS_XDIGIT(wc)))
685 return -1;
686 if (wc != '0')
687 return true;
688 } while (--cwcLeft > 0);
689 return false;
690}
691
692
693/**
694 * Converts bandwidth group type to a string.
695 * @returns String representation.
696 * @param enmType Bandwidth control group type.
697 */
698static const char * bwGroupTypeToString(BandwidthGroupType_T enmType)
699{
700 switch (enmType)
701 {
702 case BandwidthGroupType_Null: return Info::tr("Null");
703 case BandwidthGroupType_Disk: return Info::tr("Disk");
704 case BandwidthGroupType_Network: return Info::tr("Network");
705#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
706 case BandwidthGroupType_32BitHack: break; /* Shut up compiler warnings. */
707#endif
708 }
709 return Info::tr("unknown");
710}
711
712HRESULT showBandwidthGroups(ComPtr<IBandwidthControl> &bwCtrl,
713 VMINFO_DETAILS details)
714{
715 SafeIfaceArray<IBandwidthGroup> bwGroups;
716 CHECK_ERROR2I_RET(bwCtrl, GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)), hrcCheck);
717
718 if (details != VMINFO_MACHINEREADABLE)
719 RTPrintf(bwGroups.size() != 0 ? "\n" : Info::tr("<none>\n"));
720 for (size_t i = 0; i < bwGroups.size(); i++)
721 {
722 Bstr strName;
723 CHECK_ERROR2I_RET(bwGroups[i], COMGETTER(Name)(strName.asOutParam()), hrcCheck);
724 BandwidthGroupType_T enmType;
725 CHECK_ERROR2I_RET(bwGroups[i], COMGETTER(Type)(&enmType), hrcCheck);
726 LONG64 cbMaxPerSec;
727 CHECK_ERROR2I_RET(bwGroups[i], COMGETTER(MaxBytesPerSec)(&cbMaxPerSec), hrcCheck);
728
729 const char *pszType = bwGroupTypeToString(enmType);
730 if (details == VMINFO_MACHINEREADABLE)
731 {
732 /* Complicated condensed format. */
733 char szName[64];
734 RTStrPrintf(szName, sizeof(szName), "BandwidthGroup%zu", i);
735 outputMachineReadableString(szName, &strName, false /*fQuoteName*/, false /*fNewline*/);
736 RTPrintf(",%s,%RI64\n", pszType, cbMaxPerSec);
737 }
738 else
739 {
740 if (cbMaxPerSec == 0)
741 {
742 RTPrintf(Info::tr("#%zu: Name: '%ls', Type: %s, Limit: none (disabled)\n"), i, strName.raw(), pszType);
743 continue;
744 }
745
746 /* translate to human readable units.*/
747 const char *pszUnit;
748 LONG64 cUnits;
749 if (!(cbMaxPerSec % _1G))
750 {
751 cUnits = cbMaxPerSec / _1G;
752 pszUnit = "GiB/s";
753 }
754 else if (!(cbMaxPerSec % _1M))
755 {
756 cUnits = cbMaxPerSec / _1M;
757 pszUnit = "MiB/s";
758 }
759 else if (!(cbMaxPerSec % _1K))
760 {
761 cUnits = cbMaxPerSec / _1K;
762 pszUnit = "KiB/s";
763 }
764 else
765 {
766 cUnits = cbMaxPerSec;
767 pszUnit = "bytes/s";
768 }
769
770 /*
771 * We want to report network rate limit in bits/s, not bytes.
772 * Only if it cannot be express it in kilobits we will fall
773 * back to reporting it in bytes.
774 */
775 if ( enmType == BandwidthGroupType_Network
776 && !(cbMaxPerSec % 125) )
777 {
778 LONG64 cNetUnits = cbMaxPerSec / 125;
779 const char *pszNetUnit = "kbps";
780 if (!(cNetUnits % 1000000))
781 {
782 cNetUnits /= 1000000;
783 pszNetUnit = "Gbps";
784 }
785 else if (!(cNetUnits % 1000))
786 {
787 cNetUnits /= 1000;
788 pszNetUnit = "Mbps";
789 }
790 RTPrintf(Info::tr("#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s (%RI64 %s)\n"),
791 i, strName.raw(), pszType, cNetUnits, pszNetUnit, cUnits, pszUnit);
792 }
793 else
794 RTPrintf(Info::tr("#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s\n"), i, strName.raw(), pszType, cUnits, pszUnit);
795 }
796 }
797
798 return VINF_SUCCESS;
799}
800
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(), i, 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(), i, 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 default:
1527 if (details == VMINFO_MACHINEREADABLE)
1528 pszCtrl = "unknown";
1529 else
1530 pszCtrl = Info::tr("Unknown");
1531 break;
1532 }
1533
1534 if (details == VMINFO_MACHINEREADABLE)
1535 RTPrintf("graphicscontroller=\"%s\"\n", pszCtrl);
1536 else
1537 RTPrintf("%-28s %s\n", Info::tr("Graphics Controller:"), pszCtrl);
1538 }
1539
1540 SHOW_ULONG_PROP(pGraphicsAdapter, MonitorCount, "monitorcount", Info::tr("Monitor count:"), "");
1541 SHOW_BOOLEAN_METHOD(pGraphicsAdapter, IsFeatureEnabled(GraphicsFeature_Acceleration3D, &f), "accelerate3d", "3D Acceleration:");
1542#ifdef VBOX_WITH_VIDEOHWACCEL
1543 SHOW_BOOLEAN_METHOD(pGraphicsAdapter, IsFeatureEnabled(GraphicsFeature_Acceleration2DVideo, &f), "accelerate2dvideo", "2D Video Acceleration:");
1544#endif
1545 SHOW_BOOLEAN_PROP( machine, TeleporterEnabled, "teleporterenabled", Info::tr("Teleporter Enabled:"));
1546 SHOW_ULONG_PROP( machine, TeleporterPort, "teleporterport", Info::tr("Teleporter Port:"), "");
1547 SHOW_STRING_PROP( machine, TeleporterAddress, "teleporteraddress", Info::tr("Teleporter Address:"));
1548 SHOW_STRING_PROP( machine, TeleporterPassword, "teleporterpassword", Info::tr("Teleporter Password:"));
1549 SHOW_BOOLEAN_PROP( machine, TracingEnabled, "tracing-enabled", Info::tr("Tracing Enabled:"));
1550 SHOW_BOOLEAN_PROP( machine, AllowTracingToAccessVM, "tracing-allow-vm-access", Info::tr("Allow Tracing to Access VM:"));
1551 SHOW_STRING_PROP( machine, TracingConfig, "tracing-config", Info::tr("Tracing Configuration:"));
1552 SHOW_BOOLEAN_PROP( machine, AutostartEnabled, "autostart-enabled", Info::tr("Autostart Enabled:"));
1553 SHOW_ULONG_PROP( machine, AutostartDelay, "autostart-delay", Info::tr("Autostart Delay:"), "");
1554 SHOW_STRING_PROP( machine, DefaultFrontend, "defaultfrontend", Info::tr("Default Frontend:"));
1555
1556 VMProcPriority_T enmVMProcPriority;
1557 CHECK_ERROR2I_RET(machine, COMGETTER(VMProcessPriority)(&enmVMProcPriority), hrcCheck);
1558 const char *pszVMProcPriority;
1559 switch (enmVMProcPriority)
1560 {
1561 case VMProcPriority_Flat:
1562 if (details == VMINFO_MACHINEREADABLE)
1563 pszVMProcPriority = "flat";
1564 else
1565 pszVMProcPriority = Info::tr("flat");
1566 break;
1567 case VMProcPriority_Low:
1568 if (details == VMINFO_MACHINEREADABLE)
1569 pszVMProcPriority = "low";
1570 else
1571 pszVMProcPriority = Info::tr("low");
1572 break;
1573 case VMProcPriority_Normal:
1574 if (details == VMINFO_MACHINEREADABLE)
1575 pszVMProcPriority = "normal";
1576 else
1577 pszVMProcPriority = Info::tr("normal");
1578 break;
1579 case VMProcPriority_High:
1580 if (details == VMINFO_MACHINEREADABLE)
1581 pszVMProcPriority = "high";
1582 else
1583 pszVMProcPriority = Info::tr("high");
1584 break;
1585 default:
1586 if (details == VMINFO_MACHINEREADABLE)
1587 pszVMProcPriority = "default";
1588 else
1589 pszVMProcPriority = Info::tr("default");
1590 break;
1591 }
1592 SHOW_UTF8_STRING("vmprocpriority", Info::tr("VM process priority:"), pszVMProcPriority);
1593
1594/** @todo Convert the remainder of the function to SHOW_XXX macros and add error
1595 * checking where missing. */
1596 /*
1597 * Storage Controllers and their attached Mediums.
1598 */
1599 com::SafeIfaceArray<IStorageController> storageCtls;
1600 CHECK_ERROR(machine, COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(storageCtls)));
1601 if (storageCtls.size() > 0)
1602 {
1603 if (details != VMINFO_MACHINEREADABLE)
1604 RTPrintf("%s\n", Info::tr("Storage Controllers:"));
1605
1606 for (size_t i = 0; i < storageCtls.size(); ++i)
1607 {
1608 ComPtr<IStorageController> storageCtl = storageCtls[i];
1609
1610 Bstr bstrName;
1611 CHECK_ERROR2I_RET(storageCtl, COMGETTER(Name)(bstrName.asOutParam()), hrcCheck);
1612 StorageControllerType_T enmCtlType = StorageControllerType_Null;
1613 CHECK_ERROR2I_RET(storageCtl, COMGETTER(ControllerType)(&enmCtlType), hrcCheck);
1614 ULONG uInstance = 0;
1615 CHECK_ERROR2I_RET(storageCtl, COMGETTER(Instance)(&uInstance), hrcCheck);
1616 ULONG cMaxPorts = 0;
1617 CHECK_ERROR2I_RET(storageCtl, COMGETTER(MaxPortCount)(&cMaxPorts), hrcCheck);
1618 ULONG cPorts = 0;
1619 CHECK_ERROR2I_RET(storageCtl, COMGETTER(PortCount)(&cPorts), hrcCheck);
1620 BOOL fBootable = FALSE;
1621 CHECK_ERROR2I_RET(storageCtl, COMGETTER(Bootable)(&fBootable), hrcCheck);
1622 if (details == VMINFO_MACHINEREADABLE)
1623 {
1624 outputMachineReadableString(FmtNm(szNm, "storagecontrollername%u", i), &bstrName);
1625 outputMachineReadableString(FmtNm(szNm, "storagecontrollertype%u", i),
1626 storageControllerTypeToName(enmCtlType, true));
1627 RTPrintf("storagecontrollerinstance%u=\"%u\"\n", i, uInstance);
1628 RTPrintf("storagecontrollermaxportcount%u=\"%u\"\n", i, cMaxPorts);
1629 RTPrintf("storagecontrollerportcount%u=\"%u\"\n", i, cPorts);
1630 RTPrintf("storagecontrollerbootable%u=\"%s\"\n", i, fBootable ? "on" : "off");
1631 }
1632 else
1633 {
1634 RTPrintf(Info::tr("#%u: '%ls', Type: %s, Instance: %u, Ports: %u (max %u), %s\n"), i, bstrName.raw(),
1635 storageControllerTypeToName(enmCtlType, false), uInstance, cPorts, cMaxPorts,
1636 fBootable ? Info::tr("Bootable") : Info::tr("Not bootable"));
1637 hrc = showMediumAttachments(machine, storageCtl, details);
1638 if (FAILED(hrc))
1639 return hrc;
1640 }
1641 }
1642 }
1643 else if (details != VMINFO_MACHINEREADABLE)
1644 RTPrintf("%-28s %s\n", Info::tr("Storage Controllers:"), Info::tr("<none>"));
1645
1646 if (details == VMINFO_MACHINEREADABLE)
1647 for (size_t j = 0; j < storageCtls.size(); ++ j)
1648 {
1649 hrc = showMediumAttachments(machine, storageCtls[j], details);
1650 if (FAILED(hrc))
1651 return hrc;
1652 }
1653
1654 /* get the maximum amount of NICS */
1655 ULONG maxNICs = getMaxNics(machine);
1656
1657 for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++)
1658 {
1659 ComPtr<INetworkAdapter> nic;
1660 hrc = machine->GetNetworkAdapter(currentNIC, nic.asOutParam());
1661 if (SUCCEEDED(hrc) && nic)
1662 {
1663 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "nic%u" : Info::tr("NIC %u:"), currentNIC + 1);
1664
1665 BOOL fEnabled;
1666 nic->COMGETTER(Enabled)(&fEnabled);
1667 if (!fEnabled)
1668 {
1669 if (details == VMINFO_MACHINEREADABLE)
1670 RTPrintf("%s=\"none\"\n", szNm);
1671 else
1672 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
1673 }
1674 else
1675 {
1676 Bstr strMACAddress;
1677 nic->COMGETTER(MACAddress)(strMACAddress.asOutParam());
1678 Utf8Str strAttachment;
1679 Utf8Str strNatSettings;
1680 Utf8Str strNatForwardings;
1681 NetworkAttachmentType_T attachment;
1682 nic->COMGETTER(AttachmentType)(&attachment);
1683 switch (attachment)
1684 {
1685 case NetworkAttachmentType_Null:
1686 if (details == VMINFO_MACHINEREADABLE)
1687 strAttachment = "null";
1688 else
1689 strAttachment = Info::tr("none");
1690 break;
1691
1692 case NetworkAttachmentType_NAT:
1693 {
1694 Bstr strNetwork;
1695 ComPtr<INATEngine> engine;
1696 nic->COMGETTER(NATEngine)(engine.asOutParam());
1697 engine->COMGETTER(Network)(strNetwork.asOutParam());
1698 com::SafeArray<BSTR> forwardings;
1699 engine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(forwardings));
1700 strNatForwardings = "";
1701 for (size_t i = 0; i < forwardings.size(); ++i)
1702 {
1703 bool fSkip = false;
1704 BSTR r = forwardings[i];
1705 Utf8Str utf = Utf8Str(r);
1706 Utf8Str strName;
1707 Utf8Str strProto;
1708 Utf8Str strHostPort;
1709 Utf8Str strHostIP;
1710 Utf8Str strGuestPort;
1711 Utf8Str strGuestIP;
1712 size_t pos, ppos;
1713 pos = ppos = 0;
1714#define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \
1715 do { \
1716 pos = str.find(",", ppos); \
1717 if (pos == Utf8Str::npos) \
1718 { \
1719 Log(( #res " extracting from %s is failed\n", str.c_str())); \
1720 fSkip = true; \
1721 } \
1722 res = str.substr(ppos, pos - ppos); \
1723 Log2((#res " %s pos:%d, ppos:%d\n", res.c_str(), pos, ppos)); \
1724 ppos = pos + 1; \
1725 } while (0)
1726 ITERATE_TO_NEXT_TERM(strName, utf, pos, ppos);
1727 if (fSkip) continue;
1728 ITERATE_TO_NEXT_TERM(strProto, utf, pos, ppos);
1729 if (fSkip) continue;
1730 ITERATE_TO_NEXT_TERM(strHostIP, utf, pos, ppos);
1731 if (fSkip) continue;
1732 ITERATE_TO_NEXT_TERM(strHostPort, utf, pos, ppos);
1733 if (fSkip) continue;
1734 ITERATE_TO_NEXT_TERM(strGuestIP, utf, pos, ppos);
1735 if (fSkip) continue;
1736 strGuestPort = utf.substr(ppos, utf.length() - ppos);
1737#undef ITERATE_TO_NEXT_TERM
1738 switch (strProto.toUInt32())
1739 {
1740 case NATProtocol_TCP:
1741 strProto = "tcp";
1742 break;
1743 case NATProtocol_UDP:
1744 strProto = "udp";
1745 break;
1746 default:
1747 strProto = "unk";
1748 break;
1749 }
1750 if (details == VMINFO_MACHINEREADABLE)
1751 /** @todo r=bird: This probably isn't good enough wrt escaping. */
1752 strNatForwardings.appendPrintf("Forwarding(%d)=\"%s,%s,%s,%s,%s,%s\"\n",
1753 i, strName.c_str(), strProto.c_str(),
1754 strHostIP.c_str(), strHostPort.c_str(),
1755 strGuestIP.c_str(), strGuestPort.c_str());
1756 else
1757 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"),
1758 currentNIC + 1, i, strName.c_str(),
1759 strProto.c_str(), strHostIP.c_str(), strHostPort.c_str(),
1760 strGuestIP.c_str(), strGuestPort.c_str());
1761 }
1762 ULONG mtu = 0;
1763 ULONG sockSnd = 0;
1764 ULONG sockRcv = 0;
1765 ULONG tcpSnd = 0;
1766 ULONG tcpRcv = 0;
1767 engine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv);
1768
1769/** @todo r=klaus dnsproxy etc needs to be dumped, too */
1770 if (details == VMINFO_MACHINEREADABLE)
1771 {
1772 RTPrintf("natnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.length() ? strNetwork.raw(): Bstr("nat").raw());
1773 strAttachment = "nat";
1774 strNatSettings.printf("mtu=\"%d\"\nsockSnd=\"%d\"\nsockRcv=\"%d\"\ntcpWndSnd=\"%d\"\ntcpWndRcv=\"%d\"\n",
1775 mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1776 }
1777 else
1778 {
1779 strAttachment = "NAT";
1780 strNatSettings.printf(Info::tr("NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d)\n"),
1781 currentNIC + 1, mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64);
1782 }
1783 break;
1784 }
1785
1786 case NetworkAttachmentType_Bridged:
1787 {
1788 Bstr strBridgeAdp;
1789 nic->COMGETTER(BridgedInterface)(strBridgeAdp.asOutParam());
1790 if (details == VMINFO_MACHINEREADABLE)
1791 {
1792 RTPrintf("bridgeadapter%d=\"%ls\"\n", currentNIC + 1, strBridgeAdp.raw());
1793 strAttachment = "bridged";
1794 }
1795 else
1796 strAttachment.printf(Info::tr("Bridged Interface '%ls'"), strBridgeAdp.raw());
1797 break;
1798 }
1799
1800 case NetworkAttachmentType_Internal:
1801 {
1802 Bstr strNetwork;
1803 nic->COMGETTER(InternalNetwork)(strNetwork.asOutParam());
1804 if (details == VMINFO_MACHINEREADABLE)
1805 {
1806 RTPrintf("intnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1807 strAttachment = "intnet";
1808 }
1809 else
1810 strAttachment.printf(Info::tr("Internal Network '%s'"), Utf8Str(strNetwork).c_str());
1811 break;
1812 }
1813
1814 case NetworkAttachmentType_HostOnly:
1815 {
1816 Bstr strHostonlyAdp;
1817 nic->COMGETTER(HostOnlyInterface)(strHostonlyAdp.asOutParam());
1818 if (details == VMINFO_MACHINEREADABLE)
1819 {
1820 RTPrintf("hostonlyadapter%d=\"%ls\"\n", currentNIC + 1, strHostonlyAdp.raw());
1821 strAttachment = "hostonly";
1822 }
1823 else
1824 strAttachment.printf(Info::tr("Host-only Interface '%ls'"), strHostonlyAdp.raw());
1825 break;
1826 }
1827
1828 case NetworkAttachmentType_Generic:
1829 {
1830 Bstr strGenericDriver;
1831 nic->COMGETTER(GenericDriver)(strGenericDriver.asOutParam());
1832 if (details == VMINFO_MACHINEREADABLE)
1833 {
1834 RTPrintf("generic%d=\"%ls\"\n", currentNIC + 1, strGenericDriver.raw());
1835 strAttachment = "Generic";
1836 }
1837 else
1838 {
1839 strAttachment.printf(Info::tr("Generic '%ls'"), strGenericDriver.raw());
1840
1841 // show the generic properties
1842 com::SafeArray<BSTR> aProperties;
1843 com::SafeArray<BSTR> aValues;
1844 hrc = nic->GetProperties(NULL,
1845 ComSafeArrayAsOutParam(aProperties),
1846 ComSafeArrayAsOutParam(aValues));
1847 if (SUCCEEDED(hrc))
1848 {
1849 strAttachment += " { ";
1850 for (unsigned i = 0; i < aProperties.size(); ++i)
1851 strAttachment.appendPrintf(!i ? "%ls='%ls'" : ", %ls='%ls'", aProperties[i], aValues[i]);
1852 strAttachment += " }";
1853 }
1854 }
1855 break;
1856 }
1857
1858 case NetworkAttachmentType_NATNetwork:
1859 {
1860 Bstr strNetwork;
1861 nic->COMGETTER(NATNetwork)(strNetwork.asOutParam());
1862 if (details == VMINFO_MACHINEREADABLE)
1863 {
1864 RTPrintf("nat-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1865 strAttachment = "natnetwork";
1866 }
1867 else
1868 strAttachment.printf(Info::tr("NAT Network '%s'"), Utf8Str(strNetwork).c_str());
1869 break;
1870 }
1871
1872#ifdef VBOX_WITH_VMNET
1873 case NetworkAttachmentType_HostOnlyNetwork:
1874 {
1875 Bstr strNetwork;
1876 nic->COMGETTER(HostOnlyNetwork)(strNetwork.asOutParam());
1877 if (details == VMINFO_MACHINEREADABLE)
1878 {
1879 RTPrintf("hostonly-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1880 strAttachment = "hostonlynetwork";
1881 }
1882 else
1883 strAttachment.printf(Info::tr("Host Only Network '%s'"), Utf8Str(strNetwork).c_str());
1884 break;
1885 }
1886#endif /* VBOX_WITH_VMNET */
1887
1888#ifdef VBOX_WITH_CLOUD_NET
1889 case NetworkAttachmentType_Cloud:
1890 {
1891 Bstr strNetwork;
1892 nic->COMGETTER(CloudNetwork)(strNetwork.asOutParam());
1893 if (details == VMINFO_MACHINEREADABLE)
1894 {
1895 RTPrintf("cloud-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw());
1896 strAttachment = "cloudnetwork";
1897 }
1898 else
1899 strAttachment.printf(Info::tr("Cloud Network '%s'"), Utf8Str(strNetwork).c_str());
1900 break;
1901 }
1902#endif /* VBOX_WITH_CLOUD_NET */
1903
1904 default:
1905 if (details == VMINFO_MACHINEREADABLE)
1906 strAttachment = "unknown";
1907 else
1908 strAttachment = Info::tr("unknown");
1909 break;
1910 }
1911
1912 /* cable connected */
1913 BOOL fConnected;
1914 nic->COMGETTER(CableConnected)(&fConnected);
1915
1916 /* promisc policy */
1917 NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy;
1918 CHECK_ERROR2I_RET(nic, COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy), hrcCheck);
1919 const char *pszPromiscuousGuestPolicy;
1920 switch (enmPromiscModePolicy)
1921 {
1922 case NetworkAdapterPromiscModePolicy_Deny: pszPromiscuousGuestPolicy = Info::tr("deny"); break;
1923 case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = Info::tr("allow-vms"); break;
1924 case NetworkAdapterPromiscModePolicy_AllowAll: pszPromiscuousGuestPolicy = Info::tr("allow-all"); break;
1925 default: AssertFailedReturn(E_INVALIDARG);
1926 }
1927
1928 /* trace stuff */
1929 BOOL fTraceEnabled;
1930 nic->COMGETTER(TraceEnabled)(&fTraceEnabled);
1931 Bstr traceFile;
1932 nic->COMGETTER(TraceFile)(traceFile.asOutParam());
1933
1934 /* NIC type */
1935 NetworkAdapterType_T NICType;
1936 nic->COMGETTER(AdapterType)(&NICType);
1937 const char *pszNICType;
1938 switch (NICType)
1939 {
1940 case NetworkAdapterType_Am79C970A: pszNICType = "Am79C970A"; break;
1941 case NetworkAdapterType_Am79C973: pszNICType = "Am79C973"; break;
1942 case NetworkAdapterType_Am79C960: pszNICType = "Am79C960"; break;
1943#ifdef VBOX_WITH_E1000
1944 case NetworkAdapterType_I82540EM: pszNICType = "82540EM"; break;
1945 case NetworkAdapterType_I82543GC: pszNICType = "82543GC"; break;
1946 case NetworkAdapterType_I82545EM: pszNICType = "82545EM"; break;
1947#endif
1948#ifdef VBOX_WITH_VIRTIO
1949 case NetworkAdapterType_Virtio: pszNICType = "virtio"; break;
1950#endif
1951 case NetworkAdapterType_NE1000: pszNICType = "NE1000"; break;
1952 case NetworkAdapterType_NE2000: pszNICType = "NE2000"; break;
1953 case NetworkAdapterType_WD8003: pszNICType = "WD8003"; break;
1954 case NetworkAdapterType_WD8013: pszNICType = "WD8013"; break;
1955 case NetworkAdapterType_ELNK2: pszNICType = "3C503"; break;
1956 case NetworkAdapterType_ELNK1: pszNICType = "3C501"; break;
1957 case NetworkAdapterType_UsbNet: pszNICType = "usbnet"; break;
1958 default:
1959 AssertFailed();
1960 if (details == VMINFO_MACHINEREADABLE)
1961 pszNICType = "unknown";
1962 else
1963 pszNICType = Info::tr("unknown");
1964 break;
1965 }
1966
1967 /* reported line speed */
1968 ULONG ulLineSpeed;
1969 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1970
1971 /* boot priority of the adapter */
1972 ULONG ulBootPriority;
1973 nic->COMGETTER(BootPriority)(&ulBootPriority);
1974
1975 /* bandwidth group */
1976 ComObjPtr<IBandwidthGroup> pBwGroup;
1977 Bstr strBwGroup;
1978 nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());
1979 if (!pBwGroup.isNull())
1980 pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam());
1981
1982 if (details == VMINFO_MACHINEREADABLE)
1983 {
1984 RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw());
1985 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1986 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str());
1987 RTPrintf("nictype%d=\"%s\"\n", currentNIC + 1, pszNICType);
1988 RTPrintf("nicspeed%d=\"%d\"\n", currentNIC + 1, ulLineSpeed);
1989 }
1990 else
1991 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"),
1992 szNm, strMACAddress.raw(), strAttachment.c_str(),
1993 fConnected ? Info::tr("on") : Info::tr("off"),
1994 fTraceEnabled ? Info::tr("on") : Info::tr("off"),
1995 traceFile.isEmpty() ? Bstr(Info::tr("none")).raw() : traceFile.raw(),
1996 pszNICType,
1997 ulLineSpeed / 1000,
1998 (int)ulBootPriority,
1999 pszPromiscuousGuestPolicy,
2000 strBwGroup.isEmpty() ? Bstr(Info::tr("none")).raw() : strBwGroup.raw());
2001 if (strNatSettings.length())
2002 RTPrintf(strNatSettings.c_str());
2003 if (strNatForwardings.length())
2004 RTPrintf(strNatForwardings.c_str());
2005 }
2006 }
2007 }
2008
2009 /* Pointing device information */
2010 PointingHIDType_T aPointingHID;
2011 const char *pszHID = Info::tr("Unknown");
2012 const char *pszMrHID = "unknown";
2013 machine->COMGETTER(PointingHIDType)(&aPointingHID);
2014 switch (aPointingHID)
2015 {
2016 case PointingHIDType_None:
2017 pszHID = Info::tr("None");
2018 pszMrHID = "none";
2019 break;
2020 case PointingHIDType_PS2Mouse:
2021 pszHID = Info::tr("PS/2 Mouse");
2022 pszMrHID = "ps2mouse";
2023 break;
2024 case PointingHIDType_USBMouse:
2025 pszHID = Info::tr("USB Mouse");
2026 pszMrHID = "usbmouse";
2027 break;
2028 case PointingHIDType_USBTablet:
2029 pszHID = Info::tr("USB Tablet");
2030 pszMrHID = "usbtablet";
2031 break;
2032 case PointingHIDType_ComboMouse:
2033 pszHID = Info::tr("USB Tablet and PS/2 Mouse");
2034 pszMrHID = "combomouse";
2035 break;
2036 case PointingHIDType_USBMultiTouch:
2037 pszHID = Info::tr("USB Multi-Touch");
2038 pszMrHID = "usbmultitouch";
2039 break;
2040 default:
2041 break;
2042 }
2043 SHOW_UTF8_STRING("hidpointing", Info::tr("Pointing Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
2044
2045 /* Keyboard device information */
2046 KeyboardHIDType_T aKeyboardHID;
2047 machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID);
2048 pszHID = Info::tr("Unknown");
2049 pszMrHID = "unknown";
2050 switch (aKeyboardHID)
2051 {
2052 case KeyboardHIDType_None:
2053 pszHID = Info::tr("None");
2054 pszMrHID = "none";
2055 break;
2056 case KeyboardHIDType_PS2Keyboard:
2057 pszHID = Info::tr("PS/2 Keyboard");
2058 pszMrHID = "ps2kbd";
2059 break;
2060 case KeyboardHIDType_USBKeyboard:
2061 pszHID = Info::tr("USB Keyboard");
2062 pszMrHID = "usbkbd";
2063 break;
2064 case KeyboardHIDType_ComboKeyboard:
2065 pszHID = Info::tr("USB and PS/2 Keyboard");
2066 pszMrHID = "combokbd";
2067 break;
2068 default:
2069 break;
2070 }
2071 SHOW_UTF8_STRING("hidkeyboard", Info::tr("Keyboard Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
2072
2073 ComPtr<ISystemProperties> sysProps;
2074 pVirtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
2075
2076 /* get the maximum amount of UARTs */
2077 ULONG maxUARTs = 0;
2078 platformProperties->COMGETTER(SerialPortCount)(&maxUARTs);
2079 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
2080 {
2081 ComPtr<ISerialPort> uart;
2082 hrc = machine->GetSerialPort(currentUART, uart.asOutParam());
2083 if (SUCCEEDED(hrc) && uart)
2084 {
2085 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "uart%u" : Info::tr("UART %u:"), currentUART + 1);
2086
2087 /* show the config of this UART */
2088 BOOL fEnabled;
2089 uart->COMGETTER(Enabled)(&fEnabled);
2090 if (!fEnabled)
2091 {
2092 if (details == VMINFO_MACHINEREADABLE)
2093 RTPrintf("%s=\"off\"\n", szNm);
2094 else
2095 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
2096 }
2097 else
2098 {
2099 ULONG ulIRQ, ulIOAddress;
2100 PortMode_T HostMode;
2101 Bstr path;
2102 BOOL fServer;
2103 UartType_T UartType;
2104 uart->COMGETTER(IRQ)(&ulIRQ);
2105 uart->COMGETTER(IOAddress)(&ulIOAddress);
2106 uart->COMGETTER(Path)(path.asOutParam());
2107 uart->COMGETTER(Server)(&fServer);
2108 uart->COMGETTER(HostMode)(&HostMode);
2109 uart->COMGETTER(UartType)(&UartType);
2110
2111 if (details == VMINFO_MACHINEREADABLE)
2112 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOAddress, ulIRQ);
2113 else
2114 RTPrintf(Info::tr("%-28s I/O address: %#06x, IRQ: %d"), szNm, ulIOAddress, ulIRQ);
2115 switch (HostMode)
2116 {
2117 default:
2118 case PortMode_Disconnected:
2119 if (details == VMINFO_MACHINEREADABLE)
2120 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
2121 else
2122 RTPrintf(Info::tr(", disconnected"));
2123 break;
2124 case PortMode_RawFile:
2125 if (details == VMINFO_MACHINEREADABLE)
2126 RTPrintf("uartmode%d=\"file,%ls\"\n", currentUART + 1,
2127 path.raw());
2128 else
2129 RTPrintf(Info::tr(", attached to raw file '%ls'\n"),
2130 path.raw());
2131 break;
2132 case PortMode_TCP:
2133 if (details == VMINFO_MACHINEREADABLE)
2134 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
2135 fServer ? "tcpserver" : "tcpclient", path.raw());
2136 else
2137 RTPrintf(Info::tr(", attached to tcp (%s) '%ls'"),
2138 fServer ? Info::tr("server") : Info::tr("client"), path.raw());
2139 break;
2140 case PortMode_HostPipe:
2141 if (details == VMINFO_MACHINEREADABLE)
2142 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
2143 fServer ? "server" : "client", path.raw());
2144 else
2145 RTPrintf(Info::tr(", attached to pipe (%s) '%ls'"),
2146 fServer ? Info::tr("server") : Info::tr("client"), path.raw());
2147 break;
2148 case PortMode_HostDevice:
2149 if (details == VMINFO_MACHINEREADABLE)
2150 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
2151 path.raw());
2152 else
2153 RTPrintf(Info::tr(", attached to device '%ls'"), path.raw());
2154 break;
2155 }
2156 switch (UartType)
2157 {
2158 default:
2159 case UartType_U16450:
2160 if (details == VMINFO_MACHINEREADABLE)
2161 RTPrintf("uarttype%d=\"16450\"\n", currentUART + 1);
2162 else
2163 RTPrintf(", 16450\n");
2164 break;
2165 case UartType_U16550A:
2166 if (details == VMINFO_MACHINEREADABLE)
2167 RTPrintf("uarttype%d=\"16550A\"\n", currentUART + 1);
2168 else
2169 RTPrintf(", 16550A\n");
2170 break;
2171 case UartType_U16750:
2172 if (details == VMINFO_MACHINEREADABLE)
2173 RTPrintf("uarttype%d=\"16750\"\n", currentUART + 1);
2174 else
2175 RTPrintf(", 16750\n");
2176 break;
2177 }
2178 }
2179 }
2180 }
2181
2182 /* get the maximum amount of LPTs */
2183 ULONG maxLPTs = 0;
2184 platformProperties->COMGETTER(ParallelPortCount)(&maxLPTs);
2185 for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++)
2186 {
2187 ComPtr<IParallelPort> lpt;
2188 hrc = machine->GetParallelPort(currentLPT, lpt.asOutParam());
2189 if (SUCCEEDED(hrc) && lpt)
2190 {
2191 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "lpt%u" : Info::tr("LPT %u:"), currentLPT + 1);
2192
2193 /* show the config of this LPT */
2194 BOOL fEnabled;
2195 lpt->COMGETTER(Enabled)(&fEnabled);
2196 if (!fEnabled)
2197 {
2198 if (details == VMINFO_MACHINEREADABLE)
2199 RTPrintf("%s=\"off\"\n", szNm);
2200 else
2201 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
2202 }
2203 else
2204 {
2205 ULONG ulIRQ, ulIOBase;
2206 Bstr path;
2207 lpt->COMGETTER(IRQ)(&ulIRQ);
2208 lpt->COMGETTER(IOBase)(&ulIOBase);
2209 lpt->COMGETTER(Path)(path.asOutParam());
2210
2211 if (details == VMINFO_MACHINEREADABLE)
2212 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
2213 else
2214 RTPrintf(Info::tr("%-28s I/O base: %#06x, IRQ: %d"), szNm, ulIOBase, ulIRQ);
2215 if (details == VMINFO_MACHINEREADABLE)
2216 RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1, path.raw());
2217 else
2218 RTPrintf(Info::tr(", attached to device '%ls'\n"), path.raw());
2219 }
2220 }
2221 }
2222
2223 ComPtr<IAudioSettings> audioSettings;
2224 ComPtr<IAudioAdapter> audioAdapter;
2225 hrc = machine->COMGETTER(AudioSettings)(audioSettings.asOutParam());
2226 if (SUCCEEDED(hrc))
2227 hrc = audioSettings->COMGETTER(Adapter)(audioAdapter.asOutParam());
2228 if (SUCCEEDED(hrc))
2229 {
2230 const char *pszDrv = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2231 const char *pszCtrl = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2232 const char *pszCodec = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2233 BOOL fEnabled;
2234 hrc = audioAdapter->COMGETTER(Enabled)(&fEnabled);
2235 if (SUCCEEDED(hrc) && fEnabled)
2236 {
2237 AudioDriverType_T enmDrvType;
2238 hrc = audioAdapter->COMGETTER(AudioDriver)(&enmDrvType);
2239 if (SUCCEEDED(hrc))
2240 {
2241 switch (enmDrvType)
2242 {
2243 case AudioDriverType_Default:
2244 if (details == VMINFO_MACHINEREADABLE)
2245 pszDrv = "default";
2246 else
2247 pszDrv = Info::tr("Default");
2248 break;
2249 case AudioDriverType_Null:
2250 if (details == VMINFO_MACHINEREADABLE)
2251 pszDrv = "null";
2252 else
2253 pszDrv = Info::tr("Null");
2254 break;
2255 case AudioDriverType_OSS:
2256 if (details == VMINFO_MACHINEREADABLE)
2257 pszDrv = "oss";
2258 else
2259 pszDrv = "OSS";
2260 break;
2261 case AudioDriverType_ALSA:
2262 if (details == VMINFO_MACHINEREADABLE)
2263 pszDrv = "alsa";
2264 else
2265 pszDrv = "ALSA";
2266 break;
2267 case AudioDriverType_Pulse:
2268 if (details == VMINFO_MACHINEREADABLE)
2269 pszDrv = "pulse";
2270 else
2271 pszDrv = "PulseAudio";
2272 break;
2273 case AudioDriverType_WinMM:
2274 if (details == VMINFO_MACHINEREADABLE)
2275 pszDrv = "winmm";
2276 else
2277 pszDrv = "WINMM";
2278 break;
2279 case AudioDriverType_DirectSound:
2280 if (details == VMINFO_MACHINEREADABLE)
2281 pszDrv = "dsound";
2282 else
2283 pszDrv = "DirectSound";
2284 break;
2285 case AudioDriverType_WAS:
2286 if (details == VMINFO_MACHINEREADABLE)
2287 pszDrv = "was";
2288 else
2289 pszDrv = "Windows Audio Session (WAS)";
2290 break;
2291 case AudioDriverType_CoreAudio:
2292 if (details == VMINFO_MACHINEREADABLE)
2293 pszDrv = "coreaudio";
2294 else
2295 pszDrv = "CoreAudio";
2296 break;
2297 case AudioDriverType_SolAudio:
2298 if (details == VMINFO_MACHINEREADABLE)
2299 pszDrv = "solaudio";
2300 else
2301 pszDrv = "SolAudio";
2302 break;
2303 default:
2304 if (details == VMINFO_MACHINEREADABLE)
2305 pszDrv = "unknown";
2306 break;
2307 }
2308 }
2309
2310 AudioControllerType_T enmCtrlType;
2311 hrc = audioAdapter->COMGETTER(AudioController)(&enmCtrlType);
2312 if (SUCCEEDED(hrc))
2313 {
2314 switch (enmCtrlType)
2315 {
2316 case AudioControllerType_AC97:
2317 if (details == VMINFO_MACHINEREADABLE)
2318 pszCtrl = "ac97";
2319 else
2320 pszCtrl = "AC97";
2321 break;
2322 case AudioControllerType_SB16:
2323 if (details == VMINFO_MACHINEREADABLE)
2324 pszCtrl = "sb16";
2325 else
2326 pszCtrl = "SB16";
2327 break;
2328 case AudioControllerType_HDA:
2329 if (details == VMINFO_MACHINEREADABLE)
2330 pszCtrl = "hda";
2331 else
2332 pszCtrl = "HDA";
2333 break;
2334 default:
2335 break;
2336 }
2337 }
2338
2339 AudioCodecType_T enmCodecType;
2340 hrc = audioAdapter->COMGETTER(AudioCodec)(&enmCodecType);
2341 if (SUCCEEDED(hrc))
2342 {
2343 switch (enmCodecType)
2344 {
2345 case AudioCodecType_SB16:
2346 pszCodec = "SB16";
2347 break;
2348 case AudioCodecType_STAC9700:
2349 pszCodec = "STAC9700";
2350 break;
2351 case AudioCodecType_AD1980:
2352 pszCodec = "AD1980";
2353 break;
2354 case AudioCodecType_STAC9221:
2355 pszCodec = "STAC9221";
2356 break;
2357 case AudioCodecType_Null: break; /* Shut up MSC. */
2358 default: break;
2359 }
2360 }
2361 }
2362 else
2363 fEnabled = FALSE;
2364
2365 if (details == VMINFO_MACHINEREADABLE)
2366 RTPrintf("audio=\"%s\"\n", fEnabled ? pszDrv : "none");
2367 else
2368 {
2369 RTPrintf("%-28s %s", Info::tr("Audio:"), fEnabled ? Info::tr("enabled") : Info::tr("disabled"));
2370 if (fEnabled)
2371 RTPrintf(Info::tr(" (Driver: %s, Controller: %s, Codec: %s)"), pszDrv, pszCtrl, pszCodec);
2372 RTPrintf("\n");
2373 }
2374 SHOW_BOOLEAN_PROP(audioAdapter, EnabledOut, "audio_out", Info::tr("Audio playback:"));
2375 SHOW_BOOLEAN_PROP(audioAdapter, EnabledIn, "audio_in", Info::tr("Audio capture:"));
2376
2377 /** @todo Add printing run-time host audio device selection(s) here. */
2378 }
2379
2380 /* Shared clipboard */
2381 {
2382 const char *psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2383 ClipboardMode_T enmMode;
2384 hrc = machine->COMGETTER(ClipboardMode)(&enmMode);
2385 if (SUCCEEDED(hrc))
2386 {
2387 switch (enmMode)
2388 {
2389 case ClipboardMode_Disabled:
2390 psz = "disabled";
2391 break;
2392 case ClipboardMode_HostToGuest:
2393 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest");
2394 break;
2395 case ClipboardMode_GuestToHost:
2396 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost");
2397 break;
2398 case ClipboardMode_Bidirectional:
2399 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional");
2400 break;
2401 default:
2402 break;
2403 }
2404 }
2405 SHOW_UTF8_STRING("clipboard", Info::tr("Clipboard Mode:"), psz);
2406#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
2407 SHOW_BOOLEAN_PROP(machine, ClipboardFileTransfersEnabled, "clipboard_file_transfers", Info::tr("Clipboard file transfers:"));
2408#endif
2409 }
2410
2411 /* Drag and drop */
2412 {
2413 const char *psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2414 DnDMode_T enmMode;
2415 hrc = machine->COMGETTER(DnDMode)(&enmMode);
2416 if (SUCCEEDED(hrc))
2417 {
2418 switch (enmMode)
2419 {
2420 case DnDMode_Disabled:
2421 psz = "disabled";
2422 break;
2423 case DnDMode_HostToGuest:
2424 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest");
2425 break;
2426 case DnDMode_GuestToHost:
2427 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost");
2428 break;
2429 case DnDMode_Bidirectional:
2430 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional");
2431 break;
2432 default:
2433 break;
2434 }
2435 }
2436 SHOW_UTF8_STRING("draganddrop", Info::tr("Drag and drop Mode:"), psz);
2437 }
2438
2439 {
2440 SessionState_T sessState;
2441 hrc = machine->COMGETTER(SessionState)(&sessState);
2442 if (SUCCEEDED(hrc) && sessState != SessionState_Unlocked)
2443 {
2444 Bstr sessName;
2445 hrc = machine->COMGETTER(SessionName)(sessName.asOutParam());
2446 if (SUCCEEDED(hrc) && !sessName.isEmpty())
2447 SHOW_BSTR_STRING("SessionName", Info::tr("Session name:"), sessName);
2448 }
2449 }
2450
2451 if (pConsole)
2452 {
2453 do
2454 {
2455 ComPtr<IDisplay> display;
2456 hrc = pConsole->COMGETTER(Display)(display.asOutParam());
2457 if (hrc == E_ACCESSDENIED || display.isNull())
2458 break; /* VM not powered up */
2459 if (FAILED(hrc))
2460 {
2461 com::GlueHandleComError(pConsole, "COMGETTER(Display)(display.asOutParam())", hrc, __FILE__, __LINE__);
2462 return hrc;
2463 }
2464 ULONG xRes, yRes, bpp;
2465 LONG xOrigin, yOrigin;
2466 GuestMonitorStatus_T monitorStatus;
2467 hrc = display->GetScreenResolution(0, &xRes, &yRes, &bpp, &xOrigin, &yOrigin, &monitorStatus);
2468 if (hrc == E_ACCESSDENIED)
2469 break; /* VM not powered up */
2470 if (FAILED(hrc))
2471 {
2472 com::ErrorInfo info(display, COM_IIDOF(IDisplay));
2473 GluePrintErrorInfo(info);
2474 return hrc;
2475 }
2476 if (details == VMINFO_MACHINEREADABLE)
2477 RTPrintf("VideoMode=\"%d,%d,%d\"@%d,%d %d\n", xRes, yRes, bpp, xOrigin, yOrigin, monitorStatus);
2478 else
2479 {
2480 const char *pszMonitorStatus = Info::tr("unknown status");
2481 switch (monitorStatus)
2482 {
2483 case GuestMonitorStatus_Blank: pszMonitorStatus = Info::tr("blank"); break;
2484 case GuestMonitorStatus_Enabled: pszMonitorStatus = Info::tr("enabled"); break;
2485 case GuestMonitorStatus_Disabled: pszMonitorStatus = Info::tr("disabled"); break;
2486 default: break;
2487 }
2488 RTPrintf("%-28s %dx%dx%d at %d,%d %s\n", Info::tr("Video mode:"), xRes, yRes, bpp, xOrigin, yOrigin, pszMonitorStatus);
2489 }
2490 }
2491 while (0);
2492 }
2493
2494 /*
2495 * Remote Desktop
2496 */
2497 ComPtr<IVRDEServer> vrdeServer;
2498 hrc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam());
2499 if (SUCCEEDED(hrc) && vrdeServer)
2500 {
2501 BOOL fEnabled = false;
2502 vrdeServer->COMGETTER(Enabled)(&fEnabled);
2503 if (fEnabled)
2504 {
2505 LONG currentPort = -1;
2506 Bstr ports;
2507 vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam());
2508 Bstr address;
2509 vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam());
2510 BOOL fMultiCon;
2511 vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
2512 BOOL fReuseCon;
2513 vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon);
2514 Bstr videoChannel;
2515 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam());
2516 BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0)
2517 || (videoChannel == "1");
2518 Bstr videoChannelQuality;
2519 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam());
2520 AuthType_T authType = (AuthType_T)0;
2521 const char *strAuthType;
2522 vrdeServer->COMGETTER(AuthType)(&authType);
2523 switch (authType)
2524 {
2525 case AuthType_Null:
2526 if (details == VMINFO_MACHINEREADABLE)
2527 strAuthType = "null";
2528 else
2529 strAuthType = Info::tr("null");
2530 break;
2531 case AuthType_External:
2532 if (details == VMINFO_MACHINEREADABLE)
2533 strAuthType = "external";
2534 else
2535 strAuthType = Info::tr("external");
2536 break;
2537 case AuthType_Guest:
2538 if (details == VMINFO_MACHINEREADABLE)
2539 strAuthType = "guest";
2540 else
2541 strAuthType = Info::tr("guest");
2542 break;
2543 default:
2544 if (details == VMINFO_MACHINEREADABLE)
2545 strAuthType = "unknown";
2546 else
2547 strAuthType = Info::tr("unknown");
2548 break;
2549 }
2550 if (pConsole)
2551 {
2552 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2553 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), hrc);
2554 if (!vrdeServerInfo.isNull())
2555 {
2556 hrc = vrdeServerInfo->COMGETTER(Port)(&currentPort);
2557 if (hrc == E_ACCESSDENIED)
2558 {
2559 currentPort = -1; /* VM not powered up */
2560 }
2561 else if (FAILED(hrc))
2562 {
2563 com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo));
2564 GluePrintErrorInfo(info);
2565 return hrc;
2566 }
2567 }
2568 }
2569 if (details == VMINFO_MACHINEREADABLE)
2570 {
2571 RTPrintf("vrde=\"on\"\n");
2572 RTPrintf("vrdeport=%d\n", currentPort);
2573 RTPrintf("vrdeports=\"%ls\"\n", ports.raw());
2574 RTPrintf("vrdeaddress=\"%ls\"\n", address.raw());
2575 RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType);
2576 RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off");
2577 RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off");
2578 RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off");
2579 if (fVideoChannel)
2580 RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw());
2581 }
2582 else
2583 {
2584 if (address.isEmpty())
2585 address = "0.0.0.0";
2586 RTPrintf(Info::tr("%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n"),
2587 "VRDE:", address.raw(), ports.raw(), fMultiCon ? Info::tr("on") : Info::tr("off"),
2588 fReuseCon ? Info::tr("on") : Info::tr("off"), strAuthType);
2589 if (pConsole && currentPort != -1 && currentPort != 0)
2590 RTPrintf("%-28s %d\n", Info::tr("VRDE port:"), currentPort);
2591 if (fVideoChannel)
2592 RTPrintf(Info::tr("%-28s enabled (Quality %ls)\n"), Info::tr("Video redirection:"), videoChannelQuality.raw());
2593 else
2594 RTPrintf(Info::tr("%-28s disabled\n"), Info::tr("Video redirection:"));
2595 }
2596 com::SafeArray<BSTR> aProperties;
2597 if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties))))
2598 {
2599 unsigned i;
2600 for (i = 0; i < aProperties.size(); ++i)
2601 {
2602 Bstr value;
2603 vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam());
2604 if (details == VMINFO_MACHINEREADABLE)
2605 {
2606 if (value.isEmpty())
2607 RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]);
2608 else
2609 RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw());
2610 }
2611 else
2612 {
2613 if (value.isEmpty())
2614 RTPrintf(Info::tr("%-28s: %-10lS = <not set>\n"), Info::tr("VRDE property"), aProperties[i]);
2615 else
2616 RTPrintf("%-28s: %-10lS = \"%ls\"\n", Info::tr("VRDE property"), aProperties[i], value.raw());
2617 }
2618 }
2619 }
2620 }
2621 else
2622 {
2623 if (details == VMINFO_MACHINEREADABLE)
2624 RTPrintf("vrde=\"off\"\n");
2625 else
2626 RTPrintf(Info::tr("%-28s disabled\n"), "VRDE:");
2627 }
2628 }
2629
2630 /*
2631 * USB.
2632 */
2633 SafeIfaceArray<IUSBController> USBCtlColl;
2634 hrc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl));
2635 if (SUCCEEDED(hrc))
2636 {
2637 bool fOhciEnabled = false;
2638 bool fEhciEnabled = false;
2639 bool fXhciEnabled = false;
2640
2641 for (unsigned i = 0; i < USBCtlColl.size(); i++)
2642 {
2643 USBControllerType_T enmType;
2644
2645 hrc = USBCtlColl[i]->COMGETTER(Type)(&enmType);
2646 if (SUCCEEDED(hrc))
2647 {
2648 switch (enmType)
2649 {
2650 case USBControllerType_OHCI:
2651 fOhciEnabled = true;
2652 break;
2653 case USBControllerType_EHCI:
2654 fEhciEnabled = true;
2655 break;
2656 case USBControllerType_XHCI:
2657 fXhciEnabled = true;
2658 break;
2659 default:
2660 break;
2661 }
2662 }
2663 }
2664
2665 SHOW_BOOL_VALUE("usb", "OHCI USB:", fOhciEnabled);
2666 SHOW_BOOL_VALUE("ehci", "EHCI USB:", fEhciEnabled);
2667 SHOW_BOOL_VALUE("xhci", "xHCI USB:", fXhciEnabled);
2668 }
2669
2670 ComPtr<IUSBDeviceFilters> USBFlts;
2671 hrc = machine->COMGETTER(USBDeviceFilters)(USBFlts.asOutParam());
2672 if (SUCCEEDED(hrc))
2673 {
2674 SafeIfaceArray <IUSBDeviceFilter> Coll;
2675 hrc = USBFlts->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll));
2676 if (SUCCEEDED(hrc))
2677 {
2678 if (Coll.size() > 0)
2679 {
2680 if (details != VMINFO_MACHINEREADABLE)
2681 RTPrintf(Info::tr("USB Device Filters:\n"));
2682 for (size_t index = 0; index < Coll.size(); ++index)
2683 {
2684 ComPtr<IUSBDeviceFilter> DevPtr = Coll[index];
2685
2686 if (details != VMINFO_MACHINEREADABLE)
2687 SHOW_UTF8_STRING("index", Info::tr("Index:"), FmtNm(szNm, "%zu", index));
2688 SHOW_BOOLEAN_PROP_EX(DevPtr, Active, FmtNm(szNm, "USBFilterActive%zu", index + 1), Info::tr(" Active:"), Info::tr("yes"), Info::tr("no"));
2689 SHOW_STRING_PROP(DevPtr, Name, FmtNm(szNm, "USBFilterName%zu", index + 1), Info::tr(" Name:"));
2690 SHOW_STRING_PROP(DevPtr, VendorId, FmtNm(szNm, "USBFilterVendorId%zu", index + 1), Info::tr(" VendorId:"));
2691 SHOW_STRING_PROP(DevPtr, ProductId, FmtNm(szNm, "USBFilterProductId%zu", index + 1), Info::tr(" ProductId:"));
2692 SHOW_STRING_PROP(DevPtr, Revision, FmtNm(szNm, "USBFilterRevision%zu", index + 1), Info::tr(" Revision:"));
2693 SHOW_STRING_PROP(DevPtr, Manufacturer, FmtNm(szNm, "USBFilterManufacturer%zu", index + 1), Info::tr(" Manufacturer:"));
2694 SHOW_STRING_PROP(DevPtr, Product, FmtNm(szNm, "USBFilterProduct%zu", index + 1), Info::tr(" Product:"));
2695 SHOW_STRING_PROP(DevPtr, Remote, FmtNm(szNm, "USBFilterRemote%zu", index + 1), Info::tr(" Remote:"));
2696 SHOW_STRING_PROP(DevPtr, SerialNumber, FmtNm(szNm, "USBFilterSerialNumber%zu", index + 1), Info::tr(" Serial Number:"));
2697 if (details != VMINFO_MACHINEREADABLE)
2698 {
2699 ULONG fMaskedIfs;
2700 CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), hrc);
2701 if (fMaskedIfs)
2702 RTPrintf("%-28s %#010x\n", Info::tr("Masked Interfaces:"), fMaskedIfs);
2703 }
2704 }
2705 }
2706 else if (details != VMINFO_MACHINEREADABLE)
2707 RTPrintf("%-28s %s\n", Info::tr("USB Device Filters:"), Info::tr("<none>"));
2708 }
2709
2710 if (pConsole)
2711 {
2712 {
2713 SafeIfaceArray<IHostUSBDevice> coll;
2714 CHECK_ERROR_RET(pConsole, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), hrc);
2715 hrc = showUsbDevices(coll, "USBRemote", Info::tr("Available remote USB devices:"), details);
2716 if (FAILED(hrc))
2717 return hrc;
2718 }
2719
2720 {
2721 SafeIfaceArray<IUSBDevice> coll;
2722 CHECK_ERROR_RET(pConsole, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), hrc);
2723 showUsbDevices(coll, "USBAttach", Info::tr("Currently attached USB devices:"), details);
2724 if (FAILED(hrc))
2725 return hrc;
2726 }
2727 }
2728 } /* USB */
2729
2730#ifdef VBOX_WITH_PCI_PASSTHROUGH
2731 /* Host PCI passthrough devices */
2732 {
2733 SafeIfaceArray <IPCIDeviceAttachment> assignments;
2734 hrc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
2735 if (SUCCEEDED(hrc))
2736 {
2737 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2738 {
2739 RTPrintf(Info::tr("\nAttached physical PCI devices:\n\n"));
2740 }
2741
2742 for (size_t index = 0; index < assignments.size(); ++index)
2743 {
2744 ComPtr<IPCIDeviceAttachment> Assignment = assignments[index];
2745 char szHostPCIAddress[32], szGuestPCIAddress[32];
2746 LONG iHostPCIAddress = -1, iGuestPCIAddress = -1;
2747 Bstr DevName;
2748
2749 Assignment->COMGETTER(Name)(DevName.asOutParam());
2750 Assignment->COMGETTER(HostAddress)(&iHostPCIAddress);
2751 Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress);
2752 PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress));
2753 PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress));
2754
2755 if (details == VMINFO_MACHINEREADABLE)
2756 RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress);
2757 else
2758 RTPrintf(Info::tr(" Host device %ls at %s attached as %s\n"), DevName.raw(), szHostPCIAddress, szGuestPCIAddress);
2759 }
2760
2761 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2762 {
2763 RTPrintf("\n");
2764 }
2765 }
2766 }
2767 /* Host PCI passthrough devices */
2768#endif
2769
2770 /*
2771 * Bandwidth groups
2772 */
2773 if (details != VMINFO_MACHINEREADABLE)
2774 RTPrintf("%-28s ", Info::tr("Bandwidth groups:"));
2775 {
2776 ComPtr<IBandwidthControl> bwCtrl;
2777 CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), hrc);
2778 showBandwidthGroups(bwCtrl, details);
2779 }
2780
2781 /*
2782 * Shared folders
2783 */
2784 if (details != VMINFO_MACHINEREADABLE)
2785 RTPrintf("%-28s ", Info::tr("Shared folders:"));
2786 uint32_t numSharedFolders = 0;
2787#if 0 // not yet implemented
2788 /* globally shared folders first */
2789 {
2790 SafeIfaceArray <ISharedFolder> sfColl;
2791 CHECK_ERROR_RET(pVirtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(sfColl)), rc);
2792 for (size_t i = 0; i < sfColl.size(); ++i)
2793 {
2794 ComPtr<ISharedFolder> sf = sfColl[i];
2795 showSharedFolder(sf, details, Info::tr("global mapping"), "GlobalMapping", i + 1, numSharedFolders == 0);
2796 ++numSharedFolders;
2797 }
2798 }
2799#endif
2800 /* now VM mappings */
2801 {
2802 com::SafeIfaceArray <ISharedFolder> folders;
2803 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc);
2804 for (size_t i = 0; i < folders.size(); ++i)
2805 {
2806 ComPtr<ISharedFolder> sf = folders[i];
2807 showSharedFolder(sf, details, Info::tr("machine mapping"), "MachineMapping", i + 1, numSharedFolders == 0);
2808 ++numSharedFolders;
2809 }
2810 }
2811 /* transient mappings */
2812 if (pConsole)
2813 {
2814 com::SafeIfaceArray <ISharedFolder> folders;
2815 CHECK_ERROR_RET(pConsole, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc);
2816 for (size_t i = 0; i < folders.size(); ++i)
2817 {
2818 ComPtr<ISharedFolder> sf = folders[i];
2819 showSharedFolder(sf, details, Info::tr("transient mapping"), "TransientMapping", i + 1, numSharedFolders == 0);
2820 ++numSharedFolders;
2821 }
2822 }
2823 if (details != VMINFO_MACHINEREADABLE)
2824 {
2825 if (!numSharedFolders)
2826 RTPrintf(Info::tr("<none>\n"));
2827 else
2828 RTPrintf("\n");
2829 }
2830
2831 if (pConsole)
2832 {
2833 /*
2834 * Live VRDE info.
2835 */
2836 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2837 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), hrc);
2838 BOOL fActive = FALSE;
2839 ULONG cNumberOfClients = 0;
2840 LONG64 BeginTime = 0;
2841 LONG64 EndTime = 0;
2842 LONG64 BytesSent = 0;
2843 LONG64 BytesSentTotal = 0;
2844 LONG64 BytesReceived = 0;
2845 LONG64 BytesReceivedTotal = 0;
2846 Bstr User;
2847 Bstr Domain;
2848 Bstr ClientName;
2849 Bstr ClientIP;
2850 ULONG ClientVersion = 0;
2851 ULONG EncryptionStyle = 0;
2852
2853 if (!vrdeServerInfo.isNull())
2854 {
2855 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&fActive), hrc);
2856 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&cNumberOfClients), hrc);
2857 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), hrc);
2858 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), hrc);
2859 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), hrc);
2860 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), hrc);
2861 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), hrc);
2862 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), hrc);
2863 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), hrc);
2864 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), hrc);
2865 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), hrc);
2866 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), hrc);
2867 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), hrc);
2868 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), hrc);
2869 }
2870
2871 SHOW_BOOL_VALUE_EX("VRDEActiveConnection", Info::tr("VRDE Connection:"), fActive, Info::tr("active"), Info::tr("not active"));
2872 SHOW_ULONG_VALUE("VRDEClients=", Info::tr("Clients so far:"), cNumberOfClients, "");
2873
2874 if (cNumberOfClients > 0)
2875 {
2876 char szTimeValue[128];
2877 makeTimeStr(szTimeValue, sizeof(szTimeValue), BeginTime);
2878 if (fActive)
2879 SHOW_UTF8_STRING("VRDEStartTime", Info::tr("Start time:"), szTimeValue);
2880 else
2881 {
2882 SHOW_UTF8_STRING("VRDELastStartTime", Info::tr("Last started:"), szTimeValue);
2883 makeTimeStr(szTimeValue, sizeof(szTimeValue), EndTime);
2884 SHOW_UTF8_STRING("VRDELastEndTime", Info::tr("Last ended:"), szTimeValue);
2885 }
2886
2887 int64_t ThroughputSend = 0;
2888 int64_t ThroughputReceive = 0;
2889 if (EndTime != BeginTime)
2890 {
2891 ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime);
2892 ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime);
2893 }
2894 SHOW_LONG64_VALUE("VRDEBytesSent", Info::tr("Sent:"), BytesSent, Info::tr("Bytes"));
2895 SHOW_LONG64_VALUE("VRDEThroughputSend", Info::tr("Average speed:"), ThroughputSend, Info::tr("B/s"));
2896 SHOW_LONG64_VALUE("VRDEBytesSentTotal", Info::tr("Sent total:"), BytesSentTotal, Info::tr("Bytes"));
2897
2898 SHOW_LONG64_VALUE("VRDEBytesReceived", Info::tr("Received:"), BytesReceived, Info::tr("Bytes"));
2899 SHOW_LONG64_VALUE("VRDEThroughputReceive", Info::tr("Speed:"), ThroughputReceive, Info::tr("B/s"));
2900 SHOW_LONG64_VALUE("VRDEBytesReceivedTotal", Info::tr("Received total:"), BytesReceivedTotal, Info::tr("Bytes"));
2901
2902 if (fActive)
2903 {
2904 SHOW_BSTR_STRING("VRDEUserName", Info::tr("User name:"), User);
2905 SHOW_BSTR_STRING("VRDEDomain", Info::tr("Domain:"), Domain);
2906 SHOW_BSTR_STRING("VRDEClientName", Info::tr("Client name:"), ClientName);
2907 SHOW_BSTR_STRING("VRDEClientIP", Info::tr("Client IP:"), ClientIP);
2908 SHOW_ULONG_VALUE("VRDEClientVersion", Info::tr("Client version:"), ClientVersion, "");
2909 SHOW_UTF8_STRING("VRDEEncryption", Info::tr("Encryption:"), EncryptionStyle == 0 ? "RDP4" : "RDP5 (X.509)");
2910 }
2911 }
2912 }
2913
2914#ifdef VBOX_WITH_RECORDING
2915 {
2916 ComPtr<IRecordingSettings> recordingSettings;
2917 CHECK_ERROR_RET(machine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam()), hrc);
2918
2919 BOOL fStarted = FALSE;
2920 ComPtr<IProgress> progress;
2921 hrc = recordingSettings->COMGETTER(Progress)(progress.asOutParam());
2922 if (SUCCEEDED(hrc))
2923 {
2924 hrc = progress->COMGETTER(Completed)(&fStarted);
2925 if (SUCCEEDED(hrc))
2926 fStarted = !fStarted;
2927 }
2928 SHOW_BOOL_VALUE_EX("recording_started", Info::tr("Recording status:"), fStarted, Info::tr("started"), Info::tr("stopped"));
2929
2930 BOOL fEnabled;
2931 CHECK_ERROR_RET(recordingSettings, COMGETTER(Enabled)(&fEnabled), hrc);
2932 SHOW_BOOL_VALUE_EX("recording_enabled", Info::tr("Recording enabled:"), fEnabled, Info::tr("yes"), Info::tr("no"));
2933
2934 SafeIfaceArray <IRecordingScreenSettings> saScreenSettings;
2935 CHECK_ERROR_RET(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saScreenSettings)), hrc);
2936
2937 SHOW_ULONG_VALUE("recording_screens", Info::tr("Recording screens:"), saScreenSettings.size(), "");
2938
2939 for (size_t i = 0; i < saScreenSettings.size(); ++i)
2940 {
2941 ComPtr<IRecordingScreenSettings> screenSettings = saScreenSettings[i];
2942
2943 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "rec_screen%zu" : Info::tr("Screen %u:"), i);
2944 RTPrintf(Info::tr(" %s\n"), szNm);
2945
2946 CHECK_ERROR_RET(screenSettings, COMGETTER(Enabled)(&fEnabled), hrc);
2947 ULONG idScreen;
2948 CHECK_ERROR_RET(screenSettings, COMGETTER(Id)(&idScreen), hrc);
2949 com::SafeArray<RecordingFeature_T> vecFeatures;
2950 CHECK_ERROR_RET(screenSettings, COMGETTER(Features)(ComSafeArrayAsOutParam(vecFeatures)), hrc);
2951 ULONG Width;
2952 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoWidth)(&Width), hrc);
2953 ULONG Height;
2954 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoHeight)(&Height), hrc);
2955 ULONG Rate;
2956 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoRate)(&Rate), hrc);
2957 ULONG Fps;
2958 CHECK_ERROR_RET(screenSettings, COMGETTER(VideoFPS)(&Fps), hrc);
2959 RecordingDestination_T enmDst;
2960 CHECK_ERROR_RET(screenSettings, COMGETTER(Destination)(&enmDst), hrc);
2961 Bstr bstrFile;
2962 CHECK_ERROR_RET(screenSettings, COMGETTER(Filename)(bstrFile.asOutParam()), hrc);
2963 Bstr bstrOptions;
2964 CHECK_ERROR_RET(screenSettings, COMGETTER(Options)(bstrOptions.asOutParam()), hrc);
2965
2966 BOOL fRecordVideo = FALSE;
2967# ifdef VBOX_WITH_AUDIO_RECORDING
2968 BOOL fRecordAudio = FALSE;
2969# endif
2970 for (size_t f = 0; f < vecFeatures.size(); ++f)
2971 {
2972 if (vecFeatures[f] == RecordingFeature_Video)
2973 fRecordVideo = TRUE;
2974# ifdef VBOX_WITH_AUDIO_RECORDING
2975 else if (vecFeatures[f] == RecordingFeature_Audio)
2976 fRecordAudio = TRUE;
2977# endif
2978 }
2979
2980 SHOW_BOOL_VALUE_EX("rec_screen_enabled", Info::tr(" Enabled:"), fEnabled,
2981 Info::tr("yes"), Info::tr("no"));
2982 SHOW_ULONG_VALUE ("rec_screen_id", Info::tr(" ID:"), idScreen, "");
2983 SHOW_BOOL_VALUE_EX("rec_screen_video_enabled", Info::tr(" Record video:"), fRecordVideo,
2984 Info::tr("yes"), Info::tr("no"));
2985# ifdef VBOX_WITH_AUDIO_RECORDING
2986 SHOW_BOOL_VALUE_EX("rec_screen_audio_enabled", Info::tr(" Record audio:"), fRecordAudio,
2987 Info::tr("yes"), Info::tr("no"));
2988# endif
2989 SHOW_UTF8_STRING("rec_screen_dest", Info::tr(" Destination:"),
2990 enmDst == RecordingDestination_File
2991 ? Info::tr("File") : Info::tr("Unknown"));
2992 /** @todo Implement other destinations. */
2993 if (enmDst == RecordingDestination_File)
2994 SHOW_BSTR_STRING("rec_screen_dest_filename", Info::tr(" File:"), bstrFile);
2995
2996 SHOW_BSTR_STRING ("rec_screen_opts", Info::tr(" Options:"), bstrOptions);
2997
2998 /* Video properties. */
2999 RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height);
3000 SHOW_UTF8_STRING ("rec_screen_video_res_xy", Info::tr(" Video dimensions:"), szValue);
3001 SHOW_ULONG_VALUE ("rec_screen_video_rate_kbps", Info::tr(" Video rate:"), Rate, Info::tr("kbps"));
3002 SHOW_ULONG_VALUE ("rec_screen_video_fps", Info::tr(" Video FPS:"), Fps, Info::tr("fps"));
3003
3004 /** @todo Add more audio capturing profile / information here. */
3005 }
3006 }
3007#endif /* VBOX_WITH_RECORDING */
3008
3009 if ( details == VMINFO_STANDARD
3010 || details == VMINFO_FULL
3011 || details == VMINFO_MACHINEREADABLE)
3012 {
3013 Bstr description;
3014 machine->COMGETTER(Description)(description.asOutParam());
3015 if (!description.isEmpty())
3016 {
3017 if (details == VMINFO_MACHINEREADABLE)
3018 outputMachineReadableString("description", &description);
3019 else
3020 RTPrintf(Info::tr("Description:\n%ls\n"), description.raw());
3021 }
3022 }
3023
3024 /* VMMDev testing config (extra data) */
3025 if (details != VMINFO_MACHINEREADABLE)
3026 {
3027 Bstr bstr;
3028 CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled").raw(),
3029 bstr.asOutParam()), hrcCheck);
3030 int const fEnabled = parseCfgmBool(&bstr);
3031
3032 CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO").raw(),
3033 bstr.asOutParam()), hrcCheck);
3034 int const fMmio = parseCfgmBool(&bstr);
3035 if (fEnabled || fMmio)
3036 {
3037 RTPrintf("%-28s %s, %s %s\n",
3038 Info::tr("VMMDev Testing"),
3039 fEnabled > 0 ? Info::tr("enabled") : fEnabled == 0 ? Info::tr("disabled") : Info::tr("misconfigured"),
3040 "MMIO:",
3041 fMmio > 0 ? Info::tr("enabled") : fMmio == 0 ? Info::tr("disabled") : Info::tr("misconfigured"));
3042 for (uint32_t i = 0; i < 10; i++)
3043 {
3044 BstrFmt bstrName("VBoxInternal/Devices/VMMDev/0/Config/TestingCfgDword%u", i);
3045 CHECK_ERROR2I_RET(machine, GetExtraData(bstrName.raw(), bstr.asOutParam()), hrcCheck);
3046 if (bstr.isNotEmpty())
3047 RTPrintf("%-28s %ls\n", FmtNm(szNm, "VMMDev Testing Cfg Dword%u:", i), bstr.raw());
3048 }
3049 }
3050 }
3051
3052 /*
3053 * Snapshots.
3054 */
3055 ComPtr<ISnapshot> snapshot;
3056 hrc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam());
3057 if (SUCCEEDED(hrc) && snapshot)
3058 {
3059 ComPtr<ISnapshot> currentSnapshot;
3060 hrc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam());
3061 if (SUCCEEDED(hrc))
3062 {
3063 if (details != VMINFO_MACHINEREADABLE)
3064 RTPrintf(Info::tr("* Snapshots:\n"));
3065 showSnapshots(snapshot, currentSnapshot, details);
3066 }
3067 }
3068
3069 /*
3070 * Guest stuff (mainly interesting when running).
3071 */
3072 if (details != VMINFO_MACHINEREADABLE)
3073 RTPrintf(Info::tr("* Guest:\n"));
3074
3075 SHOW_ULONG_PROP(machine, MemoryBalloonSize, "GuestMemoryBalloon",
3076 Info::tr("Configured memory balloon:"), Info::tr("MB"));
3077
3078 if (pConsole)
3079 {
3080 ComPtr<IGuest> guest;
3081 hrc = pConsole->COMGETTER(Guest)(guest.asOutParam());
3082 if (SUCCEEDED(hrc) && !guest.isNull())
3083 {
3084 SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", Info::tr("OS type:"));
3085
3086 AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */
3087 hrc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel);
3088 if (SUCCEEDED(hrc))
3089 SHOW_ULONG_VALUE("GuestAdditionsRunLevel", Info::tr("Additions run level:"), (ULONG)guestRunLevel, "");
3090
3091 Bstr guestString;
3092 hrc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam());
3093 if ( SUCCEEDED(hrc)
3094 && !guestString.isEmpty())
3095 {
3096 ULONG uRevision;
3097 hrc = guest->COMGETTER(AdditionsRevision)(&uRevision);
3098 if (FAILED(hrc))
3099 uRevision = 0;
3100 RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision);
3101 SHOW_UTF8_STRING("GuestAdditionsVersion", Info::tr("Additions version:"), szValue);
3102 }
3103
3104 /* Print information about known Guest Additions facilities: */
3105 SafeIfaceArray <IAdditionsFacility> collFac;
3106 CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), hrc);
3107 if (collFac.size() > 0)
3108 {
3109 if (details != VMINFO_MACHINEREADABLE)
3110 RTPrintf("%s\n", Info::tr("Guest Facilities:"));
3111 LONG64 lLastUpdatedMS;
3112 char szLastUpdated[32];
3113 AdditionsFacilityStatus_T curStatus;
3114 for (size_t index = 0; index < collFac.size(); ++index)
3115 {
3116 ComPtr<IAdditionsFacility> fac = collFac[index];
3117 if (fac)
3118 {
3119 CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), hrc);
3120 if (!guestString.isEmpty())
3121 {
3122 CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), hrc);
3123 CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), hrc);
3124 if (details == VMINFO_MACHINEREADABLE)
3125 RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n",
3126 guestString.raw(), curStatus, lLastUpdatedMS);
3127 else
3128 {
3129 makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
3130 RTPrintf(Info::tr("Facility \"%ls\": %s (last update: %s)\n"),
3131 guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated);
3132 }
3133 }
3134 else
3135 AssertMsgFailed(("Facility with undefined name retrieved!\n"));
3136 }
3137 else
3138 AssertMsgFailed(("Invalid facility returned!\n"));
3139 }
3140 }
3141 else if (details != VMINFO_MACHINEREADABLE)
3142 RTPrintf("%-28s %s\n", Info::tr("Guest Facilities:"), Info::tr("<none>"));
3143 }
3144 }
3145
3146 if (details != VMINFO_MACHINEREADABLE)
3147 RTPrintf("\n");
3148 return S_OK;
3149}
3150
3151#if defined(_MSC_VER)
3152# pragma optimize("", on)
3153# pragma warning(pop)
3154#endif
3155
3156static const RTGETOPTDEF g_aShowVMInfoOptions[] =
3157{
3158 { "--details", 'D', RTGETOPT_REQ_NOTHING },
3159 { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated
3160 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
3161 { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated
3162 { "--log", 'l', RTGETOPT_REQ_UINT32 },
3163 { "--password-id", 'i', RTGETOPT_REQ_STRING },
3164 { "-password-id", 'i', RTGETOPT_REQ_STRING },
3165 { "--password", 'w', RTGETOPT_REQ_STRING },
3166 { "-password", 'w', RTGETOPT_REQ_STRING },
3167};
3168
3169RTEXITCODE handleShowVMInfo(HandlerArg *a)
3170{
3171 HRESULT hrc;
3172 const char *VMNameOrUuid = NULL;
3173 bool fLog = false;
3174 uint32_t uLogIdx = 0;
3175 bool fDetails = false;
3176 bool fMachinereadable = false;
3177 Bstr bstrPasswordId;
3178 const char *pszPassword = NULL;
3179
3180 int c;
3181 RTGETOPTUNION ValueUnion;
3182 RTGETOPTSTATE GetState;
3183 // start at 0 because main() has hacked both the argc and argv given to us
3184 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions),
3185 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
3186 while ((c = RTGetOpt(&GetState, &ValueUnion)))
3187 {
3188 switch (c)
3189 {
3190 case 'D': // --details
3191 fDetails = true;
3192 break;
3193
3194 case 'M': // --machinereadable
3195 fMachinereadable = true;
3196 break;
3197
3198 case 'l': // --log
3199 fLog = true;
3200 uLogIdx = ValueUnion.u32;
3201 break;
3202
3203 case 'i': // --password-id
3204 bstrPasswordId = ValueUnion.psz;
3205 break;
3206
3207 case 'w': // --password
3208 pszPassword = ValueUnion.psz;
3209 break;
3210
3211 case VINF_GETOPT_NOT_OPTION:
3212 if (!VMNameOrUuid)
3213 VMNameOrUuid = ValueUnion.psz;
3214 else
3215 return errorSyntax(Info::tr("Invalid parameter '%s'"), ValueUnion.psz);
3216 break;
3217
3218 default:
3219 return errorGetOpt(c, &ValueUnion);
3220 }
3221 }
3222
3223 /* check for required options */
3224 if (!VMNameOrUuid)
3225 return errorSyntax(Info::tr("VM name or UUID required"));
3226
3227 /* try to find the given machine */
3228 ComPtr<IMachine> machine;
3229 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(),
3230 machine.asOutParam()));
3231 if (FAILED(hrc))
3232 return RTEXITCODE_FAILURE;
3233
3234 /* Printing the log is exclusive. */
3235 if (fLog && (fMachinereadable || fDetails))
3236 return errorSyntax(Info::tr("Option --log is exclusive"));
3237
3238 /* add VM password if required */
3239 if (pszPassword && bstrPasswordId.isNotEmpty())
3240 {
3241 Utf8Str strPassword;
3242 if (!RTStrCmp(pszPassword, "-"))
3243 {
3244 /* Get password from console. */
3245 RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:");
3246 if (rcExit == RTEXITCODE_FAILURE)
3247 return rcExit;
3248 }
3249 else
3250 {
3251 RTEXITCODE rcExit = readPasswordFile(pszPassword, &strPassword);
3252 if (rcExit == RTEXITCODE_FAILURE)
3253 {
3254 RTMsgError("Failed to read new password from file");
3255 return rcExit;
3256 }
3257 }
3258 CHECK_ERROR(machine, AddEncryptionPassword(bstrPasswordId.raw(), Bstr(strPassword).raw()));
3259 }
3260
3261 if (fLog)
3262 {
3263 ULONG64 uOffset = 0;
3264 SafeArray<BYTE> aLogData;
3265 size_t cbLogData;
3266 while (true)
3267 {
3268 /* Reset the array */
3269 aLogData.setNull();
3270 /* Fetch a chunk of the log file */
3271 CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, uOffset, _1M,
3272 ComSafeArrayAsOutParam(aLogData)));
3273 cbLogData = aLogData.size();
3274 if (cbLogData == 0)
3275 break;
3276 /* aLogData has a platform dependent line ending, standardize on
3277 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
3278 * Windows. Otherwise we end up with CR/CR/LF on Windows. */
3279 size_t cbLogDataPrint = cbLogData;
3280 for (BYTE *s = aLogData.raw(), *d = s;
3281 s - aLogData.raw() < (ssize_t)cbLogData;
3282 s++, d++)
3283 {
3284 if (*s == '\r')
3285 {
3286 /* skip over CR, adjust destination */
3287 d--;
3288 cbLogDataPrint--;
3289 }
3290 else if (s != d)
3291 *d = *s;
3292 }
3293 RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint);
3294 uOffset += cbLogData;
3295 }
3296 }
3297 else
3298 {
3299 /* 2nd option can be -details or -argdump */
3300 VMINFO_DETAILS details = VMINFO_NONE;
3301 if (fMachinereadable)
3302 details = VMINFO_MACHINEREADABLE;
3303 else if (fDetails)
3304 details = VMINFO_FULL;
3305 else
3306 details = VMINFO_STANDARD;
3307
3308 /* open an existing session for the VM */
3309 CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared));
3310 if (SUCCEEDED(hrc))
3311 {
3312 /* get the session machine */
3313 CHECK_ERROR(a->session, COMGETTER(Machine)(machine.asOutParam()));
3314 if (SUCCEEDED(hrc))
3315 hrc = showVMInfo(a->virtualBox, machine, a->session, details);
3316
3317 CHECK_ERROR(a->session, UnlockMachine());
3318 }
3319 }
3320
3321 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
3322}
3323
3324/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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