VirtualBox

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

Last change on this file since 73041 was 72976, checked in by vboxsync, 6 years ago

VBoxManage: XPCOM/C++ enum exorcism. Found a enum type mismatch in handleCloneMedium and fixed it as best I could.

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