VirtualBox

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

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

spaces

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