VirtualBox

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

Last change on this file since 101035 was 101035, checked in by vboxsync, 9 months ago

Initial commit (based draft v2 / on patch v5) for implementing platform architecture support for x86 and ARM. bugref:10384

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

© 2023 Oracle
ContactPrivacy policyTerms of Use