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.

426 lines
11 KiB

  1. #include "oleds.hxx"
  2. #if (!defined(BUILD_FOR_NT40))
  3. #include "atl.h"
  4. #include "cstream.h"
  5. /* -------------------------------------------------------------------------
  6. CStreamMem
  7. ------------------------------------------------------------------------- */
  8. //+---------------------------------------------------------------------------
  9. //
  10. // Function: CStreamMem::CStreamMem (constructor)
  11. //
  12. // Synopsis: constructs a CStreamMem object
  13. //
  14. //----------------------------------------------------------------------------
  15. CStreamMem::CStreamMem(void)
  16. {
  17. m_pvData = NULL;
  18. m_cbBufferSize= 0;
  19. m_cbSeek = 0;
  20. memset(&m_statstg,0,sizeof(STATSTG));
  21. m_statstg.type = STGTY_STREAM;
  22. GetSystemTimeAsFileTime(&m_statstg.ctime);
  23. m_hRow = DB_NULL_HROW;
  24. m_fExternalData = true;
  25. }
  26. //+---------------------------------------------------------------------------
  27. //
  28. // Function: CStreamMem::~CStreamMem (destructor)
  29. //
  30. // Synopsis: destructs a CStreamMem object
  31. //
  32. //----------------------------------------------------------------------------
  33. CStreamMem::~CStreamMem(void)
  34. {
  35. }
  36. //+---------------------------------------------------------------------------
  37. //
  38. // Function: CStreamMem::Initialize
  39. //
  40. // Synopsis: Initializes a CStreamMem object
  41. //
  42. // Parameters: pVar Variant of type VT_UI1 | VT_ARRAY containing the bytes
  43. // IRow * pointer to IRow interface
  44. // HROW handle to the row that is creating this stream
  45. //
  46. // Returns: HRESULT
  47. //
  48. //----------------------------------------------------------------------------
  49. HRESULT CStreamMem::Initialize(VARIANT *pVar, IRow* pSourceRow, HROW hRow)
  50. {
  51. ADsAssert (pVar && pSourceRow);
  52. //ADSI uses VT_ARRAY|VT_UI1 for binary data. Make sure we have proper type.
  53. ADsAssert(V_VT(pVar) == (VT_ARRAY | VT_UI1));
  54. HRESULT hr = NOERROR;
  55. auto_leave al(m_cs);
  56. SAFEARRAY *psa;
  57. UINT cDim;
  58. TRYBLOCK
  59. al.EnterCriticalSection();
  60. hr = m_pVar.Attach(pVar);
  61. BAIL_ON_FAILURE(hr);
  62. psa = V_ARRAY(pVar);
  63. cDim = SafeArrayGetDim(psa);
  64. if (cDim != 1)
  65. RRETURN(E_INVALIDARG);
  66. //Get bounds of safearray and determine size
  67. long lLBound, lUBound;
  68. hr = SafeArrayGetLBound(psa, cDim, &lLBound);
  69. BAIL_ON_FAILURE(hr);
  70. hr = SafeArrayGetUBound(psa, cDim, &lUBound);
  71. BAIL_ON_FAILURE(hr);
  72. m_cbBufferSize = lUBound - lLBound + 1;
  73. //Get a pointer to the actual byte data
  74. hr = SafeArrayAccessData(V_ARRAY(pVar), &m_pvData);
  75. BAIL_ON_FAILURE(hr);
  76. hr = SafeArrayUnaccessData(psa);
  77. BAIL_ON_FAILURE(hr);
  78. m_pSourceRow = pSourceRow;
  79. m_pSourceRow->AddRef();
  80. m_hRow = hRow;
  81. //Update stat structure
  82. m_statstg.cbSize.LowPart = m_cbBufferSize;
  83. GetSystemTimeAsFileTime(&m_statstg.mtime);
  84. CATCHBLOCKBAIL(hr)
  85. RRETURN(S_OK);
  86. error:
  87. RRETURN(hr);
  88. }
  89. //////////////////////////////////////////////////////////////////////////////
  90. // IStream
  91. //
  92. //+---------------------------------------------------------------------------
  93. //
  94. // Function: CStreamMem::Read
  95. //
  96. // Synopsis: Reads specified number of bytes from stream.
  97. //
  98. // For more info see IStream documentation.
  99. //----------------------------------------------------------------------------
  100. STDMETHODIMP CStreamMem::Read(
  101. void __RPC_FAR *pv,
  102. ULONG cb,
  103. ULONG __RPC_FAR *pcbRead)
  104. {
  105. if (pv == NULL)
  106. RRETURN(STG_E_INVALIDPOINTER);
  107. auto_leave al(m_cs);
  108. ULONG cbRead = 0;
  109. if( pcbRead != NULL )
  110. *pcbRead = 0;
  111. al.EnterCriticalSection();
  112. // anything to do?
  113. if( cb == 0 ||
  114. m_statstg.cbSize.LowPart == 0 ||
  115. m_cbSeek == m_statstg.cbSize.LowPart )
  116. RRETURN(NOERROR);
  117. // determine amount to copy
  118. cbRead = min(cb,m_statstg.cbSize.LowPart - m_cbSeek);
  119. if( cbRead > 0 )
  120. {
  121. // copy it
  122. CopyMemory(pv,(PBYTE)m_pvData + m_cbSeek,cbRead);
  123. // adjust seek pointer
  124. m_cbSeek += cbRead;
  125. }
  126. // update access time
  127. GetSystemTimeAsFileTime(&m_statstg.atime);
  128. if( pcbRead != NULL )
  129. *pcbRead = cbRead;
  130. RRETURN(NOERROR);
  131. }
  132. //+---------------------------------------------------------------------------
  133. //
  134. // Function: CStreamMem::Write
  135. //
  136. // Synopsis: Writes specified number of bytes to stream.
  137. //
  138. // For more info see IStream documentation.
  139. //----------------------------------------------------------------------------
  140. STDMETHODIMP CStreamMem::Write(
  141. const void __RPC_FAR *pv,
  142. ULONG cb,
  143. ULONG __RPC_FAR *pcbWritten)
  144. {
  145. //DS OLE DB provider is currently read-only.
  146. //It doesn't support writes on its streams.
  147. RRETURN(STG_E_ACCESSDENIED);
  148. }
  149. //+---------------------------------------------------------------------------
  150. //
  151. // Function: CStreamMem::Seek
  152. //
  153. // Synopsis: Sets the current read/write pointer to the given position.
  154. //
  155. // For more info see IStream documentation.
  156. //----------------------------------------------------------------------------
  157. STDMETHODIMP CStreamMem::Seek(
  158. LARGE_INTEGER dlibMove,
  159. DWORD dwOrigin,
  160. ULARGE_INTEGER __RPC_FAR *plibNewPosition)
  161. {
  162. auto_leave al(m_cs);
  163. // can we handle the seek?
  164. if( dlibMove.HighPart != 0 )
  165. RRETURN(STG_E_WRITEFAULT);
  166. al.EnterCriticalSection();
  167. // handle the seek request
  168. switch( dwOrigin)
  169. {
  170. case STREAM_SEEK_SET:
  171. if( dlibMove.LowPart > m_statstg.cbSize.LowPart )
  172. RRETURN(STG_E_INVALIDFUNCTION);
  173. m_cbSeek = dlibMove.LowPart;
  174. break;
  175. case STREAM_SEEK_CUR:
  176. if( dlibMove.LowPart + m_cbSeek > m_statstg.cbSize.LowPart )
  177. RRETURN(STG_E_INVALIDFUNCTION);
  178. m_cbSeek += (int)dlibMove.LowPart;
  179. break;
  180. case STREAM_SEEK_END:
  181. //We are read-only provider. Seeking past the end of stream
  182. //or prior to beginning of stream is not supported
  183. if ( int(dlibMove.LowPart) > 0 ||
  184. (int(dlibMove.LowPart) + int(m_statstg.cbSize.LowPart)) < 0
  185. )
  186. RRETURN(STG_E_INVALIDFUNCTION);
  187. m_cbSeek = m_statstg.cbSize.LowPart + (int)dlibMove.LowPart;
  188. break;
  189. }
  190. // return new seek position
  191. if( plibNewPosition )
  192. {
  193. plibNewPosition->HighPart = 0;
  194. plibNewPosition->LowPart = m_cbSeek;
  195. }
  196. RRETURN(NOERROR);
  197. }
  198. //+---------------------------------------------------------------------------
  199. //
  200. // Function: CStreamMem::SetSize
  201. //
  202. // Synopsis: Sets the size of the stream.
  203. //
  204. // For more info see IStream documentation.
  205. //----------------------------------------------------------------------------
  206. STDMETHODIMP CStreamMem::SetSize(
  207. ULARGE_INTEGER libNewSize)
  208. {
  209. //DS OLE DB provider is currently read-only.
  210. //It doesn't support writes on its streams.
  211. RRETURN(STG_E_ACCESSDENIED);
  212. }
  213. //+---------------------------------------------------------------------------
  214. //
  215. // Function: CStreamMem::CopyTo
  216. //
  217. // Synopsis: Copies specified number of bytes from this stream to another.
  218. //
  219. // For more info see IStream documentation.
  220. //----------------------------------------------------------------------------
  221. STDMETHODIMP CStreamMem::CopyTo(
  222. IStream __RPC_FAR *pstm,
  223. ULARGE_INTEGER cb,
  224. ULARGE_INTEGER __RPC_FAR *pcbRead,
  225. ULARGE_INTEGER __RPC_FAR *pcbWritten)
  226. {
  227. auto_leave al(m_cs);
  228. HRESULT hr = NOERROR;
  229. ULONG cbBytes = 0;
  230. ULONG cbWritten = 0;
  231. if( pstm == NULL )
  232. RRETURN(STG_E_INVALIDPOINTER);
  233. al.EnterCriticalSection();
  234. cbBytes = min(m_statstg.cbSize.LowPart - m_cbSeek,cb.LowPart);
  235. if( pcbRead )
  236. pcbRead->QuadPart = cbBytes;
  237. if( cbBytes == 0 )
  238. RRETURN(NOERROR);
  239. hr = pstm->Write((PBYTE)m_pvData + m_cbSeek,cbBytes,&cbWritten);
  240. if( pcbWritten )
  241. pcbWritten->QuadPart = cbWritten;
  242. RRETURN(hr);
  243. }
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Function: CStreamMem::Commit
  247. //
  248. // Synopsis: Makes changes to this stream permanent.
  249. // Note: This is a no-op since this stream is currently read-only.
  250. //
  251. // For more info see IStream documentation.
  252. //----------------------------------------------------------------------------
  253. STDMETHODIMP CStreamMem::Commit(
  254. DWORD grfCommitFlags)
  255. {
  256. RRETURN(S_OK);
  257. }
  258. //+---------------------------------------------------------------------------
  259. //
  260. // Function: CStreamMem::Revert
  261. //
  262. // Synopsis: Reverts changes to this stream.
  263. //
  264. // For more info see IStream documentation.
  265. //----------------------------------------------------------------------------
  266. STDMETHODIMP CStreamMem::Revert( void)
  267. {
  268. RRETURN(E_NOTIMPL);
  269. }
  270. //+---------------------------------------------------------------------------
  271. //
  272. // Function: CStreamMem::LockRegion
  273. //
  274. // Synopsis: Locks a specified number of bytes in the stream
  275. // starting from a given offset.
  276. //
  277. // For more info see IStream documentation.
  278. //----------------------------------------------------------------------------
  279. STDMETHODIMP CStreamMem::LockRegion(
  280. ULARGE_INTEGER libOffset,
  281. ULARGE_INTEGER cb,
  282. DWORD dwLockType)
  283. {
  284. RRETURN(E_NOTIMPL);
  285. }
  286. //+---------------------------------------------------------------------------
  287. //
  288. // Function: CStreamMem::UnlockRegion
  289. //
  290. // Synopsis: Unlocks a specified number of bytes in the stream
  291. // starting from a given offset.
  292. //
  293. // For more info see IStream documentation.
  294. //----------------------------------------------------------------------------
  295. STDMETHODIMP CStreamMem::UnlockRegion(
  296. ULARGE_INTEGER libOffset,
  297. ULARGE_INTEGER cb,
  298. DWORD dwLockType)
  299. {
  300. RRETURN(E_NOTIMPL);
  301. }
  302. //+---------------------------------------------------------------------------
  303. //
  304. // Function: CStreamMem::Stat
  305. //
  306. // Synopsis: Gets information about the stream: size, modification time etc.
  307. //
  308. // For more info see IStream documentation.
  309. //----------------------------------------------------------------------------
  310. STDMETHODIMP CStreamMem::Stat(
  311. STATSTG __RPC_FAR *pstatstg,
  312. DWORD grfStatFlag)
  313. {
  314. auto_leave al(m_cs);
  315. if( !pstatstg )
  316. RRETURN(STG_E_INVALIDPOINTER);
  317. al.EnterCriticalSection();
  318. memcpy(pstatstg,&m_statstg,sizeof(STATSTG));
  319. al.LeaveCriticalSection();
  320. RRETURN(NOERROR);
  321. }
  322. //+---------------------------------------------------------------------------
  323. //
  324. // Function: CStreamMem::Clone
  325. //
  326. // Synopsis: Creates a new stream object which references the same bytes
  327. // but with its own seek pointer.
  328. //
  329. // For more info see IStream documentation.
  330. //----------------------------------------------------------------------------
  331. STDMETHODIMP CStreamMem::Clone(
  332. IStream __RPC_FAR *__RPC_FAR *ppstm)
  333. {
  334. RRETURN(E_NOTIMPL);
  335. }
  336. ///////////////////////////////////////////////////////////////////////////////
  337. //IGetSourceRow
  338. //
  339. //+---------------------------------------------------------------------------
  340. //
  341. // Function: CStreamMem::GetSourceRow
  342. //
  343. // Synopsis: Gets the requested interface on the row object that originaly
  344. // created this stream.
  345. //
  346. // For more info see IGetSourceRow in OLE DB 2.5 documentation.
  347. //----------------------------------------------------------------------------
  348. STDMETHODIMP CStreamMem::GetSourceRow(REFIID riid, IUnknown **ppRow)
  349. {
  350. auto_leave al(m_cs);
  351. al.EnterCriticalSection();
  352. if (m_pSourceRow.get() == NULL)
  353. {
  354. *ppRow = NULL;
  355. RRETURN(DB_E_NOSOURCEOBJECT);
  356. }
  357. HRESULT hr = m_pSourceRow->QueryInterface(riid, (void **)ppRow);
  358. if (FAILED(hr))
  359. RRETURN(E_NOINTERFACE);
  360. RRETURN(S_OK);
  361. }
  362. #endif