[vlc-devel] [PATCH] Don't use old ActiveX control

Jean-Paul Saman jpsaman at videolan.org
Tue Jun 10 14:46:58 CEST 2008


Poe wrote:
> Remove all references to VLCControl
> Use VLCControl2 instead

This breaks the ActiveX interface contract (retaining the old interface).

I know that for the mozilla plugin the old interface was already 
completely removed.

The only two functions that are a bit problematic are getVariable() and 
setVariable(), because there are no internal replacements for. So the 
question actually is if it is safe to implement/revive this functionality?

> ---
>  projects/activex/main.cpp         |   25 +---
>  projects/activex/objectsafety.cpp |    4 +-
>  projects/activex/plugin.cpp       |    9 +-
>  projects/activex/plugin.h         |    4 -
>  projects/activex/vlccontrol2.cpp  |  325 ++++++++++++++++++++++++++++++++++++-
>  projects/activex/vlccontrol2.h    |    5 +
>  6 files changed, 333 insertions(+), 39 deletions(-)
> 
> diff --git a/projects/activex/main.cpp b/projects/activex/main.cpp
> index f3e3f5f..cd1eaa8 100644
> --- a/projects/activex/main.cpp
> +++ b/projects/activex/main.cpp
> @@ -66,8 +66,7 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
>  
>      *ppv = NULL;
>  
> -    if( (CLSID_VLCPlugin == rclsid )
> -     || ( CLSID_VLCPlugin2 == rclsid) )
> +    if( CLSID_VLCPlugin2 == rclsid )
>      {
>          VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
>          hr = plugin->QueryInterface(riid, ppv);
> @@ -157,8 +156,6 @@ STDAPI DllUnregisterServer(VOID)
>              _CATID_SafeForScripting,
>          };
>  
> -        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
> -                sizeof(implCategories)/sizeof(CATID), implCategories);
>          pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
>                  sizeof(implCategories)/sizeof(CATID), implCategories);
>          pcr->Release();
> @@ -166,7 +163,6 @@ STDAPI DllUnregisterServer(VOID)
>  
>      SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
>  
> -    UnregisterProgID(CLSID_VLCPlugin, 2);
>      UnregisterProgID(CLSID_VLCPlugin2, 1);
>  
>      return S_OK;
> @@ -307,8 +303,7 @@ STDAPI DllRegisterServer(VOID)
>      if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
>          return SELFREG_E_CLASS;
>  
> -    RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
> -    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
> +    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 1, TRUE, DllPath, DllPathLen);
>  
>      RegCloseKey(hBaseKey);
>  
> @@ -324,8 +319,6 @@ STDAPI DllRegisterServer(VOID)
>              _CATID_SafeForScripting,
>          };
>  
> -        pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
> -                sizeof(implCategories)/sizeof(CATID), implCategories);
>          pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
>                  sizeof(implCategories)/sizeof(CATID), implCategories);
>          pcr->Release();
> @@ -373,24 +366,19 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
>  
>      IUnknown *classProc = NULL;
>  
> -    if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
> +    if( FAILED(DllGetClassObject(CLSID_VLCPlugin2, IID_IUnknown, (LPVOID *)&classProc)) )
>          return 0;
>   
>      DWORD dwRegisterClassObject;
> -    DWORD dwRegisterClassObject2;
>  
> -    if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
> +    if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin2, classProc,
>          CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
>          return 0;
>  
>      DWORD dwRegisterActiveObject;
>  
> -    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
> -                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
> -        return 0;
> -
>      if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
> -                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
> +                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
>          return 0;
>  
>      classProc->Release();
> @@ -421,9 +409,6 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
>      if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
>          CoRevokeClassObject(dwRegisterClassObject);
>  
> -    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
> -        CoRevokeClassObject(dwRegisterClassObject2);
> -
>      // Reached on WM_QUIT message
>      OleUninitialize();
>      return ((int) msg.wParam);
> diff --git a/projects/activex/objectsafety.cpp b/projects/activex/objectsafety.cpp
> index 3806d36..8b2e097 100644
> --- a/projects/activex/objectsafety.cpp
> +++ b/projects/activex/objectsafety.cpp
> @@ -44,7 +44,7 @@ STDMETHODIMP VLCObjectSafety::GetInterfaceSafetyOptions(
>      *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACESAFE_FOR_UNTRUSTED_CALLER;
>  
>      if( (IID_IDispatch == riid)
> -     || (IID_IVLCControl == riid) )
> +     || (IID_IVLCControl2 == riid) )
>      {
>          *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
>          return NOERROR;
> @@ -68,7 +68,7 @@ STDMETHODIMP VLCObjectSafety::SetInterfaceSafetyOptions(
>  )
>  {
>      if( (IID_IDispatch == riid)
> -     || (IID_IVLCControl == riid) )
> +     || (IID_IVLCControl2 == riid) )
>      {
>          if( (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask)
>           && (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions) )
> diff --git a/projects/activex/plugin.cpp b/projects/activex/plugin.cpp
> index 5aa6400..0e7f535 100644
> --- a/projects/activex/plugin.cpp
> +++ b/projects/activex/plugin.cpp
> @@ -32,7 +32,6 @@
>  #include "provideclassinfo.h"
>  #include "connectioncontainer.h"
>  #include "objectsafety.h"
> -#include "vlccontrol.h"
>  #include "vlccontrol2.h"
>  #include "viewobject.h"
>  #include "dataobject.h"
> @@ -219,7 +218,6 @@ VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) :
>      vlcProvideClassInfo = new VLCProvideClassInfo(this);
>      vlcConnectionPointContainer = new VLCConnectionPointContainer(this);
>      vlcObjectSafety = new VLCObjectSafety(this);
> -    vlcControl = new VLCControl(this);
>      vlcControl2 = new VLCControl2(this);
>      vlcViewObject = new VLCViewObject(this);
>      vlcDataObject = new VLCDataObject(this);
> @@ -249,7 +247,6 @@ VLCPlugin::~VLCPlugin()
>      delete vlcDataObject;
>      delete vlcViewObject;
>      delete vlcControl2;
> -    delete vlcControl;
>      delete vlcConnectionPointContainer;
>      delete vlcProvideClassInfo;
>      delete vlcPersistPropertyBag;
> @@ -303,11 +300,7 @@ STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)
>      else if( IID_IObjectSafety == riid )
>          *ppv = reinterpret_cast<LPVOID>(vlcObjectSafety);
>      else if( IID_IDispatch == riid )
> -        *ppv = (CLSID_VLCPlugin2 == getClassID()) ?
> -                reinterpret_cast<LPVOID>(vlcControl2) :
> -                reinterpret_cast<LPVOID>(vlcControl);
> -    else if( IID_IVLCControl == riid )
> -        *ppv = reinterpret_cast<LPVOID>(vlcControl);
> +        *ppv = reinterpret_cast<LPVOID>(vlcControl2);
>      else if( IID_IVLCControl2 == riid )
>          *ppv = reinterpret_cast<LPVOID>(vlcControl2);
>      else if( IID_IViewObject == riid )
> diff --git a/projects/activex/plugin.h b/projects/activex/plugin.h
> index d21f8a6..001b176 100644
> --- a/projects/activex/plugin.h
> +++ b/projects/activex/plugin.h
> @@ -27,11 +27,8 @@
>  #include <olectl.h>
>  
>  #include <vlc/vlc.h>
> -
> -
>  #include <vlc/libvlc.h>
>  
> -extern "C" const GUID CLSID_VLCPlugin;
>  extern "C" const GUID CLSID_VLCPlugin2;
>  extern "C" const GUID LIBID_AXVLC;
>  extern "C" const GUID DIID_DVLCEvents;
> @@ -248,7 +245,6 @@ private:
>      class VLCProvideClassInfo *vlcProvideClassInfo;
>      class VLCConnectionPointContainer *vlcConnectionPointContainer;
>      class VLCObjectSafety *vlcObjectSafety;
> -    class VLCControl *vlcControl;
>      class VLCControl2 *vlcControl2;
>      class VLCViewObject *vlcViewObject;
>      class VLCDataObject *vlcDataObject;
> diff --git a/projects/activex/vlccontrol2.cpp b/projects/activex/vlccontrol2.cpp
> index 26548c0..49d2590 100644
> --- a/projects/activex/vlccontrol2.cpp
> +++ b/projects/activex/vlccontrol2.cpp
> @@ -23,7 +23,6 @@
>  
>  #include "plugin.h"
>  #include "vlccontrol2.h"
> -#include "vlccontrol.h"
>  
>  #include "utils.h"
>  
> @@ -525,7 +524,7 @@ STDMETHODIMP VLCInput::put_time(double time)
>          libvlc_media_player_t *p_md = libvlc_playlist_get_media_player(p_libvlc, &ex);
>          if( ! libvlc_exception_raised(&ex) )
>          {
> -            libvlc_media_player_set_time(p_md, (vlc_int64_t)time, &ex);
> +            libvlc_media_player_set_time(p_md, (int64_t)time, &ex);
>              libvlc_media_player_release(p_md);
>              if( ! libvlc_exception_raised(&ex) )
>              {
> @@ -1723,7 +1722,7 @@ STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* ite
>          int i_options;
>          char **ppsz_options;
>  
> -        hr = VLCControl::CreateTargetOptions(CP_UTF8, &options, &ppsz_options, &i_options);
> +        hr = VLCControl2::CreateTargetOptions(CP_UTF8, &options, &ppsz_options, &i_options);
>          if( FAILED(hr) )
>          {
>              CoTaskMemFree(psz_uri);
> @@ -1748,7 +1747,7 @@ STDMETHODIMP VLCPlaylist::add(BSTR uri, VARIANT name, VARIANT options, long* ite
>                      const_cast<const char **>(ppsz_options),
>                      &ex);
>  
> -        VLCControl::FreeTargetOptions(ppsz_options, i_options);
> +        VLCControl2::FreeTargetOptions(ppsz_options, i_options);
>          CoTaskMemFree(psz_uri);
>          if( psz_name )
>              CoTaskMemFree(psz_name);
> @@ -2782,7 +2781,7 @@ STDMETHODIMP VLCControl2::get_VersionInfo(BSTR *version)
>      if( NULL == version )
>          return E_POINTER;
>  
> -    const char *versionStr = VLC_Version();
> +    const char *versionStr = libvlc_get_version();
>      if( NULL != versionStr )
>      {
>          *version = BSTRFromCStr(CP_UTF8, versionStr);
> @@ -2909,3 +2908,319 @@ STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
>      }
>      return E_OUTOFMEMORY;
>  };
> +
> +
> +HRESULT VLCControl2::CreateTargetOptions(int codePage, VARIANT *options, char ***cOptions, int *cOptionCount)
> +{
> +    HRESULT hr = E_INVALIDARG;
> +    if( VT_ERROR == V_VT(options) )
> +    {
> +        if( DISP_E_PARAMNOTFOUND == V_ERROR(options) )
> +        {
> +            // optional parameter not set
> +            *cOptions = NULL;
> +            *cOptionCount = 0;
> +            return NOERROR;
> +        }
> +    }
> +    else if( (VT_EMPTY == V_VT(options)) || (VT_NULL == V_VT(options)) )
> +    {
> +        // null parameter
> +        *cOptions = NULL;
> +        *cOptionCount = 0;
> +        return NOERROR;
> +    }
> +    else if( VT_DISPATCH == V_VT(options) )
> +    {
> +        // if object is a collection, retrieve enumerator
> +        VARIANT colEnum;
> +        V_VT(&colEnum) = VT_UNKNOWN;
> +        hr = GetObjectProperty(V_DISPATCH(options), DISPID_NEWENUM, colEnum);
> +        if( SUCCEEDED(hr) )
> +        {
> +            IEnumVARIANT *enumVar;
> +            hr = V_UNKNOWN(&colEnum)->QueryInterface(IID_IEnumVARIANT, (LPVOID *)&enumVar);
> +            if( SUCCEEDED(hr) )
> +            {
> +                long pos = 0;
> +                long capacity = 16;
> +                VARIANT option;
> +
> +                *cOptions = (char **)CoTaskMemAlloc(capacity*sizeof(char *));
> +                if( NULL != *cOptions )
> +                {
> +                    ZeroMemory(*cOptions, sizeof(char *)*capacity);
> +                    while( SUCCEEDED(hr) && (S_OK == enumVar->Next(1, &option, NULL)) )
> +                    {
> +                        if( VT_BSTR == V_VT(&option) )
> +                        {
> +                            char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
> +                            (*cOptions)[pos] = cOption;
> +                            if( NULL != cOption )
> +                            {
> +                                ++pos;
> +                                if( pos == capacity )
> +                                {
> +                                    char **moreOptions = (char **)CoTaskMemRealloc(*cOptions, (capacity+16)*sizeof(char *));
> +                                    if( NULL != moreOptions )
> +                                    {
> +                                        ZeroMemory(moreOptions+capacity, sizeof(char *)*16);
> +                                        capacity += 16;
> +                                        *cOptions = moreOptions;
> +                                    }
> +                                    else
> +                                        hr = E_OUTOFMEMORY;
> +                                }
> +                            }
> +                            else
> +                                hr = ( SysStringLen(V_BSTR(&option)) > 0 ) ?
> +                                    E_OUTOFMEMORY : E_INVALIDARG;
> +                        }
> +                        else
> +                            hr = E_INVALIDARG;
> +
> +                        VariantClear(&option);
> +                    }
> +                    *cOptionCount = pos;
> +                    if( FAILED(hr) )
> +                    {
> +                        // free already processed elements
> +                        FreeTargetOptions(*cOptions, *cOptionCount);
> +                    }
> +                }
> +                else
> +                    hr = E_OUTOFMEMORY;
> +
> +                enumVar->Release();
> +            }
> +        }
> +        else
> +        {
> +            // coerce object into a string and parse it
> +            VARIANT v_name;
> +            VariantInit(&v_name);
> +            hr = VariantChangeType(&v_name, options, 0, VT_BSTR);
> +            if( SUCCEEDED(hr) )
> +            {
> +                hr = parseStringOptions(codePage, V_BSTR(&v_name), cOptions, cOptionCount);
> +                VariantClear(&v_name);
> +            }
> +        }
> +    }
> +    else if( V_ISARRAY(options) )
> +    {
> +        // array parameter
> +        SAFEARRAY *array = V_ISBYREF(options) ? *V_ARRAYREF(options) : V_ARRAY(options);
> +
> +        if( SafeArrayGetDim(array) != 1 )
> +            return E_INVALIDARG;
> +
> +        long lBound = 0;
> +        long uBound = 0;
> +        SafeArrayGetLBound(array, 1, &lBound);
> +        SafeArrayGetUBound(array, 1, &uBound);
> +
> +        // have we got any options
> +        if( uBound >= lBound )
> +        {
> +            VARTYPE vType;
> +            hr = SafeArrayGetVartype(array, &vType);
> +            if( FAILED(hr) )
> +                return hr;
> +
> +            long pos;
> +
> +            // marshall options into an array of C strings
> +            if( VT_VARIANT == vType )
> +            {
> +                *cOptions = (char **)CoTaskMemAlloc(sizeof(char *)*(uBound-lBound+1));
> +                if( NULL == *cOptions )
> +                    return E_OUTOFMEMORY;
> +
> +                ZeroMemory(*cOptions, sizeof(char *)*(uBound-lBound+1));
> +                for(pos=lBound; (pos<=uBound) && SUCCEEDED(hr); ++pos )
> +                {
> +                    VARIANT option;
> +                    hr = SafeArrayGetElement(array, &pos, &option);
> +                    if( SUCCEEDED(hr) )
> +                    {
> +                        if( VT_BSTR == V_VT(&option) )
> +                        {
> +                            char *cOption = CStrFromBSTR(codePage, V_BSTR(&option));
> +                            (*cOptions)[pos-lBound] = cOption;
> +                            if( NULL == cOption )
> +                                hr = ( SysStringLen(V_BSTR(&option)) > 0 ) ?
> +                                    E_OUTOFMEMORY : E_INVALIDARG;
> +                        }
> +                        else
> +                            hr = E_INVALIDARG;
> +                        VariantClear(&option);
> +                    }
> +                }
> +            }
> +            else if( VT_BSTR == vType )
> +            {
> +                *cOptions = (char **)CoTaskMemAlloc(sizeof(char *)*(uBound-lBound+1));
> +                if( NULL == *cOptions )
> +                    return E_OUTOFMEMORY;
> +
> +                ZeroMemory(*cOptions, sizeof(char *)*(uBound-lBound+1));
> +                for(pos=lBound; (pos<=uBound) && SUCCEEDED(hr); ++pos )
> +                {
> +                    BSTR option;
> +                    hr = SafeArrayGetElement(array, &pos, &option);
> +                    if( SUCCEEDED(hr) )
> +                    {
> +                        char *cOption = CStrFromBSTR(codePage, option);
> +
> +                        (*cOptions)[pos-lBound] = cOption;
> +                        if( NULL == cOption )
> +                            hr = ( SysStringLen(option) > 0 ) ?
> +                                E_OUTOFMEMORY : E_INVALIDARG;
> +                        SysFreeString(option);
> +                    }
> +                }
> +            }
> +            else
> +            {
> +                // unsupported type
> +                return E_INVALIDARG;
> +            }
> +
> +            *cOptionCount = pos-lBound;
> +            if( FAILED(hr) )
> +            {
> +                // free already processed elements
> +                FreeTargetOptions(*cOptions, *cOptionCount);
> +            }
> +        }
> +        else
> +        {
> +            // empty array
> +            *cOptions = NULL;
> +            *cOptionCount = 0;
> +            return NOERROR;
> +        }
> +    }
> +    else if( VT_UNKNOWN == V_VT(options) )
> +    {
> +        // coerce object into a string and parse it
> +        VARIANT v_name;
> +        VariantInit(&v_name);
> +        hr = VariantChangeType(&v_name, options, 0, VT_BSTR);
> +        if( SUCCEEDED(hr) )
> +        {
> +            hr = parseStringOptions(codePage, V_BSTR(&v_name), cOptions, cOptionCount);
> +            VariantClear(&v_name);
> +        }
> +    }
> +    else if( VT_BSTR == V_VT(options) )
> +    {
> +        hr = parseStringOptions(codePage, V_BSTR(options), cOptions, cOptionCount);
> +    }
> +    return hr;
> +};
> +
> +void VLCControl2::FreeTargetOptions(char **cOptions, int cOptionCount)
> +{
> +    // clean up
> +    if( NULL != cOptions )
> +    {
> +        for( int pos=0; pos<cOptionCount; ++pos )
> +        {
> +            char *cOption = cOptions[pos];
> +            if( NULL != cOption )
> +                CoTaskMemFree(cOption);
> +            else
> +                break;
> +        }
> +        CoTaskMemFree(cOptions);
> +    }
> +};
> +
> +static HRESULT parseStringOptions(int codePage, BSTR bstr, char*** cOptions, int *cOptionCount)
> +{
> +    HRESULT hr = E_INVALIDARG;
> +    if( SysStringLen(bstr) > 0 )
> +    {
> +        hr = E_OUTOFMEMORY;
> +        char *s = CStrFromBSTR(codePage, bstr);
> +        char *val = s;
> +        if( val )
> +        {
> +            long capacity = 16;
> +            char **options = (char **)CoTaskMemAlloc(capacity*sizeof(char *));
> +            if( options )
> +            {
> +                int nOptions = 0;
> +
> +                char *end = val + strlen(val);
> +                while( val < end )
> +                {
> +                    // skip leading blanks
> +                    while( (val < end)
> +                        && ((*val == ' ' ) || (*val == '\t')) )
> +                        ++val;
> +
> +                    char *start = val;
> +                    // skip till we get a blank character
> +                    while( (val < end)
> +                        && (*val != ' ' )
> +                        && (*val != '\t') )
> +                    {
> +                        char c = *(val++);
> +                        if( ('\'' == c) || ('"' == c) )
> +                        {
> +                            // skip till end of string
> +                            while( (val < end) && (*(val++) != c ) );
> +                        }
> +                    }
> +
> +                    if( val > start )
> +                    {
> +                        if( nOptions == capacity )
> +                        {
> +                            capacity += 16;
> +                            char **moreOptions = (char **)CoTaskMemRealloc(options, capacity*sizeof(char*));
> +                            if( ! moreOptions )
> +                            {
> +                                /* failed to allocate more memory */
> +                                CoTaskMemFree(s);
> +                                /* return what we got so far */
> +                                *cOptionCount = nOptions;
> +                                *cOptions = options;
> +                                return NOERROR;
> +                            }
> +                            options = moreOptions;
> +                        }
> +                        *(val++) = '\0';
> +                        options[nOptions] = (char *)CoTaskMemAlloc(val-start);
> +                        if( options[nOptions] )
> +                        {
> +                            memcpy(options[nOptions], start, val-start);
> +                            ++nOptions;
> +                        }
> +                        else
> +                        {
> +                            /* failed to allocate memory */
> +                            CoTaskMemFree(s);
> +                            /* return what we got so far */
> +                            *cOptionCount = nOptions;
> +                            *cOptions = options;
> +                            return NOERROR;
> +                        }
> +                    }
> +                    else
> +                        // must be end of string
> +                        break;
> +                }
> +                *cOptionCount = nOptions;
> +                *cOptions = options;
> +                hr = NOERROR;
> +            }
> +            CoTaskMemFree(s);
> +        }
> +    }
> +    return hr;
> +}
> +
> diff --git a/projects/activex/vlccontrol2.h b/projects/activex/vlccontrol2.h
> index 7596676..7e3a22b 100644
> --- a/projects/activex/vlccontrol2.h
> +++ b/projects/activex/vlccontrol2.h
> @@ -600,6 +600,9 @@ public:
>      STDMETHODIMP get_playlist(IVLCPlaylist**);
>      STDMETHODIMP get_video(IVLCVideo**);
>  
> +    static HRESULT CreateTargetOptions(int codePage, VARIANT *options, char ***cOptions, int *cOptionCount);
> +    static void FreeTargetOptions(char **cOptions, int cOptionCount);
> +
>  protected:
>      HRESULT loadTypeInfo();
>  
> @@ -614,4 +617,6 @@ private:
>      VLCVideo*       _p_vlcvideo;
>  };
>  
> +static HRESULT parseStringOptions(int codePage, BSTR bstr, char*** cOptions, int *cOptionCount);
> +
>  #endif




More information about the vlc-devel mailing list