VirtualBox

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

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

© 2023 Oracle
ContactPrivacy policyTerms of Use