|
|
/*===================================================================
Microsoft Denali
Microsoft Confidential. Copyright 1996 Microsoft Corporation. All Rights Reserved.
Component: Request object
File: Request.h
Owner: CGrant, DGottner
This file contains the header info for defining the Request object. Note: This was largely stolen from Kraig Brocjschmidt's Inside OLE2 second edition, chapter 14 Beeper v5. ===================================================================*/
#ifndef _Request_H
#define _Request_H
#include "debug.h"
#include "util.h"
#include "hashing.h"
#include "dispatch.h"
#include "strlist.h"
#include "asptlb.h"
#include "response.h"
#include "memcls.h"
#include "ftm.h"
#ifdef USE_LOCALE
extern DWORD g_dwTLS; #endif
class CCookie; class CClCert; class CRequestHit; class CServVarsIterator;
// Type for an object-destroyed callback
typedef void (*PFNDESTROYED)(void);
enum CollectionType {NONE, SERVERVARIABLE, QUERYSTRING, FORM, COOKIE, CLCERT }; enum FormDataStatus {AVAILABLE, BINARYREADONLY, FORMCOLLECTIONONLY, ISTREAMONLY};
class CRequest;
#define NUM_REQUEST_HITS 32
/*
* C R e q u e s t H i t s A r r a y * * Base class for: * CQueryString * CFormInputs * CCookies * CClCerts * * Implements self-reallocating array of CRequestHit */
class CRequestHitsArray { protected: DWORD m_dwCount; // How many Request hits there are
DWORD m_dwHitMax; // Number of slots available to store Request hits
CRequestHit** m_rgRequestHit; // Array of Request hits
CRequestHitsArray(); ~CRequestHitsArray();
inline HRESULT Init() { m_dwCount = 0; m_dwHitMax = 0; m_rgRequestHit = NULL; return S_OK; } inline HRESULT ReInit() { m_dwCount = 0; return S_OK; }
public: BOOL AddRequestHit(CRequestHit *pHit); };
/*
* C Q u e r y S t r i n g * * Implements the QueryString object (interface derived from IRequestDictionary) */
class CQueryString : public IRequestDictionaryImpl, public CRequestHitsArray { private: IUnknown * m_punkOuter; // object to do ref count
CRequest * m_pRequest; // pointer to parent object
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
public: CQueryString(CRequest *, IUnknown *);
// The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// OLE Automation Interface
STDMETHODIMP get_Item(VARIANT varKey, VARIANT *pvarReturn); STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn); STDMETHODIMP get_Count(int *pcValues); STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar);
HRESULT Init(); HRESULT ReInit();
~CQueryString(); };
/*
* C S e r v e r V a r i a b l e s * * Implements the ServerVariables object (interface derived from IRequestDictionary) */
class CServerVariables : public IRequestDictionaryImpl { private: IUnknown * m_punkOuter; // object to do ref count
CRequest * m_pRequest; // pointer to parent object
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
CServVarsIterator * m_pIterator; // we use an iterator to support integer index
public: CServerVariables(CRequest *, IUnknown *); HRESULT Init() { return S_OK; }
// The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// OLE Automation Interface
STDMETHODIMP get_Item(VARIANT Var, VARIANT *pVariantReturn); STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn); STDMETHODIMP get_Count(int *pcValues); STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar);
// We've added a destructor, but didn't want to change the
// order of the existing vtbl entries.
~CServerVariables(); };
/*
* C F o r m I n p u t s * * Implements the Form object (interface derived from IRequestDictionary) */
class CFormInputs : public IRequestDictionaryImpl, public CRequestHitsArray { private: IUnknown * m_punkOuter; // object to do ref count
CRequest * m_pRequest; // pointer to parent object
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
public: CFormInputs(CRequest *, IUnknown *); HRESULT Init(); HRESULT ReInit();
// The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// OLE Automation Interface
STDMETHODIMP get_Item(VARIANT Var, VARIANT *pVariantReturn); STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn); STDMETHODIMP get_Count(int *pcValues); STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar);
~CFormInputs(); };
/*
* C C o o k i e s * * Implements the Cookies object (interface derived from IRequestDictionary) */
class CCookies : public IRequestDictionaryImpl, public CRequestHitsArray { friend CResponseCookies; private: IUnknown * m_punkOuter; // object to do ref count
CRequest * m_pRequest; // pointer to parent object
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
CCookie * m_pEmptyCookie; // for when the cookie is not there
public: CCookies(CRequest *, IUnknown *); ~CCookies(); HRESULT Init(); HRESULT ReInit(); // The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// OLE Automation Interface
STDMETHODIMP get_Item(VARIANT Var, VARIANT *pVariantReturn); STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn); STDMETHODIMP get_Count(int *pcValues); STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar); };
/*
* C C l C e r t s * * Implements the ClCerts object (interface derived from IRequestDictionary) */
class CClCerts : public IRequestDictionaryImpl, public CRequestHitsArray { private: IUnknown * m_punkOuter; // object to do ref count
CRequest * m_pRequest; // pointer to parent object
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
CClCert * m_pEmptyClCert; // for when the clcert is not there
public: CClCerts(CRequest *, IUnknown *); ~CClCerts(); HRESULT Init(); HRESULT ReInit(); // The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// OLE Automation Interface
STDMETHODIMP get_Item(VARIANT Var, VARIANT *pVariantReturn); STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn); STDMETHODIMP get_Count(int *pcValues); STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar); };
/*
* C R e q u e s t H i t * * Implements the RequestHit object */
class CRequestHit : private CLinkElem { friend class CRequest; friend class CRequestData; friend class CQueryString; friend class CFormInputs; friend class CCookies; friend class CClCerts; friend class CCertRequest; friend class CResponseCookies; friend class CRequestIterator;
private: BOOL m_fInited:1; BOOL m_fDuplicate:1; CStringList *m_pQueryData, *m_pFormData; CCookie *m_pCookieData; CClCert *m_pClCertData;
public: CRequestHit(); ~CRequestHit();
HRESULT Init(char *szName, BOOL fDuplicate = FALSE); HRESULT AddValue(CollectionType source, char *szValue, CIsapiReqInfo *, UINT lCodePage); HRESULT AddCertValue(VARENUM ve, LPBYTE pValue, UINT cLen ); HRESULT AddKeyAndValue(CollectionType source, char *szKey, char *szValue, CIsapiReqInfo *, UINT lCodePage);
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS() };
/*
* C R e q u e s t D a t a * * Structure that holds the intrinsic's properties. * The instrinsic keeps pointer to it (NULL when lightweight) */ class CRequestData : public IUnknown { friend class CRequest; friend class CResponse; friend class CQueryString; friend class CServerVariables; friend class CFormInputs; friend class CCookies; friend class CClCerts; friend class CResponseCookies; friend class CRequestIterator; friend class CCertRequest;
private: // constructor to pass params to members and init members
CRequestData(CRequest *pRequest); ~CRequestData();
HRESULT Init(); HRESULT ReInit(CIsapiReqInfo *pIReq, CHitObj *pHitObj);
HRESULT GetEmptyStringList(IDispatch **ppdisp); CSupportErrorInfo m_ISupportErrImp; // Implementation of ISupportErrorInfo for this object
CIsapiReqInfo * m_pIReq; // CIsapiReqInfo block for HTTP info
CHitObj * m_pHitObj; // pointer to hitobj for this request
CHashTableMBStr m_mpszStrings; // map sz's to string lists
BOOL m_fLoadForm:1; // do we need to load the body?
BOOL m_fLoadQuery:1; // do we need to load QueryString?
BOOL m_fLoadCookies:1; // do we need to load Cookies?
BOOL m_fLoadClCerts:1; // do we need to load ClCerts?
FormDataStatus m_FormDataStatus; // Is form data available for BinaryRead or Form Collection?
BYTE * m_pbAvailableData; // pointer to available data in CIsapiReqInfo
size_t m_cbAvailable; // number of bytes available in CIsapiReqInfo
size_t m_cbTotal; // Total number of bytes remaining in request
char * m_szFormData; // pointer to form data (allocted or CIsapiReqInfo)
size_t m_cbFormData; // number of bytes allocated for form data
char * m_szFormClone; // clone of form data (LoadVariables clobbers)
char * m_szCookie; // clone of cookie data (this one gets trashed)
size_t m_cbCookie; // number of bytes allocated for the cookie data
char * m_szClCert; // clone of clcert data (this one gets trashed)
size_t m_cbClCert; // number of bytes allocated for the clcert data
CStringList * m_pEmptyString; // all empty results share the same object
CQueryString m_QueryString; // pointer to the "QueryString" object
CServerVariables m_ServerVariables; // pointer to the "ServerVariables" object
CFormInputs m_FormInputs; // pointer to the "Form" object
CCookies m_Cookies; // pointer to the "Cookies" object
CClCerts m_ClCerts; // pointer to the "ClCert" object
ULONG m_cRefs; // ref count
public: STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS() };
/*
* C R e q u e s t * * Implements the Request object */ class CRequest : public IRequestImpl, public CFTMImplementation, public IStream { friend class CQueryString; friend class CServerVariables; friend class CFormInputs; friend class CCookies; friend class CClCerts; friend class CResponseCookies; friend class CRequestIterator; friend class CCertRequest;
private: // Flags
DWORD m_fInited : 1; // Is initialized?
DWORD m_fDiagnostics : 1; // Display ref count in debug output
DWORD m_fOuterUnknown : 1; // Ref count outer unknown?
// Ref count / Outer unknown
union { DWORD m_cRefs; IUnknown *m_punkOuter; };
// Properties
CRequestData *m_pData; // pointer to structure that holds
// CRequest properties
UINT GetCodePage();
HRESULT LoadVariables(CollectionType Source, char *szURL, UINT lCodePage); HRESULT LoadCookies(char *szCookies); HRESULT LoadClCerts(char *szClCerts, UINT lCodePage);
HRESULT LoadCertList( LPSTR pszPrefix, LPSTR* pszCertList); HRESULT CopyClientData(); HRESULT GetRequestEnumerator(CollectionType, IUnknown **ppEnumReturn);
// Added support for chunked Transfer in Request.form
HRESULT CopyChunkedClientData(); HRESULT CopyNonChunkedClientData();
#ifdef DBG
inline void TurnDiagsOn() { m_fDiagnostics = TRUE; } inline void TurnDiagsOff() { m_fDiagnostics = FALSE; } void AssertValid() const; #else
inline void TurnDiagsOn() {} inline void TurnDiagsOff() {} inline void AssertValid() const {} #endif
public: CRequest(IUnknown *punkOuter = NULL); ~CRequest();
HRESULT CleanUp(); HRESULT Init(); HRESULT UnInit(); HRESULT ReInit(CIsapiReqInfo *pIReq, CHitObj *pHitObj); inline CIsapiReqInfo *GetIReq() { Assert(m_fInited); Assert(m_pData); return m_pData->m_pIReq; } inline CLinkElem* CertStoreFindElem(LPSTR pV, int cV) { Assert(m_fInited); Assert(m_pData); return m_pData->m_mpszStrings.FindElem( pV, cV ); } inline CLinkElem* CertStoreAddElem(CLinkElem* pH) { Assert(m_fInited); Assert(m_pData); return m_pData->m_mpszStrings.AddElem( pH ); } inline LPSTR GetCertStoreBuf() { Assert(m_fInited); Assert(m_pData); return m_pData->m_szClCert; } inline size_t GetCertStoreSize() { Assert(m_fInited); Assert(m_pData); return m_pData->m_cbClCert; } inline void SetCertStore(LPSTR p, size_t s) { Assert(m_fInited); Assert(m_pData); m_pData->m_szClCert = p; m_pData->m_cbClCert = s; }
inline CHashTable *GetStrings() { Assert(m_fInited); Assert(m_pData); return &(m_pData->m_mpszStrings); }
// Non-delegating object IUnknown
//
STDMETHODIMP QueryInterface(const IID &Iid, void **ppvObj); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// Tombstone stub
HRESULT CheckForTombstone(); // IRequest functions
//
STDMETHODIMP get_Item(BSTR bstrVar, IDispatch **ppDispReturn); STDMETHODIMP get_QueryString(IRequestDictionary **ppDictReturn); STDMETHODIMP get_Form(IRequestDictionary **ppDictReturn); STDMETHODIMP get_Body(IRequestDictionary **ppDictReturn); STDMETHODIMP get_ServerVariables(IRequestDictionary **ppDictReturn); STDMETHODIMP get_ClientCertificate(IRequestDictionary **ppDictReturn); STDMETHODIMP get_Cookies(IRequestDictionary **ppDictReturn); STDMETHODIMP get_TotalBytes(long *pcbTotal); STDMETHODIMP BinaryRead(VARIANT *pvarCount, VARIANT *pvarReturn);
// IStream implementation
STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead); STDMETHODIMP Write(const void *pv, ULONG cb, ULONG *pcbWritten); STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize); STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); STDMETHODIMP Commit(DWORD grfCommitFlags); STDMETHODIMP Revert(); STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag); STDMETHODIMP Clone(IStream **ppstm);
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS() };
/*===================================================================
ITERATORS:
There are two iterators used for Request - a general purpose iterator which will iterate through the keys of Cookies, QueryString, Form. A special iterator is used for ServerVariables ===================================================================*/
/*
* C S e r v V a r s I t e r a t o r * * IEnumVariant implementation for Request.ServerVariables */
class CServVarsIterator : public IEnumVARIANT { friend CServerVariables; public: CServVarsIterator(); ~CServVarsIterator();
HRESULT Init(CIsapiReqInfo *pIReq);
// The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// standard methods for iterators
STDMETHODIMP Clone(IEnumVARIANT **ppEnumReturn); STDMETHODIMP Next(unsigned long cElements, VARIANT *rgVariant, unsigned long *pcElementsFetched); STDMETHODIMP Skip(unsigned long cElements); STDMETHODIMP Reset();
private: ULONG m_cRefs; // reference count
wchar_t **m_rgwszKeys; // array of ISAPI keys
wchar_t **m_pwszKey; // current key in gm_rgwszKeys
wchar_t *m_pwchAllHttp; // extra keys in ALL_HTTP server variable
ULONG m_cKeys; // total number of keys
BOOL CreateKeys(wchar_t *pwchKeys, int *pcwchAlloc, int *pcRequestHeaders); };
/*
* C R e q u e s t I t e r a t o r * * IEnumVariant implementation for all Request collections except * ServerVariables */
class CRequestIterator : public IEnumVARIANT { public: CRequestIterator(CRequest *, CollectionType); ~CRequestIterator();
HRESULT Init();
// The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// standard methods for iterators
STDMETHODIMP Clone(IEnumVARIANT **ppEnumReturn); STDMETHODIMP Next(unsigned long cElements, VARIANT *rgVariant, unsigned long *pcElementsFetched); STDMETHODIMP Skip(unsigned long cElements); STDMETHODIMP Reset();
private: ULONG m_cRefs; // reference count
CollectionType m_Collection; // which collection to iterate over?
CRequest *m_pRequest; // pointer to the request object
CRequestHit *m_pRequestHit; // current bookmark for iteration
};
BOOL RequestSupportInit(); VOID RequestSupportTerminate();
#endif //_Request_H
|