VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/VBoxXPCOMC.cpp@ 49539

Last change on this file since 49539 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: 11.8 KB
Line 
1/* $Id: VBoxXPCOMC.cpp 49539 2013-11-18 16:52:10Z vboxsync $ */
2/** @file VBoxXPCOMC.cpp
3 * Utility functions to use with the C binding for XPCOM.
4 */
5
6/*
7 * Copyright (C) 2009-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN
19#include <nsMemory.h>
20#include <nsIServiceManager.h>
21#include <nsEventQueueUtils.h>
22#include <nsIExceptionService.h>
23
24#include <iprt/string.h>
25#include <iprt/env.h>
26#include <VBox/log.h>
27
28#include "VBoxCAPI.h"
29#include "VBox/com/com.h"
30#include "VBox/version.h"
31
32using namespace std;
33
34/* The following 3 object references should be eliminated once the legacy
35 * way to initialize the XPCOM C bindings is removed. */
36static ISession *g_Session = NULL;
37static IVirtualBox *g_VirtualBox = NULL;
38static nsIComponentManager *g_Manager = NULL;
39
40static nsIEventQueue *g_EventQueue = NULL;
41
42static void VBoxComUninitialize(void);
43static void VBoxClientUninitialize(void);
44
45static int
46VBoxUtf16ToUtf8(const PRUnichar *pwszString, char **ppszString)
47{
48 return RTUtf16ToUtf8(pwszString, ppszString);
49}
50
51static int
52VBoxUtf8ToUtf16(const char *pszString, PRUnichar **ppwszString)
53{
54 return RTStrToUtf16(pszString, ppwszString);
55}
56
57static void
58VBoxUtf16Free(PRUnichar *pwszString)
59{
60 RTUtf16Free(pwszString);
61}
62
63static void
64VBoxUtf8Free(char *pszString)
65{
66 RTStrFree(pszString);
67}
68
69static void
70VBoxComUnallocMem(void *ptr)
71{
72 if (ptr)
73 nsMemory::Free(ptr);
74}
75
76static void
77VBoxComInitialize(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
78 const char *pszSessionIID, ISession **ppSession)
79{
80 nsresult rc;
81 nsID virtualBoxIID;
82 nsID sessionIID;
83
84 *ppSession = NULL;
85 *ppVirtualBox = NULL;
86
87 /* convert the string representation of UUID to nsIID type */
88 if (!(virtualBoxIID.Parse(pszVirtualBoxIID) && sessionIID.Parse(pszSessionIID)))
89 return;
90
91 rc = com::Initialize();
92 if (NS_FAILED(rc))
93 {
94 Log(("Cbinding: XPCOM could not be initialized! rc=%Rhrc\n", rc));
95 VBoxComUninitialize();
96 return;
97 }
98
99 rc = NS_GetComponentManager(&g_Manager);
100 if (NS_FAILED(rc))
101 {
102 Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
103 VBoxComUninitialize();
104 return;
105 }
106
107 rc = NS_GetMainEventQ(&g_EventQueue);
108 if (NS_FAILED(rc))
109 {
110 Log(("Cbinding: Could not get xpcom event queue! rc=%Rhrc\n", rc));
111 VBoxComUninitialize();
112 return;
113 }
114
115 rc = g_Manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
116 nsnull,
117 virtualBoxIID,
118 (void **)&g_VirtualBox);
119 if (NS_FAILED(rc))
120 {
121 Log(("Cbinding: Could not instantiate VirtualBox object! rc=%Rhrc\n",rc));
122 VBoxComUninitialize();
123 return;
124 }
125
126 Log(("Cbinding: IVirtualBox object created.\n"));
127
128 rc = g_Manager->CreateInstanceByContractID(NS_SESSION_CONTRACTID,
129 nsnull,
130 sessionIID,
131 (void **)&g_Session);
132 if (NS_FAILED(rc))
133 {
134 Log(("Cbinding: Could not instantiate Session object! rc=%Rhrc\n",rc));
135 VBoxComUninitialize();
136 return;
137 }
138
139 Log(("Cbinding: ISession object created.\n"));
140
141 *ppSession = g_Session;
142 *ppVirtualBox = g_VirtualBox;
143}
144
145static void
146VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
147{
148 VBoxComInitialize(IVIRTUALBOX_IID_STR, ppVirtualBox,
149 ISESSION_IID_STR, ppSession);
150}
151
152static void
153VBoxComUninitialize(void)
154{
155 if (g_Session)
156 {
157 NS_RELEASE(g_Session);
158 g_Session = NULL;
159 }
160 if (g_VirtualBox)
161 {
162 NS_RELEASE(g_VirtualBox);
163 g_VirtualBox = NULL;
164 }
165 if (g_EventQueue)
166 {
167 NS_RELEASE(g_EventQueue);
168 g_EventQueue = NULL;
169 }
170 if (g_Manager)
171 {
172 NS_RELEASE(g_Manager);
173 g_Manager = NULL;
174 }
175 com::Shutdown();
176 Log(("Cbinding: Cleaned up the created objects.\n"));
177}
178
179static void
180VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
181{
182 *ppEventQueue = g_EventQueue;
183}
184
185static nsresult
186VBoxGetException(nsIException **ppException)
187{
188 nsresult rc;
189
190 *ppException = NULL;
191 nsIServiceManager *mgr = NULL;
192 rc = NS_GetServiceManager(&mgr);
193 if (NS_FAILED(rc) || !mgr)
194 return rc;
195
196 nsIID esid = NS_IEXCEPTIONSERVICE_IID;
197 nsIExceptionService *es = NULL;
198 rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
199 if (NS_FAILED(rc) || !es)
200 {
201 NS_RELEASE(mgr);
202 return rc;
203 }
204
205 nsIExceptionManager *em;
206 rc = es->GetCurrentExceptionManager(&em);
207 if (NS_FAILED(rc) || !em)
208 {
209 NS_RELEASE(es);
210 NS_RELEASE(mgr);
211 return rc;
212 }
213
214 nsIException *ex;
215 rc = em->GetCurrentException(&ex);
216 if (NS_FAILED(rc))
217 {
218 NS_RELEASE(em);
219 NS_RELEASE(es);
220 NS_RELEASE(mgr);
221 return rc;
222 }
223
224 *ppException = ex;
225 NS_RELEASE(em);
226 NS_RELEASE(es);
227 NS_RELEASE(mgr);
228 return rc;
229}
230
231static nsresult
232VBoxClearException(void)
233{
234 nsresult rc;
235
236 nsIServiceManager *mgr = NULL;
237 rc = NS_GetServiceManager(&mgr);
238 if (NS_FAILED(rc) || !mgr)
239 return rc;
240
241 nsIID esid = NS_IEXCEPTIONSERVICE_IID;
242 nsIExceptionService *es = NULL;
243 rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
244 if (NS_FAILED(rc) || !es)
245 {
246 NS_RELEASE(mgr);
247 return rc;
248 }
249
250 nsIExceptionManager *em;
251 rc = es->GetCurrentExceptionManager(&em);
252 if (NS_FAILED(rc) || !em)
253 {
254 NS_RELEASE(es);
255 NS_RELEASE(mgr);
256 return rc;
257 }
258
259 rc = em->SetCurrentException(NULL);
260 NS_RELEASE(em);
261 NS_RELEASE(es);
262 NS_RELEASE(mgr);
263 return rc;
264}
265
266static nsresult
267VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
268{
269 nsresult rc;
270 nsID virtualBoxClientIID;
271 nsID sessionIID;
272
273 *ppVirtualBoxClient = NULL;
274
275 /* convert the string representation of UUID to nsIID type */
276 if (!virtualBoxClientIID.Parse(pszVirtualBoxClientIID))
277 return NS_ERROR_INVALID_ARG;
278
279 rc = com::Initialize();
280 if (NS_FAILED(rc))
281 {
282 Log(("Cbinding: XPCOM could not be initialized! rc=%Rhrc\n", rc));
283 VBoxClientUninitialize();
284 return rc;
285 }
286
287 nsIComponentManager *pManager;
288 rc = NS_GetComponentManager(&pManager);
289 if (NS_FAILED(rc))
290 {
291 Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
292 VBoxClientUninitialize();
293 return rc;
294 }
295
296 rc = NS_GetMainEventQ(&g_EventQueue);
297 if (NS_FAILED(rc))
298 {
299 Log(("Cbinding: Could not get xpcom event queue! rc=%Rhrc\n", rc));
300 VBoxClientUninitialize();
301 return rc;
302 }
303
304 rc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
305 nsnull,
306 virtualBoxClientIID,
307 (void **)ppVirtualBoxClient);
308 if (NS_FAILED(rc))
309 {
310 Log(("Cbinding: Could not instantiate VirtualBoxClient object! rc=%Rhrc\n",rc));
311 VBoxClientUninitialize();
312 return rc;
313 }
314
315 NS_RELEASE(pManager);
316 pManager = NULL;
317
318 Log(("Cbinding: IVirtualBoxClient object created.\n"));
319
320 return NS_OK;
321}
322
323static void
324VBoxClientUninitialize(void)
325{
326 if (g_EventQueue)
327 {
328 NS_RELEASE(g_EventQueue);
329 g_EventQueue = NULL;
330 }
331 com::Shutdown();
332 Log(("Cbinding: Cleaned up the created objects.\n"));
333}
334
335static unsigned int
336VBoxVersion(void)
337{
338 return VBOX_VERSION_MAJOR * 1000 * 1000 + VBOX_VERSION_MINOR * 1000 + VBOX_VERSION_BUILD;
339}
340
341static unsigned int
342VBoxAPIVersion(void)
343{
344 return VBOX_VERSION_MAJOR * 1000 + VBOX_VERSION_MINOR + (VBOX_VERSION_BUILD > 50 ? 1 : 0);
345}
346
347VBOXXPCOMC_DECL(PCVBOXXPCOM)
348VBoxGetXPCOMCFunctions(unsigned uVersion)
349{
350 /*
351 * The current interface version.
352 */
353 static const VBOXXPCOMC s_Functions =
354 {
355 sizeof(VBOXXPCOMC),
356 VBOX_XPCOMC_VERSION,
357
358 VBoxVersion,
359 VBoxAPIVersion,
360
361 VBoxClientInitialize,
362 VBoxClientUninitialize,
363
364 VBoxComInitialize,
365 VBoxComUninitialize,
366
367 VBoxComUnallocMem,
368
369 VBoxUtf16ToUtf8,
370 VBoxUtf8ToUtf16,
371 VBoxUtf8Free,
372 VBoxUtf16Free,
373
374 VBoxGetEventQueue,
375 VBoxGetException,
376 VBoxClearException,
377
378 VBOX_XPCOMC_VERSION
379 };
380
381 if ((uVersion & 0xffff0000U) == (VBOX_XPCOMC_VERSION & 0xffff0000U))
382 return &s_Functions;
383
384 /*
385 * Legacy interface version 2.0.
386 */
387 static const struct VBOXXPCOMCV2
388 {
389 /** The size of the structure. */
390 unsigned cb;
391 /** The structure version. */
392 unsigned uVersion;
393
394 unsigned int (*pfnGetVersion)(void);
395
396 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
397 IVirtualBox **ppVirtualBox,
398 const char *pszSessionIID,
399 ISession **ppSession);
400
401 void (*pfnComUninitialize)(void);
402
403 void (*pfnComUnallocMem)(void *pv);
404 void (*pfnUtf16Free)(PRUnichar *pwszString);
405 void (*pfnUtf8Free)(char *pszString);
406
407 int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
408 int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
409
410 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
411
412 /** Tail version, same as uVersion. */
413 unsigned uEndVersion;
414 } s_Functions_v2_0 =
415 {
416 sizeof(s_Functions_v2_0),
417 0x00020000U,
418
419 VBoxVersion,
420
421 VBoxComInitialize,
422 VBoxComUninitialize,
423
424 VBoxComUnallocMem,
425 VBoxUtf16Free,
426 VBoxUtf8Free,
427
428 VBoxUtf16ToUtf8,
429 VBoxUtf8ToUtf16,
430
431 VBoxGetEventQueue,
432
433 0x00020000U
434 };
435
436 if ((uVersion & 0xffff0000U) == 0x00020000U)
437 return (PCVBOXXPCOM)&s_Functions_v2_0;
438
439 /*
440 * Legacy interface version 1.0.
441 */
442 static const struct VBOXXPCOMCV1
443 {
444 /** The size of the structure. */
445 unsigned cb;
446 /** The structure version. */
447 unsigned uVersion;
448
449 unsigned int (*pfnGetVersion)(void);
450
451 void (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
452 void (*pfnComUninitialize)(void);
453
454 void (*pfnComUnallocMem)(void *pv);
455 void (*pfnUtf16Free)(PRUnichar *pwszString);
456 void (*pfnUtf8Free)(char *pszString);
457
458 int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
459 int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
460
461 /** Tail version, same as uVersion. */
462 unsigned uEndVersion;
463 } s_Functions_v1_0 =
464 {
465 sizeof(s_Functions_v1_0),
466 0x00010000U,
467
468 VBoxVersion,
469
470 VBoxComInitializeV1,
471 VBoxComUninitialize,
472
473 VBoxComUnallocMem,
474 VBoxUtf16Free,
475 VBoxUtf8Free,
476
477 VBoxUtf16ToUtf8,
478 VBoxUtf8ToUtf16,
479
480 0x00010000U
481 };
482
483 if ((uVersion & 0xffff0000U) == 0x00010000U)
484 return (PCVBOXXPCOM)&s_Functions_v1_0;
485
486 /*
487 * Unsupported interface version.
488 */
489 return NULL;
490}
491
492/* 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