VirtualBox

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

Last change on this file since 76393 was 76366, checked in by vboxsync, 6 years ago

include/VBox/com/Guid.h: Don't include iprt/err.h for no good reason. bugref:9344

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

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