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.

568 lines
12 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // cache.cpp
  4. //
  5. // XML document cache.
  6. //
  7. // History:
  8. //
  9. // 4/15/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "persist.h"
  17. #include "cache.h"
  18. #include "cdfidl.h"
  19. #include "xmlutil.h"
  20. #include "dll.h"
  21. //
  22. // Cache functions.
  23. //
  24. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  25. //
  26. // *** Cache_Initialize ***
  27. //
  28. // Prepare the XML document cache for use.
  29. //
  30. ////////////////////////////////////////////////////////////////////////////////
  31. void
  32. Cache_Initialize(
  33. void
  34. )
  35. {
  36. ASSERT(NULL == g_pCache);
  37. InitializeCriticalSection(&g_csCache);
  38. return;
  39. }
  40. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  41. //
  42. // *** Cache_Initialize ***
  43. //
  44. // Deactivate the cache.
  45. //
  46. ////////////////////////////////////////////////////////////////////////////////
  47. void
  48. Cache_Deinitialize(
  49. void
  50. )
  51. {
  52. // MSXML has gone away at this point
  53. // Cache_FreeAll();
  54. DeleteCriticalSection(&g_csCache);
  55. return;
  56. }
  57. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  58. //
  59. // *** Cache_EnterWriteLock ***
  60. //
  61. // Obtain exclusive use of the XML document cache.
  62. //
  63. ////////////////////////////////////////////////////////////////////////////////
  64. void
  65. Cache_EnterWriteLock(
  66. void
  67. )
  68. {
  69. EnterCriticalSection(&g_csCache);
  70. return;
  71. }
  72. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  73. //
  74. // *** Cache_EnterWriteLock ***
  75. //
  76. // Release exclusive use of the XML document cache.
  77. //
  78. ////////////////////////////////////////////////////////////////////////////////
  79. void
  80. Cache_LeaveWriteLock(
  81. void
  82. )
  83. {
  84. LeaveCriticalSection(&g_csCache);
  85. return;
  86. }
  87. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  88. //
  89. // *** Cache_EnterReadLock ***
  90. //
  91. // Exclude writes to the the items list. Currently this also excludes other
  92. // reads. If need be this can be modified to allow multiple reads while
  93. // still excluding writes.
  94. //
  95. ////////////////////////////////////////////////////////////////////////////////
  96. void
  97. Cache_EnterReadLock(
  98. void
  99. )
  100. {
  101. EnterCriticalSection(&g_csCache);
  102. return;
  103. }
  104. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  105. //
  106. // *** Cache_LeaveReadLock ***
  107. //
  108. // Release a read hold on the use of the XML document cache.
  109. //
  110. ////////////////////////////////////////////////////////////////////////////////
  111. void
  112. Cache_LeaveReadLock(
  113. void
  114. )
  115. {
  116. LeaveCriticalSection(&g_csCache);
  117. return;
  118. }
  119. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  120. //
  121. // *** Cache_AddItem ***
  122. //
  123. //
  124. // Description:
  125. // Add an xml document to the cache.
  126. //
  127. // Parameters:
  128. // [In] szURL - The URL of the cdf file.
  129. // [In] pIXMLDocument - The already parsed xml document.
  130. //
  131. // Return:
  132. // S_OK if the document was added to the cache.
  133. // E_OUTOFMEMORY if the document couldn't be aded to the cache.
  134. //
  135. // Comments:
  136. // The xml document is AddRefed when inserted into the cache and
  137. // Released on removal from the cache.
  138. //
  139. ////////////////////////////////////////////////////////////////////////////////
  140. HRESULT
  141. Cache_AddItem(
  142. LPTSTR szURL,
  143. IXMLDocument* pIXMLDocument,
  144. DWORD dwParseFlags,
  145. FILETIME ftLastMod,
  146. DWORD dwCacheCount
  147. )
  148. {
  149. ASSERT(szURL);
  150. ASSERT(pIXMLDocument);
  151. Cache_EnterWriteLock();
  152. HRESULT hr;
  153. PCACHEITEM pNewItem = new CACHEITEM;
  154. if (pNewItem)
  155. {
  156. LPTSTR szURLCopy = (LPTSTR)new TCHAR[(StrLen(szURL) + 1)];
  157. if (szURLCopy)
  158. {
  159. //
  160. // Limit the cache to one item by freeing all current items.
  161. //
  162. Cache_FreeAll();
  163. //
  164. // Remove an old cache entry for this url if it exists.
  165. //
  166. // Check no longer needed since we just cleared the cache.
  167. /*IXMLDocument* pIXMLDocumentOld;
  168. if (SUCCEEDED(Cache_QueryItem(szURL, &pIXMLDocumentOld,
  169. PARSE_LOCAL)))
  170. {
  171. ASSERT(pIXMLDocumentOld);
  172. Cache_RemoveItem(szURL);
  173. pIXMLDocumentOld->Release();
  174. }*/
  175. StrCpy(szURLCopy, szURL);
  176. pIXMLDocument->AddRef();
  177. pNewItem->szURL = szURLCopy;
  178. pNewItem->dwParseFlags = dwParseFlags;
  179. pNewItem->ftLastMod = ftLastMod;
  180. pNewItem->dwCacheCount = dwCacheCount;
  181. pNewItem->pIXMLDocument = pIXMLDocument;
  182. //
  183. // REVIEW: Check for duplicate cache items?
  184. //
  185. pNewItem->pNext = g_pCache;
  186. g_pCache = pNewItem;
  187. hr = S_OK;
  188. }
  189. else
  190. {
  191. delete pNewItem;
  192. hr = E_OUTOFMEMORY;
  193. }
  194. }
  195. else
  196. {
  197. hr = E_OUTOFMEMORY;
  198. }
  199. Cache_LeaveWriteLock();
  200. return hr;
  201. }
  202. //
  203. //
  204. //
  205. BOOL
  206. IsEmptyTime(
  207. FILETIME ft
  208. )
  209. {
  210. return (0 == ft.dwLowDateTime && 0 == ft.dwHighDateTime);
  211. }
  212. BOOL
  213. IsEqualTime(
  214. FILETIME ft1,
  215. FILETIME ft2
  216. )
  217. {
  218. return ((ft1.dwLowDateTime == ft2.dwLowDateTime) &&
  219. (ft1.dwHighDateTime == ft2.dwHighDateTime));
  220. }
  221. void
  222. Cache_RefreshItem(
  223. CACHEITEM* pItem,
  224. LPTSTR pszLocalFile,
  225. FILETIME ftLastMod
  226. )
  227. {
  228. ASSERT(pItem);
  229. //
  230. // Try and parse the cdf from the wininet cache.
  231. //
  232. IXMLDocument* pIXMLDocument;
  233. HRESULT hr;
  234. DLL_ForcePreloadDlls(PRELOAD_MSXML);
  235. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  236. IID_IXMLDocument, (void**)&pIXMLDocument);
  237. BOOL bCoInit = FALSE;
  238. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  239. SUCCEEDED(CoInitialize(NULL)))
  240. {
  241. bCoInit = TRUE;
  242. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  243. IID_IXMLDocument, (void**)&pIXMLDocument);
  244. }
  245. if (SUCCEEDED(hr))
  246. {
  247. ASSERT(pIXMLDocument);
  248. hr = XML_SynchronousParse(pIXMLDocument, pszLocalFile);
  249. if (FAILED(hr))
  250. pIXMLDocument->Release();
  251. }
  252. if (bCoInit)
  253. CoUninitialize();
  254. //
  255. // If the new cdf was parsed, replace the old one.
  256. //
  257. if (SUCCEEDED(hr))
  258. {
  259. pItem->pIXMLDocument->Release();
  260. pItem->pIXMLDocument = pIXMLDocument;
  261. pItem->ftLastMod = ftLastMod;
  262. }
  263. return;
  264. }
  265. BOOL
  266. Cache_IsItemFresh(
  267. CACHEITEM* pItem,
  268. DWORD dwParseFlags
  269. )
  270. {
  271. ASSERT(pItem);
  272. BOOL fRet;
  273. DWORD dwCurrentCacheCount = g_dwCacheCount;
  274. //
  275. // If the caller asked for "Net" quality data and we only have "Local" data
  276. // then throw the "Local" data away. The resultant cache miss will cause
  277. // the caller to pick up fresher data.
  278. //
  279. if ((dwParseFlags & PARSE_NET) && (pItem->dwParseFlags & PARSE_LOCAL))
  280. {
  281. fRet = FALSE;
  282. }
  283. else
  284. {
  285. fRet = TRUE;
  286. //
  287. // If the global cache counter is greater than the counter for this
  288. // item, then a cdf has been added to the cache.
  289. //
  290. if (dwCurrentCacheCount > pItem->dwCacheCount)
  291. {
  292. //
  293. // Get the last mod time from the the cdf in the wininet cache.
  294. //
  295. FILETIME ftLastMod;
  296. TCHAR szLocalFile[MAX_PATH];
  297. if (SUCCEEDED(URLGetLocalFileName(pItem->szURL, szLocalFile,
  298. ARRAYSIZE(szLocalFile), &ftLastMod)))
  299. {
  300. //
  301. // If the last mod times are different then the cdf in the
  302. // wininet cache is newer, pick it up.
  303. // If there are no last modified times then do the conservative
  304. // thing and pick up the cdf from the wininet cache.
  305. //
  306. if ((IsEmptyTime(ftLastMod) && IsEmptyTime(pItem->ftLastMod)) ||
  307. !IsEqualTime(ftLastMod, pItem->ftLastMod))
  308. {
  309. Cache_RefreshItem(pItem, szLocalFile, ftLastMod);
  310. }
  311. }
  312. pItem->dwCacheCount = dwCurrentCacheCount;
  313. }
  314. }
  315. return fRet;
  316. }
  317. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  318. //
  319. // *** Cache_QueryItem ***
  320. //
  321. //
  322. // Description:
  323. // Returns a xml document from the cache if it is found.
  324. //
  325. // Parameters:
  326. // [In] szURL - The URL associated with the xml document.
  327. // [Out] ppIXMLDocument - A pointer that receives the xml document.
  328. //
  329. // Return:
  330. // S_OK if the document associtaed with the given URL is found in the cache.
  331. // E_FAIL if the document isn't in the cache.
  332. //
  333. // Comments:
  334. // The returned pointer is AddRefed. The caller isresposible for releasing
  335. // this pointer.
  336. //
  337. ////////////////////////////////////////////////////////////////////////////////
  338. HRESULT
  339. Cache_QueryItem(
  340. LPTSTR szURL,
  341. IXMLDocument** ppIXMLDocument,
  342. DWORD dwParseFlags
  343. )
  344. {
  345. ASSERT(szURL);
  346. ASSERT(ppIXMLDocument);
  347. HRESULT hr = E_FAIL;
  348. Cache_EnterReadLock();
  349. PCACHEITEM pItem = g_pCache;
  350. //
  351. // REVIEW: Use CompareUrl from shlwapip?
  352. //
  353. while (pItem && !StrEql(szURL, pItem->szURL))
  354. pItem = pItem->pNext;
  355. if (pItem)
  356. {
  357. if (Cache_IsItemFresh(pItem, dwParseFlags))
  358. {
  359. ASSERT(pItem->pIXMLDocument);
  360. pItem->pIXMLDocument->AddRef();
  361. *ppIXMLDocument = pItem->pIXMLDocument;
  362. hr = S_OK;
  363. }
  364. else
  365. {
  366. Cache_RemoveItem(szURL);
  367. }
  368. }
  369. Cache_LeaveReadLock();
  370. ASSERT(SUCCEEDED(hr) && ppIXMLDocument || FAILED(hr));
  371. return hr;
  372. }
  373. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  374. //
  375. // *** Cache_FreeAll ***
  376. //
  377. //
  378. // Description:
  379. // Frees all items from the xml document cache.
  380. //
  381. // Parameters:
  382. // None.
  383. //
  384. // Return:
  385. // None.
  386. //
  387. // Comments:
  388. // Frees all memory held in the xml document cache.
  389. //
  390. ////////////////////////////////////////////////////////////////////////////////
  391. void
  392. Cache_FreeAll(
  393. void
  394. )
  395. {
  396. Cache_EnterWriteLock();
  397. PCACHEITEM pItem = g_pCache;
  398. g_pCache = NULL;
  399. Cache_LeaveWriteLock();
  400. while (pItem)
  401. {
  402. PCACHEITEM pNext = pItem->pNext;
  403. ASSERT(pItem->szURL);
  404. ASSERT(pItem->pIXMLDocument);
  405. pItem->pIXMLDocument->Release();
  406. delete [] pItem->szURL;
  407. delete pItem;
  408. pItem = pNext;
  409. }
  410. return;
  411. }
  412. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  413. //
  414. // *** Cache_FreeItem ***
  415. //
  416. //
  417. // Description:
  418. // Frees item associated with given URL from the xml document cache.
  419. //
  420. // Parameters:
  421. // LPTSTR szURL
  422. //
  423. // Return:
  424. // HRESULT S_OK if item in cache and deleted, E_FAIL if item not in cache
  425. //
  426. ////////////////////////////////////////////////////////////////////////////////
  427. HRESULT
  428. Cache_RemoveItem(
  429. LPCTSTR szURL
  430. )
  431. {
  432. ASSERT(szURL);
  433. HRESULT hr;
  434. Cache_EnterWriteLock();
  435. PCACHEITEM pItem = g_pCache;
  436. PCACHEITEM pItemPrev = NULL;
  437. //
  438. // REVIEW: Use CompareUrl from slwapip?.
  439. //
  440. while (pItem && !StrEql(szURL, pItem->szURL))
  441. {
  442. pItemPrev = pItem;
  443. pItem = pItem->pNext;
  444. }
  445. if (pItem)
  446. {
  447. ASSERT(pItem->pIXMLDocument);
  448. if (pItemPrev)
  449. {
  450. pItemPrev->pNext = pItem->pNext;
  451. }
  452. else
  453. {
  454. g_pCache = pItem->pNext; // handle remove first item case
  455. }
  456. pItem->pIXMLDocument->Release();
  457. delete [] pItem->szURL;
  458. delete pItem;
  459. hr = S_OK;
  460. }
  461. else
  462. {
  463. hr = E_FAIL;
  464. }
  465. Cache_LeaveWriteLock();
  466. return hr;
  467. }