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.

913 lines
28 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Response object
  6. File: response.h
  7. Owner: CGrant
  8. This file contains the header info for defining the Response object.
  9. Note: This was largely stolen from Kraig Brocjschmidt's Inside OLE2
  10. second edition, chapter 14 Beeper v5.
  11. ===================================================================*/
  12. #ifndef _RESPONSE_H
  13. #define _RESPONSE_H
  14. #include "debug.h"
  15. #include "util.h"
  16. #include "template.h"
  17. #include "disptch2.h"
  18. #include "hashing.h"
  19. #include "memcls.h"
  20. const DWORD RESPONSE_BUFFER_SIZE = 2048;
  21. const DWORD BUFFERS_INCREMENT = 256;
  22. const DWORD ALLOCA_LIMIT = 4096;
  23. const DWORD MAX_RESPONSE = 32768;
  24. const DWORD MAX_MESSAGE_LENGTH = 512;
  25. const DWORD RESPONSE_VECTOR_INTRINSIC_SIZE = 128;
  26. const DWORD RESPONSE_VECTOR_INITIAL_ALLOC = 512;
  27. const DWORD RESPONSE_VECTOR_REALLOC_FACTOR = 2;
  28. // the minimum HTML block that is worth referingin the template rather than copying
  29. // to the response buffer is roughly 6 times the size of a VectorSend element. This is
  30. // because each such reference introduces two vector elements (the reference, and the one
  31. // to the response buffer to follow), and during the system call, 2 additional copies are
  32. // allocated. This evals out 6*24=144 bytes
  33. // BUGBUG: might want to change to save long term mem on the expense of short term allocations
  34. const DWORD MAX_HTML_IN_RESPONSE_BUFFER = 6*sizeof(HSE_VECTOR_ELEMENT);
  35. typedef struct
  36. {
  37. LONG DynamicBlocks;
  38. LONG ZeroSizeBlocks;
  39. LONG TotalCopiedHTMLBytes;
  40. LONG TotalReferencedHTMLBytes;
  41. LONG HTML16;
  42. LONG HTML32;
  43. LONG HTML48;
  44. LONG HTML64;
  45. LONG HTML128;
  46. LONG HTML256;
  47. LONG HTML512;
  48. LONG HTML1024;
  49. LONG HTML2048;
  50. LONG HTML4096;
  51. LONG HTML8192;
  52. LONG HTML16384;
  53. LONG HTMLbig;
  54. LONG Vect8;
  55. LONG Vect16;
  56. LONG Vect32;
  57. LONG Vect64;
  58. LONG Vect96;
  59. LONG Vect128;
  60. LONG Vect192;
  61. LONG Vect256;
  62. LONG Vect512;
  63. LONG Vect1024;
  64. LONG Vect2048;
  65. LONG Vect4096;
  66. LONG VectBig;
  67. } ResponseVectorStatistics;
  68. extern ResponseVectorStatistics sRespVecStats;
  69. class CScriptEngine;
  70. #ifdef USE_LOCALE
  71. extern DWORD g_dwTLS;
  72. #endif
  73. // fixed size allocator for response buffers
  74. ACACHE_FSA_EXTERN(ResponseBuffer)
  75. // forward refs
  76. class CResponse;
  77. class CRequest;
  78. //This file is generated from MKTYPLIB on denali.obj
  79. #include "asptlb.h"
  80. //Type for an object-destroyed callback
  81. typedef void (*PFNDESTROYED)(void);
  82. //Type for the "Get Active Script Engine" callback
  83. typedef CScriptEngine *(*PFNGETSCRIPT)(int iScriptEngine, void *pvContext);
  84. /*
  85. * C H T T P H e a d e r L i n k
  86. *
  87. */
  88. class CHTTPHeader
  89. {
  90. private:
  91. DWORD m_fInited : 1;
  92. DWORD m_fNameAllocated : 1;
  93. DWORD m_fValueAllocated : 1;
  94. char *m_szName;
  95. char *m_szValue;
  96. DWORD m_cchName;
  97. DWORD m_cchValue;
  98. CHTTPHeader *m_pNext;
  99. char m_rgchLtoaBuffer[20]; // enough for atol
  100. public:
  101. CHTTPHeader();
  102. ~CHTTPHeader();
  103. HRESULT InitHeader(BSTR wszName, BSTR wszValue, UINT lCodePage = CP_ACP);
  104. HRESULT InitHeader(char *szName, BSTR wszValue, UINT lCodePage = CP_ACP);
  105. HRESULT InitHeader(char *szName, char *szValue, BOOL fCopyValue);
  106. HRESULT InitHeader(char *szName, long lValue);
  107. char *PSzName();
  108. char *PSzValue();
  109. DWORD CchLength();
  110. void Print(char *szBuf);
  111. void SetNext(CHTTPHeader *pHeader);
  112. CHTTPHeader *PNext();
  113. // Cache on per-class basis
  114. ACACHE_INCLASS_DEFINITIONS()
  115. };
  116. // CHTTPHeader inlines
  117. inline char *CHTTPHeader::PSzName()
  118. {
  119. Assert(m_fInited);
  120. return m_szName;
  121. }
  122. inline char *CHTTPHeader::PSzValue()
  123. {
  124. Assert(m_fInited);
  125. return m_szValue;
  126. }
  127. inline DWORD CHTTPHeader::CchLength()
  128. {
  129. Assert(m_fInited);
  130. return (m_cchName + m_cchValue + 4); // account for ": " and "\r\n"
  131. }
  132. inline void CHTTPHeader::SetNext(CHTTPHeader *pHeader)
  133. {
  134. Assert(m_fInited);
  135. Assert(!m_pNext);
  136. m_pNext = pHeader;
  137. }
  138. inline CHTTPHeader *CHTTPHeader::PNext()
  139. {
  140. return m_pNext;
  141. }
  142. /*
  143. * C R e s p o n s e V e c t o r
  144. *
  145. */
  146. class CResponseVector
  147. {
  148. LPWSABUF m_pExtVector; // Pointer to auxilary vector
  149. DWORD m_cExtVectorSize; // Size of auxilary vector
  150. DWORD m_iCurrentEntry; // Logical index of current entry
  151. BOOL m_fEntryIsOpen:1; // Can we add to current entry?
  152. DWORD m_cchTotalBuffered; // Total of ouput bytes buffered
  153. WSABUF m_aVector0[ RESPONSE_VECTOR_INTRINSIC_SIZE ]; // Pre-allocated vector
  154. HRESULT GrowVector();
  155. BOOL IsEntryOpen();
  156. LPWSABUF GetEntry( UINT i);
  157. DWORD GetEntryCount();
  158. public:
  159. CResponseVector();
  160. ~CResponseVector();
  161. VOID Clear();
  162. HRESULT Append( char * pData, DWORD cbSize);
  163. HRESULT Insert( char * pData, DWORD cbSize);
  164. VOID Close();
  165. VOID GetVectors( LPWSABUF_VECTORS pWsabuf);
  166. DWORD BytesBuffered();
  167. };
  168. inline BOOL CResponseVector::IsEntryOpen()
  169. {
  170. return m_fEntryIsOpen;
  171. }
  172. inline LPWSABUF CResponseVector::GetEntry(UINT i)
  173. {
  174. return (i < RESPONSE_VECTOR_INTRINSIC_SIZE) ?
  175. &m_aVector0[i] : m_pExtVector + i - RESPONSE_VECTOR_INTRINSIC_SIZE;
  176. }
  177. inline DWORD CResponseVector::GetEntryCount()
  178. {
  179. return IsEntryOpen() ? m_iCurrentEntry + 1 : m_iCurrentEntry;
  180. }
  181. inline VOID CResponseVector::GetVectors( LPWSABUF_VECTORS pWsabuf)
  182. {
  183. DWORD iEntries = GetEntryCount();
  184. if (iEntries > RESPONSE_VECTOR_INTRINSIC_SIZE)
  185. {
  186. pWsabuf->pVector1 = m_aVector0;
  187. pWsabuf->dwVectorLen1 = RESPONSE_VECTOR_INTRINSIC_SIZE;
  188. pWsabuf->pVector2 = m_pExtVector;
  189. pWsabuf->dwVectorLen2 = iEntries - RESPONSE_VECTOR_INTRINSIC_SIZE;
  190. }
  191. else
  192. {
  193. if (iEntries > 0)
  194. {
  195. pWsabuf->pVector1 = m_aVector0;
  196. pWsabuf->dwVectorLen1 = iEntries;
  197. }
  198. else
  199. {
  200. pWsabuf->pVector1 = NULL;
  201. pWsabuf->dwVectorLen1 = 0;
  202. }
  203. pWsabuf->pVector2 = NULL;
  204. pWsabuf->dwVectorLen2 = 0;
  205. }
  206. }
  207. inline DWORD CResponseVector::BytesBuffered()
  208. {
  209. return m_cchTotalBuffered;
  210. }
  211. // marks the current entry as closed, so that subsequent Append() will create a new entry
  212. inline VOID CResponseVector::Close()
  213. {
  214. if (IsEntryOpen())
  215. {
  216. m_fEntryIsOpen = FALSE;
  217. m_iCurrentEntry++;
  218. }
  219. }
  220. // Create a new entry: close current, append, and close new entry
  221. inline HRESULT CResponseVector::Insert(char * pData, DWORD cbSize)
  222. {
  223. HRESULT hr;
  224. Close();
  225. hr = Append(pData, cbSize);
  226. Close();
  227. return hr;
  228. }
  229. class CResponseBufferSet;
  230. /*
  231. * C R e s p o n s e B u f f e r
  232. *
  233. */
  234. class CResponseBuffer
  235. {
  236. CResponseBufferSet* m_pBufferSet; // Pointer to BufferSet for this object
  237. CResponseVector m_ResponseVector; // Response vector object
  238. char **m_rgpchBuffers; // Array of pointers to buffers
  239. char *m_pchBuffer0; // In case of 1 element array of pointers
  240. DWORD m_cBufferPointers; // Count of buffer pointers
  241. DWORD m_cBuffers; // Count of buffers we have allocated
  242. DWORD m_iCurrentBuffer; // Array index for the buffer we are currently filling
  243. DWORD m_cchOffsetInCurrentBuffer; // Offset within the current buffer
  244. DWORD m_dwBufferLimit; // max to buffer
  245. BOOL m_fInited; // Initialization status for the object
  246. HRESULT GrowBuffers(DWORD cchNewRequest); // Increase the size of the buffers
  247. public:
  248. CResponseBuffer();
  249. ~CResponseBuffer();
  250. HRESULT Init(CResponseBufferSet * pBufferSet, DWORD dwBufferLimit);
  251. char * GetBuffer(UINT i);
  252. DWORD GetBufferSize(UINT i);
  253. DWORD CountOfBuffers();
  254. DWORD BytesBuffered();
  255. CResponseVector * GetResponseVector();
  256. HRESULT Write(char* pszSource, DWORD cch, BOOL fChunkData, BOOL fTemplateData = FALSE);
  257. HRESULT Clear();
  258. VOID SetBufferLimit(DWORD dwBufferLimit);
  259. // Cache on per-class basis
  260. ACACHE_INCLASS_DEFINITIONS()
  261. };
  262. inline char * CResponseBuffer::GetBuffer(UINT i)
  263. {
  264. Assert( i < m_cBuffers );
  265. return m_rgpchBuffers[i];
  266. }
  267. inline DWORD CResponseBuffer::GetBufferSize(UINT i)
  268. {
  269. Assert( i < m_cBuffers );
  270. // if buffer is final one, its content-length is current offset
  271. if ( i == (m_cBuffers - 1 ) )
  272. {
  273. return m_cchOffsetInCurrentBuffer;
  274. }
  275. // if buffer is other than final one, its content-length is default buffer size
  276. return RESPONSE_BUFFER_SIZE;
  277. }
  278. inline DWORD CResponseBuffer::CountOfBuffers()
  279. {
  280. return m_cBuffers;
  281. }
  282. inline DWORD CResponseBuffer::BytesBuffered()
  283. {
  284. return m_ResponseVector.BytesBuffered();
  285. }
  286. inline CResponseVector * CResponseBuffer::GetResponseVector()
  287. {
  288. return &m_ResponseVector;
  289. }
  290. inline VOID CResponseBuffer::SetBufferLimit(DWORD dwBufferLimit)
  291. {
  292. m_dwBufferLimit = dwBufferLimit;
  293. }
  294. /*
  295. * C D e b u g R e s p o n s e B u f f e r
  296. *
  297. */
  298. class CDebugResponseBuffer : public CResponseBuffer
  299. {
  300. private:
  301. HRESULT Write(const char* pszSource);
  302. public:
  303. inline CDebugResponseBuffer() {}
  304. inline ~CDebugResponseBuffer() {}
  305. HRESULT Start();
  306. HRESULT End();
  307. HRESULT InitAndStart(CResponseBufferSet* pBufferSet, DWORD dwBufferLimit);
  308. HRESULT ClearAndStart();
  309. // the only real method
  310. HRESULT AppendRecord
  311. (
  312. const int cchBlockOffset,
  313. const int cchBlockLength,
  314. const int cchSourceOffset,
  315. const char *pszSourceFile = NULL
  316. );
  317. // Cache on per-class basis
  318. ACACHE_INCLASS_DEFINITIONS()
  319. };
  320. inline HRESULT CDebugResponseBuffer::Write(const char* pszSource)
  321. {
  322. return CResponseBuffer::Write((char *)pszSource, strlen(pszSource), FALSE);
  323. }
  324. inline HRESULT CDebugResponseBuffer::Start()
  325. {
  326. return Write("<!--METADATA TYPE=\"ASP_DEBUG_INFO\"\r\n");
  327. }
  328. inline HRESULT CDebugResponseBuffer::End()
  329. {
  330. return Write("-->\r\n");
  331. }
  332. inline HRESULT CDebugResponseBuffer::InitAndStart(CResponseBufferSet* pBufferSet,
  333. DWORD dwBufferLimit)
  334. {
  335. HRESULT hr = CResponseBuffer::Init(pBufferSet, dwBufferLimit);
  336. if (SUCCEEDED(hr))
  337. hr = Start();
  338. return hr;
  339. }
  340. inline HRESULT CDebugResponseBuffer::ClearAndStart()
  341. {
  342. HRESULT hr = CResponseBuffer::Clear();
  343. if (SUCCEEDED(hr))
  344. hr = Start();
  345. return hr;
  346. }
  347. /*
  348. * C R e s p o n s e C o o k i e s
  349. *
  350. * Implements the IRequestDictionary interface for writing cookies.
  351. */
  352. class CResponseCookies : public IRequestDictionaryImpl
  353. {
  354. private:
  355. IUnknown * m_punkOuter; // for addrefs
  356. CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
  357. CRequest * m_pRequest; // pointer to request object
  358. CResponse * m_pResponse; // pointer to parent object
  359. public:
  360. CResponseCookies(CResponse *, IUnknown *);
  361. ~CResponseCookies();
  362. HRESULT Init()
  363. {
  364. return S_OK;
  365. }
  366. HRESULT ReInit(CRequest *);
  367. // The Big Three
  368. STDMETHODIMP QueryInterface(const GUID &, void **);
  369. STDMETHODIMP_(ULONG) AddRef();
  370. STDMETHODIMP_(ULONG) Release();
  371. // OLE Automation Interface
  372. STDMETHODIMP get_Item(VARIANT varKey, VARIANT *pvarReturn);
  373. STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn);
  374. STDMETHODIMP get_Count(int *pcValues);
  375. STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar);
  376. // C++ interface to write headers
  377. size_t QueryHeaderSize();
  378. char *GetHeaders(char *szBuffer);
  379. };
  380. /*
  381. * C R e s p o n s e B u f f e r S e t
  382. *
  383. * Structure that holds the response buffer and Debug response buffer
  384. */
  385. class CResponseBufferSet {
  386. private:
  387. CResponseBuffer *m_pResponseBuffer; // Pointer to response buffer object
  388. CDebugResponseBuffer *m_pClientDebugBuffer; // Pointer to response buffer object for client debugging data
  389. CTemplate *m_pTemplate; // Pointer to the template for this request
  390. CTemplate *m_aTemplates[16]; // internal array of templates referenced by this request
  391. CTemplate **m_ppTemplates; // pointer to current array of templates
  392. DWORD m_dwTemplatesRefd; // count of templates in array
  393. DWORD m_dwArraySize; // total slots in array
  394. DWORD m_fCurTemplateInArray : 1; // TRUE if m_pTemplate is in m_aTemplates
  395. DWORD m_fTemplateArrayAllocd : 1; // TRUE if array was allocated
  396. public:
  397. CResponseBufferSet();
  398. ~CResponseBufferSet();
  399. HRESULT Init(DWORD dwBufferLimit);
  400. HRESULT InitDebugBuffer(DWORD dwBufferLimit);
  401. HRESULT AddTemplateToArray();
  402. static VOID SendResponseCompletion(CIsapiReqInfo *pIReq,
  403. PVOID pContext,
  404. DWORD cbIO,
  405. DWORD dwError);
  406. // inline helpers
  407. CResponseBuffer *PResponseBuffer() { return m_pResponseBuffer; }
  408. CDebugResponseBuffer *PClientDebugBuffer() { return m_pClientDebugBuffer; }
  409. CTemplate *PTemplate() { return m_pTemplate; }
  410. VOID SetTemplate(CTemplate *pTemplate)
  411. {
  412. m_pTemplate = pTemplate;
  413. m_fCurTemplateInArray = FALSE;
  414. }
  415. VOID SetBufferLimit(DWORD dwBufferLimit) {
  416. m_pResponseBuffer->SetBufferLimit(dwBufferLimit);
  417. if (m_pClientDebugBuffer)
  418. m_pClientDebugBuffer->SetBufferLimit(dwBufferLimit);
  419. }
  420. // Cache on per-class basis
  421. ACACHE_INCLASS_DEFINITIONS()
  422. };
  423. /*
  424. * C R e s p o n s e D a t a
  425. *
  426. * Structure that holds the intrinsic's properties.
  427. * The instrinsic keeps pointer to it (NULL when lightweight)
  428. */
  429. class CResponseData : public IUnknown
  430. {
  431. friend CResponse;
  432. friend CResponseCookies;
  433. friend CResponseBuffer;
  434. private:
  435. // constructor to pass params to members and init members
  436. CResponseData(CResponse *);
  437. ~CResponseData();
  438. HRESULT Init();
  439. CSupportErrorInfo m_ISupportErrImp; // Interface to indicate that we support ErrorInfo reporting
  440. CIsapiReqInfo * m_pIReq; // CIsapiReqInfo block for HTTP info
  441. CHitObj* m_pHitObj; // pointer to hitobj for this request
  442. CHTTPHeader* m_pFirstHeader; // List of
  443. CHTTPHeader* m_pLastHeader; // headers
  444. time_t m_tExpires; // date that the HTML output page expires; -1 if no date assigned
  445. const char* m_szCookieVal; // Value of session id
  446. const char* m_pszDefaultContentType;// Default content type (pointer to static string)
  447. const char* m_pszDefaultExpires; // Default expires header value
  448. char* m_pszContentType; // Content type of response (set by user)
  449. char* m_pszCharSet; // CharSet header of response
  450. char* m_pszCacheControl; // cache-control header of response
  451. char* m_pszStatus; // HTTP Status to be returned
  452. BYTE m_dwVersionMajor; // Major version of HTTP supported by client
  453. BYTE m_dwVersionMinor; // Minor version of HTTP supported by client
  454. CResponseBufferSet *m_pBufferSet; // Buffer set for response data
  455. int m_IsHeadRequest; // HEAD request flag 0=uninit, 1=not head, 2=head
  456. PFNGETSCRIPT m_pfnGetScript; // Pointer to callback function for obtaining CActiveEngine pointers
  457. void* m_pvGetScriptContext; // Pointer to data for for callback function for CActiveEngines
  458. CResponseCookies m_WriteCookies; // write-only cookie collection
  459. DWORD m_fResponseAborted : 1; // Was "Response.End" invoked?
  460. DWORD m_fWriteClientError : 1;// Write Client Failed
  461. DWORD m_fIgnoreWrites : 1; // Ignore all writes? (in case of custom error)
  462. DWORD m_fBufferingOn : 1; // Buffer response output
  463. DWORD m_fFlushed : 1; // Has flush been called?
  464. DWORD m_fChunkData : 1; // Doing HTTP 1.1 chunking?
  465. DWORD m_fChunkDataInited : 1; // has m_fChunkData been init'd?
  466. DWORD m_fClientDebugMode : 1; // In client debug mode?
  467. DWORD m_fClientDebugFlushIgnored : 1; // Flush request ignored due to client debug?
  468. ULONG m_cRefs; // ref count
  469. DWORD m_dwBufferLimit; // max to buffer
  470. void AppendHeaderToList(CHTTPHeader *pHeader);
  471. public:
  472. STDMETHODIMP QueryInterface(const GUID &, void **);
  473. STDMETHODIMP_(ULONG) AddRef();
  474. STDMETHODIMP_(ULONG) Release();
  475. DWORD BytesBuffered();
  476. BOOL FChunkData();
  477. VOID SetBufferLimit(DWORD dwBufferLimit);
  478. // Cache on per-class basis
  479. ACACHE_INCLASS_DEFINITIONS()
  480. };
  481. inline DWORD CResponseData::BytesBuffered()
  482. {
  483. DWORD dw = m_pBufferSet->PResponseBuffer()->GetResponseVector()->BytesBuffered();
  484. if (m_pBufferSet->PClientDebugBuffer())
  485. dw += m_pBufferSet->PClientDebugBuffer()->GetResponseVector()->BytesBuffered();
  486. return dw;
  487. }
  488. inline BOOL CResponseData::FChunkData()
  489. {
  490. if (m_fChunkDataInited == FALSE) {
  491. // If using HTTP/1.1 and not buffering add length ofTransfer-Encoding headers
  492. if ((m_dwVersionMinor >= 1) && (m_dwVersionMajor >= 1) &&
  493. (m_fBufferingOn == FALSE) &&
  494. !m_pIReq->IsChild()) { // don't chunk child request output
  495. // UNDONE: Temporary setting to turn off chuncked encoding
  496. if (Glob(fEnableChunkedEncoding))
  497. m_fChunkData = TRUE;
  498. }
  499. m_fChunkDataInited = TRUE;
  500. }
  501. return m_fChunkData;
  502. }
  503. inline VOID CResponseData::SetBufferLimit(DWORD dwBufferLimit)
  504. {
  505. m_dwBufferLimit = dwBufferLimit;
  506. m_pBufferSet->SetBufferLimit(dwBufferLimit);
  507. }
  508. inline void CResponseData::AppendHeaderToList(CHTTPHeader *pHeader)
  509. {
  510. if (!m_pLastHeader)
  511. {
  512. Assert(!m_pFirstHeader);
  513. m_pFirstHeader = pHeader;
  514. }
  515. else
  516. {
  517. Assert(m_pFirstHeader);
  518. m_pLastHeader->SetNext(pHeader);
  519. }
  520. m_pLastHeader = pHeader;
  521. }
  522. class CStaticWriteFileCB {
  523. public:
  524. WSABUF m_wsaBuf;
  525. CStaticWriteFileCB() {
  526. ZeroMemory( &m_wsaBuf, sizeof(WSABUF));
  527. }
  528. ~CStaticWriteFileCB() {
  529. if (m_wsaBuf.buf)
  530. CloseHandle((HANDLE)m_wsaBuf.buf);
  531. }
  532. };
  533. /*
  534. * C R e s p o n s e
  535. *
  536. * Implements the Response object
  537. */
  538. class CResponse : public IResponseImpl, public IStream
  539. {
  540. friend CResponseCookies;
  541. friend CResponseBuffer;
  542. private:
  543. // Flags
  544. DWORD m_fInited : 1; // Is initialized?
  545. DWORD m_fDiagnostics : 1; // Display ref count in debug output
  546. DWORD m_fOuterUnknown : 1; // Ref count outer unknown?
  547. // Ref count / Outer unknown
  548. union
  549. {
  550. DWORD m_cRefs;
  551. IUnknown *m_punkOuter;
  552. };
  553. // Properties
  554. CResponseData *m_pData; // pointer to structure that holds
  555. // CResponse properties
  556. // FTM Support
  557. IUnknown *m_pUnkFTM;
  558. VOID GetClientVerison(VOID);
  559. #ifdef DBG
  560. inline void TurnDiagsOn() { m_fDiagnostics = TRUE; }
  561. inline void TurnDiagsOff() { m_fDiagnostics = FALSE; }
  562. void AssertValid() const;
  563. #else
  564. inline void TurnDiagsOn() {}
  565. inline void TurnDiagsOff() {}
  566. inline void AssertValid() const {}
  567. #endif
  568. public:
  569. CResponse(IUnknown *punkOuter = NULL);
  570. ~CResponse();
  571. HRESULT CleanUp();
  572. HRESULT Init();
  573. HRESULT UnInit();
  574. HRESULT ReInitTemplate(CTemplate* pTemplate, const char *szCookie);
  575. CTemplate *SwapTemplate(CTemplate* pNewTemplate);
  576. HRESULT ReInit(CIsapiReqInfo *pIReq, const char *szCookie, CRequest *pRequest,
  577. PFNGETSCRIPT pfnGetScript, void *pvGetScriptContext, CHitObj *pHitObj);
  578. static HRESULT ConstructSimpleHeaders(
  579. LPHSE_SEND_HEADER_EX_INFO pHeaderInfo,
  580. DWORD cbTotal,
  581. char *szMimeType,
  582. char *szStatus = NULL,
  583. char *szExtraHeaders = NULL);
  584. HRESULT ConstructHeaders(LPHSE_SEND_HEADER_EX_INFO pHeaderInfo);
  585. HRESULT WriteResponse();
  586. VOID FinalFlush(HRESULT);
  587. HRESULT WriteSz(CHAR *sz, DWORD cch);
  588. HRESULT WriteBSTR(BSTR bstr);
  589. // append headers of different kind
  590. HRESULT AppendHeader(BSTR wszName, BSTR wszValue);
  591. HRESULT AppendHeader(char *szName, BSTR wszValue);
  592. HRESULT AppendHeader(char *szName, char *szValue, BOOL fCopyValue = FALSE);
  593. HRESULT AppendHeader(char *szName, long lValue);
  594. // inlines
  595. inline BOOL FHeadersWritten();
  596. inline BOOL IsHeadRequest(void);
  597. inline BOOL FResponseAborted();
  598. inline BOOL FWriteClientError();
  599. inline BOOL FDontWrite();
  600. inline void SetIgnoreWrites();
  601. inline CIsapiReqInfo* GetIReq();
  602. inline const char* PContentType() const;
  603. inline char *PCustomStatus();
  604. inline void *SwapScriptEngineInfo(void *pvEngineInfo);
  605. //Non-delegating object IUnknown
  606. STDMETHODIMP QueryInterface(REFIID, PPVOID);
  607. STDMETHODIMP_(ULONG) AddRef(void);
  608. STDMETHODIMP_(ULONG) Release(void);
  609. // GetIDsOfNames special-case implementation
  610. STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR **, UINT, LCID, DISPID *);
  611. // Tombstone stub
  612. HRESULT CheckForTombstone();
  613. //IResponse functions
  614. STDMETHODIMP Write(VARIANT varInput);
  615. STDMETHODIMP BinaryWrite(VARIANT varInput);
  616. STDMETHODIMP WriteBlock(short iBlockNumber);
  617. STDMETHODIMP Redirect(BSTR bstrURL);
  618. STDMETHODIMP AddHeader(BSTR bstrHeaderName, BSTR bstrHeaderValue);
  619. STDMETHODIMP Pics(BSTR bstrHeaderValue);
  620. STDMETHODIMP Add(BSTR bstrHeaderValue, BSTR bstrHeaderName);
  621. STDMETHODIMP SetCookie(BSTR bstrHeader, BSTR bstrValue, VARIANT varExpires,
  622. VARIANT varDomain, VARIANT varPath, VARIANT varSecure);
  623. STDMETHODIMP Clear(void);
  624. STDMETHODIMP Flush(void);
  625. STDMETHODIMP End(void);
  626. STDMETHODIMP AppendToLog(BSTR bstrLogEntry);
  627. STDMETHODIMP get_ContentType(BSTR *pbstrContentTypeRet);
  628. STDMETHODIMP put_ContentType(BSTR bstrContentType);
  629. STDMETHODIMP get_CharSet(BSTR *pbstrContentTypeRet);
  630. STDMETHODIMP put_CharSet(BSTR bstrContentType);
  631. STDMETHODIMP get_CacheControl(BSTR *pbstrCacheControl);
  632. STDMETHODIMP put_CacheControl(BSTR bstrCacheControl);
  633. STDMETHODIMP get_Status(BSTR *pbstrStatusRet);
  634. STDMETHODIMP put_Status(BSTR bstrStatus);
  635. STDMETHODIMP get_Expires(VARIANT *pvarExpiresMinutesRet);
  636. STDMETHODIMP put_Expires(long lExpiresMinutes);
  637. STDMETHODIMP get_ExpiresAbsolute(VARIANT *pvarTimeRet);
  638. STDMETHODIMP put_ExpiresAbsolute(DATE dtExpires);
  639. STDMETHODIMP get_Buffer(VARIANT_BOOL* fIsBuffering);
  640. STDMETHODIMP put_Buffer(VARIANT_BOOL fIsBuffering);
  641. STDMETHODIMP get_Cookies(IRequestDictionary **ppDictReturn);
  642. STDMETHODIMP IsClientConnected(VARIANT_BOOL* fIsBuffering);
  643. STDMETHODIMP get_CodePage(long *plVar);
  644. STDMETHODIMP put_CodePage(long var);
  645. STDMETHODIMP get_LCID(long *plVar);
  646. STDMETHODIMP put_LCID(long var);
  647. // static method to send the entire block using SyncWriteClient
  648. static HRESULT StaticWrite(CIsapiReqInfo *pIReq,
  649. char *pchBuf,
  650. DWORD cchBuf = 0,
  651. CTemplate *pTemplate = NULL);
  652. // static method to send contents of several memory blocks as the entire response (sync)
  653. static HRESULT WriteBlocksResponse(CIsapiReqInfo *pIReq,
  654. DWORD cBlocks,
  655. LPWSABUF pWsaBuf,
  656. DWORD cbTotal,
  657. char *szMimeType = NULL,
  658. char *szStatus = NULL,
  659. char *szExtraHeaders = NULL);
  660. // static method to send contents of a file as the entire response (sync)
  661. static HRESULT SyncWriteFile(CIsapiReqInfo *pIReq,
  662. TCHAR *szFile,
  663. char *szMimeType = NULL,
  664. char *szStatus = NULL,
  665. char *szExtraHeaders = NULL);
  666. static VOID StaticWriteFileCompletion(CIsapiReqInfo *pIReq,
  667. PVOID pContext,
  668. DWORD cbIO,
  669. DWORD dwError);
  670. // static method to send contents of a scriptless template as the entire response (sync)
  671. static HRESULT WriteScriptlessTemplate(CIsapiReqInfo *pIReq,
  672. CTemplate *pTemplate);
  673. // IStream implementation
  674. STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead);
  675. STDMETHODIMP Write(const void *pv, ULONG cb, ULONG *pcbWritten);
  676. STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
  677. ULARGE_INTEGER *plibNewPosition);
  678. STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize);
  679. STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb,
  680. ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten);
  681. STDMETHODIMP Commit(DWORD grfCommitFlags);
  682. STDMETHODIMP Revert();
  683. STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  684. DWORD dwLockType);
  685. STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  686. DWORD dwLockType);
  687. STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag);
  688. STDMETHODIMP Clone(IStream **ppstm);
  689. // Cache on per-class basis
  690. ACACHE_INCLASS_DEFINITIONS()
  691. };
  692. inline BOOL CResponse::FHeadersWritten()
  693. {
  694. Assert(m_fInited);
  695. Assert(m_pData);
  696. return m_pData->m_pIReq->FHeadersWritten();
  697. }
  698. inline BOOL CResponse::FResponseAborted()
  699. {
  700. Assert(m_fInited);
  701. Assert(m_pData);
  702. return m_pData->m_fResponseAborted;
  703. }
  704. inline BOOL CResponse::FWriteClientError()
  705. {
  706. Assert(m_fInited);
  707. Assert(m_pData);
  708. return m_pData->m_fWriteClientError;
  709. }
  710. inline BOOL CResponse::FDontWrite()
  711. {
  712. Assert(m_fInited);
  713. Assert(m_pData);
  714. return (m_pData->m_fWriteClientError || m_pData->m_fIgnoreWrites);
  715. }
  716. inline void CResponse::SetIgnoreWrites()
  717. {
  718. Assert(m_fInited);
  719. Assert(m_pData);
  720. m_pData->m_fIgnoreWrites = TRUE;
  721. }
  722. inline CIsapiReqInfo* CResponse::GetIReq()
  723. {
  724. Assert(m_fInited);
  725. Assert(m_pData);
  726. return m_pData->m_pIReq;
  727. }
  728. inline const char* CResponse::PContentType() const
  729. {
  730. Assert(m_fInited);
  731. Assert(m_pData);
  732. if (m_pData->m_pszContentType)
  733. return m_pData->m_pszContentType;
  734. else
  735. return m_pData->m_pszDefaultContentType;
  736. }
  737. inline char* CResponse::PCustomStatus()
  738. {
  739. Assert(m_fInited);
  740. Assert(m_pData);
  741. return m_pData->m_pszStatus;
  742. }
  743. inline void *CResponse::SwapScriptEngineInfo(void *pvEngineInfo)
  744. {
  745. Assert(m_fInited);
  746. Assert(m_pData);
  747. void *pvOldEngineInfo = m_pData->m_pvGetScriptContext;
  748. m_pData->m_pvGetScriptContext = pvEngineInfo;
  749. return pvOldEngineInfo;
  750. }
  751. #endif //_RESPONSE_H