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.

470 lines
13 KiB

  1. // Author: Karim Farouki
  2. // Date: 24 June 1998
  3. #include "priv.h"
  4. #include "util.h"
  5. #include <emptyvc.h>
  6. #include <mluisupp.h> // for MLLoadString
  7. #include "resource.h" // for the string ID's
  8. typedef HRESULT (* LPFCALLBACK )(LPINTERNET_CACHE_ENTRY_INFO, void *);
  9. typedef struct tagRTSCBSTRUCT
  10. {
  11. IEmptyVolumeCacheCallBack * picb;
  12. DWORDLONG * pdwlSpaceUsed;
  13. } RTSCBSTRUCT; // RunningTotalSizeCallBack Struct
  14. typedef struct tagDECBSTRUCT
  15. {
  16. IEmptyVolumeCacheCallBack * picb;
  17. DWORDLONG dwlSpaceFreed;
  18. DWORDLONG dwlTotalSpace;
  19. } DECBSTRUCT; // DeleteEntryCallBack Struct
  20. class COfflinePagesCacheCleaner : public IEmptyVolumeCache2
  21. {
  22. private:
  23. // Data
  24. ULONG m_cRef;
  25. DWORDLONG m_dwlSpaceUsed;
  26. TCHAR m_szCacheDir[MAX_PATH + 1];
  27. // Functions
  28. HRESULT WalkOfflineCache(
  29. LPFCALLBACK lpfCallBack,
  30. void * pv
  31. );
  32. static HRESULT CALLBACK RunningTotalSizeCallback(
  33. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
  34. void * pv
  35. );
  36. static HRESULT CALLBACK DeleteEntryCallback(
  37. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
  38. void * pv
  39. );
  40. static VOID IncrementFileSize(
  41. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
  42. DWORDLONG * pdwlSize
  43. );
  44. ~COfflinePagesCacheCleaner(void);
  45. public:
  46. // Constructor/Destructor
  47. COfflinePagesCacheCleaner(void);
  48. // IUnknown Interface members
  49. STDMETHODIMP QueryInterface(REFIID, void **);
  50. STDMETHODIMP_(ULONG) AddRef(void);
  51. STDMETHODIMP_(ULONG) Release(void);
  52. // IEmptyVolumeCache interface methods
  53. STDMETHODIMP Initialize(
  54. HKEY hkRegKey,
  55. LPCWSTR pcwszVolume,
  56. LPWSTR * ppwszDisplayName,
  57. LPWSTR * ppwszDescription,
  58. DWORD * pdwFlags
  59. );
  60. STDMETHODIMP GetSpaceUsed(
  61. DWORDLONG * pdwlSpaceUsed,
  62. IEmptyVolumeCacheCallBack * picb
  63. );
  64. STDMETHODIMP Purge(
  65. DWORDLONG dwlSpaceToFree,
  66. IEmptyVolumeCacheCallBack * picb
  67. );
  68. STDMETHODIMP ShowProperties(
  69. HWND hwnd
  70. );
  71. STDMETHODIMP Deactivate(
  72. DWORD * pdwFlags
  73. );
  74. // IEmptyVolumeCache2 interface methods
  75. STDMETHODIMP InitializeEx(
  76. HKEY hkRegKey,
  77. LPCWSTR pcwszVolume,
  78. LPCWSTR pcwszKeyName,
  79. LPWSTR *ppwszDisplayName,
  80. LPWSTR *ppwszDescription,
  81. LPWSTR *ppwszBtnText,
  82. DWORD *pdwFlags
  83. );
  84. };
  85. STDAPI COfflinePagesCacheCleaner_CreateInstance(
  86. IUnknown * punkOuter,
  87. IUnknown ** ppunk,
  88. LPCOBJECTINFO poi
  89. )
  90. {
  91. HRESULT hr = S_OK;
  92. *ppunk = NULL;
  93. COfflinePagesCacheCleaner * lpOPCC = new COfflinePagesCacheCleaner();
  94. if (lpOPCC == NULL)
  95. hr = E_OUTOFMEMORY;
  96. else
  97. *ppunk = SAFECAST(lpOPCC, IEmptyVolumeCache *);
  98. return hr;
  99. }
  100. COfflinePagesCacheCleaner::COfflinePagesCacheCleaner() : m_cRef(1)
  101. {
  102. DllAddRef();
  103. }
  104. COfflinePagesCacheCleaner::~COfflinePagesCacheCleaner()
  105. {
  106. DllRelease();
  107. }
  108. STDMETHODIMP COfflinePagesCacheCleaner::QueryInterface(REFIID riid, LPVOID * ppv)
  109. {
  110. HRESULT hr = S_OK;
  111. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEmptyVolumeCache) || IsEqualIID(riid, IID_IEmptyVolumeCache2))
  112. {
  113. *ppv = SAFECAST(this, IEmptyVolumeCache2 *);
  114. AddRef();
  115. }
  116. else
  117. {
  118. *ppv = NULL;
  119. hr = E_NOINTERFACE;
  120. }
  121. return hr;
  122. }
  123. STDMETHODIMP_(ULONG) COfflinePagesCacheCleaner::AddRef()
  124. {
  125. return ++m_cRef;
  126. }
  127. STDMETHODIMP_(ULONG) COfflinePagesCacheCleaner::Release()
  128. {
  129. ULONG uRefCount = --m_cRef;
  130. if (!uRefCount)
  131. delete this;
  132. return uRefCount;
  133. }
  134. STDMETHODIMP COfflinePagesCacheCleaner::InitializeEx(
  135. HKEY hkRegKey,
  136. LPCWSTR pcwszVolume,
  137. LPCWSTR pcwszKeyName,
  138. LPWSTR *ppwszDisplayName,
  139. LPWSTR *ppwszDescription,
  140. LPWSTR *ppwszBtnText,
  141. DWORD *pdwFlags
  142. )
  143. {
  144. *ppwszBtnText = (LPWSTR)CoTaskMemAlloc( 128*sizeof(WCHAR) );
  145. if ( !*ppwszBtnText )
  146. return E_OUTOFMEMORY;
  147. MLLoadString( IDS_CACHEOFF_BTNTEXT, *ppwszBtnText, 512 );
  148. return Initialize(hkRegKey, pcwszVolume, ppwszDisplayName, ppwszDescription, pdwFlags );
  149. }
  150. STDMETHODIMP COfflinePagesCacheCleaner::Initialize(
  151. HKEY hkRegkey,
  152. LPCWSTR pcwszVolume,
  153. LPWSTR * ppwszDisplayName,
  154. LPWSTR * ppwszDescription,
  155. DWORD * pdwFlags
  156. )
  157. {
  158. HRESULT hr;
  159. uCLSSPEC ucs; // Used to see if Webcheck is installed
  160. QUERYCONTEXT qc = { 0 }; // Used to see if Webcheck is installed
  161. DWORDLONG dwlSize; // Amount of offline cachespace
  162. #ifdef UNICODE
  163. // We can't use the registry values on NT because they can't be multi-local localized.
  164. // Instead we must use strings loaded from resources.
  165. *ppwszDisplayName = (LPWSTR)CoTaskMemAlloc( 512*sizeof(WCHAR) );
  166. if ( !*ppwszDisplayName )
  167. return E_OUTOFMEMORY;
  168. *ppwszDescription = (LPWSTR)CoTaskMemAlloc( 512*sizeof(WCHAR) );
  169. if ( !*ppwszDescription )
  170. return E_OUTOFMEMORY;
  171. MLLoadString( IDS_CACHEOFF_DISPLAY, *ppwszDisplayName, 512 );
  172. MLLoadString( IDS_CACHEOFF_DESCRIPTION, *ppwszDescription, 512 );
  173. #else
  174. // We can use the default registry DisplayName and Description
  175. *ppwszDisplayName = NULL;
  176. *ppwszDescription = NULL;
  177. #endif
  178. // Intentionally am not turning on cleanup by default; turning on *view pages* button
  179. *pdwFlags = EVCF_HASSETTINGS;
  180. // Let's check if the Internet Cache Folder is in pcwzVolume
  181. GetCacheLocation(m_szCacheDir, sizeof(m_szCacheDir));
  182. if (StrCmpNI(pcwszVolume, m_szCacheDir, 3))
  183. {
  184. // If the cache is on a different drive return S_FALSE so that we don't show up in UI
  185. return S_FALSE;
  186. }
  187. // Determine if offline browsing pack is intalled.
  188. ucs.tyspec = TYSPEC_CLSID;
  189. ucs.tagged_union.clsid = CLSID_SubscriptionMgr;
  190. hr = FaultInIEFeature(NULL, &ucs, &qc, FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI);
  191. if (SUCCEEDED(hr)) // (if offline pack installed)
  192. {
  193. GetSpaceUsed(&dwlSize, NULL);
  194. if (dwlSize) // If there is something in offline cache to delete
  195. return S_OK; // load cleaner/
  196. }
  197. return S_FALSE;
  198. }
  199. STDMETHODIMP COfflinePagesCacheCleaner::GetSpaceUsed(
  200. DWORDLONG * pdwlSpaceUsed,
  201. IEmptyVolumeCacheCallBack * picb
  202. )
  203. {
  204. HRESULT hr;
  205. ASSERT(NULL != pdwlSpaceUsed);
  206. if (NULL != pdwlSpaceUsed)
  207. {
  208. RTSCBSTRUCT * prtscbStruct = new RTSCBSTRUCT;
  209. if (NULL != prtscbStruct)
  210. {
  211. // Initialize GetSpazeUsed Structure
  212. prtscbStruct->pdwlSpaceUsed = pdwlSpaceUsed;
  213. *(prtscbStruct->pdwlSpaceUsed) = 0;
  214. prtscbStruct->picb = picb;
  215. // Get Offline Cache Space Usage
  216. hr = WalkOfflineCache(RunningTotalSizeCallback, (void *)(prtscbStruct));
  217. m_dwlSpaceUsed = *(prtscbStruct->pdwlSpaceUsed);
  218. // Send the last notification to the cleanup manager
  219. if (picb != NULL)
  220. picb->ScanProgress(*(prtscbStruct->pdwlSpaceUsed), EVCCBF_LASTNOTIFICATION, NULL);
  221. delete prtscbStruct;
  222. }
  223. else
  224. {
  225. hr = E_OUTOFMEMORY;
  226. }
  227. }
  228. else
  229. {
  230. hr = E_INVALIDARG;
  231. }
  232. return hr;
  233. }
  234. STDMETHODIMP COfflinePagesCacheCleaner::Purge(
  235. DWORDLONG dwlSpaceToFree, // Spec makes this irrelevent!
  236. IEmptyVolumeCacheCallBack * picb
  237. )
  238. {
  239. HRESULT hr;
  240. DECBSTRUCT * pdecbStruct = new DECBSTRUCT;
  241. if (NULL != pdecbStruct)
  242. {
  243. // Initialize DeleteEntry Structure
  244. pdecbStruct->picb = picb;
  245. pdecbStruct->dwlSpaceFreed = 0;
  246. pdecbStruct->dwlTotalSpace = m_dwlSpaceUsed;
  247. // Delete Offline Cache Entries
  248. hr = WalkOfflineCache(DeleteEntryCallback, (void *)(pdecbStruct));
  249. // Send the last notification to the cleanup manager
  250. if (picb != NULL)
  251. {
  252. picb->PurgeProgress(m_dwlSpaceUsed, 0, EVCCBF_LASTNOTIFICATION, NULL);
  253. }
  254. delete pdecbStruct;
  255. }
  256. else
  257. {
  258. hr = E_OUTOFMEMORY;
  259. }
  260. return hr;
  261. }
  262. STDMETHODIMP COfflinePagesCacheCleaner::ShowProperties(HWND hwnd)
  263. {
  264. TCHAR szOfflinePath[MAX_PATH];
  265. DWORD dwSize = SIZEOF(szOfflinePath);
  266. if (SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_SUBSCRIPTION,
  267. REGSTR_VAL_DIRECTORY, NULL, (LPBYTE)szOfflinePath, &dwSize) != ERROR_SUCCESS)
  268. {
  269. TCHAR szWindows[MAX_PATH];
  270. GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows));
  271. PathCombine(szOfflinePath, szWindows, TEXT("Offline Web Pages"));
  272. }
  273. SHELLEXECUTEINFO shei;
  274. ZeroMemory(&shei, sizeof(shei));
  275. shei.cbSize = sizeof(shei);
  276. shei.lpFile = szOfflinePath;
  277. shei.nShow = SW_SHOWNORMAL;
  278. ShellExecuteEx(&shei);
  279. // Returning S_OK insures that GetSpaceUsed is recalled (to recalc) the size being
  280. // used (in case someone deletes some MAO stuff).
  281. return S_OK;
  282. }
  283. STDMETHODIMP COfflinePagesCacheCleaner::Deactivate(DWORD * pdwFlags)
  284. {
  285. // We don't implement this.
  286. *pdwFlags = 0;
  287. return S_OK;
  288. }
  289. HRESULT COfflinePagesCacheCleaner::WalkOfflineCache(
  290. LPFCALLBACK lpfCallBack,
  291. void * pv
  292. )
  293. {
  294. ASSERT(pv);
  295. HRESULT hr = S_OK;
  296. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
  297. HANDLE hCacheEntryInfo;
  298. DWORD dwCacheEntryInfoSize;
  299. if ((lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO) LocalAlloc(LPTR,
  300. MAX_CACHE_ENTRY_INFO_SIZE)) == NULL)
  301. {
  302. hr = E_OUTOFMEMORY;
  303. }
  304. else
  305. {
  306. dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
  307. if ((hCacheEntryInfo = FindFirstUrlCacheEntry(NULL, lpCacheEntryInfo,
  308. &dwCacheEntryInfoSize)) == NULL)
  309. {
  310. hr = HRESULT_FROM_WIN32(GetLastError());
  311. }
  312. if (SUCCEEDED(hr))
  313. {
  314. do
  315. {
  316. if (lpCacheEntryInfo->CacheEntryType & STICKY_CACHE_ENTRY)
  317. {
  318. hr = lpfCallBack(lpCacheEntryInfo, pv);
  319. }
  320. dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
  321. } while ((E_ABORT != hr) &&
  322. FindNextUrlCacheEntry(hCacheEntryInfo, lpCacheEntryInfo,
  323. &dwCacheEntryInfoSize));
  324. if (hr != E_ABORT)
  325. {
  326. DWORD dwLastErr = GetLastError();
  327. if (dwLastErr != ERROR_NO_MORE_ITEMS)
  328. {
  329. hr = HRESULT_FROM_WIN32(dwLastErr);
  330. }
  331. }
  332. }
  333. LocalFree(lpCacheEntryInfo);
  334. lpCacheEntryInfo = NULL;
  335. }
  336. return hr;
  337. }
  338. HRESULT CALLBACK COfflinePagesCacheCleaner::RunningTotalSizeCallback(
  339. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo, // Name of the CacheEntry to sum
  340. void * pv // A RTSCBSTRUCT
  341. )
  342. {
  343. HRESULT hr = S_OK;
  344. RTSCBSTRUCT * prtscbStruct = (RTSCBSTRUCT *)pv;
  345. // Add current file size to total
  346. IncrementFileSize(lpCacheEntryInfo, prtscbStruct->pdwlSpaceUsed);
  347. // Update the progressbar!
  348. if (prtscbStruct->picb != NULL)
  349. hr = prtscbStruct->picb->ScanProgress(*(prtscbStruct->pdwlSpaceUsed), 0, NULL);
  350. return hr;
  351. }
  352. HRESULT CALLBACK COfflinePagesCacheCleaner::DeleteEntryCallback(
  353. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo, // Name of the CacheEntry to delete
  354. void * pv // Pointer to DECBSTRUCT
  355. )
  356. {
  357. HRESULT hr = S_OK;
  358. DECBSTRUCT * pdecbStruct = (DECBSTRUCT *)pv;
  359. // Add current file size to total deleted
  360. IncrementFileSize(lpCacheEntryInfo, &(pdecbStruct->dwlSpaceFreed));
  361. DeleteUrlCacheEntry(lpCacheEntryInfo->lpszSourceUrlName);
  362. // Update the progress bar!
  363. if (pdecbStruct->picb != NULL)
  364. {
  365. hr = pdecbStruct->picb->PurgeProgress(pdecbStruct->dwlSpaceFreed,
  366. pdecbStruct->dwlTotalSpace - pdecbStruct->dwlSpaceFreed, NULL, NULL);
  367. }
  368. return hr;
  369. }
  370. VOID COfflinePagesCacheCleaner::IncrementFileSize(
  371. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
  372. DWORDLONG * pdwlSize
  373. )
  374. {
  375. ULARGE_INTEGER uliFileSize;
  376. uliFileSize.HighPart = lpCacheEntryInfo->dwSizeHigh;
  377. uliFileSize.LowPart = lpCacheEntryInfo->dwSizeLow;
  378. *pdwlSize += QUAD_PART(uliFileSize);
  379. }