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.

363 lines
8.1 KiB

  1. #include "stdafx.h"
  2. //#include <stdio.h>
  3. #define StreamName L"ResetTable"
  4. ULONG CXResetData::BinarySearch(
  5. LPRESETREC pTbl,
  6. ULONG ulStart,
  7. ULONG ulEnd,
  8. ULARGE_INTEGER uliKey
  9. )
  10. {
  11. #ifdef _DEBUG
  12. static int cLoop; // BugBug! This will fail in multithreaded situations!
  13. cLoop++;
  14. RonM_ASSERT(cLoop < 20);
  15. #endif
  16. if (ulStart == ulEnd)
  17. {
  18. DEBUGCODE(cLoop = 0;)
  19. return ulStart;
  20. }
  21. else
  22. if (ulStart == (ulEnd -1))
  23. {
  24. #ifdef _DEBUG
  25. cLoop = 0;
  26. #endif
  27. if (CULINT(uliKey) >= CULINT(ulEnd * m_ulBlockSize))
  28. return ulEnd;
  29. else
  30. return ulStart;
  31. }
  32. ULONG ulMid = (ulEnd + ulStart) / 2;
  33. if (CULINT(uliKey) <= CULINT(ulMid * m_ulBlockSize))
  34. {
  35. return BinarySearch(pTbl, ulStart, ulMid, uliKey);
  36. }
  37. else
  38. {
  39. return BinarySearch(pTbl, ulMid, ulEnd, uliKey);
  40. }
  41. }
  42. ULONG CXResetData::FindRecord(
  43. ULARGE_INTEGER uliOffset,
  44. ULARGE_INTEGER *puliXOffset,
  45. BOOL *pfLastRecord
  46. )
  47. {
  48. ULONG ulRecNum;
  49. if (m_cFillRecs)
  50. {
  51. ulRecNum = BinarySearch(m_pSyncTbl, 0, m_cFillRecs - 1, uliOffset);
  52. *puliXOffset = (m_pSyncTbl + ulRecNum)->uliXOffset;
  53. *pfLastRecord = (ulRecNum == (m_cFillRecs - 1));
  54. }
  55. return ulRecNum;
  56. }
  57. BOOL CXResetData::FGetRecord(
  58. ULONG ulRecNum,
  59. ULARGE_INTEGER *puliOffset,
  60. ULARGE_INTEGER *puliXOffset,
  61. BOOL *pfLastRecord
  62. )
  63. {
  64. if (ulRecNum >= m_cFillRecs)
  65. return FALSE;
  66. *puliOffset = CULINT(ulRecNum * m_ulBlockSize).Uli();
  67. *puliXOffset = (m_pSyncTbl + ulRecNum)->uliXOffset;
  68. *pfLastRecord = (ulRecNum == (m_cFillRecs - 1));
  69. return TRUE;
  70. }
  71. HRESULT CXResetData::DeleteRecord(ULONG ulRecNum)
  72. {
  73. HRESULT hr = NO_ERROR;
  74. //Verify we are deleting valid record
  75. if (ulRecNum < m_cFillRecs)
  76. {
  77. m_cFillRecs--;
  78. m_cEmptyRecs++;
  79. }
  80. else
  81. {
  82. hr = E_FAIL;
  83. }
  84. return hr;
  85. }
  86. HRESULT CXResetData::AddRecord(ULARGE_INTEGER uliOffset, ULARGE_INTEGER uliXOffset)
  87. {
  88. if (m_cEmptyRecs <= 0)
  89. {
  90. //double the size of reset table for future use
  91. LPRESETREC prec = m_pSyncTbl;
  92. ULONG nTotalRecs = (m_cFillRecs ? m_cFillRecs : 64) * 2;
  93. if (m_pSyncTbl = New sResetRec[nTotalRecs])
  94. {
  95. //copy old table to newly created table with bigger size
  96. if (prec)
  97. {
  98. memCpy((LPBYTE)m_pSyncTbl, (LPBYTE)prec, m_cFillRecs * sizeof(sResetRec));
  99. delete prec;
  100. }
  101. m_cEmptyRecs = nTotalRecs - m_cFillRecs;
  102. }
  103. else
  104. {
  105. m_pSyncTbl = prec;
  106. return STG_E_INSUFFICIENTMEMORY;
  107. }
  108. }
  109. LPRESETREC prec = m_pSyncTbl + m_cFillRecs;
  110. prec->uliXOffset = uliXOffset;
  111. m_cFillRecs++;
  112. m_cEmptyRecs--;
  113. m_fDirty = TRUE;
  114. return NO_ERROR;
  115. }
  116. CXResetData::CXResetData(
  117. /*IStorage *pstg*/
  118. )
  119. {
  120. m_fDirty = FALSE;
  121. m_pStm = NULL;
  122. m_pStg = NULL;
  123. m_cFillRecs = 0;
  124. m_cEmptyRecs =0;
  125. m_pSyncTbl = NULL;
  126. }
  127. CXResetData::~CXResetData()
  128. {
  129. if (m_pSyncTbl)
  130. {
  131. delete m_pSyncTbl;
  132. m_pSyncTbl = NULL;
  133. }
  134. if (m_pStm)
  135. m_pStm->Release();
  136. if (m_pStg)
  137. m_pStg->Release();
  138. }
  139. HRESULT CXResetData::InitResetTable(IStorage *pStg,
  140. ULARGE_INTEGER *puliVSpaceSize,
  141. ULARGE_INTEGER *puliTxSpaceSize,
  142. ULONG ulBlockSize)
  143. {
  144. m_pStg = pStg;
  145. m_pStg->AddRef();
  146. HRESULT hr = NO_ERROR;
  147. *puliVSpaceSize = CULINT(0).Uli();
  148. *puliTxSpaceSize = CULINT(0).Uli();
  149. m_ulBlockSize = ulBlockSize;
  150. if (SUCCEEDED(hr = GetResetTblStream(pStg, &m_pStm)))
  151. {
  152. sHeader header;
  153. ULONG cbBytesRead = 0;
  154. int hr = m_pStm->Read((LPVOID)&header, sizeof(sHeader), &cbBytesRead);
  155. if (SUCCEEDED(hr) && (cbBytesRead == sizeof(sHeader)))
  156. {
  157. *puliVSpaceSize = header.uliVSpaceSize;
  158. *puliTxSpaceSize = header.uliTxSpaceSize;
  159. m_cFillRecs = header.cRecs;
  160. if (m_cFillRecs > 0)
  161. {
  162. //allocate reset table with record
  163. //count which is double of m_cFillRecs.
  164. ULONG nTotalRecs = m_cFillRecs * 2;
  165. if (m_pSyncTbl = New sResetRec[nTotalRecs])
  166. {
  167. m_cEmptyRecs = nTotalRecs - m_cFillRecs;
  168. LARGE_INTEGER dliB;
  169. ULARGE_INTEGER dliBFinal;
  170. dliB.HighPart = 0;
  171. dliB. LowPart = header.cbSize;
  172. dliBFinal.HighPart = 0;
  173. dliBFinal. LowPart = 0;
  174. if (SUCCEEDED(hr = m_pStm->Seek(dliB, STREAM_SEEK_SET, &dliBFinal)))
  175. {
  176. if (header.dwVerInfo == 1)
  177. {
  178. sResetRecV1 sRecV1;
  179. ULONG cb;
  180. for (int iRec = 0; SUCCEEDED(hr) && (iRec < m_cFillRecs); iRec++)
  181. {
  182. hr = m_pStm->Read((LPVOID)&sRecV1,
  183. sizeof(sResetRecV1),
  184. &cb);
  185. cbBytesRead += cb;
  186. (m_pSyncTbl + iRec)->uliXOffset = sRecV1.uliXOffset;
  187. }
  188. }
  189. else if (header.dwVerInfo == LZX_Current_Version)
  190. {
  191. hr = m_pStm->Read((LPVOID)(m_pSyncTbl),
  192. m_cFillRecs * sizeof(sResetRec),
  193. &cbBytesRead);
  194. }//read
  195. }//seek
  196. }// new
  197. else
  198. {
  199. hr = STG_E_INSUFFICIENTMEMORY;
  200. }
  201. }//no. of entries in table > 0
  202. }//read header
  203. }//open reset table stream
  204. return hr;
  205. }
  206. HRESULT CXResetData::DumpStream(IStream *pTempStrm, LPSTR pFileName)
  207. {
  208. HRESULT hr = NO_ERROR;
  209. #if 0 //test code
  210. FILE *file = fopen(pFileName, "w" );
  211. if (file != NULL)
  212. {
  213. RonM_ASSERT(pTempStrm != NULL);
  214. HRESULT hr = NO_ERROR;
  215. BYTE lpBuf[2048];
  216. if (SUCCEEDED(hr = pTempStrm->Seek(CLINT(0).Li(), STREAM_SEEK_SET, 0)))
  217. {
  218. ULONG cbToRead = sizeof(lpBuf);
  219. ULONG cbWritten;
  220. ULONG cbRead = cbToRead;
  221. while (SUCCEEDED(hr) && (cbRead == cbToRead))
  222. {
  223. if (SUCCEEDED(hr = pTempStrm->Read(lpBuf, cbToRead, &cbRead)))
  224. {
  225. cbWritten = fwrite(lpBuf, sizeof(BYTE), cbRead, file);
  226. RonM_ASSERT(cbRead == cbWritten);
  227. if (cbRead != cbWritten)
  228. hr = E_FAIL;
  229. }//ReadAt
  230. }//while
  231. }//seek
  232. fclose(file);
  233. }
  234. else
  235. hr = E_FAIL;
  236. #endif //end test code
  237. return hr;
  238. }
  239. HRESULT CXResetData::CommitResetTable(ULARGE_INTEGER uliVSpaceSize,
  240. ULARGE_INTEGER uliTxSpaceSize)
  241. {
  242. RonM_ASSERT(m_pStm);
  243. HRESULT hr = NO_ERROR;
  244. if (m_fDirty)
  245. {
  246. sHeader header;
  247. //latest version
  248. header.dwVerInfo = LZX_Current_Version;
  249. header.cRecs = m_cFillRecs;
  250. header.cbSize = sizeof(sHeader);
  251. header.cbRecSize = sizeof(sResetRec);
  252. header.uliVSpaceSize = uliVSpaceSize;
  253. header.uliTxSpaceSize = uliTxSpaceSize;
  254. header.ulBlockSize = m_ulBlockSize;
  255. header.unused = 0;
  256. ULONG cbWritten;
  257. LARGE_INTEGER dliB;
  258. ULARGE_INTEGER dliBFinal;
  259. dliB.HighPart = 0;
  260. dliB. LowPart = 0;
  261. dliBFinal.HighPart = 0;
  262. dliBFinal. LowPart = 0;
  263. if (SUCCEEDED(hr = m_pStm->Seek(dliB, STREAM_SEEK_SET, &dliBFinal)))
  264. {
  265. hr = m_pStm->Write((LPVOID)&header, sizeof(header), &cbWritten);
  266. if (SUCCEEDED(hr) && (cbWritten == sizeof(header)))
  267. {
  268. if (SUCCEEDED(hr = m_pStm->Write((LPVOID)m_pSyncTbl,
  269. sizeof(sResetRec) * m_cFillRecs,
  270. &cbWritten)))
  271. {
  272. if (cbWritten != sizeof(sResetRec) * m_cFillRecs)
  273. hr = E_FAIL;
  274. else
  275. m_fDirty = FALSE;
  276. }//write table
  277. }//write header
  278. }//seek
  279. }//if table dirty
  280. //test code
  281. #ifdef _DEBUG
  282. DumpStream(m_pStm, "c:\\dbg.tbl");
  283. #else
  284. DumpStream(m_pStm, "c:\\rel.tbl");
  285. #endif
  286. return hr;
  287. }
  288. HRESULT CXResetData::GetResetTblStream(IStorage *pStg, IStream **ppStm)
  289. {
  290. HRESULT hr;
  291. if (STG_E_FILENOTFOUND == (hr = pStg->OpenStream(StreamName,
  292. 0,
  293. STGM_READWRITE | STGM_SHARE_EXCLUSIVE| STGM_DIRECT,
  294. 0,
  295. ppStm)))
  296. {
  297. hr = pStg->CreateStream(StreamName,
  298. STGM_READWRITE | STGM_SHARE_EXCLUSIVE
  299. | STGM_DIRECT
  300. | STGM_CREATE,
  301. 0,
  302. 0,
  303. ppStm);
  304. }//open stream
  305. return hr;
  306. }