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.

334 lines
9.8 KiB

  1. // --------------------------------------------------------------------------------
  2. // Ibdylock.cpp
  3. // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  4. // Steven J. Bailey
  5. // --------------------------------------------------------------------------------
  6. #include "pch.hxx"
  7. #ifndef WIN16
  8. #include "ibdylock.h"
  9. #endif // !WIn16
  10. #include "stmlock.h"
  11. #include "booktree.h"
  12. #ifdef WIN16
  13. #include "ibdylock.h"
  14. #endif // WIn16
  15. #include "demand.h"
  16. // --------------------------------------------------------------------------------
  17. // CBodyLockBytes::CBodyLockBytes
  18. // --------------------------------------------------------------------------------
  19. CBodyLockBytes::CBodyLockBytes(ILockBytes *pLockBytes, LPTREENODEINFO pNode)
  20. {
  21. // Invalid ARg
  22. Assert(pLockBytes && pNode);
  23. // Set Initialize Ref Count and State
  24. m_cRef = 1;
  25. m_dwState = 0;
  26. // AddRef the LockBytes
  27. m_pLockBytes = pLockBytes;
  28. m_pLockBytes->AddRef();
  29. // Save State
  30. FLAGSET(m_dwState, BODYLOCK_HANDSONSTORAGE);
  31. // Save the bind state
  32. m_bindstate = pNode->bindstate;
  33. // Save body start and body end..
  34. Assert(pNode->cbBodyStart <= pNode->cbBodyEnd);
  35. // Save Body Start
  36. #ifdef MAC
  37. ULISet32(m_uliBodyStart, pNode->cbBodyStart);
  38. ULISet32(m_uliBodyEnd, pNode->cbBodyEnd);
  39. // This condition is here to insure that we don't have a problem...
  40. if (m_uliBodyStart.LowPart > m_uliBodyEnd.LowPart)
  41. m_uliBodyStart.LowPart = m_uliBodyEnd.LowPart;
  42. #else // !MAC
  43. m_uliBodyStart.QuadPart = pNode->cbBodyStart;
  44. m_uliBodyEnd.QuadPart = pNode->cbBodyEnd;
  45. // This condition is here to insure that we don't have a problem...
  46. if (m_uliBodyStart.QuadPart > m_uliBodyEnd.QuadPart)
  47. m_uliBodyStart.QuadPart = m_uliBodyEnd.QuadPart;
  48. #endif // MAC
  49. // Initialize the CriticalSection
  50. InitializeCriticalSection(&m_cs);
  51. }
  52. // --------------------------------------------------------------------------------
  53. // CBodyLockBytes::~CBodyLockBytes
  54. // --------------------------------------------------------------------------------
  55. CBodyLockBytes::~CBodyLockBytes(void)
  56. {
  57. SafeRelease(m_pLockBytes);
  58. Assert(!ISFLAGSET(m_dwState, BODYLOCK_HANDSONSTORAGE));
  59. DeleteCriticalSection(&m_cs);
  60. }
  61. // --------------------------------------------------------------------------------
  62. // CBodyLockBytes::QueryInterface
  63. // --------------------------------------------------------------------------------
  64. STDMETHODIMP CBodyLockBytes::QueryInterface(REFIID riid, LPVOID *ppv)
  65. {
  66. // check params
  67. if (ppv == NULL)
  68. return TrapError(E_INVALIDARG);
  69. // Init
  70. *ppv = NULL;
  71. // Find IID
  72. if (IID_IUnknown == riid)
  73. *ppv = (IUnknown *)this;
  74. else if (IID_ILockBytes == riid)
  75. *ppv = (ILockBytes *)this;
  76. else if (IID_CBodyLockBytes == riid)
  77. *ppv = (CBodyLockBytes *)this;
  78. else
  79. {
  80. *ppv = NULL;
  81. return TrapError(E_NOINTERFACE);
  82. }
  83. // AddRef It
  84. ((IUnknown *)*ppv)->AddRef();
  85. // Done
  86. return S_OK;
  87. }
  88. // --------------------------------------------------------------------------------
  89. // CBodyLockBytes::AddRef
  90. // --------------------------------------------------------------------------------
  91. STDMETHODIMP_(ULONG) CBodyLockBytes::AddRef(void)
  92. {
  93. return (ULONG)InterlockedIncrement(&m_cRef);
  94. }
  95. // --------------------------------------------------------------------------------
  96. // CBodyLockBytes::Release
  97. // --------------------------------------------------------------------------------
  98. STDMETHODIMP_(ULONG) CBodyLockBytes::Release(void)
  99. {
  100. LONG cRef = InterlockedDecrement(&m_cRef);
  101. if (0 == cRef)
  102. delete this;
  103. return (ULONG)cRef;
  104. }
  105. // --------------------------------------------------------------------------------
  106. // CBodyLockBytes::ReadAt
  107. // --------------------------------------------------------------------------------
  108. #ifndef WIN16
  109. STDMETHODIMP CBodyLockBytes::ReadAt(ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
  110. #else
  111. STDMETHODIMP CBodyLockBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP *pv, ULONG cb, ULONG *pcbRead)
  112. #endif // !WIN16
  113. {
  114. // Locals
  115. HRESULT hr=S_OK;
  116. ULONG cbGet;
  117. ULONG cbRead;
  118. ULARGE_INTEGER uliActualOffset;
  119. // Thread Safety
  120. EnterCriticalSection(&m_cs);
  121. // Reading from ILockBytes...
  122. Assert(m_pLockBytes);
  123. #ifdef MAC
  124. // Compute Actual offset
  125. AssertSz(m_uliBodyStart.HighPart >= 0, "How can the start be negative??");
  126. ULISet32(uliActualOffset, m_uliBodyStart.LowPart);
  127. AssertSz((uliActualOffset.LowPart + ulOffset.LowPart) >= uliActualOffset.LowPart,
  128. "Oops! We don't handle backwards reads correctly!");
  129. uliActualOffset.LowPart += ulOffset.LowPart;
  130. // Compute amount to read
  131. cbGet = min(cb, m_uliBodyEnd.LowPart - uliActualOffset.LowPart);
  132. #else // !MAC
  133. // Compute Actual offset
  134. uliActualOffset.QuadPart = ulOffset.QuadPart + m_uliBodyStart.QuadPart;
  135. // Compute amount to read
  136. cbGet = (ULONG)min(cb, m_uliBodyEnd.QuadPart - uliActualOffset.QuadPart);
  137. #endif // MAC
  138. // Read a block of data...
  139. CHECKHR(hr = m_pLockBytes->ReadAt(uliActualOffset, pv, cbGet, &cbRead));
  140. // Return amount read
  141. if (pcbRead)
  142. *pcbRead = cbRead;
  143. // E_PENDING
  144. if (0 == cbRead && BINDSTATE_COMPLETE != m_bindstate)
  145. {
  146. hr = TrapError(E_PENDING);
  147. goto exit;
  148. }
  149. exit:
  150. // Thread Safety
  151. LeaveCriticalSection(&m_cs);
  152. // Done
  153. return hr;
  154. }
  155. // --------------------------------------------------------------------------------
  156. // CBodyLockBytes::Stat
  157. // --------------------------------------------------------------------------------
  158. STDMETHODIMP CBodyLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  159. {
  160. // Parameters
  161. if (NULL == pstatstg)
  162. return TrapError(E_INVALIDARG);
  163. // Thread Safety
  164. EnterCriticalSection(&m_cs);
  165. // Init
  166. ZeroMemory(pstatstg, sizeof(STATSTG));
  167. // Reading from ILockBytes...
  168. pstatstg->type = STGTY_LOCKBYTES;
  169. // Set Size
  170. #ifdef MAC
  171. AssertSz(0 == m_uliBodyEnd.HighPart, "We have too big of a file!");
  172. AssertSz(0 == m_uliBodyStart.HighPart, "We have too big of a file!");
  173. ULISet32(pstatstg->cbSize, (m_uliBodyEnd.LowPart - m_uliBodyStart.LowPart));
  174. #else // !MAC
  175. pstatstg->cbSize.QuadPart = m_uliBodyEnd.QuadPart - m_uliBodyStart.QuadPart;
  176. #endif // MAC
  177. // Thread Safety
  178. LeaveCriticalSection(&m_cs);
  179. // Done
  180. return S_OK;
  181. }
  182. // --------------------------------------------------------------------------------
  183. // CBodyLockBytes::HrHandsOffStorage
  184. // --------------------------------------------------------------------------------
  185. HRESULT CBodyLockBytes::HrHandsOffStorage(void)
  186. {
  187. // Locals
  188. HRESULT hr=S_OK;
  189. IStream *pstmTemp=NULL;
  190. ULARGE_INTEGER uliCopy;
  191. BYTE rgbBuffer[4096];
  192. ULONG cbRead;
  193. // Thread Safety
  194. EnterCriticalSection(&m_cs);
  195. // If I live in the tree, copy data to temporary location...
  196. if (ISFLAGSET(m_dwState, BODYLOCK_HANDSONSTORAGE) && BINDSTATE_COMPLETE == m_bindstate)
  197. {
  198. // If more than one reference count
  199. if (m_cRef > 1)
  200. {
  201. // Create Temp Stream
  202. CHECKHR(hr = CreateTempFileStream(&pstmTemp));
  203. // Set offset
  204. #ifdef MAC
  205. ULISet32(uliCopy, 0);
  206. #else // !MAC
  207. uliCopy.QuadPart = 0;
  208. #endif // MAC
  209. // Copy m_pLockBytes to pstmTemp
  210. while(1)
  211. {
  212. // Read
  213. CHECKHR(hr = ReadAt(uliCopy, rgbBuffer, sizeof(rgbBuffer), &cbRead));
  214. // Done
  215. if (0 == cbRead)
  216. break;
  217. // Write to stream
  218. CHECKHR(hr = pstmTemp->Write(rgbBuffer, cbRead, NULL));
  219. // Increment offset
  220. #ifdef MAC
  221. uliCopy.LowPart += cbRead;
  222. #else // !MAC
  223. uliCopy.QuadPart += cbRead;
  224. #endif // MAC
  225. }
  226. // Kill offsets, but maintain bodyend for stat command and Size esitmates
  227. #ifdef MAC
  228. AssertSz(0 == m_uliBodyEnd.HighPart, "We have too big of a file!");
  229. m_uliBodyEnd.LowPart -= m_uliBodyStart.LowPart;
  230. ULISet32(m_uliBodyStart, 0);
  231. #else // !MAC
  232. m_uliBodyEnd.QuadPart -= m_uliBodyStart.QuadPart;
  233. m_uliBodyStart.QuadPart = 0;
  234. #endif // MAC
  235. // Rewind and commit
  236. CHECKHR(hr = pstmTemp->Commit(STGC_DEFAULT));
  237. // Release current lockbytes
  238. SafeRelease(m_pLockBytes);
  239. // New CBodyLockBytes
  240. CHECKALLOC(m_pLockBytes = new CStreamLockBytes(pstmTemp));
  241. }
  242. // Remove lives in tree flag
  243. FLAGCLEAR(m_dwState, BODYLOCK_HANDSONSTORAGE);
  244. }
  245. exit:
  246. // Cleanup
  247. SafeRelease(pstmTemp);
  248. // Thread Safety
  249. LeaveCriticalSection(&m_cs);
  250. // Done
  251. return hr;
  252. }
  253. // --------------------------------------------------------------------------------
  254. // CBodyLockBytes::OnDataAvailable
  255. // --------------------------------------------------------------------------------
  256. void CBodyLockBytes::OnDataAvailable(LPTREENODEINFO pNode)
  257. {
  258. // Thread Safety
  259. EnterCriticalSection(&m_cs);
  260. // Bind Complete
  261. m_bindstate = pNode->bindstate;
  262. // Save body start and body end..
  263. #ifdef MAC
  264. Assert(m_uliBodyStart.LowPart <= pNode->cbBodyEnd);
  265. // Save start and End
  266. ULISet32(m_uliBodyEnd, pNode->cbBodyEnd);
  267. #else // !MAC
  268. Assert(m_uliBodyStart.QuadPart <= pNode->cbBodyEnd);
  269. // Save start and End
  270. m_uliBodyEnd.QuadPart = pNode->cbBodyEnd;
  271. #endif // MAC
  272. // Thread Safety
  273. LeaveCriticalSection(&m_cs);
  274. }