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.

458 lines
8.1 KiB

  1. //
  2. // loadimag.cpp
  3. //
  4. // implementation of the CBmpStream class
  5. //
  6. #include "stdafx.h"
  7. #include "bmpstrm.h"
  8. #include "imaging.h"
  9. //////////////////////////////////////////////////////////////////////////
  10. //
  11. //
  12. //
  13. CBmpStream::CBmpStream()
  14. {
  15. m_cRef = 1;
  16. m_hBuffer = 0;
  17. m_nSize = 0;
  18. m_nPosition = 0;
  19. }
  20. //////////////////////////////////////////////////////////////////////////
  21. //
  22. //
  23. //
  24. CBmpStream::~CBmpStream()
  25. {
  26. }
  27. //////////////////////////////////////////////////////////////////////////
  28. //
  29. //
  30. //
  31. HRESULT CBmpStream::Create(CBmpStream **ppvObject)
  32. {
  33. if (ppvObject == 0)
  34. {
  35. return E_POINTER;
  36. }
  37. TRY
  38. {
  39. *ppvObject = new CBmpStream;
  40. }
  41. CATCH(CMemoryException, e)
  42. {
  43. *ppvObject = 0;
  44. }
  45. END_CATCH
  46. if (*ppvObject == 0)
  47. {
  48. return E_OUTOFMEMORY;
  49. }
  50. return S_OK;
  51. }
  52. //////////////////////////////////////////////////////////////////////////
  53. //
  54. //
  55. //
  56. HGLOBAL CBmpStream::GetBuffer()
  57. {
  58. return m_hBuffer;
  59. }
  60. //////////////////////////////////////////////////////////////////////////
  61. //
  62. //
  63. //
  64. VOID CBmpStream::SetBuffer(HGLOBAL hBuffer, DWORD dwSize, DWORD dwOffBits)
  65. {
  66. m_hBuffer = hBuffer;
  67. m_nSize = dwSize;
  68. m_nPosition = 0;
  69. if (dwOffBits == 0)
  70. {
  71. PBYTE pBuffer = (PBYTE) GlobalLock(m_hBuffer);
  72. if (pBuffer)
  73. {
  74. dwOffBits = FindDibOffBits(pBuffer);
  75. GlobalUnlock(m_hBuffer);
  76. }
  77. }
  78. m_Header.bfType = MAKEWORD('B', 'M');
  79. m_Header.bfSize = sizeof(BITMAPFILEHEADER) + dwSize;
  80. m_Header.bfReserved1 = 0;
  81. m_Header.bfReserved2 = 0;
  82. m_Header.bfOffBits = sizeof(BITMAPFILEHEADER) + dwOffBits;
  83. }
  84. //////////////////////////////////////////////////////////////////////////
  85. //
  86. //
  87. //
  88. VOID CBmpStream::FreeBuffer()
  89. {
  90. if (m_hBuffer)
  91. {
  92. GlobalFree(m_hBuffer);
  93. m_hBuffer = 0;
  94. m_nSize = 0;
  95. m_nPosition = 0;
  96. }
  97. }
  98. //////////////////////////////////////////////////////////////////////////
  99. //
  100. //
  101. //
  102. HRESULT CBmpStream::ReAllocBuffer(SIZE_T dwBytes)
  103. {
  104. HGLOBAL hBuffer;
  105. if (m_hBuffer == 0)
  106. {
  107. hBuffer = GlobalAlloc(GMEM_MOVEABLE, dwBytes);
  108. }
  109. else
  110. {
  111. hBuffer = GlobalReAlloc(m_hBuffer, dwBytes, 0);
  112. }
  113. if (hBuffer == 0)
  114. {
  115. return HRESULT_FROM_WIN32(GetLastError());
  116. }
  117. m_hBuffer = hBuffer;
  118. m_nSize = dwBytes;
  119. return S_OK;
  120. }
  121. //////////////////////////////////////////////////////////////////////////
  122. //
  123. //
  124. //
  125. STDMETHODIMP CBmpStream::QueryInterface(REFIID riid, void **ppvObject)
  126. {
  127. if (ppvObject == 0)
  128. {
  129. return E_POINTER;
  130. }
  131. if (riid == IID_IUnknown)
  132. {
  133. AddRef();
  134. *ppvObject = (IUnknown*) this;
  135. return S_OK;
  136. }
  137. if (riid == IID_IStream)
  138. {
  139. AddRef();
  140. *ppvObject = (IStream *) this;
  141. return S_OK;
  142. }
  143. *ppvObject = 0;
  144. return E_NOINTERFACE;
  145. }
  146. //////////////////////////////////////////////////////////////////////////
  147. //
  148. //
  149. //
  150. STDMETHODIMP_(ULONG) CBmpStream::AddRef()
  151. {
  152. return InterlockedIncrement(&m_cRef);
  153. }
  154. //////////////////////////////////////////////////////////////////////////
  155. //
  156. //
  157. //
  158. STDMETHODIMP_(ULONG) CBmpStream::Release()
  159. {
  160. LONG cRef = InterlockedDecrement(&m_cRef);
  161. if (cRef == 0)
  162. {
  163. delete this;
  164. }
  165. return cRef;
  166. }
  167. //////////////////////////////////////////////////////////////////////////
  168. //
  169. //
  170. //
  171. STDMETHODIMP CBmpStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
  172. {
  173. if (pcbRead)
  174. {
  175. *pcbRead = 0;
  176. }
  177. if (m_nPosition > sizeof(m_Header) + m_nSize)
  178. {
  179. return S_FALSE;
  180. }
  181. if (cb == 0)
  182. {
  183. return S_OK;
  184. }
  185. if (cb > sizeof(m_Header) + m_nSize - m_nPosition)
  186. {
  187. cb = (ULONG) (sizeof(m_Header) + m_nSize - m_nPosition);
  188. }
  189. if (m_nPosition < sizeof(m_Header))
  190. {
  191. ULONG nBytesToReadInHeader = min(cb, sizeof(m_Header) - m_nPosition);
  192. CopyMemory(pv, (PBYTE) &m_Header + m_nPosition, nBytesToReadInHeader);
  193. pv = (PBYTE) pv + nBytesToReadInHeader;
  194. cb -= nBytesToReadInHeader;
  195. m_nPosition += nBytesToReadInHeader;
  196. if (pcbRead)
  197. {
  198. *pcbRead += nBytesToReadInHeader;
  199. }
  200. }
  201. if (cb > 0)
  202. {
  203. PBYTE pBuffer = (PBYTE) GlobalLock(m_hBuffer);
  204. if (pBuffer == 0)
  205. {
  206. return HRESULT_FROM_WIN32(GetLastError());
  207. }
  208. CopyMemory(pv, pBuffer + m_nPosition - sizeof(m_Header), cb);
  209. GlobalUnlock(m_hBuffer);
  210. m_nPosition += cb;
  211. if (pcbRead)
  212. {
  213. *pcbRead += cb;
  214. }
  215. }
  216. return S_OK;
  217. }
  218. //////////////////////////////////////////////////////////////////////////
  219. //
  220. //
  221. //
  222. STDMETHODIMP CBmpStream::Write(const void *pv, ULONG cb, ULONG *pcbWritten)
  223. {
  224. if (pcbWritten)
  225. {
  226. *pcbWritten = 0;
  227. }
  228. if (cb == 0)
  229. {
  230. return S_OK;
  231. }
  232. if (m_nSize + sizeof(m_Header) < m_nPosition + cb)
  233. {
  234. HRESULT hr = ReAllocBuffer(m_nPosition + cb - sizeof(m_Header));
  235. if (hr != S_OK)
  236. {
  237. return hr;
  238. }
  239. }
  240. if (m_nPosition < sizeof(m_Header))
  241. {
  242. ULONG nBytesToWriteInHeader = min(cb, sizeof(m_Header) - m_nPosition);
  243. CopyMemory((PBYTE) &m_Header + m_nPosition, pv, nBytesToWriteInHeader);
  244. pv = (PBYTE) pv + nBytesToWriteInHeader;
  245. cb -= nBytesToWriteInHeader;
  246. m_nPosition += nBytesToWriteInHeader;
  247. if (pcbWritten)
  248. {
  249. *pcbWritten += nBytesToWriteInHeader;
  250. }
  251. }
  252. if (cb > 0)
  253. {
  254. PBYTE pBuffer = (PBYTE) GlobalLock(m_hBuffer);
  255. if (pBuffer == 0)
  256. {
  257. return HRESULT_FROM_WIN32(GetLastError());
  258. }
  259. CopyMemory(pBuffer + m_nPosition - sizeof(m_Header), pv, cb);
  260. GlobalUnlock(m_hBuffer);
  261. m_nPosition += cb;
  262. if (pcbWritten)
  263. {
  264. *pcbWritten += cb;
  265. }
  266. }
  267. return S_OK;
  268. }
  269. //////////////////////////////////////////////////////////////////////////
  270. //
  271. //
  272. //
  273. STDMETHODIMP CBmpStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
  274. {
  275. switch (dwOrigin)
  276. {
  277. case STREAM_SEEK_SET:
  278. m_nPosition = (SIZE_T) dlibMove.QuadPart;
  279. break;
  280. case STREAM_SEEK_CUR:
  281. m_nPosition += (SIZE_T) dlibMove.QuadPart;
  282. break;
  283. case STREAM_SEEK_END:
  284. m_nPosition = m_nSize - (SIZE_T) dlibMove.QuadPart;
  285. break;
  286. default:
  287. return E_INVALIDARG;
  288. }
  289. if (plibNewPosition)
  290. {
  291. plibNewPosition->QuadPart = m_nPosition;
  292. }
  293. return S_OK;
  294. }
  295. //////////////////////////////////////////////////////////////////////////
  296. //
  297. //
  298. //
  299. STDMETHODIMP CBmpStream::SetSize(ULARGE_INTEGER libNewSize)
  300. {
  301. return ReAllocBuffer((SIZE_T) libNewSize.QuadPart);
  302. }
  303. //////////////////////////////////////////////////////////////////////////
  304. //
  305. //
  306. //
  307. STDMETHODIMP CBmpStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
  308. {
  309. return E_NOTIMPL;
  310. }
  311. //////////////////////////////////////////////////////////////////////////
  312. //
  313. //
  314. //
  315. STDMETHODIMP CBmpStream::Commit(DWORD grfCommitFlags)
  316. {
  317. return E_NOTIMPL;
  318. }
  319. //////////////////////////////////////////////////////////////////////////
  320. //
  321. //
  322. //
  323. STDMETHODIMP CBmpStream::Revert()
  324. {
  325. return E_NOTIMPL;
  326. }
  327. //////////////////////////////////////////////////////////////////////////
  328. //
  329. //
  330. //
  331. STDMETHODIMP CBmpStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  332. {
  333. return E_NOTIMPL;
  334. }
  335. //////////////////////////////////////////////////////////////////////////
  336. //
  337. //
  338. //
  339. STDMETHODIMP CBmpStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  340. {
  341. return E_NOTIMPL;
  342. }
  343. //////////////////////////////////////////////////////////////////////////
  344. //
  345. //
  346. //
  347. STDMETHODIMP CBmpStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  348. {
  349. return E_NOTIMPL;
  350. }
  351. //////////////////////////////////////////////////////////////////////////
  352. //
  353. //
  354. //
  355. STDMETHODIMP CBmpStream::Clone(IStream **ppstm)
  356. {
  357. return E_NOTIMPL;
  358. }