VirtualBox

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

Last change on this file was 103355, checked in by vboxsync, 3 months ago

Main/VBoxCAPI.cpp: Try initialize pManager to NULL to see if that shuts up parfait warnings about using it uninitialized. bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.9 KB
RevLine 
[16487]1/* $Id: VBoxCAPI.cpp 103355 2024-02-14 14:13:23Z vboxsync $ */
[50183]2/** @file VBoxCAPI.cpp
3 * Utility functions to use with the C API binding.
[16483]4 */
5
6/*
[98103]7 * Copyright (C) 2009-2023 Oracle and/or its affiliates.
[16483]8 *
[96407]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
[16483]26 */
27
[16534]28#define LOG_GROUP LOG_GROUP_MAIN
[16406]29
[50183]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
[76346]40#include <iprt/env.h>
41#include <iprt/err.h>
[50183]42#include <iprt/initterm.h>
[76346]43#include <iprt/mem.h>
[16406]44#include <iprt/string.h>
[76408]45#include <iprt/utf16.h>
[50183]46#include <iprt/uuid.h>
[16534]47#include <VBox/log.h>
[50183]48#include <VBox/version.h>
[16406]49
[16684]50#include "VBox/com/com.h"
[50183]51#include "VBox/com/NativeEventQueue.h"
[16406]52
[63447]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]*/
[16406]55using namespace std;
[63447]56#endif
[16406]57
[50183]58/* The following 2 object references should be eliminated once the legacy
59 * way to initialize the COM/XPCOM C bindings is removed. */
[49539]60static ISession *g_Session = NULL;
61static IVirtualBox *g_VirtualBox = NULL;
[16406]62
[50183]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. */
[49539]66static nsIEventQueue *g_EventQueue = NULL;
[50183]67#endif /* VBOX_WITH_XPCOM */
[49539]68
[18137]69static void VBoxComUninitialize(void);
[49539]70static void VBoxClientUninitialize(void);
[17712]71
[18137]72static int
[50183]73VBoxUtf16ToUtf8(CBSTR pwszString, char **ppszString)
[16406]74{
[50183]75 if (!pwszString)
76 {
77 *ppszString = NULL;
78 return VINF_SUCCESS;
79 }
[16497]80 return RTUtf16ToUtf8(pwszString, ppszString);
[16406]81}
82
[18137]83static int
[50183]84VBoxUtf8ToUtf16(const char *pszString, BSTR *ppwszString)
[16406]85{
[62770]86 *ppwszString = NULL;
[50183]87 if (!pszString)
88 return VINF_SUCCESS;
89#ifdef VBOX_WITH_XPCOM
[16406]90 return RTStrToUtf16(pszString, ppwszString);
[50183]91#else /* !VBOX_WITH_XPCOM */
92 PRTUTF16 pwsz;
93 int vrc = RTStrToUtf16(pszString, &pwsz);
[62770]94 if (RT_SUCCESS(vrc))
95 {
96 *ppwszString = ::SysAllocString(pwsz);
97 if (!*ppwszString)
98 vrc = VERR_NO_STR_MEMORY;
99 RTUtf16Free(pwsz);
100 }
[50183]101 return vrc;
102#endif /* !VBOX_WITH_XPCOM */
[16406]103}
104
[18137]105static void
[54027]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
[50183]118VBoxUtf16Free(BSTR pwszString)
[16406]119{
[50183]120#ifdef VBOX_WITH_XPCOM
[16406]121 RTUtf16Free(pwszString);
[62770]122#else
[50183]123 ::SysFreeString(pwszString);
[62770]124#endif
[16406]125}
126
[18137]127static void
[16497]128VBoxUtf8Free(char *pszString)
[16406]129{
130 RTStrFree(pszString);
131}
132
[18137]133static void
[50183]134VBoxComUnallocString(BSTR pwsz)
[16406]135{
[50183]136 if (pwsz)
137 {
138#ifdef VBOX_WITH_XPCOM
139 nsMemory::Free(pwsz);
[62770]140#else
[50183]141 ::SysFreeString(pwsz);
[62770]142#endif
[50183]143 }
[16406]144}
145
[18137]146static void
[50183]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 */
[55752]230 VARTYPE vt = VT_UNKNOWN;
[98297]231 HRESULT hrc = SafeArrayGetVartype(psa, &vt);
232 if (FAILED(hrc))
233 return hrc;
[55752]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;
[98297]240 hrc = SafeArrayAccessData(psa, &pData);
241 if (FAILED(hrc))
242 return hrc;
[55752]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 }
[50183]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 */
[98297]267 HRESULT hrc = SafeArrayAccessData(psa, &pData);
268 if (FAILED(hrc))
269 return hrc;
[50183]270#endif /* !VBOX_WITH_XPCOM */
271 memcpy(pData, pv, cb);
272#ifndef VBOX_WITH_XPCOM
273 SafeArrayUnaccessData(psa);
[62770]274#endif
[50183]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)
[50930]285 {
286 *ppv = NULL;
287 if (pcb)
288 *pcb = 0;
[50183]289 return E_INVALIDARG;
[50930]290 }
[50183]291#ifndef VBOX_WITH_XPCOM
292 if (psa->cDims != 1)
[50930]293 {
294 *ppv = NULL;
295 if (pcb)
296 *pcb = 0;
[50183]297 return E_INVALIDARG;
[50930]298 }
[50183]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 */
[98297]307 HRESULT hrc = SafeArrayAccessData(psa, &pData);
308 if (FAILED(hrc))
[50930]309 {
310 *ppv = NULL;
311 if (pcb)
312 *pcb = 0;
[98297]313 return hrc;
[50930]314 }
[50183]315 cElements = psa->rgsabound[0].cElements;
316#endif /* !VBOX_WITH_XPCOM */
317 size_t cbTotal = cbElement * cElements;
[50930]318 void *pv = NULL;
319 if (cbTotal)
[50183]320 {
[50930]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);
[50183]331 }
[50930]332 *ppv = pv;
333 if (pcb)
334 *pcb = (ULONG)cbTotal;
[50183]335#ifndef VBOX_WITH_XPCOM
336 SafeArrayUnaccessData(psa);
[62770]337#endif
[50183]338 return S_OK;
339}
340
341static HRESULT
342VBoxSafeArrayCopyOutIfaceParamHelper(IUnknown ***ppaObj, ULONG *pcObj, SAFEARRAY *psa)
343{
344 ULONG mypcb;
[98297]345 HRESULT hrc = VBoxSafeArrayCopyOutParamHelper((void **)ppaObj, &mypcb, VT_UNKNOWN, psa);
346 if (FAILED(hrc))
[50930]347 {
348 if (pcObj)
349 *pcObj = 0;
[98297]350 return hrc;
[50930]351 }
[50183]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
[50930]370static HRESULT
371VBoxArrayOutFree(void *pv)
372{
373 free(pv);
374 return S_OK;
375}
376
[50183]377static void
[19081]378VBoxComInitialize(const char *pszVirtualBoxIID, IVirtualBox **ppVirtualBox,
379 const char *pszSessionIID, ISession **ppSession)
[16406]380{
[50183]381 int vrc;
382 IID virtualBoxIID;
383 IID sessionIID;
[16406]384
[19081]385 *ppSession = NULL;
386 *ppVirtualBox = NULL;
[16406]387
[50183]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;
[19106]405
[98297]406 HRESULT hrc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
407 if (FAILED(hrc))
[16406]408 {
[98297]409 Log(("Cbinding: COM/XPCOM could not be initialized! hrc=%Rhrc\n", hrc));
[16406]410 VBoxComUninitialize();
411 return;
412 }
413
[50183]414#ifdef VBOX_WITH_XPCOM
[98297]415 hrc = NS_GetMainEventQ(&g_EventQueue);
416 if (FAILED(hrc))
[16406]417 {
[98297]418 Log(("Cbinding: Could not get XPCOM event queue! hrc=%Rhrc\n", hrc));
[16406]419 VBoxComUninitialize();
420 return;
421 }
[50183]422#endif /* VBOX_WITH_XPCOM */
[16406]423
[50183]424#ifdef VBOX_WITH_XPCOM
[103355]425 nsIComponentManager *pManager = NULL;
[98297]426 hrc = NS_GetComponentManager(&pManager);
427 if (FAILED(hrc))
[18998]428 {
[98297]429 Log(("Cbinding: Could not get component manager! hrc=%Rhrc\n", hrc));
[18998]430 VBoxComUninitialize();
431 return;
432 }
433
[98297]434 hrc = pManager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID,
435 nsnull,
436 virtualBoxIID,
437 (void **)&g_VirtualBox);
[50183]438#else /* !VBOX_WITH_XPCOM */
[60063]439 IVirtualBoxClient *pVirtualBoxClient;
[98297]440 hrc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, IID_IVirtualBoxClient, (void **)&pVirtualBoxClient);
441 if (SUCCEEDED(hrc))
[60063]442 {
443 IVirtualBox *pVirtualBox;
[98297]444 hrc = pVirtualBoxClient->get_VirtualBox(&pVirtualBox);
445 if (SUCCEEDED(hrc))
[60063]446 {
[98297]447 hrc = pVirtualBox->QueryInterface(virtualBoxIID, (void **)&g_VirtualBox);
[60063]448 pVirtualBox->Release();
449 }
450 pVirtualBoxClient->Release();
451 }
[50183]452#endif /* !VBOX_WITH_XPCOM */
[98297]453 if (FAILED(hrc))
[16406]454 {
[98297]455 Log(("Cbinding: Could not instantiate VirtualBox object! hrc=%Rhrc\n",hrc));
[50183]456#ifdef VBOX_WITH_XPCOM
457 pManager->Release();
458 pManager = NULL;
459#endif /* VBOX_WITH_XPCOM */
[16406]460 VBoxComUninitialize();
461 return;
462 }
463
[16513]464 Log(("Cbinding: IVirtualBox object created.\n"));
[16406]465
[50183]466#ifdef VBOX_WITH_XPCOM
[98297]467 hrc = pManager->CreateInstanceByContractID(NS_SESSION_CONTRACTID, nsnull, sessionIID, (void **)&g_Session);
[50183]468#else /* !VBOX_WITH_XPCOM */
[98297]469 hrc = CoCreateInstance(CLSID_Session, NULL, CLSCTX_INPROC_SERVER, sessionIID, (void **)&g_Session);
[50183]470#endif /* !VBOX_WITH_XPCOM */
[98297]471 if (FAILED(hrc))
[16406]472 {
[98297]473 Log(("Cbinding: Could not instantiate Session object! hrc=%Rhrc\n",hrc));
[50183]474#ifdef VBOX_WITH_XPCOM
475 pManager->Release();
476 pManager = NULL;
477#endif /* VBOX_WITH_XPCOM */
[16406]478 VBoxComUninitialize();
479 return;
480 }
481
[16513]482 Log(("Cbinding: ISession object created.\n"));
[19098]483
[50183]484#ifdef VBOX_WITH_XPCOM
485 pManager->Release();
486 pManager = NULL;
487#endif /* VBOX_WITH_XPCOM */
488
[49539]489 *ppSession = g_Session;
490 *ppVirtualBox = g_VirtualBox;
[16406]491}
492
[18137]493static void
[19081]494VBoxComInitializeV1(IVirtualBox **ppVirtualBox, ISession **ppSession)
495{
[50183]496 VBoxComInitialize(NULL, ppVirtualBox, NULL, ppSession);
[19081]497}
498
499static void
[16488]500VBoxComUninitialize(void)
[16406]501{
[49539]502 if (g_Session)
503 {
[50183]504 g_Session->Release();
[49539]505 g_Session = NULL;
506 }
507 if (g_VirtualBox)
508 {
[50183]509 g_VirtualBox->Release();
[49539]510 g_VirtualBox = NULL;
511 }
[50183]512#ifdef VBOX_WITH_XPCOM
[49539]513 if (g_EventQueue)
514 {
[50183]515 g_EventQueue->Release();
[49539]516 g_EventQueue = NULL;
517 }
[50183]518#endif /* VBOX_WITH_XPCOM */
[16684]519 com::Shutdown();
[49539]520 Log(("Cbinding: Cleaned up the created objects.\n"));
[16406]521}
522
[50183]523#ifdef VBOX_WITH_XPCOM
[18998]524static void
[49539]525VBoxGetEventQueue(nsIEventQueue **ppEventQueue)
[18998]526{
[49539]527 *ppEventQueue = g_EventQueue;
[18998]528}
[50183]529#endif /* VBOX_WITH_XPCOM */
[18998]530
[50183]531static int
532VBoxProcessEventQueue(LONG64 iTimeoutMS)
[17837]533{
[50183]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}
[16832]556
[50183]557static int
558VBoxInterruptEventQueueProcessing(void)
559{
560 com::NativeEventQueue::getMainEventQueue()->interruptEventQueueProcessing();
561 return 0;
562}
563
564static HRESULT
565VBoxGetException(IErrorInfo **ppException)
566{
[98297]567 HRESULT hrc;
[50183]568
[49539]569 *ppException = NULL;
[50183]570
571#ifdef VBOX_WITH_XPCOM
[49539]572 nsIServiceManager *mgr = NULL;
[98297]573 hrc = NS_GetServiceManager(&mgr);
574 if (FAILED(hrc) || !mgr)
575 return hrc;
[17837]576
[50183]577 IID esid = NS_IEXCEPTIONSERVICE_IID;
[49539]578 nsIExceptionService *es = NULL;
[98297]579 hrc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
580 if (FAILED(hrc) || !es)
[49539]581 {
[50183]582 mgr->Release();
[98297]583 return hrc;
[49539]584 }
585
586 nsIExceptionManager *em;
[98297]587 hrc = es->GetCurrentExceptionManager(&em);
588 if (FAILED(hrc) || !em)
[49539]589 {
[50183]590 es->Release();
591 mgr->Release();
[98297]592 return hrc;
[49539]593 }
594
595 nsIException *ex;
[98297]596 hrc = em->GetCurrentException(&ex);
597 if (FAILED(hrc))
[49539]598 {
[50183]599 em->Release();
600 es->Release();
601 mgr->Release();
[98297]602 return hrc;
[49539]603 }
604
605 *ppException = ex;
[50183]606 em->Release();
607 es->Release();
608 mgr->Release();
609#else /* !VBOX_WITH_XPCOM */
610 IErrorInfo *ex;
[98297]611 hrc = ::GetErrorInfo(0, &ex);
612 if (FAILED(hrc))
613 return hrc;
[50183]614
615 *ppException = ex;
616#endif /* !VBOX_WITH_XPCOM */
617
[98297]618 return hrc;
[17837]619}
620
[50183]621static HRESULT
[49539]622VBoxClearException(void)
623{
[98297]624 HRESULT hrc;
[49539]625
[50183]626#ifdef VBOX_WITH_XPCOM
[49539]627 nsIServiceManager *mgr = NULL;
[98297]628 hrc = NS_GetServiceManager(&mgr);
629 if (FAILED(hrc) || !mgr)
630 return hrc;
[49539]631
[50183]632 IID esid = NS_IEXCEPTIONSERVICE_IID;
[49539]633 nsIExceptionService *es = NULL;
[98297]634 hrc = mgr->GetServiceByContractID(NS_EXCEPTIONSERVICE_CONTRACTID, esid, (void **)&es);
635 if (FAILED(hrc) || !es)
[49539]636 {
[50183]637 mgr->Release();
[98297]638 return hrc;
[49539]639 }
640
641 nsIExceptionManager *em;
[98297]642 hrc = es->GetCurrentExceptionManager(&em);
643 if (FAILED(hrc) || !em)
[49539]644 {
[50183]645 es->Release();
646 mgr->Release();
[98297]647 return hrc;
[49539]648 }
649
[98297]650 hrc = em->SetCurrentException(NULL);
[50183]651 em->Release();
652 es->Release();
653 mgr->Release();
654#else /* !VBOX_WITH_XPCOM */
[98297]655 hrc = ::SetErrorInfo(0, NULL);
[50183]656#endif /* !VBOX_WITH_XPCOM */
657
[98297]658 return hrc;
[49539]659}
660
[50183]661static HRESULT
[49539]662VBoxClientInitialize(const char *pszVirtualBoxClientIID, IVirtualBoxClient **ppVirtualBoxClient)
663{
[50183]664 IID virtualBoxClientIID;
[49539]665
666 *ppVirtualBoxClient = NULL;
667
[50183]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;
[49539]677
[98297]678 HRESULT hrc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
679 if (FAILED(hrc))
[49539]680 {
[98297]681 Log(("Cbinding: COM/XPCOM could not be initialized! hrc=%Rhrc\n", hrc));
[49539]682 VBoxClientUninitialize();
[98297]683 return hrc;
[49539]684 }
685
[50183]686#ifdef VBOX_WITH_XPCOM
[98297]687 hrc = NS_GetMainEventQ(&g_EventQueue);
688 if (NS_FAILED(hrc))
[49539]689 {
[98297]690 Log(("Cbinding: Could not get XPCOM event queue! hrc=%Rhrc\n", hrc));
[49539]691 VBoxClientUninitialize();
[98297]692 return hrc;
[49539]693 }
[50183]694#endif /* VBOX_WITH_XPCOM */
[49539]695
[50183]696#ifdef VBOX_WITH_XPCOM
[103355]697 nsIComponentManager *pManager = NULL;
[98297]698 hrc = NS_GetComponentManager(&pManager);
699 if (FAILED(hrc))
[49539]700 {
[98297]701 Log(("Cbinding: Could not get component manager! hrc=%Rhrc\n", hrc));
[49539]702 VBoxClientUninitialize();
[98297]703 return hrc;
[49539]704 }
705
[98297]706 hrc = pManager->CreateInstanceByContractID(NS_VIRTUALBOXCLIENT_CONTRACTID,
707 nsnull,
708 virtualBoxClientIID,
709 (void **)ppVirtualBoxClient);
[50183]710#else /* !VBOX_WITH_XPCOM */
[98297]711 hrc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER, virtualBoxClientIID, (void **)ppVirtualBoxClient);
[50183]712#endif /* !VBOX_WITH_XPCOM */
[98297]713 if (FAILED(hrc))
[49539]714 {
[98297]715 Log(("Cbinding: Could not instantiate VirtualBoxClient object! hrc=%Rhrc\n",hrc));
[50183]716#ifdef VBOX_WITH_XPCOM
717 pManager->Release();
718 pManager = NULL;
719#endif /* VBOX_WITH_XPCOM */
[49539]720 VBoxClientUninitialize();
[98297]721 return hrc;
[49539]722 }
723
[50183]724#ifdef VBOX_WITH_XPCOM
725 pManager->Release();
[49539]726 pManager = NULL;
[50183]727#endif /* VBOX_WITH_XPCOM */
[49539]728
729 Log(("Cbinding: IVirtualBoxClient object created.\n"));
730
[50183]731 return S_OK;
[49539]732}
733
[50183]734static HRESULT
735VBoxClientThreadInitialize(void)
736{
[78088]737 return com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING);
[50183]738}
739
740static HRESULT
741VBoxClientThreadUninitialize(void)
742{
743 return com::Shutdown();
744}
745
[49539]746static void
747VBoxClientUninitialize(void)
748{
[50183]749#ifdef VBOX_WITH_XPCOM
[49539]750 if (g_EventQueue)
751 {
752 NS_RELEASE(g_EventQueue);
753 g_EventQueue = NULL;
754 }
[50183]755#endif /* VBOX_WITH_XPCOM */
[49539]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
[50183]772VBOXCAPI_DECL(PCVBOXCAPI)
773VBoxGetCAPIFunctions(unsigned uVersion)
[16832]774{
[50183]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. */
[98694]778 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
[50183]779
[19078]780 /*
781 * The current interface version.
782 */
[50183]783 static const VBOXCAPI s_Functions =
[16832]784 {
[50183]785 sizeof(VBOXCAPI),
786 VBOX_CAPI_VERSION,
[16832]787
[17837]788 VBoxVersion,
[49539]789 VBoxAPIVersion,
[17837]790
[49539]791 VBoxClientInitialize,
[50183]792 VBoxClientThreadInitialize,
793 VBoxClientThreadUninitialize,
[49539]794 VBoxClientUninitialize,
795
[16832]796 VBoxComInitialize,
797 VBoxComUninitialize,
798
[50183]799 VBoxComUnallocString,
[16832]800
801 VBoxUtf16ToUtf8,
802 VBoxUtf8ToUtf16,
[49539]803 VBoxUtf8Free,
804 VBoxUtf16Free,
[16832]805
[50183]806 VBoxSafeArrayCreateVector,
807 VBoxSafeArrayOutParamAlloc,
808 VBoxSafeArrayCopyInParamHelper,
809 VBoxSafeArrayCopyOutParamHelper,
810 VBoxSafeArrayCopyOutIfaceParamHelper,
811 VBoxSafeArrayDestroy,
[50930]812 VBoxArrayOutFree,
[50183]813
814#ifdef VBOX_WITH_XPCOM
[18998]815 VBoxGetEventQueue,
[50183]816#endif /* VBOX_WITH_XPCOM */
[49539]817 VBoxGetException,
818 VBoxClearException,
[50183]819 VBoxProcessEventQueue,
820 VBoxInterruptEventQueueProcessing,
[18998]821
[54027]822 VBoxUtf8Clear,
823 VBoxUtf16Clear,
824
[50183]825 VBOX_CAPI_VERSION
[16832]826 };
827
[50183]828 if ((uVersion & 0xffff0000U) == (VBOX_CAPI_VERSION & 0xffff0000U))
[19078]829 return &s_Functions;
[16832]830
[19078]831 /*
[50183]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
[54027]849 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
850 IVirtualBox **ppVirtualBox,
851 const char *pszSessionIID,
852 ISession **ppSession);
[50183]853
[54027]854 void (*pfnComUninitialize)(void);
[50183]855
[54027]856 void (*pfnComUnallocMem)(void *pv);
[50183]857
[54027]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);
[50183]862
863#ifdef VBOX_WITH_XPCOM
[54027]864 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
[50183]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 /*
[49539]905 * Legacy interface version 2.0.
906 */
[50183]907 static const struct VBOXCAPIV2
[49539]908 {
909 /** The size of the structure. */
910 unsigned cb;
911 /** The structure version. */
912 unsigned uVersion;
913
914 unsigned int (*pfnGetVersion)(void);
915
[54027]916 void (*pfnComInitialize)(const char *pszVirtualBoxIID,
917 IVirtualBox **ppVirtualBox,
918 const char *pszSessionIID,
919 ISession **ppSession);
[49539]920
[54027]921 void (*pfnComUninitialize)(void);
[49539]922
[54027]923 void (*pfnComUnallocMem)(void *pv);
924 void (*pfnUtf16Free)(BSTR pwszString);
925 void (*pfnUtf8Free)(char *pszString);
[49539]926
[54027]927 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
928 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
[49539]929
[50183]930#ifdef VBOX_WITH_XPCOM
[54027]931 void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
[50183]932#endif /* VBOX_WITH_XPCOM */
[49539]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
[50183]953#ifdef VBOX_WITH_XPCOM
[49539]954 VBoxGetEventQueue,
[50183]955#endif /* VBOX_WITH_XPCOM */
[49539]956
957 0x00020000U
958 };
959
960 if ((uVersion & 0xffff0000U) == 0x00020000U)
[50183]961 return (PCVBOXCAPI)&s_Functions_v2_0;
[49539]962
963 /*
[19078]964 * Legacy interface version 1.0.
965 */
[50183]966 static const struct VBOXCAPIV1
[19078]967 {
968 /** The size of the structure. */
969 unsigned cb;
970 /** The structure version. */
971 unsigned uVersion;
972
973 unsigned int (*pfnGetVersion)(void);
974
[54027]975 void (*pfnComInitialize)(IVirtualBox **virtualBox, ISession **session);
976 void (*pfnComUninitialize)(void);
[19078]977
[54027]978 void (*pfnComUnallocMem)(void *pv);
979 void (*pfnUtf16Free)(BSTR pwszString);
980 void (*pfnUtf8Free)(char *pszString);
[19078]981
[54027]982 int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
983 int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
[19078]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
[19081]994 VBoxComInitializeV1,
[19078]995 VBoxComUninitialize,
996
997 VBoxComUnallocMem,
998 VBoxUtf16Free,
999 VBoxUtf8Free,
1000
1001 VBoxUtf16ToUtf8,
1002 VBoxUtf8ToUtf16,
1003
1004 0x00010000U
1005 };
1006
1007 if ((uVersion & 0xffff0000U) == 0x00010000U)
[50183]1008 return (PCVBOXCAPI)&s_Functions_v1_0;
[19078]1009
1010 /*
1011 * Unsupported interface version.
1012 */
1013 return NULL;
[16832]1014}
1015
[50183]1016#ifdef VBOX_WITH_XPCOM
1017VBOXCAPI_DECL(PCVBOXCAPI)
1018VBoxGetXPCOMCFunctions(unsigned uVersion)
1019{
1020 return VBoxGetCAPIFunctions(uVersion);
1021}
1022#endif /* VBOX_WITH_XPCOM */
[16406]1023/* vim: set ts=4 sw=4 et: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use