VirtualBox

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

Last change on this file since 107380 was 107267, checked in by vboxsync, 4 months ago

Main/API,UI: bugref:10810 Based on Brent's patch, added UsbNet support into Main API and UI

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

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