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.

425 lines
9.8 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. ULONG ulRefs = InterlockedDecrement(&_clRefs);
  63. if (ulRefs == 0)
  64. {
  65. delete this;
  66. }
  67. return ulRefs;
  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 > _cbData - _lOffset)
  80. {
  81. cb = _cbData - _lOffset;
  82. hresult = STG_E_READFAULT;
  83. }
  84. memcpy(pv,_pifData->abData + _lOffset, (size_t) cb);
  85. _lOffset += cb;
  86. if (pcbRead != NULL)
  87. {
  88. *pcbRead = cb;
  89. }
  90. return hresult;
  91. }
  92. STDMETHODIMP ActivationStream::Write(
  93. VOID const HUGEP* pv,
  94. ULONG cbToWrite,
  95. ULONG FAR* pcbWritten)
  96. {
  97. HRESULT hresult = S_OK;
  98. if (pcbWritten)
  99. {
  100. *pcbWritten = 0L;
  101. }
  102. if (cbToWrite > _cbData - _lOffset)
  103. {
  104. // the current stream is too small, try to grow it.
  105. // Validate that we can fulfill this request (this class doesn't
  106. // support buffers bigger than MAX_ULONG, so we need to avoid
  107. // overflow)
  108. UINT64 cbReq = sizeof(DWORD) + cbToWrite + _lOffset + 64;
  109. if(cbReq > ULONG_MAX)
  110. return E_OUTOFMEMORY;
  111. // We have a valid request
  112. ULONG ulLen = (ULONG) cbReq;
  113. if (!_fFree)
  114. {
  115. // The stream doesn't own the buffer so it can't reallocate it
  116. return STG_E_WRITEFAULT;
  117. }
  118. // Reallocate the size of the buffer
  119. // NOTE: The constant (64) added to the size allocated is a number
  120. // designed simply to try and decrease the number of follow on
  121. // allocations.
  122. BYTE *pbNewBuf = (BYTE *) ActMemAlloc(ulLen);
  123. if (pbNewBuf == NULL)
  124. {
  125. return E_OUTOFMEMORY;
  126. }
  127. if (_pifData)
  128. {
  129. // we had a buffer from before, copy that in, and free the old one.
  130. memcpy(pbNewBuf, _pifData, sizeof(DWORD) + _cbData);
  131. ActMemFree(_pifData);
  132. }
  133. _cbData = cbToWrite + _lOffset + 64;
  134. _pifData = (InterfaceData *)pbNewBuf;
  135. }
  136. // copy in the new data
  137. memcpy(_pifData->abData + _lOffset, pv, (size_t) cbToWrite);
  138. _lOffset += cbToWrite;
  139. if (pcbWritten != NULL)
  140. {
  141. *pcbWritten = cbToWrite;
  142. }
  143. // We assume maxium size of buffer is the size to send on the network.
  144. if (_cSize < _lOffset)
  145. {
  146. _cSize = _lOffset;
  147. }
  148. return hresult;
  149. }
  150. STDMETHODIMP ActivationStream::Seek(
  151. LARGE_INTEGER dlibMoveIN,
  152. DWORD dwOrigin,
  153. ULARGE_INTEGER FAR* plibNewPosition)
  154. {
  155. HRESULT hresult = S_OK;
  156. /*
  157. can't use this code until the stuff in ole2pr32.dll is fixed.
  158. // check against -2^31-1 <= x <= 2^31-1
  159. if (dlibMoveIN.HighPart == 0 && dlibMoveIN.LowPart < 0x80000000)
  160. // positive 31 bit value
  161. ;
  162. else if (dlibMoveIN.HighPart == -1L && dlibMoveIN.LowPart >= 0x80000000)
  163. // negative 31 bit value
  164. ;
  165. else
  166. return STG_E_SEEKERROR;
  167. */
  168. LONG dlibMove = dlibMoveIN.LowPart;
  169. ULONG cbNewPos = dlibMove;
  170. switch(dwOrigin)
  171. {
  172. case STREAM_SEEK_SET:
  173. if (dlibMove >= 0)
  174. {
  175. _lOffset = dlibMove;
  176. }
  177. else
  178. {
  179. hresult = STG_E_SEEKERROR;
  180. }
  181. break;
  182. case STREAM_SEEK_CUR:
  183. if (!(dlibMove < 0 && (-dlibMove > _lOffset)))
  184. {
  185. _lOffset += (ULONG) dlibMove;
  186. }
  187. else
  188. {
  189. hresult = STG_E_SEEKERROR;
  190. }
  191. break;
  192. case STREAM_SEEK_END:
  193. if (!(dlibMove < 0 && ((ULONG) -dlibMove) > _cbData))
  194. {
  195. _lOffset = _cbData + dlibMove;
  196. }
  197. else
  198. {
  199. hresult = STG_E_SEEKERROR;
  200. }
  201. break;
  202. default:
  203. hresult = STG_E_SEEKERROR;
  204. }
  205. if (plibNewPosition != NULL)
  206. {
  207. ULISet32(*plibNewPosition, _lOffset);
  208. }
  209. return hresult;
  210. }
  211. STDMETHODIMP ActivationStream::SetSize(ULARGE_INTEGER cb)
  212. {
  213. return E_NOTIMPL;
  214. }
  215. STDMETHODIMP ActivationStream::CopyTo(
  216. IStream FAR* pstm,
  217. ULARGE_INTEGER cb,
  218. ULARGE_INTEGER FAR* pcbRead,
  219. ULARGE_INTEGER FAR* pcbWritten)
  220. {
  221. return E_NOTIMPL;
  222. }
  223. STDMETHODIMP ActivationStream::Commit(DWORD grfCommitFlags)
  224. {
  225. return NOERROR;
  226. }
  227. STDMETHODIMP ActivationStream::Revert(void)
  228. {
  229. return NOERROR;
  230. }
  231. STDMETHODIMP ActivationStream::LockRegion(
  232. ULARGE_INTEGER libOffset,
  233. ULARGE_INTEGER cb,
  234. DWORD dwLockType)
  235. {
  236. return STG_E_INVALIDFUNCTION;
  237. }
  238. STDMETHODIMP ActivationStream::UnlockRegion(
  239. ULARGE_INTEGER libOffset,
  240. ULARGE_INTEGER cb,
  241. DWORD dwLockType)
  242. {
  243. return STG_E_INVALIDFUNCTION;
  244. }
  245. STDMETHODIMP ActivationStream::Stat(
  246. STATSTG FAR* pstatstg,
  247. DWORD statflag)
  248. {
  249. if (!pstatstg)
  250. return E_POINTER;
  251. memset(pstatstg, 0, sizeof(STATSTG));
  252. pstatstg->type = STGTY_LOCKBYTES;
  253. pstatstg->cbSize.LowPart = _cbData;
  254. // Everything else is zero or null, including the name
  255. return S_OK;
  256. }
  257. STDMETHODIMP ActivationStream::SetCopyAlignment(DWORD alignment)
  258. {
  259. _copyAlignment = alignment;
  260. return S_OK;
  261. }
  262. inline ActivationStream *ActivationStream::Clone()
  263. {
  264. DWORD len;
  265. BYTE *newBuff;
  266. DWORD alignmentOffset=0;
  267. // Assume 8 byte alignment for new buffer
  268. ActivationStream *strm = new ActivationStream(_cbData+_copyAlignment-1);
  269. if (strm == NULL)
  270. return strm;
  271. // make sure we were able to allocate an internal buffer
  272. if (_cbData != 0)
  273. {
  274. strm->GetLength(&len);
  275. if (len == 0)
  276. {
  277. delete strm;
  278. return NULL;
  279. }
  280. }
  281. strm->GetBuffer(&len, &newBuff);
  282. ASSERT(len==(_cbData+_copyAlignment-1));
  283. ASSERT( sizeof(_lOffset) == sizeof(LONG) );
  284. if ((UINT_PTR)(newBuff+_lOffset) & (_copyAlignment-1))
  285. {
  286. alignmentOffset = _copyAlignment -
  287. ( PtrToUlong(newBuff+_lOffset) & (_copyAlignment-1) );
  288. }
  289. GetCopy(newBuff+alignmentOffset);
  290. strm->SetPosition(len, _lOffset+alignmentOffset);
  291. return strm;
  292. }
  293. STDMETHODIMP ActivationStream::Clone(IStream FAR * FAR *ppstm)
  294. {
  295. *ppstm = Clone();
  296. if (*ppstm==NULL)
  297. return E_OUTOFMEMORY;
  298. return S_OK;
  299. }
  300. STDMETHODIMP ActivationStream::GetOrCreateBuffer(DWORD dwReq, DWORD *pdwLength, BYTE **ppBuff)
  301. {
  302. if (((_cbData - _lOffset) < dwReq) || (!_pifData))
  303. {
  304. BYTE* pbNewBuf = (BYTE*)ActMemAlloc(sizeof(DWORD)+dwReq+_cbData-_lOffset);
  305. if (pbNewBuf==NULL)
  306. return E_OUTOFMEMORY;
  307. if (_pifData)
  308. {
  309. // we had a buffer from before, copy that in, and free the old one.
  310. memcpy(pbNewBuf, _pifData, sizeof(DWORD) + _cbData);
  311. ActMemFree(_pifData);
  312. }
  313. // update _cbData
  314. _cbData = dwReq + _cbData - _lOffset;
  315. _pifData = (InterfaceData*)pbNewBuf;
  316. }
  317. *ppBuff = _pifData->abData + _lOffset;
  318. *pdwLength = _cbData - _lOffset;
  319. return S_OK;
  320. }
  321. STDMETHODIMP ActivationStream::GetBuffer(DWORD *pdwLength, BYTE **ppBuff)
  322. {
  323. *pdwLength = _cbData-_lOffset;
  324. *ppBuff = _pifData->abData + _lOffset;
  325. return S_OK;
  326. }
  327. STDMETHODIMP ActivationStream::GetLength(DWORD *pdwLength)
  328. {
  329. *pdwLength = _cbData;
  330. return S_OK;
  331. }
  332. STDMETHODIMP ActivationStream::GetCopy(BYTE *pBuff)
  333. {
  334. memcpy(pBuff, _pifData->abData, _cbData);
  335. return S_OK;
  336. }
  337. STDMETHODIMP ActivationStream::SetPosition(DWORD dwLenFromEnd, DWORD dwPosFromStart)
  338. {
  339. if (dwPosFromStart > dwLenFromEnd)
  340. return E_FAIL;
  341. _lOffset = _cbData - dwLenFromEnd + dwPosFromStart;
  342. if (_cSize < _lOffset)
  343. _cSize = _lOffset;
  344. return S_OK;
  345. }
  346. STDMETHODIMP ActivationStream::SetBuffer(DWORD dwLength, BYTE *pBuff)
  347. {
  348. return E_NOTIMPL;
  349. }