VirtualBox

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

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

Added emulation of several classic Ethernet adapters.

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

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