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.

277 lines
6.5 KiB

  1. /*
  2. * R G I T E R . H
  3. *
  4. * Range iterator
  5. */
  6. #ifndef _EX_RGITER_H_
  7. #define _EX_RGITER_H_
  8. #pragma warning(disable:4200) // zero-sized array
  9. // Ranges --------------------------------------------------------------------
  10. //
  11. enum {
  12. RANGE_TOTAL_UNKNOWN = 0xFFFFFFFF,
  13. RANGE_NOT_PRESENT = 0xFFFFFFFF,
  14. RANGE_UNKNOWN = 0,
  15. RANGE_ROW,
  16. RANGE_URL,
  17. RANGE_FIND
  18. };
  19. // Range Items ---------------------------------------------------------------
  20. //
  21. // There are two different range item formats.
  22. //
  23. // row/byte ranges = DWRGITEM;
  24. // url/find ranges = SZRGITEM;
  25. //
  26. typedef struct _dwrgitem
  27. {
  28. DWORD dwFirst; // first row/byte of a range
  29. DWORD dwLast; // last row/byte of a range
  30. } DWRGITEM;
  31. typedef struct _szrgitem
  32. {
  33. LONG lcRows; // count of rows to return
  34. DWORD cb; // length, in bytes of item including NULL and padding
  35. WCHAR wsz[]; // item padded out to align as needed
  36. } SZRGITEM;
  37. typedef struct _rgitem
  38. {
  39. DWORD uRT; // range type
  40. SCODE sc;
  41. union {
  42. DWRGITEM dwrgi; // item for byte and row ranges
  43. SZRGITEM szrgi; // item for url and find ranges
  44. };
  45. } RGITEM, *PRGITEM;
  46. inline
  47. DWORD CbRangeItem (const RGITEM * prgi)
  48. {
  49. Assert (prgi);
  50. DWORD cb = sizeof(RGITEM);
  51. if ((RANGE_URL == prgi->uRT) || (RANGE_FIND == prgi->uRT))
  52. cb += prgi->szrgi.cb;
  53. return cb;
  54. }
  55. // Range Classes -------------------------------------------------------------
  56. //
  57. // There are two classes for dealing with ranges. A class that constructs the
  58. // range item array (a range parser), and a class that iterates over a range
  59. // array.
  60. //
  61. // It is important to note that the CRangeParser only is used to parse the HTTP
  62. // "Range" header. This header does not support the syntax of url and/or find
  63. // ranges, so the parser only builds items of type "bytes" and/or "rows".
  64. //
  65. // Since both of these share the same format (DWRGITEM), and it is a fixed size,
  66. // there are some simplifying assumptions that can be made without adding too
  67. // much complexity to the parser.
  68. //
  69. // Both parser and iterator share a common base...
  70. //
  71. class CRangeBase
  72. {
  73. protected:
  74. // Count of ranges parsed out.
  75. //
  76. DWORD m_cRGList;
  77. // Index of the range that is currently being parsed and/or processed
  78. //
  79. DWORD m_iCur;
  80. RGITEM * m_prgi;
  81. // An array of ranges of size m_cRCList. As noted above, this array is
  82. // built up from items that were parsed from the HTTP header, and can
  83. // then be assumed to be a fixed size based on the count of ranges. This
  84. // is an important aspect of the CRangeParser.
  85. //
  86. auto_heap_ptr<BYTE> m_pbData;
  87. DWORD m_cbSize;
  88. // Collapsing unknown ranges
  89. //
  90. void CollapseUnknown();
  91. // NOT IMPLEMENTED
  92. //
  93. CRangeBase& operator=( const CRangeBase& );
  94. CRangeBase( const CRangeBase& );
  95. public:
  96. ~CRangeBase();
  97. CRangeBase()
  98. : m_cRGList(0),
  99. m_cbSize(0),
  100. m_iCur(0),
  101. m_prgi(0)
  102. {
  103. }
  104. // Range fixup. There are some cases where ranges need to be fixed up
  105. // to match the actual amount of bytes/rows available. Note that this
  106. // only impacts byte and/or row ranges.
  107. //
  108. SCODE ScFixupRanges (DWORD dwCount);
  109. // Advances through the rangGet the next range.
  110. //
  111. const RGITEM * PrgiNextRange();
  112. // Rewind to the first range.
  113. //
  114. void Rewind()
  115. {
  116. m_iCur = 0;
  117. m_prgi = NULL;
  118. }
  119. // Check for more ranges
  120. //
  121. BOOL FMoreRanges () const { return m_iCur < m_cRGList; }
  122. // Check if a range present or not
  123. //
  124. BOOL FRangePresent (DWORD dw) const { return RANGE_NOT_PRESENT != dw; }
  125. // Gets the total number of ranges.
  126. //
  127. ULONG UlTotalRanges() const { return m_cRGList; }
  128. // Return the range array, with count and size.
  129. //
  130. RGITEM * PrgRangeArray(
  131. /* [out] */ ULONG * pulCount,
  132. /* [out] */ ULONG * pulSize,
  133. /* [in] */ BOOL fTakeOwnership)
  134. {
  135. Assert (pulCount);
  136. Assert (pulSize);
  137. RGITEM * prgi = reinterpret_cast<RGITEM*>
  138. (fTakeOwnership ? m_pbData.relinquish() : m_pbData.get());
  139. *pulCount = m_cRGList;
  140. *pulSize = m_cbSize;
  141. return prgi;
  142. }
  143. };
  144. class CRangeParser : public CRangeBase
  145. {
  146. private:
  147. // NOT IMPLEMENTED
  148. //
  149. CRangeParser& operator=( const CRangeParser& );
  150. CRangeParser( const CRangeParser& );
  151. public:
  152. CRangeParser() {}
  153. ~CRangeParser();
  154. // Takes a range header and builds an array of ranges. Calls
  155. // ScParseRangeHdr() to perform syntax checking, then validates
  156. // the ranges against the entity size.
  157. //
  158. SCODE ScParseByteRangeHdr (LPCWSTR pwszRgHeader, DWORD dwSize);
  159. // Take a range header and builds an array of ranges. Performs
  160. // syntax checking.
  161. //
  162. SCODE ScParseRangeHdr (LPCWSTR pwszRgHeader, LPCWSTR pwszRangeUnit);
  163. };
  164. class CRangeIter : public CRangeBase
  165. {
  166. private:
  167. // NOT IMPLEMENTED
  168. //
  169. CRangeIter& operator=( const CRangeIter& );
  170. CRangeIter( const CRangeIter& );
  171. public:
  172. CRangeIter() {}
  173. ~CRangeIter();
  174. // Initialize a range iteration object based off of an existing
  175. // range data blob. In this case, the blob is copied and not consumed
  176. // by the call.
  177. //
  178. SCODE ScInit (ULONG cRGList, const RGITEM * prgRGList, ULONG cbSize);
  179. // Initialize a range iteration object based off of an existing
  180. // range data blob. In this case, the blob is consumed by the new
  181. // object.
  182. //
  183. SCODE ScInit (CRangeParser& crp)
  184. {
  185. RGITEM * prgi = crp.PrgRangeArray (&m_cRGList,
  186. &m_cbSize,
  187. TRUE /* fTakeOwnership */);
  188. m_pbData = reinterpret_cast<BYTE*>(prgi);
  189. // Rewind all the state.
  190. //
  191. Rewind();
  192. return S_OK;
  193. }
  194. };
  195. // Range Parsing -------------------------------------------------------------
  196. //
  197. SCODE
  198. ScParseOneWideRange (
  199. /* [in] */ LPCWSTR pwsz,
  200. /* [out] */ DWORD * pdwStart,
  201. /* [out] */ DWORD * pdwEnd);
  202. // Range support -------------------------------------------------------------
  203. //
  204. // Helper function to tell whether a range is a special range (0,0xffffffff)
  205. // which is used to represent the rows(bytes)=-n range on a zero sized response
  206. // body.
  207. //
  208. inline
  209. BOOL FSpecialRangeForZeroSizedBody (RGITEM * prgItem)
  210. {
  211. Assert (prgItem);
  212. return ((RANGE_ROW == prgItem->uRT)
  213. && (0 == prgItem->dwrgi.dwFirst)
  214. && (RANGE_NOT_PRESENT == prgItem->dwrgi.dwLast));
  215. }
  216. // Range emitting ------------------------------------------------------------
  217. //
  218. SCODE ScGenerateContentRange (
  219. /* [in] */ LPCSTR pszRangeUnit,
  220. /* [in] */ const RGITEM * prgRGList,
  221. /* [in] */ ULONG cRanges,
  222. /* [in] */ ULONG cbRanges,
  223. /* [in] */ ULONG ulTotal,
  224. /* [out] */ LPSTR *ppszContentRange);
  225. #endif // _EX_RGITER_H_