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.

489 lines
13 KiB

  1. // wwuperst.cpp: Implementation of wordwheel update persistance interface
  2. #include <mvopsys.h>
  3. #ifdef _DEBUG
  4. static char s_aszModule[] = __FILE__; /* For error report */
  5. #endif
  6. #include <windows.h>
  7. #include <iterror.h>
  8. #include <atlinc.h>
  9. #include <itpropl.h>
  10. #include <ccfiles.h>
  11. #include <itsortid.h>
  12. #include "wwumain.h"
  13. // Type Definitions ***********************************************************
  14. typedef struct
  15. {
  16. DWORD cKeys;
  17. DWORD ilOffset;
  18. } RECKW, FAR * PRECKW;
  19. STDMETHODIMP CITWordWheelUpdate::Save(IStorage *pStgSave, BOOL fSameAsLoad)
  20. {
  21. if (FALSE == m_fInitialized || NULL == m_piitskSortKey)
  22. return SetErrReturn(E_NOTINIT);
  23. // Create the permanent header stream
  24. HRESULT hr;
  25. IStream *pHeaderStream;
  26. if (FAILED(hr = pStgSave->CreateStream
  27. (SZ_BTREE_HEADER, STGM_WRITE, 0, 0, &pHeaderStream)))
  28. return hr;
  29. ResolveGlobalProperties (pHeaderStream);
  30. // Handle occurence/term data
  31. DWORD dwSize = GetFileSize(m_hTempFile, NULL);
  32. CloseHandle(m_hTempFile);
  33. m_hTempFile = NULL;
  34. if (dwSize)
  35. {
  36. if (FAILED(hr = BuildPermanentFiles(pStgSave, pHeaderStream)))
  37. {
  38. pHeaderStream->Release();
  39. return hr;
  40. }
  41. }
  42. DeleteFile(m_szTempFile);
  43. pHeaderStream->Release();
  44. return S_OK;
  45. } /* Save */
  46. /***************************************************************
  47. * @doc INTERNAL
  48. *
  49. * @api HRESULT FAR PASCAL | BuildKeywordFiles | This routine is called
  50. * at the end of compilation to generate the appropriate
  51. * .MVB subfiles to support runtime keyword stuff.
  52. *
  53. ****************************************************************/
  54. HRESULT WINAPI CITWordWheelUpdate::BuildPermanentFiles
  55. (IStorage *pIStorage, IStream *pHeaderStream)
  56. {
  57. RECKW reckw;
  58. HBT hbt;
  59. IStream *pDataStream = NULL;
  60. HRESULT hr; // Return code
  61. LKW kwCur, kwNext;
  62. LPSTR pCur, pEnd;
  63. char fEOF;
  64. DWORD dwWritten, dwTemp;
  65. LPSTR pInput; // Input buffer
  66. void * pvNewKey; // Used to resolve duplicate keys
  67. DWORD dwBufferSize = CBMAX_KWENTRY; // Used to resolve duplicate keys
  68. LPBYTE pKeyDataBuffer = NULL, pOccDataBuffer = NULL;
  69. // Allocate temp buffers
  70. pvNewKey = (void *)new BYTE[dwBufferSize];
  71. if(NULL == pvNewKey)
  72. return SetErrReturn(E_OUTOFMEMORY);
  73. pKeyDataBuffer = new BYTE[m_cbMaxKeyData];
  74. if (pKeyDataBuffer == NULL)
  75. {
  76. hr = E_OUTOFMEMORY;
  77. goto exit0;
  78. }
  79. pOccDataBuffer = new BYTE[m_cbMaxOccData];
  80. if (pOccDataBuffer == NULL)
  81. {
  82. hr = E_OUTOFMEMORY;
  83. goto exit0;
  84. }
  85. // Sort the input file using our own sort function
  86. if (S_OK !=(hr = FileSort(NULL,(LPB)m_szTempFile,
  87. NULL, NULL, 0, CompareKeys, m_piitskSortKey, ScanTempFile, NULL)))
  88. {
  89. exit0:
  90. delete pvNewKey;
  91. if(pKeyDataBuffer)
  92. delete pKeyDataBuffer;
  93. if(pOccDataBuffer)
  94. delete pOccDataBuffer;
  95. return hr;
  96. }
  97. m_btParams.hfs = pIStorage;
  98. // *****************************
  99. // Map the input file to memory
  100. // *****************************
  101. pInput = MapSequentialReadFile(m_szTempFile, &dwTemp);
  102. if (!pInput)
  103. {
  104. SetErrCode(&hr, E_FAIL);
  105. goto exit0;
  106. }
  107. pCur = pInput;
  108. pEnd = pInput + dwTemp;
  109. hbt = HbtInitFill(SZ_BTREE_BTREE_A, &m_btParams, &hr);
  110. if (hbt == hNil)
  111. {
  112. exit2:
  113. UnmapViewOfFile(pInput);
  114. goto exit0;
  115. }
  116. BtreeSetExtSort(hbt, m_piitskSortKey);
  117. // **************************************
  118. // CREATE KEYWORD FILE IN MVB FILE SYSTEM
  119. // **************************************
  120. if (FAILED(hr = pIStorage->CreateStream
  121. (SZ_BTREE_DATA, STGM_WRITE, 0, 0, &pDataStream)))
  122. {
  123. exit4:
  124. if (pDataStream)
  125. pDataStream->Release();
  126. RcAbandonHbt(hbt);
  127. goto exit2;
  128. }
  129. // Process keywords until we get to the next set
  130. reckw.ilOffset = dwWritten = 0;
  131. fEOF = 0;
  132. pCur = ParseKeywordLine(pCur, &kwCur); // Load first record
  133. // Process occurence information
  134. while (!fEOF)
  135. {
  136. LARGE_INTEGER liNull = {0};
  137. DWORD cbKeyProp; // Size of the Key data block
  138. reckw.cKeys = 1;
  139. dwWritten = 0;
  140. // Handle properties for the key
  141. BOOL fNotDup = TRUE;
  142. cbKeyProp = 0;
  143. while (!fEOF && kwCur.bPropDest == C_PROPDEST_KEY)
  144. {
  145. if (fNotDup)
  146. {
  147. hr = FWriteData
  148. (pDataStream, &kwCur, &cbKeyProp, pKeyDataBuffer);
  149. if (FAILED(hr))
  150. goto exit4;
  151. fNotDup = FALSE;
  152. }
  153. if (pCur == pEnd)
  154. fEOF = TRUE;
  155. else
  156. pCur = ParseKeywordLine(pCur, &kwCur);
  157. }
  158. // cbKeyProp is an accumulated total for all previous writes
  159. // if we didin't write anything we must at least write a
  160. // record size of zero to the stream.
  161. if (0 == cbKeyProp)
  162. {
  163. dwTemp = 0;
  164. pDataStream->Write (&dwTemp, sizeof (DWORD), &cbKeyProp);
  165. }
  166. // You must have occurrence information -- not just key data
  167. if (fEOF)
  168. {
  169. SetErrCode(&hr, E_FAIL);
  170. goto exit4;
  171. }
  172. if (FAILED(hr = FWriteData
  173. (pDataStream, &kwCur, &dwWritten, pOccDataBuffer)))
  174. goto exit4;
  175. if (pEnd != pCur)
  176. pCur = ParseKeywordLine(pCur, &kwNext);
  177. else
  178. fEOF = 1;
  179. // ********************************************************
  180. // ********* PROCESS ALL IDENTICAL ENTRIES **********
  181. // ********************************************************
  182. while (!fEOF)
  183. {
  184. LONG lResult;
  185. hr = m_piitskSortKey->Compare(kwCur.szKeyword + sizeof(DWORD),
  186. kwNext.szKeyword + sizeof(DWORD), &lResult, NULL);
  187. ITASSERT(SUCCEEDED(hr));
  188. if(lResult)
  189. break;
  190. // These keys are identical, but the user may want to calapse
  191. // them for some reason. Maybe he has custom data embedded in
  192. // the keys.
  193. hr = m_piitskSortKey->ResolveDuplicates(
  194. kwCur.szKeyword + sizeof(DWORD),
  195. kwNext.szKeyword + sizeof(DWORD),
  196. pvNewKey, &dwBufferSize);
  197. if(SUCCEEDED(hr))
  198. {
  199. // Verify that the user didn't alter the sort order!
  200. hr = m_piitskSortKey->Compare(
  201. kwCur.szKeyword + sizeof(DWORD),
  202. pvNewKey, &lResult, NULL);
  203. ITASSERT(SUCCEEDED(hr));
  204. if(lResult)
  205. {
  206. ITASSERT(FALSE);
  207. SetErrCode(&hr, E_UNEXPECTED);
  208. goto exit4;
  209. }
  210. // Copy the key to our local buffer
  211. MEMCPY(kwCur.szKeyword
  212. + sizeof(DWORD), pvNewKey, CBMAX_KWENTRY);
  213. }
  214. else if(hr != E_NOTIMPL)
  215. {
  216. ITASSERT(FALSE);
  217. goto exit4;
  218. }
  219. if (FAILED(hr = FWriteData
  220. (pDataStream, &kwNext, &dwWritten, pOccDataBuffer)))
  221. goto exit4;
  222. if (pEnd == pCur)
  223. fEOF = 1;
  224. else
  225. pCur = ParseKeywordLine(pCur, &kwNext);
  226. reckw.cKeys++;
  227. }
  228. // Add record into B-Tree
  229. if (FAILED (hr = RcFillHbt(hbt,
  230. (KEY)kwCur.szKeyword + sizeof(DWORD),(QV)&reckw)))
  231. goto exit4;
  232. reckw.ilOffset += dwWritten + cbKeyProp;
  233. LKW kwTemp = kwCur;
  234. kwCur = kwNext;
  235. kwNext = kwTemp;
  236. }
  237. // ***********************************************
  238. // CLOSE THE BTREE FOR THIS KEYWORD SET, CLOSE THE
  239. // .MVB SUBFILE, AND DISPOSE OF THE TEMPORARY FILE
  240. // ***********************************************
  241. pDataStream->Release();
  242. pDataStream = NULL;
  243. hr = RcFiniFillHbt(hbt);
  244. if (FAILED(hr))
  245. goto exit4;
  246. // ***********************************************
  247. // NOW, BUILD THE APPROPRIATE MAP FILE FOR EACH
  248. // KEYWORD SET USED BY THE THUMB ON THE SCROLL BOX
  249. // ***********************************************
  250. if (FAILED (hr = RcCreateBTMapHfs(pIStorage, hbt, SZ_WORDWHEEL_MAP_A)))
  251. goto exit4;
  252. if (FAILED (hr = RcCloseBtreeHbt(hbt)))
  253. goto exit4;
  254. // Write PROPERTY file (contains property headers)
  255. DWORD dwSize;
  256. if (m_lpbKeyHeader)
  257. {
  258. pHeaderStream->Write (&m_cbKeyHeader, sizeof (DWORD), &dwWritten);
  259. pHeaderStream->Write (m_lpbKeyHeader, m_cbKeyHeader, &dwWritten);
  260. }
  261. else
  262. {
  263. dwSize = 0;
  264. pHeaderStream->Write (&dwSize, sizeof (DWORD), &dwWritten);
  265. }
  266. // For now, we have no default data
  267. dwSize = 0;
  268. pHeaderStream->Write (&dwSize, sizeof (DWORD), &dwWritten);
  269. if (m_lpbOccHeader)
  270. {
  271. pHeaderStream->Write (&m_cbOccHeader, sizeof (DWORD), &dwWritten);
  272. pHeaderStream->Write (m_lpbOccHeader, m_cbOccHeader, &dwWritten);
  273. }
  274. else
  275. {
  276. dwSize = 0;
  277. pHeaderStream->Write (&dwSize, sizeof (DWORD), &dwWritten);
  278. }
  279. // For now, we have no default data
  280. dwSize = 0;
  281. pHeaderStream->Write (&dwSize, sizeof (DWORD), &dwWritten);
  282. // *****************
  283. // TIDY UP AND LEAVE
  284. // *****************
  285. hr = S_OK;
  286. goto exit2;
  287. } /* BuildPermanentFiles */
  288. STDMETHODIMP CITWordWheelUpdate::ResolveGlobalProperties
  289. (IStream *pHeaderStream)
  290. {
  291. DWORD dwSize, dwWritten;
  292. CloseHandle(m_hGlobalPropTempFile);
  293. m_hGlobalPropTempFile = NULL;
  294. if (!m_dwGlobalPropSize)
  295. {
  296. dwSize = 0;
  297. pHeaderStream->Write (&dwSize, sizeof (DWORD), &dwWritten);
  298. DeleteFile(m_szGlobalPropTempFile);
  299. return S_OK;
  300. }
  301. HRESULT hr;
  302. IITPropList *plTemp = NULL;
  303. LPSTR pInput = NULL;
  304. ULARGE_INTEGER ulSize;
  305. // Map the temp file to memory
  306. pInput = MapSequentialReadFile(m_szGlobalPropTempFile, &dwSize);
  307. if (NULL == pInput)
  308. {
  309. SetErrCode(&hr, E_FAIL);
  310. GlobalExit0:
  311. if (plTemp)
  312. plTemp->Release();
  313. if (pInput)
  314. UnmapViewOfFile (pInput);
  315. return hr;
  316. }
  317. // Create property list
  318. hr = CoCreateInstance(CLSID_IITPropList, NULL,
  319. CLSCTX_INPROC_SERVER, IID_IITPropList,(LPVOID *)&plTemp);
  320. if (FAILED(hr))
  321. goto GlobalExit0;
  322. // Load list from temp file
  323. if (FAILED (hr = plTemp->LoadFromMem (pInput, dwSize)))
  324. goto GlobalExit0;
  325. // Get list size
  326. plTemp->GetSizeMax(&ulSize);
  327. // Write the property list size
  328. hr = pHeaderStream->Write
  329. (&ulSize.LowPart, sizeof(ulSize.LowPart), &dwSize);
  330. if (FAILED(hr))
  331. goto GlobalExit0;
  332. // Write the property list
  333. if (FAILED(hr = plTemp->Save(pHeaderStream, TRUE)))
  334. goto GlobalExit0;
  335. plTemp->Release();
  336. UnmapViewOfFile (pInput);
  337. DeleteFile(m_szGlobalPropTempFile);
  338. return S_OK;
  339. } /* ResolveGlobalProperties */
  340. STDMETHODIMP CITWordWheelUpdate::GetClassID(CLSID *pClsID)
  341. {
  342. if (NULL == pClsID
  343. || IsBadWritePtr(pClsID, sizeof(CLSID)))
  344. return SetErrReturn(E_INVALIDARG);
  345. *pClsID = CLSID_IITWordWheelUpdate;
  346. return S_OK;
  347. } /* GetClassID */
  348. STDMETHODIMP CITWordWheelUpdate::IsDirty(void)
  349. {
  350. if (m_fIsDirty)
  351. return S_OK;
  352. return S_FALSE;
  353. } /* IsDirty */
  354. STDMETHODIMP CITWordWheelUpdate::Load(IStorage *pStg)
  355. {
  356. return SetErrReturn(E_NOTIMPL);
  357. } /* Load */
  358. STDMETHODIMP CITWordWheelUpdate::InitNew(IStorage *pStg)
  359. {
  360. if (m_pStorage)
  361. return SetErrReturn(CO_E_ALREADYINITIALIZED);
  362. if (NULL == pStg)
  363. return SetErrReturn(E_INVALIDARG);
  364. m_pStorage = pStg;
  365. pStg->AddRef();
  366. m_fIsDirty = FALSE;
  367. // Create a temp file
  368. char szTempPath [_MAX_PATH + 1];
  369. if (0 == GetTempPath(_MAX_PATH, szTempPath))
  370. return SetErrReturn(E_FILECREATE);
  371. if (0 == GetTempFileName(szTempPath, "WWU", 0, m_szTempFile))
  372. return SetErrReturn(E_FILECREATE);
  373. m_hTempFile = CreateFile
  374. (m_szTempFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  375. FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  376. if (INVALID_HANDLE_VALUE == m_hTempFile)
  377. return SetErrReturn(E_FILECREATE);
  378. if (0 == GetTempFileName(szTempPath, "WWU", 0, m_szGlobalPropTempFile))
  379. return SetErrReturn(E_FILECREATE);
  380. m_hGlobalPropTempFile = CreateFile(m_szGlobalPropTempFile,
  381. GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  382. FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  383. if (INVALID_HANDLE_VALUE == m_hGlobalPropTempFile)
  384. return SetErrReturn(E_FILECREATE);
  385. // Reset member variables
  386. m_dwEntryCount = 0;
  387. m_dwGlobalPropSize = 0;
  388. m_lpbKeyHeader = m_lpbOccHeader = NULL;
  389. m_cbMaxKeyData = m_cbMaxOccData = 0;
  390. m_fInitialized = TRUE;
  391. return S_OK;
  392. } /* InitNew */
  393. STDMETHODIMP CITWordWheelUpdate::SaveCompleted(IStorage *pStgNew)
  394. {
  395. if (pStgNew)
  396. {
  397. if (!m_pStorage)
  398. return SetErrReturn(E_UNEXPECTED);
  399. m_pStorage->Release();
  400. (m_pStorage = pStgNew)->AddRef();
  401. }
  402. m_fIsDirty = FALSE;
  403. return S_OK;
  404. } /* SaveCompleted */
  405. STDMETHODIMP CITWordWheelUpdate::HandsOffStorage(void)
  406. {
  407. return S_OK;
  408. } /* HandsOffStorage */