VirtualBox

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

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 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 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file VBoxCAPI.cpp
3 * Utility functions to use with the C API binding.
4 */
5
6/*
7 * Copyright (C) 2009-2024 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 hrc = SafeArrayGetVartype(psa, &vt);
232 if (FAILED(hrc))
233 return hrc;
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 hrc = SafeArrayAccessData(psa, &pData);
241 if (FAILED(hrc))
242 return hrc;
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 hrc = SafeArrayAccessData(psa, &pData);
268 if (FAILED(hrc))
269 return hrc;
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 hrc = SafeArrayAccessData(psa, &pData);
308 if (FAILED(hrc))
309 {
310 *ppv = NULL;
311 if (pcb)
312 *pcb = 0;
313 return hrc;
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 hrc = VBoxSafeArrayCopyOutParamHelper((void **)ppaObj, &mypcb, VT_UNKNOWN, psa);
346 if (FAILED(hrc))
347 {
348 if (pcObj)
349 *pcObj = 0;
350 return hrc;
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 hrc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
407 if (FAILED(hrc))
408 {
409 Log(("Cbinding: COM/XPCOM could not be initialized! hrc=%Rhrc\n", hrc));
410 VBoxComUninitialize();
411 return;
412 }
413
414#ifdef VBOX_WITH_XPCOM
415 hrc = NS_GetMainEventQ(&g_EventQueue);
416 if (FAILED(hrc))
417 {
418 Log(("Cbinding: Could not get XPCOM event queue! hrc=%Rhrc\n", hrc));
419 VBoxComUninitialize();
420 return;
421 }
422#endif /* VBOX_WITH_XPCOM */
423
424#ifdef VBOX_WITH_XPCOM
425 nsIComponentManager *pManager = NULL;
426 hrc = NS_GetComponentManager(&pManager);
427 if (FAILED(hrc))
428 {
429 Log(("Cbinding: Could not get component manager! hrc=%Rhrc\n", hrc));
430 VBoxComUninitialize();
431 return;
432 }
433
434 hrc = pManager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
435 nsnull,
436 virtualBoxIID,
437 (void **)&g_VirtualBox);
438#else /* !VBOX_WITH_XPCOM */
439 IVirtualBoxClient *pVirtualBoxClient;
440 hrc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, IID_IVirtualBoxClient, (void **)&pVirtualBoxClient);
441 if (SUCCEEDED(hrc))
442 {
443 IVirtualBox *pVirtualBox;
444 hrc = pVirtualBoxClient->get_VirtualBox(&pVirtualBox);
445 if (SUCCEEDED(hrc))
446 {
447 hrc = pVirtualBox->QueryInterface(virtualBoxIID, (void **)&g_VirtualBox);
448 pVirtualBox->Release();
449 }
450 pVirtualBoxClient->Release();
451 }
452#endif /* !VBOX_WITH_XPCOM */
453 if (FAILED(hrc))
454 {
455 Log(("Cbinding: Could not instantiate VirtualBox object! hrc=%Rhrc\n",hrc));
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 hrc = pManager->CreateInstanceByContractID(NS_SESSION_CONTRACTID, nsnull, sessionIID, (void **)&g_Session);
468#else /* !VBOX_WITH_XPCOM */
469 hrc = CoCreateInstance(CLSID_Session, NULL, CLSCTX_INPROC_SERVER, sessionIID, (void **)&g_Session);
470#endif /* !VBOX_WITH_XPCOM */
471 if (FAILED(hrc))
472 {
473 Log(("Cbinding: Could not instantiate Session object! hrc=%Rhrc\n",hrc));
474#ifdef VBOX_WITH_XPCOM
475 pManager->Release();
476 pManager = NULL;
477#endif /* VBOX_WITH_XPCOM */
478 VBoxComUninitialize();
479 return;
480 }
481
482 Log(("Cbinding: ISession object created.\n"));
483
484#ifdef VBOX_WITH_XPCOM
485 pManager->Release();
486 pManager = NULL;
487#endif /* VBOX_WITH_XPCOM */
488
489 *ppSession = g_Session;
490 *ppVirtualBox = g_VirtualBox;
491}
492
493static void
494VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
495{
496 VBoxComInitialize(NULL, ppVirtualBox, NULL, ppSession);
497}
498
499static void
500VBoxComUninitialize(void)
501{
502 if (g_Session)
503 {
504 g_Session->Release();
505 g_Session = NULL;
506 }
507 if (g_VirtualBox)
508 {
509 g_VirtualBox->Release();
510 g_VirtualBox = NULL;
511 }
512#ifdef VBOX_WITH_XPCOM
513 if (g_EventQueue)
514 {
515 g_EventQueue->Release();
516 g_EventQueue = NULL;
517 }
518#endif /* VBOX_WITH_XPCOM */
519 com::Shutdown();
520 Log(("Cbinding: Cleaned up the created objects.\n"));
521}
522
523#ifdef VBOX_WITH_XPCOM
524static void
525VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
526{
527 *ppEventQueue = g_EventQueue;
528}
529#endif /* VBOX_WITH_XPCOM */
530
531static int
532VBoxProcessEventQueue(LONG64 iTimeoutMS)
533{
534 RTMSINTERVAL iTimeout;
535 if (iTimeoutMS < 0 || iTimeoutMS > UINT32_MAX)
536 iTimeout = RT_INDEFINITE_WAIT;
537 else
538 iTimeout = (RTMSINTERVAL)iTimeoutMS;
539 int vrc = com::NativeEventQueue::getMainEventQueue()->processEventQueue(iTimeout);
540 switch (vrc)
541 {
542 case VINF_SUCCESS:
543 return 0;
544 case VINF_INTERRUPTED:
545 return 1;
546 case VERR_INTERRUPTED:
547 return 2;
548 case VERR_TIMEOUT:
549 return 3;
550 case VERR_INVALID_CONTEXT:
551 return 4;
552 default:
553 return 5;
554 }
555}
556
557static int
558VBoxInterruptEventQueueProcessing(void)
559{
560 com::NativeEventQueue::getMainEventQueue()->interruptEventQueueProcessing();
561 return 0;
562}
563
564static HRESULT
565VBoxGetException(IErrorInfo **ppException)
566{
567 HRESULT hrc;
568
569 *ppException = NULL;
570
571#ifdef VBOX_WITH_XPCOM
572 nsIServiceManager *mgr = NULL;
573 hrc = NS_GetServiceManager(&mgr);
574 if (FAILED(hrc) || !mgr)
575 return hrc;
576
577 IID esid = NS_IEXCEPTIONSERVICE_IID;
578 nsIExceptionService *es = NULL;
579 hrc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
580 if (FAILED(hrc) || !es)
581 {
582 mgr->Release();
583 return hrc;
584 }
585
586 nsIExceptionManager *em;
587 hrc = es->GetCurrentExceptionManager(&em);
588 if (FAILED(hrc) || !em)
589 {
590 es->Release();
591 mgr->Release();
592 return hrc;
593 }
594
595 nsIException *ex;
596 hrc = em->GetCurrentException(&ex);
597 if (FAILED(hrc))
598 {
599 em->Release();
600 es->Release();
601 mgr->Release();
602 return hrc;
603 }
604
605 *ppException = ex;
606 em->Release();
607 es->Release();
608 mgr->Release();
609#else /* !VBOX_WITH_XPCOM */
610 IErrorInfo *ex;
611 hrc = ::GetErrorInfo(0, &ex);
612 if (FAILED(hrc))
613 return hrc;
614
615 *ppException = ex;
616#endif /* !VBOX_WITH_XPCOM */
617
618 return hrc;
619}
620
621static HRESULT
622VBoxClearException(void)
623{
624 HRESULT hrc;
625
626#ifdef VBOX_WITH_XPCOM
627 nsIServiceManager *mgr = NULL;
628 hrc = NS_GetServiceManager(&mgr);
629 if (FAILED(hrc) || !mgr)
630 return hrc;
631
632 IID esid = NS_IEXCEPTIONSERVICE_IID;
633 nsIExceptionService *es = NULL;
634 hrc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
635 if (FAILED(hrc) || !es)
636 {
637 mgr->Release();
638 return hrc;
639 }
640
641 nsIExceptionManager *em;
642 hrc = es->GetCurrentExceptionManager(&em);
643 if (FAILED(hrc) || !em)
644 {
645 es->Release();
646 mgr->Release();
647 return hrc;
648 }
649
650 hrc = em->SetCurrentException(NULL);
651 em->Release();
652 es->Release();
653 mgr->Release();
654#else /* !VBOX_WITH_XPCOM */
655 hrc = ::SetErrorInfo(0, NULL);
656#endif /* !VBOX_WITH_XPCOM */
657
658 return hrc;
659}
660
661static HRESULT
662VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
663{
664 IID virtualBoxClientIID;
665
666 *ppVirtualBoxClient = NULL;
667
668 /* convert the string representation of UUID to IID type */
669 if (pszVirtualBoxClientIID && *pszVirtualBoxClientIID)
670 {
671 int vrc = ::RTUuidFromStr((RTUUID *)&virtualBoxClientIID, pszVirtualBoxClientIID);
672 if (RT_FAILURE(vrc))
673 return E_INVALIDARG;
674 }
675 else
676 virtualBoxClientIID = IID_IVirtualBoxClient;
677
678 HRESULT hrc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
679 if (FAILED(hrc))
680 {
681 Log(("Cbinding: COM/XPCOM could not be initialized! hrc=%Rhrc\n", hrc));
682 VBoxClientUninitialize();
683 return hrc;
684 }
685
686#ifdef VBOX_WITH_XPCOM
687 hrc = NS_GetMainEventQ(&g_EventQueue);
688 if (NS_FAILED(hrc))
689 {
690 Log(("Cbinding: Could not get XPCOM event queue! hrc=%Rhrc\n", hrc));
691 VBoxClientUninitialize();
692 return hrc;
693 }
694#endif /* VBOX_WITH_XPCOM */
695
696#ifdef VBOX_WITH_XPCOM
697 nsIComponentManager *pManager = NULL;
698 hrc = NS_GetComponentManager(&pManager);
699 if (FAILED(hrc))
700 {
701 Log(("Cbinding: Could not get component manager! hrc=%Rhrc\n", hrc));
702 VBoxClientUninitialize();
703 return hrc;
704 }
705
706 hrc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
707 nsnull,
708 virtualBoxClientIID,
709 (void **)ppVirtualBoxClient);
710#else /* !VBOX_WITH_XPCOM */
711 hrc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, virtualBoxClientIID, (void **)ppVirtualBoxClient);
712#endif /* !VBOX_WITH_XPCOM */
713 if (FAILED(hrc))
714 {
715 Log(("Cbinding: Could not instantiate VirtualBoxClient object! hrc=%Rhrc\n",hrc));
716#ifdef VBOX_WITH_XPCOM
717 pManager->Release();
718 pManager = NULL;
719#endif /* VBOX_WITH_XPCOM */
720 VBoxClientUninitialize();
721 return hrc;
722 }
723
724#ifdef VBOX_WITH_XPCOM
725 pManager->Release();
726 pManager = NULL;
727#endif /* VBOX_WITH_XPCOM */
728
729 Log(("Cbinding: IVirtualBoxClient object created.\n"));
730
731 return S_OK;
732}
733
734static HRESULT
735VBoxClientThreadInitialize(void)
736{
737 return com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
738}
739
740static HRESULT
741VBoxClientThreadUninitialize(void)
742{
743 return com::Shutdown();
744}
745
746static void
747VBoxClientUninitialize(void)
748{
749#ifdef VBOX_WITH_XPCOM
750 if (g_EventQueue)
751 {
752 NS_RELEASE(g_EventQueue);
753 g_EventQueue = NULL;
754 }
755#endif /* VBOX_WITH_XPCOM */
756 com::Shutdown();
757 Log(("Cbinding: Cleaned up the created objects.\n"));
758}
759
760static unsigned int
761VBoxVersion(void)
762{
763 return VBOX_VERSION_MAJOR * 1000 * 1000 + VBOX_VERSION_MINOR * 1000 + VBOX_VERSION_BUILD;
764}
765
766static unsigned int
767VBoxAPIVersion(void)
768{
769 return VBOX_VERSION_MAJOR * 1000 + VBOX_VERSION_MINOR + (VBOX_VERSION_BUILD > 50 ? 1 : 0);
770}
771
772VBOXCAPI_DECL(PCVBOXCAPI)
773VBoxGetCAPIFunctions(unsigned uVersion)
774{
775 /* This is the first piece of code which knows that IPRT exists, so
776 * initialize it properly. The limited initialization in VBoxC is not
777 * sufficient, and causes trouble with com::Initialize() misbehaving. */
778 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
779
780 /*
781 * The current interface version.
782 */
783 static const VBOXCAPI s_Functions =
784 {
785 sizeof(VBOXCAPI),
786 VBOX_CAPI_VERSION,
787
788 VBoxVersion,
789 VBoxAPIVersion,
790
791 VBoxClientInitialize,
792 VBoxClientThreadInitialize,
793 VBoxClientThreadUninitialize,
794 VBoxClientUninitialize,
795
796 VBoxComInitialize,
797 VBoxComUninitialize,
798
799 VBoxComUnallocString,
800
801 VBoxUtf16ToUtf8,
802 VBoxUtf8ToUtf16,
803 VBoxUtf8Free,
804 VBoxUtf16Free,
805
806 VBoxSafeArrayCreateVector,
807 VBoxSafeArrayOutParamAlloc,
808 VBoxSafeArrayCopyInParamHelper,
809 VBoxSafeArrayCopyOutParamHelper,
810 VBoxSafeArrayCopyOutIfaceParamHelper,
811 VBoxSafeArrayDestroy,
812 VBoxArrayOutFree,
813
814#ifdef VBOX_WITH_XPCOM
815 VBoxGetEventQueue,
816#endif /* VBOX_WITH_XPCOM */
817 VBoxGetException,
818 VBoxClearException,
819 VBoxProcessEventQueue,
820 VBoxInterruptEventQueueProcessing,
821
822 VBoxUtf8Clear,
823 VBoxUtf16Clear,
824
825 VBOX_CAPI_VERSION
826 };
827
828 if ((uVersion & 0xffff0000U) == (VBOX_CAPI_VERSION & 0xffff0000U))
829 return &s_Functions;
830
831 /*
832 * Legacy interface version 3.0.
833 */
834 static const struct VBOXCAPIV3
835 {
836 /** The size of the structure. */
837 unsigned cb;
838 /** The structure version. */
839 unsigned uVersion;
840
841 unsigned int (*pfnGetVersion)(void);
842
843 unsigned int (*pfnGetAPIVersion)(void);
844
845 HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
846 IVirtualBoxClient **ppVirtualBoxClient);
847 void (*pfnClientUninitialize)(void);
848
849 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
850 IVirtualBox **ppVirtualBox,
851 const char *pszSessionIID,
852 ISession **ppSession);
853
854 void (*pfnComUninitialize)(void);
855
856 void (*pfnComUnallocMem)(void *pv);
857
858 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
859 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
860 void (*pfnUtf8Free)(char *pszString);
861 void (*pfnUtf16Free)(BSTR pwszString);
862
863#ifdef VBOX_WITH_XPCOM
864 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
865#endif /* VBOX_WITH_XPCOM */
866 HRESULT (*pfnGetException)(IErrorInfo **ppException);
867 HRESULT (*pfnClearException)(void);
868
869 /** Tail version, same as uVersion. */
870 unsigned uEndVersion;
871 } s_Functions_v3_0 =
872 {
873 sizeof(s_Functions_v3_0),
874 0x00030000U,
875
876 VBoxVersion,
877 VBoxAPIVersion,
878
879 VBoxClientInitialize,
880 VBoxClientUninitialize,
881
882 VBoxComInitialize,
883 VBoxComUninitialize,
884
885 VBoxComUnallocMem,
886
887 VBoxUtf16ToUtf8,
888 VBoxUtf8ToUtf16,
889 VBoxUtf8Free,
890 VBoxUtf16Free,
891
892#ifdef VBOX_WITH_XPCOM
893 VBoxGetEventQueue,
894#endif /* VBOX_WITH_XPCOM */
895 VBoxGetException,
896 VBoxClearException,
897
898 0x00030000U
899 };
900
901 if ((uVersion & 0xffff0000U) == 0x00030000U)
902 return (PCVBOXCAPI)&s_Functions_v3_0;
903
904 /*
905 * Legacy interface version 2.0.
906 */
907 static const struct VBOXCAPIV2
908 {
909 /** The size of the structure. */
910 unsigned cb;
911 /** The structure version. */
912 unsigned uVersion;
913
914 unsigned int (*pfnGetVersion)(void);
915
916 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
917 IVirtualBox **ppVirtualBox,
918 const char *pszSessionIID,
919 ISession **ppSession);
920
921 void (*pfnComUninitialize)(void);
922
923 void (*pfnComUnallocMem)(void *pv);
924 void (*pfnUtf16Free)(BSTR pwszString);
925 void (*pfnUtf8Free)(char *pszString);
926
927 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
928 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
929
930#ifdef VBOX_WITH_XPCOM
931 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
932#endif /* VBOX_WITH_XPCOM */
933
934 /** Tail version, same as uVersion. */
935 unsigned uEndVersion;
936 } s_Functions_v2_0 =
937 {
938 sizeof(s_Functions_v2_0),
939 0x00020000U,
940
941 VBoxVersion,
942
943 VBoxComInitialize,
944 VBoxComUninitialize,
945
946 VBoxComUnallocMem,
947 VBoxUtf16Free,
948 VBoxUtf8Free,
949
950 VBoxUtf16ToUtf8,
951 VBoxUtf8ToUtf16,
952
953#ifdef VBOX_WITH_XPCOM
954 VBoxGetEventQueue,
955#endif /* VBOX_WITH_XPCOM */
956
957 0x00020000U
958 };
959
960 if ((uVersion & 0xffff0000U) == 0x00020000U)
961 return (PCVBOXCAPI)&s_Functions_v2_0;
962
963 /*
964 * Legacy interface version 1.0.
965 */
966 static const struct VBOXCAPIV1
967 {
968 /** The size of the structure. */
969 unsigned cb;
970 /** The structure version. */
971 unsigned uVersion;
972
973 unsigned int (*pfnGetVersion)(void);
974
975 void (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
976 void (*pfnComUninitialize)(void);
977
978 void (*pfnComUnallocMem)(void *pv);
979 void (*pfnUtf16Free)(BSTR pwszString);
980 void (*pfnUtf8Free)(char *pszString);
981
982 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
983 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
984
985 /** Tail version, same as uVersion. */
986 unsigned uEndVersion;
987 } s_Functions_v1_0 =
988 {
989 sizeof(s_Functions_v1_0),
990 0x00010000U,
991
992 VBoxVersion,
993
994 VBoxComInitializeV1,
995 VBoxComUninitialize,
996
997 VBoxComUnallocMem,
998 VBoxUtf16Free,
999 VBoxUtf8Free,
1000
1001 VBoxUtf16ToUtf8,
1002 VBoxUtf8ToUtf16,
1003
1004 0x00010000U
1005 };
1006
1007 if ((uVersion & 0xffff0000U) == 0x00010000U)
1008 return (PCVBOXCAPI)&s_Functions_v1_0;
1009
1010 /*
1011 * Unsupported interface version.
1012 */
1013 return NULL;
1014}
1015
1016#ifdef VBOX_WITH_XPCOM
1017VBOXCAPI_DECL(PCVBOXCAPI)
1018VBoxGetXPCOMCFunctions(unsigned uVersion)
1019{
1020 return VBoxGetCAPIFunctions(uVersion);
1021}
1022#endif /* VBOX_WITH_XPCOM */
1023/* 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