You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
14 KiB
527 lines
14 KiB
// This is a part of the Active Template Library.
|
|
// Copyright (C) Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Active Template Library Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Active Template Library product.
|
|
|
|
#ifndef __SCOMCLI_H__
|
|
#define __SCOMCLI_H__
|
|
|
|
#pragma once
|
|
|
|
#include <unknwn.h>
|
|
|
|
#ifndef SASSERT
|
|
#include <assert.h>
|
|
#define SASSERT(x) assert(x);
|
|
#endif
|
|
|
|
#pragma warning (push)
|
|
#pragma warning (disable: 4127) // conditional expression constant
|
|
#pragma warning (disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions
|
|
|
|
|
|
#pragma pack(push,8)
|
|
namespace SOUI
|
|
{
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Smart Pointer helpers
|
|
|
|
|
|
inline IUnknown* SComPtrAssign(IUnknown** pp, IUnknown* lp)
|
|
{
|
|
if (pp == NULL)
|
|
return NULL;
|
|
|
|
if (lp != NULL)
|
|
lp->AddRef();
|
|
if (*pp)
|
|
(*pp)->Release();
|
|
*pp = lp;
|
|
return lp;
|
|
}
|
|
|
|
inline IUnknown* SComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid)
|
|
{
|
|
if (pp == NULL)
|
|
return NULL;
|
|
|
|
IUnknown* pTemp = *pp;
|
|
*pp = NULL;
|
|
if (lp != NULL)
|
|
lp->QueryInterface(riid, (void**)pp);
|
|
if (pTemp)
|
|
pTemp->Release();
|
|
return *pp;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COM Smart pointers
|
|
|
|
template <class T>
|
|
class _SNoAddRefReleaseOnCComPtr : public T
|
|
{
|
|
private:
|
|
STDMETHOD_(ULONG, AddRef)()=0;
|
|
STDMETHOD_(ULONG, Release)()=0;
|
|
};
|
|
|
|
//SComPtrBase provides the basis for all other smart pointers
|
|
//The other smartpointers add their own constructors and operators
|
|
template <class T>
|
|
class SComPtrBase
|
|
{
|
|
protected:
|
|
SComPtrBase() throw()
|
|
{
|
|
p = NULL;
|
|
}
|
|
SComPtrBase( int nNull) throw()
|
|
{
|
|
SASSERT(nNull == 0);
|
|
(void)nNull;
|
|
p = NULL;
|
|
}
|
|
SComPtrBase( T* lp) throw()
|
|
{
|
|
p = lp;
|
|
if (p != NULL)
|
|
p->AddRef();
|
|
}
|
|
public:
|
|
typedef T _PtrClass;
|
|
~SComPtrBase() throw()
|
|
{
|
|
if (p)
|
|
p->Release();
|
|
}
|
|
operator T*() const throw()
|
|
{
|
|
return p;
|
|
}
|
|
T& operator*() const
|
|
{
|
|
SASSERT(p!=NULL);
|
|
return *p;
|
|
}
|
|
//The assert on operator& usually indicates a bug. If this is really
|
|
//what is needed, however, take the address of the p member explicitly.
|
|
T** operator&() throw()
|
|
{
|
|
SASSERT(p==NULL);
|
|
return &p;
|
|
}
|
|
_SNoAddRefReleaseOnCComPtr<T>* operator->() const throw()
|
|
{
|
|
SASSERT(p!=NULL);
|
|
return (_SNoAddRefReleaseOnCComPtr<T>*)p;
|
|
}
|
|
bool operator!() const throw()
|
|
{
|
|
return (p == NULL);
|
|
}
|
|
bool operator<( T* pT) const throw()
|
|
{
|
|
return p < pT;
|
|
}
|
|
bool operator!=( T* pT) const
|
|
{
|
|
return !operator==(pT);
|
|
}
|
|
bool operator==( T* pT) const throw()
|
|
{
|
|
return p == pT;
|
|
}
|
|
|
|
// Release the interface and set to NULL
|
|
void Release() throw()
|
|
{
|
|
T* pTemp = p;
|
|
if (pTemp)
|
|
{
|
|
p = NULL;
|
|
pTemp->Release();
|
|
}
|
|
}
|
|
// Compare two objects for equivalence
|
|
bool IsEqualObject( IUnknown* pOther) throw()
|
|
{
|
|
if (p == NULL && pOther == NULL)
|
|
return true; // They are both NULL objects
|
|
|
|
if (p == NULL || pOther == NULL)
|
|
return false; // One is NULL the other is not
|
|
|
|
IUnknown* punk1;
|
|
IUnknown* punk2;
|
|
p->QueryInterface(__uuidof(IUnknown), (void**)&punk1);
|
|
pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2);
|
|
bool bEqual = punk1 == punk2;
|
|
punk1->Release();
|
|
punk2->Release();
|
|
return bEqual;
|
|
}
|
|
// Attach to an existing interface (does not AddRef)
|
|
void Attach( T* p2) throw()
|
|
{
|
|
if (p)
|
|
p->Release();
|
|
p = p2;
|
|
}
|
|
// Detach the interface (does not Release)
|
|
T* Detach() throw()
|
|
{
|
|
T* pt = p;
|
|
p = NULL;
|
|
return pt;
|
|
}
|
|
HRESULT CopyTo( T** ppT) throw()
|
|
{
|
|
SASSERT(ppT != NULL);
|
|
if (ppT == NULL)
|
|
return E_POINTER;
|
|
*ppT = p;
|
|
if (p)
|
|
p->AddRef();
|
|
return S_OK;
|
|
}
|
|
HRESULT CoCreateInstance( REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
|
|
{
|
|
SASSERT(p == NULL);
|
|
return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
|
|
}
|
|
HRESULT CoCreateInstance( LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) throw()
|
|
{
|
|
CLSID clsid;
|
|
HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
|
|
SASSERT(p == NULL);
|
|
if (SUCCEEDED(hr))
|
|
hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
|
|
return hr;
|
|
}
|
|
template <class Q>
|
|
HRESULT QueryInterface( Q** pp) const throw()
|
|
{
|
|
SASSERT(pp != NULL);
|
|
return p->QueryInterface(__uuidof(Q), (void**)pp);
|
|
}
|
|
T* p;
|
|
};
|
|
|
|
template <class T>
|
|
class SComPtr : public SComPtrBase<T>
|
|
{
|
|
public:
|
|
SComPtr() throw()
|
|
{
|
|
}
|
|
SComPtr(int nNull) throw() :
|
|
SComPtrBase<T>(nNull)
|
|
{
|
|
}
|
|
SComPtr(T* lp) throw() :
|
|
SComPtrBase<T>(lp)
|
|
|
|
{
|
|
}
|
|
SComPtr( const SComPtr<T>& lp) throw() :
|
|
SComPtrBase<T>(lp.p)
|
|
{
|
|
}
|
|
T* operator=( T* lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<T*>(SComPtrAssign((IUnknown**)&this->p, lp));
|
|
}
|
|
return *this;
|
|
}
|
|
template <typename Q>
|
|
T* operator=( const SComPtr<Q>& lp) throw()
|
|
{
|
|
if( !IsEqualObject(lp) )
|
|
{
|
|
return static_cast<T*>(SComQIPtrAssign((IUnknown**)&this->p, lp, __uuidof(T)));
|
|
}
|
|
return *this;
|
|
}
|
|
T* operator=( const SComPtr<T>& lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<T*>(SComPtrAssign((IUnknown**)&this->p, lp));
|
|
}
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
//specialization for IDispatch
|
|
template <>
|
|
class SComPtr<IDispatch> : public SComPtrBase<IDispatch>
|
|
{
|
|
public:
|
|
SComPtr() throw()
|
|
{
|
|
}
|
|
SComPtr(IDispatch* lp) throw() :
|
|
SComPtrBase<IDispatch>(lp)
|
|
{
|
|
}
|
|
SComPtr(const SComPtr<IDispatch>& lp) throw() :
|
|
SComPtrBase<IDispatch>(lp.p)
|
|
{
|
|
}
|
|
IDispatch* operator=(IDispatch* lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<IDispatch*>(SComPtrAssign((IUnknown**)&p, lp));
|
|
}
|
|
return *this;
|
|
}
|
|
IDispatch* operator=(const SComPtr<IDispatch>& lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<IDispatch*>(SComPtrAssign((IUnknown**)&p, lp.p));
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// IDispatch specific stuff
|
|
HRESULT GetPropertyByName( LPCOLESTR lpsz, VARIANT* pVar) throw()
|
|
{
|
|
SASSERT(p);
|
|
SASSERT(pVar);
|
|
DISPID dwDispID;
|
|
HRESULT hr = GetIDOfName(lpsz, &dwDispID);
|
|
if (SUCCEEDED(hr))
|
|
hr = GetProperty(dwDispID, pVar);
|
|
return hr;
|
|
}
|
|
HRESULT GetProperty( DISPID dwDispID, VARIANT* pVar) throw()
|
|
{
|
|
return GetProperty(p, dwDispID, pVar);
|
|
}
|
|
HRESULT PutPropertyByName( LPCOLESTR lpsz, VARIANT* pVar) throw()
|
|
{
|
|
SASSERT(p);
|
|
SASSERT(pVar);
|
|
DISPID dwDispID;
|
|
HRESULT hr = GetIDOfName(lpsz, &dwDispID);
|
|
if (SUCCEEDED(hr))
|
|
hr = PutProperty(dwDispID, pVar);
|
|
return hr;
|
|
}
|
|
HRESULT PutProperty( DISPID dwDispID, VARIANT* pVar) throw()
|
|
{
|
|
return PutProperty(p, dwDispID, pVar);
|
|
}
|
|
HRESULT GetIDOfName( LPCOLESTR lpsz, DISPID* pdispid) throw()
|
|
{
|
|
return p->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid);
|
|
}
|
|
// Invoke a method by DISPID with no parameters
|
|
HRESULT Invoke0( DISPID dispid, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
DISPPARAMS dispparams = { NULL, NULL, 0, 0};
|
|
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
|
|
}
|
|
// Invoke a method by name with no parameters
|
|
HRESULT Invoke0( LPCOLESTR lpszName, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
HRESULT hr;
|
|
DISPID dispid;
|
|
hr = GetIDOfName(lpszName, &dispid);
|
|
if (SUCCEEDED(hr))
|
|
hr = Invoke0(dispid, pvarRet);
|
|
return hr;
|
|
}
|
|
// Invoke a method by DISPID with a single parameter
|
|
HRESULT Invoke1( DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0};
|
|
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
|
|
}
|
|
// Invoke a method by name with a single parameter
|
|
HRESULT Invoke1( LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
HRESULT hr;
|
|
DISPID dispid;
|
|
hr = GetIDOfName(lpszName, &dispid);
|
|
if (SUCCEEDED(hr))
|
|
hr = Invoke1(dispid, pvarParam1, pvarRet);
|
|
return hr;
|
|
}
|
|
// Invoke a method by DISPID with two parameters
|
|
HRESULT Invoke2( DISPID dispid, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL) throw();
|
|
// Invoke a method by name with two parameters
|
|
HRESULT Invoke2( LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
HRESULT hr;
|
|
DISPID dispid;
|
|
hr = GetIDOfName(lpszName, &dispid);
|
|
if (SUCCEEDED(hr))
|
|
hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet);
|
|
return hr;
|
|
}
|
|
// Invoke a method by DISPID with N parameters
|
|
HRESULT InvokeN(DISPID dispid, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
DISPPARAMS dispparams = { pvarParams, NULL, (UINT)nParams, 0};
|
|
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
|
|
}
|
|
// Invoke a method by name with Nparameters
|
|
HRESULT InvokeN(LPCOLESTR lpszName, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw()
|
|
{
|
|
HRESULT hr;
|
|
DISPID dispid;
|
|
hr = GetIDOfName(lpszName, &dispid);
|
|
if (SUCCEEDED(hr))
|
|
hr = InvokeN(dispid, pvarParams, nParams, pvarRet);
|
|
return hr;
|
|
}
|
|
static HRESULT PutProperty( IDispatch* p, DISPID dwDispID, VARIANT* pVar) throw()
|
|
{
|
|
SASSERT(p);
|
|
SASSERT(pVar != NULL);
|
|
if (pVar == NULL)
|
|
return E_POINTER;
|
|
|
|
if(p == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
DISPPARAMS dispparams = {NULL, NULL, 1, 1};
|
|
dispparams.rgvarg = pVar;
|
|
DISPID dispidPut = DISPID_PROPERTYPUT;
|
|
dispparams.rgdispidNamedArgs = &dispidPut;
|
|
|
|
if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH ||
|
|
(pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF))
|
|
{
|
|
HRESULT hr = p->Invoke(dwDispID, IID_NULL,
|
|
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
|
|
&dispparams, NULL, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
return hr;
|
|
}
|
|
return p->Invoke(dwDispID, IID_NULL,
|
|
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
|
|
&dispparams, NULL, NULL, NULL);
|
|
}
|
|
static HRESULT GetProperty( IDispatch* p, DISPID dwDispID, VARIANT* pVar) throw()
|
|
{
|
|
SASSERT(p);
|
|
SASSERT(pVar != NULL);
|
|
if (pVar == NULL)
|
|
return E_POINTER;
|
|
|
|
if(p == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
|
|
return p->Invoke(dwDispID, IID_NULL,
|
|
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
|
|
&dispparamsNoArgs, pVar, NULL, NULL);
|
|
}
|
|
};
|
|
|
|
template <class T, const IID* piid = &__uuidof(T)>
|
|
class SComQIPtr : public SComPtr<T>
|
|
{
|
|
public:
|
|
SComQIPtr() throw()
|
|
{
|
|
}
|
|
SComQIPtr( T* lp) throw() :
|
|
SComPtr<T>(lp)
|
|
{
|
|
}
|
|
SComQIPtr( const SComQIPtr<T,piid>& lp) throw() :
|
|
SComPtr<T>(lp.p)
|
|
{
|
|
}
|
|
SComQIPtr( IUnknown* lp) throw()
|
|
{
|
|
if (lp != NULL)
|
|
lp->QueryInterface(*piid, (void **)&this->p);
|
|
}
|
|
T* operator=( T* lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<T*>(SComPtrAssign((IUnknown**)&this->p, lp));
|
|
}
|
|
return *this;
|
|
}
|
|
T* operator=( const SComQIPtr<T,piid>& lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<T*>(SComPtrAssign((IUnknown**)&this->p, lp.p));
|
|
}
|
|
return *this;
|
|
}
|
|
T* operator=( IUnknown* lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return static_cast<T*>(SComQIPtrAssign((IUnknown**)&this->p, lp, *piid));
|
|
}
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
//Specialization to make it work
|
|
template<>
|
|
class SComQIPtr<IUnknown, &IID_IUnknown> : public SComPtr<IUnknown>
|
|
{
|
|
public:
|
|
SComQIPtr() throw()
|
|
{
|
|
}
|
|
SComQIPtr( IUnknown* lp) throw()
|
|
{
|
|
//Actually do a QI to get identity
|
|
if (lp != NULL)
|
|
lp->QueryInterface(__uuidof(IUnknown), (void **)&p);
|
|
}
|
|
SComQIPtr( const SComQIPtr<IUnknown,&IID_IUnknown>& lp) throw() :
|
|
SComPtr<IUnknown>(lp.p)
|
|
{
|
|
}
|
|
IUnknown* operator=( IUnknown* lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
//Actually do a QI to get identity
|
|
return SComQIPtrAssign((IUnknown**)&p, lp, __uuidof(IUnknown));
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
IUnknown* operator=( const SComQIPtr<IUnknown,&IID_IUnknown>& lp) throw()
|
|
{
|
|
if(*this!=lp)
|
|
{
|
|
return SComPtrAssign((IUnknown**)&p, lp.p);
|
|
}
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
typedef SComQIPtr<IDispatch, &__uuidof(IDispatch)> CComDispatchDriver;
|
|
|
|
} // namespace SOUI
|
|
#pragma pack(pop)
|
|
|
|
#pragma warning (pop)
|
|
|
|
|
|
#endif // __SCOMCLI_H__
|
|
|