VirtualBox

Changeset 50930 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 31, 2014 3:55:14 PM (11 years ago)
Author:
vboxsync
Message:

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)

Location:
trunk/src/VBox/Main/cbinding
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/cbinding/VBoxCAPI.cpp

    r50183 r50930  
    232232    ULONG cbElement = VBoxVTElemSize(vt);
    233233    if (!cbElement)
     234    {
     235        *ppv = NULL;
     236        if (pcb)
     237            *pcb = 0;
    234238        return E_INVALIDARG;
     239    }
    235240#ifndef VBOX_WITH_XPCOM
    236241    if (psa->cDims != 1)
     242    {
     243        *ppv = NULL;
     244        if (pcb)
     245            *pcb = 0;
    237246        return E_INVALIDARG;
     247    }
    238248    Assert(cbElement = psa->cbElements);
    239249#endif /* !VBOX_WITH_XPCOM */
     
    246256    HRESULT rc = SafeArrayAccessData(psa, &pData);
    247257    if (FAILED(rc))
    248         return rc;
     258    {
     259        *ppv = NULL;
     260        if (pcb)
     261            *pcb = 0;
     262        return rc;
     263    }
    249264    cElements = psa->rgsabound[0].cElements;
    250265#endif /* !VBOX_WITH_XPCOM */
    251266    size_t cbTotal = cbElement * cElements;
    252     void *pv = malloc(cbTotal);
    253     if (pv)
    254     {
    255         memcpy(pv, pData, cbTotal);
    256         *ppv = pv;
    257         if (pcb)
    258             *pcb = (ULONG)cbTotal;
    259     }
     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;
    260284#ifndef VBOX_WITH_XPCOM
    261285    SafeArrayUnaccessData(psa);
     
    270294    HRESULT rc = VBoxSafeArrayCopyOutParamHelper((void **)ppaObj, &mypcb, VT_UNKNOWN, psa);
    271295    if (FAILED(rc))
    272         return rc;
     296    {
     297        if (pcObj)
     298            *pcObj = 0;
     299        return rc;
     300    }
    273301    ULONG cElements = mypcb / sizeof(void *);
    274302    if (pcObj)
     
    286314    }
    287315#endif /* VBOX_WITH_XPCOM */
     316    return S_OK;
     317}
     318
     319static HRESULT
     320VBoxArrayOutFree(void *pv)
     321{
     322    free(pv);
    288323    return S_OK;
    289324}
     
    715750        VBoxSafeArrayCopyOutIfaceParamHelper,
    716751        VBoxSafeArrayDestroy,
     752        VBoxArrayOutFree,
    717753
    718754#ifdef VBOX_WITH_XPCOM
     
    731767
    732768    /*
    733      * Legacy interface version 3.0.
     769     * Legacy interface version 4.0.
    734770     */
    735     static const struct VBOXCAPIV3
     771    static const struct VBOXCAPIV4
    736772    {
    737773        /** The size of the structure. */
     
    741777
    742778        unsigned int (*pfnGetVersion)(void);
    743 
    744779        unsigned int (*pfnGetAPIVersion)(void);
    745780
    746781        HRESULT (*pfnClientInitialize)(const char *pszVirtualBoxClientIID,
    747782                                       IVirtualBoxClient **ppVirtualBoxClient);
     783        HRESULT (*pfnClientThreadInitialize)(void);
     784        HRESULT (*pfnClientThreadUninitialize)(void);
    748785        void (*pfnClientUninitialize)(void);
    749786
     
    755792        void  (*pfnComUninitialize)(void);
    756793
    757         void  (*pfnComUnallocMem)(void *pv);
     794        void (*pfnComUnallocString)(BSTR pwsz);
    758795
    759796        int   (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
     
    762799        void  (*pfnUtf16Free)(BSTR pwszString);
    763800
     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
    764808#ifdef VBOX_WITH_XPCOM
    765809        void  (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
     
    767811        HRESULT (*pfnGetException)(IErrorInfo **ppException);
    768812        HRESULT (*pfnClearException)(void);
     813        int (*pfnProcessEventQueue)(LONG64 iTimeoutMS);
     814        int (*pfnInterruptEventQueueProcessing)(void);
    769815
    770816        /** Tail version, same as uVersion. */
    771817        unsigned uEndVersion;
    772     } s_Functions_v3_0 =
    773     {
    774         sizeof(s_Functions_v3_0),
    775         0x00030000U,
     818    } s_Functions_v4_0 =
     819    {
     820        sizeof(s_Functions_v4_0),
     821        0x00040000U,
    776822
    777823        VBoxVersion,
     
    779825
    780826        VBoxClientInitialize,
     827        VBoxClientThreadInitialize,
     828        VBoxClientThreadUninitialize,
    781829        VBoxClientUninitialize,
    782830
     
    784832        VBoxComUninitialize,
    785833
    786         VBoxComUnallocMem,
     834        VBoxComUnallocString,
    787835
    788836        VBoxUtf16ToUtf8,
     
    791839        VBoxUtf16Free,
    792840
     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
    793923#ifdef VBOX_WITH_XPCOM
    794924        VBoxGetEventQueue,
  • trunk/src/VBox/Main/cbinding/capiidl.xsl

    r50254 r50930  
    13581358     *          owned by C bindings
    13591359     */
    1360     void  (*pfnComInitialize)(const char *pszVirtualBoxIID,
    1361                               IVirtualBox **ppVirtualBox,
    1362                               const char *pszSessionIID,
    1363                               ISession **ppSession);
     1360    void (*pfnComInitialize)(const char *pszVirtualBoxIID,
     1361                             IVirtualBox **ppVirtualBox,
     1362                             const char *pszSessionIID,
     1363                             ISession **ppSession);
    13641364    /**
    13651365     * Deprecated way to uninitialize the C bindings for an API client.
     
    13731373     * @param pwsz          pointer to string to be freed
    13741374     */
    1375     void  (*pfnComUnallocString)(BSTR pwsz);
     1375    void (*pfnComUnallocString)(BSTR pwsz);
    13761376#ifndef WIN32
    13771377    /** Legacy function, was always for freeing strings only. */
     
    13861386     * @returns IPRT status code
    13871387     */
    1388     int   (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
     1388    int (*pfnUtf16ToUtf8)(CBSTR pwszString, char **ppszString);
    13891389    /**
    13901390     * Convert string from UTF-8 encoding to UTF-16 encoding.
     
    13941394     * @returns IPRT status code
    13951395     */
    1396     int   (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
     1396    int (*pfnUtf8ToUtf16)(const char *pszString, BSTR *ppwszString);
    13971397    /**
    13981398     * Free memory returned by pfnUtf16ToUtf8. Do not use for anything else.
     
    14001400     * @param pszString     string to be freed.
    14011401     */
    1402     void  (*pfnUtf8Free)(char *pszString);
     1402    void (*pfnUtf8Free)(char *pszString);
    14031403    /**
    14041404     * Free memory returned by pfnUtf8ToUtf16. Do not use for anything else.
     
    14061406     * @param pwszString    string to be freed.
    14071407     */
    1408     void  (*pfnUtf16Free)(BSTR pwszString);
     1408    void (*pfnUtf16Free)(BSTR pwszString);
    14091409
    14101410    /**
     
    14411441     *
    14421442     * @param ppv           output pointer to newly created array, which has to
    1443      *          be freed with free().
     1443     *          be freed with pfnArrayOutFree.
    14441444     * @param pcb           number of bytes in the output buffer.
    14451445     * @param vt            variant type, defines the size of the elements
     
    14521452     *
    14531453     * @param ppaObj        output pointer to newly created array, which has
    1454      *          to be freed with free(). Note that it's the caller's
     1454     *          to be freed with pfnArrayOutFree. Note that it's the caller's
    14551455     *          responsibility to call Release() on each non-NULL interface
    14561456     *          pointer before freeing.
     
    14631463     * Free a safearray
    14641464     *
    1465      * @param psa           pointer to safearray for getting the data
     1465     * @param psa           pointer to safearray
    14661466     * @returns COM/XPCOM error code
    14671467     */
    14681468    HRESULT (*pfnSafeArrayDestroy)(SAFEARRAY *psa);
     1469    /**
     1470     * Free an out array created by pfnSafeArrayCopyOutParamHelper or
     1471     * pdnSafeArrayCopyOutIfaceParamHelper.
     1472     *
     1473     * @param psa           pointer to memory block
     1474     * @returns COM/XPCOM error code
     1475     */
     1476    HRESULT (*pfnArrayOutFree)(void *pv);
    14691477
    14701478#ifndef WIN32
     
    14751483     *              owned by C bindings.
    14761484     */
    1477     void  (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
     1485    void (*pfnGetEventQueue)(nsIEventQueue **ppEventQueue);
    14781486#endif /* !WIN32 */
    14791487
  • trunk/src/VBox/Main/cbinding/tstCAPIGlue.c

    r50254 r50930  
    740740    BSTR env              = NULL;
    741741    BSTR sessionType;
     742    SAFEARRAY *groupsSA = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc();
    742743
    743744    rc = IVirtualBox_FindMachine(virtualBox, id, &machine);
     
    746747        PrintErrorInfo(argv0, "Error: Couldn't get the Machine reference", rc);
    747748        return;
     749    }
     750
     751    rc = IMachine_get_Groups(machine, ComSafeArrayAsOutParam(groupsSA));
     752    if (SUCCEEDED(rc))
     753    {
     754        BSTR *groups = NULL;
     755        ULONG cbGroups = 0;
     756        ULONG i, cGroups;
     757        g_pVBoxFuncs->pfnSafeArrayCopyOutParamHelper((void **)&groups, &cbGroups, VT_BSTR, groupsSA);
     758        cGroups = cbGroups / sizeof(groups[0]);
     759        for (i = 0; i < cGroups; ++i)
     760        {
     761            /* Note that the use of %S might be tempting, but it is not
     762             * available on all platforms, and even where it is usable it
     763             * may depend on correct compiler options to make wchar_t a
     764             * 16 bit number. So better play safe and use UTF-8. */
     765            char *group;
     766            g_pVBoxFuncs->pfnUtf16ToUtf8(groups[i], &group);
     767            printf("Groups[%d]: %s\n", i, group);
     768            g_pVBoxFuncs->pfnUtf8Free(group);
     769        }
     770        for (i = 0; i < cGroups; ++i)
     771            g_pVBoxFuncs->pfnComUnallocString(groups[i]);
     772        g_pVBoxFuncs->pfnArrayOutFree(groups);
    748773    }
    749774
     
    835860    if (!machineCnt)
    836861    {
     862        g_pVBoxFuncs->pfnArrayOutFree(machines);
    837863        printf("\tNo VMs\n");
    838864        return;
     
    962988        }
    963989    }
    964     if (machines)
    965         free(machines);
     990    g_pVBoxFuncs->pfnArrayOutFree(machines);
    966991}
    967992
Note: See TracChangeset for help on using the changeset viewer.

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