VirtualBox

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

Last change on this file since 71679 was 70790, checked in by vboxsync, 7 years ago

VBoxManageInfo: potentially uninitialized variable due to missing error checking.

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