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.

523 lines
16 KiB

  1. // --------------------------------------------------------------------------------
  2. // Stmlock.cpp
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // Steven J. Bailey
  5. // --------------------------------------------------------------------------------
  6. #include "pch.hxx"
  7. #include "stmlock.h"
  8. #include "vstream.h"
  9. #include "demand.h"
  10. // --------------------------------------------------------------------------------
  11. // CStreamLockBytes::CStreamLockBytes
  12. // --------------------------------------------------------------------------------
  13. CStreamLockBytes::CStreamLockBytes(IStream *pStream)
  14. {
  15. Assert(pStream);
  16. m_cRef = 1;
  17. m_pStream = pStream;
  18. m_pStream->AddRef();
  19. InitializeCriticalSection(&m_cs);
  20. }
  21. // --------------------------------------------------------------------------------
  22. // CStreamLockBytes::CStreamLockBytes
  23. // --------------------------------------------------------------------------------
  24. CStreamLockBytes::~CStreamLockBytes(void)
  25. {
  26. SafeRelease(m_pStream);
  27. DeleteCriticalSection(&m_cs);
  28. }
  29. // --------------------------------------------------------------------------------
  30. // CStreamLockBytes::CStreamLockBytes
  31. // --------------------------------------------------------------------------------
  32. STDMETHODIMP CStreamLockBytes::QueryInterface(REFIID riid, LPVOID *ppv)
  33. {
  34. // check params
  35. if (ppv == NULL)
  36. return TrapError(E_INVALIDARG);
  37. // Init
  38. *ppv = NULL;
  39. // Find IID
  40. if (IID_IUnknown == riid)
  41. *ppv = (IUnknown *)this;
  42. else if (IID_ILockBytes == riid)
  43. *ppv = (ILockBytes *)this;
  44. else if (IID_CStreamLockBytes == riid)
  45. *ppv = (CStreamLockBytes *)this;
  46. else
  47. {
  48. *ppv = NULL;
  49. return E_NOINTERFACE;
  50. }
  51. // AddRef It
  52. ((IUnknown *)*ppv)->AddRef();
  53. // Done
  54. return S_OK;
  55. }
  56. // --------------------------------------------------------------------------------
  57. // CStreamLockBytes::CStreamLockBytes
  58. // --------------------------------------------------------------------------------
  59. STDMETHODIMP_(ULONG) CStreamLockBytes::AddRef(void)
  60. {
  61. return (ULONG)InterlockedIncrement(&m_cRef);
  62. }
  63. // --------------------------------------------------------------------------------
  64. // CStreamLockBytes::CStreamLockBytes
  65. // --------------------------------------------------------------------------------
  66. STDMETHODIMP_(ULONG) CStreamLockBytes::Release(void)
  67. {
  68. LONG cRef = InterlockedDecrement(&m_cRef);
  69. if (0 == cRef)
  70. delete this;
  71. return (ULONG)cRef;
  72. }
  73. // --------------------------------------------------------------------------------
  74. // CStreamLockBytes::HrSetPosition
  75. // --------------------------------------------------------------------------------
  76. HRESULT CStreamLockBytes::HrSetPosition(ULARGE_INTEGER uliOffset)
  77. {
  78. EnterCriticalSection(&m_cs);
  79. LARGE_INTEGER liOrigin;
  80. liOrigin.QuadPart = (DWORDLONG)uliOffset.QuadPart;
  81. HRESULT hr = m_pStream->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  82. LeaveCriticalSection(&m_cs);
  83. return hr;
  84. }
  85. // --------------------------------------------------------------------------------
  86. // CStreamLockBytes::HrHandsOffStorage
  87. // --------------------------------------------------------------------------------
  88. HRESULT CStreamLockBytes::HrHandsOffStorage(void)
  89. {
  90. // Locals
  91. HRESULT hr=S_OK;
  92. LPSTREAM pstmNew=NULL;
  93. // Thread Safety
  94. EnterCriticalSection(&m_cs);
  95. // If Reference Count Isn't 1 (i.e. owned by IMimeMessageTree), dup the internal data
  96. if (1 != m_cRef)
  97. {
  98. // Copy m_pStream to a local place...
  99. CHECKALLOC(pstmNew = new CVirtualStream);
  100. // Rewind Internal
  101. CHECKHR(hr = HrRewindStream(m_pStream));
  102. // Copy the stream
  103. CHECKHR(hr = HrCopyStream(m_pStream, pstmNew, NULL));
  104. // Rewind and commit
  105. CHECKHR(hr = pstmNew->Commit(STGC_DEFAULT));
  106. // Rewind
  107. CHECKHR(hr = HrRewindStream(pstmNew));
  108. // Replace Internal Stream
  109. ReplaceInternalStream(pstmNew);
  110. }
  111. exit:
  112. // Cleanup
  113. SafeRelease(pstmNew);
  114. // Thread Safety
  115. LeaveCriticalSection(&m_cs);
  116. // Done
  117. return hr;
  118. }
  119. // -------------------------------------------------------------------------
  120. // CStreamLockBytes::GetCurrentStream
  121. // -------------------------------------------------------------------------
  122. void CStreamLockBytes::GetCurrentStream(IStream **ppStream)
  123. {
  124. EnterCriticalSection(&m_cs);
  125. Assert(ppStream && m_pStream);
  126. *ppStream = m_pStream;
  127. (*ppStream)->AddRef();
  128. LeaveCriticalSection(&m_cs);
  129. }
  130. // --------------------------------------------------------------------------------
  131. // CStreamLockBytes::ReplaceInternalStream
  132. // --------------------------------------------------------------------------------
  133. void CStreamLockBytes::ReplaceInternalStream(IStream *pStream)
  134. {
  135. // Locals
  136. HRESULT hr=S_OK;
  137. // Thread Safety
  138. EnterCriticalSection(&m_cs);
  139. // No Internal Strea ?
  140. if (NULL == m_pStream)
  141. {
  142. Assert(FALSE);
  143. goto exit;
  144. }
  145. // DEBUG: Make sure stream are EXACTLY the same size
  146. #ifdef DEBUG
  147. ULONG cbInternal, cbExternal;
  148. HrGetStreamSize(m_pStream, &cbInternal);
  149. HrGetStreamSize(pStream, &cbExternal);
  150. Assert(cbInternal == cbExternal);
  151. #endif
  152. // Release Internal
  153. m_pStream->Release();
  154. m_pStream = pStream;
  155. m_pStream->AddRef();
  156. exit:
  157. // Thread Safety
  158. LeaveCriticalSection(&m_cs);
  159. }
  160. // --------------------------------------------------------------------------------
  161. // CStreamLockBytes::Flush
  162. // --------------------------------------------------------------------------------
  163. STDMETHODIMP CStreamLockBytes::Flush(void)
  164. {
  165. EnterCriticalSection(&m_cs);
  166. HRESULT hr = m_pStream->Commit(STGC_DEFAULT);
  167. LeaveCriticalSection(&m_cs);
  168. return hr;
  169. }
  170. // --------------------------------------------------------------------------------
  171. // CStreamLockBytes::LockRegion
  172. // --------------------------------------------------------------------------------
  173. STDMETHODIMP CStreamLockBytes::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  174. {
  175. EnterCriticalSection(&m_cs);
  176. HRESULT hr = m_pStream->LockRegion(libOffset, cb, dwLockType);
  177. LeaveCriticalSection(&m_cs);
  178. return hr;
  179. }
  180. // --------------------------------------------------------------------------------
  181. // CStreamLockBytes::UnlockRegion
  182. // --------------------------------------------------------------------------------
  183. STDMETHODIMP CStreamLockBytes::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  184. {
  185. EnterCriticalSection(&m_cs);
  186. HRESULT hr = m_pStream->LockRegion(libOffset, cb, dwLockType);
  187. LeaveCriticalSection(&m_cs);
  188. return hr;
  189. }
  190. // --------------------------------------------------------------------------------
  191. // CStreamLockBytes::ReadAt
  192. // --------------------------------------------------------------------------------
  193. #ifndef WIN16
  194. STDMETHODIMP CStreamLockBytes::ReadAt(ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
  195. #else
  196. STDMETHODIMP CStreamLockBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP *pv, ULONG cb, ULONG *pcbRead)
  197. #endif // !WIN16
  198. {
  199. LARGE_INTEGER liOrigin={ulOffset.LowPart, ulOffset.HighPart};
  200. EnterCriticalSection(&m_cs);
  201. HRESULT hr = m_pStream->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  202. if (SUCCEEDED(hr))
  203. hr = m_pStream->Read(pv, cb, pcbRead);
  204. LeaveCriticalSection(&m_cs);
  205. return hr;
  206. }
  207. // --------------------------------------------------------------------------------
  208. // CStreamLockBytes::WriteAt
  209. // --------------------------------------------------------------------------------
  210. #ifndef WIN16
  211. STDMETHODIMP CStreamLockBytes::WriteAt(ULARGE_INTEGER ulOffset, void const *pv, ULONG cb, ULONG *pcbWritten)
  212. #else
  213. STDMETHODIMP CStreamLockBytes::WriteAt(ULARGE_INTEGER ulOffset, void const HUGEP *pv, ULONG cb, ULONG *pcbWritten)
  214. #endif // !WIN16
  215. {
  216. LARGE_INTEGER liOrigin={ulOffset.LowPart, ulOffset.HighPart};
  217. EnterCriticalSection(&m_cs);
  218. HRESULT hr = m_pStream->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  219. if (SUCCEEDED(hr))
  220. hr = m_pStream->Write(pv, cb, pcbWritten);
  221. LeaveCriticalSection(&m_cs);
  222. return hr;
  223. }
  224. // --------------------------------------------------------------------------------
  225. // CStreamLockBytes::SetSize
  226. // --------------------------------------------------------------------------------
  227. STDMETHODIMP CStreamLockBytes::SetSize(ULARGE_INTEGER cb)
  228. {
  229. EnterCriticalSection(&m_cs);
  230. HRESULT hr = m_pStream->SetSize(cb);
  231. LeaveCriticalSection(&m_cs);
  232. return hr;
  233. }
  234. // --------------------------------------------------------------------------------
  235. // CStreamLockBytes::Stat
  236. // --------------------------------------------------------------------------------
  237. STDMETHODIMP CStreamLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  238. {
  239. // Locals
  240. HRESULT hr=S_OK;
  241. // Parameters
  242. if (NULL == pstatstg)
  243. return TrapError(E_INVALIDARG);
  244. // Thread Safety
  245. EnterCriticalSection(&m_cs);
  246. // Zero Init
  247. ZeroMemory(pstatstg, sizeof(STATSTG));
  248. // Stat
  249. if (FAILED(m_pStream->Stat(pstatstg, grfStatFlag)))
  250. {
  251. // Locals
  252. ULARGE_INTEGER uliPos;
  253. LARGE_INTEGER liOrigin;
  254. // Initialize
  255. uliPos.QuadPart = 0;
  256. liOrigin.QuadPart = 0;
  257. // If that failed, lets generate our own information (mainly, fill in size
  258. pstatstg->type = STGTY_LOCKBYTES;
  259. // Seek
  260. if (FAILED(m_pStream->Seek(liOrigin, STREAM_SEEK_END, &uliPos)))
  261. hr = E_FAIL;
  262. else
  263. pstatstg->cbSize.QuadPart = uliPos.QuadPart;
  264. }
  265. // URLMON Streams return a filled pwcsName event though this flag is set
  266. else if (ISFLAGSET(grfStatFlag, STATFLAG_NONAME))
  267. {
  268. // Free it
  269. SafeMemFree(pstatstg->pwcsName);
  270. }
  271. // Thread Safety
  272. LeaveCriticalSection(&m_cs);
  273. // Done
  274. return hr;
  275. }
  276. // -------------------------------------------------------------------------
  277. // CLockedStream::CLockedStream
  278. // -------------------------------------------------------------------------
  279. CLockedStream::CLockedStream(ILockBytes *pLockBytes, ULONG cbSize)
  280. {
  281. Assert(pLockBytes);
  282. m_cRef = 1;
  283. m_pLockBytes = pLockBytes;
  284. m_pLockBytes->AddRef();
  285. m_uliOffset.QuadPart = 0;
  286. m_uliSize.QuadPart = cbSize;
  287. InitializeCriticalSection(&m_cs);
  288. }
  289. // -------------------------------------------------------------------------
  290. // CLockedStream::CLockedStream
  291. // -------------------------------------------------------------------------
  292. CLockedStream::~CLockedStream(void)
  293. {
  294. SafeRelease(m_pLockBytes);
  295. DeleteCriticalSection(&m_cs);
  296. }
  297. // -------------------------------------------------------------------------
  298. // CLockedStream::QueryInterface
  299. // -------------------------------------------------------------------------
  300. STDMETHODIMP CLockedStream::QueryInterface(REFIID riid, LPVOID *ppv)
  301. {
  302. // check params
  303. if (ppv == NULL)
  304. return TrapError(E_INVALIDARG);
  305. // Init
  306. *ppv = NULL;
  307. // Find IID
  308. if (IID_IUnknown == riid)
  309. *ppv = (IUnknown *)this;
  310. else if (IID_IStream == riid)
  311. *ppv = (IStream *)this;
  312. else
  313. {
  314. *ppv = NULL;
  315. return TrapError(E_NOINTERFACE);
  316. }
  317. // AddRef It
  318. ((IUnknown *)*ppv)->AddRef();
  319. // Done
  320. return S_OK;
  321. }
  322. // -------------------------------------------------------------------------
  323. // CLockedStream::AddRef
  324. // -------------------------------------------------------------------------
  325. STDMETHODIMP_(ULONG) CLockedStream::AddRef(void)
  326. {
  327. return (ULONG)InterlockedIncrement(&m_cRef);
  328. }
  329. // -------------------------------------------------------------------------
  330. // CLockedStream::Release
  331. // -------------------------------------------------------------------------
  332. STDMETHODIMP_(ULONG) CLockedStream::Release(void)
  333. {
  334. LONG cRef = InterlockedDecrement(&m_cRef);
  335. if (0 == cRef)
  336. delete this;
  337. return (ULONG)cRef;
  338. }
  339. // -------------------------------------------------------------------------
  340. // CLockedStream::Read
  341. // -------------------------------------------------------------------------
  342. #ifndef WIN16
  343. STDMETHODIMP CLockedStream::Read(LPVOID pv, ULONG cb, ULONG *pcbRead)
  344. #else
  345. STDMETHODIMP CLockedStream::Read(VOID HUGEP *pv, ULONG cb, ULONG *pcbRead)
  346. #endif // !WIN16
  347. {
  348. // Locals
  349. HRESULT hr=S_OK;
  350. ULONG cbRead;
  351. // Thread Safety
  352. EnterCriticalSection(&m_cs);
  353. // Read Buffer
  354. CHECKHR(hr = m_pLockBytes->ReadAt(m_uliOffset, pv, cb, &cbRead));
  355. // Done
  356. m_uliOffset.QuadPart += cbRead;
  357. // Return amount read
  358. if (pcbRead)
  359. *pcbRead = cbRead;
  360. exit:
  361. // Thread Safety
  362. LeaveCriticalSection(&m_cs);
  363. // Done
  364. return hr;
  365. }
  366. // -------------------------------------------------------------------------
  367. // CLockedStream::Seek
  368. // -------------------------------------------------------------------------
  369. STDMETHODIMP CLockedStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNew)
  370. {
  371. // Locals
  372. HRESULT hr=S_OK;
  373. ULARGE_INTEGER uliNew;
  374. // Thread Safety
  375. EnterCriticalSection(&m_cs);
  376. // Seek the file pointer
  377. switch (dwOrigin)
  378. {
  379. // --------------------------------------------------------
  380. case STREAM_SEEK_SET:
  381. uliNew.QuadPart = (DWORDLONG)dlibMove.QuadPart;
  382. break;
  383. // --------------------------------------------------------
  384. case STREAM_SEEK_CUR:
  385. if (dlibMove.QuadPart < 0)
  386. {
  387. if ((DWORDLONG)(0 - dlibMove.QuadPart) > m_uliOffset.QuadPart)
  388. {
  389. hr = TrapError(E_FAIL);
  390. goto exit;
  391. }
  392. }
  393. uliNew.QuadPart = m_uliOffset.QuadPart + dlibMove.QuadPart;
  394. break;
  395. // --------------------------------------------------------
  396. case STREAM_SEEK_END:
  397. if (dlibMove.QuadPart < 0 || (DWORDLONG)dlibMove.QuadPart > m_uliSize.QuadPart)
  398. {
  399. hr = TrapError(E_FAIL);
  400. goto exit;
  401. }
  402. uliNew.QuadPart = m_uliSize.QuadPart - dlibMove.QuadPart;
  403. break;
  404. // --------------------------------------------------------
  405. default:
  406. hr = TrapError(STG_E_INVALIDFUNCTION);
  407. goto exit;
  408. }
  409. // New offset greater than size...
  410. m_uliOffset.QuadPart = min(uliNew.QuadPart, m_uliSize.QuadPart);
  411. // Return Position
  412. if (plibNew)
  413. plibNew->QuadPart = (LONGLONG)m_uliOffset.QuadPart;
  414. exit:
  415. // Thread Safety
  416. LeaveCriticalSection(&m_cs);
  417. // Done
  418. return hr;
  419. }
  420. // --------------------------------------------------------------------------------
  421. // CLockedStream::CopyTo
  422. // --------------------------------------------------------------------------------
  423. STDMETHODIMP CLockedStream::CopyTo(LPSTREAM pstmDest, ULARGE_INTEGER cb, ULARGE_INTEGER *puliRead, ULARGE_INTEGER *puliWritten)
  424. {
  425. return HrCopyStreamCB((IStream *)this, pstmDest, cb, puliRead, puliWritten);
  426. }
  427. // --------------------------------------------------------------------------------
  428. // CLockedStream::Stat
  429. // --------------------------------------------------------------------------------
  430. STDMETHODIMP CLockedStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  431. {
  432. // Parameters
  433. if (NULL == pstatstg)
  434. return TrapError(E_INVALIDARG);
  435. // Thread Safety
  436. EnterCriticalSection(&m_cs);
  437. // If that failed, lets generate our own information (mainly, fill in size
  438. ZeroMemory(pstatstg, sizeof(STATSTG));
  439. pstatstg->type = STGTY_STREAM;
  440. pstatstg->cbSize.QuadPart = m_uliSize.QuadPart;
  441. // Thread Safety
  442. LeaveCriticalSection(&m_cs);
  443. // Done
  444. return S_OK;
  445. }