VirtualBox

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

Last change on this file since 95353 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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