VirtualBox

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

Last change on this file since 105266 was 105266, checked in by vboxsync, 5 months ago

Recording: Implemented support for a dedicated progress object, which is exposed to API clients. This can be used for better tracking the recording progress as well as for error reporting. The RecordingSettings API also now has a dedicated start() method to start recording, as well as support for attaching to an already ongoing recording by retrieving the progress object at a later time. Adapted FE/Qt (draft, see @todos), FE/VBoxManage and the Validation Kit testdriver to the new APIs. VBoxManage also can attach to an ongoing recording now. The recording progress object also will have multiple operations to get the recording progress for convenience. bugref:10718

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