VirtualBox

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

Last change on this file since 94887 was 94660, checked in by vboxsync, 3 years ago

doc/manual,Main,Frontends: API changes in preparation for full VM encryption, guarded by VBOX_WITH_FULL_VM_ENCRYPTION (disabled by default) and returning a not supported error for now, bugref:9955

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