VirtualBox

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

最後變更 在這個檔案從94394是 94394,由 vboxsync 提交於 3 年 前

Main/Machine+FE/Qt+VBoxManage/showvminfo: Attaching USB devices to a VM
when it isn't running should default to being marked as 'hot-pluggable'.
Further, attempts to remove the 'hot-pluggable' status of a USB device
via either the API or GUI should be impossible. Also update 'VBoxManage
showvminfo' to include the 'hot-pluggable' status of medium attachments
along with a few other IMediumAttachment attributes which were omitted
previously. bugref:8211

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

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