VirtualBox

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

Last change on this file was 108566, checked in by vboxsync, 6 weeks ago

bugref:10806. Excluded Machine, Medium, Session support. Only Progress support.

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