VirtualBox

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

Last change on this file since 98123 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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