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.

312 lines
6.3 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * dibstream.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Wrap an IStream interface around DIB data.
  12. *
  13. * Revision History:
  14. *
  15. * 07/01/1999 davidx
  16. * Created it.
  17. *
  18. \**************************************************************************/
  19. #ifndef _DIBSTREAM_HPP
  20. #define _DIBSTREAM_HPP
  21. // NOTE: This is not a thread-safe object.
  22. class DibStream : public IStream
  23. {
  24. public:
  25. // Constructor
  26. DibStream(const BITMAPINFO* bmi, const BYTE* bits)
  27. {
  28. ComRefCount = 1;
  29. CurrentPos = 0;
  30. DibBits = bits;
  31. ZeroMemory(HeaderBuffer, sizeof(HeaderBuffer));
  32. // Figure out the size of header information
  33. HeaderSize = sizeof(BITMAPINFOHEADER);
  34. const BITMAPINFOHEADER* bmih = &bmi->bmiHeader;
  35. ULONG n = bmih->biClrUsed;
  36. if (n == 0)
  37. {
  38. switch (bmih->biBitCount)
  39. {
  40. case 1:
  41. case 4:
  42. case 8:
  43. n = 1 << bmih->biBitCount;
  44. break;
  45. case 16:
  46. case 32:
  47. if (bmih->biCompression == BI_BITFIELDS)
  48. n = 3;
  49. break;
  50. }
  51. }
  52. HeaderSize += n * sizeof(RGBQUAD);
  53. memcpy(&HeaderBuffer[sizeof(BITMAPFILEHEADER)], bmi, HeaderSize);
  54. HeaderSize += sizeof(BITMAPFILEHEADER);
  55. // Figure out the size of bitmap data
  56. n = bmih->biSizeImage;
  57. if (n == 0 && bmih->biCompression == BI_RGB)
  58. {
  59. // Scanline is always DWORD-aligned
  60. n = ((bmih->biWidth * bmih->biBitCount) + 7) / 8;
  61. n = (n + 3) & ~3;
  62. n *= abs(bmih->biHeight);
  63. }
  64. TotalSize = HeaderSize + n;
  65. // Fix BMP file header information
  66. BITMAPFILEHEADER* fileHeader = (BITMAPFILEHEADER*) HeaderBuffer;
  67. fileHeader->bfType = 0x4D42;
  68. fileHeader->bfSize = TotalSize;
  69. fileHeader->bfOffBits = HeaderSize;
  70. }
  71. // Query interface
  72. STDMETHOD(QueryInterface)(REFIID riid, VOID** ppv)
  73. {
  74. if (riid == IID_IUnknown)
  75. *ppv = static_cast<IUnknown*>(this);
  76. else if (riid == IID_IStream)
  77. *ppv = static_cast<IStream*>(this);
  78. else
  79. {
  80. *ppv = NULL;
  81. return E_NOINTERFACE;
  82. }
  83. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  84. return S_OK;
  85. }
  86. // Increment reference count
  87. STDMETHOD_(ULONG, AddRef)(VOID)
  88. {
  89. return InterlockedIncrement(&ComRefCount);
  90. }
  91. // Decrement reference count
  92. STDMETHOD_(ULONG, Release)(VOID)
  93. {
  94. ULONG count = InterlockedDecrement(&ComRefCount);
  95. if (count == 0)
  96. delete this;
  97. return count;
  98. }
  99. // Read data
  100. STDMETHOD(Read)(
  101. VOID* buf,
  102. ULONG cb,
  103. ULONG* cbRead
  104. )
  105. {
  106. ULONG n = TotalSize - CurrentPos;
  107. if (cb > n)
  108. cb = n;
  109. if (CurrentPos >= HeaderSize)
  110. {
  111. // Read bitmap data
  112. memcpy(buf, DibBits + (CurrentPos - HeaderSize), cb);
  113. }
  114. else
  115. {
  116. // Read header data
  117. n = HeaderSize - CurrentPos;
  118. if (cb <= n)
  119. {
  120. memcpy(buf, &HeaderBuffer[CurrentPos], cb);
  121. }
  122. else
  123. {
  124. memcpy(buf, &HeaderBuffer[CurrentPos], n);
  125. memcpy((BYTE*) buf + n, DibBits, cb - n);
  126. }
  127. }
  128. CurrentPos += cb;
  129. *cbRead = cb;
  130. return S_OK;
  131. }
  132. // Change read pointer
  133. STDMETHOD(Seek)(
  134. LARGE_INTEGER offset,
  135. DWORD origin,
  136. ULARGE_INTEGER* newPos
  137. )
  138. {
  139. LONGLONG pos;
  140. switch (origin)
  141. {
  142. case STREAM_SEEK_SET:
  143. pos = offset.QuadPart;
  144. break;
  145. case STREAM_SEEK_END:
  146. pos = TotalSize;
  147. break;
  148. case STREAM_SEEK_CUR:
  149. pos = (LONGLONG) CurrentPos + offset.QuadPart;
  150. break;
  151. default:
  152. pos = -1;
  153. break;
  154. }
  155. if (pos < 0 || pos > TotalSize)
  156. return E_INVALIDARG;
  157. CurrentPos = (ULONG) pos;
  158. if (newPos)
  159. newPos->QuadPart = pos;
  160. return S_OK;
  161. }
  162. // Get information
  163. STDMETHOD(Stat)(
  164. STATSTG* statstg,
  165. DWORD statFlag
  166. )
  167. {
  168. ZeroMemory(statstg, sizeof(STATSTG));
  169. statstg->type = STGTY_STREAM;
  170. statstg->cbSize.QuadPart = TotalSize;
  171. statstg->grfMode = STGM_READ;
  172. return S_OK;
  173. }
  174. STDMETHOD(Write)(
  175. const VOID* buf,
  176. ULONG cb,
  177. ULONG* cbWritten
  178. )
  179. {
  180. return STG_E_ACCESSDENIED;
  181. }
  182. STDMETHOD(CopyTo)(
  183. IStream* stream,
  184. ULARGE_INTEGER cb,
  185. ULARGE_INTEGER* cbRead,
  186. ULARGE_INTEGER* cbWritten
  187. )
  188. {
  189. return E_NOTIMPL;
  190. }
  191. STDMETHOD(SetSize)(
  192. ULARGE_INTEGER newSize
  193. )
  194. {
  195. return E_NOTIMPL;
  196. }
  197. STDMETHOD(Commit)(
  198. DWORD commitFlags
  199. )
  200. {
  201. return S_OK;
  202. }
  203. STDMETHOD(Revert)()
  204. {
  205. return E_NOTIMPL;
  206. }
  207. STDMETHOD(LockRegion)(
  208. ULARGE_INTEGER offset,
  209. ULARGE_INTEGER cb,
  210. DWORD lockType
  211. )
  212. {
  213. return E_NOTIMPL;
  214. }
  215. STDMETHOD(UnlockRegion)(
  216. ULARGE_INTEGER offset,
  217. ULARGE_INTEGER cb,
  218. DWORD lockType
  219. )
  220. {
  221. return E_NOTIMPL;
  222. }
  223. STDMETHOD(Clone)(
  224. IStream** stream
  225. )
  226. {
  227. return E_NOTIMPL;
  228. }
  229. private:
  230. LONG ComRefCount;
  231. ULONG HeaderSize;
  232. ULONG TotalSize;
  233. ULONG CurrentPos;
  234. const BYTE* DibBits;
  235. // Large enough buffer for storing bitmap file header information
  236. BYTE HeaderBuffer[sizeof(BITMAPFILEHEADER) +
  237. sizeof(BITMAPINFOHEADER) +
  238. sizeof(RGBQUAD) * 256];
  239. };
  240. #endif // !_DIBSTREAM_HPP