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.

354 lines
6.4 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. #include "precomp.h"
  8. #include "buffer.h"
  9. #include "comutl.h"
  10. /************************************************************************
  11. CBuffer
  12. *************************************************************************/
  13. CBuffer::CBuffer( PBYTE pData, ULONG cData, BOOL bDelete )
  14. : m_pData(pData), m_cData(cData), m_bDelete(bDelete), m_iData(0), m_cRefs(0)
  15. {
  16. }
  17. CBuffer::~CBuffer()
  18. {
  19. if ( m_bDelete )
  20. {
  21. delete [] m_pData;
  22. }
  23. }
  24. CBuffer::CBuffer( const CBuffer& rOther )
  25. : m_pData(NULL), m_cData(0), m_bDelete(FALSE), m_iData(0), m_cRefs(0)
  26. {
  27. *this = rOther;
  28. }
  29. CBuffer& CBuffer::operator= ( const CBuffer& rOther )
  30. {
  31. EnsureSize( rOther.m_iData );
  32. memcpy( m_pData, rOther.m_pData, m_iData );
  33. return *this;
  34. }
  35. void CBuffer::EnsureSize( ULONG ulSize )
  36. {
  37. if ( ulSize <= m_cData )
  38. {
  39. return;
  40. }
  41. ULONG cData = m_cData*2 > ulSize ? m_cData*2 : ulSize + 256;
  42. BYTE* pData = new BYTE[cData];
  43. if ( pData == NULL )
  44. {
  45. throw CX_MemoryException();
  46. }
  47. memcpy( pData, m_pData, m_iData );
  48. if ( m_bDelete )
  49. {
  50. delete [] m_pData;
  51. }
  52. m_bDelete = TRUE;
  53. m_cData = cData;
  54. m_pData = pData;
  55. }
  56. HRESULT CBuffer::ReadLPWSTR( LPCWSTR& rwszStr )
  57. {
  58. HRESULT hr;
  59. ULONG cStr;
  60. hr = Read( &cStr, sizeof(DWORD), NULL );
  61. if ( hr != S_OK )
  62. {
  63. return hr;
  64. }
  65. if ( m_cData-m_iData < cStr )
  66. {
  67. return S_FALSE;
  68. }
  69. rwszStr = LPCWSTR(m_pData+m_iData);
  70. m_iData += cStr;
  71. return S_OK;
  72. }
  73. HRESULT CBuffer::WriteLPWSTR( LPCWSTR wszStr )
  74. {
  75. HRESULT hr;
  76. //
  77. // ensure that the packed string's length is divisible by sizeof WCHAR.
  78. // this makes it easier to ensure that all strings in the message are
  79. // at least aligned appropriately.
  80. //
  81. DWORD cStr = (wcslen(wszStr) + 1)*2; // in bytes
  82. DWORD cPad = cStr%2;
  83. DWORD cPackedStr = cStr + cPad;
  84. hr = Write( &cPackedStr, sizeof(DWORD), NULL );
  85. if ( FAILED(hr) )
  86. {
  87. return hr;
  88. }
  89. hr = Write( wszStr, cStr, NULL );
  90. if ( SUCCEEDED(hr) )
  91. {
  92. hr = Advance( cPad );
  93. }
  94. return hr;
  95. }
  96. ULONG CBuffer::AddRef()
  97. {
  98. return InterlockedIncrement( &m_cRefs );
  99. }
  100. ULONG CBuffer::Release()
  101. {
  102. ULONG cRefs = InterlockedDecrement( &m_cRefs );
  103. if ( cRefs == 0 )
  104. {
  105. delete this;
  106. }
  107. return cRefs;
  108. }
  109. STDMETHODIMP CBuffer::QueryInterface( REFIID riid, void** ppv )
  110. {
  111. *ppv = NULL;
  112. if ( riid==IID_IStream ||
  113. riid==IID_ISequentialStream ||
  114. riid==IID_IUnknown )
  115. {
  116. *ppv = (IStream*)this;
  117. AddRef();
  118. return S_OK;
  119. }
  120. return E_NOINTERFACE;
  121. }
  122. STDMETHODIMP CBuffer::Read( void *pv, ULONG cb, ULONG *pcbRead )
  123. {
  124. ULONG cRead = cb > m_cData-m_iData ? m_cData-m_iData : cb;
  125. memcpy( pv, m_pData + m_iData, cRead );
  126. if ( pcbRead != NULL )
  127. {
  128. *pcbRead = cRead;
  129. }
  130. m_iData += cRead;
  131. return cRead == cb ? S_OK : S_FALSE;
  132. }
  133. STDMETHODIMP CBuffer::Write( const void *pv, ULONG cb, ULONG *pcbWritten )
  134. {
  135. ENTER_API_CALL
  136. HRESULT hr;
  137. if ( pcbWritten != NULL )
  138. {
  139. *pcbWritten = 0;
  140. }
  141. EnsureSize( m_iData + cb );
  142. memcpy( m_pData + m_iData, pv, cb );
  143. m_iData += cb;
  144. if ( pcbWritten != NULL )
  145. {
  146. *pcbWritten = cb;
  147. }
  148. return S_OK;
  149. EXIT_API_CALL
  150. }
  151. STDMETHODIMP CBuffer::Seek( LARGE_INTEGER dlibMove,
  152. DWORD dwOrigin,
  153. ULARGE_INTEGER *plibNewPosition )
  154. {
  155. ENTER_API_CALL
  156. HRESULT hr;
  157. __int64 i64Data;
  158. __int64 i64Move = dlibMove.QuadPart;
  159. if ( plibNewPosition != NULL )
  160. {
  161. plibNewPosition->QuadPart = m_iData;
  162. }
  163. if ( dwOrigin == STREAM_SEEK_SET )
  164. {
  165. i64Data = 0;
  166. }
  167. else if ( dwOrigin == STREAM_SEEK_CUR )
  168. {
  169. i64Data = m_iData;
  170. }
  171. else if ( dwOrigin == STREAM_SEEK_END )
  172. {
  173. i64Data = m_cData;
  174. }
  175. else
  176. {
  177. return STG_E_INVALIDFUNCTION;
  178. }
  179. i64Data += i64Move;
  180. EnsureSize( ULONG(i64Data) );
  181. m_iData = ULONG(i64Data);
  182. if ( plibNewPosition != NULL )
  183. {
  184. plibNewPosition->QuadPart = i64Data;
  185. }
  186. return S_OK;
  187. EXIT_API_CALL
  188. }
  189. STDMETHODIMP CBuffer::SetSize( ULARGE_INTEGER libNewSize )
  190. {
  191. ENTER_API_CALL
  192. EnsureSize( libNewSize.LowPart );
  193. return S_OK;
  194. EXIT_API_CALL
  195. }
  196. STDMETHODIMP CBuffer::CopyTo( IStream *pstm,
  197. ULARGE_INTEGER cb,
  198. ULARGE_INTEGER *pcbRead,
  199. ULARGE_INTEGER *pcbWritten )
  200. {
  201. ENTER_API_CALL
  202. HRESULT hr;
  203. ULONG cRead, cWritten;
  204. if ( pcbRead != NULL )
  205. {
  206. pcbRead->QuadPart = 0;
  207. }
  208. cRead = cb.LowPart > m_cData-m_iData ? m_cData-m_iData : cb.LowPart;
  209. hr = pstm->Write( m_pData + m_iData, cRead, &cWritten );
  210. if ( pcbWritten != NULL )
  211. {
  212. pcbWritten->QuadPart = cWritten;
  213. }
  214. if ( FAILED(hr) )
  215. {
  216. return hr;
  217. }
  218. m_iData += cRead;
  219. if ( pcbRead != NULL )
  220. {
  221. pcbRead->QuadPart = cRead;
  222. }
  223. return hr;
  224. EXIT_API_CALL
  225. }
  226. STDMETHODIMP CBuffer::Stat( STATSTG* pstatstg, DWORD grfStatFlag )
  227. {
  228. if ( pstatstg == NULL )
  229. {
  230. return STG_E_INVALIDPOINTER;
  231. }
  232. ZeroMemory( pstatstg, sizeof(STATSTG) );
  233. pstatstg->cbSize.LowPart = m_cData;
  234. return S_OK;
  235. }
  236. STDMETHODIMP CBuffer::Clone( IStream **ppstm )
  237. {
  238. ENTER_API_CALL
  239. BYTE* pData = new BYTE[m_cData];
  240. if ( pData == NULL )
  241. {
  242. return E_OUTOFMEMORY;
  243. }
  244. CBuffer* pNew;
  245. try
  246. {
  247. pNew = new CBuffer( pData, m_cData );
  248. }
  249. catch( CX_MemoryException )
  250. {
  251. delete pData;
  252. throw;
  253. }
  254. if ( pNew == NULL ) // just in case we don't have a new which throws on OOM
  255. {
  256. delete pData;
  257. return E_OUTOFMEMORY;
  258. }
  259. pNew->m_iData = m_iData;
  260. return pNew->QueryInterface( IID_IStream, (void**)ppstm );
  261. EXIT_API_CALL
  262. }