VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/tstXPCOMCEvent.c@ 48225

Last change on this file since 48225 was 48225, checked in by vboxsync, 11 years ago

testcase/*: move the installation path for the remaining API/XPCOM testcases to the tescase subdirectory
Main/cbinding: repair event listener testcase, various cleanups

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.9 KB
Line 
1/* $Revision: 48225 $ */
2/** @file tstXPCOMCEvent.c
3 * Demonstrator program to illustrate use of C bindings of Main API,
4 * and in particular how to handle active event listeners (event delivery
5 * through callbacks). The code is derived from tstXPCOMCGlue.c, so keep
6 * the diffs to the original code as small as possible.
7 *
8 * Linux only at the moment due to shared library magic in the Makefile.
9 */
10
11/*
12 * Copyright (C) 2009-2013 Oracle Corporation
13 *
14 * This file is part of VirtualBox Open Source Edition (OSE), as
15 * available from http://www.virtualbox.org. This file is free software;
16 * you can redistribute it and/or modify it under the terms of the GNU
17 * General Public License (GPL) as published by the Free Software
18 * Foundation, in version 2 as it comes in the "COPYING" file of the
19 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
20 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
21 */
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include "VBoxXPCOMCGlue.h"
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <signal.h>
32#include <sys/poll.h>
33
34/*******************************************************************************
35* Global Variables *
36*******************************************************************************/
37/** Set by signal handler. */
38static volatile int g_fStop = 0;
39
40int volatile g_refcount = 0;
41
42/* #define for printing nsID type UUID's */
43
44#define printUUID(iid) \
45{\
46 printf(#iid ": {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",\
47 (unsigned)(iid)->m0,\
48 (unsigned)(iid)->m1,\
49 (unsigned)(iid)->m2,\
50 (unsigned)(iid)->m3[0],\
51 (unsigned)(iid)->m3[1],\
52 (unsigned)(iid)->m3[2],\
53 (unsigned)(iid)->m3[3],\
54 (unsigned)(iid)->m3[4],\
55 (unsigned)(iid)->m3[5],\
56 (unsigned)(iid)->m3[6],\
57 (unsigned)(iid)->m3[7]);\
58}\
59
60static const char *GetStateName(PRUint32 machineState)
61{
62 switch (machineState)
63 {
64 case MachineState_Null: return "<null>";
65 case MachineState_PoweredOff: return "PoweredOff";
66 case MachineState_Saved: return "Saved";
67 case MachineState_Teleported: return "Teleported";
68 case MachineState_Aborted: return "Aborted";
69 case MachineState_Running: return "Running";
70 case MachineState_Paused: return "Paused";
71 case MachineState_Stuck: return "Stuck";
72 case MachineState_Teleporting: return "Teleporting";
73 case MachineState_LiveSnapshotting: return "LiveSnapshotting";
74 case MachineState_Starting: return "Starting";
75 case MachineState_Stopping: return "Stopping";
76 case MachineState_Saving: return "Saving";
77 case MachineState_Restoring: return "Restoring";
78 case MachineState_TeleportingPausedVM: return "TeleportingPausedVM";
79 case MachineState_TeleportingIn: return "TeleportingIn";
80 case MachineState_FaultTolerantSyncing: return "FaultTolerantSyncing";
81 case MachineState_DeletingSnapshotOnline: return "DeletingSnapshotOnline";
82 case MachineState_DeletingSnapshotPaused: return "DeletingSnapshotPaused";
83 case MachineState_RestoringSnapshot: return "RestoringSnapshot";
84 case MachineState_DeletingSnapshot: return "DeletingSnapshot";
85 case MachineState_SettingUp: return "SettingUp";
86 default: return "no idea";
87 }
88}
89
90/**
91 * Event handler function
92 */
93static nsresult HandleEvent(IEventListener *pThis, IEvent *event)
94{
95 enum VBoxEventType evType;
96 nsresult rc;
97
98 if (!event)
99 {
100 printf("event null\n");
101 return 0;
102 }
103
104 evType = VBoxEventType_Invalid;
105 rc = event->vtbl->GetType(event, &evType);
106 if (NS_FAILED(rc))
107 {
108 printf("cannot get event type, rc=%#x\n", rc);
109 return 0;
110 }
111
112 switch (evType)
113 {
114 case VBoxEventType_OnMousePointerShapeChanged:
115 printf("OnMousePointerShapeChanged\n");
116 break;
117
118 case VBoxEventType_OnMouseCapabilityChanged:
119 printf("OnMouseCapabilityChanged\n");
120 break;
121
122 case VBoxEventType_OnKeyboardLedsChanged:
123 printf("OnMouseCapabilityChanged\n");
124 break;
125
126 case VBoxEventType_OnStateChanged:
127 {
128 static const nsID istateChangedEventUUID = ISTATECHANGEDEVENT_IID;
129 IStateChangedEvent *ev = NULL;
130 enum MachineState state;
131 rc = event->vtbl->nsisupports.QueryInterface((nsISupports *)event, &istateChangedEventUUID, (void **)&ev);
132 if (NS_FAILED(rc))
133 {
134 printf("cannot get StateChangedEvent interface, rc=%#x\n", rc);
135 return 0;
136 }
137 if (!ev)
138 {
139 printf("StateChangedEvent reference null\n");
140 return 0;
141 }
142 rc = ev->vtbl->GetState(ev, &state);
143 if (NS_FAILED(rc))
144 printf("warning: cannot get state, rc=%#x\n", rc);
145 ev->vtbl->ievent.nsisupports.Release((nsISupports *)ev);
146 printf("OnStateChanged: %s\n", GetStateName(state));
147
148 fflush(stdout);
149 if ( state == MachineState_PoweredOff
150 || state == MachineState_Saved
151 || state == MachineState_Teleported
152 || state == MachineState_Aborted
153 )
154 g_fStop = 1;
155 break;
156 }
157
158 case VBoxEventType_OnAdditionsStateChanged:
159 printf("OnAdditionsStateChanged\n");
160 break;
161
162 case VBoxEventType_OnNetworkAdapterChanged:
163 printf("OnNetworkAdapterChanged\n");
164 break;
165
166 case VBoxEventType_OnSerialPortChanged:
167 printf("OnSerialPortChanged\n");
168 break;
169
170 case VBoxEventType_OnParallelPortChanged:
171 printf("OnParallelPortChanged\n");
172 break;
173
174 case VBoxEventType_OnStorageControllerChanged:
175 printf("OnStorageControllerChanged\n");
176 break;
177
178 case VBoxEventType_OnMediumChanged:
179 printf("OnMediumChanged\n");
180 break;
181
182 case VBoxEventType_OnVRDEServerChanged:
183 printf("OnVRDEServerChanged\n");
184 break;
185
186 case VBoxEventType_OnUSBControllerChanged:
187 printf("OnUSBControllerChanged\n");
188 break;
189
190 case VBoxEventType_OnUSBDeviceStateChanged:
191 printf("OnUSBDeviceStateChanged\n");
192 break;
193
194 case VBoxEventType_OnSharedFolderChanged:
195 printf("OnSharedFolderChanged\n");
196 break;
197
198 case VBoxEventType_OnRuntimeError:
199 printf("OnRuntimeError\n");
200 break;
201
202 case VBoxEventType_OnCanShowWindow:
203 printf("OnCanShowWindow\n");
204 break;
205
206 case VBoxEventType_OnShowWindow:
207 printf("OnShowWindow\n");
208 break;
209
210 default:
211 printf("unknown event: %d\n", evType);
212 }
213
214 return 0;
215}
216
217static nsresult AddRef(nsISupports *pThis)
218{
219 nsresult c;
220
221 c = ++g_refcount;
222 printf("AddRef: %d\n", c);
223 return c;
224}
225
226static nsresult Release(nsISupports *pThis)
227{
228 nsresult c;
229
230 c = --g_refcount;
231 printf("Release: %d\n", c);
232 if (c == 0)
233 {
234 /* delete object */
235 free(pThis->vtbl);
236 free(pThis);
237 }
238 return c;
239}
240
241static nsresult QueryInterface(nsISupports *pThis, const nsID *iid, void **resultp)
242{
243 static const nsID ieventListenerUUID = IEVENTLISTENER_IID;
244 static const nsID isupportIID = NS_ISUPPORTS_IID;
245
246 /* match iid */
247 if ( memcmp(iid, &ieventListenerUUID, sizeof(nsID)) == 0
248 || memcmp(iid, &isupportIID, sizeof(nsID)) == 0)
249 {
250 ++g_refcount;
251 printf("QueryInterface: %d\n", g_refcount);
252 *resultp = pThis;
253 return NS_OK;
254 }
255
256 /* printf("event listener QueryInterface didn't find a matching interface\n"); */
257 printUUID(iid);
258 printUUID(&ieventListenerUUID);
259 return NS_NOINTERFACE;
260}
261
262/**
263 * Signal handler, terminate event listener.
264 *
265 * @param iSig The signal number (ignored).
266 */
267static void sigIntHandler(int iSig)
268{
269 printf("sigIntHandler\n");
270 (void)iSig;
271 g_fStop = 1;
272}
273
274/**
275 * Register event listener for the selected VM.
276 *
277 * @param virtualBox ptr to IVirtualBox object
278 * @param session ptr to ISession object
279 * @param id identifies the machine to start
280 * @param queue handle to the event queue
281 */
282static void registerEventListener(IVirtualBox *virtualBox, ISession *session, PRUnichar *machineId, nsIEventQueue *queue)
283{
284 IConsole *console = NULL;
285 nsresult rc;
286
287 rc = session->vtbl->GetConsole(session, &console);
288 if ((NS_SUCCEEDED(rc)) && console)
289 {
290 IEventSource *es = NULL;
291 rc = console->vtbl->GetEventSource(console, &es);
292 if (NS_SUCCEEDED(rc) && es)
293 {
294 PRUint32 interestingEvents[] =
295 {
296 VBoxEventType_OnMousePointerShapeChanged,
297 VBoxEventType_OnMouseCapabilityChanged,
298 VBoxEventType_OnKeyboardLedsChanged,
299 VBoxEventType_OnStateChanged,
300 VBoxEventType_OnAdditionsStateChanged,
301 VBoxEventType_OnNetworkAdapterChanged,
302 VBoxEventType_OnSerialPortChanged,
303 VBoxEventType_OnParallelPortChanged,
304 VBoxEventType_OnStorageControllerChanged,
305 VBoxEventType_OnMediumChanged,
306 VBoxEventType_OnVRDEServerChanged,
307 VBoxEventType_OnUSBControllerChanged,
308 VBoxEventType_OnUSBDeviceStateChanged,
309 VBoxEventType_OnSharedFolderChanged,
310 VBoxEventType_OnRuntimeError,
311 VBoxEventType_OnCanShowWindow,
312 VBoxEventType_OnShowWindow
313 };
314 IEventListener *consoleListener = NULL;
315 consoleListener = calloc(1, sizeof(IEventListener));
316 consoleListener->vtbl = calloc(1, sizeof(struct IEventListener_vtbl));
317
318 if (consoleListener && consoleListener->vtbl)
319 {
320 consoleListener->vtbl->nsisupports.AddRef = &AddRef;
321 consoleListener->vtbl->nsisupports.Release = &Release;
322 consoleListener->vtbl->nsisupports.QueryInterface = &QueryInterface;
323 consoleListener->vtbl->HandleEvent = &HandleEvent;
324 g_refcount = 1;
325
326 rc = es->vtbl->RegisterListener(es, consoleListener,
327 sizeof(interestingEvents) / sizeof(interestingEvents[0]),
328 interestingEvents, 1 /* active */);
329 if (NS_SUCCEEDED(rc))
330 {
331 /* crude way to show how it works, but any
332 * great ideas anyone?
333 */
334 PRInt32 fd;
335 int ret;
336
337 printf("Entering event loop, PowerOff the machine to exit or press Ctrl-C to terminate\n");
338 fflush(stdout);
339 signal(SIGINT, sigIntHandler);
340
341 fd = queue->vtbl->GetEventQueueSelectFD(queue);
342 if (fd >= 0)
343 {
344 while (!g_fStop)
345 {
346 struct pollfd pfd;
347
348 pfd.fd = fd;
349 pfd.events = POLLIN | POLLERR | POLLHUP;
350 pfd.revents = 0;
351
352 ret = poll(&pfd, 1, 250);
353
354 if (ret <= 0)
355 continue;
356
357 if (pfd.revents & POLLHUP)
358 g_fStop = 1;
359
360 queue->vtbl->ProcessPendingEvents(queue);
361 }
362 }
363 else
364 {
365 while (!g_fStop)
366 {
367 PLEvent *pEvent = NULL;
368 rc = queue->vtbl->WaitForEvent(queue, &pEvent);
369 /*printf("event: %p rc=%x\n", (void *)pEvent, rc);*/
370 if (NS_SUCCEEDED(rc))
371 queue->vtbl->HandleEvent(queue, pEvent);
372 }
373 }
374 signal(SIGINT, SIG_DFL);
375 }
376 es->vtbl->UnregisterListener(es, consoleListener);
377 consoleListener->vtbl->nsisupports.Release((nsISupports *)consoleListener);
378 }
379 else
380 {
381 printf("Failed while allocating memory for console event listener.\n");
382 }
383 es->vtbl->nsisupports.Release((nsISupports *)es);
384 }
385 console->vtbl->nsisupports.Release((nsISupports *)console);
386 }
387}
388
389/**
390 * Start a VM.
391 *
392 * @param virtualBox ptr to IVirtualBox object
393 * @param session ptr to ISession object
394 * @param id identifies the machine to start
395 * @param queue handle to the event queue
396 */
397
398static void startVM(IVirtualBox *virtualBox, ISession *session, PRUnichar *id, nsIEventQueue *queue)
399{
400 nsresult rc;
401 IMachine *machine = NULL;
402 IProgress *progress = NULL;
403 PRUnichar *env = NULL;
404 PRUnichar *sessionType;
405
406 rc = virtualBox->vtbl->FindMachine(virtualBox, id, &machine);
407
408 if (NS_FAILED(rc) || !machine)
409 {
410 fprintf(stderr, "Error: Couldn't get the machine handle.\n");
411 return;
412 }
413
414 g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType);
415
416 rc = machine->vtbl->LaunchVMProcess(machine,
417 session,
418 sessionType,
419 env,
420 &progress
421 );
422
423 g_pVBoxFuncs->pfnUtf16Free(sessionType);
424
425 if (NS_FAILED(rc))
426 {
427 fprintf(stderr, "Error: OpenRemoteSession failed.\n");
428 }
429 else
430 {
431 PRBool completed;
432 PRInt32 resultCode;
433
434 printf("Waiting for the remote session to open...\n");
435 progress->vtbl->WaitForCompletion(progress, -1);
436
437 rc = progress->vtbl->GetCompleted(progress, &completed);
438 if (NS_FAILED(rc))
439 {
440 fprintf (stderr, "Error: GetCompleted status failed.\n");
441 }
442
443 progress->vtbl->GetResultCode(progress, &resultCode);
444 if (NS_FAILED(resultCode))
445 {
446 IVirtualBoxErrorInfo *errorInfo;
447 PRUnichar *textUtf16;
448 char *text;
449
450 progress->vtbl->GetErrorInfo(progress, &errorInfo);
451 errorInfo->vtbl->GetText(errorInfo, &textUtf16);
452 g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
453 printf("Error: %s\n", text);
454
455 g_pVBoxFuncs->pfnComUnallocMem(textUtf16);
456 g_pVBoxFuncs->pfnUtf8Free(text);
457 }
458 else
459 {
460 fprintf(stderr, "Remote session has been successfully opened.\n");
461 registerEventListener(virtualBox, session, id, queue);
462 }
463 progress->vtbl->nsisupports.Release((nsISupports *)progress);
464 }
465
466 /* It's important to always release resources. */
467 machine->vtbl->nsisupports.Release((nsISupports *)machine);
468}
469
470/**
471 * List the registered VMs.
472 *
473 * @param virtualBox ptr to IVirtualBox object
474 * @param session ptr to ISession object
475 * @param queue handle to the event queue
476 */
477static void listVMs(IVirtualBox *virtualBox, ISession *session, nsIEventQueue *queue)
478{
479 nsresult rc;
480 IMachine **machines = NULL;
481 PRUint32 machineCnt = 0;
482 PRUint32 i;
483 unsigned start_id;
484
485 /*
486 * Get the list of all registered VMs.
487 */
488
489 rc = virtualBox->vtbl->GetMachines(virtualBox, &machineCnt, &machines);
490 if (NS_FAILED(rc))
491 {
492 fprintf(stderr, "could not get list of machines, rc=%08x\n",
493 (unsigned)rc);
494 return;
495 }
496
497 if (machineCnt == 0)
498 {
499 printf("\tNo VMs\n");
500 return;
501 }
502
503 printf("VM List:\n\n");
504
505 /*
506 * Iterate through the collection.
507 */
508
509 for (i = 0; i < machineCnt; ++i)
510 {
511 IMachine *machine = machines[i];
512 PRBool isAccessible = PR_FALSE;
513
514 printf("\tMachine #%u\n", (unsigned)i);
515
516 if (!machine)
517 {
518 printf("\t(skipped, NULL)\n");
519 continue;
520 }
521
522 machine->vtbl->GetAccessible(machine, &isAccessible);
523
524 if (isAccessible)
525 {
526 PRUnichar *machineNameUtf16;
527 char *machineName;
528
529 machine->vtbl->GetName(machine, &machineNameUtf16);
530 g_pVBoxFuncs->pfnUtf16ToUtf8(machineNameUtf16,&machineName);
531 printf("\tName: %s\n", machineName);
532
533 g_pVBoxFuncs->pfnUtf8Free(machineName);
534 g_pVBoxFuncs->pfnComUnallocMem(machineNameUtf16);
535 }
536 else
537 {
538 printf("\tName: <inaccessible>\n");
539 }
540
541 {
542 PRUnichar *uuidUtf16 = NULL;
543 char *uuidUtf8 = NULL;
544
545 machine->vtbl->GetId(machine, &uuidUtf16);
546 g_pVBoxFuncs->pfnUtf16ToUtf8(uuidUtf16, &uuidUtf8);
547 printf("\tUUID: %s\n", uuidUtf8);
548
549 g_pVBoxFuncs->pfnUtf8Free(uuidUtf8);
550 g_pVBoxFuncs->pfnUtf16Free(uuidUtf16);
551 }
552
553 if (isAccessible)
554 {
555 {
556 PRUnichar *configFile;
557 char *configFile1 = calloc((size_t)64, (size_t)1);
558
559 machine->vtbl->GetSettingsFilePath(machine, &configFile);
560 g_pVBoxFuncs->pfnUtf16ToUtf8(configFile, &configFile1);
561 printf("\tConfig file: %s\n", configFile1);
562
563 free(configFile1);
564 g_pVBoxFuncs->pfnComUnallocMem(configFile);
565 }
566
567 {
568 PRUint32 memorySize;
569
570 machine->vtbl->GetMemorySize(machine, &memorySize);
571 printf("\tMemory size: %uMB\n", memorySize);
572 }
573
574 {
575 PRUnichar *typeId;
576 PRUnichar *osNameUtf16;
577 char *osName;
578 IGuestOSType *osType = NULL;
579
580 machine->vtbl->GetOSTypeId(machine, &typeId);
581 virtualBox->vtbl->GetGuestOSType(virtualBox, typeId, &osType);
582 osType->vtbl->GetDescription(osType, &osNameUtf16);
583 g_pVBoxFuncs->pfnUtf16ToUtf8(osNameUtf16,&osName);
584 printf("\tGuest OS: %s\n\n", osName);
585
586 osType->vtbl->nsisupports.Release((nsISupports *)osType);
587 g_pVBoxFuncs->pfnUtf8Free(osName);
588 g_pVBoxFuncs->pfnComUnallocMem(osNameUtf16);
589 g_pVBoxFuncs->pfnComUnallocMem(typeId);
590 }
591 }
592 }
593
594 /*
595 * Let the user chose a machine to start.
596 */
597
598 printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ",
599 (unsigned)(machineCnt - 1));
600 fflush(stdout);
601
602 if (scanf("%u", &start_id) == 1 && start_id < machineCnt)
603 {
604 IMachine *machine = machines[start_id];
605
606 if (machine)
607 {
608 PRUnichar *uuidUtf16 = NULL;
609
610 machine->vtbl->GetId(machine, &uuidUtf16);
611 startVM(virtualBox, session, uuidUtf16, queue);
612
613 g_pVBoxFuncs->pfnUtf16Free(uuidUtf16);
614 }
615 }
616
617 /*
618 * Don't forget to release the objects in the array.
619 */
620
621 for (i = 0; i < machineCnt; ++i)
622 {
623 IMachine *machine = machines[i];
624
625 if (machine)
626 {
627 machine->vtbl->nsisupports.Release((nsISupports *)machine);
628 }
629 }
630}
631
632/* Main - Start the ball rolling. */
633
634int main(int argc, char **argv)
635{
636 IVirtualBox *vbox = NULL;
637 ISession *session = NULL;
638 nsIEventQueue *queue = NULL;
639 PRUint32 revision = 0;
640 PRUnichar *versionUtf16 = NULL;
641 PRUnichar *homefolderUtf16 = NULL;
642 nsresult rc; /* Result code of various function (method) calls. */
643
644 printf("Starting Main\n");
645
646 /*
647 * VBoxComInitialize does all the necessary startup action and
648 * provides us with pointers to vbox and session handles.
649 * It should be matched by a call to VBoxComUninitialize(vbox)
650 * when done.
651 */
652
653 if (VBoxCGlueInit() != 0)
654 {
655 fprintf(stderr, "%s: FATAL: VBoxCGlueInit failed: %s\n",
656 argv[0], g_szVBoxErrMsg);
657 return EXIT_FAILURE;
658 }
659
660 g_pVBoxFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &vbox,
661 ISESSION_IID_STR, &session);
662 if (vbox == NULL)
663 {
664 fprintf(stderr, "%s: FATAL: could not get vbox handle\n", argv[0]);
665 return EXIT_FAILURE;
666 }
667 if (session == NULL)
668 {
669 fprintf(stderr, "%s: FATAL: could not get session handle\n", argv[0]);
670 return EXIT_FAILURE;
671 }
672 g_pVBoxFuncs->pfnGetEventQueue(&queue);
673 printf("Got the event queue: %p\n", (void *)queue);
674
675 /*
676 * Now ask for revision, version and home folder information of
677 * this vbox. Were not using fancy macros here so it
678 * remains easy to see how we access C++'s vtable.
679 */
680
681 printf("----------------------------------------------------\n");
682
683 /* 1. Revision */
684
685 rc = vbox->vtbl->GetRevision(vbox, &revision);
686 if (NS_SUCCEEDED(rc))
687 {
688 printf("\tRevision: %u\n", revision);
689 }
690 else
691 {
692 fprintf(stderr, "%s: GetRevision() returned %08x\n",
693 argv[0], (unsigned)rc);
694 }
695
696 /* 2. Version */
697
698 rc = vbox->vtbl->GetVersion(vbox, &versionUtf16);
699 if (NS_SUCCEEDED(rc))
700 {
701 char *version = NULL;
702 g_pVBoxFuncs->pfnUtf16ToUtf8(versionUtf16, &version);
703 printf("\tVersion: %s\n", version);
704 g_pVBoxFuncs->pfnUtf8Free(version);
705 g_pVBoxFuncs->pfnComUnallocMem(versionUtf16);
706 }
707 else
708 {
709 fprintf(stderr, "%s: GetVersion() returned %08x\n",
710 argv[0], (unsigned)rc);
711 }
712
713 /* 3. Home Folder */
714
715 rc = vbox->vtbl->GetHomeFolder(vbox, &homefolderUtf16);
716 if (NS_SUCCEEDED(rc))
717 {
718 char *homefolder = NULL;
719 g_pVBoxFuncs->pfnUtf16ToUtf8(homefolderUtf16, &homefolder);
720 printf("\tHomeFolder: %s\n", homefolder);
721 g_pVBoxFuncs->pfnUtf8Free(homefolder);
722 g_pVBoxFuncs->pfnComUnallocMem(homefolderUtf16);
723 }
724 else
725 {
726 fprintf(stderr, "%s: GetHomeFolder() returned %08x\n",
727 argv[0], (unsigned)rc);
728 }
729
730 listVMs(vbox, session, queue);
731 session->vtbl->UnlockMachine(session);
732
733 printf("----------------------------------------------------\n");
734
735 /*
736 * Do as mom told us: always clean up after yourself.
737 */
738
739 g_pVBoxFuncs->pfnComUninitialize();
740 VBoxCGlueTerm();
741 printf("Finished Main\n");
742
743 return 0;
744}
745/* vim: set ts=4 sw=4 et: */
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