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.

232 lines
6.5 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: dfbasis.cxx
  7. //
  8. // Contents: Docfile basis implementation
  9. //
  10. // History: 28-Jul-92 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <dfhead.cxx>
  14. #pragma hdrstop
  15. #include <sstream.hxx>
  16. #include <ole.hxx>
  17. #include <entry.hxx>
  18. #include <smalloc.hxx>
  19. #include <lock.hxx>
  20. size_t CDFBasis::_aReserveSize[CDFB_CLASSCOUNT] =
  21. {
  22. sizeof(CDocFile),
  23. sizeof(CDirectStream),
  24. sizeof(CWrappedDocFile),
  25. sizeof(CTransactedStream)
  26. };
  27. //+--------------------------------------------------------------
  28. //
  29. // Member: CDFBasis::Release, public
  30. //
  31. // Synopsis: Decrease reference count and free memory
  32. //
  33. // History: 02-Mar-92 DrewB Created
  34. // 24-Jul-95 SusiA Take mutex prior to delete
  35. //
  36. //---------------------------------------------------------------
  37. #ifdef CODESEGMENTS
  38. #pragma code_seg(SEG_CDFBasis_vRelease)
  39. #endif
  40. void CDFBasis::vRelease(void)
  41. {
  42. LONG lRet;
  43. olDebugOut((DEB_ITRACE, "In CDFBasis::Release()\n"));
  44. olAssert(_cReferences > 0);
  45. lRet = InterlockedDecrement(&_cReferences);
  46. if (lRet == 0)
  47. {
  48. #if !defined(MULTIHEAP)
  49. //take the mutex here instead of in the allocator.
  50. g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
  51. #endif
  52. delete this;
  53. #if !defined(MULTIHEAP)
  54. g_smAllocator.GetMutex()->Release();
  55. #endif
  56. }
  57. olDebugOut((DEB_ITRACE, "Out CDFBasis::Release()\n"));
  58. }
  59. #ifdef DIRECTWRITERLOCK
  60. //+--------------------------------------------------------------
  61. //
  62. // Member: CDFBasis::TryReadLocks, public
  63. //
  64. // Synopsis: attempts to obtain read locks
  65. //
  66. // Arguments: [ulOpenLock] - lock index for this open docfile
  67. // [ulMask] - range lock mask
  68. //
  69. // History: 30-Apr-96 HenryLee Created
  70. //
  71. // Notes: tree mutex and update lock must be taken
  72. //
  73. //---------------------------------------------------------------
  74. HRESULT CDFBasis::TryReadLocks (CGlobalContext *pgc, ULONG ulMask)
  75. {
  76. HRESULT sc = S_OK;
  77. ULARGE_INTEGER cbLength = {0,0};
  78. ULARGE_INTEGER ulOffset = {0,0};
  79. ILockBytes *plst = GetBase();
  80. olAssert (pgc != NULL);
  81. ULISetLow(cbLength, COPENLOCKS);
  82. ULISetLow(ulOffset, ODIRECTWRITERLOCK & ulMask);
  83. olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  84. olVerSucc(plst->UnlockRegion(ulOffset,cbLength,LOCK_ONLYONCE));
  85. EH_Err:
  86. return sc;
  87. }
  88. //+--------------------------------------------------------------
  89. //
  90. // Member: CDFBasis::WaitForWriteAccess, public
  91. //
  92. // Synopsis: attempts to obtain write access
  93. //
  94. // Arguments: [dwTimeout] - in milliseconds
  95. // [ulOpenLock] - lock index for this open docfile
  96. //
  97. // History: 30-Apr-96 HenryLee Created
  98. //
  99. // Notes: tree mutex must be taken
  100. //
  101. //---------------------------------------------------------------
  102. HRESULT CDFBasis::WaitForWriteAccess (DWORD dwTimeout, CGlobalContext *pgc)
  103. {
  104. olDebugOut((DEB_ITRACE,"In CDFBasis::WaitForWriteAccess(%d)\n",dwTimeout));
  105. HRESULT sc = S_OK;
  106. BOOL fUpdateLocked = FALSE;
  107. BOOL fDenyLocked = FALSE;
  108. ULARGE_INTEGER cbLength = {0,0};
  109. ULARGE_INTEGER ulOffset = {0,0};
  110. ILockBytes *plst = GetBase();
  111. const ULONG ulMask = 0xFFFFFFFF;
  112. // lock out other opens
  113. ULISetLow(ulOffset, OUPDATE & ulMask);
  114. ULISetLow(cbLength, 1);
  115. olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  116. fUpdateLocked = TRUE;
  117. // lock out future readers
  118. ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask);
  119. ULISetLow(cbLength, COPENLOCKS);
  120. olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  121. fDenyLocked = TRUE;
  122. // try to identify current readers
  123. sc = TryReadLocks (pgc, ulMask);
  124. if (sc == STG_E_LOCKVIOLATION && dwTimeout != 0)
  125. {
  126. const DWORD dwWaitInitial = 100;
  127. DWORD dwWait = dwWaitInitial, dwWaitTotal = 0;
  128. for (;;)
  129. {
  130. sc = TryReadLocks (pgc, ulMask);
  131. if (sc != STG_E_LOCKVIOLATION || dwWaitTotal >= dwTimeout)
  132. {
  133. break;
  134. }
  135. Sleep(dwWait);
  136. dwWaitTotal += dwWait;
  137. dwWait *= 2;
  138. }
  139. }
  140. EH_Err:
  141. if (fDenyLocked && !SUCCEEDED(sc))
  142. {
  143. ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask);
  144. ULISetLow(cbLength, COPENLOCKS);
  145. olVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  146. }
  147. if (fUpdateLocked)
  148. {
  149. ULISetLow(ulOffset, OUPDATE & ulMask);
  150. ULISetLow(cbLength, 1);
  151. olVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  152. }
  153. if (sc == STG_E_LOCKVIOLATION) sc = STG_E_INUSE;
  154. if (SUCCEEDED(sc)) _fWriteLocked = TRUE;
  155. olDebugOut((DEB_ITRACE,"Out CDFBasis::WaitForWriteAccess(%x)\n", sc));
  156. return sc;
  157. };
  158. //+--------------------------------------------------------------
  159. //
  160. // Member: CDFBasis::ReleaseWriteAccess, public
  161. //
  162. // Synopsis: relinquishes write access
  163. // releases all locks except for ulOpenLock
  164. //
  165. // History: 30-Apr-96 HenryLee Created
  166. //
  167. // Notes: tree mutex must be taken
  168. //
  169. //---------------------------------------------------------------
  170. HRESULT CDFBasis::ReleaseWriteAccess ()
  171. {
  172. olDebugOut((DEB_ITRACE,"In CDFBasis::ReleaseWriteAccess()\n"));
  173. HRESULT sc = S_OK;
  174. BOOL fUpdateLocked = FALSE;
  175. ULARGE_INTEGER cbLength = {0,0};
  176. ULARGE_INTEGER ulOffset = {0,0};
  177. const ULONG ulMask = 0xFFFFFFFF;
  178. ILockBytes *plst = GetBase();
  179. // lock out other opens
  180. ULISetLow(ulOffset, OUPDATE & ulMask);
  181. ULISetLow(cbLength, 1);
  182. olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  183. fUpdateLocked = TRUE;
  184. // undo WaitForWriteAccess
  185. ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask);
  186. ULISetLow(cbLength, COPENLOCKS);
  187. olChk(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  188. EH_Err:
  189. if (fUpdateLocked)
  190. {
  191. ULISetLow(ulOffset, OUPDATE & ulMask);
  192. ULISetLow(cbLength, 1);
  193. olVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
  194. }
  195. if (SUCCEEDED(sc)) _fWriteLocked = FALSE;
  196. olDebugOut((DEB_ITRACE,"Out CDFBasis::ReleaseWriteAccess(%x)\n", sc));
  197. return sc;
  198. };
  199. #endif