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.

592 lines
14 KiB

  1. #ifndef W3RESPONSE_HXX_INCLUDED
  2. #define W3RESPONSE_HXX_INCLUDED
  3. //
  4. // HTTP status codes
  5. //
  6. #define REASON(x) (x),sizeof(x)-sizeof(CHAR)
  7. struct HTTP_STATUS
  8. {
  9. USHORT statusCode;
  10. PCHAR pszReason;
  11. USHORT cbReason;
  12. };
  13. extern HTTP_STATUS HttpStatusOk;
  14. extern HTTP_STATUS HttpStatusPartialContent;
  15. extern HTTP_STATUS HttpStatusMultiStatus;
  16. extern HTTP_STATUS HttpStatusMovedPermanently;
  17. extern HTTP_STATUS HttpStatusRedirect;
  18. extern HTTP_STATUS HttpStatusMovedTemporarily;
  19. extern HTTP_STATUS HttpStatusNotModified;
  20. extern HTTP_STATUS HttpStatusBadRequest;
  21. extern HTTP_STATUS HttpStatusUnauthorized;
  22. extern HTTP_STATUS HttpStatusForbidden;
  23. extern HTTP_STATUS HttpStatusNotFound;
  24. extern HTTP_STATUS HttpStatusMethodNotAllowed;
  25. extern HTTP_STATUS HttpStatusNotAcceptable;
  26. extern HTTP_STATUS HttpStatusProxyAuthRequired;
  27. extern HTTP_STATUS HttpStatusPreconditionFailed;
  28. extern HTTP_STATUS HttpStatusEntityTooLarge;
  29. extern HTTP_STATUS HttpStatusUrlTooLong;
  30. extern HTTP_STATUS HttpStatusRangeNotSatisfiable;
  31. extern HTTP_STATUS HttpStatusExpectationFailed;
  32. extern HTTP_STATUS HttpStatusLockedError;
  33. extern HTTP_STATUS HttpStatusServerError;
  34. extern HTTP_STATUS HttpStatusNotImplemented;
  35. extern HTTP_STATUS HttpStatusBadGateway;
  36. extern HTTP_STATUS HttpStatusServiceUnavailable;
  37. extern HTTP_STATUS HttpStatusGatewayTimeout;
  38. //
  39. // HTTP Sub Errors
  40. //
  41. struct HTTP_SUB_ERROR
  42. {
  43. USHORT mdSubError;
  44. DWORD dwStringId;
  45. };
  46. extern HTTP_SUB_ERROR HttpNoSubError;
  47. extern HTTP_SUB_ERROR Http401BadLogon;
  48. extern HTTP_SUB_ERROR Http401Config;
  49. extern HTTP_SUB_ERROR Http401Resource;
  50. extern HTTP_SUB_ERROR Http401Filter;
  51. extern HTTP_SUB_ERROR Http401Application;
  52. extern HTTP_SUB_ERROR Http403ExecAccessDenied;
  53. extern HTTP_SUB_ERROR Http403ReadAccessDenied;
  54. extern HTTP_SUB_ERROR Http403WriteAccessDenied;
  55. extern HTTP_SUB_ERROR Http403SSLRequired;
  56. extern HTTP_SUB_ERROR Http403SSL128Required;
  57. extern HTTP_SUB_ERROR Http403IPAddressReject;
  58. extern HTTP_SUB_ERROR Http403CertRequired;
  59. extern HTTP_SUB_ERROR Http403SiteAccessDenied;
  60. extern HTTP_SUB_ERROR Http403TooManyUsers;
  61. extern HTTP_SUB_ERROR Http403InvalidateConfig;
  62. extern HTTP_SUB_ERROR Http403PasswordChange;
  63. extern HTTP_SUB_ERROR Http403MapperDenyAccess;
  64. extern HTTP_SUB_ERROR Http403CertRevoked;
  65. extern HTTP_SUB_ERROR Http403DirBrowsingDenied;
  66. extern HTTP_SUB_ERROR Http403CertInvalid;
  67. extern HTTP_SUB_ERROR Http403CertTimeInvalid;
  68. extern HTTP_SUB_ERROR Http403AppPoolDenied;
  69. extern HTTP_SUB_ERROR Http403InsufficientPrivilegeForCgi;
  70. extern HTTP_SUB_ERROR Http403PassportLoginFailure;
  71. extern HTTP_SUB_ERROR Http404SiteNotFound;
  72. extern HTTP_SUB_ERROR Http404DeniedByPolicy;
  73. extern HTTP_SUB_ERROR Http404DeniedByMimeMap;
  74. extern HTTP_SUB_ERROR Http500UNCAccess;
  75. extern HTTP_SUB_ERROR Http500BadMetadata;
  76. extern HTTP_SUB_ERROR Http502Timeout;
  77. extern HTTP_SUB_ERROR Http502PrematureExit;
  78. #define W3_RESPONSE_INLINE_HEADERS 10
  79. #define W3_RESPONSE_INLINE_CHUNKS 5
  80. #define W3_RESPONSE_SIGNATURE ((DWORD) 'PR3W')
  81. #define W3_RESPONSE_SIGNATURE_FREE ((DWORD) 'pr3w')
  82. #define W3_RESPONSE_ASYNC 0x01
  83. #define W3_RESPONSE_MORE_DATA 0x02
  84. #define W3_RESPONSE_DISCONNECT 0x04
  85. #define W3_RESPONSE_SUPPRESS_ENTITY 0x10
  86. #define W3_RESPONSE_SUPPRESS_HEADERS 0x20
  87. enum W3_RESPONSE_MODE
  88. {
  89. RESPONSE_MODE_PARSED,
  90. RESPONSE_MODE_RAW
  91. };
  92. class W3_RESPONSE
  93. {
  94. private:
  95. DWORD _dwSignature;
  96. HTTP_RESPONSE _ulHttpResponse;
  97. HTTP_SUB_ERROR _subError;
  98. //
  99. // Buffer to store any strings for header values/names which are
  100. // referenced in the _ulHttpResponse
  101. //
  102. CHUNK_BUFFER _HeaderBuffer;
  103. HTTP_UNKNOWN_HEADER _rgUnknownHeaders[ W3_RESPONSE_INLINE_HEADERS ];
  104. BUFFER _bufUnknownHeaders;
  105. //
  106. // Buffer to store chunk data structures referenced in calls
  107. // to UlSendHttpResponse or UlSendEntityBody
  108. //
  109. HTTP_DATA_CHUNK _rgChunks[ W3_RESPONSE_INLINE_CHUNKS ];
  110. BUFFER _bufChunks;
  111. USHORT _cChunks;
  112. ULONGLONG _cbContentLength;
  113. //
  114. // Has this response been touched at all?
  115. //
  116. BOOL _fResponseTouched;
  117. //
  118. // Has a response been sent
  119. //
  120. BOOL _fResponseSent;
  121. //
  122. // Some buffers used when in raw mode
  123. //
  124. STRA _strRawCoreHeaders;
  125. CHAR _achRawCoreHeaders[ 200 ];
  126. //
  127. // Are we in raw mode or parsed mode?
  128. //
  129. W3_RESPONSE_MODE _responseMode;
  130. //
  131. // Does an ISAPI expect to complete headers with WriteClient()
  132. //
  133. BOOL _fIncompleteHeaders;
  134. //
  135. // Which chunk is the first of actual entity
  136. //
  137. USHORT _cFirstEntityChunk;
  138. //
  139. // Manage where we are as it relates to chunks to be filtered
  140. //
  141. USHORT _cCurrentChunk;
  142. ULONGLONG _cbCurrentOffset;
  143. BUFFER _bufRawChunk;
  144. DWORD _dwSendFlags;
  145. BOOL _fHandleCompletion;
  146. DWORD _cbTotalCompletion;
  147. static DWORD sm_dwSendRawDataBufferSize;
  148. HRESULT
  149. BuildRawCoreHeaders(
  150. VOID
  151. );
  152. HRESULT
  153. SwitchToRawMode(
  154. CHAR * pszAdditionalHeaders,
  155. DWORD cchAdditionalHeaders
  156. );
  157. HRESULT
  158. ParseHeadersFromStream(
  159. CHAR * pszStream
  160. );
  161. HRESULT
  162. InsertDataChunk(
  163. HTTP_DATA_CHUNK * pNewChunk,
  164. LONG cPosition
  165. );
  166. HTTP_DATA_CHUNK *
  167. QueryChunks(
  168. VOID
  169. )
  170. {
  171. return (HTTP_DATA_CHUNK*) _bufChunks.QueryPtr();
  172. }
  173. VOID
  174. Reset(
  175. VOID
  176. );
  177. public:
  178. W3_RESPONSE()
  179. : _bufUnknownHeaders( (BYTE*) _rgUnknownHeaders,
  180. sizeof( _rgUnknownHeaders ) ),
  181. _bufChunks( (BYTE*) _rgChunks,
  182. sizeof( _rgChunks ) ),
  183. _strRawCoreHeaders( _achRawCoreHeaders, sizeof( _achRawCoreHeaders ) )
  184. {
  185. Reset();
  186. _dwSignature = W3_RESPONSE_SIGNATURE;
  187. }
  188. ~W3_RESPONSE()
  189. {
  190. _dwSignature = W3_RESPONSE_SIGNATURE_FREE;
  191. }
  192. static
  193. HRESULT
  194. Initialize(
  195. VOID
  196. );
  197. static
  198. VOID
  199. Terminate(
  200. VOID
  201. );
  202. BOOL
  203. CheckSignature(
  204. VOID
  205. ) const
  206. {
  207. return _dwSignature == W3_RESPONSE_SIGNATURE;
  208. }
  209. //
  210. // Core header adding/deleting functions
  211. //
  212. HRESULT
  213. SwitchToParsedMode(
  214. VOID
  215. );
  216. HRESULT
  217. DeleteHeader(
  218. CHAR * pszHeaderName
  219. );
  220. HRESULT
  221. SetHeader(
  222. DWORD headerIndex,
  223. CHAR * pszHeaderValue,
  224. USHORT cchHeaderValue,
  225. BOOL fAppend = FALSE
  226. );
  227. HRESULT
  228. SetHeaderByReference(
  229. DWORD headerIndex,
  230. CHAR * pszHeaderValue,
  231. USHORT cchHeaderValue,
  232. BOOL fForceParsedMode = FALSE
  233. );
  234. HRESULT
  235. SetHeader(
  236. CHAR * pszHeaderName,
  237. USHORT cchHeaderName,
  238. CHAR * pszHeaderValue,
  239. USHORT cchHeaderValue,
  240. BOOL fAppend = FALSE,
  241. BOOL fForceParsedMode = FALSE,
  242. BOOL fAlwaysAddUnknown = FALSE,
  243. BOOL fAppendAsDupHeader = FALSE
  244. );
  245. //
  246. // Some friendly SetHeader helpers
  247. //
  248. const CHAR *
  249. GetHeader(
  250. DWORD headerIndex
  251. )
  252. {
  253. HRESULT hr;
  254. if ( _responseMode == RESPONSE_MODE_RAW )
  255. {
  256. hr = SwitchToParsedMode();
  257. if ( FAILED( hr ) )
  258. {
  259. return NULL;
  260. }
  261. }
  262. DBG_ASSERT( _responseMode == RESPONSE_MODE_PARSED );
  263. DBG_ASSERT(headerIndex < HttpHeaderResponseMaximum);
  264. return _ulHttpResponse.Headers.KnownHeaders[headerIndex].pRawValue;
  265. }
  266. HRESULT
  267. GetHeader(
  268. CHAR * pszHeaderName,
  269. STRA * pstrHeaderValue
  270. );
  271. VOID
  272. ClearHeaders(
  273. VOID
  274. );
  275. //
  276. // Chunk management
  277. //
  278. HRESULT
  279. AddFileHandleChunk(
  280. HANDLE hFile,
  281. ULONGLONG cbOffset,
  282. ULONGLONG cbLength
  283. );
  284. HRESULT
  285. AddMemoryChunkByReference(
  286. PVOID pvBuffer,
  287. DWORD cbBuffer
  288. );
  289. HRESULT
  290. AddFragmentChunk(
  291. WCHAR * pszFragmentName,
  292. USHORT dwNameLength
  293. );
  294. HRESULT
  295. Clear(
  296. BOOL fClearEntityOnly = FALSE
  297. );
  298. HRESULT
  299. GenerateAutomaticHeaders(
  300. W3_CONTEXT * pW3Context,
  301. DWORD * pdwFlags
  302. );
  303. //
  304. // ULATQ send APIs
  305. //
  306. HRESULT
  307. SendResponse(
  308. W3_CONTEXT * pW3Context,
  309. DWORD dwResponseFlags,
  310. HTTP_CACHE_POLICY *pCachePolicy,
  311. DWORD * pcbSent
  312. );
  313. HRESULT
  314. SendEntity(
  315. W3_CONTEXT * pW3Context,
  316. DWORD dwResponseFlags,
  317. DWORD * pcbSent
  318. );
  319. HRESULT
  320. ResumeResponseTransfer(
  321. W3_CONTEXT * pW3Context,
  322. BOOL fCompletion,
  323. DWORD cbCompletion,
  324. DWORD dwCompletionStatus,
  325. BOOL fAsync,
  326. DWORD * pcbSent
  327. );
  328. HRESULT
  329. OnIoCompletion(
  330. W3_CONTEXT * pW3Context,
  331. DWORD cbCompletion,
  332. DWORD dwCompletionStatus
  333. )
  334. {
  335. DWORD cbSent;
  336. if ( _fHandleCompletion == FALSE )
  337. {
  338. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  339. }
  340. else
  341. {
  342. ResumeResponseTransfer( pW3Context,
  343. TRUE,
  344. cbCompletion,
  345. dwCompletionStatus,
  346. TRUE,
  347. &cbSent );
  348. return NO_ERROR;
  349. }
  350. }
  351. //
  352. // Setup and send an ISAPI response
  353. //
  354. HRESULT
  355. FilterWriteClient(
  356. W3_CONTEXT * pW3Context,
  357. PVOID pvData,
  358. DWORD cbData
  359. );
  360. HRESULT
  361. BuildResponseFromIsapi(
  362. W3_CONTEXT * pW3Context,
  363. LPSTR pszStatusLine,
  364. LPSTR pszHeaderStream,
  365. DWORD cchHeaderStream
  366. );
  367. HRESULT
  368. BuildStatusFromIsapi(
  369. LPSTR pszStatusLine
  370. );
  371. HRESULT
  372. AppendResponseHeaders(
  373. STRA & strHeaders
  374. );
  375. //
  376. // Get the raw response stream for use by raw data filter
  377. //
  378. HRESULT
  379. GetRawResponseStream(
  380. STRA * pstrResponseStream
  381. );
  382. //
  383. // Status code and reason
  384. //
  385. VOID
  386. SetStatus(
  387. HTTP_STATUS & httpStatus,
  388. HTTP_SUB_ERROR & httpSubError = HttpNoSubError
  389. )
  390. {
  391. _ulHttpResponse.StatusCode = httpStatus.statusCode;
  392. _ulHttpResponse.pReason = httpStatus.pszReason;
  393. _ulHttpResponse.ReasonLength = httpStatus.cbReason;
  394. _subError = httpSubError;
  395. _fResponseTouched = TRUE;
  396. }
  397. VOID
  398. SetStatusCode(
  399. USHORT StatusCode
  400. )
  401. {
  402. _ulHttpResponse.StatusCode = StatusCode;
  403. }
  404. VOID
  405. GetStatus(
  406. HTTP_STATUS *phttpStatus
  407. )
  408. {
  409. phttpStatus->statusCode = _ulHttpResponse.StatusCode;
  410. phttpStatus->pszReason = (PSTR) _ulHttpResponse.pReason;
  411. phttpStatus->cbReason = _ulHttpResponse.ReasonLength;
  412. }
  413. HRESULT
  414. SetStatus(
  415. USHORT StatusCode,
  416. STRA & strReason,
  417. HTTP_SUB_ERROR & subError = HttpNoSubError
  418. );
  419. HRESULT
  420. GetStatusLine(
  421. STRA * pstrStatusLine
  422. );
  423. USHORT
  424. QueryStatusCode(
  425. VOID
  426. ) const
  427. {
  428. return _ulHttpResponse.StatusCode;
  429. }
  430. HRESULT
  431. QuerySubError(
  432. HTTP_SUB_ERROR * pSubError
  433. )
  434. {
  435. if ( pSubError == NULL )
  436. {
  437. DBG_ASSERT( FALSE );
  438. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  439. }
  440. pSubError->mdSubError = _subError.mdSubError;
  441. pSubError->dwStringId = _subError.dwStringId;
  442. return NO_ERROR;
  443. }
  444. VOID
  445. SetSubError(
  446. HTTP_SUB_ERROR * pSubError
  447. )
  448. {
  449. if ( pSubError == NULL )
  450. {
  451. DBG_ASSERT( FALSE );
  452. return;
  453. }
  454. _subError.mdSubError = pSubError->mdSubError;
  455. _subError.dwStringId = pSubError->dwStringId;
  456. }
  457. VOID
  458. FindStringId(
  459. VOID
  460. );
  461. //
  462. // Touched state. Used to determine whether the system needs to send
  463. // an error (500) response due to not state handler creating a response
  464. //
  465. BOOL
  466. QueryResponseTouched(
  467. VOID
  468. ) const
  469. {
  470. return _fResponseTouched;
  471. }
  472. BOOL
  473. QueryResponseSent(
  474. VOID
  475. ) const
  476. {
  477. return _fResponseSent;
  478. }
  479. ULONGLONG
  480. QueryContentLength(
  481. VOID
  482. ) const
  483. {
  484. return _cbContentLength;
  485. }
  486. //
  487. // Is there any entity in this response (used by custom error logic)
  488. //
  489. BOOL
  490. QueryEntityExists(
  491. VOID
  492. )
  493. {
  494. return _cChunks > 0 && _cChunks > _cFirstEntityChunk;
  495. }
  496. };
  497. #endif