Source code of Windows XP (NT5)
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.

646 lines
19 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. #include "ftm.h"
  21. const DWORD RESPONSE_BUFFER_SIZE = 32768;
  22. const DWORD BUFFERS_INCREMENT = 256;
  23. const DWORD ALLOCA_LIMIT = 4096;
  24. const DWORD MAX_RESPONSE = 32768;
  25. const DWORD MAX_MESSAGE_LENGTH = 512;
  26. class CScriptEngine;
  27. #ifdef USE_LOCALE
  28. extern DWORD g_dwTLS;
  29. #endif
  30. // fixed size allocator for response buffers
  31. ACACHE_FSA_EXTERN(ResponseBuffer)
  32. // forward refs
  33. class CResponse;
  34. class CRequest;
  35. //This file is generated from MKTYPLIB on denali.obj
  36. #include "asptlb.h"
  37. //Type for an object-destroyed callback
  38. typedef void (*PFNDESTROYED)(void);
  39. //Type for the "Get Active Script Engine" callback
  40. typedef CScriptEngine *(*PFNGETSCRIPT)(int iScriptEngine, void *pvContext);
  41. /*
  42. * C H T T P H e a d e r L i n k
  43. *
  44. */
  45. class CHTTPHeader
  46. {
  47. private:
  48. DWORD m_fInited : 1;
  49. DWORD m_fNameAllocated : 1;
  50. DWORD m_fValueAllocated : 1;
  51. char *m_szName;
  52. char *m_szValue;
  53. DWORD m_cchName;
  54. DWORD m_cchValue;
  55. CHTTPHeader *m_pNext;
  56. char m_rgchLtoaBuffer[20]; // enough for atol
  57. public:
  58. CHTTPHeader();
  59. ~CHTTPHeader();
  60. HRESULT InitHeader(BSTR wszName, BSTR wszValue, UINT lCodePage = CP_ACP);
  61. HRESULT InitHeader(char *szName, BSTR wszValue, UINT lCodePage = CP_ACP);
  62. HRESULT InitHeader(char *szName, char *szValue, BOOL fCopyValue);
  63. HRESULT InitHeader(char *szName, long lValue);
  64. char *PSzName();
  65. char *PSzValue();
  66. DWORD CchLength();
  67. void Print(char *szBuf);
  68. void SetNext(CHTTPHeader *pHeader);
  69. CHTTPHeader *PNext();
  70. // Cache on per-class basis
  71. ACACHE_INCLASS_DEFINITIONS()
  72. };
  73. // CHTTPHeader inlines
  74. inline char *CHTTPHeader::PSzName()
  75. {
  76. Assert(m_fInited);
  77. return m_szName;
  78. }
  79. inline char *CHTTPHeader::PSzValue()
  80. {
  81. Assert(m_fInited);
  82. return m_szValue;
  83. }
  84. inline DWORD CHTTPHeader::CchLength()
  85. {
  86. Assert(m_fInited);
  87. return (m_cchName + m_cchValue + 4); // account for ": " and "\r\n"
  88. }
  89. inline void CHTTPHeader::SetNext(CHTTPHeader *pHeader)
  90. {
  91. Assert(m_fInited);
  92. Assert(!m_pNext);
  93. m_pNext = pHeader;
  94. }
  95. inline CHTTPHeader *CHTTPHeader::PNext()
  96. {
  97. return m_pNext;
  98. }
  99. /*
  100. * C R e s p o n s e B u f f e r
  101. *
  102. */
  103. class CResponseBuffer
  104. {
  105. CResponse* m_pResponse; // Pointer to enclosing response
  106. char **m_rgpchBuffers; // Array of pointers to buffers
  107. char *m_pchBuffer0; // In case of 1 element array of pointers
  108. DWORD m_cBufferPointers; // Count of buffer pointers
  109. DWORD m_cBuffers; // Count of buffers we have allocated
  110. DWORD m_iCurrentBuffer; // Array index for the buffer we are currently filling
  111. DWORD m_cchOffsetInCurrentBuffer; // Offset within the current buffer
  112. DWORD m_cchTotalBuffered; // Total of ouput bytes buffered
  113. BOOL m_fInited; // Initialization status for the object
  114. HRESULT GrowBuffers(DWORD cchNewRequest); // Increase the size of the buffers
  115. public:
  116. CResponseBuffer();
  117. ~CResponseBuffer();
  118. HRESULT Init(CResponse* pResponse);
  119. char * GetBuffer(UINT i);
  120. DWORD GetBufferSize(UINT i);
  121. DWORD CountOfBuffers();
  122. DWORD BytesBuffered();
  123. HRESULT Write(char* pszSource, DWORD cch);
  124. HRESULT Flush(CIsapiReqInfo *pIReq);
  125. HRESULT Clear();
  126. // Cache on per-class basis
  127. ACACHE_INCLASS_DEFINITIONS()
  128. };
  129. inline char * CResponseBuffer::GetBuffer(UINT i)
  130. {
  131. Assert( i < m_cBuffers );
  132. return m_rgpchBuffers[i];
  133. }
  134. inline DWORD CResponseBuffer::GetBufferSize(UINT i)
  135. {
  136. Assert( i < m_cBuffers );
  137. // if buffer is final one, its content-length is current offset
  138. if ( i == (m_cBuffers - 1 ) )
  139. {
  140. return m_cchOffsetInCurrentBuffer;
  141. }
  142. // if buffer is other than final one, its content-length is default buffer size
  143. return RESPONSE_BUFFER_SIZE;
  144. }
  145. inline DWORD CResponseBuffer::CountOfBuffers()
  146. {
  147. return m_cBuffers;
  148. }
  149. inline DWORD CResponseBuffer::BytesBuffered()
  150. {
  151. return m_cchTotalBuffered;
  152. }
  153. /*
  154. * C D e b u g R e s p o n s e B u f f e r
  155. *
  156. */
  157. class CDebugResponseBuffer : public CResponseBuffer
  158. {
  159. private:
  160. HRESULT Write(const char* pszSource);
  161. public:
  162. inline CDebugResponseBuffer() {}
  163. inline ~CDebugResponseBuffer() {}
  164. HRESULT Start();
  165. HRESULT End();
  166. HRESULT InitAndStart(CResponse* pResponse);
  167. HRESULT ClearAndStart();
  168. // the only real method
  169. HRESULT AppendRecord
  170. (
  171. const int cchBlockOffset,
  172. const int cchBlockLength,
  173. const int cchSourceOffset,
  174. const char *pszSourceFile = NULL
  175. );
  176. // Cache on per-class basis
  177. ACACHE_INCLASS_DEFINITIONS()
  178. };
  179. inline HRESULT CDebugResponseBuffer::Write(const char* pszSource)
  180. {
  181. return CResponseBuffer::Write((char *)pszSource, strlen(pszSource));
  182. }
  183. inline HRESULT CDebugResponseBuffer::Start()
  184. {
  185. return Write("<!--METADATA TYPE=\"ASP_DEBUG_INFO\"\r\n");
  186. }
  187. inline HRESULT CDebugResponseBuffer::End()
  188. {
  189. return Write("-->\r\n");
  190. }
  191. inline HRESULT CDebugResponseBuffer::InitAndStart(CResponse* pResponse)
  192. {
  193. HRESULT hr = CResponseBuffer::Init(pResponse);
  194. if (SUCCEEDED(hr))
  195. hr = Start();
  196. return hr;
  197. }
  198. inline HRESULT CDebugResponseBuffer::ClearAndStart()
  199. {
  200. HRESULT hr = CResponseBuffer::Clear();
  201. if (SUCCEEDED(hr))
  202. hr = Start();
  203. return hr;
  204. }
  205. /*
  206. * C R e s p o n s e C o o k i e s
  207. *
  208. * Implements the IRequestDictionary interface for writing cookies.
  209. */
  210. class CResponseCookies : public IRequestDictionaryImpl
  211. {
  212. private:
  213. IUnknown * m_punkOuter; // for addrefs
  214. CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
  215. CRequest * m_pRequest; // pointer to request object
  216. CResponse * m_pResponse; // pointer to parent object
  217. public:
  218. CResponseCookies(CResponse *, IUnknown *);
  219. ~CResponseCookies();
  220. HRESULT Init()
  221. {
  222. return S_OK;
  223. }
  224. HRESULT ReInit(CRequest *);
  225. // The Big Three
  226. STDMETHODIMP QueryInterface(const GUID &, void **);
  227. STDMETHODIMP_(ULONG) AddRef();
  228. STDMETHODIMP_(ULONG) Release();
  229. // OLE Automation Interface
  230. STDMETHODIMP get_Item(VARIANT varKey, VARIANT *pvarReturn);
  231. STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn);
  232. STDMETHODIMP get_Count(int *pcValues);
  233. STDMETHODIMP get_Key(VARIANT VarKey, VARIANT *pvar);
  234. // C++ interface to write headers
  235. size_t QueryHeaderSize();
  236. char *GetHeaders(char *szBuffer);
  237. };
  238. /*
  239. * C R e s p o n s e D a t a
  240. *
  241. * Structure that holds the intrinsic's properties.
  242. * The instrinsic keeps pointer to it (NULL when lightweight)
  243. */
  244. class CResponseData : public IUnknown
  245. {
  246. friend CResponse;
  247. friend CResponseCookies;
  248. friend CResponseBuffer;
  249. private:
  250. // constructor to pass params to members and init members
  251. CResponseData(CResponse *pResponse);
  252. ~CResponseData();
  253. HRESULT Init(CResponse *pResponse);
  254. CSupportErrorInfo m_ISupportErrImp; // Interface to indicate that we support ErrorInfo reporting
  255. CIsapiReqInfo * m_pIReq; // CIsapiReqInfo block for HTTP info
  256. CHitObj* m_pHitObj; // pointer to hitobj for this request
  257. CTemplate* m_pTemplate; // Pointer to the template for this request
  258. CHTTPHeader* m_pFirstHeader; // List of
  259. CHTTPHeader* m_pLastHeader; // headers
  260. time_t m_tExpires; // date that the HTML output page expires; -1 if no date assigned
  261. const char* m_szCookieVal; // Value of session id
  262. const char* m_pszDefaultContentType;// Default content type (pointer to static string)
  263. const char* m_pszDefaultExpires; // Default expires header value
  264. char* m_pszContentType; // Content type of response (set by user)
  265. char* m_pszCharSet; // CharSet header of response
  266. char* m_pszCacheControl; // cache-control header of response
  267. char* m_pszStatus; // HTTP Status to be returned
  268. BYTE m_dwVersionMajor; // Major version of HTTP supported by client
  269. BYTE m_dwVersionMinor; // Minor version of HTTP supported by client
  270. CResponseBuffer * m_pResponseBuffer; // Pointer to response buffer object
  271. CDebugResponseBuffer * m_pClientDebugBuffer; // Pointer to response buffer object for client debugging data
  272. int m_IsHeadRequest; // HEAD request flag 0=uninit, 1=not head, 2=head
  273. PFNGETSCRIPT m_pfnGetScript; // Pointer to callback function for obtaining CActiveEngine pointers
  274. void* m_pvGetScriptContext; // Pointer to data for for callback function for CActiveEngines
  275. CResponseCookies m_WriteCookies; // write-only cookie collection
  276. BOOL m_fHeadersWritten : 1; // Have the output headers been written?
  277. BOOL m_fResponseAborted : 1; // Was "Response.End" invoked?
  278. BOOL m_fWriteClientError : 1;// Write Client Failed
  279. BOOL m_fIgnoreWrites : 1; // Ignore all writes? (in case of custom error)
  280. BOOL m_fBufferingOn : 1; // Buffer response output
  281. BOOL m_fFlushed : 1; // Has flush been called?
  282. BOOL m_fChunked : 1; // Doing HTTP 1.1 chunking?
  283. BOOL m_fClientDebugMode : 1; // In client debug mode?
  284. BOOL m_fClientDebugFlushIgnored : 1; // Flush request ignored due to client debug?
  285. ULONG m_cRefs; // ref count
  286. void AppendHeaderToList(CHTTPHeader *pHeader);
  287. public:
  288. STDMETHODIMP QueryInterface(const GUID &, void **);
  289. STDMETHODIMP_(ULONG) AddRef();
  290. STDMETHODIMP_(ULONG) Release();
  291. // Cache on per-class basis
  292. ACACHE_INCLASS_DEFINITIONS()
  293. };
  294. inline void CResponseData::AppendHeaderToList(CHTTPHeader *pHeader)
  295. {
  296. if (!m_pLastHeader)
  297. {
  298. Assert(!m_pFirstHeader);
  299. m_pFirstHeader = pHeader;
  300. }
  301. else
  302. {
  303. Assert(m_pFirstHeader);
  304. m_pLastHeader->SetNext(pHeader);
  305. }
  306. m_pLastHeader = pHeader;
  307. }
  308. /*
  309. * C R e s p o n s e
  310. *
  311. * Implements the Response object
  312. */
  313. class CResponse : public IResponseImpl, public CFTMImplementation, public IStream
  314. {
  315. friend CResponseCookies;
  316. friend CResponseBuffer;
  317. private:
  318. // Flags
  319. DWORD m_fInited : 1; // Is initialized?
  320. DWORD m_fDiagnostics : 1; // Display ref count in debug output
  321. DWORD m_fOuterUnknown : 1; // Ref count outer unknown?
  322. // Ref count / Outer unknown
  323. union
  324. {
  325. DWORD m_cRefs;
  326. IUnknown *m_punkOuter;
  327. };
  328. // Properties
  329. CResponseData *m_pData; // pointer to structure that holds
  330. // CResponse properties
  331. VOID GetClientVerison(VOID);
  332. HRESULT WriteClient(BYTE *pb, DWORD cb);
  333. HRESULT WriteClientChunked(BYTE *pb, DWORD cb);
  334. #ifdef DBG
  335. inline void TurnDiagsOn() { m_fDiagnostics = TRUE; }
  336. inline void TurnDiagsOff() { m_fDiagnostics = FALSE; }
  337. void AssertValid() const;
  338. #else
  339. inline void TurnDiagsOn() {}
  340. inline void TurnDiagsOff() {}
  341. inline void AssertValid() const {}
  342. #endif
  343. public:
  344. CResponse(IUnknown *punkOuter = NULL);
  345. ~CResponse();
  346. HRESULT CleanUp();
  347. HRESULT Init();
  348. HRESULT UnInit();
  349. HRESULT ReInitTemplate(CTemplate* pTemplate, const char *szCookie);
  350. CTemplate *SwapTemplate(CTemplate* pNewTemplate);
  351. HRESULT ReInit(CIsapiReqInfo *pIReq, const char *szCookie, CRequest *pRequest,
  352. PFNGETSCRIPT pfnGetScript, void *pvGetScriptContext, CHitObj *pHitObj);
  353. HRESULT WriteHeaders(BOOL fSendEntireResponse = FALSE);
  354. HRESULT FinalFlush(HRESULT);
  355. HRESULT WriteSz(CHAR *sz, DWORD cch);
  356. HRESULT WriteBSTR(BSTR bstr);
  357. // append headers of different kind
  358. HRESULT AppendHeader(BSTR wszName, BSTR wszValue);
  359. HRESULT AppendHeader(char *szName, BSTR wszValue);
  360. HRESULT AppendHeader(char *szName, char *szValue, BOOL fCopyValue = FALSE);
  361. HRESULT AppendHeader(char *szName, long lValue);
  362. // inlines
  363. inline BOOL FHeadersWritten();
  364. inline BOOL IsHeadRequest(void);
  365. inline BOOL FResponseAborted();
  366. inline BOOL FWriteClientError();
  367. inline BOOL FDontWrite();
  368. inline void SetHeadersWritten();
  369. inline void SetIgnoreWrites();
  370. inline CIsapiReqInfo* GetIReq();
  371. inline const char* PContentType() const;
  372. inline char *PCustomStatus();
  373. inline void *SwapScriptEngineInfo(void *pvEngineInfo);
  374. //Non-delegating object IUnknown
  375. STDMETHODIMP QueryInterface(REFIID, PPVOID);
  376. STDMETHODIMP_(ULONG) AddRef(void);
  377. STDMETHODIMP_(ULONG) Release(void);
  378. // GetIDsOfNames special-case implementation
  379. STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR **, UINT, LCID, DISPID *);
  380. // Tombstone stub
  381. HRESULT CheckForTombstone();
  382. //IResponse functions
  383. STDMETHODIMP Write(VARIANT varInput);
  384. STDMETHODIMP BinaryWrite(VARIANT varInput);
  385. STDMETHODIMP WriteBlock(short iBlockNumber);
  386. STDMETHODIMP Redirect(BSTR bstrURL);
  387. STDMETHODIMP AddHeader(BSTR bstrHeaderName, BSTR bstrHeaderValue);
  388. STDMETHODIMP Pics(BSTR bstrHeaderValue);
  389. STDMETHODIMP Add(BSTR bstrHeaderValue, BSTR bstrHeaderName);
  390. STDMETHODIMP SetCookie(BSTR bstrHeader, BSTR bstrValue, VARIANT varExpires,
  391. VARIANT varDomain, VARIANT varPath, VARIANT varSecure);
  392. STDMETHODIMP Clear(void);
  393. STDMETHODIMP Flush(void);
  394. STDMETHODIMP End(void);
  395. STDMETHODIMP AppendToLog(BSTR bstrLogEntry);
  396. STDMETHODIMP get_ContentType(BSTR *pbstrContentTypeRet);
  397. STDMETHODIMP put_ContentType(BSTR bstrContentType);
  398. STDMETHODIMP get_CharSet(BSTR *pbstrContentTypeRet);
  399. STDMETHODIMP put_CharSet(BSTR bstrContentType);
  400. STDMETHODIMP get_CacheControl(BSTR *pbstrCacheControl);
  401. STDMETHODIMP put_CacheControl(BSTR bstrCacheControl);
  402. STDMETHODIMP get_Status(BSTR *pbstrStatusRet);
  403. STDMETHODIMP put_Status(BSTR bstrStatus);
  404. STDMETHODIMP get_Expires(VARIANT *pvarExpiresMinutesRet);
  405. STDMETHODIMP put_Expires(long lExpiresMinutes);
  406. STDMETHODIMP get_ExpiresAbsolute(VARIANT *pvarTimeRet);
  407. STDMETHODIMP put_ExpiresAbsolute(DATE dtExpires);
  408. STDMETHODIMP get_Buffer(VARIANT_BOOL* fIsBuffering);
  409. STDMETHODIMP put_Buffer(VARIANT_BOOL fIsBuffering);
  410. STDMETHODIMP get_Cookies(IRequestDictionary **ppDictReturn);
  411. STDMETHODIMP IsClientConnected(VARIANT_BOOL* fIsBuffering);
  412. STDMETHODIMP get_CodePage(long *plVar);
  413. STDMETHODIMP put_CodePage(long var);
  414. STDMETHODIMP get_LCID(long *plVar);
  415. STDMETHODIMP put_LCID(long var);
  416. // static method to send the entire block using SyncWriteClient
  417. static HRESULT SyncWrite(CIsapiReqInfo *pIReq,
  418. char *pchBuf,
  419. DWORD cchBuf = 0);
  420. // static method to send contents of several memory blocks as the entire response (sync)
  421. static HRESULT SyncWriteBlocks(CIsapiReqInfo *pIReq,
  422. DWORD cBlocks,
  423. DWORD cbTotal,
  424. void **rgpvBlock,
  425. DWORD *rgcbBlock,
  426. char *szMimeType = NULL,
  427. char *szStatus = NULL,
  428. char *szExtraHeaders = NULL);
  429. // static method to send contents of a memory block as the entire response (sync)
  430. inline static HRESULT SyncWriteBlock(CIsapiReqInfo *pIReq,
  431. void *pvBlock,
  432. DWORD cbBlock,
  433. char *szMimeType = NULL,
  434. char *szStatus = NULL,
  435. char *szExtraHeaders = NULL)
  436. {
  437. return SyncWriteBlocks(pIReq, 1, cbBlock, &pvBlock, &cbBlock,
  438. szMimeType, szStatus, szExtraHeaders);
  439. }
  440. // static method to send contents of a file as the entire response (sync)
  441. static HRESULT SyncWriteFile(CIsapiReqInfo *pIReq,
  442. TCHAR *szFile,
  443. char *szMimeType = NULL,
  444. char *szStatus = NULL,
  445. char *szExtraHeaders = NULL);
  446. // static method to send contents of a scriptless template as the entire response (sync)
  447. static HRESULT SyncWriteScriptlessTemplate(CIsapiReqInfo *pIReq,
  448. CTemplate *pTemplate);
  449. // IStream implementation
  450. STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead);
  451. STDMETHODIMP Write(const void *pv, ULONG cb, ULONG *pcbWritten);
  452. STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
  453. ULARGE_INTEGER *plibNewPosition);
  454. STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize);
  455. STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb,
  456. ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten);
  457. STDMETHODIMP Commit(DWORD grfCommitFlags);
  458. STDMETHODIMP Revert();
  459. STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  460. DWORD dwLockType);
  461. STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
  462. DWORD dwLockType);
  463. STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag);
  464. STDMETHODIMP Clone(IStream **ppstm);
  465. // Cache on per-class basis
  466. ACACHE_INCLASS_DEFINITIONS()
  467. };
  468. inline BOOL CResponse::FHeadersWritten()
  469. {
  470. Assert(m_fInited);
  471. Assert(m_pData);
  472. return m_pData->m_fHeadersWritten;
  473. }
  474. inline BOOL CResponse::FResponseAborted()
  475. {
  476. Assert(m_fInited);
  477. Assert(m_pData);
  478. return m_pData->m_fResponseAborted;
  479. }
  480. inline BOOL CResponse::FWriteClientError()
  481. {
  482. Assert(m_fInited);
  483. Assert(m_pData);
  484. return m_pData->m_fWriteClientError;
  485. }
  486. inline BOOL CResponse::FDontWrite()
  487. {
  488. Assert(m_fInited);
  489. Assert(m_pData);
  490. return (m_pData->m_fWriteClientError || m_pData->m_fIgnoreWrites);
  491. }
  492. inline void CResponse::SetHeadersWritten()
  493. {
  494. Assert(m_fInited);
  495. Assert(m_pData);
  496. m_pData->m_fHeadersWritten = TRUE;
  497. }
  498. inline void CResponse::SetIgnoreWrites()
  499. {
  500. Assert(m_fInited);
  501. Assert(m_pData);
  502. m_pData->m_fIgnoreWrites = TRUE;
  503. }
  504. inline CIsapiReqInfo* CResponse::GetIReq()
  505. {
  506. Assert(m_fInited);
  507. Assert(m_pData);
  508. return m_pData->m_pIReq;
  509. }
  510. inline const char* CResponse::PContentType() const
  511. {
  512. Assert(m_fInited);
  513. Assert(m_pData);
  514. if (m_pData->m_pszContentType)
  515. return m_pData->m_pszContentType;
  516. else
  517. return m_pData->m_pszDefaultContentType;
  518. }
  519. inline char* CResponse::PCustomStatus()
  520. {
  521. Assert(m_fInited);
  522. Assert(m_pData);
  523. return m_pData->m_pszStatus;
  524. }
  525. inline void *CResponse::SwapScriptEngineInfo(void *pvEngineInfo)
  526. {
  527. Assert(m_fInited);
  528. Assert(m_pData);
  529. void *pvOldEngineInfo = m_pData->m_pvGetScriptContext;
  530. m_pData->m_pvGetScriptContext = pvEngineInfo;
  531. return pvOldEngineInfo;
  532. }
  533. #endif //_RESPONSE_H