📄 atlcom.h
字号:
// This is a part of the Active Template Library.
// Copyright (C) 1996-1998 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 __ATLCOM_H__
#define __ATLCOM_H__
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLBASE_H__
#error atlcom.h requires atlbase.h to be included first
#endif
#pragma pack(push, _ATL_PACKING)
EXTERN_C const IID IID_ITargetFrame;
namespace ATL
{
#define CComConnectionPointContainerImpl IConnectionPointContainerImpl
#define CComISupportErrorInfoImpl ISupportErrorInfoImpl
#define CComProvideClassInfo2Impl IProvideClassInfoImpl
#define CComDualImpl IDispatchImpl
#ifdef _ATL_DEBUG_QI
#ifndef _ATL_DEBUG
#define _ATL_DEBUG
#endif // _ATL_DEBUG
#endif // _ATL_DEBUG_QI
#ifdef _ATL_DEBUG_QI
#define _ATLDUMPIID(iid, name, hr) AtlDumpIID(iid, name, hr)
#else
#define _ATLDUMPIID(iid, name, hr) hr
#endif
#define _ATL_DEBUG_ADDREF_RELEASE_IMPL(className)\
virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;\
virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
/////////////////////////////////////////////////////////////////////////////
// AtlReportError
inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid,
HRESULT hRes, HINSTANCE hInst)
{
return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst);
}
inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
{
return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID,
lpszHelpFile, iid, hRes, hInst);
}
#ifndef OLE2ANSI
inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid, HRESULT hRes)
{
ATLASSERT(lpszDesc != NULL);
USES_CONVERSION;
return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), dwHelpID, A2CW(lpszHelpFile),
iid, hRes, NULL);
}
inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
const IID& iid, HRESULT hRes)
{
ATLASSERT(lpszDesc != NULL);
USES_CONVERSION;
return AtlSetErrorInfo(clsid, A2COLE(lpszDesc), 0, NULL, iid, hRes, NULL);
}
#endif
inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc,
const IID& iid, HRESULT hRes)
{
return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL);
}
inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes)
{
return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL);
}
//////////////////////////////////////////////////////////////////////////////
// IPersistImpl
template <class T>
class ATL_NO_VTABLE IPersistImpl : public IPersist
{
public:
STDMETHOD(GetClassID)(CLSID *pClassID)
{
ATLTRACE2(atlTraceCOM, 0, _T("IPersistImpl::GetClassID\n"));
if (pClassID == NULL)
return E_FAIL;
*pClassID = T::GetObjectCLSID();
return S_OK;
}
};
//////////////////////////////////////////////////////////////////////////////
// CComDispatchDriver / Specialization of CComQIPtr<IDispatch, IID_IDispatch>
class CComDispatchDriver
{
public:
CComDispatchDriver()
{
p = NULL;
}
CComDispatchDriver(IDispatch* lp)
{
if ((p = lp) != NULL)
p->AddRef();
}
CComDispatchDriver(IUnknown* lp)
{
p=NULL;
if (lp != NULL)
lp->QueryInterface(IID_IDispatch, (void **)&p);
}
~CComDispatchDriver() { if (p) p->Release(); }
void Release() {if (p) p->Release(); p=NULL;}
operator IDispatch*() {return p;}
IDispatch& operator*() {ATLASSERT(p!=NULL); return *p; }
IDispatch** operator&() {ATLASSERT(p==NULL); return &p; }
IDispatch* operator->() {ATLASSERT(p!=NULL); return p; }
IDispatch* operator=(IDispatch* lp){return (IDispatch*)AtlComPtrAssign((IUnknown**)&p, lp);}
IDispatch* operator=(IUnknown* lp)
{
return (IDispatch*)AtlComQIPtrAssign((IUnknown**)&p, lp, IID_IDispatch);
}
BOOL operator!(){return (p == NULL) ? TRUE : FALSE;}
HRESULT GetPropertyByName(LPCOLESTR lpsz, VARIANT* pVar)
{
ATLASSERT(p);
ATLASSERT(pVar);
DISPID dwDispID;
HRESULT hr = GetIDOfName(lpsz, &dwDispID);
if (SUCCEEDED(hr))
hr = GetProperty(p, dwDispID, pVar);
return hr;
}
HRESULT GetProperty(DISPID dwDispID, VARIANT* pVar)
{
ATLASSERT(p);
return GetProperty(p, dwDispID, pVar);
}
HRESULT PutPropertyByName(LPCOLESTR lpsz, VARIANT* pVar)
{
ATLASSERT(p);
ATLASSERT(pVar);
DISPID dwDispID;
HRESULT hr = GetIDOfName(lpsz, &dwDispID);
if (SUCCEEDED(hr))
hr = PutProperty(p, dwDispID, pVar);
return hr;
}
HRESULT PutProperty(DISPID dwDispID, VARIANT* pVar)
{
ATLASSERT(p);
return PutProperty(p, dwDispID, pVar);
}
HRESULT GetIDOfName(LPCOLESTR lpsz, DISPID* pdispid)
{
return p->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpsz, 1, LOCALE_USER_DEFAULT, pdispid);
}
// Invoke a method by DISPID with no parameters
HRESULT Invoke0(DISPID dispid, VARIANT* pvarRet = NULL)
{
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)
{
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)
{
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)
{
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)
{
CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 };
DISPPARAMS dispparams = { &varArgs[0], NULL, 2, 0};
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
}
// Invoke a method by name with two parameters
HRESULT Invoke2(LPCOLESTR lpszName, VARIANT* pvarParam1, VARIANT* pvarParam2, VARIANT* pvarRet = NULL)
{
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)
{
DISPPARAMS dispparams = { pvarParams, NULL, 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)
{
HRESULT hr;
DISPID dispid;
hr = GetIDOfName(lpszName, &dispid);
if (SUCCEEDED(hr))
hr = InvokeN(dispid, pvarParams, nParams, pvarRet);
return hr;
}
static HRESULT GetProperty(IDispatch* pDisp, DISPID dwDispID,
VARIANT* pVar)
{
ATLTRACE2(atlTraceCOM, 0, _T("CPropertyHelper::GetProperty\n"));
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
return pDisp->Invoke(dwDispID, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
&dispparamsNoArgs, pVar, NULL, NULL);
}
static HRESULT PutProperty(IDispatch* pDisp, DISPID dwDispID,
VARIANT* pVar)
{
ATLTRACE2(atlTraceCOM, 0, _T("CPropertyHelper::PutProperty\n"));
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 = pDisp->Invoke(dwDispID, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
&dispparams, NULL, NULL, NULL);
if (SUCCEEDED(hr))
return hr;
}
return pDisp->Invoke(dwDispID, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
&dispparams, NULL, NULL, NULL);
}
IDispatch* p;
};
//////////////////////////////////////////////////////////////////////////////
// CFakeFirePropNotifyEvent
class CFakeFirePropNotifyEvent
{
public:
static HRESULT FireOnRequestEdit(IUnknown* /*pUnk*/, DISPID /*dispID*/)
{
return S_OK;
}
static HRESULT FireOnChanged(IUnknown* /*pUnk*/, DISPID /*dispID*/)
{
return S_OK;
}
};
typedef CFakeFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS;
//////////////////////////////////////////////////////////////////////////////
// ATL Persistence
struct ATL_PROPMAP_ENTRY
{
LPCOLESTR szDesc;
DISPID dispid;
const CLSID* pclsidPropPage;
const IID* piidDispatch;
DWORD dwOffsetData;
DWORD dwSizeData;
VARTYPE vt;
};
// This one is DEPRECATED and is used for ATL 2.X controls
// it includes an implicit m_sizeExtent
#define BEGIN_PROPERTY_MAP(theClass) \
typedef _ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \
typedef theClass _PropMapClass; \
static ATL_PROPMAP_ENTRY* GetPropertyMap()\
{\
static ATL_PROPMAP_ENTRY pPropMap[] = \
{ \
{OLESTR("_cx"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cx), sizeof(long), VT_UI4}, \
{OLESTR("_cy"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cy), sizeof(long), VT_UI4},
// This one can be used on any type of object, but does not
// include the implicit m_sizeExtent
#define BEGIN_PROP_MAP(theClass) \
typedef _ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \
typedef theClass _PropMapClass; \
static ATL_PROPMAP_ENTRY* GetPropertyMap()\
{\
static ATL_PROPMAP_ENTRY pPropMap[] = \
{
#define PROP_ENTRY(szDesc, dispid, clsid) \
{OLESTR(szDesc), dispid, &clsid, &IID_IDispatch, 0, 0, 0},
#define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \
{OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, 0},
#define PROP_PAGE(clsid) \
{NULL, NULL, &clsid, &IID_NULL, 0, 0, 0},
#define PROP_DATA_ENTRY(szDesc, member, vt) \
{OLESTR(szDesc), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, member), sizeof(((_PropMapClass*)0)->member), vt},
#define END_PROPERTY_MAP() \
{NULL, 0, NULL, &IID_NULL, 0, 0, 0} \
}; \
return pPropMap; \
}
#define END_PROP_MAP() \
{NULL, 0, NULL, &IID_NULL, 0, 0, 0} \
}; \
return pPropMap; \
}
#ifdef _ATL_DLL
ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
#else
ATLINLINE ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
{
ATLASSERT(pMap != NULL);
HRESULT hr = S_OK;
DWORD dwVer;
hr = pStm->Read(&dwVer, sizeof(DWORD), NULL);
if (FAILED(hr))
return hr;
if (dwVer > _ATL_VER)
return E_FAIL;
CComPtr<IDispatch> pDispatch;
const IID* piidOld = NULL;
for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
{
if (pMap[i].szDesc == NULL)
continue;
// check if raw data entry
if (pMap[i].dwSizeData != 0)
{
void* pData = (void*) (pMap[i].dwOffsetData + (DWORD)pThis);
hr = pStm->Read(pData, pMap[i].dwSizeData, NULL);
if (FAILED(hr))
return hr;
continue;
}
CComVariant var;
hr = var.ReadFromStream(pStm);
if (FAILED(hr))
break;
if (pMap[i].piidDispatch != piidOld)
{
pDispatch.Release();
if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
{
ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
hr = E_FAIL;
break;
}
piidOld = pMap[i].piidDispatch;
}
if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
{
ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
hr = E_FAIL;
break;
}
}
return hr;
}
#endif //_ATL_DLL
#ifdef _ATL_DLL
ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
#else
ATLINLINE ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm,
BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap,
void* pThis, IUnknown* pUnk)
{
ATLASSERT(pMap != NULL);
DWORD dw = _ATL_VER;
HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL);
if (FAILED(hr))
return hr;
CComPtr<IDispatch> pDispatch;
const IID* piidOld = NULL;
for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
{
if (pMap[i].szDesc == NULL)
continue;
// check if raw data entry
if (pMap[i].dwSizeData != 0)
{
void* pData = (void*) (pMap[i].dwOffsetData + (DWORD)pThis);
hr = pStm->Write(pData, pMap[i].dwSizeData, NULL);
if (FAILED(hr))
return hr;
continue;
}
CComVariant var;
if (pMap[i].piidDispatch != piidOld)
{
pDispatch.Release();
if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
{
ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
hr = E_FAIL;
break;
}
piidOld = pMap[i].piidDispatch;
}
if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
{
ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
hr = E_FAIL;
break;
}
hr = var.WriteToStream(pStm);
if (FAILED(hr))
break;
}
return hr;
}
#endif //_ATL_DLL
#ifdef _ATL_DLL
ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
#else
ATLINLINE ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
{
USES_CONVERSION;
CComPtr<IDispatch> pDispatch;
const IID* piidOld = NULL;
for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
{
if (pMap[i].szDesc == NULL)
continue;
CComVariant var;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -