VirtualBox

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

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 129.1 KB
Line 
1/* $Id: VBoxManageInfo.cpp 93115 2022-01-01 11:31:46Z 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 default:
1817 AssertFailed();
1818 if (details == VMINFO_MACHINEREADABLE)
1819 pszNICType = "unknown";
1820 else
1821 pszNICType = Info::tr("unknown");
1822 break;
1823 }
1824
1825 /* reported line speed */
1826 ULONG ulLineSpeed;
1827 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1828
1829 /* boot priority of the adapter */
1830 ULONG ulBootPriority;
1831 nic->COMGETTER(BootPriority)(&ulBootPriority);
1832
1833 /* bandwidth group */
1834 ComObjPtr<IBandwidthGroup> pBwGroup;
1835 Bstr strBwGroup;
1836 nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam());
1837 if (!pBwGroup.isNull())
1838 pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam());
1839
1840 if (details == VMINFO_MACHINEREADABLE)
1841 {
1842 RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw());
1843 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1844 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str());
1845 RTPrintf("nictype%d=\"%s\"\n", currentNIC + 1, pszNICType);
1846 RTPrintf("nicspeed%d=\"%d\"\n", currentNIC + 1, ulLineSpeed);
1847 }
1848 else
1849 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"),
1850 szNm, strMACAddress.raw(), strAttachment.c_str(),
1851 fConnected ? Info::tr("on") : Info::tr("off"),
1852 fTraceEnabled ? Info::tr("on") : Info::tr("off"),
1853 traceFile.isEmpty() ? Bstr(Info::tr("none")).raw() : traceFile.raw(),
1854 pszNICType,
1855 ulLineSpeed / 1000,
1856 (int)ulBootPriority,
1857 pszPromiscuousGuestPolicy,
1858 strBwGroup.isEmpty() ? Bstr(Info::tr("none")).raw() : strBwGroup.raw());
1859 if (strNatSettings.length())
1860 RTPrintf(strNatSettings.c_str());
1861 if (strNatForwardings.length())
1862 RTPrintf(strNatForwardings.c_str());
1863 }
1864 }
1865 }
1866
1867 /* Pointing device information */
1868 PointingHIDType_T aPointingHID;
1869 const char *pszHID = Info::tr("Unknown");
1870 const char *pszMrHID = "unknown";
1871 machine->COMGETTER(PointingHIDType)(&aPointingHID);
1872 switch (aPointingHID)
1873 {
1874 case PointingHIDType_None:
1875 pszHID = Info::tr("None");
1876 pszMrHID = "none";
1877 break;
1878 case PointingHIDType_PS2Mouse:
1879 pszHID = Info::tr("PS/2 Mouse");
1880 pszMrHID = "ps2mouse";
1881 break;
1882 case PointingHIDType_USBMouse:
1883 pszHID = Info::tr("USB Mouse");
1884 pszMrHID = "usbmouse";
1885 break;
1886 case PointingHIDType_USBTablet:
1887 pszHID = Info::tr("USB Tablet");
1888 pszMrHID = "usbtablet";
1889 break;
1890 case PointingHIDType_ComboMouse:
1891 pszHID = Info::tr("USB Tablet and PS/2 Mouse");
1892 pszMrHID = "combomouse";
1893 break;
1894 case PointingHIDType_USBMultiTouch:
1895 pszHID = Info::tr("USB Multi-Touch");
1896 pszMrHID = "usbmultitouch";
1897 break;
1898 default:
1899 break;
1900 }
1901 SHOW_UTF8_STRING("hidpointing", Info::tr("Pointing Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
1902
1903 /* Keyboard device information */
1904 KeyboardHIDType_T aKeyboardHID;
1905 machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID);
1906 pszHID = Info::tr("Unknown");
1907 pszMrHID = "unknown";
1908 switch (aKeyboardHID)
1909 {
1910 case KeyboardHIDType_None:
1911 pszHID = Info::tr("None");
1912 pszMrHID = "none";
1913 break;
1914 case KeyboardHIDType_PS2Keyboard:
1915 pszHID = Info::tr("PS/2 Keyboard");
1916 pszMrHID = "ps2kbd";
1917 break;
1918 case KeyboardHIDType_USBKeyboard:
1919 pszHID = Info::tr("USB Keyboard");
1920 pszMrHID = "usbkbd";
1921 break;
1922 case KeyboardHIDType_ComboKeyboard:
1923 pszHID = Info::tr("USB and PS/2 Keyboard");
1924 pszMrHID = "combokbd";
1925 break;
1926 default:
1927 break;
1928 }
1929 SHOW_UTF8_STRING("hidkeyboard", Info::tr("Keyboard Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID);
1930
1931 ComPtr<ISystemProperties> sysProps;
1932 pVirtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
1933
1934 /* get the maximum amount of UARTs */
1935 ULONG maxUARTs = 0;
1936 sysProps->COMGETTER(SerialPortCount)(&maxUARTs);
1937 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
1938 {
1939 ComPtr<ISerialPort> uart;
1940 rc = machine->GetSerialPort(currentUART, uart.asOutParam());
1941 if (SUCCEEDED(rc) && uart)
1942 {
1943 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "uart%u" : Info::tr("UART %u:"), currentUART + 1);
1944
1945 /* show the config of this UART */
1946 BOOL fEnabled;
1947 uart->COMGETTER(Enabled)(&fEnabled);
1948 if (!fEnabled)
1949 {
1950 if (details == VMINFO_MACHINEREADABLE)
1951 RTPrintf("%s=\"off\"\n", szNm);
1952 else
1953 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
1954 }
1955 else
1956 {
1957 ULONG ulIRQ, ulIOBase;
1958 PortMode_T HostMode;
1959 Bstr path;
1960 BOOL fServer;
1961 UartType_T UartType;
1962 uart->COMGETTER(IRQ)(&ulIRQ);
1963 uart->COMGETTER(IOBase)(&ulIOBase);
1964 uart->COMGETTER(Path)(path.asOutParam());
1965 uart->COMGETTER(Server)(&fServer);
1966 uart->COMGETTER(HostMode)(&HostMode);
1967 uart->COMGETTER(UartType)(&UartType);
1968
1969 if (details == VMINFO_MACHINEREADABLE)
1970 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
1971 else
1972 RTPrintf(Info::tr("%-28s I/O base: %#06x, IRQ: %d"), szNm, ulIOBase, ulIRQ);
1973 switch (HostMode)
1974 {
1975 default:
1976 case PortMode_Disconnected:
1977 if (details == VMINFO_MACHINEREADABLE)
1978 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
1979 else
1980 RTPrintf(Info::tr(", disconnected"));
1981 break;
1982 case PortMode_RawFile:
1983 if (details == VMINFO_MACHINEREADABLE)
1984 RTPrintf("uartmode%d=\"file,%ls\"\n", currentUART + 1,
1985 path.raw());
1986 else
1987 RTPrintf(Info::tr(", attached to raw file '%ls'\n"),
1988 path.raw());
1989 break;
1990 case PortMode_TCP:
1991 if (details == VMINFO_MACHINEREADABLE)
1992 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
1993 fServer ? "tcpserver" : "tcpclient", path.raw());
1994 else
1995 RTPrintf(Info::tr(", attached to tcp (%s) '%ls'"),
1996 fServer ? Info::tr("server") : Info::tr("client"), path.raw());
1997 break;
1998 case PortMode_HostPipe:
1999 if (details == VMINFO_MACHINEREADABLE)
2000 RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1,
2001 fServer ? "server" : "client", path.raw());
2002 else
2003 RTPrintf(Info::tr(", attached to pipe (%s) '%ls'"),
2004 fServer ? Info::tr("server") : Info::tr("client"), path.raw());
2005 break;
2006 case PortMode_HostDevice:
2007 if (details == VMINFO_MACHINEREADABLE)
2008 RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1,
2009 path.raw());
2010 else
2011 RTPrintf(Info::tr(", attached to device '%ls'"), path.raw());
2012 break;
2013 }
2014 switch (UartType)
2015 {
2016 default:
2017 case UartType_U16450:
2018 if (details == VMINFO_MACHINEREADABLE)
2019 RTPrintf("uarttype%d=\"16450\"\n", currentUART + 1);
2020 else
2021 RTPrintf(", 16450\n");
2022 break;
2023 case UartType_U16550A:
2024 if (details == VMINFO_MACHINEREADABLE)
2025 RTPrintf("uarttype%d=\"16550A\"\n", currentUART + 1);
2026 else
2027 RTPrintf(", 16550A\n");
2028 break;
2029 case UartType_U16750:
2030 if (details == VMINFO_MACHINEREADABLE)
2031 RTPrintf("uarttype%d=\"16750\"\n", currentUART + 1);
2032 else
2033 RTPrintf(", 16750\n");
2034 break;
2035 }
2036 }
2037 }
2038 }
2039
2040 /* get the maximum amount of LPTs */
2041 ULONG maxLPTs = 0;
2042 sysProps->COMGETTER(ParallelPortCount)(&maxLPTs);
2043 for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++)
2044 {
2045 ComPtr<IParallelPort> lpt;
2046 rc = machine->GetParallelPort(currentLPT, lpt.asOutParam());
2047 if (SUCCEEDED(rc) && lpt)
2048 {
2049 FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "lpt%u" : Info::tr("LPT %u:"), currentLPT + 1);
2050
2051 /* show the config of this LPT */
2052 BOOL fEnabled;
2053 lpt->COMGETTER(Enabled)(&fEnabled);
2054 if (!fEnabled)
2055 {
2056 if (details == VMINFO_MACHINEREADABLE)
2057 RTPrintf("%s=\"off\"\n", szNm);
2058 else
2059 RTPrintf(Info::tr("%-28s disabled\n"), szNm);
2060 }
2061 else
2062 {
2063 ULONG ulIRQ, ulIOBase;
2064 Bstr path;
2065 lpt->COMGETTER(IRQ)(&ulIRQ);
2066 lpt->COMGETTER(IOBase)(&ulIOBase);
2067 lpt->COMGETTER(Path)(path.asOutParam());
2068
2069 if (details == VMINFO_MACHINEREADABLE)
2070 RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ);
2071 else
2072 RTPrintf(Info::tr("%-28s I/O base: %#06x, IRQ: %d"), szNm, ulIOBase, ulIRQ);
2073 if (details == VMINFO_MACHINEREADABLE)
2074 RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1, path.raw());
2075 else
2076 RTPrintf(Info::tr(", attached to device '%ls'\n"), path.raw());
2077 }
2078 }
2079 }
2080
2081 ComPtr<IAudioAdapter> AudioAdapter;
2082 rc = machine->COMGETTER(AudioAdapter)(AudioAdapter.asOutParam());
2083 if (SUCCEEDED(rc))
2084 {
2085 const char *pszDrv = Info::tr("Unknown");
2086 const char *pszCtrl = Info::tr("Unknown");
2087 const char *pszCodec = Info::tr("Unknown");
2088 BOOL fEnabled;
2089 rc = AudioAdapter->COMGETTER(Enabled)(&fEnabled);
2090 if (SUCCEEDED(rc) && fEnabled)
2091 {
2092 AudioDriverType_T enmDrvType;
2093 rc = AudioAdapter->COMGETTER(AudioDriver)(&enmDrvType);
2094 switch (enmDrvType)
2095 {
2096 case AudioDriverType_Null:
2097 if (details == VMINFO_MACHINEREADABLE)
2098 pszDrv = "null";
2099 else
2100 pszDrv = Info::tr("Null");
2101 break;
2102 case AudioDriverType_WinMM:
2103 if (details == VMINFO_MACHINEREADABLE)
2104 pszDrv = "winmm";
2105 else
2106 pszDrv = "WINMM";
2107 break;
2108 case AudioDriverType_DirectSound:
2109 if (details == VMINFO_MACHINEREADABLE)
2110 pszDrv = "dsound";
2111 else
2112 pszDrv = "DSOUND";
2113 break;
2114 case AudioDriverType_OSS:
2115 if (details == VMINFO_MACHINEREADABLE)
2116 pszDrv = "oss";
2117 else
2118 pszDrv = "OSS";
2119 break;
2120 case AudioDriverType_ALSA:
2121 if (details == VMINFO_MACHINEREADABLE)
2122 pszDrv = "alsa";
2123 else
2124 pszDrv = "ALSA";
2125 break;
2126 case AudioDriverType_Pulse:
2127 if (details == VMINFO_MACHINEREADABLE)
2128 pszDrv = "pulse";
2129 else
2130 pszDrv = "PulseAudio";
2131 break;
2132 case AudioDriverType_CoreAudio:
2133 if (details == VMINFO_MACHINEREADABLE)
2134 pszDrv = "coreaudio";
2135 else
2136 pszDrv = "CoreAudio";
2137 break;
2138 case AudioDriverType_SolAudio:
2139 if (details == VMINFO_MACHINEREADABLE)
2140 pszDrv = "solaudio";
2141 else
2142 pszDrv = "SolAudio";
2143 break;
2144 default:
2145 if (details == VMINFO_MACHINEREADABLE)
2146 pszDrv = "unknown";
2147 break;
2148 }
2149 AudioControllerType_T enmCtrlType;
2150 rc = AudioAdapter->COMGETTER(AudioController)(&enmCtrlType);
2151 switch (enmCtrlType)
2152 {
2153 case AudioControllerType_AC97:
2154 if (details == VMINFO_MACHINEREADABLE)
2155 pszCtrl = "ac97";
2156 else
2157 pszCtrl = "AC97";
2158 break;
2159 case AudioControllerType_SB16:
2160 if (details == VMINFO_MACHINEREADABLE)
2161 pszCtrl = "sb16";
2162 else
2163 pszCtrl = "SB16";
2164 break;
2165 case AudioControllerType_HDA:
2166 if (details == VMINFO_MACHINEREADABLE)
2167 pszCtrl = "hda";
2168 else
2169 pszCtrl = "HDA";
2170 break;
2171 default:
2172 break;
2173 }
2174 AudioCodecType_T enmCodecType;
2175 rc = AudioAdapter->COMGETTER(AudioCodec)(&enmCodecType);
2176 switch (enmCodecType)
2177 {
2178 case AudioCodecType_SB16:
2179 pszCodec = "SB16";
2180 break;
2181 case AudioCodecType_STAC9700:
2182 pszCodec = "STAC9700";
2183 break;
2184 case AudioCodecType_AD1980:
2185 pszCodec = "AD1980";
2186 break;
2187 case AudioCodecType_STAC9221:
2188 pszCodec = "STAC9221";
2189 break;
2190 case AudioCodecType_Null: break; /* Shut up MSC. */
2191 default: break;
2192 }
2193 }
2194 else
2195 fEnabled = FALSE;
2196
2197 if (details == VMINFO_MACHINEREADABLE)
2198 RTPrintf("audio=\"%s\"\n", fEnabled ? pszDrv : "none");
2199 else
2200 {
2201 RTPrintf("%-28s %s", Info::tr("Audio:"), fEnabled ? Info::tr("enabled") : Info::tr("disabled"));
2202 if (fEnabled)
2203 RTPrintf(Info::tr(" (Driver: %s, Controller: %s, Codec: %s)"), pszDrv, pszCtrl, pszCodec);
2204 RTPrintf("\n");
2205 }
2206 SHOW_BOOLEAN_PROP(AudioAdapter, EnabledOut, "audio_out", Info::tr("Audio playback:"));
2207 SHOW_BOOLEAN_PROP(AudioAdapter, EnabledIn, "audio_in", Info::tr("Audio capture:"));
2208 }
2209
2210 /* Shared clipboard */
2211 {
2212 const char *psz;
2213 ClipboardMode_T enmMode = (ClipboardMode_T)0;
2214 rc = machine->COMGETTER(ClipboardMode)(&enmMode);
2215 switch (enmMode)
2216 {
2217 case ClipboardMode_Disabled:
2218 psz = "disabled";
2219 break;
2220 case ClipboardMode_HostToGuest:
2221 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest");
2222 break;
2223 case ClipboardMode_GuestToHost:
2224 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost");
2225 break;
2226 case ClipboardMode_Bidirectional:
2227 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional");
2228 break;
2229 default:
2230 psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2231 break;
2232 }
2233 SHOW_UTF8_STRING("clipboard", Info::tr("Clipboard Mode:"), psz);
2234#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
2235 SHOW_BOOLEAN_PROP(machine, ClipboardFileTransfersEnabled, "clipboard_file_transfers", Info::tr("Clipboard file transfers:"));
2236#endif
2237 }
2238
2239 /* Drag and drop */
2240 {
2241 const char *psz;
2242 DnDMode_T enmMode;
2243 rc = machine->COMGETTER(DnDMode)(&enmMode);
2244 switch (enmMode)
2245 {
2246 case DnDMode_Disabled:
2247 psz = "disabled";
2248 break;
2249 case DnDMode_HostToGuest:
2250 psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest");
2251 break;
2252 case DnDMode_GuestToHost:
2253 psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost");
2254 break;
2255 case DnDMode_Bidirectional:
2256 psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional");
2257 break;
2258 default:
2259 psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown");
2260 break;
2261 }
2262 SHOW_UTF8_STRING("draganddrop", Info::tr("Drag and drop Mode:"), psz);
2263 }
2264
2265 {
2266 SessionState_T sessState;
2267 rc = machine->COMGETTER(SessionState)(&sessState);
2268 if (SUCCEEDED(rc) && sessState != SessionState_Unlocked)
2269 {
2270 Bstr sessName;
2271 rc = machine->COMGETTER(SessionName)(sessName.asOutParam());
2272 if (SUCCEEDED(rc) && !sessName.isEmpty())
2273 SHOW_BSTR_STRING("SessionName", Info::tr("Session name:"), sessName);
2274 }
2275 }
2276
2277 if (pConsole)
2278 {
2279 do
2280 {
2281 ComPtr<IDisplay> display;
2282 rc = pConsole->COMGETTER(Display)(display.asOutParam());
2283 if (rc == E_ACCESSDENIED || display.isNull())
2284 break; /* VM not powered up */
2285 if (FAILED(rc))
2286 {
2287 com::GlueHandleComError(pConsole, "COMGETTER(Display)(display.asOutParam())", rc, __FILE__, __LINE__);
2288 return rc;
2289 }
2290 ULONG xRes, yRes, bpp;
2291 LONG xOrigin, yOrigin;
2292 GuestMonitorStatus_T monitorStatus;
2293 rc = display->GetScreenResolution(0, &xRes, &yRes, &bpp, &xOrigin, &yOrigin, &monitorStatus);
2294 if (rc == E_ACCESSDENIED)
2295 break; /* VM not powered up */
2296 if (FAILED(rc))
2297 {
2298 com::ErrorInfo info(display, COM_IIDOF(IDisplay));
2299 GluePrintErrorInfo(info);
2300 return rc;
2301 }
2302 if (details == VMINFO_MACHINEREADABLE)
2303 RTPrintf("VideoMode=\"%d,%d,%d\"@%d,%d %d\n", xRes, yRes, bpp, xOrigin, yOrigin, monitorStatus);
2304 else
2305 {
2306 const char *pszMonitorStatus = Info::tr("unknown status");
2307 switch (monitorStatus)
2308 {
2309 case GuestMonitorStatus_Blank: pszMonitorStatus = Info::tr("blank"); break;
2310 case GuestMonitorStatus_Enabled: pszMonitorStatus = Info::tr("enabled"); break;
2311 case GuestMonitorStatus_Disabled: pszMonitorStatus = Info::tr("disabled"); break;
2312 default: break;
2313 }
2314 RTPrintf("%-28s %dx%dx%d at %d,%d %s\n", Info::tr("Video mode:"), xRes, yRes, bpp, xOrigin, yOrigin, pszMonitorStatus);
2315 }
2316 }
2317 while (0);
2318 }
2319
2320 /*
2321 * Remote Desktop
2322 */
2323 ComPtr<IVRDEServer> vrdeServer;
2324 rc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam());
2325 if (SUCCEEDED(rc) && vrdeServer)
2326 {
2327 BOOL fEnabled = false;
2328 vrdeServer->COMGETTER(Enabled)(&fEnabled);
2329 if (fEnabled)
2330 {
2331 LONG currentPort = -1;
2332 Bstr ports;
2333 vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam());
2334 Bstr address;
2335 vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam());
2336 BOOL fMultiCon;
2337 vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
2338 BOOL fReuseCon;
2339 vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon);
2340 Bstr videoChannel;
2341 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam());
2342 BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0)
2343 || (videoChannel == "1");
2344 Bstr videoChannelQuality;
2345 vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam());
2346 AuthType_T authType = (AuthType_T)0;
2347 const char *strAuthType;
2348 vrdeServer->COMGETTER(AuthType)(&authType);
2349 switch (authType)
2350 {
2351 case AuthType_Null:
2352 if (details == VMINFO_MACHINEREADABLE)
2353 strAuthType = "null";
2354 else
2355 strAuthType = Info::tr("null");
2356 break;
2357 case AuthType_External:
2358 if (details == VMINFO_MACHINEREADABLE)
2359 strAuthType = "external";
2360 else
2361 strAuthType = Info::tr("external");
2362 break;
2363 case AuthType_Guest:
2364 if (details == VMINFO_MACHINEREADABLE)
2365 strAuthType = "guest";
2366 else
2367 strAuthType = Info::tr("guest");
2368 break;
2369 default:
2370 if (details == VMINFO_MACHINEREADABLE)
2371 strAuthType = "unknown";
2372 else
2373 strAuthType = Info::tr("unknown");
2374 break;
2375 }
2376 if (pConsole)
2377 {
2378 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2379 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2380 if (!vrdeServerInfo.isNull())
2381 {
2382 rc = vrdeServerInfo->COMGETTER(Port)(&currentPort);
2383 if (rc == E_ACCESSDENIED)
2384 {
2385 currentPort = -1; /* VM not powered up */
2386 }
2387 else if (FAILED(rc))
2388 {
2389 com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo));
2390 GluePrintErrorInfo(info);
2391 return rc;
2392 }
2393 }
2394 }
2395 if (details == VMINFO_MACHINEREADABLE)
2396 {
2397 RTPrintf("vrde=\"on\"\n");
2398 RTPrintf("vrdeport=%d\n", currentPort);
2399 RTPrintf("vrdeports=\"%ls\"\n", ports.raw());
2400 RTPrintf("vrdeaddress=\"%ls\"\n", address.raw());
2401 RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType);
2402 RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off");
2403 RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off");
2404 RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off");
2405 if (fVideoChannel)
2406 RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw());
2407 }
2408 else
2409 {
2410 if (address.isEmpty())
2411 address = "0.0.0.0";
2412 RTPrintf(Info::tr("%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n"),
2413 "VRDE:", address.raw(), ports.raw(), fMultiCon ? Info::tr("on") : Info::tr("off"),
2414 fReuseCon ? Info::tr("on") : Info::tr("off"), strAuthType);
2415 if (pConsole && currentPort != -1 && currentPort != 0)
2416 RTPrintf("%-28s %d\n", Info::tr("VRDE port:"), currentPort);
2417 if (fVideoChannel)
2418 RTPrintf(Info::tr("%-28s enabled (Quality %ls)\n"), Info::tr("Video redirection:"), videoChannelQuality.raw());
2419 else
2420 RTPrintf(Info::tr("%-28s disabled\n"), Info::tr("Video redirection:"));
2421 }
2422 com::SafeArray<BSTR> aProperties;
2423 if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties))))
2424 {
2425 unsigned i;
2426 for (i = 0; i < aProperties.size(); ++i)
2427 {
2428 Bstr value;
2429 vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam());
2430 if (details == VMINFO_MACHINEREADABLE)
2431 {
2432 if (value.isEmpty())
2433 RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]);
2434 else
2435 RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw());
2436 }
2437 else
2438 {
2439 if (value.isEmpty())
2440 RTPrintf(Info::tr("%-28s: %-10lS = <not set>\n"), Info::tr("VRDE property"), aProperties[i]);
2441 else
2442 RTPrintf("%-28s: %-10lS = \"%ls\"\n", Info::tr("VRDE property"), aProperties[i], value.raw());
2443 }
2444 }
2445 }
2446 }
2447 else
2448 {
2449 if (details == VMINFO_MACHINEREADABLE)
2450 RTPrintf("vrde=\"off\"\n");
2451 else
2452 RTPrintf(Info::tr("%-28s disabled\n"), "VRDE:");
2453 }
2454 }
2455
2456 /*
2457 * USB.
2458 */
2459 SafeIfaceArray<IUSBController> USBCtlColl;
2460 rc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl));
2461 if (SUCCEEDED(rc))
2462 {
2463 bool fOhciEnabled = false;
2464 bool fEhciEnabled = false;
2465 bool fXhciEnabled = false;
2466
2467 for (unsigned i = 0; i < USBCtlColl.size(); i++)
2468 {
2469 USBControllerType_T enmType;
2470
2471 rc = USBCtlColl[i]->COMGETTER(Type)(&enmType);
2472 if (SUCCEEDED(rc))
2473 {
2474 switch (enmType)
2475 {
2476 case USBControllerType_OHCI:
2477 fOhciEnabled = true;
2478 break;
2479 case USBControllerType_EHCI:
2480 fEhciEnabled = true;
2481 break;
2482 case USBControllerType_XHCI:
2483 fXhciEnabled = true;
2484 break;
2485 default:
2486 break;
2487 }
2488 }
2489 }
2490
2491 SHOW_BOOL_VALUE("usb", "OHCI USB:", fOhciEnabled);
2492 SHOW_BOOL_VALUE("ehci", "EHCI USB:", fEhciEnabled);
2493 SHOW_BOOL_VALUE("xhci", "xHCI USB:", fXhciEnabled);
2494 }
2495
2496 ComPtr<IUSBDeviceFilters> USBFlts;
2497 rc = machine->COMGETTER(USBDeviceFilters)(USBFlts.asOutParam());
2498 if (SUCCEEDED(rc))
2499 {
2500 SafeIfaceArray <IUSBDeviceFilter> Coll;
2501 rc = USBFlts->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll));
2502 if (SUCCEEDED(rc))
2503 {
2504 if (Coll.size() > 0)
2505 {
2506 if (details != VMINFO_MACHINEREADABLE)
2507 RTPrintf(Info::tr("USB Device Filters:\n"));
2508 for (size_t index = 0; index < Coll.size(); ++index)
2509 {
2510 ComPtr<IUSBDeviceFilter> DevPtr = Coll[index];
2511
2512 if (details != VMINFO_MACHINEREADABLE)
2513 SHOW_UTF8_STRING("index", Info::tr("Index:"), FmtNm(szNm, "%zu", index));
2514 SHOW_BOOLEAN_PROP_EX(DevPtr, Active, FmtNm(szNm, "USBFilterActive%zu", index + 1), Info::tr(" Active:"), Info::tr("yes"), Info::tr("no"));
2515 SHOW_STRING_PROP(DevPtr, Name, FmtNm(szNm, "USBFilterName%zu", index + 1), Info::tr(" Name:"));
2516 SHOW_STRING_PROP(DevPtr, VendorId, FmtNm(szNm, "USBFilterVendorId%zu", index + 1), Info::tr(" VendorId:"));
2517 SHOW_STRING_PROP(DevPtr, ProductId, FmtNm(szNm, "USBFilterProductId%zu", index + 1), Info::tr(" ProductId:"));
2518 SHOW_STRING_PROP(DevPtr, Revision, FmtNm(szNm, "USBFilterRevision%zu", index + 1), Info::tr(" Revision:"));
2519 SHOW_STRING_PROP(DevPtr, Manufacturer, FmtNm(szNm, "USBFilterManufacturer%zu", index + 1), Info::tr(" Manufacturer:"));
2520 SHOW_STRING_PROP(DevPtr, Product, FmtNm(szNm, "USBFilterProduct%zu", index + 1), Info::tr(" Product:"));
2521 SHOW_STRING_PROP(DevPtr, Remote, FmtNm(szNm, "USBFilterRemote%zu", index + 1), Info::tr(" Remote:"));
2522 SHOW_STRING_PROP(DevPtr, SerialNumber, FmtNm(szNm, "USBFilterSerialNumber%zu", index + 1), Info::tr(" Serial Number:"));
2523 if (details != VMINFO_MACHINEREADABLE)
2524 {
2525 ULONG fMaskedIfs;
2526 CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), rc);
2527 if (fMaskedIfs)
2528 RTPrintf("%-28s %#010x\n", Info::tr("Masked Interfaces:"), fMaskedIfs);
2529 }
2530 }
2531 }
2532 else if (details != VMINFO_MACHINEREADABLE)
2533 RTPrintf("%-28s %s\n", Info::tr("USB Device Filters:"), Info::tr("<none>"));
2534 }
2535
2536 if (pConsole)
2537 {
2538 {
2539 SafeIfaceArray<IHostUSBDevice> coll;
2540 CHECK_ERROR_RET(pConsole, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), rc);
2541 rc = showUsbDevices(coll, "USBRemote", Info::tr("Available remote USB devices:"), details);
2542 if (FAILED(rc))
2543 return rc;
2544 }
2545
2546 {
2547 SafeIfaceArray<IUSBDevice> coll;
2548 CHECK_ERROR_RET(pConsole, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), rc);
2549 showUsbDevices(coll, "USBAttach", Info::tr("Currently attached USB devices:"), details);
2550 if (FAILED(rc))
2551 return rc;
2552 }
2553 }
2554 } /* USB */
2555
2556#ifdef VBOX_WITH_PCI_PASSTHROUGH
2557 /* Host PCI passthrough devices */
2558 {
2559 SafeIfaceArray <IPCIDeviceAttachment> assignments;
2560 rc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
2561 if (SUCCEEDED(rc))
2562 {
2563 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2564 {
2565 RTPrintf(Info::tr("\nAttached physical PCI devices:\n\n"));
2566 }
2567
2568 for (size_t index = 0; index < assignments.size(); ++index)
2569 {
2570 ComPtr<IPCIDeviceAttachment> Assignment = assignments[index];
2571 char szHostPCIAddress[32], szGuestPCIAddress[32];
2572 LONG iHostPCIAddress = -1, iGuestPCIAddress = -1;
2573 Bstr DevName;
2574
2575 Assignment->COMGETTER(Name)(DevName.asOutParam());
2576 Assignment->COMGETTER(HostAddress)(&iHostPCIAddress);
2577 Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress);
2578 PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress));
2579 PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress));
2580
2581 if (details == VMINFO_MACHINEREADABLE)
2582 RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress);
2583 else
2584 RTPrintf(Info::tr(" Host device %ls at %s attached as %s\n"), DevName.raw(), szHostPCIAddress, szGuestPCIAddress);
2585 }
2586
2587 if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE))
2588 {
2589 RTPrintf("\n");
2590 }
2591 }
2592 }
2593 /* Host PCI passthrough devices */
2594#endif
2595
2596 /*
2597 * Bandwidth groups
2598 */
2599 if (details != VMINFO_MACHINEREADABLE)
2600 RTPrintf("%-28s ", Info::tr("Bandwidth groups:"));
2601 {
2602 ComPtr<IBandwidthControl> bwCtrl;
2603 CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), rc);
2604
2605 rc = showBandwidthGroups(bwCtrl, details);
2606 }
2607
2608
2609 /*
2610 * Shared folders
2611 */
2612 if (details != VMINFO_MACHINEREADABLE)
2613 RTPrintf("%-28s ", Info::tr("Shared folders:"));
2614 uint32_t numSharedFolders = 0;
2615#if 0 // not yet implemented
2616 /* globally shared folders first */
2617 {
2618 SafeIfaceArray <ISharedFolder> sfColl;
2619 CHECK_ERROR_RET(pVirtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(sfColl)), rc);
2620 for (size_t i = 0; i < sfColl.size(); ++i)
2621 {
2622 ComPtr<ISharedFolder> sf = sfColl[i];
2623 showSharedFolder(sf, details, Info::tr("global mapping"), "GlobalMapping", i + 1, numSharedFolders == 0);
2624 ++numSharedFolders;
2625 }
2626 }
2627#endif
2628 /* now VM mappings */
2629 {
2630 com::SafeIfaceArray <ISharedFolder> folders;
2631 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2632 for (size_t i = 0; i < folders.size(); ++i)
2633 {
2634 ComPtr<ISharedFolder> sf = folders[i];
2635 showSharedFolder(sf, details, Info::tr("machine mapping"), "MachineMapping", i + 1, numSharedFolders == 0);
2636 ++numSharedFolders;
2637 }
2638 }
2639 /* transient mappings */
2640 if (pConsole)
2641 {
2642 com::SafeIfaceArray <ISharedFolder> folders;
2643 CHECK_ERROR_RET(pConsole, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), rc);
2644 for (size_t i = 0; i < folders.size(); ++i)
2645 {
2646 ComPtr<ISharedFolder> sf = folders[i];
2647 showSharedFolder(sf, details, Info::tr("transient mapping"), "TransientMapping", i + 1, numSharedFolders == 0);
2648 ++numSharedFolders;
2649 }
2650 }
2651 if (details != VMINFO_MACHINEREADABLE)
2652 {
2653 if (!numSharedFolders)
2654 RTPrintf(Info::tr("<none>\n"));
2655 else
2656 RTPrintf("\n");
2657 }
2658
2659 if (pConsole)
2660 {
2661 /*
2662 * Live VRDE info.
2663 */
2664 ComPtr<IVRDEServerInfo> vrdeServerInfo;
2665 CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), rc);
2666 BOOL fActive = FALSE;
2667 ULONG cNumberOfClients = 0;
2668 LONG64 BeginTime = 0;
2669 LONG64 EndTime = 0;
2670 LONG64 BytesSent = 0;
2671 LONG64 BytesSentTotal = 0;
2672 LONG64 BytesReceived = 0;
2673 LONG64 BytesReceivedTotal = 0;
2674 Bstr User;
2675 Bstr Domain;
2676 Bstr ClientName;
2677 Bstr ClientIP;
2678 ULONG ClientVersion = 0;
2679 ULONG EncryptionStyle = 0;
2680
2681 if (!vrdeServerInfo.isNull())
2682 {
2683 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&fActive), rc);
2684 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&cNumberOfClients), rc);
2685 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), rc);
2686 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), rc);
2687 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), rc);
2688 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), rc);
2689 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), rc);
2690 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), rc);
2691 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), rc);
2692 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), rc);
2693 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), rc);
2694 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), rc);
2695 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), rc);
2696 CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), rc);
2697 }
2698
2699 SHOW_BOOL_VALUE_EX("VRDEActiveConnection", Info::tr("VRDE Connection:"), fActive, Info::tr("active"), Info::tr("not active"));
2700 SHOW_ULONG_VALUE("VRDEClients=", Info::tr("Clients so far:"), cNumberOfClients, "");
2701
2702 if (cNumberOfClients > 0)
2703 {
2704 char szTimeValue[128];
2705 makeTimeStr(szTimeValue, sizeof(szTimeValue), BeginTime);
2706 if (fActive)
2707 SHOW_UTF8_STRING("VRDEStartTime", Info::tr("Start time:"), szTimeValue);
2708 else
2709 {
2710 SHOW_UTF8_STRING("VRDELastStartTime", Info::tr("Last started:"), szTimeValue);
2711 makeTimeStr(szTimeValue, sizeof(szTimeValue), EndTime);
2712 SHOW_UTF8_STRING("VRDELastEndTime", Info::tr("Last ended:"), szTimeValue);
2713 }
2714
2715 int64_t ThroughputSend = 0;
2716 int64_t ThroughputReceive = 0;
2717 if (EndTime != BeginTime)
2718 {
2719 ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime);
2720 ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime);
2721 }
2722 SHOW_LONG64_VALUE("VRDEBytesSent", Info::tr("Sent:"), BytesSent, Info::tr("Bytes"));
2723 SHOW_LONG64_VALUE("VRDEThroughputSend", Info::tr("Average speed:"), ThroughputSend, Info::tr("B/s"));
2724 SHOW_LONG64_VALUE("VRDEBytesSentTotal", Info::tr("Sent total:"), BytesSentTotal, Info::tr("Bytes"));
2725
2726 SHOW_LONG64_VALUE("VRDEBytesReceived", Info::tr("Received:"), BytesReceived, Info::tr("Bytes"));
2727 SHOW_LONG64_VALUE("VRDEThroughputReceive", Info::tr("Speed:"), ThroughputReceive, Info::tr("B/s"));
2728 SHOW_LONG64_VALUE("VRDEBytesReceivedTotal", Info::tr("Received total:"), BytesReceivedTotal, Info::tr("Bytes"));
2729
2730 if (fActive)
2731 {
2732 SHOW_BSTR_STRING("VRDEUserName", Info::tr("User name:"), User);
2733 SHOW_BSTR_STRING("VRDEDomain", Info::tr("Domain:"), Domain);
2734 SHOW_BSTR_STRING("VRDEClientName", Info::tr("Client name:"), ClientName);
2735 SHOW_BSTR_STRING("VRDEClientIP", Info::tr("Client IP:"), ClientIP);
2736 SHOW_ULONG_VALUE("VRDEClientVersion", Info::tr("Client version:"), ClientVersion, "");
2737 SHOW_UTF8_STRING("VRDEEncryption", Info::tr("Encryption:"), EncryptionStyle == 0 ? "RDP4" : "RDP5 (X.509)");
2738 }
2739 }
2740 }
2741
2742#ifdef VBOX_WITH_RECORDING
2743 {
2744 /* Video capture */
2745 BOOL fCaptureVideo = FALSE;
2746# ifdef VBOX_WITH_AUDIO_RECORDING
2747 BOOL fCaptureAudio = FALSE;
2748# endif
2749
2750 ComPtr<IRecordingSettings> recordingSettings;
2751 CHECK_ERROR_RET(machine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam()), rc);
2752
2753 SafeIfaceArray <IRecordingScreenSettings> saRecordingScreenScreens;
2754 CHECK_ERROR_RET(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saRecordingScreenScreens)), rc);
2755
2756 /* For now all screens have the same configuration; so take screen 0 and work with that. */
2757 ULONG fFeatures;
2758 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Features)(&fFeatures), rc);
2759 ULONG Width;
2760 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoWidth)(&Width), rc);
2761 ULONG Height;
2762 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoHeight)(&Height), rc);
2763 ULONG Rate;
2764 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoRate)(&Rate), rc);
2765 ULONG Fps;
2766 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(VideoFPS)(&Fps), rc);
2767 Bstr bstrFile;
2768 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Filename)(bstrFile.asOutParam()), rc);
2769 Bstr bstrOptions;
2770 CHECK_ERROR_RET(saRecordingScreenScreens[0], COMGETTER(Options)(bstrOptions.asOutParam()), rc);
2771
2772 Utf8Str strOptions(bstrOptions);
2773 size_t pos = 0;
2774 com::Utf8Str key, value;
2775 while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos)
2776 {
2777 if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0)
2778 {
2779 fCaptureVideo = value.compare("true", Utf8Str::CaseInsensitive) == 0;
2780 }
2781 else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0)
2782 {
2783# ifdef VBOX_WITH_AUDIO_RECORDING
2784 fCaptureAudio = value.compare("true", Utf8Str::CaseInsensitive) == 0;
2785# endif
2786 }
2787 }
2788
2789 SHOW_BOOL_VALUE_EX("videocap", Info::tr("Capturing:"), fCaptureVideo, Info::tr("active"), Info::tr("not active"));
2790# ifdef VBOX_WITH_AUDIO_RECORDING
2791 SHOW_BOOL_VALUE_EX("videocapaudio", Info::tr("Capture audio:"), fCaptureAudio, Info::tr("active"), Info::tr("not active"));
2792# endif
2793 szValue[0] = '\0';
2794 for (size_t i = 0, off = 0; i < saRecordingScreenScreens.size(); i++)
2795 {
2796 BOOL fEnabled;
2797 CHECK_ERROR_RET(saRecordingScreenScreens[i], COMGETTER(Enabled)(&fEnabled), rc);
2798 if (fEnabled && off < sizeof(szValue) - 3)
2799 off += RTStrPrintf(&szValue[off], sizeof(szValue) - off, off ? ",%zu" : "%zu", i);
2800 }
2801 SHOW_UTF8_STRING("capturescreens", Info::tr("Capture screens:"), szValue);
2802 SHOW_BSTR_STRING("capturefilename", Info::tr("Capture file:"), bstrFile);
2803 RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height);
2804 SHOW_UTF8_STRING("captureres", Info::tr("Capture dimensions:"), szValue);
2805 SHOW_ULONG_VALUE("capturevideorate", Info::tr("Capture rate:"), Rate, Info::tr("kbps"));
2806 SHOW_ULONG_VALUE("capturevideofps", Info::tr("Capture FPS:"), Fps, Info::tr("kbps"));
2807 SHOW_BSTR_STRING("captureopts", Info::tr("Capture options:"), bstrOptions);
2808
2809 /** @todo Add more audio capturing profile / information here. */
2810 }
2811#endif /* VBOX_WITH_RECORDING */
2812
2813 if ( details == VMINFO_STANDARD
2814 || details == VMINFO_FULL
2815 || details == VMINFO_MACHINEREADABLE)
2816 {
2817 Bstr description;
2818 machine->COMGETTER(Description)(description.asOutParam());
2819 if (!description.isEmpty())
2820 {
2821 if (details == VMINFO_MACHINEREADABLE)
2822 outputMachineReadableString("description", &description);
2823 else
2824 RTPrintf(Info::tr("Description:\n%ls\n"), description.raw());
2825 }
2826 }
2827
2828 /* VMMDev testing config (extra data) */
2829 if (details != VMINFO_MACHINEREADABLE)
2830 {
2831 Bstr bstr;
2832 CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled").raw(),
2833 bstr.asOutParam()), hrcCheck);
2834 int const fEnabled = parseCfgmBool(&bstr);
2835
2836 CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO").raw(),
2837 bstr.asOutParam()), hrcCheck);
2838 int const fMmio = parseCfgmBool(&bstr);
2839 if (fEnabled || fMmio)
2840 {
2841 RTPrintf("%-28s %s, %s %s\n",
2842 Info::tr("VMMDev Testing"),
2843 fEnabled > 0 ? Info::tr("enabled") : fEnabled == 0 ? Info::tr("disabled") : Info::tr("misconfigured"),
2844 "MMIO:",
2845 fMmio > 0 ? Info::tr("enabled") : fMmio == 0 ? Info::tr("disabled") : Info::tr("misconfigured"));
2846 for (uint32_t i = 0; i < 10; i++)
2847 {
2848 BstrFmt bstrName("VBoxInternal/Devices/VMMDev/0/Config/TestingCfgDword%u", i);
2849 CHECK_ERROR2I_RET(machine, GetExtraData(bstrName.raw(), bstr.asOutParam()), hrcCheck);
2850 if (bstr.isNotEmpty())
2851 RTPrintf("%-28s %ls\n", FmtNm(szNm, "VMMDev Testing Cfg Dword%u:", i), bstr.raw());
2852 }
2853 }
2854 }
2855
2856 /*
2857 * Snapshots.
2858 */
2859 ComPtr<ISnapshot> snapshot;
2860 rc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam());
2861 if (SUCCEEDED(rc) && snapshot)
2862 {
2863 ComPtr<ISnapshot> currentSnapshot;
2864 rc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam());
2865 if (SUCCEEDED(rc))
2866 {
2867 if (details != VMINFO_MACHINEREADABLE)
2868 RTPrintf(Info::tr("* Snapshots:\n"));
2869 showSnapshots(snapshot, currentSnapshot, details);
2870 }
2871 }
2872
2873 /*
2874 * Guest stuff (mainly interesting when running).
2875 */
2876 if (details != VMINFO_MACHINEREADABLE)
2877 RTPrintf(Info::tr("* Guest:\n"));
2878
2879 SHOW_ULONG_PROP(machine, MemoryBalloonSize, "GuestMemoryBalloon",
2880 Info::tr("Configured memory balloon:"), Info::tr("MB"));
2881
2882 if (pConsole)
2883 {
2884 ComPtr<IGuest> guest;
2885 rc = pConsole->COMGETTER(Guest)(guest.asOutParam());
2886 if (SUCCEEDED(rc) && !guest.isNull())
2887 {
2888 SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", Info::tr("OS type:"));
2889
2890 AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */
2891 rc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel);
2892 if (SUCCEEDED(rc))
2893 SHOW_ULONG_VALUE("GuestAdditionsRunLevel", Info::tr("Additions run level:"), (ULONG)guestRunLevel, "");
2894
2895 Bstr guestString;
2896 rc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam());
2897 if ( SUCCEEDED(rc)
2898 && !guestString.isEmpty())
2899 {
2900 ULONG uRevision;
2901 rc = guest->COMGETTER(AdditionsRevision)(&uRevision);
2902 if (FAILED(rc))
2903 uRevision = 0;
2904 RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision);
2905 SHOW_UTF8_STRING("GuestAdditionsVersion", Info::tr("Additions version:"), szValue);
2906 }
2907
2908 /* Print information about known Guest Additions facilities: */
2909 SafeIfaceArray <IAdditionsFacility> collFac;
2910 CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), rc);
2911 if (collFac.size() > 0)
2912 {
2913 if (details != VMINFO_MACHINEREADABLE)
2914 RTPrintf("%s\n", Info::tr("Guest Facilities:"));
2915 LONG64 lLastUpdatedMS;
2916 char szLastUpdated[32];
2917 AdditionsFacilityStatus_T curStatus;
2918 for (size_t index = 0; index < collFac.size(); ++index)
2919 {
2920 ComPtr<IAdditionsFacility> fac = collFac[index];
2921 if (fac)
2922 {
2923 CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), rc);
2924 if (!guestString.isEmpty())
2925 {
2926 CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), rc);
2927 CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), rc);
2928 if (details == VMINFO_MACHINEREADABLE)
2929 RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n",
2930 guestString.raw(), curStatus, lLastUpdatedMS);
2931 else
2932 {
2933 makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS);
2934 RTPrintf(Info::tr("Facility \"%ls\": %s (last update: %s)\n"),
2935 guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated);
2936 }
2937 }
2938 else
2939 AssertMsgFailed(("Facility with undefined name retrieved!\n"));
2940 }
2941 else
2942 AssertMsgFailed(("Invalid facility returned!\n"));
2943 }
2944 }
2945 else if (details != VMINFO_MACHINEREADABLE)
2946 RTPrintf("%-28s %s\n", Info::tr("Guest Facilities:"), Info::tr("<none>"));
2947 }
2948 }
2949
2950 if (details != VMINFO_MACHINEREADABLE)
2951 RTPrintf("\n");
2952 return S_OK;
2953}
2954
2955#if defined(_MSC_VER)
2956# pragma optimize("", on)
2957# pragma warning(pop)
2958#endif
2959
2960static const RTGETOPTDEF g_aShowVMInfoOptions[] =
2961{
2962 { "--details", 'D', RTGETOPT_REQ_NOTHING },
2963 { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated
2964 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
2965 { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated
2966 { "--log", 'l', RTGETOPT_REQ_UINT32 },
2967};
2968
2969RTEXITCODE handleShowVMInfo(HandlerArg *a)
2970{
2971 HRESULT rc;
2972 const char *VMNameOrUuid = NULL;
2973 bool fLog = false;
2974 uint32_t uLogIdx = 0;
2975 bool fDetails = false;
2976 bool fMachinereadable = false;
2977
2978 int c;
2979 RTGETOPTUNION ValueUnion;
2980 RTGETOPTSTATE GetState;
2981 // start at 0 because main() has hacked both the argc and argv given to us
2982 RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions),
2983 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2984 while ((c = RTGetOpt(&GetState, &ValueUnion)))
2985 {
2986 switch (c)
2987 {
2988 case 'D': // --details
2989 fDetails = true;
2990 break;
2991
2992 case 'M': // --machinereadable
2993 fMachinereadable = true;
2994 break;
2995
2996 case 'l': // --log
2997 fLog = true;
2998 uLogIdx = ValueUnion.u32;
2999 break;
3000
3001 case VINF_GETOPT_NOT_OPTION:
3002 if (!VMNameOrUuid)
3003 VMNameOrUuid = ValueUnion.psz;
3004 else
3005 return errorSyntax(USAGE_SHOWVMINFO, Info::tr("Invalid parameter '%s'"), ValueUnion.psz);
3006 break;
3007
3008 default:
3009 return errorGetOpt(USAGE_SHOWVMINFO, c, &ValueUnion);
3010 }
3011 }
3012
3013 /* check for required options */
3014 if (!VMNameOrUuid)
3015 return errorSyntax(USAGE_SHOWVMINFO, Info::tr("VM name or UUID required"));
3016
3017 /* try to find the given machine */
3018 ComPtr<IMachine> machine;
3019 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(),
3020 machine.asOutParam()));
3021 if (FAILED(rc))
3022 return RTEXITCODE_FAILURE;
3023
3024 /* Printing the log is exclusive. */
3025 if (fLog && (fMachinereadable || fDetails))
3026 return errorSyntax(USAGE_SHOWVMINFO, Info::tr("Option --log is exclusive"));
3027
3028 if (fLog)
3029 {
3030 ULONG64 uOffset = 0;
3031 SafeArray<BYTE> aLogData;
3032 size_t cbLogData;
3033 while (true)
3034 {
3035 /* Reset the array */
3036 aLogData.setNull();
3037 /* Fetch a chunk of the log file */
3038 CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, uOffset, _1M,
3039 ComSafeArrayAsOutParam(aLogData)));
3040 cbLogData = aLogData.size();
3041 if (cbLogData == 0)
3042 break;
3043 /* aLogData has a platform dependent line ending, standardize on
3044 * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
3045 * Windows. Otherwise we end up with CR/CR/LF on Windows. */
3046 size_t cbLogDataPrint = cbLogData;
3047 for (BYTE *s = aLogData.raw(), *d = s;
3048 s - aLogData.raw() < (ssize_t)cbLogData;
3049 s++, d++)
3050 {
3051 if (*s == '\r')
3052 {
3053 /* skip over CR, adjust destination */
3054 d--;
3055 cbLogDataPrint--;
3056 }
3057 else if (s != d)
3058 *d = *s;
3059 }
3060 RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint);
3061 uOffset += cbLogData;
3062 }
3063 }
3064 else
3065 {
3066 /* 2nd option can be -details or -argdump */
3067 VMINFO_DETAILS details = VMINFO_NONE;
3068 if (fMachinereadable)
3069 details = VMINFO_MACHINEREADABLE;
3070 else if (fDetails)
3071 details = VMINFO_FULL;
3072 else
3073 details = VMINFO_STANDARD;
3074
3075 /* open an existing session for the VM */
3076 rc = machine->LockMachine(a->session, LockType_Shared);
3077 if (SUCCEEDED(rc))
3078 /* get the session machine */
3079 rc = a->session->COMGETTER(Machine)(machine.asOutParam());
3080
3081 rc = showVMInfo(a->virtualBox, machine, a->session, details);
3082
3083 a->session->UnlockMachine();
3084 }
3085
3086 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
3087}
3088
3089#endif /* !VBOX_ONLY_DOCS */
3090/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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