VirtualBox

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

Last change on this file since 77910 was 77910, checked in by vboxsync, 5 years ago

Main: bugref:7929: Added ability to change the priority of the VM process

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

© 2023 Oracle
ContactPrivacy policyTerms of Use