|
|
#ifndef __CNCTNPT_H__
#define __CNCTNPT_H__
//
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//
// This class is shared between DLLs, and DLLs that use it have already
// shipped as part of IE4 (specifically, shell32). This means that
// any changes you make must be done EXTREMELY CAREFULLY and TESTED
// FOR INTEROPERABILITY WITH IE4! For one thing, you have to make sure
// that none of your changes alter the vtbl used by IE4's shell32.
//
// If you change CIE4ConnectionPoint, you must build SHDOC401 and
// test it on IE4!
//
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//
//
// First, the class as it was defined in IE4. All virtual functions
// must be be listed in exactly the same order as they were in IE4.
// Fortunately, no cross-component users mucked with the member
// variables.
//
// Change any of these at your own risk.
//
class CIE4ConnectionPoint : public IConnectionPoint {
public: // IUnknown methods
//
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj) PURE; virtual STDMETHODIMP_(ULONG) AddRef(void) PURE; virtual STDMETHODIMP_(ULONG) Release(void) PURE;
// IConnectionPoint methods
//
virtual STDMETHODIMP GetConnectionInterface(IID FAR* pIID) PURE; virtual STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer FAR* FAR* ppCPC) PURE; virtual STDMETHODIMP Advise(LPUNKNOWN pUnkSink, DWORD FAR* pdwCookie) PURE; virtual STDMETHODIMP Unadvise(DWORD dwCookie) PURE; virtual STDMETHODIMP EnumConnections(LPENUMCONNECTIONS FAR* ppEnum) PURE;
// This is how you actually fire the events
// Those called by shell32 are virtual
// (Renamed to DoInvokeIE4)
virtual HRESULT DoInvokeIE4(LPBOOL pf, LPVOID *ppv, DISPID dispid, DISPPARAMS *pdispparams) PURE;
// This helper function does work that callers of DoInvoke often need done
virtual HRESULT DoInvokePIDLIE4(DISPID dispid, LPCITEMIDLIST pidl, BOOL fCanCancel) PURE;
};
//
// CConnectionPoint is an implementation of a conection point.
// To get the rest of the implementation, you also have to include
// lib\cnctnpt.cpp in your project.
//
// Embed an instance of CConnectionPoint in an object that needs to
// implement a connectionpoint and call SetOwner to initialize it.
//
// Fire events to anyone connected to this connectionpoint via DoInvoke
// or DoOnChanged. External clients should use the shlwapi functions
// like IConnectionPoint_Invoke or IConnectionPoint_OnChanged.
//
class CConnectionPoint : public CIE4ConnectionPoint { friend class CConnectionPointEnum;
public: // IUnknown methods
//
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj); virtual STDMETHODIMP_(ULONG) AddRef(void) { return m_punk->AddRef(); } virtual STDMETHODIMP_(ULONG) Release(void) { return m_punk->Release(); }
// IConnectionPoint methods
//
virtual STDMETHODIMP GetConnectionInterface(IID * pIID); virtual STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer ** ppCPC); virtual STDMETHODIMP Advise(LPUNKNOWN pUnkSink, DWORD * pdwCookie); virtual STDMETHODIMP Unadvise(DWORD dwCookie); virtual STDMETHODIMP EnumConnections(LPENUMCONNECTIONS * ppEnum);
// CIE4ConnectionPoint methods - called by IE4's shell32
virtual HRESULT DoInvokeIE4(LPBOOL pf, LPVOID *ppv, DISPID dispid, DISPPARAMS *pdispparams);
// DoInvokePidlIE4 is strange in that shell32 linked to it but never
// actually called it. This makes the implementation particularly simple.
virtual HRESULT DoInvokePIDLIE4(DISPID dispid, LPCITEMIDLIST pidl, BOOL fCanCancel) { return E_NOTIMPL; }
public: // Additional helper methods
// Performs a basic DISPID Invoke on the object
inline HRESULT InvokeDispid(DISPID dispid) { return IConnectionPoint_SimpleInvoke(this, dispid, NULL); }
// Performs an OnChanged on the object
inline HRESULT OnChanged(DISPID dispid) { return IConnectionPoint_OnChanged(this, dispid); }
// A couple functions to setup and destroy this subclass object
~CConnectionPoint(); // not virtual: nobody inherits from this class
//
// The containing object must call SetOwner to initialize the
// connection point.
//
// punk - The IUnknown of the object this ConnectionPoint is
// embedded in; it will be treated as the connection
// point container.
//
// piid - The IID that the sinks are expected to support.
// If you call DoInvoke, then it must be derived from
// IID_IDispatch. If you call DoOnChanged, then it must
// be exactly &IID_IPropertyNotifySink.
//
void SetOwner(IUnknown* punk, const IID* piid) { // Validate the special requirement on the piid parameter.
if (*piid == IID_IPropertyNotifySink) { ASSERT(piid == &IID_IPropertyNotifySink); }
// don't AddRef -- we're a member variable of the object punk points to
m_punk = punk; m_piid = piid; }
// The underline version is inline
BOOL _HasSinks() { return (BOOL)m_cSinks; }
// We are empty if there are no sinks
BOOL IsEmpty() { return !_HasSinks(); }
HRESULT UnadviseAll(void);
// A lot of people need to convert a CConnectionPoint into an
// IConnectionPoint. We used to be multiply inherited, hence the
// need for this member, but that's gone now.
IConnectionPoint *CastToIConnectionPoint() { return SAFECAST(this, IConnectionPoint*); }
private: IUnknown **m_rgSinks; int m_cSinks; int m_cSinksAlloc;
IUnknown *m_punk; // IUnknown of object containing us
const IID *m_piid; // IID of this connection point
};
#endif
|