VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/tstdlOpen.c@ 16867

Last change on this file since 16867 was 16838, checked in by vboxsync, 16 years ago

Fixed $Revision$ typo.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1/* $Revision: 16838 $ */
2/** @file tstdlOpen.c
3 * Demonstrator program to illustrate use of C bindings of Main API
4 * using dynamic linking (dlopen and friends).
5 */
6
7/*
8 * Copyright (C) 2009 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include <sys/stat.h>
27#include <dlfcn.h>
28#include "cbinding.h"
29
30static char *nsIDToString(nsID *guid);
31static void listVMs(IVirtualBox *virtualBox, ISession *session);
32static void startVM(IVirtualBox *virtualBox, ISession *session, nsID *id);
33
34void (*VBoxComInitializePtr)(IVirtualBox **virtualBox, ISession **session);
35void (*VBoxComUninitializePtr)(void);
36void (*VBoxComUnallocMemPtr)(void *ptr);
37void (*VBoxUtf16FreePtr)(PRUnichar *pwszString);
38void (*VBoxUtf8FreePtr)(char *pszString);
39int (*VBoxUtf16ToUtf8Ptr)(const PRUnichar *pwszString, char **ppszString);
40int (*VBoxUtf8ToUtf16Ptr)(const char *pszString, PRUnichar **ppwszString);
41const char * (*VBoxGetEnvPtr)(const char *pszVar);
42int (*VBoxSetEnvPtr)(const char *pszVar, const char *pszValue);
43
44/**
45 * Helper function to convert an nsID into a human readable string.
46 *
47 * @returns result string, allocated. Has to be freed using free()
48 * @param guid Pointer to nsID that will be converted.
49 */
50static char *nsIDToString(nsID *guid)
51{
52 /* Avoid magic number 39. Yes, sizeof "literal" includes the NUL byte. */
53 char *res = malloc(sizeof "{12345678-1234-1234-1234-123456789012}");
54
55 if (res != NULL)
56 {
57 sprintf(res, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
58 (unsigned)guid->m0, (unsigned)guid->m1, (unsigned)guid->m2,
59 (unsigned)guid->m3[0], (unsigned)guid->m3[1],
60 (unsigned)guid->m3[2], (unsigned)guid->m3[3],
61 (unsigned)guid->m3[4], (unsigned)guid->m3[5],
62 (unsigned)guid->m3[6], (unsigned)guid->m3[7]);
63 }
64 return res;
65}
66
67/**
68 * List the registered VMs.
69 *
70 * @param virtualBox ptr to IVirtualBox object
71 * @param session ptr to ISession object
72 */
73static void listVMs(IVirtualBox *virtualBox, ISession *session)
74{
75 nsresult rc;
76 IMachine **machines = NULL;
77 PRUint32 machineCnt = 0;
78 PRUint32 i;
79 unsigned start_id;
80
81 /*
82 * Get the list of all registered VMs.
83 */
84
85 rc = virtualBox->vtbl->GetMachines2(virtualBox, &machineCnt, &machines);
86 if (NS_FAILED(rc))
87 {
88 fprintf(stderr, "could not get list of machines, rc=%08x\n",
89 (unsigned)rc);
90 return;
91 }
92
93 if (machineCnt == 0)
94 {
95 printf("\tNo VMs\n");
96 return;
97 }
98
99 printf("VM List:\n\n");
100
101 /*
102 * Iterate through the collection.
103 */
104
105 for (i = 0; i < machineCnt; ++i)
106 {
107 IMachine *machine = machines[i];
108 PRBool isAccessible = PR_FALSE;
109
110 printf("\tMachine #%u\n", (unsigned)i);
111
112 if (!machine)
113 {
114 printf("\t(skipped, NULL)\n");
115 continue;
116 }
117
118 machine->vtbl->GetAccessible(machine, &isAccessible);
119
120 if (isAccessible)
121 {
122 PRUnichar *machineNameUtf16;
123 char *machineName;
124
125 machine->vtbl->GetName(machine, &machineNameUtf16);
126 VBoxUtf16ToUtf8Ptr(machineNameUtf16,&machineName);
127 printf("\tName: %s\n", machineName);
128
129 VBoxUtf8FreePtr(machineName);
130 VBoxComUnallocMemPtr(machineNameUtf16);
131 }
132 else
133 {
134 printf("\tName: <inaccessible>\n");
135 }
136
137
138 {
139 nsID *iid = NULL;
140 char *uuidString;
141
142 machine->vtbl->GetId(machine, &iid);
143 uuidString = nsIDToString(iid);
144 printf("\tUUID: %s\n", uuidString);
145
146 free(uuidString);
147 VBoxComUnallocMemPtr(iid);
148 }
149
150 if (isAccessible)
151 {
152 {
153 PRUnichar *configFile;
154 char *configFile1 = calloc((size_t)64, (size_t)1);
155
156 machine->vtbl->GetSettingsFilePath(machine, &configFile);
157 VBoxUtf16ToUtf8Ptr(configFile, &configFile1);
158 printf("\tConfig file: %s\n", configFile1);
159
160 free(configFile1);
161 VBoxComUnallocMemPtr(configFile);
162 }
163
164 {
165 PRUint32 memorySize;
166
167 machine->vtbl->GetMemorySize(machine, &memorySize);
168 printf("\tMemory size: %uMB\n", memorySize);
169 }
170
171 {
172 PRUnichar *typeId;
173 PRUnichar *osNameUtf16;
174 char *osName;
175 IGuestOSType *osType = NULL;
176
177 machine->vtbl->GetOSTypeId(machine, &typeId);
178 virtualBox->vtbl->GetGuestOSType(virtualBox, typeId, &osType);
179 osType->vtbl->GetDescription(osType, &osNameUtf16);
180 VBoxUtf16ToUtf8Ptr(osNameUtf16,&osName);
181 printf("\tGuest OS: %s\n\n", osName);
182
183 osType->vtbl->nsisupports.Release((void *)osType);
184 VBoxUtf8FreePtr(osName);
185 VBoxComUnallocMemPtr(osNameUtf16);
186 VBoxComUnallocMemPtr(typeId);
187 }
188 }
189 }
190
191 /*
192 * Let the user chose a machine to start.
193 */
194
195 printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ",
196 (unsigned)(machineCnt - 1));
197 fflush(stdout);
198
199 if (scanf("%u", &start_id) == 1 && start_id < machineCnt)
200 {
201 IMachine *machine = machines[start_id];
202
203 if (machine)
204 {
205 nsID *iid = NULL;
206
207 machine->vtbl->GetId(machine, &iid);
208 startVM(virtualBox, session, iid);
209
210 VBoxComUnallocMemPtr(iid);
211 }
212 }
213
214 /*
215 * Don't forget to release the objects in the array.
216 */
217
218 for (i = 0; i < machineCnt; ++i)
219 {
220 IMachine *machine = machines[i];
221
222 if (machine)
223 {
224 machine->vtbl->nsisupports.Release((void *)machine);
225 }
226 }
227}
228
229/**
230 * Start a VM.
231 *
232 * @param virtualBox ptr to IVirtualBox object
233 * @param session ptr to ISession object
234 * @param id identifies the machine to start
235 */
236static void startVM(IVirtualBox *virtualBox, ISession *session, nsID *id)
237{
238 nsresult rc;
239 IMachine *machine = NULL;
240 IProgress *progress = NULL;
241 PRUnichar *env = NULL;
242 PRUnichar *sessionType;
243
244 rc = virtualBox->vtbl->GetMachine(virtualBox, id, &machine);
245
246 if (NS_FAILED(rc) || !machine)
247 {
248 fprintf(stderr, "Error: Couldn't get the machine handle.\n");
249 return;
250 }
251
252 VBoxUtf8ToUtf16Ptr("gui", &sessionType);
253
254 rc = virtualBox->vtbl->OpenRemoteSession(
255 virtualBox,
256 session,
257 id,
258 sessionType,
259 env,
260 &progress
261 );
262
263 VBoxUtf16FreePtr(sessionType);
264
265 if (NS_FAILED(rc))
266 {
267 fprintf(stderr, "Error: OpenRemoteSession failed.\n");
268 }
269 else
270 {
271 PRBool completed;
272 nsresult resultCode;
273
274 printf("Waiting for the remote session to open...\n");
275 progress->vtbl->WaitForCompletion(progress, -1);
276
277 rc = progress->vtbl->GetCompleted(progress, &completed);
278 if (NS_FAILED(rc))
279 {
280 fprintf (stderr, "Error: GetCompleted status failed.\n");
281 }
282
283 progress->vtbl->GetResultCode(progress, &resultCode);
284 if (NS_FAILED(resultCode))
285 {
286 IVirtualBoxErrorInfo *errorInfo;
287 PRUnichar *textUtf16;
288 char *text;
289
290 progress->vtbl->GetErrorInfo(progress, &errorInfo);
291 errorInfo->vtbl->GetText(errorInfo, &textUtf16);
292 VBoxUtf16ToUtf8Ptr(textUtf16, &text);
293 printf("Error: %s\n", text);
294
295 VBoxComUnallocMemPtr(textUtf16);
296 VBoxUtf8FreePtr(text);
297 }
298 else
299 {
300 fprintf(stderr, "Remote session has been successfully opened.\n");
301 }
302 progress->vtbl->nsisupports.Release((void *)progress);
303 }
304
305 /* It's important to always release resources. */
306 machine->vtbl->nsisupports.Release((void *)machine);
307}
308
309#ifdef USE_DYNAMIC_GLUE
310/** The dlopen handle for VBoxXPCOM. */
311void *g_hVBoxXPCOMC = NULL;
312/** The last load error. */
313char g_szVBoxXPCOMErrMsg[256];
314
315#if defined(__linux__) || defined(__linux_gnu__) || defined(__sun__)
316# define SYM_PREFIX ""
317# define DYNLIB_NAME "VBoxXPCOMC.so"
318#elif defined(__APPLE__)
319# define SYM_PREFIX "_"
320# define DYNLIB_NAME "VBoxXPCOMC.dylib"
321#else
322# error "Port me"
323#endif
324
325/**
326 * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all
327 * the symbols we need.
328 *
329 * @returns 0 on success, -1 on failure.
330 * @param pszHome The director where to try load VBoxXPCOMC from. Can be NULL.
331 * @param pszMsgPrefix Error message prefix. NULL means no error messages.
332 */
333static int tryLoadOne(const char *pszHome, const char *pszMsgPrefix)
334{
335 static struct
336 {
337 const char *pszSymbol;
338 void **ppvSym;
339 } const s_aSyms[] =
340 {
341 { SYM_PREFIX "VBoxComInitialize", (void **)&VBoxComInitializePtr },
342 { SYM_PREFIX "VBoxComUninitialize", (void **)&VBoxComUninitializePtr },
343 { SYM_PREFIX "VBoxComUnallocMem", (void **)&VBoxComUnallocMemPtr },
344 { SYM_PREFIX "VBoxUtf16Free", (void **)&VBoxUtf16FreePtr },
345 { SYM_PREFIX "VBoxUtf8Free", (void **)&VBoxUtf8FreePtr },
346 { SYM_PREFIX "VBoxUtf16ToUtf8", (void **)&VBoxUtf16ToUtf8Ptr },
347 { SYM_PREFIX "VBoxUtf8ToUtf16", (void **)&VBoxUtf8ToUtf16Ptr },
348 { SYM_PREFIX "VBoxGetEnv", (void **)&VBoxGetEnvPtr },
349 { SYM_PREFIX "VBoxSetEnv", (void **)&VBoxSetEnvPtr }
350 };
351 size_t cchHome = pszHome ? strlen(pszHome) : 0;
352 size_t cbBuf;
353 char * pszBuf;
354 int rc = 0;
355
356 /*
357 * Construct the full name.
358 */
359
360 cbBuf = cchHome + sizeof("/" DYNLIB_NAME);
361 pszBuf = (char *)malloc(cbBuf);
362 if (!pszBuf)
363 {
364 sprintf(g_szVBoxXPCOMErrMsg, "malloc(%u) failed", (unsigned)cbBuf);
365 if (pszMsgPrefix)
366 fprintf(stderr, "%s%s\n", pszMsgPrefix, g_szVBoxXPCOMErrMsg);
367 return -1;
368 }
369 if (pszHome)
370 {
371 memcpy(pszBuf, pszHome, cchHome);
372 pszBuf[cchHome] = '/';
373 cchHome++;
374 }
375 memcpy(&pszBuf[cchHome], DYNLIB_NAME, sizeof(DYNLIB_NAME));
376
377 /*
378 * Try load it by that name, setting the VBOX_APP_HOME first (for now).
379 */
380
381 setenv("VBOX_APP_HOME", pszHome, 0 /* no need to overwrite */);
382 g_hVBoxXPCOMC = dlopen(pszBuf, RTLD_NOW | RTLD_LOCAL);
383 if (g_hVBoxXPCOMC)
384 {
385 unsigned i = sizeof(s_aSyms) / sizeof(s_aSyms[0]);
386 while (i-- > 0)
387 {
388 void *pv = dlsym(g_hVBoxXPCOMC, s_aSyms[i].pszSymbol);
389 if (!pv)
390 {
391 sprintf(g_szVBoxXPCOMErrMsg, "dlsym(%.80s/%.32s): %128s",
392 pszBuf, s_aSyms[i].pszSymbol, dlerror());
393 if (pszMsgPrefix)
394 fprintf(stderr, "%s%s\n", pszMsgPrefix, g_szVBoxXPCOMErrMsg);
395 rc = -1;
396 break;
397 }
398 *s_aSyms[i].ppvSym = pv;
399 }
400 }
401 else
402 {
403 sprintf(g_szVBoxXPCOMErrMsg, "dlopen(%.80s): %128s", pszBuf, dlerror());
404 rc = -1;
405 }
406 free(pszBuf);
407 return rc;
408}
409
410/**
411 * Tries to locate and load VBoxXPCOMC.so/dylib/dll, resolving all the related
412 * function pointers.
413 *
414 * @returns 0 on success, -1 on failure.
415 * @param pszMsgPrefix Error message prefix. NULL means no error messages.
416 *
417 * @remark This should be considered moved into a separate glue library since
418 * its its going to be pretty much the same for any user of VBoxXPCOMC
419 * and it will just cause trouble to have duplicate versions of this
420 * source code all around the place.
421 */
422static int tryLoad(const char *pszMsgPrefix)
423{
424 /*
425 * If the user specifies the location, try only that.
426 */
427
428 const char *pszHome = getenv("VBOX_APP_HOME");
429 if (pszHome)
430 return tryLoadOne(pszHome, pszMsgPrefix);
431
432 /*
433 * Try the known standard locations.
434 */
435
436#if defined(__gnu__linux__) || defined(__linux__)
437 if (tryLoadOne("/opt/VirtualBox", pszMsgPrefix) == 0)
438 return 0;
439 if (tryLoadOne("/usr/lib/virtualbox", pszMsgPrefix) == 0)
440 return 0;
441#elif defined(__sun__)
442 if (tryLoadOne("/opt/VirtualBox/amd64", pszMsgPrefix) == 0)
443 return 0;
444 if (tryLoadOne("/opt/VirtualBox/i386", pszMsgPrefix) == 0)
445 return 0;
446#elif defined(__APPLE__)
447 if (tryLoadOne("/Application/VirtualBox.app/Contents/MacOS", pszMsgPrefix) == 0)
448 return 0;
449#else
450# error "port me"
451#endif
452
453 /*
454 * Finally try the dynamic linker search path.
455 */
456
457 if (tryLoadOne(NULL, pszMsgPrefix) == 0)
458 return 0;
459
460 /* No luck, return failure. */
461 if (pszMsgPrefix)
462 fprintf(stderr, "%sFailed to locate VBoxXPCOMC\n", pszMsgPrefix);
463 return -1;
464}
465#endif
466
467
468/* Main - Start the ball rolling. */
469
470int main(int argc, char **argv)
471{
472 IVirtualBox *vbox = NULL;
473 ISession *session = NULL;
474 PRUint32 revision = 0;
475 PRUnichar *versionUtf16 = NULL;
476 PRUnichar *homefolderUtf16 = NULL;
477 nsresult rc; /* Result code of various function (method) calls. */
478#ifndef USE_DYNAMIC_GLUE
479 void *xpcomHandle = NULL;
480 const char *xpcomdlError = NULL;
481 struct stat stIgnored;
482
483 /*
484 * Guess where VirtualBox is installed not mentioned in the environment.
485 * (This will be moved to VBoxComInitialize later.)
486 */
487
488 if (stat("/opt/VirtualBox/VBoxXPCOMC.so", &stIgnored) == 0)
489 {
490 xpcomHandle = dlopen ("/opt/VirtualBox/VBoxXPCOMC.so", RTLD_NOW);
491 if (!xpcomHandle)
492 {
493 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],dlerror());
494 return EXIT_FAILURE;
495 }
496 *(void **) (&VBoxSetEnvPtr) = dlsym(xpcomHandle, "VBoxSetEnv");
497 if ((xpcomdlError = dlerror()) != NULL) {
498 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
499 return EXIT_FAILURE;
500 }
501 VBoxSetEnvPtr("VBOX_APP_HOME","/opt/VirtualBox/");
502 }
503 else if (stat("/usr/lib/virtualbox/VBoxXPCOMC.so", &stIgnored) == 0)
504 {
505 xpcomHandle = dlopen ("/usr/lib/virtualbox/VBoxXPCOMC.so", RTLD_NOW);
506 if (!xpcomHandle)
507 {
508 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],dlerror());
509 return EXIT_FAILURE;
510 }
511 *(void **) (&VBoxSetEnvPtr) = dlsym(xpcomHandle, "VBoxSetEnv");
512 if ((xpcomdlError = dlerror()) != NULL) {
513 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
514 return EXIT_FAILURE;
515 }
516 VBoxSetEnvPtr("VBOX_APP_HOME","/usr/lib/virtualbox/");
517 }
518#else
519 /*
520 * Initialize the dynamic linking glue.
521 */
522
523 if (tryLoad(NULL) != 0)
524 {
525 fprintf(stderr, "%s: FATAL: %s\n", argv[0], g_szVBoxXPCOMErrMsg);
526 return EXIT_FAILURE;
527 }
528#endif
529
530 printf("Starting Main\n");
531
532 /*
533 * VBoxComInitialize does all the necessary startup action and
534 * provides us with pointers to vbox and session handles.
535 * It should be matched by a call to VBoxComUninitialize(vbox)
536 * when done.
537 */
538
539#ifndef USE_DYNAMIC_GLUE
540 dlerror(); /* Clear any existing error */
541 *(void **) (&VBoxComInitializePtr) = dlsym(xpcomHandle, "VBoxComInitialize");
542 if ((xpcomdlError = dlerror()) != NULL) {
543 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
544 return EXIT_FAILURE;
545 }
546#endif
547 VBoxComInitializePtr(&vbox, &session);
548
549 if (vbox == NULL)
550 {
551 fprintf(stderr, "%s: FATAL: could not get vbox handle\n", argv[0]);
552 return EXIT_FAILURE;
553 }
554 if (session == NULL)
555 {
556 fprintf(stderr, "%s: FATAL: could not get session handle\n", argv[0]);
557 return EXIT_FAILURE;
558 }
559
560#ifndef USE_DYNAMIC_GLUE
561 *(void **) (&VBoxUtf16ToUtf8Ptr) = dlsym(xpcomHandle, "VBoxUtf16ToUtf8");
562 if ((xpcomdlError = dlerror()) != NULL) {
563 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
564 return EXIT_FAILURE;
565 }
566 *(void **) (&VBoxUtf8ToUtf16Ptr) = dlsym(xpcomHandle, "VBoxUtf8ToUtf16");
567 if ((xpcomdlError = dlerror()) != NULL) {
568 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
569 return EXIT_FAILURE;
570 }
571 *(void **) (&VBoxUtf8FreePtr) = dlsym(xpcomHandle, "VBoxUtf8Free");
572 if ((xpcomdlError = dlerror()) != NULL) {
573 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
574 return EXIT_FAILURE;
575 }
576 *(void **) (&VBoxUtf16FreePtr) = dlsym(xpcomHandle, "VBoxUtf16Free");
577 if ((xpcomdlError = dlerror()) != NULL) {
578 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
579 return EXIT_FAILURE;
580 }
581 *(void **) (&VBoxComUnallocMemPtr) = dlsym(xpcomHandle, "VBoxComUnallocMem");
582 if ((xpcomdlError = dlerror()) != NULL) {
583 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
584 return EXIT_FAILURE;
585 }
586#endif
587
588 /*
589 * Now ask for revision, version and home folder information of
590 * this vbox. Were not using fancy macros here so it
591 * remains easy to see how we access C++'s vtable.
592 */
593
594 printf("----------------------------------------------------\n");
595
596 /* 1. Revision */
597
598 rc = vbox->vtbl->GetRevision(vbox, &revision);
599 if (NS_SUCCEEDED(rc))
600 {
601 printf("\tRevision: %u\n", revision);
602 }
603 else
604 {
605 fprintf(stderr, "%s: GetRevision() returned %08x\n",
606 argv[0], (unsigned)rc);
607 }
608
609 /* 2. Version */
610
611 rc = vbox->vtbl->GetVersion(vbox, &versionUtf16);
612 if (NS_SUCCEEDED(rc))
613 {
614 char *version = NULL;
615 VBoxUtf16ToUtf8Ptr(versionUtf16, &version);
616 printf("\tVersion: %s\n", version);
617 VBoxUtf8FreePtr(version);
618 VBoxComUnallocMemPtr(versionUtf16);
619 }
620 else
621 {
622 fprintf(stderr, "%s: GetVersion() returned %08x\n",
623 argv[0], (unsigned)rc);
624 }
625
626 /* 3. Home Folder */
627
628 rc = vbox->vtbl->GetHomeFolder(vbox, &homefolderUtf16);
629 if (NS_SUCCEEDED(rc))
630 {
631 char *homefolder = NULL;
632 VBoxUtf16ToUtf8Ptr(homefolderUtf16, &homefolder);
633 printf("\tHomeFolder: %s\n", homefolder);
634 VBoxUtf8FreePtr(homefolder);
635 VBoxComUnallocMemPtr(homefolderUtf16);
636 }
637 else
638 {
639 fprintf(stderr, "%s: GetHomeFolder() returned %08x\n",
640 argv[0], (unsigned)rc);
641 }
642
643 listVMs(vbox, session);
644 session->vtbl->Close(session);
645
646 printf("----------------------------------------------------\n");
647
648 /*
649 * Do as mom told us: always clean up after yourself.
650 */
651
652#ifndef USE_DYNAMIC_GLUE
653 *(void **) (&VBoxComUninitializePtr) = dlsym(xpcomHandle, "VBoxComUninitialize");
654 if ((xpcomdlError = dlerror()) != NULL) {
655 fprintf(stderr, "%s: FATAL: could not open VBoxXPCOMC.so library: %s\n", argv[0],xpcomdlError);
656 return EXIT_FAILURE;
657 }
658#endif
659 VBoxComUninitializePtr();
660#ifndef USE_DYNAMIC_GLUE
661 dlclose(xpcomHandle);
662#else
663 dlclose(g_hVBoxXPCOMC);
664#endif
665 printf("Finished Main\n");
666
667 return 0;
668}
669/* 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