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.

569 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. size_t cch = StrLen(szURL) + 1;
  157. LPTSTR pszURLCopy = (LPTSTR)new TCHAR[cch];
  158. if (pszURLCopy)
  159. {
  160. //
  161. // Limit the cache to one item by freeing all current items.
  162. //
  163. Cache_FreeAll();
  164. //
  165. // Remove an old cache entry for this url if it exists.
  166. //
  167. // Check no longer needed since we just cleared the cache.
  168. /*IXMLDocument* pIXMLDocumentOld;
  169. if (SUCCEEDED(Cache_QueryItem(szURL, &pIXMLDocumentOld,
  170. PARSE_LOCAL)))
  171. {
  172. ASSERT(pIXMLDocumentOld);
  173. Cache_RemoveItem(szURL);
  174. pIXMLDocumentOld->Release();
  175. }*/
  176. StrCpyN(pszURLCopy, szURL, cch);
  177. pIXMLDocument->AddRef();
  178. pNewItem->szURL = pszURLCopy;
  179. pNewItem->dwParseFlags = dwParseFlags;
  180. pNewItem->ftLastMod = ftLastMod;
  181. pNewItem->dwCacheCount = dwCacheCount;
  182. pNewItem->pIXMLDocument = pIXMLDocument;
  183. //
  184. // REVIEW: Check for duplicate cache items?
  185. //
  186. pNewItem->pNext = g_pCache;
  187. g_pCache = pNewItem;
  188. hr = S_OK;
  189. }
  190. else
  191. {
  192. delete pNewItem;
  193. hr = E_OUTOFMEMORY;
  194. }
  195. }
  196. else
  197. {
  198. hr = E_OUTOFMEMORY;
  199. }
  200. Cache_LeaveWriteLock();
  201. return hr;
  202. }
  203. //
  204. //
  205. //
  206. BOOL
  207. IsEmptyTime(
  208. FILETIME ft
  209. )
  210. {
  211. return (0 == ft.dwLowDateTime && 0 == ft.dwHighDateTime);
  212. }
  213. BOOL
  214. IsEqualTime(
  215. FILETIME ft1,
  216. FILETIME ft2
  217. )
  218. {
  219. return ((ft1.dwLowDateTime == ft2.dwLowDateTime) &&
  220. (ft1.dwHighDateTime == ft2.dwHighDateTime));
  221. }
  222. void
  223. Cache_RefreshItem(
  224. CACHEITEM* pItem,
  225. LPTSTR pszLocalFile,
  226. FILETIME ftLastMod
  227. )
  228. {
  229. ASSERT(pItem);
  230. //
  231. // Try and parse the cdf from the wininet cache.
  232. //
  233. IXMLDocument* pIXMLDocument;
  234. HRESULT hr;
  235. DLL_ForcePreloadDlls(PRELOAD_MSXML);
  236. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  237. IID_IXMLDocument, (void**)&pIXMLDocument);
  238. BOOL bCoInit = FALSE;
  239. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  240. SUCCEEDED(CoInitialize(NULL)))
  241. {
  242. bCoInit = TRUE;
  243. hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
  244. IID_IXMLDocument, (void**)&pIXMLDocument);
  245. }
  246. if (SUCCEEDED(hr))
  247. {
  248. ASSERT(pIXMLDocument);
  249. hr = XML_SynchronousParse(pIXMLDocument, pszLocalFile);
  250. if (FAILED(hr))
  251. pIXMLDocument->Release();
  252. }
  253. if (bCoInit)
  254. CoUninitialize();
  255. //
  256. // If the new cdf was parsed, replace the old one.
  257. //
  258. if (SUCCEEDED(hr))
  259. {
  260. pItem->pIXMLDocument->Release();
  261. pItem->pIXMLDocument = pIXMLDocument;
  262. pItem->ftLastMod = ftLastMod;
  263. }
  264. return;
  265. }
  266. BOOL
  267. Cache_IsItemFresh(
  268. CACHEITEM* pItem,
  269. DWORD dwParseFlags
  270. )
  271. {
  272. ASSERT(pItem);
  273. BOOL fRet;
  274. DWORD dwCurrentCacheCount = g_dwCacheCount;
  275. //
  276. // If the caller asked for "Net" quality data and we only have "Local" data
  277. // then throw the "Local" data away. The resultant cache miss will cause
  278. // the caller to pick up fresher data.
  279. //
  280. if ((dwParseFlags & PARSE_NET) && (pItem->dwParseFlags & PARSE_LOCAL))
  281. {
  282. fRet = FALSE;
  283. }
  284. else
  285. {
  286. fRet = TRUE;
  287. //
  288. // If the global cache counter is greater than the counter for this
  289. // item, then a cdf has been added to the cache.
  290. //
  291. if (dwCurrentCacheCount > pItem->dwCacheCount)
  292. {
  293. //
  294. // Get the last mod time from the the cdf in the wininet cache.
  295. //
  296. FILETIME ftLastMod;
  297. TCHAR szLocalFile[MAX_PATH];
  298. if (SUCCEEDED(URLGetLocalFileName(pItem->szURL, szLocalFile,
  299. ARRAYSIZE(szLocalFile), &ftLastMod)))
  300. {
  301. //
  302. // If the last mod times are different then the cdf in the
  303. // wininet cache is newer, pick it up.
  304. // If there are no last modified times then do the conservative
  305. // thing and pick up the cdf from the wininet cache.
  306. //
  307. if ((IsEmptyTime(ftLastMod) && IsEmptyTime(pItem->ftLastMod)) ||
  308. !IsEqualTime(ftLastMod, pItem->ftLastMod))
  309. {
  310. Cache_RefreshItem(pItem, szLocalFile, ftLastMod);
  311. }
  312. }
  313. pItem->dwCacheCount = dwCurrentCacheCount;
  314. }
  315. }
  316. return fRet;
  317. }
  318. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  319. //
  320. // *** Cache_QueryItem ***
  321. //
  322. //
  323. // Description:
  324. // Returns a xml document from the cache if it is found.
  325. //
  326. // Parameters:
  327. // [In] szURL - The URL associated with the xml document.
  328. // [Out] ppIXMLDocument - A pointer that receives the xml document.
  329. //
  330. // Return:
  331. // S_OK if the document associtaed with the given URL is found in the cache.
  332. // E_FAIL if the document isn't in the cache.
  333. //
  334. // Comments:
  335. // The returned pointer is AddRefed. The caller isresposible for releasing
  336. // this pointer.
  337. //
  338. ////////////////////////////////////////////////////////////////////////////////
  339. HRESULT
  340. Cache_QueryItem(
  341. LPTSTR szURL,
  342. IXMLDocument** ppIXMLDocument,
  343. DWORD dwParseFlags
  344. )
  345. {
  346. ASSERT(szURL);
  347. ASSERT(ppIXMLDocument);
  348. HRESULT hr = E_FAIL;
  349. Cache_EnterReadLock();
  350. PCACHEITEM pItem = g_pCache;
  351. //
  352. // REVIEW: Use CompareUrl from shlwapip?
  353. //
  354. while (pItem && !StrEql(szURL, pItem->szURL))
  355. pItem = pItem->pNext;
  356. if (pItem)
  357. {
  358. if (Cache_IsItemFresh(pItem, dwParseFlags))
  359. {
  360. ASSERT(pItem->pIXMLDocument);
  361. pItem->pIXMLDocument->AddRef();
  362. *ppIXMLDocument = pItem->pIXMLDocument;
  363. hr = S_OK;
  364. }
  365. else
  366. {
  367. Cache_RemoveItem(szURL);
  368. }
  369. }
  370. Cache_LeaveReadLock();
  371. ASSERT(SUCCEEDED(hr) && ppIXMLDocument || FAILED(hr));
  372. return hr;
  373. }
  374. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  375. //
  376. // *** Cache_FreeAll ***
  377. //
  378. //
  379. // Description:
  380. // Frees all items from the xml document cache.
  381. //
  382. // Parameters:
  383. // None.
  384. //
  385. // Return:
  386. // None.
  387. //
  388. // Comments:
  389. // Frees all memory held in the xml document cache.
  390. //
  391. ////////////////////////////////////////////////////////////////////////////////
  392. void
  393. Cache_FreeAll(
  394. void
  395. )
  396. {
  397. Cache_EnterWriteLock();
  398. PCACHEITEM pItem = g_pCache;
  399. g_pCache = NULL;
  400. Cache_LeaveWriteLock();
  401. while (pItem)
  402. {
  403. PCACHEITEM pNext = pItem->pNext;
  404. ASSERT(pItem->szURL);
  405. ASSERT(pItem->pIXMLDocument);
  406. pItem->pIXMLDocument->Release();
  407. delete [] pItem->szURL;
  408. delete pItem;
  409. pItem = pNext;
  410. }
  411. return;
  412. }
  413. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  414. //
  415. // *** Cache_FreeItem ***
  416. //
  417. //
  418. // Description:
  419. // Frees item associated with given URL from the xml document cache.
  420. //
  421. // Parameters:
  422. // LPTSTR szURL
  423. //
  424. // Return:
  425. // HRESULT S_OK if item in cache and deleted, E_FAIL if item not in cache
  426. //
  427. ////////////////////////////////////////////////////////////////////////////////
  428. HRESULT
  429. Cache_RemoveItem(
  430. LPCTSTR szURL
  431. )
  432. {
  433. ASSERT(szURL);
  434. HRESULT hr;
  435. Cache_EnterWriteLock();
  436. PCACHEITEM pItem = g_pCache;
  437. PCACHEITEM pItemPrev = NULL;
  438. //
  439. // REVIEW: Use CompareUrl from slwapip?.
  440. //
  441. while (pItem && !StrEql(szURL, pItem->szURL))
  442. {
  443. pItemPrev = pItem;
  444. pItem = pItem->pNext;
  445. }
  446. if (pItem)
  447. {
  448. ASSERT(pItem->pIXMLDocument);
  449. if (pItemPrev)
  450. {
  451. pItemPrev->pNext = pItem->pNext;
  452. }
  453. else
  454. {
  455. g_pCache = pItem->pNext; // handle remove first item case
  456. }
  457. pItem->pIXMLDocument->Release();
  458. delete [] pItem->szURL;
  459. delete pItem;
  460. hr = S_OK;
  461. }
  462. else
  463. {
  464. hr = E_FAIL;
  465. }
  466. Cache_LeaveWriteLock();
  467. return hr;
  468. }