windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/cmp/asp51/request.h
2020-09-26 16:20:57 +08:00

627 lines
17 KiB
C++

/*===================================================================
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