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.

481 lines
14 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, 128 );
  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. {
  171. CoTaskMemFree(*ppwszDisplayName);
  172. return E_OUTOFMEMORY;
  173. }
  174. MLLoadString( IDS_CACHEOFF_DISPLAY, *ppwszDisplayName, 512 );
  175. MLLoadString( IDS_CACHEOFF_DESCRIPTION, *ppwszDescription, 512 );
  176. #else
  177. // We can use the default registry DisplayName and Description
  178. *ppwszDisplayName = NULL;
  179. *ppwszDescription = NULL;
  180. #endif
  181. // Intentionally am not turning on cleanup by default; turning on *view pages* button
  182. *pdwFlags = EVCF_HASSETTINGS;
  183. // Let's check if the Internet Cache Folder is in pcwzVolume
  184. GetCacheLocation(m_szCacheDir, ARRAYSIZE(m_szCacheDir));
  185. if (StrCmpNI(pcwszVolume, m_szCacheDir, 3))
  186. {
  187. // If the cache is on a different drive return S_FALSE so that we don't show up in UI
  188. return S_FALSE;
  189. }
  190. // Determine if offline browsing pack is intalled.
  191. ucs.tyspec = TYSPEC_CLSID;
  192. ucs.tagged_union.clsid = CLSID_SubscriptionMgr;
  193. hr = FaultInIEFeature(NULL, &ucs, &qc, FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI);
  194. if (SUCCEEDED(hr)) // (if offline pack installed)
  195. {
  196. GetSpaceUsed(&dwlSize, NULL);
  197. if (dwlSize) // If there is something in offline cache to delete
  198. return S_OK; // load cleaner/
  199. }
  200. return S_FALSE;
  201. }
  202. STDMETHODIMP COfflinePagesCacheCleaner::GetSpaceUsed(
  203. DWORDLONG * pdwlSpaceUsed,
  204. IEmptyVolumeCacheCallBack * picb
  205. )
  206. {
  207. HRESULT hr;
  208. ASSERT(NULL != pdwlSpaceUsed);
  209. if (NULL != pdwlSpaceUsed)
  210. {
  211. RTSCBSTRUCT * prtscbStruct = new RTSCBSTRUCT;
  212. if (NULL != prtscbStruct)
  213. {
  214. // Initialize GetSpazeUsed Structure
  215. prtscbStruct->pdwlSpaceUsed = pdwlSpaceUsed;
  216. *(prtscbStruct->pdwlSpaceUsed) = 0;
  217. prtscbStruct->picb = picb;
  218. // Get Offline Cache Space Usage
  219. hr = WalkOfflineCache(RunningTotalSizeCallback, (void *)(prtscbStruct));
  220. m_dwlSpaceUsed = *(prtscbStruct->pdwlSpaceUsed);
  221. // Send the last notification to the cleanup manager
  222. if (picb != NULL)
  223. picb->ScanProgress(*(prtscbStruct->pdwlSpaceUsed), EVCCBF_LASTNOTIFICATION, NULL);
  224. delete prtscbStruct;
  225. }
  226. else
  227. {
  228. hr = E_OUTOFMEMORY;
  229. }
  230. }
  231. else
  232. {
  233. hr = E_INVALIDARG;
  234. }
  235. return hr;
  236. }
  237. STDMETHODIMP COfflinePagesCacheCleaner::Purge(
  238. DWORDLONG dwlSpaceToFree, // Spec makes this irrelevent!
  239. IEmptyVolumeCacheCallBack * picb
  240. )
  241. {
  242. HRESULT hr;
  243. DECBSTRUCT * pdecbStruct = new DECBSTRUCT;
  244. if (NULL != pdecbStruct)
  245. {
  246. // Initialize DeleteEntry Structure
  247. pdecbStruct->picb = picb;
  248. pdecbStruct->dwlSpaceFreed = 0;
  249. pdecbStruct->dwlTotalSpace = m_dwlSpaceUsed;
  250. // Delete Offline Cache Entries
  251. hr = WalkOfflineCache(DeleteEntryCallback, (void *)(pdecbStruct));
  252. // Send the last notification to the cleanup manager
  253. if (picb != NULL)
  254. {
  255. picb->PurgeProgress(m_dwlSpaceUsed, 0, EVCCBF_LASTNOTIFICATION, NULL);
  256. }
  257. delete pdecbStruct;
  258. }
  259. else
  260. {
  261. hr = E_OUTOFMEMORY;
  262. }
  263. return hr;
  264. }
  265. STDMETHODIMP COfflinePagesCacheCleaner::ShowProperties(HWND hwnd)
  266. {
  267. TCHAR szOfflinePath[MAX_PATH];
  268. DWORD dwSize = SIZEOF(szOfflinePath);
  269. szOfflinePath[0] = L'\0';
  270. if (SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_SUBSCRIPTION,
  271. REGSTR_VAL_DIRECTORY, NULL, (LPBYTE)szOfflinePath, &dwSize) != ERROR_SUCCESS)
  272. {
  273. TCHAR szWindows[MAX_PATH];
  274. szWindows[0] = L'\0';
  275. GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows));
  276. if (*szWindows)
  277. PathCombine(szOfflinePath, szWindows, TEXT("Offline Web Pages"));
  278. }
  279. if (*szOfflinePath)
  280. {
  281. PathQuoteSpaces(szOfflinePath);
  282. SHELLEXECUTEINFO shei;
  283. ZeroMemory(&shei, sizeof(shei));
  284. shei.cbSize = sizeof(shei);
  285. shei.lpFile = szOfflinePath;
  286. shei.nShow = SW_SHOWNORMAL;
  287. ShellExecuteEx(&shei);
  288. }
  289. // Returning S_OK insures that GetSpaceUsed is recalled (to recalc) the size being
  290. // used (in case someone deletes some MAO stuff).
  291. return S_OK;
  292. }
  293. STDMETHODIMP COfflinePagesCacheCleaner::Deactivate(DWORD * pdwFlags)
  294. {
  295. // We don't implement this.
  296. *pdwFlags = 0;
  297. return S_OK;
  298. }
  299. HRESULT COfflinePagesCacheCleaner::WalkOfflineCache(
  300. LPFCALLBACK lpfCallBack,
  301. void * pv
  302. )
  303. {
  304. ASSERT(pv);
  305. HRESULT hr = S_OK;
  306. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo;
  307. HANDLE hCacheEntryInfo;
  308. DWORD dwCacheEntryInfoSize;
  309. if ((lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO) LocalAlloc(LPTR,
  310. MAX_CACHE_ENTRY_INFO_SIZE)) == NULL)
  311. {
  312. hr = E_OUTOFMEMORY;
  313. }
  314. else
  315. {
  316. dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
  317. if ((hCacheEntryInfo = FindFirstUrlCacheEntry(NULL, lpCacheEntryInfo,
  318. &dwCacheEntryInfoSize)) == NULL)
  319. {
  320. hr = HRESULT_FROM_WIN32(GetLastError());
  321. }
  322. if (SUCCEEDED(hr))
  323. {
  324. do
  325. {
  326. if (lpCacheEntryInfo->CacheEntryType & STICKY_CACHE_ENTRY)
  327. {
  328. hr = lpfCallBack(lpCacheEntryInfo, pv);
  329. }
  330. dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
  331. } while ((E_ABORT != hr) &&
  332. FindNextUrlCacheEntry(hCacheEntryInfo, lpCacheEntryInfo,
  333. &dwCacheEntryInfoSize));
  334. if (hr != E_ABORT)
  335. {
  336. DWORD dwLastErr = GetLastError();
  337. if (dwLastErr != ERROR_NO_MORE_ITEMS)
  338. {
  339. hr = HRESULT_FROM_WIN32(dwLastErr);
  340. }
  341. }
  342. }
  343. LocalFree(lpCacheEntryInfo);
  344. lpCacheEntryInfo = NULL;
  345. }
  346. return hr;
  347. }
  348. HRESULT CALLBACK COfflinePagesCacheCleaner::RunningTotalSizeCallback(
  349. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo, // Name of the CacheEntry to sum
  350. void * pv // A RTSCBSTRUCT
  351. )
  352. {
  353. HRESULT hr = S_OK;
  354. RTSCBSTRUCT * prtscbStruct = (RTSCBSTRUCT *)pv;
  355. // Add current file size to total
  356. IncrementFileSize(lpCacheEntryInfo, prtscbStruct->pdwlSpaceUsed);
  357. // Update the progressbar!
  358. if (prtscbStruct->picb != NULL)
  359. hr = prtscbStruct->picb->ScanProgress(*(prtscbStruct->pdwlSpaceUsed), 0, NULL);
  360. return hr;
  361. }
  362. HRESULT CALLBACK COfflinePagesCacheCleaner::DeleteEntryCallback(
  363. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo, // Name of the CacheEntry to delete
  364. void * pv // Pointer to DECBSTRUCT
  365. )
  366. {
  367. HRESULT hr = S_OK;
  368. DECBSTRUCT * pdecbStruct = (DECBSTRUCT *)pv;
  369. // Add current file size to total deleted
  370. IncrementFileSize(lpCacheEntryInfo, &(pdecbStruct->dwlSpaceFreed));
  371. DeleteUrlCacheEntry(lpCacheEntryInfo->lpszSourceUrlName);
  372. // Update the progress bar!
  373. if (pdecbStruct->picb != NULL)
  374. {
  375. hr = pdecbStruct->picb->PurgeProgress(pdecbStruct->dwlSpaceFreed,
  376. pdecbStruct->dwlTotalSpace - pdecbStruct->dwlSpaceFreed, NULL, NULL);
  377. }
  378. return hr;
  379. }
  380. VOID COfflinePagesCacheCleaner::IncrementFileSize(
  381. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo,
  382. DWORDLONG * pdwlSize
  383. )
  384. {
  385. ULARGE_INTEGER uliFileSize;
  386. uliFileSize.HighPart = lpCacheEntryInfo->dwSizeHigh;
  387. uliFileSize.LowPart = lpCacheEntryInfo->dwSizeLow;
  388. *pdwlSize += QUAD_PART(uliFileSize);
  389. }