VirtualBox

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

Last change on this file since 99844 was 99775, checked in by vboxsync, 19 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

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