VirtualBox

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

最後變更 在這個檔案從62770是 62770,由 vboxsync 提交於 9 年 前

Main/cbining: warnings

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette