VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/tstXPCOMCCall.c@ 19169

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

cbinding: updated sample

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.4 KB
Line 
1/* $Revision: 19085 $ */
2/** @file tstXPCOMCGlue.c
3 * Demonstrator program to illustrate use of C bindings of Main API.
4 *
5 * Linux only at the moment due to shared library magic in the Makefile.
6 */
7
8/*
9 * Copyright (C) 2009 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include "VBoxXPCOMCGlue.h"
28#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31#include <unistd.h>
32
33static char *nsIDToString(nsID *guid);
34static void listVMs(IVirtualBox *virtualBox, ISession *session, nsIEventQueue *queue);
35static void registerCallBack(IVirtualBox *virtualBox, ISession *session, nsID *machineId, nsIEventQueue *queue);
36static void startVM(IVirtualBox *virtualBox, ISession *session, nsID *id, nsIEventQueue *queue);
37
38int volatile g_refcount = 0;
39
40/**
41 * Helper function to convert an nsID into a human readable string.
42 *
43 * @returns result string, allocated. Has to be freed using free()
44 * @param guid Pointer to nsID that will be converted.
45 */
46static char *nsIDToString(nsID *guid)
47{
48 /* Avoid magic number 39. Yes, sizeof "literal" includes the NUL byte. */
49 char *res = malloc(sizeof "{12345678-1234-1234-1234-123456789012}");
50
51 if (res != NULL)
52 {
53 sprintf(res, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
54 (unsigned)guid->m0, (unsigned)guid->m1, (unsigned)guid->m2,
55 (unsigned)guid->m3[0], (unsigned)guid->m3[1],
56 (unsigned)guid->m3[2], (unsigned)guid->m3[3],
57 (unsigned)guid->m3[4], (unsigned)guid->m3[5],
58 (unsigned)guid->m3[6], (unsigned)guid->m3[7]);
59 }
60 return res;
61}
62
63/**
64 * Callback functions
65 */
66static const char *GetStateName(PRUint32 machineState)
67{
68 switch (machineState)
69 {
70 case MachineState_Null: return "<null>";
71 case MachineState_PoweredOff: return "PoweredOff";
72 case MachineState_Saved: return "Saved";
73 case MachineState_Aborted: return "Aborted";
74 case MachineState_Running: return "Running";
75 case MachineState_Paused: return "Paused";
76 case MachineState_Stuck: return "Stuck";
77 case MachineState_Starting: return "Starting";
78 case MachineState_Stopping: return "Stopping";
79 case MachineState_Saving: return "Saving";
80 case MachineState_Restoring: return "Restoring";
81 case MachineState_Discarding: return "Discarding";
82 case MachineState_SettingUp: return "SettingUp";
83 default: return "no idea";
84 }
85}
86
87static nsresult OnMousePointerShapeChange(
88 IConsoleCallback *pThis,
89 PRBool visible,
90 PRBool alpha,
91 PRUint32 xHot,
92 PRUint32 yHot,
93 PRUint32 width,
94 PRUint32 height,
95 PRUint8 * shape
96) {
97 printf("OnMousePointerShapeChange\n");
98 return 0;
99}
100
101static nsresult OnMouseCapabilityChange(
102 IConsoleCallback *pThis,
103 PRBool supportsAbsolute,
104 PRBool needsHostCursor
105) {
106 printf("OnMouseCapabilityChange\n");
107 return 0;
108}
109
110static nsresult OnKeyboardLedsChange(
111 IConsoleCallback *pThis,
112 PRBool numLock,
113 PRBool capsLock,
114 PRBool scrollLock
115) {
116 printf("OnMouseCapabilityChange\n");
117 return 0;
118}
119
120static nsresult OnStateChange(
121 IConsoleCallback *pThis,
122 PRUint32 state
123) {
124 printf("OnStateChange: %s\n", GetStateName(state));
125 fflush(stdout);
126 return 0;
127}
128
129static nsresult OnAdditionsStateChange(IConsoleCallback *pThis )
130{
131 printf("OnAdditionsStateChange\n");
132 return 0;
133}
134
135static nsresult OnDVDDriveChange(IConsoleCallback *pThis )
136{
137 printf("OnDVDDriveChange \n");
138 return 0;
139}
140
141static nsresult OnFloppyDriveChange(IConsoleCallback *pThis )
142{
143 printf("OnFloppyDriveChange \n");
144 return 0;
145}
146
147static nsresult OnNetworkAdapterChange(
148 IConsoleCallback *pThis,
149 INetworkAdapter * networkAdapter
150) {
151 printf("OnNetworkAdapterChange\n");
152 return 0;
153}
154
155static nsresult OnSerialPortChange(
156 IConsoleCallback *pThis,
157 ISerialPort * serialPort
158) {
159 printf("OnSerialPortChange\n");
160 return 0;
161}
162
163static nsresult OnParallelPortChange(
164 IConsoleCallback *pThis,
165 IParallelPort * parallelPort
166) {
167 printf("OnParallelPortChange\n");
168 return 0;
169}
170
171static nsresult OnStorageControllerChange(IConsoleCallback *pThis )
172{
173 printf("OnStorageControllerChange\n");
174 return 0;
175}
176
177static nsresult OnVRDPServerChange(IConsoleCallback *pThis )
178{
179 printf("OnVRDPServerChange\n");
180 return 0;
181}
182
183static nsresult OnUSBControllerChange(IConsoleCallback *pThis )
184{
185 printf("OnUSBControllerChange\n");
186 return 0;
187}
188
189static nsresult OnUSBDeviceStateChange(
190 IConsoleCallback *pThis,
191 IUSBDevice * device,
192 PRBool attached,
193 IVirtualBoxErrorInfo * error
194) {
195 printf("OnUSBDeviceStateChange\n");
196 return 0;
197}
198
199static nsresult OnSharedFolderChange(
200 IConsoleCallback *pThis,
201 PRUint32 scope
202) {
203 printf("OnSharedFolderChange\n");
204 return 0;
205}
206
207static nsresult OnRuntimeError(
208 IConsoleCallback *pThis,
209 PRBool fatal,
210 PRUnichar * id,
211 PRUnichar * message
212) {
213 printf("OnRuntimeError\n");
214 return 0;
215}
216
217static nsresult OnCanShowWindow(
218 IConsoleCallback *pThis,
219 PRBool * canShow
220) {
221 printf("OnCanShowWindow\n");
222 return 0;
223}
224
225static nsresult OnShowWindow(
226 IConsoleCallback *pThis,
227 PRUint64 * winId
228) {
229 printf("OnShowWindow\n");
230 return 0;
231}
232
233
234static nsresult AddRef(nsISupports *pThis)
235{
236 nsresult c;
237
238 printf("AddRef\n");
239 c = g_refcount++;
240 return c;
241}
242
243static nsresult Release(nsISupports *pThis)
244{
245 nsresult c;
246 printf("Release\n");
247
248 c = g_refcount--;
249 if (c == 0)
250 {
251 /* delete object */
252 free(pThis->vtbl);
253 free(pThis);
254 }
255 return c;
256}
257
258static nsresult QueryInterface(nsISupports *pThis, const nsID *iid, void **resultp)
259{
260 IConsoleCallback *that = (IConsoleCallback *)pThis;
261
262 printf("QueryInterface\n");
263 /* match iid */
264 g_refcount++;
265 *resultp = that;
266 return 0;
267}
268
269/**
270 * Register callback functions for the selected VM.
271 *
272 * @param virtualBox ptr to IVirtualBox object
273 * @param session ptr to ISession object
274 * @param id identifies the machine to start
275 * @param queue handle to the event queue
276 */
277static void registerCallBack(IVirtualBox *virtualBox, ISession *session, nsID *machineId, nsIEventQueue *queue)
278{
279 IConsole *console = NULL;
280 nsresult rc;
281
282 rc = virtualBox->vtbl->OpenExistingSession(virtualBox, session, machineId);
283 session->vtbl->GetConsole(session, &console);
284 if (console) {
285 IConsoleCallback *consoleCallback = NULL;
286
287 consoleCallback = calloc(1, sizeof(IConsoleCallback));
288 consoleCallback->vtbl = calloc(1, sizeof(struct IConsoleCallback_vtbl));
289
290 if (consoleCallback && consoleCallback->vtbl) {
291
292 consoleCallback->vtbl->nsisupports.AddRef = &AddRef;
293 consoleCallback->vtbl->nsisupports.Release = &Release;
294 consoleCallback->vtbl->nsisupports.QueryInterface = &QueryInterface;
295 consoleCallback->vtbl->OnMousePointerShapeChange = &OnMousePointerShapeChange;
296 consoleCallback->vtbl->OnMouseCapabilityChange = &OnMouseCapabilityChange;
297 consoleCallback->vtbl->OnKeyboardLedsChange =&OnKeyboardLedsChange;
298 consoleCallback->vtbl->OnStateChange = &OnStateChange;
299 consoleCallback->vtbl->OnAdditionsStateChange = &OnAdditionsStateChange;
300 consoleCallback->vtbl->OnDVDDriveChange = &OnDVDDriveChange;
301 consoleCallback->vtbl->OnFloppyDriveChange = &OnFloppyDriveChange;
302 consoleCallback->vtbl->OnNetworkAdapterChange = &OnNetworkAdapterChange;
303 consoleCallback->vtbl->OnSerialPortChange = &OnSerialPortChange;
304 consoleCallback->vtbl->OnParallelPortChange = &OnParallelPortChange;
305 consoleCallback->vtbl->OnStorageControllerChange = &OnStorageControllerChange;
306 consoleCallback->vtbl->OnVRDPServerChange = &OnVRDPServerChange;
307 consoleCallback->vtbl->OnUSBControllerChange = &OnUSBControllerChange;
308 consoleCallback->vtbl->OnUSBDeviceStateChange = &OnUSBDeviceStateChange;
309 consoleCallback->vtbl->OnSharedFolderChange = &OnSharedFolderChange;
310 consoleCallback->vtbl->OnRuntimeError = &OnRuntimeError;
311 consoleCallback->vtbl->OnCanShowWindow = &OnCanShowWindow;
312 consoleCallback->vtbl->OnShowWindow = &OnShowWindow;
313 g_refcount = 1;
314
315 console->vtbl->RegisterCallback(console, consoleCallback);
316
317 {
318 /* crude way to show how it works, but any
319 * great ideas anyone?
320 */
321 int run = 10000000;
322 while (run-- > 0) {
323 queue->vtbl->ProcessPendingEvents(queue);
324 }
325 }
326 console->vtbl->UnregisterCallback(console, consoleCallback);
327 }
328 consoleCallback->vtbl->nsisupports.Release((nsISupports *)consoleCallback);
329 }
330 session->vtbl->Close((void *)session);
331}
332
333/**
334 * List the registered VMs.
335 *
336 * @param virtualBox ptr to IVirtualBox object
337 * @param session ptr to ISession object
338 * @param queue handle to the event queue
339 */
340static void listVMs(IVirtualBox *virtualBox, ISession *session, nsIEventQueue *queue)
341{
342 nsresult rc;
343 IMachine **machines = NULL;
344 PRUint32 machineCnt = 0;
345 PRUint32 i;
346 unsigned start_id;
347
348 /*
349 * Get the list of all registered VMs.
350 */
351
352 rc = virtualBox->vtbl->GetMachines(virtualBox, &machineCnt, &machines);
353 if (NS_FAILED(rc))
354 {
355 fprintf(stderr, "could not get list of machines, rc=%08x\n",
356 (unsigned)rc);
357 return;
358 }
359
360 if (machineCnt == 0)
361 {
362 printf("\tNo VMs\n");
363 return;
364 }
365
366 printf("VM List:\n\n");
367
368 /*
369 * Iterate through the collection.
370 */
371
372 for (i = 0; i < machineCnt; ++i)
373 {
374 IMachine *machine = machines[i];
375 PRBool isAccessible = PR_FALSE;
376
377 printf("\tMachine #%u\n", (unsigned)i);
378
379 if (!machine)
380 {
381 printf("\t(skipped, NULL)\n");
382 continue;
383 }
384
385 machine->vtbl->GetAccessible(machine, &isAccessible);
386
387 if (isAccessible)
388 {
389 PRUnichar *machineNameUtf16;
390 char *machineName;
391
392 machine->vtbl->GetName(machine, &machineNameUtf16);
393 g_pVBoxFuncs->pfnUtf16ToUtf8(machineNameUtf16,&machineName);
394 printf("\tName: %s\n", machineName);
395
396 g_pVBoxFuncs->pfnUtf8Free(machineName);
397 g_pVBoxFuncs->pfnComUnallocMem(machineNameUtf16);
398 }
399 else
400 {
401 printf("\tName: <inaccessible>\n");
402 }
403
404
405 {
406 nsID *iid = NULL;
407 char *uuidString;
408
409 machine->vtbl->GetId(machine, &iid);
410 uuidString = nsIDToString(iid);
411 printf("\tUUID: %s\n", uuidString);
412
413 free(uuidString);
414 g_pVBoxFuncs->pfnComUnallocMem(iid);
415 }
416
417 if (isAccessible)
418 {
419 {
420 PRUnichar *configFile;
421 char *configFile1 = calloc((size_t)64, (size_t)1);
422
423 machine->vtbl->GetSettingsFilePath(machine, &configFile);
424 g_pVBoxFuncs->pfnUtf16ToUtf8(configFile, &configFile1);
425 printf("\tConfig file: %s\n", configFile1);
426
427 free(configFile1);
428 g_pVBoxFuncs->pfnComUnallocMem(configFile);
429 }
430
431 {
432 PRUint32 memorySize;
433
434 machine->vtbl->GetMemorySize(machine, &memorySize);
435 printf("\tMemory size: %uMB\n", memorySize);
436 }
437
438 {
439 PRUnichar *typeId;
440 PRUnichar *osNameUtf16;
441 char *osName;
442 IGuestOSType *osType = NULL;
443
444 machine->vtbl->GetOSTypeId(machine, &typeId);
445 virtualBox->vtbl->GetGuestOSType(virtualBox, typeId, &osType);
446 osType->vtbl->GetDescription(osType, &osNameUtf16);
447 g_pVBoxFuncs->pfnUtf16ToUtf8(osNameUtf16,&osName);
448 printf("\tGuest OS: %s\n\n", osName);
449
450 osType->vtbl->nsisupports.Release((void *)osType);
451 g_pVBoxFuncs->pfnUtf8Free(osName);
452 g_pVBoxFuncs->pfnComUnallocMem(osNameUtf16);
453 g_pVBoxFuncs->pfnComUnallocMem(typeId);
454 }
455 }
456 }
457
458 /*
459 * Let the user chose a machine to start.
460 */
461
462 printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ",
463 (unsigned)(machineCnt - 1));
464 fflush(stdout);
465
466 if (scanf("%u", &start_id) == 1 && start_id < machineCnt)
467 {
468 IMachine *machine = machines[start_id];
469
470 if (machine)
471 {
472 nsID *iid = NULL;
473
474 machine->vtbl->GetId(machine, &iid);
475 startVM(virtualBox, session, iid, queue);
476
477 g_pVBoxFuncs->pfnComUnallocMem(iid);
478 }
479 }
480
481 /*
482 * Don't forget to release the objects in the array.
483 */
484
485 for (i = 0; i < machineCnt; ++i)
486 {
487 IMachine *machine = machines[i];
488
489 if (machine)
490 {
491 machine->vtbl->nsisupports.Release((nsISupports *)machine);
492 }
493 }
494}
495
496/**
497 * Start a VM.
498 *
499 * @param virtualBox ptr to IVirtualBox object
500 * @param session ptr to ISession object
501 * @param id identifies the machine to start
502 * @param queue handle to the event queue
503 */
504
505static void startVM(IVirtualBox *virtualBox, ISession *session, nsID *id, nsIEventQueue *queue)
506{
507 nsresult rc;
508 IMachine *machine = NULL;
509 IProgress *progress = NULL;
510 PRUnichar *env = NULL;
511 PRUnichar *sessionType;
512
513 rc = virtualBox->vtbl->GetMachine(virtualBox, id, &machine);
514
515 if (NS_FAILED(rc) || !machine)
516 {
517 fprintf(stderr, "Error: Couldn't get the machine handle.\n");
518 return;
519 }
520
521 g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType);
522
523 rc = virtualBox->vtbl->OpenRemoteSession(
524 virtualBox,
525 session,
526 id,
527 sessionType,
528 env,
529 &progress
530 );
531
532 g_pVBoxFuncs->pfnUtf16Free(sessionType);
533
534 if (NS_FAILED(rc))
535 {
536 fprintf(stderr, "Error: OpenRemoteSession failed.\n");
537 }
538 else
539 {
540 PRBool completed;
541 nsresult resultCode;
542
543 printf("Waiting for the remote session to open...\n");
544 progress->vtbl->WaitForCompletion(progress, -1);
545
546 rc = progress->vtbl->GetCompleted(progress, &completed);
547 if (NS_FAILED(rc))
548 {
549 fprintf (stderr, "Error: GetCompleted status failed.\n");
550 }
551
552 progress->vtbl->GetResultCode(progress, &resultCode);
553 if (NS_FAILED(resultCode))
554 {
555 IVirtualBoxErrorInfo *errorInfo;
556 PRUnichar *textUtf16;
557 char *text;
558
559 progress->vtbl->GetErrorInfo(progress, &errorInfo);
560 errorInfo->vtbl->GetText(errorInfo, &textUtf16);
561 g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text);
562 printf("Error: %s\n", text);
563
564 g_pVBoxFuncs->pfnComUnallocMem(textUtf16);
565 g_pVBoxFuncs->pfnUtf8Free(text);
566 }
567 else
568 {
569 fprintf(stderr, "Remote session has been successfully opened.\n");
570 registerCallBack(virtualBox, session, id, queue);
571 }
572 progress->vtbl->nsisupports.Release((void *)progress);
573 }
574
575 /* It's important to always release resources. */
576 machine->vtbl->nsisupports.Release((void *)machine);
577}
578
579/* Main - Start the ball rolling. */
580
581int main(int argc, char **argv)
582{
583 IVirtualBox *vbox = NULL;
584 ISession *session = NULL;
585 nsIEventQueue *queue = NULL;
586 PRUint32 revision = 0;
587 PRUnichar *versionUtf16 = NULL;
588 PRUnichar *homefolderUtf16 = NULL;
589 nsresult rc; /* Result code of various function (method) calls. */
590
591 printf("Starting Main\n");
592
593 /*
594 * VBoxComInitialize does all the necessary startup action and
595 * provides us with pointers to vbox and session handles.
596 * It should be matched by a call to VBoxComUninitialize(vbox)
597 * when done.
598 */
599
600 if (VBoxCGlueInit() != 0)
601 {
602 fprintf(stderr, "%s: FATAL: VBoxCGlueInit failed: %s\n",
603 argv[0], g_szVBoxErrMsg);
604 return EXIT_FAILURE;
605 }
606
607 g_pVBoxFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &vbox,
608 ISESSION_IID_STR, &session);
609 if (vbox == NULL)
610 {
611 fprintf(stderr, "%s: FATAL: could not get vbox handle\n", argv[0]);
612 return EXIT_FAILURE;
613 }
614 if (session == NULL)
615 {
616 fprintf(stderr, "%s: FATAL: could not get session handle\n", argv[0]);
617 return EXIT_FAILURE;
618 }
619 g_pVBoxFuncs->pfnGetEventQueue(&queue);
620 printf("Got the event queue: %p\n", queue);
621
622 /*
623 * Now ask for revision, version and home folder information of
624 * this vbox. Were not using fancy macros here so it
625 * remains easy to see how we access C++'s vtable.
626 */
627
628 printf("----------------------------------------------------\n");
629
630 /* 1. Revision */
631
632 rc = vbox->vtbl->GetRevision(vbox, &revision);
633 if (NS_SUCCEEDED(rc))
634 {
635 printf("\tRevision: %u\n", revision);
636 }
637 else
638 {
639 fprintf(stderr, "%s: GetRevision() returned %08x\n",
640 argv[0], (unsigned)rc);
641 }
642
643 /* 2. Version */
644
645 rc = vbox->vtbl->GetVersion(vbox, &versionUtf16);
646 if (NS_SUCCEEDED(rc))
647 {
648 char *version = NULL;
649 g_pVBoxFuncs->pfnUtf16ToUtf8(versionUtf16, &version);
650 printf("\tVersion: %s\n", version);
651 g_pVBoxFuncs->pfnUtf8Free(version);
652 g_pVBoxFuncs->pfnComUnallocMem(versionUtf16);
653 }
654 else
655 {
656 fprintf(stderr, "%s: GetVersion() returned %08x\n",
657 argv[0], (unsigned)rc);
658 }
659
660 /* 3. Home Folder */
661
662 rc = vbox->vtbl->GetHomeFolder(vbox, &homefolderUtf16);
663 if (NS_SUCCEEDED(rc))
664 {
665 char *homefolder = NULL;
666 g_pVBoxFuncs->pfnUtf16ToUtf8(homefolderUtf16, &homefolder);
667 printf("\tHomeFolder: %s\n", homefolder);
668 g_pVBoxFuncs->pfnUtf8Free(homefolder);
669 g_pVBoxFuncs->pfnComUnallocMem(homefolderUtf16);
670 }
671 else
672 {
673 fprintf(stderr, "%s: GetHomeFolder() returned %08x\n",
674 argv[0], (unsigned)rc);
675 }
676
677 listVMs(vbox, session, queue);
678 session->vtbl->Close(session);
679
680 printf("----------------------------------------------------\n");
681
682 /*
683 * Do as mom told us: always clean up after yourself.
684 */
685
686 g_pVBoxFuncs->pfnComUninitialize();
687 VBoxCGlueTerm();
688 printf("Finished Main\n");
689
690 return 0;
691}
692/* 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