VirtualBox

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

Last change on this file since 58106 was 55752, checked in by vboxsync, 10 years ago

Main/cbinding: fix incorrect freeing of string arrays on Windows host, and fix a memory leak in the sample code

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