template <class Base, class Interface, const IID* piid = &__uuidof(Interface)>
class TCustomSink : public Base
{
private:
  CComPtr<IUnknown> m_ptrSender; // rdo zdarzenia
  DWORD m_dwCookie;              // Identyfikator poczenia

public:
  TCustomSink() :
    m_dwCookie(0) { }

  virtual ~TCustomSink()  { Disconnect(); }

  // IUnknown
  STDMETHOD_(ULONG, AddRef)() { return 1; }
  STDMETHOD_(ULONG, Release)() { return 1; }
  STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
    { return _InternalQueryInterface(iid, ppvObject); }

public:
  // czenie i odczanie od rda zdarze
  HRESULT __fastcall Connect(IUnknown* pSender)
  {
    HRESULT hr = S_FALSE;

    if (pSender != m_ptrSender)
    {
       m_ptrSender = pSender;
       if (m_ptrSender != NULL)
       {
         CComPtr<IUnknown> ptrUnk;
         QueryInterface(IID_IUnknown, reinterpret_cast<LPVOID*>(&ptrUnk));
         hr = AtlAdvise(m_ptrSender, ptrUnk, *piid, &m_dwCookie);
       }
    }

    return hr;
  }

  HRESULT __fastcall Disconnect()
  {
    HRESULT hr = S_FALSE;

    if ( (m_ptrSender != NULL) &&
           (0 != m_dwCookie) )
    {
      hr = AtlUnadvise(m_ptrSender, *piid, m_dwCookie);
      m_dwCookie = 0;
      m_ptrSender = NULL;
    }

    return hr;
  }
};
