1298 lines
34 KiB
C++
1298 lines
34 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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_
|
|
|
|
|