VirtualBox

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

Last change on this file since 50930 was 50930, checked in by vboxsync, 11 years ago

Main/cbinding: Add new helper function to free memory allocated by pfnSafeArrayCopyOutParamHelper, as on Windows getting the right free() function can be difficult otherwise. Fix pfnSafeArrayCopyOutParamHelper to be more robust (avoiding malloc(0) and returning bogus values in some error situations), and extend the sample code somewhat to print the groups (showing how to deal with string arrays)

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