[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