VirtualBox

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

Last change on this file was 106209, checked in by vboxsync, 2 months ago

VBoxManage: Fix breakage of "list vms" and "showvminfo" for inaccessible VMs due to misplaced API calls. The inaccessible VM checking must be done first, otherwise just meaningless errors are shown. bugref:10384

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