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.

534 lines
15 KiB

  1. // Author: Pritvinath Obla
  2. // Date: 10 July 1997
  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. class CInternetCacheCleaner : public IEmptyVolumeCache2
  9. {
  10. private:
  11. //
  12. // Data
  13. //
  14. ULONG m_cRef; // reference count
  15. DWORDLONG m_dwlSpaceUsed;
  16. TCHAR m_szCacheDir[MAX_PATH + 1];
  17. //
  18. // Functions
  19. //
  20. HRESULT GetInternetCacheSize(
  21. DWORDLONG *pdwlSpaceUsed,
  22. IEmptyVolumeCacheCallBack *picb
  23. );
  24. HRESULT DelInternetCacheFiles(
  25. DWORD dwPercentToFree,
  26. IEmptyVolumeCacheCallBack *picb
  27. );
  28. public:
  29. //
  30. // Constructor and Destructor
  31. //
  32. CInternetCacheCleaner(void);
  33. ~CInternetCacheCleaner(void);
  34. //
  35. // IUnknown interface members
  36. //
  37. STDMETHODIMP QueryInterface(REFIID, void **);
  38. STDMETHODIMP_(ULONG) AddRef(void);
  39. STDMETHODIMP_(ULONG) Release(void);
  40. //
  41. // IEmptyVolumeCache interface methods
  42. //
  43. STDMETHODIMP Initialize(
  44. HKEY hkRegKey,
  45. LPCWSTR pcwszVolume,
  46. LPWSTR *ppwszDisplayName,
  47. LPWSTR *ppwszDescription,
  48. DWORD *pdwFlags
  49. );
  50. STDMETHODIMP GetSpaceUsed(
  51. DWORDLONG *pdwlSpaceUsed,
  52. IEmptyVolumeCacheCallBack *picb
  53. );
  54. STDMETHODIMP Purge(
  55. DWORDLONG dwlSpaceToFree,
  56. IEmptyVolumeCacheCallBack *picb
  57. );
  58. STDMETHODIMP ShowProperties(
  59. HWND hwnd
  60. );
  61. STDMETHODIMP Deactivate(
  62. DWORD *pdwFlags
  63. );
  64. //
  65. // IEmptyVolumeCache2 interface methods
  66. //
  67. STDMETHODIMP InitializeEx(
  68. HKEY hkRegKey,
  69. LPCWSTR pcwszVolume,
  70. LPCWSTR pcwszKeyName,
  71. LPWSTR *ppwszDisplayName,
  72. LPWSTR *ppwszDescription,
  73. LPWSTR *ppwszBtnText,
  74. DWORD *pdwFlags
  75. );
  76. };
  77. //
  78. //------------------------------------------------------------------------------
  79. // CInternetCacheCleaner_CreateInstance
  80. //
  81. // Purpose: CreateInstance function for IClassFactory
  82. //------------------------------------------------------------------------------
  83. //
  84. STDAPI CInternetCacheCleaner_CreateInstance(
  85. IUnknown *punkOuter,
  86. IUnknown **ppunk,
  87. LPCOBJECTINFO poi
  88. )
  89. {
  90. *ppunk = NULL;
  91. CInternetCacheCleaner *lpICC = new CInternetCacheCleaner();
  92. if (lpICC == NULL)
  93. return E_OUTOFMEMORY;
  94. *ppunk = SAFECAST(lpICC, IEmptyVolumeCache *);
  95. return S_OK;
  96. }
  97. CInternetCacheCleaner::CInternetCacheCleaner() : m_cRef(1)
  98. {
  99. DllAddRef();
  100. m_dwlSpaceUsed = 0;
  101. *m_szCacheDir = '\0';
  102. }
  103. CInternetCacheCleaner::~CInternetCacheCleaner()
  104. {
  105. DllRelease();
  106. }
  107. STDMETHODIMP CInternetCacheCleaner::QueryInterface(REFIID riid, LPVOID *ppv)
  108. {
  109. if (IsEqualIID(riid, IID_IUnknown) ||
  110. IsEqualIID(riid, IID_IEmptyVolumeCache2) ||
  111. IsEqualIID(riid, IID_IEmptyVolumeCache))
  112. {
  113. *ppv = SAFECAST(this, IEmptyVolumeCache2 *);
  114. }
  115. else
  116. {
  117. *ppv = NULL;
  118. return E_NOINTERFACE;
  119. }
  120. AddRef();
  121. return NOERROR;
  122. }
  123. STDMETHODIMP_(ULONG) CInternetCacheCleaner::AddRef()
  124. {
  125. return ++m_cRef;
  126. }
  127. STDMETHODIMP_(ULONG) CInternetCacheCleaner::Release()
  128. {
  129. //
  130. // Decrement and check
  131. //
  132. if (--m_cRef)
  133. return m_cRef;
  134. //
  135. // No references left to this object
  136. //
  137. delete this;
  138. return 0;
  139. }
  140. //
  141. //------------------------------------------------------------------------------
  142. // CInternetCacheCleaner::InitializeEx
  143. //
  144. // Purpose: Initializes the Internet Cache Cleaner and returns the
  145. // specified IEmptyVolumeCache flags to the cache manager
  146. //------------------------------------------------------------------------------
  147. //
  148. STDMETHODIMP CInternetCacheCleaner::InitializeEx(
  149. HKEY hkRegKey,
  150. LPCWSTR pcwszVolume,
  151. LPCWSTR pcwszKeyName,
  152. LPWSTR *ppwszDisplayName,
  153. LPWSTR *ppwszDescription,
  154. LPWSTR *ppwszBtnText,
  155. DWORD *pdwFlags
  156. )
  157. {
  158. *ppwszBtnText = (LPWSTR)CoTaskMemAlloc( 128*sizeof(WCHAR) );
  159. if ( !*ppwszBtnText )
  160. return E_OUTOFMEMORY;
  161. MLLoadString( IDS_CACHECLN_BTNTEXT, *ppwszBtnText, 128 );
  162. return Initialize(hkRegKey, pcwszVolume, ppwszDisplayName, ppwszDescription, pdwFlags );
  163. }
  164. //
  165. //------------------------------------------------------------------------------
  166. // CInternetCacheCleaner::Initialize
  167. //
  168. // Purpose: Initializes the Internet Cache Cleaner and returns the
  169. // specified IEmptyVolumeCache flags to the cache manager
  170. //------------------------------------------------------------------------------
  171. //
  172. STDMETHODIMP CInternetCacheCleaner::Initialize(
  173. HKEY hkRegKey,
  174. LPCWSTR pcwszVolume,
  175. LPWSTR *ppwszDisplayName,
  176. LPWSTR *ppwszDescription,
  177. DWORD *pdwFlags
  178. )
  179. {
  180. #ifdef UNICODE
  181. // We can't use the registry values on NT because they can't be multi-local localized. As
  182. // a result we must set the out pointers with values read from resources.
  183. *ppwszDisplayName = (LPWSTR)CoTaskMemAlloc( 512*sizeof(WCHAR) );
  184. if ( !*ppwszDisplayName )
  185. return E_OUTOFMEMORY;
  186. *ppwszDescription = (LPWSTR)CoTaskMemAlloc( 512*sizeof(WCHAR) );
  187. if ( !*ppwszDescription )
  188. {
  189. CoTaskMemFree(*ppwszDisplayName);
  190. return E_OUTOFMEMORY;
  191. }
  192. MLLoadString( IDS_CACHECLN_DISPLAY, *ppwszDisplayName, 512 );
  193. MLLoadString( IDS_CACHECLN_DESCRIPTION, *ppwszDescription, 512 );
  194. #else
  195. //
  196. // Let cleanmgr read the default DisplayName and Description
  197. // from hkRegKey and use them
  198. //
  199. *ppwszDisplayName = NULL;
  200. *ppwszDescription = NULL;
  201. #endif
  202. *pdwFlags = 0; // initialize the [out] parameter
  203. //
  204. // Check if the Internet Cache Folder is in pcwzVolume
  205. //
  206. GetCacheLocation(m_szCacheDir, ARRAYSIZE(m_szCacheDir));
  207. if (StrCmpNI(pcwszVolume, m_szCacheDir, 3))
  208. {
  209. //
  210. // Different drives; return S_FALSE so that this cleaner
  211. // doesn't show up in cleanmgr's UI
  212. //
  213. return S_FALSE;
  214. }
  215. //
  216. // Enable this cleaner by default both in cleanup and tuneup modes
  217. //
  218. *pdwFlags = EVCF_ENABLEBYDEFAULT |
  219. EVCF_ENABLEBYDEFAULT_AUTO |
  220. EVCF_HASSETTINGS;
  221. #if 0
  222. /***
  223. // Since GetInternetCacheSize returns only an approx. size,
  224. // we would never get a value of 0 even if the cache is empty
  225. // Should enable this check once wininet.dll exports a GetCacheSize API
  226. //
  227. // Check if there is any disk space to free at all
  228. // If not, return S_FALSE so that this cleaner doesn't show up in
  229. // cleanmgr's UI
  230. //
  231. DWORDLONG dwlSpaceUsed;
  232. if (SUCCEEDED(GetInternetCacheSize(&dwlSpaceUsed, NULL)) &&
  233. dwlSpaceUsed == 0)
  234. {
  235. return S_FALSE;
  236. }
  237. ***/
  238. #endif
  239. return S_OK;
  240. }
  241. //
  242. //------------------------------------------------------------------------------
  243. // CInternetCacheCleaner::GetSpaceUsed
  244. //
  245. // Purpose: Return the total amount of space this internet cache cleaner
  246. // can free up
  247. //------------------------------------------------------------------------------
  248. //
  249. STDMETHODIMP CInternetCacheCleaner::GetSpaceUsed(
  250. DWORDLONG *pdwlSpaceUsed,
  251. IEmptyVolumeCacheCallBack *picb
  252. )
  253. {
  254. HRESULT hr;
  255. hr = GetInternetCacheSize(pdwlSpaceUsed, picb);
  256. m_dwlSpaceUsed = *pdwlSpaceUsed;
  257. //
  258. // Send the last notification to the cleanup manager
  259. //
  260. if (picb != NULL)
  261. {
  262. picb->ScanProgress(*pdwlSpaceUsed, EVCCBF_LASTNOTIFICATION, NULL);
  263. }
  264. if (hr != E_ABORT)
  265. {
  266. if (FAILED(hr))
  267. {
  268. //
  269. // *pdwlSpaceUsed is only a guesstimate; so return S_FALSE
  270. //
  271. hr = S_FALSE;
  272. }
  273. else
  274. {
  275. //
  276. // Return S_OK once wininet exports a GetCacheSize API;
  277. // till then use FindFirstUrlCacheEntry/FindNextUrlCacheEntry
  278. // to get approx. size of the cache
  279. //
  280. hr = S_FALSE;
  281. }
  282. }
  283. return hr;
  284. }
  285. //
  286. //------------------------------------------------------------------------------
  287. // CInternetCacheCleaner::Purge
  288. //
  289. // Purpose: Delete the internet cache files
  290. //------------------------------------------------------------------------------
  291. //
  292. STDMETHODIMP CInternetCacheCleaner::Purge(
  293. DWORDLONG dwlSpaceToFree,
  294. IEmptyVolumeCacheCallBack *picb
  295. )
  296. {
  297. HRESULT hr;
  298. DWORD dwPercentToFree = 100; // Optimize the most common scenario:
  299. // In most cases, dwlSpaceToFree will be
  300. // equal to m_dwlSpaceUsed
  301. if (dwlSpaceToFree != m_dwlSpaceUsed)
  302. {
  303. dwPercentToFree = m_dwlSpaceUsed ?
  304. DWORD((dwlSpaceToFree * 100) / m_dwlSpaceUsed) :
  305. 100;
  306. }
  307. hr = DelInternetCacheFiles(dwPercentToFree, picb);
  308. //
  309. // Send the last notification to the cleanup manager
  310. //
  311. if (picb != NULL)
  312. {
  313. picb->PurgeProgress(dwlSpaceToFree, 0,
  314. EVCCBF_LASTNOTIFICATION, NULL);
  315. }
  316. if (hr != E_ABORT)
  317. {
  318. hr = S_OK; // cannot return anything else
  319. }
  320. return hr;
  321. }
  322. //
  323. //------------------------------------------------------------------------------
  324. // CInternetCacheCleaner::ShowProperties
  325. //
  326. // Purpose: Launch the cache viewer to list the internet cache files
  327. //------------------------------------------------------------------------------
  328. //
  329. STDMETHODIMP CInternetCacheCleaner::ShowProperties(
  330. HWND hwnd
  331. )
  332. {
  333. DWORD dwAttrib;
  334. if (*m_szCacheDir == '\0') // Internet cache dir is not yet initialized
  335. {
  336. GetCacheLocation(m_szCacheDir, ARRAYSIZE(m_szCacheDir));
  337. }
  338. dwAttrib = GetFileAttributes(m_szCacheDir);
  339. if (dwAttrib != 0xffffffff && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
  340. {
  341. WCHAR szCache[MAX_PATH];
  342. StringCchCopy(szCache, ARRAYSIZE(szCache), m_szCacheDir);
  343. PathQuoteSpaces(szCache);
  344. SHELLEXECUTEINFO sei;
  345. //
  346. // Launch the cache viewer
  347. //
  348. sei.cbSize = sizeof(SHELLEXECUTEINFO);
  349. sei.hwnd = hwnd;
  350. sei.lpVerb = NULL;
  351. sei.lpFile = szCache;
  352. sei.lpParameters = NULL;
  353. sei.lpDirectory = NULL;
  354. sei.nShow = SW_SHOWNORMAL;
  355. sei.fMask = 0;
  356. ShellExecuteEx(&sei);
  357. }
  358. //
  359. // The user may or may not delete files directly from the cachevu folder
  360. // Since there is no way of knowing this, don't return S_OK which would
  361. // trigger cleanmgr to call GetSpaceUsed again
  362. //
  363. return S_OK;
  364. }
  365. //
  366. //------------------------------------------------------------------------------
  367. // CInternetCacheCleaner::Deactivate
  368. //
  369. // Purpose: Deactivates the Internet Cache Cleaner...Not implemented
  370. //------------------------------------------------------------------------------
  371. //
  372. STDMETHODIMP CInternetCacheCleaner::Deactivate(
  373. DWORD *pdwFlags
  374. )
  375. {
  376. *pdwFlags = 0;
  377. return S_OK;
  378. }
  379. //
  380. //------------------------------------------------------------------------------
  381. // CInternetCacheCleaner::GetInternetCacheSize
  382. //
  383. // Purpose: Find the size of the internet cache by calling into wininet APIs
  384. //
  385. // Notes: The current implementation is temporary; once wininet exports
  386. // a real API for getting the cache size, use that
  387. //------------------------------------------------------------------------------
  388. //
  389. HRESULT CInternetCacheCleaner::GetInternetCacheSize(
  390. DWORDLONG *pdwlSpaceUsed,
  391. IEmptyVolumeCacheCallBack *picb // not used
  392. )
  393. {
  394. HRESULT hr = S_OK;
  395. DWORD dwLastErr;
  396. LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo;
  397. HANDLE hCacheEntryInfo;
  398. DWORD dwCacheEntryInfoSize;
  399. *pdwlSpaceUsed = 0;
  400. if ((lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFOA) LocalAlloc(LPTR,
  401. MAX_CACHE_ENTRY_INFO_SIZE)) == NULL)
  402. {
  403. return E_OUTOFMEMORY;
  404. }
  405. dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
  406. if ((hCacheEntryInfo = FindFirstUrlCacheEntryA(NULL, lpCacheEntryInfo,
  407. &dwCacheEntryInfoSize)) == NULL)
  408. {
  409. hr = HRESULT_FROM_WIN32(GetLastError());
  410. }
  411. if (SUCCEEDED(hr))
  412. {
  413. do
  414. {
  415. if (!(lpCacheEntryInfo->CacheEntryType & (STICKY_CACHE_ENTRY | COOKIE_CACHE_ENTRY)))
  416. {
  417. ULARGE_INTEGER uliFileSize;
  418. uliFileSize.HighPart = lpCacheEntryInfo->dwSizeHigh;
  419. uliFileSize.LowPart = lpCacheEntryInfo->dwSizeLow;
  420. *pdwlSpaceUsed += QUAD_PART(uliFileSize);
  421. }
  422. dwCacheEntryInfoSize = MAX_CACHE_ENTRY_INFO_SIZE;
  423. } while (FindNextUrlCacheEntryA(hCacheEntryInfo, lpCacheEntryInfo,
  424. &dwCacheEntryInfoSize));
  425. if ((dwLastErr = GetLastError()) != ERROR_NO_MORE_ITEMS)
  426. {
  427. hr = HRESULT_FROM_WIN32(dwLastErr);
  428. }
  429. }
  430. if (lpCacheEntryInfo != NULL)
  431. {
  432. LocalFree(lpCacheEntryInfo);
  433. lpCacheEntryInfo = NULL;
  434. }
  435. return hr;
  436. }
  437. //
  438. //------------------------------------------------------------------------------
  439. // CInternetCacheCleaner::DelInternetCacheFiles
  440. //
  441. // Purpose: Delete the internet cache files
  442. //------------------------------------------------------------------------------
  443. //
  444. HRESULT CInternetCacheCleaner::DelInternetCacheFiles(
  445. DWORD dwPercentToFree,
  446. IEmptyVolumeCacheCallBack *picb // not used
  447. )
  448. {
  449. HRESULT hr = S_OK;
  450. if (*m_szCacheDir == '\0') // Internet cache dir is not yet initialized
  451. {
  452. hr = GetCacheLocation(m_szCacheDir, ARRAYSIZE(m_szCacheDir));
  453. }
  454. if (SUCCEEDED(hr))
  455. {
  456. FreeUrlCacheSpace(m_szCacheDir, dwPercentToFree, STICKY_CACHE_ENTRY);
  457. }
  458. return hr;
  459. }