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.

413 lines
9.3 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: actstrm.cxx
  4. //
  5. // Contents: code for providing a stream with an IBuffer interface
  6. // as well as providing marshalled interface data for
  7. // RPC.
  8. //
  9. // Classes: ActivationStream
  10. //
  11. // History: 30-Jan-93 Ricksa Created CXmitRpcStream
  12. // 04-Feb-98 Vinaykr ActivationStream
  13. //
  14. // Description: All requirements of CXmitRpcStream, plus the additional
  15. // requirement of being able to support a buffer interface
  16. // for activation custom marshalling.
  17. //--------------------------------------------------------------------
  18. #include <ole2int.h>
  19. #include <actstrm.hxx>
  20. HRESULT GetActivationStream(REFIID riid, void** ppv, DWORD size)
  21. {
  22. ActivationStream *st = new ActivationStream(size);
  23. if (st==NULL)
  24. return E_OUTOFMEMORY;
  25. return st->QueryInterface(riid, ppv);
  26. return S_OK;
  27. }
  28. STDMETHODIMP ActivationStream::QueryInterface(
  29. REFIID iidInterface,
  30. void FAR* FAR* ppvObj)
  31. {
  32. HRESULT hresult = S_OK;
  33. // We only support IUnknown and IStream
  34. if (IsEqualIID(iidInterface, IID_IUnknown) ||
  35. IsEqualIID(iidInterface, IID_IStream))
  36. {
  37. *ppvObj = (IStream*)this;
  38. AddRef();
  39. }
  40. else
  41. if (IsEqualIID(iidInterface, IID_IBuffer))
  42. {
  43. *ppvObj = (IBuffer*)this;
  44. AddRef();
  45. }
  46. else
  47. {
  48. *ppvObj = NULL;
  49. hresult = E_NOINTERFACE;
  50. }
  51. return hresult;
  52. }
  53. STDMETHODIMP_(ULONG) ActivationStream::AddRef(void)
  54. {
  55. Win4Assert((_clRefs != 0) && "ActivationStream::AddRef");
  56. InterlockedIncrement(&_clRefs);
  57. return _clRefs;
  58. }
  59. STDMETHODIMP_(ULONG) ActivationStream::Release(void)
  60. {
  61. Win4Assert((_clRefs != 0) && "ActivationStream::Release");
  62. if (InterlockedDecrement(&_clRefs) == 0)
  63. {
  64. delete this;
  65. return 0;
  66. }
  67. return _clRefs;
  68. }
  69. STDMETHODIMP ActivationStream::Read(
  70. VOID HUGEP* pv,
  71. ULONG cb,
  72. ULONG FAR* pcbRead)
  73. {
  74. HRESULT hresult = S_OK;
  75. if (pcbRead)
  76. {
  77. *pcbRead = 0L;
  78. }
  79. if (cb + _lOffset > _cbData)
  80. {
  81. cb = _cbData - _lOffset;
  82. //CairoleDebugOut((DEB_ERROR, "ActivationStream read past end of stream %x\n", cb+_lOffset));
  83. hresult = STG_E_READFAULT;
  84. }
  85. memcpy(pv,_pifData->abData + _lOffset, (size_t) cb);
  86. _lOffset += cb;
  87. if (pcbRead != NULL)
  88. {
  89. *pcbRead = cb;
  90. }
  91. return hresult;
  92. }
  93. STDMETHODIMP ActivationStream::Write(
  94. VOID const HUGEP* pv,
  95. ULONG cbToWrite,
  96. ULONG FAR* pcbWritten)
  97. {
  98. HRESULT hresult = S_OK;
  99. if (pcbWritten)
  100. {
  101. *pcbWritten = 0L;
  102. }
  103. if (cbToWrite + _lOffset > _cbData)
  104. {
  105. // the current stream is too small, try to grow it.
  106. if (!_fFree)
  107. {
  108. // The stream doesn't own the buffer so it can't reallocate it
  109. //CairoleDebugOut((DEB_ERROR, "ActivationStream write past end of stream %x\n",
  110. //cbToWrite + _lOffset));
  111. return STG_E_WRITEFAULT;
  112. }
  113. // Reallocate the size of the buffer
  114. // REVIEW: The constant added to the size allocated is a number
  115. // designed simply to try and decrease the number of follow on
  116. // allocations. In other words it needs to be tuned (or dropped!).
  117. BYTE *pbNewBuf = (BYTE *) ActMemAlloc(sizeof(DWORD) +
  118. cbToWrite +
  119. _lOffset + 64);
  120. if (pbNewBuf == NULL)
  121. {
  122. //CairoleDebugOut((DEB_ERROR, "ActivationStream cant grow stream\n"));
  123. return E_OUTOFMEMORY;
  124. }
  125. if (_pifData)
  126. {
  127. // we had a buffer from before, copy that in, and free the old one.
  128. memcpy(pbNewBuf, _pifData, sizeof(DWORD) + _cbData);
  129. ActMemFree(_pifData);
  130. }
  131. _cbData = cbToWrite + _lOffset + 64;
  132. _pifData = (InterfaceData *)pbNewBuf;
  133. }
  134. // copy in the new data
  135. memcpy(_pifData->abData + _lOffset, pv, (size_t) cbToWrite);
  136. _lOffset += cbToWrite;
  137. if (pcbWritten != NULL)
  138. {
  139. *pcbWritten = cbToWrite;
  140. }
  141. // We assume maxium size of buffer is the size to send on the network.
  142. if (_cSize < _lOffset)
  143. {
  144. _cSize = _lOffset;
  145. }
  146. return hresult;
  147. }
  148. STDMETHODIMP ActivationStream::Seek(
  149. LARGE_INTEGER dlibMoveIN,
  150. DWORD dwOrigin,
  151. ULARGE_INTEGER FAR* plibNewPosition)
  152. {
  153. HRESULT hresult = S_OK;
  154. /*
  155. can't use this code until the stuff in ole2pr32.dll is fixed.
  156. // check against -2^31-1 <= x <= 2^31-1
  157. if (dlibMoveIN.HighPart == 0 && dlibMoveIN.LowPart < 0x80000000)
  158. // positive 31 bit value
  159. ;
  160. else if (dlibMoveIN.HighPart == -1L && dlibMoveIN.LowPart >= 0x80000000)
  161. // negative 31 bit value
  162. ;
  163. else
  164. return STG_E_SEEKERROR;
  165. */
  166. LONG dlibMove = dlibMoveIN.LowPart;
  167. ULONG cbNewPos = dlibMove;
  168. switch(dwOrigin)
  169. {
  170. case STREAM_SEEK_SET:
  171. if (dlibMove >= 0)
  172. {
  173. _lOffset = dlibMove;
  174. }
  175. else
  176. {
  177. hresult = STG_E_SEEKERROR;
  178. }
  179. break;
  180. case STREAM_SEEK_CUR:
  181. if (!(dlibMove < 0 && (-dlibMove > _lOffset)))
  182. {
  183. _lOffset += (ULONG) dlibMove;
  184. }
  185. else
  186. {
  187. hresult = STG_E_SEEKERROR;
  188. }
  189. break;
  190. case STREAM_SEEK_END:
  191. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > _cbData))
  192. {
  193. _lOffset = _cbData + dlibMove;
  194. }
  195. else
  196. {
  197. hresult = STG_E_SEEKERROR;
  198. }
  199. break;
  200. default:
  201. hresult = STG_E_SEEKERROR;
  202. }
  203. if (plibNewPosition != NULL)
  204. {
  205. ULISet32(*plibNewPosition, _lOffset);
  206. }
  207. return hresult;
  208. }
  209. STDMETHODIMP ActivationStream::SetSize(ULARGE_INTEGER cb)
  210. {
  211. return E_NOTIMPL;
  212. }
  213. STDMETHODIMP ActivationStream::CopyTo(
  214. IStream FAR* pstm,
  215. ULARGE_INTEGER cb,
  216. ULARGE_INTEGER FAR* pcbRead,
  217. ULARGE_INTEGER FAR* pcbWritten)
  218. {
  219. return E_NOTIMPL;
  220. }
  221. STDMETHODIMP ActivationStream::Commit(DWORD grfCommitFlags)
  222. {
  223. return NOERROR;
  224. }
  225. STDMETHODIMP ActivationStream::Revert(void)
  226. {
  227. return NOERROR;
  228. }
  229. STDMETHODIMP ActivationStream::LockRegion(
  230. ULARGE_INTEGER libOffset,
  231. ULARGE_INTEGER cb,
  232. DWORD dwLockType)
  233. {
  234. return STG_E_INVALIDFUNCTION;
  235. }
  236. STDMETHODIMP ActivationStream::UnlockRegion(
  237. ULARGE_INTEGER libOffset,
  238. ULARGE_INTEGER cb,
  239. DWORD dwLockType)
  240. {
  241. return STG_E_INVALIDFUNCTION;
  242. }
  243. STDMETHODIMP ActivationStream::Stat(
  244. STATSTG FAR* pstatstg,
  245. DWORD statflag)
  246. {
  247. memset(pstatstg, 0, sizeof(STATSTG));
  248. return E_NOTIMPL;
  249. }
  250. STDMETHODIMP ActivationStream::SetCopyAlignment(DWORD alignment)
  251. {
  252. _copyAlignment = alignment;
  253. return S_OK;
  254. }
  255. inline ActivationStream *ActivationStream::Clone()
  256. {
  257. DWORD len;
  258. BYTE *newBuff;
  259. DWORD alignmentOffset=0;
  260. // Assume 8 byte alignment for new buffer
  261. ActivationStream *strm = new ActivationStream(_cbData+_copyAlignment-1);
  262. if (strm == NULL)
  263. return strm;
  264. // make sure we were able to allocate an internal buffer
  265. if (_cbData != 0)
  266. {
  267. strm->GetLength(&len);
  268. if (len == 0)
  269. {
  270. delete strm;
  271. return NULL;
  272. }
  273. }
  274. strm->GetBuffer(&len, &newBuff);
  275. ASSERT(len==(_cbData+_copyAlignment-1));
  276. ASSERT( sizeof(_lOffset) == sizeof(LONG) );
  277. if ((UINT_PTR)(newBuff+_lOffset) & (_copyAlignment-1))
  278. {
  279. alignmentOffset = _copyAlignment -
  280. ( PtrToUlong(newBuff+_lOffset) & (_copyAlignment-1) );
  281. }
  282. GetCopy(newBuff+alignmentOffset);
  283. strm->SetPosition(len, _lOffset+alignmentOffset);
  284. return strm;
  285. }
  286. STDMETHODIMP ActivationStream::Clone(IStream FAR * FAR *ppstm)
  287. {
  288. *ppstm = Clone();
  289. if (*ppstm==NULL)
  290. return E_OUTOFMEMORY;
  291. return S_OK;
  292. }
  293. STDMETHODIMP ActivationStream::GetOrCreateBuffer(DWORD dwReq, DWORD *pdwLength, BYTE **ppBuff)
  294. {
  295. if (((_cbData - _lOffset) < dwReq) || (!_pifData))
  296. {
  297. BYTE* pbNewBuf = (BYTE*)ActMemAlloc(sizeof(DWORD)+dwReq+_cbData-_lOffset);
  298. if (pbNewBuf==NULL)
  299. return E_OUTOFMEMORY;
  300. if (_pifData)
  301. {
  302. // we had a buffer from before, copy that in, and free the old one.
  303. memcpy(pbNewBuf, _pifData, sizeof(DWORD) + _cbData);
  304. ActMemFree(_pifData);
  305. }
  306. // update _cbData
  307. _cbData = dwReq + _cbData - _lOffset;
  308. _pifData = (InterfaceData*)pbNewBuf;
  309. }
  310. *ppBuff = _pifData->abData + _lOffset;
  311. *pdwLength = _cbData - _lOffset;
  312. return S_OK;
  313. }
  314. STDMETHODIMP ActivationStream::GetBuffer(DWORD *pdwLength, BYTE **ppBuff)
  315. {
  316. *pdwLength = _cbData-_lOffset;
  317. *ppBuff = _pifData->abData + _lOffset;
  318. return S_OK;
  319. }
  320. STDMETHODIMP ActivationStream::GetLength(DWORD *pdwLength)
  321. {
  322. *pdwLength = _cbData;
  323. return S_OK;
  324. }
  325. STDMETHODIMP ActivationStream::GetCopy(BYTE *pBuff)
  326. {
  327. memcpy(pBuff, _pifData->abData, _cbData);
  328. return S_OK;
  329. }
  330. STDMETHODIMP ActivationStream::SetPosition(DWORD dwLenFromEnd, DWORD dwPosFromStart)
  331. {
  332. if (dwPosFromStart > dwLenFromEnd)
  333. return E_FAIL;
  334. _lOffset = _cbData - dwLenFromEnd + dwPosFromStart;
  335. if (_cSize < _lOffset)
  336. _cSize = _lOffset;
  337. return S_OK;
  338. }
  339. STDMETHODIMP ActivationStream::SetBuffer(DWORD dwLength, BYTE *pBuff)
  340. {
  341. return E_NOTIMPL;
  342. }