Windows2003-3790/inetsrv/iis/svcs/cmp/asp/response.h
2020-09-30 16:53:55 +02:00

914 lines
28 KiB
C++

/*===================================================================
Microsoft Denali
Microsoft Confidential.
Copyright 1996 Microsoft Corporation. All Rights Reserved.
Component: Response object
File: response.h
Owner: CGrant
This file contains the header info for defining the Response object.
Note: This was largely stolen from Kraig Brocjschmidt's Inside OLE2
second edition, chapter 14 Beeper v5.
===================================================================*/
#ifndef _RESPONSE_H
#define _RESPONSE_H
#include "debug.h"
#include "util.h"
#include "template.h"
#include "disptch2.h"
#include "hashing.h"
#include "memcls.h"
const DWORD RESPONSE_BUFFER_SIZE = 2048;
const DWORD BUFFERS_INCREMENT = 256;
const DWORD ALLOCA_LIMIT = 4096;
const DWORD MAX_RESPONSE = 32768;
const DWORD MAX_MESSAGE_LENGTH = 512;
const DWORD RESPONSE_VECTOR_INTRINSIC_SIZE = 128;
const DWORD RESPONSE_VECTOR_INITIAL_ALLOC = 512;
const DWORD RESPONSE_VECTOR_REALLOC_FACTOR = 2;
// the minimum HTML block that is worth referingin the template rather than copying
// to the response buffer is roughly 6 times the size of a VectorSend element. This is
// because each such reference introduces two vector elements (the reference, and the one
// to the response buffer to follow), and during the system call, 2 additional copies are
// allocated. This evals out 6*24=144 bytes
// BUGBUG: might want to change to save long term mem on the expense of short term allocations
const DWORD MAX_HTML_IN_RESPONSE_BUFFER = 6*sizeof(HSE_VECTOR_ELEMENT);
typedef struct
{
LONG DynamicBlocks;
LONG ZeroSizeBlocks;
LONG TotalCopiedHTMLBytes;
LONG TotalReferencedHTMLBytes;
LONG HTML16;
LONG HTML32;
LONG HTML48;
LONG HTML64;
LONG HTML128;
LONG HTML256;
LONG HTML512;
LONG HTML1024;
LONG HTML2048;
LONG HTML4096;
LONG HTML8192;
LONG HTML16384;
LONG HTMLbig;
LONG Vect8;
LONG Vect16;
LONG Vect32;
LONG Vect64;
LONG Vect96;
LONG Vect128;
LONG Vect192;
LONG Vect256;
LONG Vect512;
LONG Vect1024;
LONG Vect2048;
LONG Vect4096;
LONG VectBig;
} ResponseVectorStatistics;
extern ResponseVectorStatistics sRespVecStats;
class CScriptEngine;
#ifdef USE_LOCALE
extern DWORD g_dwTLS;
#endif
// fixed size allocator for response buffers
ACACHE_FSA_EXTERN(ResponseBuffer)
// forward refs
class CResponse;
class CRequest;
//This file is generated from MKTYPLIB on denali.obj
#include "asptlb.h"
//Type for an object-destroyed callback
typedef void (*PFNDESTROYED)(void);
//Type for the "Get Active Script Engine" callback
typedef CScriptEngine *(*PFNGETSCRIPT)(int iScriptEngine, void *pvContext);
/*
* C H T T P H e a d e r L i n k
*
*/
class CHTTPHeader
{
private:
DWORD m_fInited : 1;
DWORD m_fNameAllocated : 1;
DWORD m_fValueAllocated : 1;
char *m_szName;
char *m_szValue;
DWORD m_cchName;
DWORD m_cchValue;
CHTTPHeader *m_pNext;
char m_rgchLtoaBuffer[20]; // enough for atol
public:
CHTTPHeader();
~CHTTPHeader();
HRESULT InitHeader(BSTR wszName, BSTR wszValue, UINT lCodePage = CP_ACP);
HRESULT InitHeader(char *szName, BSTR wszValue, UINT lCodePage = CP_ACP);
HRESULT InitHeader(char *szName, char *szValue, BOOL fCopyValue);
HRESULT InitHeader(char *szName, long lValue);
char *PSzName();
char *PSzValue();
DWORD CchLength();
void Print(char *szBuf);
void SetNext(CHTTPHeader *pHeader);
CHTTPHeader *PNext();
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
};
// CHTTPHeader inlines
inline char *CHTTPHeader::PSzName()
{
Assert(m_fInited);
return m_szName;
}
inline char *CHTTPHeader::PSzValue()
{
Assert(m_fInited);
return m_szValue;
}
inline DWORD CHTTPHeader::CchLength()
{
Assert(m_fInited);
return (m_cchName + m_cchValue + 4); // account for ": " and "\r\n"
}
inline void CHTTPHeader::SetNext(CHTTPHeader *pHeader)
{
Assert(m_fInited);
Assert(!m_pNext);
m_pNext = pHeader;
}
inline CHTTPHeader *CHTTPHeader::PNext()
{
return m_pNext;
}
/*
* C R e s p o n s e V e c t o r
*
*/
class CResponseVector
{
LPWSABUF m_pExtVector; // Pointer to auxilary vector
DWORD m_cExtVectorSize; // Size of auxilary vector
DWORD m_iCurrentEntry; // Logical index of current entry
BOOL m_fEntryIsOpen:1; // Can we add to current entry?
DWORD m_cchTotalBuffered; // Total of ouput bytes buffered
WSABUF m_aVector0[ RESPONSE_VECTOR_INTRINSIC_SIZE ]; // Pre-allocated vector
HRESULT GrowVector();
BOOL IsEntryOpen();
LPWSABUF GetEntry( UINT i);
DWORD GetEntryCount();
public:
CResponseVector();
~CResponseVector();
VOID Clear();
HRESULT Append( char * pData, DWORD cbSize);
HRESULT Insert( char * pData, DWORD cbSize);
VOID Close();
VOID GetVectors( LPWSABUF_VECTORS pWsabuf);
DWORD BytesBuffered();
};
inline BOOL CResponseVector::IsEntryOpen()
{
return m_fEntryIsOpen;
}
inline LPWSABUF CResponseVector::GetEntry(UINT i)
{
return (i < RESPONSE_VECTOR_INTRINSIC_SIZE) ?
&m_aVector0[i] : m_pExtVector + i - RESPONSE_VECTOR_INTRINSIC_SIZE;
}
inline DWORD CResponseVector::GetEntryCount()
{
return IsEntryOpen() ? m_iCurrentEntry + 1 : m_iCurrentEntry;
}
inline VOID CResponseVector::GetVectors( LPWSABUF_VECTORS pWsabuf)
{
DWORD iEntries = GetEntryCount();
if (iEntries > RESPONSE_VECTOR_INTRINSIC_SIZE)
{
pWsabuf->pVector1 = m_aVector0;
pWsabuf->dwVectorLen1 = RESPONSE_VECTOR_INTRINSIC_SIZE;
pWsabuf->pVector2 = m_pExtVector;
pWsabuf->dwVectorLen2 = iEntries - RESPONSE_VECTOR_INTRINSIC_SIZE;
}
else
{
if (iEntries > 0)
{
pWsabuf->pVector1 = m_aVector0;
pWsabuf->dwVectorLen1 = iEntries;
}
else
{
pWsabuf->pVector1 = NULL;
pWsabuf->dwVectorLen1 = 0;
}
pWsabuf->pVector2 = NULL;
pWsabuf->dwVectorLen2 = 0;
}
}
inline DWORD CResponseVector::BytesBuffered()
{
return m_cchTotalBuffered;
}
// marks the current entry as closed, so that subsequent Append() will create a new entry
inline VOID CResponseVector::Close()
{
if (IsEntryOpen())
{
m_fEntryIsOpen = FALSE;
m_iCurrentEntry++;
}
}
// Create a new entry: close current, append, and close new entry
inline HRESULT CResponseVector::Insert(char * pData, DWORD cbSize)
{
HRESULT hr;
Close();
hr = Append(pData, cbSize);
Close();
return hr;
}
class CResponseBufferSet;
/*
* C R e s p o n s e B u f f e r
*
*/
class CResponseBuffer
{
CResponseBufferSet* m_pBufferSet; // Pointer to BufferSet for this object
CResponseVector m_ResponseVector; // Response vector object
char **m_rgpchBuffers; // Array of pointers to buffers
char *m_pchBuffer0; // In case of 1 element array of pointers
DWORD m_cBufferPointers; // Count of buffer pointers
DWORD m_cBuffers; // Count of buffers we have allocated
DWORD m_iCurrentBuffer; // Array index for the buffer we are currently filling
DWORD m_cchOffsetInCurrentBuffer; // Offset within the current buffer
DWORD m_dwBufferLimit; // max to buffer
BOOL m_fInited; // Initialization status for the object
HRESULT GrowBuffers(DWORD cchNewRequest); // Increase the size of the buffers
public:
CResponseBuffer();
~CResponseBuffer();
HRESULT Init(CResponseBufferSet * pBufferSet, DWORD dwBufferLimit);
char * GetBuffer(UINT i);
DWORD GetBufferSize(UINT i);
DWORD CountOfBuffers();
DWORD BytesBuffered();
CResponseVector * GetResponseVector();
HRESULT Write(char* pszSource, DWORD cch, BOOL fChunkData, BOOL fTemplateData = FALSE);
HRESULT Clear();
VOID SetBufferLimit(DWORD dwBufferLimit);
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
};
inline char * CResponseBuffer::GetBuffer(UINT i)
{
Assert( i < m_cBuffers );
return m_rgpchBuffers[i];
}
inline DWORD CResponseBuffer::GetBufferSize(UINT i)
{
Assert( i < m_cBuffers );
// if buffer is final one, its content-length is current offset
if ( i == (m_cBuffers - 1 ) )
{
return m_cchOffsetInCurrentBuffer;
}
// if buffer is other than final one, its content-length is default buffer size
return RESPONSE_BUFFER_SIZE;
}
inline DWORD CResponseBuffer::CountOfBuffers()
{
return m_cBuffers;
}
inline DWORD CResponseBuffer::BytesBuffered()
{
return m_ResponseVector.BytesBuffered();
}
inline CResponseVector * CResponseBuffer::GetResponseVector()
{
return &m_ResponseVector;
}
inline VOID CResponseBuffer::SetBufferLimit(DWORD dwBufferLimit)
{
m_dwBufferLimit = dwBufferLimit;
}
/*
* C D e b u g R e s p o n s e B u f f e r
*
*/
class CDebugResponseBuffer : public CResponseBuffer
{
private:
HRESULT Write(const char* pszSource);
public:
inline CDebugResponseBuffer() {}
inline ~CDebugResponseBuffer() {}
HRESULT Start();
HRESULT End();
HRESULT InitAndStart(CResponseBufferSet* pBufferSet, DWORD dwBufferLimit);
HRESULT ClearAndStart();
// the only real method
HRESULT AppendRecord
(
const int cchBlockOffset,
const int cchBlockLength,
const int cchSourceOffset,
const char *pszSourceFile = NULL
);
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
};
inline HRESULT CDebugResponseBuffer::Write(const char* pszSource)
{
return CResponseBuffer::Write((char *)pszSource, strlen(pszSource), FALSE);
}
inline HRESULT CDebugResponseBuffer::Start()
{
return Write("<!--METADATA TYPE=\"ASP_DEBUG_INFO\"\r\n");
}
inline HRESULT CDebugResponseBuffer::End()
{
return Write("-->\r\n");
}
inline HRESULT CDebugResponseBuffer::InitAndStart(CResponseBufferSet* pBufferSet,
DWORD dwBufferLimit)
{
HRESULT hr = CResponseBuffer::Init(pBufferSet, dwBufferLimit);
if (SUCCEEDED(hr))
hr = Start();
return hr;
}
inline HRESULT CDebugResponseBuffer::ClearAndStart()
{
HRESULT hr = CResponseBuffer::Clear();
if (SUCCEEDED(hr))
hr = Start();
return hr;
}
/*
* C R e s p o n s e C o o k i e s
*
* Implements the IRequestDictionary interface for writing cookies.
*/
class CResponseCookies : public IRequestDictionaryImpl
{
private:
IUnknown * m_punkOuter; // for addrefs
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
CRequest * m_pRequest; // pointer to request object
CResponse * m_pResponse; // pointer to parent object
public:
CResponseCookies(CResponse *, IUnknown *);
~CResponseCookies();
HRESULT Init()
{
return S_OK;
}
HRESULT ReInit(CRequest *);
// 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);
// C++ interface to write headers
size_t QueryHeaderSize();
char *GetHeaders(char *szBuffer);
};
/*
* C R e s p o n s e B u f f e r S e t
*
* Structure that holds the response buffer and Debug response buffer
*/
class CResponseBufferSet {
private:
CResponseBuffer *m_pResponseBuffer; // Pointer to response buffer object
CDebugResponseBuffer *m_pClientDebugBuffer; // Pointer to response buffer object for client debugging data
CTemplate *m_pTemplate; // Pointer to the template for this request
CTemplate *m_aTemplates[16]; // internal array of templates referenced by this request
CTemplate **m_ppTemplates; // pointer to current array of templates
DWORD m_dwTemplatesRefd; // count of templates in array
DWORD m_dwArraySize; // total slots in array
DWORD m_fCurTemplateInArray : 1; // TRUE if m_pTemplate is in m_aTemplates
DWORD m_fTemplateArrayAllocd : 1; // TRUE if array was allocated
public:
CResponseBufferSet();
~CResponseBufferSet();
HRESULT Init(DWORD dwBufferLimit);
HRESULT InitDebugBuffer(DWORD dwBufferLimit);
HRESULT AddTemplateToArray();
static VOID SendResponseCompletion(CIsapiReqInfo *pIReq,
PVOID pContext,
DWORD cbIO,
DWORD dwError);
// inline helpers
CResponseBuffer *PResponseBuffer() { return m_pResponseBuffer; }
CDebugResponseBuffer *PClientDebugBuffer() { return m_pClientDebugBuffer; }
CTemplate *PTemplate() { return m_pTemplate; }
VOID SetTemplate(CTemplate *pTemplate)
{
m_pTemplate = pTemplate;
m_fCurTemplateInArray = FALSE;
}
VOID SetBufferLimit(DWORD dwBufferLimit) {
m_pResponseBuffer->SetBufferLimit(dwBufferLimit);
if (m_pClientDebugBuffer)
m_pClientDebugBuffer->SetBufferLimit(dwBufferLimit);
}
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
};
/*
* C R e s p o n s e D a t a
*
* Structure that holds the intrinsic's properties.
* The instrinsic keeps pointer to it (NULL when lightweight)
*/
class CResponseData : public IUnknown
{
friend CResponse;
friend CResponseCookies;
friend CResponseBuffer;
private:
// constructor to pass params to members and init members
CResponseData(CResponse *);
~CResponseData();
HRESULT Init();
CSupportErrorInfo m_ISupportErrImp; // Interface to indicate that we support ErrorInfo reporting
CIsapiReqInfo * m_pIReq; // CIsapiReqInfo block for HTTP info
CHitObj* m_pHitObj; // pointer to hitobj for this request
CHTTPHeader* m_pFirstHeader; // List of
CHTTPHeader* m_pLastHeader; // headers
time_t m_tExpires; // date that the HTML output page expires; -1 if no date assigned
const char* m_szCookieVal; // Value of session id
const char* m_pszDefaultContentType;// Default content type (pointer to static string)
const char* m_pszDefaultExpires; // Default expires header value
char* m_pszContentType; // Content type of response (set by user)
char* m_pszCharSet; // CharSet header of response
char* m_pszCacheControl; // cache-control header of response
char* m_pszStatus; // HTTP Status to be returned
BYTE m_dwVersionMajor; // Major version of HTTP supported by client
BYTE m_dwVersionMinor; // Minor version of HTTP supported by client
CResponseBufferSet *m_pBufferSet; // Buffer set for response data
int m_IsHeadRequest; // HEAD request flag 0=uninit, 1=not head, 2=head
PFNGETSCRIPT m_pfnGetScript; // Pointer to callback function for obtaining CActiveEngine pointers
void* m_pvGetScriptContext; // Pointer to data for for callback function for CActiveEngines
CResponseCookies m_WriteCookies; // write-only cookie collection
DWORD m_fResponseAborted : 1; // Was "Response.End" invoked?
DWORD m_fWriteClientError : 1;// Write Client Failed
DWORD m_fIgnoreWrites : 1; // Ignore all writes? (in case of custom error)
DWORD m_fBufferingOn : 1; // Buffer response output
DWORD m_fFlushed : 1; // Has flush been called?
DWORD m_fChunkData : 1; // Doing HTTP 1.1 chunking?
DWORD m_fChunkDataInited : 1; // has m_fChunkData been init'd?
DWORD m_fClientDebugMode : 1; // In client debug mode?
DWORD m_fClientDebugFlushIgnored : 1; // Flush request ignored due to client debug?
ULONG m_cRefs; // ref count
DWORD m_dwBufferLimit; // max to buffer
void AppendHeaderToList(CHTTPHeader *pHeader);
public:
STDMETHODIMP QueryInterface(const GUID &, void **);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
DWORD BytesBuffered();
BOOL FChunkData();
VOID SetBufferLimit(DWORD dwBufferLimit);
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
};
inline DWORD CResponseData::BytesBuffered()
{
DWORD dw = m_pBufferSet->PResponseBuffer()->GetResponseVector()->BytesBuffered();
if (m_pBufferSet->PClientDebugBuffer())
dw += m_pBufferSet->PClientDebugBuffer()->GetResponseVector()->BytesBuffered();
return dw;
}
inline BOOL CResponseData::FChunkData()
{
if (m_fChunkDataInited == FALSE) {
// If using HTTP/1.1 and not buffering add length ofTransfer-Encoding headers
if ((m_dwVersionMinor >= 1) && (m_dwVersionMajor >= 1) &&
(m_fBufferingOn == FALSE) &&
!m_pIReq->IsChild()) { // don't chunk child request output
// UNDONE: Temporary setting to turn off chuncked encoding
if (Glob(fEnableChunkedEncoding))
m_fChunkData = TRUE;
}
m_fChunkDataInited = TRUE;
}
return m_fChunkData;
}
inline VOID CResponseData::SetBufferLimit(DWORD dwBufferLimit)
{
m_dwBufferLimit = dwBufferLimit;
m_pBufferSet->SetBufferLimit(dwBufferLimit);
}
inline void CResponseData::AppendHeaderToList(CHTTPHeader *pHeader)
{
if (!m_pLastHeader)
{
Assert(!m_pFirstHeader);
m_pFirstHeader = pHeader;
}
else
{
Assert(m_pFirstHeader);
m_pLastHeader->SetNext(pHeader);
}
m_pLastHeader = pHeader;
}
class CStaticWriteFileCB {
public:
WSABUF m_wsaBuf;
CStaticWriteFileCB() {
ZeroMemory( &m_wsaBuf, sizeof(WSABUF));
}
~CStaticWriteFileCB() {
if (m_wsaBuf.buf)
CloseHandle((HANDLE)m_wsaBuf.buf);
}
};
/*
* C R e s p o n s e
*
* Implements the Response object
*/
class CResponse : public IResponseImpl, public IStream
{
friend CResponseCookies;
friend CResponseBuffer;
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
CResponseData *m_pData; // pointer to structure that holds
// CResponse properties
// FTM Support
IUnknown *m_pUnkFTM;
VOID GetClientVerison(VOID);
#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:
CResponse(IUnknown *punkOuter = NULL);
~CResponse();
HRESULT CleanUp();
HRESULT Init();
HRESULT UnInit();
HRESULT ReInitTemplate(CTemplate* pTemplate, const char *szCookie);
CTemplate *SwapTemplate(CTemplate* pNewTemplate);
HRESULT ReInit(CIsapiReqInfo *pIReq, const char *szCookie, CRequest *pRequest,
PFNGETSCRIPT pfnGetScript, void *pvGetScriptContext, CHitObj *pHitObj);
static HRESULT ConstructSimpleHeaders(
LPHSE_SEND_HEADER_EX_INFO pHeaderInfo,
DWORD cbTotal,
char *szMimeType,
char *szStatus = NULL,
char *szExtraHeaders = NULL);
HRESULT ConstructHeaders(LPHSE_SEND_HEADER_EX_INFO pHeaderInfo);
HRESULT WriteResponse();
VOID FinalFlush(HRESULT);
HRESULT WriteSz(CHAR *sz, DWORD cch);
HRESULT WriteBSTR(BSTR bstr);
// append headers of different kind
HRESULT AppendHeader(BSTR wszName, BSTR wszValue);
HRESULT AppendHeader(char *szName, BSTR wszValue);
HRESULT AppendHeader(char *szName, char *szValue, BOOL fCopyValue = FALSE);
HRESULT AppendHeader(char *szName, long lValue);
// inlines
inline BOOL FHeadersWritten();
inline BOOL IsHeadRequest(void);
inline BOOL FResponseAborted();
inline BOOL FWriteClientError();
inline BOOL FDontWrite();
inline void SetIgnoreWrites();
inline CIsapiReqInfo* GetIReq();
inline const char* PContentType() const;
inline char *PCustomStatus();
inline void *SwapScriptEngineInfo(void *pvEngineInfo);
//Non-delegating object IUnknown
STDMETHODIMP QueryInterface(REFIID, PPVOID);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// GetIDsOfNames special-case implementation
STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR **, UINT, LCID, DISPID *);
// Tombstone stub
HRESULT CheckForTombstone();
//IResponse functions
STDMETHODIMP Write(VARIANT varInput);
STDMETHODIMP BinaryWrite(VARIANT varInput);
STDMETHODIMP WriteBlock(short iBlockNumber);
STDMETHODIMP Redirect(BSTR bstrURL);
STDMETHODIMP AddHeader(BSTR bstrHeaderName, BSTR bstrHeaderValue);
STDMETHODIMP Pics(BSTR bstrHeaderValue);
STDMETHODIMP Add(BSTR bstrHeaderValue, BSTR bstrHeaderName);
STDMETHODIMP SetCookie(BSTR bstrHeader, BSTR bstrValue, VARIANT varExpires,
VARIANT varDomain, VARIANT varPath, VARIANT varSecure);
STDMETHODIMP Clear(void);
STDMETHODIMP Flush(void);
STDMETHODIMP End(void);
STDMETHODIMP AppendToLog(BSTR bstrLogEntry);
STDMETHODIMP get_ContentType(BSTR *pbstrContentTypeRet);
STDMETHODIMP put_ContentType(BSTR bstrContentType);
STDMETHODIMP get_CharSet(BSTR *pbstrContentTypeRet);
STDMETHODIMP put_CharSet(BSTR bstrContentType);
STDMETHODIMP get_CacheControl(BSTR *pbstrCacheControl);
STDMETHODIMP put_CacheControl(BSTR bstrCacheControl);
STDMETHODIMP get_Status(BSTR *pbstrStatusRet);
STDMETHODIMP put_Status(BSTR bstrStatus);
STDMETHODIMP get_Expires(VARIANT *pvarExpiresMinutesRet);
STDMETHODIMP put_Expires(long lExpiresMinutes);
STDMETHODIMP get_ExpiresAbsolute(VARIANT *pvarTimeRet);
STDMETHODIMP put_ExpiresAbsolute(DATE dtExpires);
STDMETHODIMP get_Buffer(VARIANT_BOOL* fIsBuffering);
STDMETHODIMP put_Buffer(VARIANT_BOOL fIsBuffering);
STDMETHODIMP get_Cookies(IRequestDictionary **ppDictReturn);
STDMETHODIMP IsClientConnected(VARIANT_BOOL* fIsBuffering);
STDMETHODIMP get_CodePage(long *plVar);
STDMETHODIMP put_CodePage(long var);
STDMETHODIMP get_LCID(long *plVar);
STDMETHODIMP put_LCID(long var);
// static method to send the entire block using SyncWriteClient
static HRESULT StaticWrite(CIsapiReqInfo *pIReq,
char *pchBuf,
DWORD cchBuf = 0,
CTemplate *pTemplate = NULL);
// static method to send contents of several memory blocks as the entire response (sync)
static HRESULT WriteBlocksResponse(CIsapiReqInfo *pIReq,
DWORD cBlocks,
LPWSABUF pWsaBuf,
DWORD cbTotal,
char *szMimeType = NULL,
char *szStatus = NULL,
char *szExtraHeaders = NULL);
// static method to send contents of a file as the entire response (sync)
static HRESULT SyncWriteFile(CIsapiReqInfo *pIReq,
TCHAR *szFile,
char *szMimeType = NULL,
char *szStatus = NULL,
char *szExtraHeaders = NULL);
static VOID StaticWriteFileCompletion(CIsapiReqInfo *pIReq,
PVOID pContext,
DWORD cbIO,
DWORD dwError);
// static method to send contents of a scriptless template as the entire response (sync)
static HRESULT WriteScriptlessTemplate(CIsapiReqInfo *pIReq,
CTemplate *pTemplate);
// 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()
};
inline BOOL CResponse::FHeadersWritten()
{
Assert(m_fInited);
Assert(m_pData);
return m_pData->m_pIReq->FHeadersWritten();
}
inline BOOL CResponse::FResponseAborted()
{
Assert(m_fInited);
Assert(m_pData);
return m_pData->m_fResponseAborted;
}
inline BOOL CResponse::FWriteClientError()
{
Assert(m_fInited);
Assert(m_pData);
return m_pData->m_fWriteClientError;
}
inline BOOL CResponse::FDontWrite()
{
Assert(m_fInited);
Assert(m_pData);
return (m_pData->m_fWriteClientError || m_pData->m_fIgnoreWrites);
}
inline void CResponse::SetIgnoreWrites()
{
Assert(m_fInited);
Assert(m_pData);
m_pData->m_fIgnoreWrites = TRUE;
}
inline CIsapiReqInfo* CResponse::GetIReq()
{
Assert(m_fInited);
Assert(m_pData);
return m_pData->m_pIReq;
}
inline const char* CResponse::PContentType() const
{
Assert(m_fInited);
Assert(m_pData);
if (m_pData->m_pszContentType)
return m_pData->m_pszContentType;
else
return m_pData->m_pszDefaultContentType;
}
inline char* CResponse::PCustomStatus()
{
Assert(m_fInited);
Assert(m_pData);
return m_pData->m_pszStatus;
}
inline void *CResponse::SwapScriptEngineInfo(void *pvEngineInfo)
{
Assert(m_fInited);
Assert(m_pData);
void *pvOldEngineInfo = m_pData->m_pvGetScriptContext;
m_pData->m_pvGetScriptContext = pvEngineInfo;
return pvOldEngineInfo;
}
#endif //_RESPONSE_H