VirtualBox

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

Last change on this file since 76346 was 76346, checked in by vboxsync, 6 years ago

*: Preparing for iprt/string.h, iprt/json.h and iprt/serialport.h no longer including iprt/err.h and string.h no longer including latin1.h (it needs err.h). bugref:9344

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