VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageObjectTracker.cpp@ 107817

Last change on this file since 107817 was 107261, checked in by vboxsync, 2 months ago

bugref:10806. Invented the TrackedObjInfoShow structure. Adapted the handleObjInfo() code to match VirtualBox::getTrackedObject().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 KB
Line 
1/* $Id: VBoxManageObjectTracker.cpp 107261 2024-12-09 15:09:37Z vboxsync $ */
2/** @file
3 * VBoxManageObjectTracker - The object tracker related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include "VBoxManage.h"
29
30#include <map>
31#include <vector>
32#include <iprt/time.h>
33
34using namespace com;
35using namespace std;
36
37enum supIfaces_T
38{
39 None = 0,
40 kProgress = 1,
41 kSession,
42 kMedium,
43 kMachine,
44};
45
46std::map <com::Utf8Str, supIfaces_T> mapInterfaceNameToEnum = {
47 {"IProgress", kProgress},
48 {"ISession", kSession},
49 {"IMedium", kMedium},
50 {"IMachine", kMachine}
51};
52
53static void printProgressObjectInfo(const ComPtr<IProgress>& pObj);
54static void printSessionObjectInfo(const ComPtr<ISession>& pObj);
55static void printMediumObjectInfo(const ComPtr<IMedium>& pObj);
56static void printMachineObjectInfo(const ComPtr<IMachine>& pObj);
57
58static void makeTimeStr(char *s, int cb, int64_t millies)
59{
60 RTTIME t;
61 RTTIMESPEC ts;
62
63 RTTimeSpecSetMilli(&ts, millies);
64
65 RTTimeExplode(&t, &ts);
66
67 RTStrPrintf(s, cb, "%04d/%02d/%02d %02d:%02d:%02d UTC",
68 t.i32Year, t.u8Month, t.u8MonthDay,
69 t.u8Hour, t.u8Minute, t.u8Second);
70}
71
72static Utf8Str trackedObjectStateToStr(TrackedObjectState_T aState)
73{
74 Utf8Str strState("None");
75 switch (aState)
76 {
77 case TrackedObjectState_Alive:
78 strState = "Alive";
79 break;
80 case TrackedObjectState_Deleted:
81 strState = "Deleted";
82 break;
83 case TrackedObjectState_Invalid:
84 strState = "Invalid";
85 break;
86 case TrackedObjectState_None:
87 default:
88 strState = "None";
89 break;
90 }
91
92 return strState;
93}
94
95struct TrackedObjInfo_T
96{
97 ComPtr<IUnknown> pIUnknown;
98 TrackedObjectState_T enmState;
99 LONG64 creationTime;
100 LONG64 deletionTime;
101};
102
103struct TrackedObjInfoShow
104{
105 supIfaces_T m_iface;
106 Utf8Str m_id;
107 TrackedObjInfo_T m_objInfo;
108
109 TrackedObjInfoShow(Utf8Str aId, const TrackedObjInfo_T& aObjInfo, supIfaces_T aIface):
110 m_iface(aIface),
111 m_id(aId)
112 {
113 m_objInfo = aObjInfo;
114 }
115
116 TrackedObjInfoShow(supIfaces_T aIface): m_iface(aIface) {}
117
118 void setObjId(const Utf8Str& aId)
119 {
120 m_id = aId;
121 }
122
123 void setObjInfo(const TrackedObjInfo_T& aObjInfo)
124 {
125 m_objInfo = aObjInfo;
126 }
127
128 void show() const
129 {
130 RTPrintf(("\nTracked object id: %s\n"), m_id.c_str());
131
132 Utf8Str strState = trackedObjectStateToStr(m_objInfo.enmState);
133 RTPrintf((" State %s\n"), strState.c_str());
134
135 char szTimeValue[128];
136 makeTimeStr(szTimeValue, sizeof(szTimeValue), m_objInfo.creationTime);
137 RTPrintf((" Creation time %s\n"), szTimeValue);
138
139 if (m_objInfo.deletionTime != 0)
140 {
141 makeTimeStr(szTimeValue, sizeof(szTimeValue), m_objInfo.deletionTime);
142 RTPrintf((" Deletion time %s\n"), szTimeValue);
143 }
144
145 switch (m_iface)
146 {
147 case kProgress:
148 {
149 if (m_objInfo.enmState != TrackedObjectState_Invalid)
150 {
151 ComPtr<IProgress> pObj;
152 m_objInfo.pIUnknown->QueryInterface(IID_IProgress, (void **)pObj.asOutParam());
153 if (pObj.isNotNull())
154 printProgressObjectInfo(pObj);
155 }
156 break;
157 }
158 case kSession:
159 {
160 if (m_objInfo.enmState != TrackedObjectState_Invalid)
161 {
162 ComPtr<ISession> pObj;
163 m_objInfo.pIUnknown->QueryInterface(IID_ISession, (void **)pObj.asOutParam());
164 if (pObj.isNotNull())
165 printSessionObjectInfo(pObj);
166 }
167 break;
168 }
169 case kMedium:
170 {
171 if (m_objInfo.enmState != TrackedObjectState_Invalid)
172 {
173 ComPtr<IMedium> pObj;
174 m_objInfo.pIUnknown->QueryInterface(IID_IMedium, (void **)pObj.asOutParam());
175 if (pObj.isNotNull())
176 printMediumObjectInfo(pObj);
177 }
178 break;
179 }
180 case kMachine:
181 {
182 if (m_objInfo.enmState != TrackedObjectState_Invalid)
183 {
184 ComPtr<IMachine> pObj;
185 m_objInfo.pIUnknown->QueryInterface(IID_IMachine, (void **)pObj.asOutParam());
186 if(pObj.isNotNull())
187 printMachineObjectInfo(pObj);
188 }
189 break;
190 }
191 /* Impossible situation but to support the default case */
192 default:
193 RTPrintf("Interface isn't supported by object tracker at moment");
194 }
195 }
196};
197
198static void printProgressObjectInfo(const ComPtr<IProgress>& pObj)
199{
200 if (pObj.isNotNull())
201 {
202 RTPrintf(("Progress:\n"));
203 Bstr bStrAttr;
204 pObj->COMGETTER(Id)(bStrAttr.asOutParam());
205 RTPrintf((" Id %s\n"), Utf8Str(bStrAttr).c_str());
206
207 pObj->COMGETTER(Description)(bStrAttr.asOutParam());
208 RTPrintf((" Description %s\n"), Utf8Str(bStrAttr).c_str());
209
210 BOOL fBoolAttr;
211 pObj->COMGETTER(Completed)(&fBoolAttr);
212 RTPrintf((" Completed %s\n"), fBoolAttr ? "True" : "False");
213
214 pObj->COMGETTER(Canceled)(&fBoolAttr);
215 RTPrintf((" Canceled %s\n"), fBoolAttr ? "True" : "False");
216 }
217}
218
219static void printSessionObjectInfo(const ComPtr<ISession>& pObj)
220{
221 if (pObj.isNotNull())
222 {
223 RTPrintf(("Session:\n"));
224 Bstr bStrAttr;
225 pObj->COMGETTER(Name)(bStrAttr.asOutParam());
226 RTPrintf((" Name %s\n"), Utf8Str(bStrAttr).c_str());
227
228 SessionState_T enmState;
229 pObj->COMGETTER(State)(&enmState);
230 RTPrintf((" State %u\n"), enmState);
231
232 SessionType_T enmType;
233 pObj->COMGETTER(Type)(&enmType);
234 RTPrintf((" Type %u\n"), enmType);
235 }
236}
237
238static void printMediumObjectInfo(const ComPtr<IMedium>& pObj)
239{
240 if (pObj.isNotNull())
241 {
242 RTPrintf(("Medium:\n"));
243 Bstr bStrAttr;
244 pObj->COMGETTER(Id)(bStrAttr.asOutParam());
245 RTPrintf((" Medium Id %s\n"), Utf8Str(bStrAttr).c_str());
246
247 pObj->COMGETTER(Name)(bStrAttr.asOutParam());
248 RTPrintf((" Name %s\n"), Utf8Str(bStrAttr).c_str());
249
250 pObj->COMGETTER(Description)(bStrAttr.asOutParam());
251 RTPrintf((" Description %s\n"), Utf8Str(bStrAttr).c_str());
252
253 pObj->COMGETTER(Location)(bStrAttr.asOutParam());
254 RTPrintf((" Location %s\n"), Utf8Str(bStrAttr).c_str());
255
256 pObj->COMGETTER(Format)(bStrAttr.asOutParam());
257 RTPrintf((" Format %s\n"), Utf8Str(bStrAttr).c_str());
258
259 pObj->COMGETTER(LastAccessError)(bStrAttr.asOutParam());
260 RTPrintf((" LastAccessError %s\n"), Utf8Str(bStrAttr).c_str());
261
262 MediumState_T enmState;
263 pObj->RefreshState(&enmState);
264 /* check for accessibility */
265 const char *pszState = "unknown";
266 switch (enmState)
267 {
268 case MediumState_NotCreated:
269 pszState = "not created";
270 break;
271 case MediumState_Created:
272 pszState = "created";
273 break;
274 case MediumState_LockedRead:
275 pszState = "locked read";
276 break;
277 case MediumState_LockedWrite:
278 pszState = "locked write";
279 break;
280 case MediumState_Inaccessible:
281 pszState = "inaccessible";
282 break;
283 case MediumState_Creating:
284 pszState = "creating";
285 break;
286 case MediumState_Deleting:
287 pszState = "deleting";
288 break;
289#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
290 case MediumState_32BitHack: break; /* Shut up compiler warnings. */
291#endif
292 }
293 RTPrintf((" State %s\n"), pszState);
294
295 BOOL fBoolAttr;
296 pObj->COMGETTER(HostDrive)(&fBoolAttr);
297 RTPrintf((" HostDrive %s\n"), fBoolAttr ? "True" : "False");
298
299 LONG64 nLongIntAttr;
300 pObj->COMGETTER(LogicalSize)(&nLongIntAttr);
301 RTPrintf((" Logical Size (MB) %ld\n"), nLongIntAttr / _1M);
302
303 pObj->COMGETTER(Size)(&nLongIntAttr);
304 RTPrintf((" Real Size (MB) %ld\n"), nLongIntAttr / _1M);
305 }
306}
307
308static void printMachineObjectInfo(const ComPtr<IMachine>& pObj)
309{
310 if (pObj.isNotNull())
311 {
312 RTPrintf(("Machine:\n"));
313
314 Bstr bStrAttr;
315 pObj->COMGETTER(Name)(bStrAttr.asOutParam());
316 RTPrintf((" Name %s\n"), Utf8Str(bStrAttr).c_str());
317
318 BOOL fBoolAttr;
319 pObj->COMGETTER(Accessible)(&fBoolAttr);
320 RTPrintf((" Accessible %s\n"), fBoolAttr ? "True" : "False");
321
322 pObj->COMGETTER(Id)(bStrAttr.asOutParam());
323 RTPrintf((" Machine Id %s\n"), Utf8Str(bStrAttr).c_str());
324
325 pObj->COMGETTER(Description)(bStrAttr.asOutParam());
326 RTPrintf((" Description %s\n"), Utf8Str(bStrAttr).c_str());
327
328 pObj->COMGETTER(OSTypeId)(bStrAttr.asOutParam());
329 RTPrintf((" OSTypeId %s\n"), Utf8Str(bStrAttr).c_str());
330
331 pObj->COMGETTER(HardwareVersion)(bStrAttr.asOutParam());
332 RTPrintf((" HardwareVersion %s\n"), Utf8Str(bStrAttr).c_str());
333
334 pObj->COMGETTER(HardwareUUID)(bStrAttr.asOutParam());
335 RTPrintf((" HardwareUUID %s\n"), Utf8Str(bStrAttr).c_str());
336
337 pObj->COMGETTER(SnapshotFolder)(bStrAttr.asOutParam());
338 RTPrintf((" SnapshotFolder %s\n"), Utf8Str(bStrAttr).c_str());
339
340 pObj->COMGETTER(SettingsFilePath)(bStrAttr.asOutParam());
341 RTPrintf((" SettingsFilePath %s\n"), Utf8Str(bStrAttr).c_str());
342
343 pObj->COMGETTER(StateFilePath)(bStrAttr.asOutParam());
344 RTPrintf((" StateFilePath %s\n"), Utf8Str(bStrAttr).c_str());
345
346 pObj->COMGETTER(LogFolder)(bStrAttr.asOutParam());
347 RTPrintf((" LogFolder %s\n"), Utf8Str(bStrAttr).c_str());
348
349 ULONG nIntAttr;
350 pObj->COMGETTER(CPUCount)(&nIntAttr);
351 RTPrintf((" CPUCount %ld\n"), nIntAttr);
352
353 pObj->COMGETTER(MemorySize)(&nIntAttr);
354 RTPrintf((" Memory Size (MB) %ld\n"), nIntAttr);
355
356 MachineState_T enmState;
357 pObj->COMGETTER(State)(&enmState);
358 const char *pszState = machineStateToName(enmState, true);
359 RTPrintf((" State %s\n"), pszState);
360 }
361}
362
363void printTrackedObjectInfo(supIfaces_T aIface, const map < Bstr, TrackedObjInfo_T >& aObjMap)
364{
365 TrackedObjInfoShow trackedObjInfoShow(aIface);
366 for (const pair< const Bstr, TrackedObjInfo_T >& item : aObjMap)
367 {
368 trackedObjInfoShow.setObjId(Utf8Str(item.first));
369 trackedObjInfoShow.setObjInfo(item.second);
370 trackedObjInfoShow.show();
371 }
372
373}
374
375static RTEXITCODE handleObjInfo(HandlerArg *a, int iFirst)
376{
377 HRESULT hrc = S_OK;
378
379 static const RTGETOPTDEF s_aOptions[] =
380 {
381 { "--id", 'i', RTGETOPT_REQ_STRING },
382 { "--ifacename", 'f', RTGETOPT_REQ_STRING },
383 { "help", 'h', RTGETOPT_REQ_NOTHING },
384 { "--help", 'h', RTGETOPT_REQ_NOTHING }
385 };
386 RTGETOPTSTATE GetState;
387 RTGETOPTUNION ValueUnion;
388 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
389 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
390 if (a->argc == iFirst)
391 {
392 RTPrintf(("Empty command parameter list, show help.\n"));
393 printHelp(g_pStdOut);
394 return RTEXITCODE_SUCCESS;
395 }
396
397 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
398
399 Utf8Str strObjUuid;
400 Utf8Str strIfaceName;
401
402 int c;
403 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
404 {
405 switch (c)
406 {
407 case 'i':
408 {
409 if (strObjUuid.isNotEmpty())
410 return errorArgument("Duplicate parameter: --id");
411
412 strObjUuid = ValueUnion.psz;
413 if (strObjUuid.isEmpty())
414 return errorArgument("Empty parameter: --id");
415
416 break;
417 }
418 case 'f':
419 {
420 if (strIfaceName.isNotEmpty())
421 return errorArgument("Duplicate parameter: --ifacename");
422
423 strIfaceName = ValueUnion.psz;
424 if (strIfaceName.isEmpty())
425 return errorArgument("Empty parameter: --ifacename");
426
427 break;
428 }
429 case 'h':
430 printHelp(g_pStdOut);
431 return RTEXITCODE_SUCCESS;
432 case VINF_GETOPT_NOT_OPTION:
433 return errorUnknownSubcommand(ValueUnion.psz);
434
435 default:
436 return errorGetOpt(c, &ValueUnion);
437 }
438 }
439
440 map <com::Utf8Str, supIfaces_T>::const_iterator cIt = mapInterfaceNameToEnum.find(strIfaceName);
441 if (cIt != mapInterfaceNameToEnum.end())
442 {
443 supIfaces_T foundIface = cIt->second;
444 com::SafeArray<BSTR> ObjIDsList;
445 hrc = pVirtualBox->GetTrackedObjectIds(Bstr(cIt->first).raw(), ComSafeArrayAsOutParam(ObjIDsList));
446 if (SUCCEEDED(hrc))
447 {
448 map < Bstr, TrackedObjInfo_T > lObjInfoMap;
449
450 if (strObjUuid.isNotEmpty())
451 {
452 for (size_t i = 0; i < ObjIDsList.size(); ++i)
453 {
454 Bstr bstrObjId = ObjIDsList[i];
455 if (bstrObjId.equals(strObjUuid.c_str()))
456 {
457 TrackedObjInfo_T objInfo;
458 hrc = pVirtualBox->GetTrackedObject(bstrObjId.raw(),
459 objInfo.pIUnknown.asOutParam(),
460 &objInfo.enmState,
461 &objInfo.creationTime,
462 &objInfo.deletionTime);
463 lObjInfoMap[bstrObjId] = objInfo;
464 break;
465 }
466 }
467 }
468 else
469 {
470 for (size_t i = 0; i < ObjIDsList.size(); ++i)
471 {
472 Bstr bstrObjId = ObjIDsList[i];
473 TrackedObjInfo_T objInfo;
474 hrc = pVirtualBox->GetTrackedObject(bstrObjId.raw(),
475 objInfo.pIUnknown.asOutParam(),
476 &objInfo.enmState,
477 &objInfo.creationTime,
478 &objInfo.deletionTime);
479 if (SUCCEEDED(hrc))
480 lObjInfoMap[bstrObjId] = objInfo;
481 else
482 RTPrintf(("VirtualBox::getTrackedObject() returned the error 0x%LX\n"), hrc);
483 }
484 }
485
486 if (!lObjInfoMap.empty())
487 printTrackedObjectInfo(foundIface, lObjInfoMap);
488 else
489 RTPrintf(("Object with Id %s wasn't found\n"), strObjUuid.c_str());
490 }
491 else
492 RTPrintf(("VirtualBox::getTrackedObjectIds() returned the error 0x%LX\n"), hrc);
493 }
494 else
495 RTPrintf(("Interface %s isn't supported at present\n"), strIfaceName.c_str());
496
497 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
498}
499
500
501static RTEXITCODE handleSupIfaceList(HandlerArg *a, int iFirst)
502{
503 HRESULT hrc = S_OK;
504
505 static const RTGETOPTDEF s_aOptions[] =
506 {
507 { "help", 'h', RTGETOPT_REQ_NOTHING },
508 { "--help", 'h', RTGETOPT_REQ_NOTHING }
509 };
510 RTGETOPTSTATE GetState;
511 RTGETOPTUNION ValueUnion;
512 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
513 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
514
515 int c;
516 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
517 {
518 switch (c)
519 {
520 case 'h':
521 printHelp(g_pStdOut);
522 return RTEXITCODE_SUCCESS;
523 case VINF_GETOPT_NOT_OPTION:
524 return errorUnknownSubcommand(ValueUnion.psz);
525
526 default:
527 return errorGetOpt(c, &ValueUnion);
528 }
529 }
530
531 RTPrintf(("Supported interfaces:\n"));
532 for (pair<const com::Utf8Str, supIfaces_T>& item : mapInterfaceNameToEnum)
533 RTPrintf((" %s\n"), item.first.c_str());
534
535 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
536}
537
538static RTEXITCODE handleObjectList(HandlerArg *a, int iFirst)
539{
540 HRESULT hrc = S_OK;
541
542 static const RTGETOPTDEF s_aOptions[] =
543 {
544 { "--ifacename", 'f', RTGETOPT_REQ_STRING },
545 { "help", 'h', RTGETOPT_REQ_NOTHING },
546 { "--help", 'h', RTGETOPT_REQ_NOTHING }
547 };
548 RTGETOPTSTATE GetState;
549 RTGETOPTUNION ValueUnion;
550 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0);
551 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
552 if (a->argc == iFirst)
553 {
554 RTPrintf(("Empty command parameter list, show help.\n"));
555 printHelp(g_pStdOut);
556 return RTEXITCODE_SUCCESS;
557 }
558
559 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
560 Utf8Str strIfaceName;
561
562 int c;
563 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
564 {
565 switch (c)
566 {
567 case 'f':
568 {
569 if (strIfaceName.isNotEmpty())
570 return errorArgument("Duplicate parameter: --ifacename");
571
572 strIfaceName = ValueUnion.psz;
573 if (strIfaceName.isEmpty())
574 return errorArgument("Empty parameter: --ifacename");
575
576 break;
577 }
578 case 'h':
579 printHelp(g_pStdOut);
580 return RTEXITCODE_SUCCESS;
581 case VINF_GETOPT_NOT_OPTION:
582 return errorUnknownSubcommand(ValueUnion.psz);
583
584 default:
585 return errorGetOpt(c, &ValueUnion);
586 }
587 }
588
589 map <com::Utf8Str, supIfaces_T>::const_iterator cIt = mapInterfaceNameToEnum.find(strIfaceName);
590 if (cIt != mapInterfaceNameToEnum.end())
591 {
592 com::SafeArray<BSTR> ObjIDsList;
593 hrc = pVirtualBox->GetTrackedObjectIds(Bstr(strIfaceName).raw(), ComSafeArrayAsOutParam(ObjIDsList));
594 if (SUCCEEDED(hrc))
595 {
596 RTPrintf(("Tracked objects IIDs:\n"));
597 for (size_t i = 0; i < ObjIDsList.size(); ++i)
598 {
599 Bstr bstrObjId = ObjIDsList[i];
600 RTPrintf((" %s\n"), Utf8Str(bstrObjId).c_str());
601 }
602 }
603 }
604
605 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
606}
607
608RTEXITCODE handleTrackedObjects(HandlerArg *a)
609{
610 enum
611 {
612 kObjectTracker_Ifaces = 1000,
613 kObjectTracker_ObjList,
614 kObjectTracker_ObjInfo,
615 };
616
617 static const RTGETOPTDEF s_aOptions[] =
618 {
619 /* common options */
620 { "ifaces", kObjectTracker_Ifaces, RTGETOPT_REQ_NOTHING },
621 { "objlist", kObjectTracker_ObjList, RTGETOPT_REQ_NOTHING },
622 { "objinfo", kObjectTracker_ObjInfo, RTGETOPT_REQ_NOTHING },
623 };
624
625 if (a->argc < 1)
626 return errorNoSubcommand();
627
628 RTGETOPTSTATE GetState;
629 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
630 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
631
632 int c;
633 RTGETOPTUNION ValueUnion;
634 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
635 {
636 switch (c)
637 {
638 /* Sub-commands: */
639 case kObjectTracker_Ifaces:
640 setCurrentSubcommand(HELP_SCOPE_OBJTRACKER_IFACES);
641 return handleSupIfaceList(a, GetState.iNext);
642 case kObjectTracker_ObjList:
643 setCurrentSubcommand(HELP_SCOPE_OBJTRACKER_OBJLIST);
644 return handleObjectList(a, GetState.iNext);
645 case kObjectTracker_ObjInfo:
646 setCurrentSubcommand(HELP_SCOPE_OBJTRACKER_OBJINFO);
647 return handleObjInfo(a, GetState.iNext);
648 case VINF_GETOPT_NOT_OPTION:
649 return errorUnknownSubcommand(ValueUnion.psz);
650 default:
651 return errorGetOpt(c, &ValueUnion);
652 }
653 }
654
655 return errorNoSubcommand();
656}
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