VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/tstXPCOMCGlue.c@ 49890

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

Main/cbinding: lots of love and care for this long forgotten part of the code, make it easier to use and more functional (error handling, initialization), and clean up and extend the sample code. It now includes the event sample, no need to keep so much redundant code.

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