Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1297 lines
35 KiB

//+---------------------------------------------------------------------------
//
// 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 <wininet.h>
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_