VirtualBox

source: vbox/trunk/src/VBox/Main/cbinding/VBoxCAPI.cpp@ 62514

Last change on this file since 62514 was 60063, checked in by vboxsync, 9 years ago

Frontends etc: convert more code to use VirtualBoxClient instead of direct creation of VirtualBox instances, to improve error handling

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.3 KB
Line 
1/* $Id: VBoxCAPI.cpp 60063 2016-03-16 15:00:06Z vboxsync $ */
2/** @file VBoxCAPI.cpp
3 * Utility functions to use with the C API binding.
4 */
5
6/*
7 * Copyright (C) 2009-2016 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
20#include "VBoxCAPI.h"
21
22#ifdef VBOX_WITH_XPCOM
23# include <nsMemory.h>
24# include <nsIServiceManager.h>
25# include <nsEventQueueUtils.h>
26# include <nsIExceptionService.h>
27# include <stdlib.h>
28#endif /* VBOX_WITH_XPCOM */
29
30#include <iprt/initterm.h>
31#include <iprt/string.h>
32#include <iprt/uuid.h>
33#include <iprt/env.h>
34#include <iprt/mem.h>
35#include <VBox/log.h>
36#include <VBox/version.h>
37
38#include "VBox/com/com.h"
39#include "VBox/com/NativeEventQueue.h"
40
41using namespace std;
42
43/* The following 2 object references should be eliminated once the legacy
44 * way to initialize the COM/XPCOM C bindings is removed. */
45static ISession *g_Session = NULL;
46static IVirtualBox *g_VirtualBox = NULL;
47
48#ifdef VBOX_WITH_XPCOM
49/* This object reference should be eliminated once the legacy way of handling
50 * the event queue (XPCOM specific) is removed. */
51static nsIEventQueue *g_EventQueue = NULL;
52#endif /* VBOX_WITH_XPCOM */
53
54static void VBoxComUninitialize(void);
55static void VBoxClientUninitialize(void);
56
57static int
58VBoxUtf16ToUtf8(CBSTR pwszString, char **ppszString)
59{
60 if (!pwszString)
61 {
62 *ppszString = NULL;
63 return VINF_SUCCESS;
64 }
65 return RTUtf16ToUtf8(pwszString, ppszString);
66}
67
68static int
69VBoxUtf8ToUtf16(const char *pszString, BSTR *ppwszString)
70{
71 if (!pszString)
72 {
73 *ppwszString = NULL;
74 return VINF_SUCCESS;
75 }
76#ifdef VBOX_WITH_XPCOM
77 return RTStrToUtf16(pszString, ppwszString);
78#else /* !VBOX_WITH_XPCOM */
79 PRTUTF16 pwsz;
80 int vrc = RTStrToUtf16(pszString, &pwsz);
81 *ppwszString = ::SysAllocString(pwsz);
82 RTUtf16Free(pwsz);
83 return vrc;
84#endif /* !VBOX_WITH_XPCOM */
85}
86
87static void
88VBoxUtf8Clear(char *pszString)
89{
90 RT_BZERO(pszString, strlen(pszString));
91}
92
93static void
94VBoxUtf16Clear(BSTR pwszString)
95{
96 RT_BZERO(pwszString, RTUtf16Len(pwszString) * sizeof(RTUTF16));
97}
98
99static void
100VBoxUtf16Free(BSTR pwszString)
101{
102#ifdef VBOX_WITH_XPCOM
103 RTUtf16Free(pwszString);
104#else /* !VBOX_WITH_XPCOM */
105 ::SysFreeString(pwszString);
106#endif /* !VBOX_WITH_XPCOM */
107}
108
109static void
110VBoxUtf8Free(char *pszString)
111{
112 RTStrFree(pszString);
113}
114
115static void
116VBoxComUnallocString(BSTR pwsz)
117{
118 if (pwsz)
119 {
120#ifdef VBOX_WITH_XPCOM
121 nsMemory::Free(pwsz);
122#else /* !VBOX_WITH_XPCOM */
123 ::SysFreeString(pwsz);
124#endif /* !VBOX_WITH_XPCOM */
125 }
126}
127
128static void
129VBoxComUnallocMem(void *pv)
130{
131 VBoxComUnallocString((BSTR)pv);
132}
133
134static ULONG
135VBoxVTElemSize(VARTYPE vt)
136{
137 switch (vt)
138 {
139 case VT_BOOL:
140 case VT_I1:
141 case VT_UI1:
142 return 1;
143 case VT_I2:
144 case VT_UI2:
145 return 2;
146 case VT_I4:
147 case VT_UI4:
148 case VT_HRESULT:
149 return 4;
150 case VT_I8:
151 case VT_UI8:
152 return 8;
153 case VT_BSTR:
154 case VT_DISPATCH:
155 case VT_UNKNOWN:
156 return sizeof(void *);
157 default:
158 return 0;
159 }
160}
161
162static SAFEARRAY *
163VBoxSafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
164{
165#ifdef VBOX_WITH_XPCOM
166 NOREF(lLbound);
167 ULONG cbElement = VBoxVTElemSize(vt);
168 if (!cbElement)
169 return NULL;
170 SAFEARRAY *psa = (SAFEARRAY *)RTMemAllocZ(sizeof(SAFEARRAY));
171 if (!psa)
172 return psa;
173 if (cElements)
174 {
175 void *pv = nsMemory::Alloc(cElements * cbElement);
176 if (!pv)
177 {
178 RTMemFree(psa);
179 return NULL;
180 }
181 psa->pv = pv;
182 psa->c = cElements;
183 }
184 return psa;
185#else /* !VBOX_WITH_XPCOM */
186 return SafeArrayCreateVector(vt, lLbound, cElements);
187#endif /* !VBOX_WITH_XPCOM */
188}
189
190static SAFEARRAY *
191VBoxSafeArrayOutParamAlloc(void)
192{
193#ifdef VBOX_WITH_XPCOM
194 return (SAFEARRAY *)RTMemAllocZ(sizeof(SAFEARRAY));
195#else /* !VBOX_WITH_XPCOM */
196 return NULL;
197#endif /* !VBOX_WITH_XPCOM */
198}
199
200static HRESULT
201VBoxSafeArrayDestroy(SAFEARRAY *psa)
202{
203#ifdef VBOX_WITH_XPCOM
204 if (psa)
205 {
206 if (psa->pv)
207 nsMemory::Free(psa->pv);
208 RTMemFree(psa);
209 }
210 return S_OK;
211#else /* !VBOX_WITH_XPCOM */
212 VARTYPE vt = VT_UNKNOWN;
213 HRESULT rc = SafeArrayGetVartype(psa, &vt);
214 if (FAILED(rc))
215 return rc;
216 if (vt == VT_BSTR)
217 {
218 /* Special treatment: strings are to be freed explicitly, see sample
219 * C binding code, so zap it here. No way to reach compatible code
220 * behavior between COM and XPCOM without this kind of trickery. */
221 void *pData;
222 rc = SafeArrayAccessData(psa, &pData);
223 if (FAILED(rc))
224 return rc;
225 ULONG cbElement = VBoxVTElemSize(vt);
226 if (!cbElement)
227 return E_INVALIDARG;
228 Assert(cbElement = psa->cbElements);
229 ULONG cElements = psa->rgsabound[0].cElements;
230 memset(pData, '\0', cbElement * cElements);
231 SafeArrayUnaccessData(psa);
232 }
233 return SafeArrayDestroy(psa);
234#endif /* !VBOX_WITH_XPCOM */
235}
236
237static HRESULT
238VBoxSafeArrayCopyInParamHelper(SAFEARRAY *psa, const void *pv, ULONG cb)
239{
240 if (!pv || !psa)
241 return E_POINTER;
242 if (!cb)
243 return S_OK;
244
245 void *pData;
246#ifdef VBOX_WITH_XPCOM
247 pData = psa->pv;
248#else /* !VBOX_WITH_XPCOM */
249 HRESULT rc = SafeArrayAccessData(psa, &pData);
250 if (FAILED(rc))
251 return rc;
252#endif /* !VBOX_WITH_XPCOM */
253 memcpy(pData, pv, cb);
254#ifndef VBOX_WITH_XPCOM
255 SafeArrayUnaccessData(psa);
256#endif /* !VBOX_WITH_XPCOM */
257 return S_OK;
258}
259
260static HRESULT
261VBoxSafeArrayCopyOutParamHelper(void **ppv, ULONG *pcb, VARTYPE vt, SAFEARRAY *psa)
262{
263 if (!ppv)
264 return E_POINTER;
265 ULONG cbElement = VBoxVTElemSize(vt);
266 if (!cbElement)
267 {
268 *ppv = NULL;
269 if (pcb)
270 *pcb = 0;
271 return E_INVALIDARG;
272 }
273#ifndef VBOX_WITH_XPCOM
274 if (psa->cDims != 1)
275 {
276 *ppv = NULL;
277 if (pcb)
278 *pcb = 0;
279 return E_INVALIDARG;
280 }
281 Assert(cbElement = psa->cbElements);
282#endif /* !VBOX_WITH_XPCOM */
283 void *pData;
284 ULONG cElements;
285#ifdef VBOX_WITH_XPCOM
286 pData = psa->pv;
287 cElements = psa->c;
288#else /* !VBOX_WITH_XPCOM */
289 HRESULT rc = SafeArrayAccessData(psa, &pData);
290 if (FAILED(rc))
291 {
292 *ppv = NULL;
293 if (pcb)
294 *pcb = 0;
295 return rc;
296 }
297 cElements = psa->rgsabound[0].cElements;
298#endif /* !VBOX_WITH_XPCOM */
299 size_t cbTotal = cbElement * cElements;
300 void *pv = NULL;
301 if (cbTotal)
302 {
303 pv = malloc(cbTotal);
304 if (!pv)
305 {
306 *ppv = NULL;
307 if (pcb)
308 *pcb = 0;
309 return E_OUTOFMEMORY;
310 }
311 else
312 memcpy(pv, pData, cbTotal);
313 }
314 *ppv = pv;
315 if (pcb)
316 *pcb = (ULONG)cbTotal;
317#ifndef VBOX_WITH_XPCOM
318 SafeArrayUnaccessData(psa);
319#endif /* !VBOX_WITH_XPCOM */
320 return S_OK;
321}
322
323static HRESULT
324VBoxSafeArrayCopyOutIfaceParamHelper(IUnknown ***ppaObj, ULONG *pcObj, SAFEARRAY *psa)
325{
326 ULONG mypcb;
327 HRESULT rc = VBoxSafeArrayCopyOutParamHelper((void **)ppaObj, &mypcb, VT_UNKNOWN, psa);
328 if (FAILED(rc))
329 {
330 if (pcObj)
331 *pcObj = 0;
332 return rc;
333 }
334 ULONG cElements = mypcb / sizeof(void *);
335 if (pcObj)
336 *pcObj = cElements;
337#ifndef VBOX_WITH_XPCOM
338 /* Do this only for COM, as there the SAFEARRAY destruction will release
339 * the contained references automatically. XPCOM doesn't do that, which
340 * means that copying implicitly transfers ownership. */
341 IUnknown **paObj = *ppaObj;
342 for (ULONG i = 0; i < cElements; i++)
343 {
344 IUnknown *pObj = paObj[i];
345 if (pObj)
346 pObj->AddRef();
347 }
348#endif /* VBOX_WITH_XPCOM */
349 return S_OK;
350}
351
352static HRESULT
353VBoxArrayOutFree(void *pv)
354{
355 free(pv);
356 return S_OK;
357}
358
359static void
360VBoxComInitialize(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
361 const char *pszSessionIID, ISession **ppSession)
362{
363 int vrc;
364 IID virtualBoxIID;
365 IID sessionIID;
366
367 *ppSession = NULL;
368 *ppVirtualBox = NULL;
369
370 /* convert the string representation of the UUIDs (if provided) to IID */
371 if (pszVirtualBoxIID && *pszVirtualBoxIID)
372 {
373 vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxIID, pszVirtualBoxIID);
374 if (RT_FAILURE(vrc))
375 return;
376 }
377 else
378 virtualBoxIID = IID_IVirtualBox;
379 if (pszSessionIID && *pszSessionIID)
380 {
381 vrc = ::RTUuidFromStr((RTUUID *)&sessionIID, pszSessionIID);
382 if (RT_FAILURE(vrc))
383 return;
384 }
385 else
386 sessionIID = IID_ISession;
387
388 HRESULT rc = com::Initialize();
389 if (FAILED(rc))
390 {
391 Log(("Cbinding: COM/XPCOM could not be initialized! rc=%Rhrc\n", rc));
392 VBoxComUninitialize();
393 return;
394 }
395
396#ifdef VBOX_WITH_XPCOM
397 rc = NS_GetMainEventQ(&g_EventQueue);
398 if (FAILED(rc))
399 {
400 Log(("Cbinding: Could not get XPCOM event queue! rc=%Rhrc\n", rc));
401 VBoxComUninitialize();
402 return;
403 }
404#endif /* VBOX_WITH_XPCOM */
405
406#ifdef VBOX_WITH_XPCOM
407 nsIComponentManager *pManager;
408 rc = NS_GetComponentManager(&pManager);
409 if (FAILED(rc))
410 {
411 Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
412 VBoxComUninitialize();
413 return;
414 }
415
416 rc = pManager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
417 nsnull,
418 virtualBoxIID,
419 (void **)&g_VirtualBox);
420#else /* !VBOX_WITH_XPCOM */
421 IVirtualBoxClient *pVirtualBoxClient;
422 rc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, IID_IVirtualBoxClient, (void **)&pVirtualBoxClient);
423 if (SUCCEEDED(rc))
424 {
425 IVirtualBox *pVirtualBox;
426 rc = pVirtualBoxClient->get_VirtualBox(&pVirtualBox);
427 if (SUCCEEDED(rc))
428 {
429 rc = pVirtualBox->QueryInterface(virtualBoxIID, (void **)&g_VirtualBox);
430 pVirtualBox->Release();
431 }
432 pVirtualBoxClient->Release();
433 }
434#endif /* !VBOX_WITH_XPCOM */
435 if (FAILED(rc))
436 {
437 Log(("Cbinding: Could not instantiate VirtualBox object! rc=%Rhrc\n",rc));
438#ifdef VBOX_WITH_XPCOM
439 pManager->Release();
440 pManager = NULL;
441#endif /* VBOX_WITH_XPCOM */
442 VBoxComUninitialize();
443 return;
444 }
445
446 Log(("Cbinding: IVirtualBox object created.\n"));
447
448#ifdef VBOX_WITH_XPCOM
449 rc = pManager->CreateInstanceByContractID(NS_SESSION_CONTRACTID,
450 nsnull,
451 sessionIID,
452 (void **)&g_Session);
453#else /* !VBOX_WITH_XPCOM */
454 rc = CoCreateInstance(CLSID_Session, NULL, CLSCTX_INPROC_SERVER, sessionIID, (void **)&g_Session);
455#endif /* !VBOX_WITH_XPCOM */
456 if (FAILED(rc))
457 {
458 Log(("Cbinding: Could not instantiate Session object! rc=%Rhrc\n",rc));
459#ifdef VBOX_WITH_XPCOM
460 pManager->Release();
461 pManager = NULL;
462#endif /* VBOX_WITH_XPCOM */
463 VBoxComUninitialize();
464 return;
465 }
466
467 Log(("Cbinding: ISession object created.\n"));
468
469#ifdef VBOX_WITH_XPCOM
470 pManager->Release();
471 pManager = NULL;
472#endif /* VBOX_WITH_XPCOM */
473
474 *ppSession = g_Session;
475 *ppVirtualBox = g_VirtualBox;
476}
477
478static void
479VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
480{
481 VBoxComInitialize(NULL, ppVirtualBox, NULL, ppSession);
482}
483
484static void
485VBoxComUninitialize(void)
486{
487 if (g_Session)
488 {
489 g_Session->Release();
490 g_Session = NULL;
491 }
492 if (g_VirtualBox)
493 {
494 g_VirtualBox->Release();
495 g_VirtualBox = NULL;
496 }
497#ifdef VBOX_WITH_XPCOM
498 if (g_EventQueue)
499 {
500 g_EventQueue->Release();
501 g_EventQueue = NULL;
502 }
503#endif /* VBOX_WITH_XPCOM */
504 com::Shutdown();
505 Log(("Cbinding: Cleaned up the created objects.\n"));
506}
507
508#ifdef VBOX_WITH_XPCOM
509static void
510VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
511{
512 *ppEventQueue = g_EventQueue;
513}
514#endif /* VBOX_WITH_XPCOM */
515
516static int
517VBoxProcessEventQueue(LONG64 iTimeoutMS)
518{
519 RTMSINTERVAL iTimeout;
520 if (iTimeoutMS < 0 || iTimeoutMS > UINT32_MAX)
521 iTimeout = RT_INDEFINITE_WAIT;
522 else
523 iTimeout = (RTMSINTERVAL)iTimeoutMS;
524 int vrc = com::NativeEventQueue::getMainEventQueue()->processEventQueue(iTimeout);
525 switch (vrc)
526 {
527 case VINF_SUCCESS:
528 return 0;
529 case VINF_INTERRUPTED:
530 return 1;
531 case VERR_INTERRUPTED:
532 return 2;
533 case VERR_TIMEOUT:
534 return 3;
535 case VERR_INVALID_CONTEXT:
536 return 4;
537 default:
538 return 5;
539 }
540}
541
542static int
543VBoxInterruptEventQueueProcessing(void)
544{
545 com::NativeEventQueue::getMainEventQueue()->interruptEventQueueProcessing();
546 return 0;
547}
548
549static HRESULT
550VBoxGetException(IErrorInfo **ppException)
551{
552 HRESULT rc;
553
554 *ppException = NULL;
555
556#ifdef VBOX_WITH_XPCOM
557 nsIServiceManager *mgr = NULL;
558 rc = NS_GetServiceManager(&mgr);
559 if (FAILED(rc) || !mgr)
560 return rc;
561
562 IID esid = NS_IEXCEPTIONSERVICE_IID;
563 nsIExceptionService *es = NULL;
564 rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
565 if (FAILED(rc) || !es)
566 {
567 mgr->Release();
568 return rc;
569 }
570
571 nsIExceptionManager *em;
572 rc = es->GetCurrentExceptionManager(&em);
573 if (FAILED(rc) || !em)
574 {
575 es->Release();
576 mgr->Release();
577 return rc;
578 }
579
580 nsIException *ex;
581 rc = em->GetCurrentException(&ex);
582 if (FAILED(rc))
583 {
584 em->Release();
585 es->Release();
586 mgr->Release();
587 return rc;
588 }
589
590 *ppException = ex;
591 em->Release();
592 es->Release();
593 mgr->Release();
594#else /* !VBOX_WITH_XPCOM */
595 IErrorInfo *ex;
596 rc = ::GetErrorInfo(0, &ex);
597 if (FAILED(rc))
598 return rc;
599
600 *ppException = ex;
601#endif /* !VBOX_WITH_XPCOM */
602
603 return rc;
604}
605
606static HRESULT
607VBoxClearException(void)
608{
609 HRESULT rc;
610
611#ifdef VBOX_WITH_XPCOM
612 nsIServiceManager *mgr = NULL;
613 rc = NS_GetServiceManager(&mgr);
614 if (FAILED(rc) || !mgr)
615 return rc;
616
617 IID esid = NS_IEXCEPTIONSERVICE_IID;
618 nsIExceptionService *es = NULL;
619 rc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
620 if (FAILED(rc) || !es)
621 {
622 mgr->Release();
623 return rc;
624 }
625
626 nsIExceptionManager *em;
627 rc = es->GetCurrentExceptionManager(&em);
628 if (FAILED(rc) || !em)
629 {
630 es->Release();
631 mgr->Release();
632 return rc;
633 }
634
635 rc = em->SetCurrentException(NULL);
636 em->Release();
637 es->Release();
638 mgr->Release();
639#else /* !VBOX_WITH_XPCOM */
640 rc = ::SetErrorInfo(0, NULL);
641#endif /* !VBOX_WITH_XPCOM */
642
643 return rc;
644}
645
646static HRESULT
647VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
648{
649 IID virtualBoxClientIID;
650
651 *ppVirtualBoxClient = NULL;
652
653 /* convert the string representation of UUID to IID type */
654 if (pszVirtualBoxClientIID && *pszVirtualBoxClientIID)
655 {
656 int vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxClientIID, pszVirtualBoxClientIID);
657 if (RT_FAILURE(vrc))
658 return E_INVALIDARG;
659 }
660 else
661 virtualBoxClientIID = IID_IVirtualBoxClient;
662
663 HRESULT rc = com::Initialize();
664 if (FAILED(rc))
665 {
666 Log(("Cbinding: COM/XPCOM could not be initialized! rc=%Rhrc\n", rc));
667 VBoxClientUninitialize();
668 return rc;
669 }
670
671#ifdef VBOX_WITH_XPCOM
672 rc = NS_GetMainEventQ(&g_EventQueue);
673 if (NS_FAILED(rc))
674 {
675 Log(("Cbinding: Could not get XPCOM event queue! rc=%Rhrc\n", rc));
676 VBoxClientUninitialize();
677 return rc;
678 }
679#endif /* VBOX_WITH_XPCOM */
680
681#ifdef VBOX_WITH_XPCOM
682 nsIComponentManager *pManager;
683 rc = NS_GetComponentManager(&pManager);
684 if (FAILED(rc))
685 {
686 Log(("Cbinding: Could not get component manager! rc=%Rhrc\n", rc));
687 VBoxClientUninitialize();
688 return rc;
689 }
690
691 rc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
692 nsnull,
693 virtualBoxClientIID,
694 (void **)ppVirtualBoxClient);
695#else /* !VBOX_WITH_XPCOM */
696 rc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, virtualBoxClientIID, (void **)ppVirtualBoxClient);
697#endif /* !VBOX_WITH_XPCOM */
698 if (FAILED(rc))
699 {
700 Log(("Cbinding: Could not instantiate VirtualBoxClient object! rc=%Rhrc\n",rc));
701#ifdef VBOX_WITH_XPCOM
702 pManager->Release();
703 pManager = NULL;
704#endif /* VBOX_WITH_XPCOM */
705 VBoxClientUninitialize();
706 return rc;
707 }
708
709#ifdef VBOX_WITH_XPCOM
710 pManager->Release();
711 pManager = NULL;
712#endif /* VBOX_WITH_XPCOM */
713
714 Log(("Cbinding: IVirtualBoxClient object created.\n"));
715
716 return S_OK;
717}
718
719static HRESULT
720VBoxClientThreadInitialize(void)
721{
722 return com::Initialize();
723}
724
725static HRESULT
726VBoxClientThreadUninitialize(void)
727{
728 return com::Shutdown();
729}
730
731static void
732VBoxClientUninitialize(void)
733{
734#ifdef VBOX_WITH_XPCOM
735 if (g_EventQueue)
736 {
737 NS_RELEASE(g_EventQueue);
738 g_EventQueue = NULL;
739 }
740#endif /* VBOX_WITH_XPCOM */
741 com::Shutdown();
742 Log(("Cbinding: Cleaned up the created objects.\n"));
743}
744
745static unsigned int
746VBoxVersion(void)
747{
748 return VBOX_VERSION_MAJOR * 1000 * 1000 + VBOX_VERSION_MINOR * 1000 + VBOX_VERSION_BUILD;
749}
750
751static unsigned int
752VBoxAPIVersion(void)
753{
754 return VBOX_VERSION_MAJOR * 1000 + VBOX_VERSION_MINOR + (VBOX_VERSION_BUILD > 50 ? 1 : 0);
755}
756
757VBOXCAPI_DECL(PCVBOXCAPI)
758VBoxGetCAPIFunctions(unsigned uVersion)
759{
760 /* This is the first piece of code which knows that IPRT exists, so
761 * initialize it properly. The limited initialization in VBoxC is not
762 * sufficient, and causes trouble with com::Initialize() misbehaving. */
763 RTR3InitDll(0);
764
765 /*
766 * The current interface version.
767 */
768 static const VBOXCAPI s_Functions =
769 {
770 sizeof(VBOXCAPI),
771 VBOX_CAPI_VERSION,
772
773 VBoxVersion,
774 VBoxAPIVersion,
775
776 VBoxClientInitialize,
777 VBoxClientThreadInitialize,
778 VBoxClientThreadUninitialize,
779 VBoxClientUninitialize,
780
781 VBoxComInitialize,
782 VBoxComUninitialize,
783
784 VBoxComUnallocString,
785
786 VBoxUtf16ToUtf8,
787 VBoxUtf8ToUtf16,
788 VBoxUtf8Free,
789 VBoxUtf16Free,
790
791 VBoxSafeArrayCreateVector,
792 VBoxSafeArrayOutParamAlloc,
793 VBoxSafeArrayCopyInParamHelper,
794 VBoxSafeArrayCopyOutParamHelper,
795 VBoxSafeArrayCopyOutIfaceParamHelper,
796 VBoxSafeArrayDestroy,
797 VBoxArrayOutFree,
798
799#ifdef VBOX_WITH_XPCOM
800 VBoxGetEventQueue,
801#endif /* VBOX_WITH_XPCOM */
802 VBoxGetException,
803 VBoxClearException,
804 VBoxProcessEventQueue,
805 VBoxInterruptEventQueueProcessing,
806
807 VBoxUtf8Clear,
808 VBoxUtf16Clear,
809
810 VBOX_CAPI_VERSION
811 };
812
813 if ((uVersion & 0xffff0000U) == (VBOX_CAPI_VERSION & 0xffff0000U))
814 return &s_Functions;
815
816 /*
817 * Legacy interface version 3.0.
818 */
819 static const struct VBOXCAPIV3
820 {
821 /** The size of the structure. */
822 unsigned cb;
823 /** The structure version. */
824 unsigned uVersion;
825
826 unsigned int (*pfnGetVersion)(void);
827
828 unsigned int (*pfnGetAPIVersion)(void);
829
830 HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
831 IVirtualBoxClient **ppVirtualBoxClient);
832 void (*pfnClientUninitialize)(void);
833
834 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
835 IVirtualBox **ppVirtualBox,
836 const char *pszSessionIID,
837 ISession **ppSession);
838
839 void (*pfnComUninitialize)(void);
840
841 void (*pfnComUnallocMem)(void *pv);
842
843 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
844 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
845 void (*pfnUtf8Free)(char *pszString);
846 void (*pfnUtf16Free)(BSTR pwszString);
847
848#ifdef VBOX_WITH_XPCOM
849 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
850#endif /* VBOX_WITH_XPCOM */
851 HRESULT (*pfnGetException)(IErrorInfo **ppException);
852 HRESULT (*pfnClearException)(void);
853
854 /** Tail version, same as uVersion. */
855 unsigned uEndVersion;
856 } s_Functions_v3_0 =
857 {
858 sizeof(s_Functions_v3_0),
859 0x00030000U,
860
861 VBoxVersion,
862 VBoxAPIVersion,
863
864 VBoxClientInitialize,
865 VBoxClientUninitialize,
866
867 VBoxComInitialize,
868 VBoxComUninitialize,
869
870 VBoxComUnallocMem,
871
872 VBoxUtf16ToUtf8,
873 VBoxUtf8ToUtf16,
874 VBoxUtf8Free,
875 VBoxUtf16Free,
876
877#ifdef VBOX_WITH_XPCOM
878 VBoxGetEventQueue,
879#endif /* VBOX_WITH_XPCOM */
880 VBoxGetException,
881 VBoxClearException,
882
883 0x00030000U
884 };
885
886 if ((uVersion & 0xffff0000U) == 0x00030000U)
887 return (PCVBOXCAPI)&s_Functions_v3_0;
888
889 /*
890 * Legacy interface version 2.0.
891 */
892 static const struct VBOXCAPIV2
893 {
894 /** The size of the structure. */
895 unsigned cb;
896 /** The structure version. */
897 unsigned uVersion;
898
899 unsigned int (*pfnGetVersion)(void);
900
901 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
902 IVirtualBox **ppVirtualBox,
903 const char *pszSessionIID,
904 ISession **ppSession);
905
906 void (*pfnComUninitialize)(void);
907
908 void (*pfnComUnallocMem)(void *pv);
909 void (*pfnUtf16Free)(BSTR pwszString);
910 void (*pfnUtf8Free)(char *pszString);
911
912 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
913 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
914
915#ifdef VBOX_WITH_XPCOM
916 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
917#endif /* VBOX_WITH_XPCOM */
918
919 /** Tail version, same as uVersion. */
920 unsigned uEndVersion;
921 } s_Functions_v2_0 =
922 {
923 sizeof(s_Functions_v2_0),
924 0x00020000U,
925
926 VBoxVersion,
927
928 VBoxComInitialize,
929 VBoxComUninitialize,
930
931 VBoxComUnallocMem,
932 VBoxUtf16Free,
933 VBoxUtf8Free,
934
935 VBoxUtf16ToUtf8,
936 VBoxUtf8ToUtf16,
937
938#ifdef VBOX_WITH_XPCOM
939 VBoxGetEventQueue,
940#endif /* VBOX_WITH_XPCOM */
941
942 0x00020000U
943 };
944
945 if ((uVersion & 0xffff0000U) == 0x00020000U)
946 return (PCVBOXCAPI)&s_Functions_v2_0;
947
948 /*
949 * Legacy interface version 1.0.
950 */
951 static const struct VBOXCAPIV1
952 {
953 /** The size of the structure. */
954 unsigned cb;
955 /** The structure version. */
956 unsigned uVersion;
957
958 unsigned int (*pfnGetVersion)(void);
959
960 void (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
961 void (*pfnComUninitialize)(void);
962
963 void (*pfnComUnallocMem)(void *pv);
964 void (*pfnUtf16Free)(BSTR pwszString);
965 void (*pfnUtf8Free)(char *pszString);
966
967 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
968 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
969
970 /** Tail version, same as uVersion. */
971 unsigned uEndVersion;
972 } s_Functions_v1_0 =
973 {
974 sizeof(s_Functions_v1_0),
975 0x00010000U,
976
977 VBoxVersion,
978
979 VBoxComInitializeV1,
980 VBoxComUninitialize,
981
982 VBoxComUnallocMem,
983 VBoxUtf16Free,
984 VBoxUtf8Free,
985
986 VBoxUtf16ToUtf8,
987 VBoxUtf8ToUtf16,
988
989 0x00010000U
990 };
991
992 if ((uVersion & 0xffff0000U) == 0x00010000U)
993 return (PCVBOXCAPI)&s_Functions_v1_0;
994
995 /*
996 * Unsupported interface version.
997 */
998 return NULL;
999}
1000
1001#ifdef VBOX_WITH_XPCOM
1002VBOXCAPI_DECL(PCVBOXCAPI)
1003VBoxGetXPCOMCFunctions(unsigned uVersion)
1004{
1005 return VBoxGetCAPIFunctions(uVersion);
1006}
1007#endif /* VBOX_WITH_XPCOM */
1008/* 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