//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: CNet.hxx // // Contents: // // Classes: // // Functions: // // History: 12-04-95 JohannP (Johann Posch) Created // //---------------------------------------------------------------------------- #ifndef _CNET_HXX_ #define _CNET_HXX_ #include const ULONG SENDBUFFER_MAX = 8192; const ULONG MAX_ACP_ENCHEADERS_SIZE=128; #ifdef unix #undef offsetof #endif /* unix */ #define offsetof(s,m) ( (SIZE_T) &(((s *)0)->m) ) //+---------------------------------------------------------------------------- // // Macro: // GETPPARENT // // Synopsis: // Given a pointer to something contained by a struct (or // class,) the type name of the containing struct (or class), // and the name of the member being pointed to, return a pointer // to the container. // // Arguments: // [pmemb] -- pointer to member of struct (or class.) // [struc] -- type name of containing struct (or class.) // [membname] - name of member within the struct (or class.) // // Returns: // pointer to containing struct (or class) // // Notes: // Assumes all pointers are FAR. // // History: // //----------------------------------------------------------------------------- #define GETPPARENT(pmemb, struc, membname) (\ (struc*)(((char*)(pmemb))-offsetof(struc, membname))) #define INET_E_OK NOERROR #define INET_E_DONE _HRESULT_TYPEDEF_(0x800A0001L) #define AUTHENTICATE_MAX 3 // number of authentication retries typedef enum { INetState_None = 0 ,INetState_START = 1 ,INetState_OPEN_REQUEST ,INetState_CONNECT_REQUEST ,INetState_PROTOPEN_REQUEST ,INetState_SEND_REQUEST ,INetState_AUTHENTICATE ,INetState_DISPLAY_UI ,INetState_READ ,INetState_DATA_AVAILABLE ,INetState_READ_DIRECT ,INetState_DATA_AVAILABLE_DIRECT ,INetState_INETSTATE_CHANGE ,INetState_DONE ,INetState_ABORT ,INetState_ERROR } INetState; typedef enum { HandleState_None = 0 ,HandleState_Pending = 1 ,HandleState_Initialized ,HandleState_Aborted ,HandleState_Closed } HandleState; class CUrl; class CAuthData; class CINet; class CINetEmbdFilter; class CINetProtImpl; //+--------------------------------------------------------------------------- // // Class: CINet () // // Purpose: class to interact with WinINet // // Interface: dwFlags -- // hThread -- // dwThreadID -- // state -- // uError -- // ipPort -- // postData -- // dwProto -- // _hServer -- // _hRequest -- // _dwIsA -- // _cbDataSize -- // _cbTotalBytesRead -- // _cbReadReturn -- // _pCTransData -- // _pCTrans -- // _hrINet -- // _dwState -- // _hr -- // INetAsyncStart -- // OnINetStart -- // INetAsyncOpen -- // OnINetAsyncOpen -- // OnINetOpen -- // INetAsyncConnect -- // OnINetConnect -- // INetAsyncOpenRequest -- // OnINetOpenRequest -- // INetAsyncSendRequest -- // OnINetSendRequest -- // INetQueryInfo -- // OnINetRead -- // INetRead -- // GetTransBindInfo -- // CINetCallback -- // TransitState -- // OnINetInternal -- // OnINetError -- // ReportResultAndStop -- // TerminateRequest -- // FindTagInHeader -- // ReportNotification -- // szBaseURL -- // szBaseURL -- // OperationOnAparmentThread -- // QueryInfoOnResponse -- // CINet -- // _dwIsA -- // ~CINet -- // QueryStatusOnResponse -- // QueryHeaderOnResponse -- // RedirectRequest -- // AuthenticationRequest -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINet : public IOInetProtocol, public IWinInetHttpInfo, public IOInetThreadSwitch, public IOInetPriority, public CUrl { public: // IUnknown methods STDMETHODIMP QueryInterface(REFIID iid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP Start( LPCWSTR szUrl, IOInetProtocolSink *pProtSink, IOInetBindInfo *pOIBindInfo, DWORD grfSTI, DWORD_PTR dwReserved ); STDMETHODIMP Continue( PROTOCOLDATA *pStateInfo ); STDMETHODIMP Abort( HRESULT hrReason, DWORD dwOptions ); STDMETHODIMP Terminate( DWORD dwOptions ); STDMETHODIMP Suspend(); STDMETHODIMP Resume(); STDMETHODIMP SetPriority(LONG nPriority); STDMETHODIMP GetPriority(LONG * pnPriority); virtual STDMETHODIMP Read( void *pv, ULONG cb, ULONG *pcbRead); STDMETHODIMP Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); STDMETHODIMP LockRequest( DWORD dwOptions); STDMETHODIMP UnlockRequest(); // IWinInetInfo STDMETHODIMP QueryOption(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf); // IWinInetHttpInfo STDMETHODIMP QueryInfo(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf, DWORD *pdwFlags, DWORD *pdwReserved); // IOInetThreadSwitch STDMETHODIMP Prepare(); STDMETHODIMP Continue(); static DWORD CALLBACK InternetAuthNotifyCallback( DWORD_PTR dwContext, // the this pointer DWORD dwAction, // action to be taken LPVOID lpReserved); // unused // My Interface STDMETHODIMP MyContinue( PROTOCOLDATA *pStateInfo ); STDMETHODIMP MyAbort( HRESULT hrReason, DWORD dwOptions ); STDMETHODIMP MyTerminate( DWORD dwOptions ); STDMETHODIMP MySuspend(); STDMETHODIMP MyResume(); STDMETHODIMP MySetPriority(LONG nPriority); STDMETHODIMP MyGetPriority(LONG * pnPriority); virtual STDMETHODIMP MyRead( void *pv, ULONG cb, ULONG *pcbRead); STDMETHODIMP MySeek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); STDMETHODIMP MyLockRequest( DWORD dwOptions); STDMETHODIMP MyUnlockRequest(); // Helper function for _pEmbdFilter sanity check: bool IsEmbdFilterOk(); public: //CINet data //private: //protected: DWORD _dwFlags; DWORD _dwThreadID; HRESULT _hrError; // error code INetState _INState; LPWSTR _pwzUrl; LPSTR _pszUserAgentStr; // wininet handles HINTERNET _hServer; HINTERNET _hRequest; DWORD _dwIsA; ULONG _cbDataSize; ULONG _cbTotalBytesRead; ULONG _cbReadReturn; ULONG _cbReadyToRead; ULONG _cbRedirect; ULONG _cbAuthenticate; ULONG _cbProxyAuthenticate; ULONG _cbSizeLastReportData; DWORD _bscf; BOOL _fProxyAuth; IOInetProtocolSink *_pCTrans; IOInetBindInfo *_pOIBindInfo; IServiceProvider *_pServiceProvider; IWindowForBindingUI *_pWindow; // Pointer to IWindowForBindingUI // Filter Handler, can handle cascade filters CINetEmbdFilter* _pEmbdFilter; DWORD _dwEmbdFilter; HRESULT _hrINet; INetState _dwState; HRESULT _hrPending; CRefCount _cReadCount; CMutexSem _mxs; DWORD _dwCacheFlags; DWORD _dwConnectFlags; DWORD _dwOpenFlags; DWORD _dwSendRequestResult; LPVOID _lpvExtraSendRequestResult; BOOL _fRedirected; BOOL _fP2PRedirected; BOOL _fLocked; BOOL _fDoSimpleRetry; BOOL _fCompleted; BOOL _fSendAgain; BOOL _fSendRequestAgain; BOOL _fForceSwitch; BOOL _fFilenameReported; BOOL _fHandlesRecycled; HANDLE _hFile; HANDLE _hLockHandle; REFCLSID _pclsidProtocol; DWORD _dwResult; LPSTR _pszResult; HandleState _HandleStateServer; HandleState _HandleStateRequest; CAuthData *_pCAuthData; HWND _hwndAuth; //new DWORD _grfBindF; BINDINFO _BndInfo; LONG _nPriority; // read direct stuff INTERNET_BUFFERS _inetBufferSend; INTERNET_BUFFERS _inetBufferReceived; private: CRefCount _CRefs; // the total refcount of this object CRefCount _CRefsHandles; // the number of handles in use by this object union { ULONG _flags; #ifndef unix struct { #endif /* unix */ unsigned _fAborted : 1; unsigned _fDone : 1; #ifndef unix }; #endif /* unix */ }; public: class CPrivUnknown : public IUnknown { public: STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj); STDMETHOD_(ULONG,AddRef) (void); STDMETHOD_(ULONG,Release) (void); ~CPrivUnknown() {} CPrivUnknown() : _CRefs() {} private: CRefCount _CRefs; // the total refcount of this object }; friend class CPrivUnknown; CPrivUnknown _Unknown; IUnknown *_pUnkOuter; BYTE* _pbRootSecurityId; DWORD _cbRootSecurityId; public: CINet(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINet(); IUnknown *GetIUnkInner(BOOL fReleaseOuter = FALSE) { if (fReleaseOuter) { PProtAssert((_CRefs > 0)); _CRefs--; } return &_Unknown; } protected: HRESULT INetAsyncStart(); HRESULT OnINetStart(); HRESULT CINet::OnCookieNotification(DWORD dwStatus, LPVOID pvInfo); virtual HRESULT INetAsyncOpen(); HRESULT OnINetAsyncOpen(DWORD_PTR dwResult); HRESULT OnINetOpen(DWORD dwResult); virtual HRESULT INetAsyncConnect(); HRESULT OnINetConnect(DWORD_PTR dwResult); virtual HRESULT INetAsyncOpenRequest(); HRESULT OnINetOpenRequest(DWORD_PTR dwResult); virtual HRESULT INetAsyncSendRequest(); HRESULT OnINetSendRequest( DWORD dwResult); HRESULT OnINetSuspendSendRequest( DWORD dwResult, LPVOID lpvExtraResult); HRESULT INetResumeAsyncRequest(DWORD dwResultCode); virtual HRESULT INetStateChange(); HRESULT OnINetStateChange(DWORD dwResult); HRESULT INetQueryInfo(); HRESULT INetAuthenticate(); HRESULT OnINetAuthenticate(DWORD dwResult); HRESULT INetDisplayUI(); HRESULT OnINetRead(DWORD_PTR dwResult); HRESULT INetRead(); virtual HRESULT INetWrite(); HRESULT INetDataAvailable(); HRESULT OnINetDataAvailable( DWORD dwResult); HRESULT INetReportAvailableData(); HRESULT OnINetReadDirect(DWORD dwResult); HRESULT INetReadDirect(); HRESULT ReadDirect(BYTE *pBuffer, DWORD cbBytes, DWORD *pcbBytes); HRESULT GetBindResult(CLSID *pclsidProtocol, DWORD *pdwResult, LPWSTR *pszResult,DWORD *pdwReserved); virtual HRESULT SetBindResult(DWORD dwResult, HRESULT hrSuggested = NOERROR); void SetCNetBindResult(DWORD dwResult, LPSTR szResult = NULL) { _dwResult = dwResult; PProtAssert((_pszResult == NULL)); _pszResult = szResult; } BOOL IsApartmentThread() { PProtAssert((_dwThreadID != 0)); return (_dwThreadID == GetCurrentThreadId()); } void TransitState(DWORD dwState, BOOL fAsync = FALSE); void OnINetInternal(DWORD_PTR dwState); HRESULT ReportResultAndStop(HRESULT hr,ULONG ulProgress = 0, ULONG ulProgressMax = 0,LPWSTR pwzStr = 0); HRESULT ReportNotification(BINDSTATUS NMsg, LPCSTR szStr = NULL); HRESULT ReportNotificationW(BINDSTATUS NMsg, LPCWSTR wzStr = NULL); void TerminateRequest(); virtual HRESULT LockFile(BOOL fRetrieve = FALSE); virtual HRESULT UnlockFile(); virtual HRESULT INetSeek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition); HRESULT SetStatePending(HRESULT hrNew); HRESULT GetStatePending(); REFCLSID GetProtocolClassID() { return _pclsidProtocol; } static VOID CALLBACK CINetCallback( IN HINTERNET hInternet, // IN DWORD_PTR dwContext, // could be LPDLD IN DWORD dwInternetStatus, IN LPVOID lpvStatusInformation, IN DWORD dwStatusInformationLength); LPSTR FindTagInHeader(LPCSTR lpBuffer, LPCSTR lpszTag); HRESULT ReadDataHere(BYTE *pBuffer, DWORD cbBytes, DWORD *pcbBytes); HRESULT GetUrlCacheFilename(LPSTR szFilename, DWORD dwSize); BOOL OperationOnAparmentThread(DWORD dwState); HRESULT QueryInfoOnResponse(); HRESULT OnRedirect(LPSTR szNewUrl); HRESULT HResultFromInternetError(DWORD dwStatus); INetState SetINetState(INetState inState); INetState GetINetState(); void SetByteCountReadyToRead(LONG cbReadyReadNow); ULONG GetByteCountReadyToRead(); BOOL UTF8Enabled(); BOOL IsThirdPartyUrl(LPCWSTR pwszUrl); BOOL IsThirdPartyUrl(LPCSTR pszUrl); // If this was not public we get an error from // cnet.cxx line that: // cnet.cxx", line 238: static CINet::operator delete(void*, unsigned) is not accessible from CreateKnownProtocolInstance(unsigned long, const _GUID&, IUnknown*, const _GUID&, IUnknown**). public: void operator delete( void *pBuffer, size_t size) { memset(pBuffer,0, size); ::delete pBuffer; } protected: DWORD IsA() { return _dwIsA; }; virtual HRESULT QueryStatusOnResponse(); virtual HRESULT QueryStatusOnResponseDefault(DWORD dwStat); virtual HRESULT QueryHeaderOnResponse(); virtual HRESULT RedirectRequest(LPSTR lpszBuffer, DWORD *pdwBuffSize, DWORD dwStatus); virtual HRESULT AuthenticationRequest(); //NEW DWORD GetBindFlags() { return _grfBindF; } BINDINFO *GetBindInfo() { return &_BndInfo; } LPWSTR GetUrl() { return _pwzUrl; } LPSTR GetUserAgentString(); BOOL IsUpLoad(); HRESULT QueryService(REFIID riid, void ** ppvObj) { HRESULT hr = E_NOINTERFACE; if (!_pServiceProvider) { hr = _pCTrans->QueryInterface(IID_IServiceProvider, (void **)&_pServiceProvider); } if (_pServiceProvider) { hr = _pServiceProvider->QueryService(riid, riid, ppvObj); } return hr; } STDMETHODIMP_(ULONG) PrivAddRef(BOOL fAddRefHandle = FALSE) { if (fAddRefHandle) { _CRefsHandles++; } return _Unknown.AddRef(); } STDMETHODIMP_(ULONG) PrivRelease(BOOL fReleaseHandle = FALSE) { if (fReleaseHandle) { _CRefsHandles--; } return _Unknown.Release(); } void ReleaseTransAndBindInfo(); }; class CAuthData : public INTERNET_AUTH_NOTIFY_DATA { public: CAuthData(CINet *pCINet) { PProtAssert((pCINet)); cbStruct = sizeof(INTERNET_AUTH_NOTIFY_DATA); dwOptions = 0; pfnNotify = &CINet::InternetAuthNotifyCallback; dwContext = (DWORD_PTR) pCINet; pCINet->AddRef(); } ~CAuthData() { PProtAssert((dwContext)); ((CINet *)dwContext)->Release(); } friend CINet; }; class CStateInfo : public PROTOCOLDATA { public: CStateInfo(DWORD dwSt, DWORD dwFl, LPVOID pD = NULL, DWORD cb = 0) { grfFlags = dwFl; dwState = dwSt; pData = pD; cbData = cb; } ~CStateInfo() { if (pData && cbData) { delete pData; } } private: }; //+--------------------------------------------------------------------------- // // Class: CINetFile () // // Purpose: Simple file protocol // // Interface: CINetFile -- // ~CINetFile -- // INetAsyncOpen -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINetFile : public CINet { public: CINetFile(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINetFile(); virtual HRESULT INetAsyncOpen(); virtual HRESULT LockFile(BOOL fRetrieve = FALSE); virtual HRESULT UnlockFile(); virtual STDMETHODIMP Read(void *pBuffer, DWORD cbBytes, DWORD *pcbBytes); private: LPWSTR GetObjectNameW() { if( _wzFileName[0] == '\0' ) { DWORD dwLen = MAX_PATH; PathCreateFromUrlW(_pwzUrl, _wzFileName, &dwLen, 0); } return _wzFileName; } HANDLE _hFile; // handle to open file for locking the file WCHAR _wzFileName[MAX_PATH]; }; //+--------------------------------------------------------------------------- // // Class: CINetHttp () // // Purpose: Http protocoll class // // Interface: INetAsyncOpenRequest -- // INetAsyncSendRequest -- // QueryStatusOnResponse -- // QueryHeaderOnResponse -- // RedirectRequest -- // GetVerb -- // GetDataToSend -- // GetAdditionalHeader -- // CallHttpNegBeginningTransaction -- // CallHttpNegOnResponse -- // CINetHttp -- // ~CINetHttp -- // _pszHeader -- // _pHttpNeg -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINetHttp : public CINet { public: STDMETHODIMP Terminate(DWORD dwOptions); virtual HRESULT INetAsyncOpenRequest(); virtual HRESULT INetAsyncSendRequest(); virtual HRESULT QueryStatusOnResponse(); virtual HRESULT QueryStatusOnResponseDefault(DWORD dwStat); virtual HRESULT QueryHeaderOnResponse(); virtual HRESULT RedirectRequest(LPSTR lpszBuffer, DWORD *pdwBuffSize, DWORD dwStatus); LPSTR GetVerb(); HRESULT GetDataToSend(LPVOID *ppBuffer, DWORD *pdwSize); HRESULT GetAdditionalHeader(); HRESULT ErrorHandlingRequest(DWORD dwstatus, LPSTR szBuffer); HRESULT HResultFromHttpStatus(DWORD dwStatus); HRESULT HttpSecurity(DWORD dwProblem); HRESULT HttpNegBeginningTransaction(); HRESULT HttpNegOnHeadersAvailable(DWORD dwResponseCode, LPSTR szHeaders); HRESULT HttpNegOnError(DWORD dwResponseCode, LPSTR szResponseHeaders); HRESULT HttpSecurityProblem(HWND* phwnd, DWORD dwProblem); HRESULT ZonesSecurityCheck(HWND hWnd, DWORD dwProblem, DWORD *pdwError); HRESULT HttpNegGetRootSecurityId(); // new definitions for file upload HRESULT INetAsyncSendRequestEx(); virtual HRESULT INetWrite(); HRESULT GetNextSendBuffer(INTERNET_BUFFERS *pIB, IStream *pStm, BOOL fFirst = FALSE); CINetHttp(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINetHttp(); private: LPSTR _pszHeader; LPSTR _pszSendHeader; LPSTR _pwzAddHeader; IHttpNegotiate *_pHttpNeg; // point to HttpNeg holder IHttpSecurity *_pHttSecurity; // Pointer to // file upload stuff char *_pBuffer; //[SENDBUFFER_MAX]; DWORD _dwBufferSize; DWORD _dwBytesSent; IStream *_pStm; // the stream we read from LPSTR _pszVerb; DWORD _dwSendTotalSize; BOOL _fSendEnd : 1; BOOL _f2ndCacheKeySet; IHttpNegotiate2 *_pHttpNeg2; // for GetRootSecurityId ( for cookies fix. ) }; //+--------------------------------------------------------------------------- // // Class: CINetHttpS () // // Purpose: // // Interface: CINetHttpS -- // ~CINetHttpS -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINetHttpS : public CINetHttp { public: // constructor does some special initialization CINetHttpS(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINetHttpS(); private: }; //+--------------------------------------------------------------------------- // // Class: CINetSimple () // // Purpose: Class for simple protocolls such as ftp and gopher // // Interface: INetAsyncOpenRequest -- // INetAsyncSendRequest -- // INetAsyncConnect -- // CINetSimple -- // ~CINetSimple -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINetSimple : public CINet { public: // CINetSimple implements the following methods virtual HRESULT INetAsyncOpenRequest(); virtual HRESULT INetAsyncSendRequest(); virtual HRESULT INetAsyncConnect(); virtual HRESULT QueryStatusOnResponse(); virtual HRESULT QueryStatusOnResponseDefault(DWORD dwStat); virtual HRESULT QueryHeaderOnResponse(); CINetSimple(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINetSimple(); private: }; //+--------------------------------------------------------------------------- // // Class: CINetFtp () // // Purpose: class for ftp // // Interface: CINetFtp -- does all special ftp intialization // ~CINetFtp -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINetFtp : public CINetSimple { public: // constructor does some special initialization CINetFtp(REFCLSID rclsid, IUnknown *pUnkOuter = 0); HRESULT INetAsyncSendRequest(); virtual ~CINetFtp(); private: }; //+--------------------------------------------------------------------------- // // Class: CINetGopher () // // Purpose: // // Interface: CINetGopher -- does all gopher special initialization // ~CINetGopher -- // // History: 2-10-96 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- class CINetGopher : public CINetSimple { public: // constructor does some special initialization CINetGopher(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINetGopher(); private: }; class CINetStream : public CINet { public: CINetStream(REFCLSID rclsid, IUnknown *pUnkOuter = 0); virtual ~CINetStream(); virtual HRESULT INetAsyncOpen(); virtual STDMETHODIMP Read(void *pBuffer, DWORD cbBytes, DWORD *pcbBytes); virtual HRESULT INetSeek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition); virtual HRESULT LockFile(BOOL fRetrieve = FALSE); virtual HRESULT UnlockFile(); private: IStream *_pstm; }; //+--------------------------------------------------------------------------- // // Class: CINetProtImpl() // // Purpose: the implementation of CINet's protocol interface // // Interface: supports OINetProtocol methods. // // History: 11-17-97 DanpoZ(Danpo Zhang) Created // // Notes: 1. this object is ONLY used by CINetEmbdFilter, // the IUnknown interface thus is not implemented // when CINetEmbdFilter get destroied, this object // will be destroied as well. // // 2. All the IOInetProtocol methods gets delegated // to CINet->MyXXXXX() method, where XXXXX are the // names of the IOInetProtocol method // //---------------------------------------------------------------------------- class CINetProtImpl : public IInternetProtocol { public: // IUnknown methods STDMETHODIMP QueryInterface(REFIID iid, void **ppvObj) { return _pCINet->QueryInterface(iid, ppvObj); } STDMETHODIMP_(ULONG) AddRef(void) { return 1; } STDMETHODIMP_(ULONG) Release(void) { return 1; } STDMETHODIMP Start( LPCWSTR, IOInetProtocolSink*, IOInetBindInfo*, DWORD, DWORD_PTR ) { return NOERROR; } STDMETHODIMP Continue(PROTOCOLDATA *pStateInfo) { return _pCINet->MyContinue(pStateInfo); } STDMETHODIMP Abort(HRESULT hrReason,DWORD dwOptions) { return _pCINet->MyAbort(hrReason, dwOptions); } STDMETHODIMP Terminate(DWORD dwOptions) { return _pCINet->MyTerminate(dwOptions); } STDMETHODIMP Suspend() { return _pCINet->MySuspend(); } STDMETHODIMP Resume() { return _pCINet->MyResume(); } STDMETHODIMP Read(void *pv,ULONG cb,ULONG *pcbRead) { return _pCINet->MyRead(pv, cb, pcbRead); } STDMETHODIMP Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) { return _pCINet->MySeek(dlibMove, dwOrigin, plibNewPosition); } STDMETHODIMP LockRequest(DWORD dwOptions) { return _pCINet->MyLockRequest(dwOptions); } STDMETHODIMP UnlockRequest() { return _pCINet->MyUnlockRequest(); } CINetProtImpl(CINet* pCINet) { _pCINet = pCINet; } virtual ~CINetProtImpl() { } void Destroy() { delete this; } friend class CINetEmbdFilter; private: CINet* _pCINet; // Filters' Imp }; //+--------------------------------------------------------------------------- // // Class: CINetEmbdFilter() // // Purpose: Default protocol filter for CINet, all the filter // stacking and chaining are implemented thorugh this // object // // Interface: supports OINetProtocol and OINetProtocolSink methods. // However, this is not a COM object // // History: 11-17-97 DanpoZ(Danpo Zhang) Created // // Notes: // //---------------------------------------------------------------------------- class CINetEmbdFilter { public: CINetEmbdFilter(CINet* pCINet, IOInetProtocolSink* pSnk) { // Construct is called via CINet::Start() _pProtSink = pSnk; // Get Prot, only CINet can generate that _pProt = new CINetProtImpl(pCINet); if(!_pProt) { _bInited = FALSE; return; } _pProtSink->AddRef(); _pProtImp = NULL; _pProtSinkOrig = NULL; // number of filter stacked _cbStacked = 0; _bInited = TRUE; } virtual ~CINetEmbdFilter() { // // dtor is called via CINet::~CINet() // _pProtSink is released on Terminate, otherwise, CTrans // won't be destroyed, thus CINet never get destory // ole style destroy, since delete _pProt won't fire // CINetProtImpl's dtor // if(_pProt) { ((CINetProtImpl*)_pProt)->Destroy(); } _pProt = NULL; _pProtSink = NULL; } BOOL IsInited() { return _bInited; } STDMETHODIMP Continue(PROTOCOLDATA *pStateInfo) { return _pProt->Continue(pStateInfo); } STDMETHODIMP Abort(HRESULT hrReason,DWORD dwOptions) { return _pProt->Abort(hrReason, dwOptions); } STDMETHODIMP Terminate(DWORD dwOptions) { HRESULT hr = NOERROR; hr = _pProt->Terminate(dwOptions); // unload all the filters _pProt->Release(); _pProtSink->Release(); // all filters are gone now // reconnect Imp for the last call (usually UnlockRequest) if( _pProtImp ) { _pProt = _pProtImp; } // we need to release this original pointer (CTrans) if( _pProtSinkOrig ) { _pProtSink = _pProtSinkOrig; _pProtSinkOrig->Release(); } return hr; } 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(); } // // IOInetProtocolSink methods 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); } // Plug in filters // BUG, only support 1, pProt is OK, the logic for pSink needs some // work so that it can be STACKED... // STDMETHODIMP StackFilter( LPCWSTR pwzUrl, IOInetProtocol* pProt, IOInetProtocolSink* pProtSink, IOInetBindInfo* pBindInfo ) { HRESULT hr = E_FAIL; // keep the original prot and sink if( !_pProtImp ) { // // _pProtImp should always be the last pProt on the Prot Chain // we only need to change once // no matter how many times ::StackFilter() gets called. // _pProtImp = _pProt; } // If another filter already stacked, we have to // move the additional ref count on the protocol // interface of that filter if( _pProt != _pProtImp ) { _pProt->Release(); } // the new filter is plugged on top of _pProt and // under _pProtSinkOrig IOInetProtocol* pProtUnder = _pProt; _pProt = pProt; PROTOCOLFILTERDATA FilterData = {sizeof(PROTOCOLFILTERDATA), 0 ,0, 0,0}; FilterData.pProtocolSink = 0; FilterData.pProtocol = 0; FilterData.pUnk = 0; FilterData.dwFilterFlags = 0; FilterData.pProtocol = pProtUnder; // // since we are stacking, so the newly stacked filter should // ALWAYS points to _pProtSinkOrig // hr = _pProt->Start( pwzUrl, _pProtSinkOrig, pBindInfo, PI_FILTER_MODE | PI_FORCE_ASYNC, (DWORD_PTR) &FilterData ); _cbStacked++; return hr; } // // Before SwitchSink get called, the sink of the top filter // is pointing to _pProtSinkOrig // After SwitchSink, the sink of the top filter is pointing // to the sink we just passed in (which is the sink for the new // top level filter) // STDMETHODIMP SwitchSink(IOInetProtocolSink* pProtSink) { HRESULT hr = NOERROR; if( _pProtSinkOrig ) { // _pProt is pointing to the top level filter IOInetProtocolSinkStackable* pSinkStackable = NULL; hr = _pProt->QueryInterface( IID_IOInetProtocolSinkStackable, (void**)&pSinkStackable); if( hr == NOERROR ) { pSinkStackable->SwitchSink(pProtSink); pSinkStackable->Release(); } } else { // // there is no filter existing at this moment // we need toremember the _pProtSinkOrig, which should // always be the LAST sink on the chain // _pProtSinkOrig = _pProtSink; // // switch the existing sink to the filter's sink // the filter's sink will be set via StackFilter // method later // _pProtSink = pProtSink; } return hr; } STDMETHODIMP CommitSwitch() { return NOERROR; } STDMETHODIMP RollbackSwitch() { return NOERROR; } ULONG FilterStacked() { return _cbStacked; } private: IInternetProtocolSink* _pProtSink; // Filter's sink IInternetProtocol* _pProt; // Filter's Prot IInternetProtocolSink* _pProtSinkOrig; // Filter's original sink IInternetProtocol* _pProtImp; // Filter's original Prot ULONG _cbStacked; // number of filter stacked BOOL _bInited; // Constructor succeeded }; // global variables extern char vszHttp[]; extern char vszFtp[]; extern char vszGopher[]; extern char vszFile[]; extern char vszLocal[]; extern char vszHttps[]; extern char vszLocationTag[]; extern LPSTR ppszAcceptTypes[]; extern char vszStream[]; BOOL AppendToString(LPSTR* pszDest, LPDWORD pcbDest, LPDWORD pcbAlloced, LPSTR szSrc, DWORD cbSrc); //LPCSTR GetUserAgentString(); #define HTTP_STATUS_BEGIN HTTP_STATUS_OK #define HTTP_STATUS_END HTTP_STATUS_VERSION_NOT_SUP #endif // _CNET_HXX_