windows-nt/Source/XPSP1/NT/admin/pchealth/pchmars/inc/marscom.h
2020-09-26 16:20:57 +08:00

212 lines
6.6 KiB
C++

#pragma once
//
// Macro to delegate IDispatch to base class. Needed so that CMarsBehaviorSite vtbl works -
// the only other way to do this is make CMarsBehaviorSite and CMarsBehaviorFor templated classes
//
#define IMPLEMENT_IDISPATCH_DELEGATE_TO_BASE(BaseClass) \
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) \
{ return BaseClass::GetTypeInfoCount(pctinfo); } \
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) \
{ return BaseClass::GetTypeInfo(itinfo, lcid, pptinfo); } \
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, \
LCID lcid, DISPID* rgdispid) \
{ return BaseClass::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); } \
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, \
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, \
EXCEPINFO* pexcepinfo, UINT* puArgErr) \
{ return BaseClass::Invoke(dispidMember, riid, lcid, wFlags, \
pdispparams, pvarResult, pexcepinfo, puArgErr); }
//---------------------------------------------------------------------------------
// CMarsComObject provides some functionality used by all or most Mars com objects
// including addref/release and passivation
// Exposed methods should be protected to ensure that they're not called while the
// object is passive. There are three types of passivation protection:
// if (VerifyNotPassive()) - this function should not be called while passive,
// but we still want to protect against it
// if (IsPassive()) - this function may be called while passive,
// but we want to protect against it
// ASSERT(!IsPassive()); - we're pretty sure this won't be called while passive,
// but we want to detect it if it starts happening
// Use:
// derive from CMarsComObject
// IMPLEMENT_ADDREF_RELEASE in source file
// Implement DoPassivate()
// Use IsPassive() and VerifyNotPassive() where appropriate
// Don't call "delete" directly
// CYourClass->Passivate() should be called before CYourClass->Release()
// TODO: FENTER on Passivate() causes debug link warnings due to dupe functions
class CMarsComObject
{
protected:
LONG m_cRef;
BOOL m_fPassive;
protected:
virtual ~CMarsComObject() { ATLASSERT(IsPassive()); ATLASSERT(m_cRef==0); }
CMarsComObject() { m_cRef = 1; }
ULONG InternalAddRef()
{
return ++m_cRef;
}
ULONG InternalRelease()
{
if (--m_cRef)
{
return m_cRef;
}
delete this;
return 0;
}
inline BOOL VerifyNotPassive(HRESULT *phr=NULL)
{
if (IsPassive())
{
if (phr)
{
*phr = SCRIPT_ERROR;
}
return FALSE;
}
return TRUE;
}
inline HRESULT GetBSTROut(const BSTR &bstrParam, BSTR *pbstrOut)
{
HRESULT hr = E_UNEXPECTED;
ATLASSERT(API_IsValidBstr(bstrParam));
if (API_IsValidWritePtr(pbstrOut))
{
if (VerifyNotPassive(&hr))
{
*pbstrOut = ::SysAllocStringLen(bstrParam,
::SysStringLen(bstrParam));
hr = (*pbstrOut) ? S_OK : E_OUTOFMEMORY;
}
else
{
*pbstrOut = NULL;
}
}
return hr;
}
virtual HRESULT DoPassivate() = 0;
public:
BOOL IsPassive() { return m_fPassive; }
virtual HRESULT Passivate()
{
if (!IsPassive())
{
m_fPassive=TRUE;
return DoPassivate();
}
else
{
return S_FALSE;
}
}
};
#define IMPLEMENT_ADDREF_RELEASE(cls) \
STDMETHODIMP_(ULONG) cls::AddRef() \
{ \
return InternalAddRef(); \
} \
\
STDMETHODIMP_(ULONG) cls::Release() \
{ \
return InternalRelease(); \
}
#define FAIL_AFTER_PASSIVATE() if(IsPassive()) { ATLASSERT(0); return E_FAIL; }
//---------------------------------------------------------------------------------
// CMarsComObjectDelegate is used by objects which are completely contained within
// another object. They delegate their lifetime to the other object and are
// passivated when the parent is passivated.
// Use:
// derive from CMarsComObjectDelegate<ParentClass>
// IMPLEMENT_ADDREF_RELEASE in source file
// Implement DoPassivate()
// Use IsPassive() and VerifyNotPassive() where appropriate
// Use Parent() to access the parent object
template <class clsDelegateTo> class CMarsComObjectDelegate
{
clsDelegateTo *m_pParent;
// DEBUG_ONLY(BOOL m_fPassivateCalled);
protected:
virtual ~CMarsComObjectDelegate() { ATLASSERT(m_fPassivateCalled); }
CMarsComObjectDelegate(clsDelegateTo *pParent)
{
ATLASSERT(pParent);
m_pParent = pParent;
}
ULONG InternalAddRef() { return m_pParent->AddRef(); }
ULONG InternalRelease() { return m_pParent->Release(); }
clsDelegateTo *Parent() { ATLASSERT(!IsPassive()); return m_pParent; }
inline BOOL VerifyNotPassive(HRESULT *phr=NULL)
{
ATLASSERT(m_fPassivateCalled == IsPassive());
if (m_pParent->IsPassive())
{
if (phr)
{
*phr = SCRIPT_ERROR;
}
return FALSE;
}
return TRUE;
}
virtual HRESULT DoPassivate() = 0;
public:
BOOL IsPassive() { return m_pParent->IsPassive(); }
private:
friend clsDelegateTo;
HRESULT Passivate()
{
// TODO: assert that we are being called by our parent's DoPassivate
ATLASSERT(m_fPassivateCalled==FALSE);
//DEBUG_ONLY(m_fPassivateCalled=TRUE);
return DoPassivate();
}
};
// This typedef's some CxxxSubObject types to make syntax easier
#define TYPEDEF_SUB_OBJECT(cls) typedef CMarsComObjectDelegate<class cls> cls##SubObject;