VirtualBox

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

Last change on this file since 107817 was 107799, checked in by vboxsync, 4 weeks ago

doc/manual,Frontends/VBoxManage: Update VBoxManage to include support
for changing the graphics controller to QemuRamFB via 'modifyvm
--graphicscontroller' and also display this new graphics controller type
when running 'showvminfo'. Follow up to r159173. bugref:10386
ticketref:22232

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

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