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.
 
 
 
 
 
 

501 lines
16 KiB

/*
* HttpRequest.hxx
*
* WinHttp HttpRequest COM component
*
* Copyright (C) 2000 Microsoft Corporation. All rights reserved. *
*
*
*/
#ifndef _HTTPREQUEST_HXX_
#define _HTTPREQUEST_HXX_
#include <httprequest.h>
#include <httprequestid.h>
#include <ocidl.h>
typedef INTERNETAPI WINHTTP_STATUS_CALLBACK InternetSetStatusCallbackFunc(
IN HINTERNET hInternet,
IN WINHTTP_STATUS_CALLBACK lpfnInternetCallback
);
#define WINHTTP_DEFAULT_USER_AGENT L"Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)"
/////////////////////////////////////////////////////////////////////////////
// CClassFactory for CHttpRequest
class CClassFactory : public IClassFactory
{
public:
//---------------------------------------------------------------
// IUnknown methods.
//---------------------------------------------------------------
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
//---------------------------------------------------------------
// IClassFactory methods.
//---------------------------------------------------------------
STDMETHOD(CreateInstance)(IUnknown * pUnkOuter, REFIID riid, void ** ppv);
STDMETHOD(LockServer)(BOOL fLock);
CClassFactory();
private:
long _cRefs;
};
/////////////////////////////////////////////////////////////////////////////
// CSinkArray
class CSinkArray : public IWinHttpRequestEvents
{
public:
CSinkArray()
{
_nSize = 0;
_ppUnk = NULL;
}
~CSinkArray()
{
if (_nSize > 1)
FREE_FIXED_MEMORY(_ppUnk);
}
DWORD Add(IUnknown* pUnk);
BOOL Remove(DWORD dwCookie);
void ReleaseAll();
IUnknown * GetUnknown(DWORD dwCookie)
{
ULONG iIndex;
if (dwCookie == 0)
return NULL;
iIndex = dwCookie-1;
return begin()[iIndex];
}
IUnknown ** begin()
{
return (_nSize < 2) ? &_pUnk : _ppUnk;
}
IUnknown ** end()
{
return (_nSize < 2) ? (&_pUnk)+_nSize : &_ppUnk[_nSize];
}
//---------------------------------------------------------------
// IUnknown methods.
//---------------------------------------------------------------
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
//---------------------------------------------------------------
// IWinHttpRequestEvents
//---------------------------------------------------------------
// These could fail when out of memory
STDMETHOD_(void, OnResponseStart)(long Status, BSTR ContentType);
STDMETHOD_(void, OnResponseDataAvailable)(SAFEARRAY ** Data);
STDMETHOD_(void, OnResponseFinished)();
STDMETHOD_(void, OnError)(long ErrorNumber, BSTR ErrorDescription);
protected:
union
{
IUnknown ** _ppUnk;
IUnknown * _pUnk;
};
int _nSize;
};
#define _DEFAULT_VECTORLENGTH 4
/////////////////////////////////////////////////////////////////////////////
// CWinHttpRequestEventsMarshaller
class CWinHttpRequestEventsMarshaller : public IWinHttpRequestEvents
{
CSinkArray * _pSinkArray;
HWND _hWnd;
long _cRefs;
bool _bFireEvents;
CCritSec _cs;
public:
CWinHttpRequestEventsMarshaller(CSinkArray * pSinkArray, HWND hWnd);
~CWinHttpRequestEventsMarshaller();
//---------------------------------------------------------------
// IUnknown methods.
//---------------------------------------------------------------
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
//---------------------------------------------------------------
// IWinHttpRequestEvents
//---------------------------------------------------------------
STDMETHOD_(void, OnResponseStart)(long Status, BSTR bstrContentType);
STDMETHOD_(void, OnResponseDataAvailable)(SAFEARRAY ** Data);
STDMETHOD_(void, OnResponseFinished)();
STDMETHOD_(void, OnError)(long ErrorNumber, BSTR ErrorDescription);
CSinkArray * GetSinkArray() const
{
return _pSinkArray;
}
static HRESULT Create(CSinkArray * pSinkArray,
CWinHttpRequestEventsMarshaller ** ppSinkMarshaller);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void Shutdown();
void FreezeEvents()
{
_bFireEvents = false;
}
void UnfreezeEvents()
{
_bFireEvents = true;
}
bool OkToFireEvents() const
{
return _bFireEvents;
}
};
#define WHREM_MSG_ON_RESPONSE_START (WM_USER + 1)
#define WHREM_MSG_ON_RESPONSE_DATA_AVAILABLE (WM_USER + 2)
#define WHREM_MSG_ON_RESPONSE_FINISHED (WM_USER + 3)
#define WHREM_MSG_ON_ERROR (WM_USER + 4)
/////////////////////////////////////////////////////////////////////////////
// CHttpRequest
class CHttpRequest : public IWinHttpRequest,
public ISupportErrorInfo,
public IProvideClassInfo2,
public IConnectionPointContainer
{
public:
CHttpRequest();
~CHttpRequest();
#if !defined(TRUE_ASYNC)
DWORD SendAsync();
#endif//!TRUE_ASYNC
inline LPCWSTR GetUserAgentString() const
{
return (_bstrUserAgent != NULL) ?
_bstrUserAgent :
WINHTTP_DEFAULT_USER_AGENT;
}
//---------------------------------------------------------------
// IUnknown methods.
//---------------------------------------------------------------
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
//---------------------------------------------------------------
// IDispatch methods.
//---------------------------------------------------------------
STDMETHOD(GetTypeInfoCount)(UINT * pctinfo);
STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo ** ppTInfo);
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR * rgszNames,
UINT cNames,
LCID lcid,
DISPID * rgDispId);
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags,
DISPPARAMS * pDispParams,
VARIANT * pVarResult,
EXCEPINFO * pExcepInfo,
UINT * puArgErr);
//---------------------------------------------------------------
// IWinHttpRequest methods.
//---------------------------------------------------------------
STDMETHOD(SetProxy)(HTTPREQUEST_PROXY_SETTING ProxySetting,
VARIANT varProxyServer,
VARIANT varBypassList);
STDMETHOD(SetCredentials)(BSTR bstrUserName,
BSTR bstrPassword,
HTTPREQUEST_SETCREDENTIALS_FLAGS Flags);
STDMETHOD(Open)(BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync);
STDMETHOD(SetRequestHeader)(BSTR bstrHeader, BSTR bstrValue);
STDMETHOD(GetResponseHeader)(BSTR bstrHeader, BSTR * pbstrValue);
STDMETHOD(GetAllResponseHeaders)(BSTR * pbstrHeaders);
STDMETHOD(Send)(VARIANT varBody);
STDMETHOD(get_Status)(long * plStatus);
STDMETHOD(get_StatusText)(BSTR * pbstrStatus);
STDMETHOD(get_ResponseText)(BSTR * pbstrBody);
STDMETHOD(get_ResponseBody)(VARIANT * pvarBody);
STDMETHOD(get_ResponseStream)(VARIANT * pvarBody);
STDMETHOD(get_Option)(WinHttpRequestOption Option, VARIANT * Value);
STDMETHOD(put_Option)(WinHttpRequestOption Option, VARIANT Value);
STDMETHOD(WaitForResponse)(VARIANT Timeout, VARIANT_BOOL * pboolSucceeded);
STDMETHOD(Abort)();
STDMETHOD(SetTimeouts)(long ResolveTimeout, long ConnectTimeout, long SendTimeout, long ReceiveTimeout);
STDMETHOD(SetClientCertificate)(BSTR ClientCertificate);
STDMETHOD(SetAutoLogonPolicy)(WinHttpRequestAutoLogonPolicy AutoLogonPolicy);
//---------------------------------------------------------------
// ISupportErrorInfo methods.
//---------------------------------------------------------------
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
//---------------------------------------------------------------
// IProvideClassInfo methods.
//---------------------------------------------------------------
STDMETHOD(GetClassInfo)(ITypeInfo ** ppTI);
//---------------------------------------------------------------
// IProvideClassInfo2 methods.
//---------------------------------------------------------------
STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID * pGUID);
//---------------------------------------------------------------
// IConnectionPointContainer methods.
//---------------------------------------------------------------
STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints ** ppEnum);
STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint ** ppCP);
class CHttpRequestEventsCP : public IConnectionPoint
{
public:
CSinkArray _SinkArray;
CWinHttpRequestEventsMarshaller * _pSinkMarshaller;
DWORD _cConnections;
BOOL _bOnErrorDisabled;
//---------------------------------------------------------------
// IUnknown methods.
//---------------------------------------------------------------
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject);
STDMETHOD_(ULONG, AddRef)();
STDMETHOD_(ULONG, Release)();
//---------------------------------------------------------------
// IConnectionPoint methods.
//---------------------------------------------------------------
STDMETHOD(GetConnectionInterface)(IID * pIID);
STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer ** ppCPC);
STDMETHOD(Advise)(IUnknown * pUnk, DWORD * pdwCookie);
STDMETHOD(Unadvise)(DWORD dwCookie);
STDMETHOD(EnumConnections)(IEnumConnections **);
inline CHttpRequest * Px() const
{
return (CHttpRequest *)((BYTE *)this - offsetof(CHttpRequest, _CP));
}
void FireOnResponseStart(long Status, BSTR ContentType);
void FireOnResponseDataAvailable(const BYTE * rgbData, DWORD cbData);
void FireOnResponseFinished();
void FireOnError(HRESULT hr);
CHttpRequestEventsCP()
{
_cConnections = 0;
_pSinkMarshaller = NULL;
_bOnErrorDisabled = FALSE;
}
~CHttpRequestEventsCP();
inline IWinHttpRequestEvents * GetSink()
{
return (_pSinkMarshaller == NULL) ?
static_cast<IWinHttpRequestEvents *>(&_SinkArray)
: static_cast<IWinHttpRequestEvents *>(_pSinkMarshaller);
}
inline void DisableOnError() { _bOnErrorDisabled = TRUE; }
HRESULT CreateEventSinksMarshaller();
void ShutdownEventSinksMarshaller();
void ReleaseEventSinksMarshaller();
void FreezeEvents();
void UnfreezeEvents();
};
friend class CHttpRequestEventsCP;
private:
enum State
{
CREATED = 0,
OPENED = 1,
SENDING = 2,
SENT = 3,
RECEIVING = 4,
RESPONSE = 5
};
long _cRefs;
IUnknown * _pUnkSite;
ITypeInfo * _pTypeInfo;
BSTR _bstrUserAgent;
DWORD _dwProxySetting;
BSTR _bstrProxyServer;
BSTR _bstrBypassList;
State _eState;
HINTERNET _hInet;
HINTERNET _hConnection;
HINTERNET _hHTTP;
DWORD _ResolveTimeout;
DWORD _ConnectTimeout;
DWORD _SendTimeout;
DWORD _ReceiveTimeout;
BOOL _fAsync;
#ifdef TRUE_ASYNC
DWORD _dwNumberOfBytesAvailable;
DWORD _cbNumberOfBytesRead;
HANDLE _hCompleteEvent;
BOOL _bRetriedWithCert;
DWORD _dwContentLength;
BYTE * _Buffer;
#else
HANDLE _hWorkerThread;
#endif
DWORD _cRefsOnMainThread;
DWORD _dwMainThreadId;
HRESULT _hrAsyncResult;
void * _hAbortedConnectObject;
void * _hAbortedRequestObject;
bool _bAborted;
bool _bSetTimeouts;
bool _bSetUtf8Charset;
DWORD _dwCodePage;
DWORD _dwEscapeFlag;
DWORD _cbRequestBody;
char * _szRequestBuffer;
DWORD _cbResponseBody;
IStream * _pResponseStream;
BOOL _fCheckForRevocation;
DWORD _dwSslIgnoreFlags;
BOOL _fCertLocalMachine;
BSTR _bstrCertStore;
BSTR _bstrCertSubject;
DWORD _dwSecureProtocols;
HRESULT _hrSecureFailure;
BOOL _bEnableSslImpersonation;
BOOL _bMethodGET;
BOOL _bHttp1_1Mode;
DWORD _dwAutoLogonPolicy;
DWORD _dwRedirectPolicy;
LONG _lMaxAutomaticRedirects;
LONG _lMaxResponseHeaderSize;
LONG _lMaxResponseDrainSize;
DWORD _dwPassportConfig;
CHttpRequestEventsCP _CP;
void Initialize();
void ReleaseResources();
void Recycle();
void Reset();
HRESULT GetHttpRequestTypeInfo(REFGUID guid, ITypeInfo ** ppTypeInfo);
HRESULT ReadResponse();
HRESULT SetRequiredRequestHeaders();
HRESULT SetRequestBody(VARIANT varBody);
void SetState(State state);
HRESULT CreateStreamOnResponse(IStream ** ppStm);
#if !defined(TRUE_ASYNC)
HRESULT _GetResponseHeader(OLECHAR * wszHeader, BSTR * pbstrValue);
HRESULT CreateAsyncWorkerThread();
#else
HRESULT _GetResponseHeader(OLECHAR * wszHeader, BSTR * pbstrValue);
static HRESULT _GetResponseHeader2(OLECHAR * wszHeader, BSTR * pbstrValue, HINTERNET hInternet);
#endif//!TRUE_ASYNC
static IErrorInfo * CreateErrorObject(HRESULT hr);
static void SetErrorInfo(HRESULT hr);
BOOL SelectCertificate();
#ifdef TRUE_ASYNC
HRESULT StartAsyncSend();
HRESULT PrepareToReadData(HINTERNET);
void CompleteDataRead(bool bNotAborted, HINTERNET);
static void CALLBACK AsyncCallback(HINTERNET hInternet,
DWORD_PTR dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength);
#endif//TRUE_ASYNC
static void CALLBACK SyncCallback(HINTERNET hInternet,
DWORD_PTR dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength);
};
/////////////////////////////////////////////////////////////////////////////
// function prototypes
STDMETHODIMP
CreateHttpRequest(REFIID riid, void ** ppvObject);
#ifdef WINHTTP_STATIC_LIBRARY
STDAPI WinHttpCreateHttpRequestComponent(REFIID riid, void ** ppvObject);
#endif
BOOLAPI WinHttpCheckPlatform(void);
BOOL RegisterWinHttpEventMarshallerWndClass();
void CleanupWinHttpRequestGlobals();
#endif //_HTTPREQUEST_HXX_