Commit 3cf5be69 authored by Damien Fouilleul's avatar Damien Fouilleul

- ActiveX: optimized implementation of all IEnumXXX classes (more template...

- ActiveX: optimized implementation of all IEnumXXX classes (more template obfuscation I'm afraid), fixed IConnectionPoints for DCOM
parent 68cb6a3a
...@@ -29,46 +29,62 @@ using namespace std; ...@@ -29,46 +29,62 @@ using namespace std;
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
class VLCEnumConnections : public IEnumConnections /* this function object is used to return the value from a map pair */
struct VLCEnumConnectionsDereference
{ {
public: CONNECTDATA operator()(const map<DWORD,LPUNKNOWN>::iterator& i)
VLCEnumConnections(vector<CONNECTDATA> &v) : {
e(VLCEnum<CONNECTDATA>(IID_IEnumConnections, v)) CONNECTDATA cd;
{ e.setRetainOperation((VLCEnum<CONNECTDATA>::retainer)&retain); };
cd.dwCookie = i->first;
VLCEnumConnections(const VLCEnumConnections &vlcEnum) : IEnumConnections(), e(vlcEnum.e) {}; cd.pUnk = i->second;
return cd;
virtual ~VLCEnumConnections() {};
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{ return e.QueryInterface(riid, ppv); };
STDMETHODIMP_(ULONG) AddRef(void)
{ return e.AddRef(); };
STDMETHODIMP_(ULONG) Release(void)
{return e.Release(); };
//IEnumConnectionPoints
STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched)
{ return e.Next(celt, rgelt, pceltFetched); };
STDMETHODIMP Skip(ULONG celt)
{ return e.Skip(celt);};
STDMETHODIMP Reset(void)
{ return e.Reset();};
STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum)
{ if( NULL == ppenum ) return E_POINTER;
*ppenum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(*this));
return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
}; };
};
class VLCEnumConnections : public VLCEnumIterator<IID_IEnumConnections,
IEnumConnections,
CONNECTDATA,
map<DWORD,LPUNKNOWN>::iterator,
VLCEnumConnectionsDereference>
{
public:
VLCEnumConnections(map<DWORD,LPUNKNOWN> &m) :
VLCEnumIterator<IID_IEnumConnections,
IEnumConnections,
CONNECTDATA,
map<DWORD,LPUNKNOWN>::iterator,
VLCEnumConnectionsDereference> (m.begin(), m.end())
{};
};
private: ////////////////////////////////////////////////////////////////////////////////////////////////
static void retain(CONNECTDATA cd) /* this function object is used to retain the dereferenced iterator value */
struct VLCEnumConnectionPointsDereference
{
LPCONNECTIONPOINT operator()(const vector<LPCONNECTIONPOINT>::iterator& i)
{ {
cd.pUnk->AddRef(); LPCONNECTIONPOINT cp = *i;
}; cp->AddRef();
return cp;
}
};
VLCEnum<CONNECTDATA> e; class VLCEnumConnectionPoints: public VLCEnumIterator<IID_IEnumConnectionPoints,
IEnumConnectionPoints,
LPCONNECTIONPOINT,
vector<LPCONNECTIONPOINT>::iterator,
VLCEnumConnectionPointsDereference>
{
public:
VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT>& v) :
VLCEnumIterator<IID_IEnumConnectionPoints,
IEnumConnectionPoints,
LPCONNECTIONPOINT,
vector<LPCONNECTIONPOINT>::iterator,
VLCEnumConnectionPointsDereference> (v.begin(), v.end())
{};
}; };
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
...@@ -94,32 +110,29 @@ STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCO ...@@ -94,32 +110,29 @@ STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCO
STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie) STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
{ {
static DWORD dwCookieCounter = 0;
if( (NULL == pUnk) || (NULL == pdwCookie) ) if( (NULL == pUnk) || (NULL == pdwCookie) )
return E_POINTER; return E_POINTER;
CONNECTDATA cd;
pUnk->AddRef(); pUnk->AddRef();
cd.pUnk = pUnk;
*pdwCookie = cd.dwCookie = _connections.size()+1;
_connections.push_back(cd); *pdwCookie = ++dwCookieCounter;
_connections[*pdwCookie] = pUnk;
return S_OK; return S_OK;
}; };
STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie) STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)
{ {
if( (0 < pdwCookie) && (pdwCookie <= _connections.size()) ) map<DWORD,LPUNKNOWN>::iterator pcd = _connections.find((DWORD)pdwCookie);
{ if( pcd != _connections.end() )
CONNECTDATA cd = _connections[pdwCookie-1];
if( NULL != cd.pUnk )
{ {
cd.pUnk->Release(); pcd->second->Release();
cd.pUnk = NULL;
_connections.erase(pdwCookie);
return S_OK; return S_OK;
} }
}
return CONNECT_E_NOCONNECTION; return CONNECT_E_NOCONNECTION;
}; };
...@@ -135,16 +148,16 @@ STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum) ...@@ -135,16 +148,16 @@ STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams) void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
{ {
vector<CONNECTDATA>::iterator end = _connections.end(); map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
vector<CONNECTDATA>::iterator iter = _connections.begin(); map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
while( iter != end ) while( iter != end )
{ {
CONNECTDATA cd = *iter; LPUNKNOWN pUnk = iter->second;
if( NULL != cd.pUnk ) if( NULL != pUnk )
{ {
IDispatch *pDisp; IDispatch *pDisp;
if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) ) if( SUCCEEDED(pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )
{ {
pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL); pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL);
pDisp->Release(); pDisp->Release();
...@@ -156,16 +169,16 @@ void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams) ...@@ -156,16 +169,16 @@ void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
void VLCConnectionPoint::firePropChangedEvent(DISPID dispId) void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
{ {
vector<CONNECTDATA>::iterator end = _connections.end(); map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
vector<CONNECTDATA>::iterator iter = _connections.begin(); map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
while( iter != end ) while( iter != end )
{ {
CONNECTDATA cd = *iter; LPUNKNOWN pUnk = iter->second;
if( NULL != cd.pUnk ) if( NULL != pUnk )
{ {
IPropertyNotifySink *pPropSink; IPropertyNotifySink *pPropSink;
if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) ) if( SUCCEEDED(pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
{ {
pPropSink->OnChanged(dispId); pPropSink->OnChanged(dispId);
pPropSink->Release(); pPropSink->Release();
...@@ -177,50 +190,6 @@ void VLCConnectionPoint::firePropChangedEvent(DISPID dispId) ...@@ -177,50 +190,6 @@ void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
class VLCEnumConnectionPoints : public IEnumConnectionPoints
{
public:
VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT> &v) :
e(VLCEnum<LPCONNECTIONPOINT>(IID_IEnumConnectionPoints, v))
{ e.setRetainOperation((VLCEnum<LPCONNECTIONPOINT>::retainer)&retain); };
VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : IEnumConnectionPoints(), e(vlcEnum.e) {};
virtual ~VLCEnumConnectionPoints() {};
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{ return e.QueryInterface(riid, ppv); };
STDMETHODIMP_(ULONG) AddRef(void)
{ return e.AddRef(); };
STDMETHODIMP_(ULONG) Release(void)
{return e.Release(); };
//IEnumConnectionPoints
STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched)
{ return e.Next(celt, rgelt, pceltFetched); };
STDMETHODIMP Skip(ULONG celt)
{ return e.Skip(celt);};
STDMETHODIMP Reset(void)
{ return e.Reset();};
STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum)
{ if( NULL == ppenum ) return E_POINTER;
*ppenum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(*this));
return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
};
private:
static void retain(LPCONNECTIONPOINT cp)
{
cp->AddRef();
};
VLCEnum<LPCONNECTIONPOINT> e;
};
////////////////////////////////////////////////////////////////////////////////////////////////
VLCDispatchEvent::~VLCDispatchEvent() VLCDispatchEvent::~VLCDispatchEvent()
{ {
//clear event arguments //clear event arguments
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <ocidl.h> #include <ocidl.h>
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <map>
class VLCConnectionPoint : public IConnectionPoint class VLCConnectionPoint : public IConnectionPoint
{ {
...@@ -69,7 +70,7 @@ private: ...@@ -69,7 +70,7 @@ private:
REFIID _iid; REFIID _iid;
IConnectionPointContainer *_p_cpc; IConnectionPointContainer *_p_cpc;
std::vector<CONNECTDATA> _connections; std::map<DWORD, LPUNKNOWN> _connections;
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
......
...@@ -29,44 +29,6 @@ using namespace std; ...@@ -29,44 +29,6 @@ using namespace std;
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
class VLCEnumFORMATETC : public IEnumFORMATETC
{
public:
VLCEnumFORMATETC(vector<FORMATETC> &v) :
e(VLCEnum<FORMATETC>(IID_IEnumFORMATETC, v)) {};
VLCEnumFORMATETC(const VLCEnumFORMATETC &vlcEnum) : IEnumFORMATETC(), e(vlcEnum.e) {};
virtual ~VLCEnumFORMATETC() {};
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{ return e.QueryInterface(riid, ppv); };
STDMETHODIMP_(ULONG) AddRef(void)
{ return e.AddRef(); };
STDMETHODIMP_(ULONG) Release(void)
{return e.Release(); };
//IEnumConnectionPoints
STDMETHODIMP Next(ULONG celt, LPFORMATETC rgelt, ULONG *pceltFetched)
{ return e.Next(celt, rgelt, pceltFetched); };
STDMETHODIMP Skip(ULONG celt)
{ return e.Skip(celt);};
STDMETHODIMP Reset(void)
{ return e.Reset();};
STDMETHODIMP Clone(LPENUMFORMATETC *ppenum)
{ if( NULL == ppenum ) return E_POINTER;
*ppenum = dynamic_cast<LPENUMFORMATETC>(new VLCEnumFORMATETC(*this));
return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
};
private:
VLCEnum<FORMATETC> e;
};
////////////////////////////////////////////////////////////////////////////////////////////////
static const FORMATETC _metaFileFormatEtc = static const FORMATETC _metaFileFormatEtc =
{ {
CF_METAFILEPICT, CF_METAFILEPICT,
...@@ -84,6 +46,22 @@ static const FORMATETC _enhMetaFileFormatEtc = ...@@ -84,6 +46,22 @@ static const FORMATETC _enhMetaFileFormatEtc =
TYMED_ENHMF, TYMED_ENHMF,
}; };
class VLCEnumFORMATETC : public VLCEnumIterator<IID_IEnumFORMATETC,
IEnumFORMATETC,
FORMATETC,
vector<FORMATETC>::iterator>
{
public:
VLCEnumFORMATETC(vector<FORMATETC> v) :
VLCEnumIterator<IID_IEnumFORMATETC,
IEnumFORMATETC,
FORMATETC,
vector<FORMATETC>::iterator>(v.begin(), v.end())
{};
};
////////////////////////////////////////////////////////////////////////////////////////////////
VLCDataObject::VLCDataObject(VLCPlugin *p_instance) : _p_instance(p_instance) VLCDataObject::VLCDataObject(VLCPlugin *p_instance) : _p_instance(p_instance)
{ {
_v_formatEtc.push_back(_enhMetaFileFormatEtc); _v_formatEtc.push_back(_enhMetaFileFormatEtc);
...@@ -114,13 +92,14 @@ STDMETHODIMP VLCDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise) ...@@ -114,13 +92,14 @@ STDMETHODIMP VLCDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
return _p_adviseHolder->EnumAdvise(ppenumAdvise); return _p_adviseHolder->EnumAdvise(ppenumAdvise);
}; };
STDMETHODIMP VLCDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumformatetc) STDMETHODIMP VLCDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnum)
{ {
if( NULL == ppenumformatetc ) if( NULL == ppEnum )
return E_POINTER; return E_POINTER;
*ppenumformatetc = new VLCEnumFORMATETC(_v_formatEtc); *ppEnum = dynamic_cast<IEnumFORMATETC *>(new VLCEnumFORMATETC(_v_formatEtc));
return NOERROR;
return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
}; };
STDMETHODIMP VLCDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtcIn, LPFORMATETC pFormatEtcOut) STDMETHODIMP VLCDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtcIn, LPFORMATETC pFormatEtcOut)
......
...@@ -43,79 +43,47 @@ extern void HimetricFromDP(HDC hdc, LPPOINT pt, int count); ...@@ -43,79 +43,47 @@ extern void HimetricFromDP(HDC hdc, LPPOINT pt, int count);
/**************************************************************************************************/ /**************************************************************************************************/
// enumeration /* this function object is used to dereference the iterator into a value */
template<class T> class VLCEnum : IUnknown template <class T, class Iterator>
struct VLCDereference
{ {
T operator()(const Iterator& i) const
public: {
return *i;
VLCEnum(REFIID riid, std::vector<T> &); };
VLCEnum(const VLCEnum<T> &);
virtual ~VLCEnum() {};
VLCEnum<T>& operator=(const VLCEnum<T> &t);
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IEnumXXXX methods
STDMETHODIMP Next(ULONG, T *, ULONG *);
STDMETHODIMP Skip(ULONG);
STDMETHODIMP Reset(void);
// cloning is implemented by subclasses and must use copy constructor
//STDMETHODIMP Clone(VLCEnum<T> **);
typedef void (*retainer)(T);
void setRetainOperation(retainer retain) { _retain = retain; };
private:
LONG _refcount;
std::vector<T> _v;
typename std::vector<T>::iterator _i;
REFIID _riid;
retainer _retain;
}; };
template<class T> template<REFIID EnumeratorIID, class Enumerator, class T, class Iterator, typename Dereference = VLCDereference<T, Iterator> >
VLCEnum<T>::VLCEnum(REFIID riid, std::vector<T> &v) : class VLCEnumIterator : public Enumerator
_refcount(1),
_v(v),
_riid(riid),
_retain(NULL)
{ {
_i= v.begin();
};
template<class T> public:
VLCEnum<T>::VLCEnum(const VLCEnum<T> &e) :
IUnknown(),
_refcount(1),
_v(e._v),
_riid(e._riid)
{
};
template<class T> VLCEnumIterator(const Iterator& from, const Iterator& to) :
VLCEnum<T>& VLCEnum<T>::operator=(const VLCEnum<T> &e) _refcount(1),
{ _begin(from),
this->_refcount = 1; _curr(from),
this->_riid = e._riid; _end(to)
this->_v = e._v; {};
this->_i = e._i;
return this; VLCEnumIterator(const VLCEnumIterator& e) :
}; Enumerator(),
_refcount(e._refcount),
_begin(e._begin),
_curr(e._curr),
_end(e._end)
{};
virtual ~VLCEnumIterator()
{};
template<class T> // IUnknown methods
STDMETHODIMP VLCEnum<T>::QueryInterface(REFIID riid, void **ppv) STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{ {
if( NULL == ppv ) if( NULL == ppv )
return E_POINTER; return E_POINTER;
if( (IID_IUnknown == riid) if( (IID_IUnknown == riid)
|| (_riid == riid) ) || (EnumeratorIID == riid) )
{ {
AddRef(); AddRef();
*ppv = reinterpret_cast<LPVOID>(this); *ppv = reinterpret_cast<LPVOID>(this);
...@@ -123,17 +91,15 @@ STDMETHODIMP VLCEnum<T>::QueryInterface(REFIID riid, void **ppv) ...@@ -123,17 +91,15 @@ STDMETHODIMP VLCEnum<T>::QueryInterface(REFIID riid, void **ppv)
} }
// standalone object // standalone object
return E_NOINTERFACE; return E_NOINTERFACE;
}; };
template<class T> STDMETHODIMP_(ULONG) AddRef(void)
STDMETHODIMP_(ULONG) VLCEnum<T>::AddRef(void) {
{
return InterlockedIncrement(&_refcount); return InterlockedIncrement(&_refcount);
}; };
template<class T> STDMETHODIMP_(ULONG) Release(void)
STDMETHODIMP_(ULONG) VLCEnum<T>::Release(void) {
{
ULONG refcount = InterlockedDecrement(&_refcount); ULONG refcount = InterlockedDecrement(&_refcount);
if( 0 == refcount ) if( 0 == refcount )
{ {
...@@ -141,11 +107,12 @@ STDMETHODIMP_(ULONG) VLCEnum<T>::Release(void) ...@@ -141,11 +107,12 @@ STDMETHODIMP_(ULONG) VLCEnum<T>::Release(void)
return 0; return 0;
} }
return refcount; return refcount;
}; };
template<class T>
STDMETHODIMP VLCEnum<T>::Next(ULONG celt, T *rgelt, ULONG *pceltFetched) // IEnumXXXX methods
{ STDMETHODIMP Next(ULONG celt, T *rgelt, ULONG *pceltFetched)
{
if( NULL == rgelt ) if( NULL == rgelt )
return E_POINTER; return E_POINTER;
...@@ -153,13 +120,11 @@ STDMETHODIMP VLCEnum<T>::Next(ULONG celt, T *rgelt, ULONG *pceltFetched) ...@@ -153,13 +120,11 @@ STDMETHODIMP VLCEnum<T>::Next(ULONG celt, T *rgelt, ULONG *pceltFetched)
return E_INVALIDARG; return E_INVALIDARG;
ULONG c = 0; ULONG c = 0;
typename std::vector<T>::iterator end = _v.end();
while( (c < celt) && (_i != end) ) while( (c < celt) && (_curr != _end) )
{ {
rgelt[c] = *_i; rgelt[c] = dereference(_curr);
if( NULL != _retain ) _retain(rgelt[c]); ++_curr;
++_i;
++c; ++c;
} }
...@@ -167,27 +132,41 @@ STDMETHODIMP VLCEnum<T>::Next(ULONG celt, T *rgelt, ULONG *pceltFetched) ...@@ -167,27 +132,41 @@ STDMETHODIMP VLCEnum<T>::Next(ULONG celt, T *rgelt, ULONG *pceltFetched)
*pceltFetched = c; *pceltFetched = c;
return (c == celt) ? S_OK : S_FALSE; return (c == celt) ? S_OK : S_FALSE;
}; };
template<class T> STDMETHODIMP Skip(ULONG celt)
STDMETHODIMP VLCEnum<T>::Skip(ULONG celt) {
{
ULONG c = 0; ULONG c = 0;
typename std::vector<T>::iterator end = _v.end();
while( (c < celt) && (_i != end) ) while( (c < celt) && (_curr != _end) )
{ {
++_i; ++_curr;
++c; ++c;
} }
return (c == celt) ? S_OK : S_FALSE; return (c == celt) ? S_OK : S_FALSE;
}; };
template<class T> STDMETHODIMP Reset(void)
STDMETHODIMP VLCEnum<T>::Reset(void) {
{ _curr = _begin;
_i= _v.begin();
return S_OK; return S_OK;
};
STDMETHODIMP Clone(Enumerator **ppEnum)
{
if( NULL == ppEnum )
return E_POINTER;
*ppEnum = dynamic_cast<Enumerator *>(new VLCEnumIterator(*this));
return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
};
private:
LONG _refcount;
Iterator _begin, _curr, _end;
Dereference dereference;
}; };
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment