VirtualBox

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

Last change on this file since 101125 was 101125, checked in by vboxsync, 8 months ago

FE/VBoxManage: Added armv8virtual chipset handling. bugref:10384.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use