//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: Mft.hxx (sample stackable filter) // // Contents: // // Classes: // // Functions: // // History: 04-16-97 DanpoZ (Danpo Zhang) Created // //---------------------------------------------------------------------------- #ifndef _CMFT_HXX_ #define _CMFT_HXX_ #include //+--------------------------------------------------------------------------- // // Class: CMft // // Purpose: Mime filter // // Interface: [support all IOInetProtocol interfaces] // [support all IOInetProtocolSink interfaces] // // History: 11-24-97 DanpoZ (Danpo Zhang) Created // //---------------------------------------------------------------------------- class CMft : public IOInetProtocol, public IOInetProtocolSink, public IOInetProtocolSinkStackable { public: // IUnknown methods STDMETHODIMP QueryInterface(REFIID iid, void **ppvObj) { HRESULT hr = E_NOINTERFACE; *ppvObj = NULL; if( (iid == IID_IUnknown) || (iid == IID_IOInetProtocol) || (iid == IID_IOInetProtocolRoot) ) { *ppvObj = (IOInetProtocol*)this; } else if( iid == IID_IOInetProtocolSink ) { *ppvObj = (IOInetProtocolSink*)this; } else if( iid == IID_IOInetProtocolSinkStackable ) { *ppvObj = (IOInetProtocolSinkStackable*)this; } if( *ppvObj ) { hr = NOERROR; AddRef(); } return hr; } STDMETHODIMP_(ULONG) AddRef(void) { LONG lRet = ++_CRefs; return lRet; } STDMETHODIMP_(ULONG) Release(void) { LONG lRet = --_CRefs; if( !lRet ) { delete this; } return lRet; } // IOInetProtocol STDMETHODIMP Start( LPCWSTR szUrl, IOInetProtocolSink *pProtSink, IOInetBindInfo *pOIBindInfo, DWORD grfSTI, DWORD dwReserved ) { PROTOCOLFILTERDATA* FiltData = (PROTOCOLFILTERDATA*) dwReserved; _pProt = FiltData->pProtocol; _pProtSink = pProtSink; _pProt->AddRef(); _pProtSink->AddRef(); return NOERROR; } STDMETHODIMP Continue( PROTOCOLDATA *pStateInfo) { return _pProt->Continue(pStateInfo); } STDMETHODIMP Abort( HRESULT hrReason, DWORD dwOptions) { return _pProt->Abort(hrReason, dwOptions); } STDMETHODIMP Terminate( DWORD dwOptions) { if( _pProtSink ) { _pProtSink->Release(); _pProtSink = NULL; } return _pProt->Terminate(dwOptions); } STDMETHODIMP Suspend() { return _pProt->Suspend(); } STDMETHODIMP Resume() { return _pProt->Resume(); } STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead) { return _pProt->Read(pv, cb, pcbRead); } STDMETHODIMP Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition ) { return _pProt->Seek(dlibMove, dwOrigin, plibNewPosition); } STDMETHODIMP LockRequest(DWORD dwOptions) { return _pProt->LockRequest(dwOptions); } STDMETHODIMP UnlockRequest() { return _pProt->UnlockRequest(); } STDMETHODIMP Switch( PROTOCOLDATA *pStateInfo) { return _pProtSink->Switch(pStateInfo); } STDMETHODIMP ReportProgress( ULONG ulStatusCode, LPCWSTR szStatusText) { return _pProtSink->ReportProgress(ulStatusCode, szStatusText); } STDMETHODIMP ReportData( DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax ) { return _pProtSink->ReportData(grfBSCF, ulProgress, ulProgressMax); } STDMETHODIMP ReportResult( HRESULT hrResult, DWORD dwError, LPCWSTR wzResult ) { return _pProtSink->ReportResult(hrResult, dwError, wzResult); } STDMETHODIMP SwitchSink(IOInetProtocolSink* pSink) { HRESULT hr = NOERROR; // keep track the existing sink (support for Commit/Rollback) // the release of the old sink will be done at the Commit time _pProtSinkOld = _pProtSink; // ----------------------------------------------------------- // BUG: remove this block once enable the Commit-Rollback func // release the old sink // if( _pProtSinkOld ) { _pProtSinkOld->Release(); } // ----------------------------------------------------------- // Change the sink _pProtSink = pSink; _pProtSink->AddRef(); return hr; } STDMETHODIMP CommitSwitch() { // release the old sink //if( _pProtSinkOld ) //{ // _pProtSinkOld->Release(); //} // reset //_pProtSinkOld = NULL; return NOERROR; } STDMETHODIMP RollbackSwitch() { // copy the old sink back, release the new sink // (new sink is AddRef'ed at SwitchSink time) //if( _pProtSink ) //{ // _pProtSink->Release(); //} //_pProtSink = _pProtSinkOld; // reset //_pProtSinkOld = NULL; return NOERROR; } CMft() : _CRefs() { _pProtSink = NULL; _pProt = NULL; _pProtSinkOld = NULL; } virtual ~CMft() { if( _pProt ) { _pProt->Release(); } } private: CRefCount _CRefs; IOInetProtocol* _pProt; IOInetProtocolSink* _pProtSink; IOInetProtocolSink* _pProtSinkOld; }; #endif