VirtualBox

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

Last change on this file since 72949 was 72919, checked in by vboxsync, 7 years ago

Main/*: From now on any valid UTF8 string is considered a valid guest OS type. Of course not all of them are known, so the API clients must be prepared to deal with not having a matching IGuestOSType object.
Frontends/VBoxManage+VBoxShell: adjust to deal with the change

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

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