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.

282 lines
8.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: volclean.cpp
  8. //
  9. // Authors;
  10. // Jeff Saathoff (jeffreys)
  11. //
  12. // Notes;
  13. // CSC disk cleanup implementation (IEmptyVolumeCache)
  14. //--------------------------------------------------------------------------
  15. #include "pch.h"
  16. #include "folder.h"
  17. int
  18. CoTaskLoadString(HINSTANCE hInstance, UINT idString, LPWSTR *ppwsz)
  19. {
  20. int nResult = 0;
  21. *ppwsz = NULL;
  22. ULONG cchString = SizeofStringResource(hInstance, idString);
  23. if (cchString)
  24. {
  25. cchString++; // for NULL
  26. *ppwsz = (LPWSTR)CoTaskMemAlloc(cchString * sizeof(WCHAR));
  27. if (*ppwsz)
  28. nResult = LoadStringW(hInstance, idString, *ppwsz, cchString);
  29. }
  30. return nResult;
  31. }
  32. ///////////////////////////////////////////////////////////////////////////////
  33. // //
  34. // IClassFactory::CreateInstance support //
  35. // //
  36. ///////////////////////////////////////////////////////////////////////////////
  37. HRESULT WINAPI
  38. CCscVolumeCleaner::CreateInstance(REFIID riid, LPVOID *ppv)
  39. {
  40. return Create(FALSE, riid, ppv);
  41. }
  42. HRESULT WINAPI
  43. CCscVolumeCleaner::CreateInstance2(REFIID riid, LPVOID *ppv)
  44. {
  45. return Create(TRUE, riid, ppv);
  46. }
  47. HRESULT WINAPI
  48. CCscVolumeCleaner::Create(BOOL fPinned, REFIID riid, LPVOID *ppv)
  49. {
  50. HRESULT hr;
  51. CCscVolumeCleaner *pThis = new CCscVolumeCleaner(fPinned);
  52. if (pThis)
  53. {
  54. hr = pThis->QueryInterface(riid, ppv);
  55. pThis->Release();
  56. }
  57. else
  58. hr = E_OUTOFMEMORY;
  59. return hr;
  60. }
  61. ///////////////////////////////////////////////////////////////////////////////
  62. // //
  63. // IUnknown implementation //
  64. // //
  65. ///////////////////////////////////////////////////////////////////////////////
  66. STDMETHODIMP CCscVolumeCleaner::QueryInterface(REFIID riid, void **ppv)
  67. {
  68. static const QITAB qit[] =
  69. {
  70. QITABENT(CCscVolumeCleaner, IEmptyVolumeCache),
  71. QITABENT(CCscVolumeCleaner, IEmptyVolumeCache2),
  72. { 0 },
  73. };
  74. return QISearch(this, qit, riid, ppv);
  75. }
  76. STDMETHODIMP_(ULONG) CCscVolumeCleaner::AddRef()
  77. {
  78. return InterlockedIncrement(&m_cRef);
  79. }
  80. STDMETHODIMP_(ULONG) CCscVolumeCleaner::Release()
  81. {
  82. if (InterlockedDecrement(&m_cRef))
  83. return m_cRef;
  84. delete this;
  85. return 0;
  86. }
  87. ///////////////////////////////////////////////////////////////////////////////
  88. // //
  89. // IEmptyVolumeCache implementation //
  90. // //
  91. ///////////////////////////////////////////////////////////////////////////////
  92. STDMETHODIMP
  93. CCscVolumeCleaner::Initialize(HKEY /*hkRegKey*/,
  94. LPCWSTR pcwszVolume,
  95. LPWSTR *ppwszDisplayName,
  96. LPWSTR *ppwszDescription,
  97. LPDWORD pdwFlags)
  98. {
  99. BOOL bSettingsMode;
  100. CSCSPACEUSAGEINFO sui = {0};
  101. USES_CONVERSION;
  102. TraceEnter(TRACE_SHELLEX, "IEmptyVolumeCache::Initialize");
  103. TraceAssert(pcwszVolume != NULL);
  104. TraceAssert(ppwszDisplayName != NULL);
  105. TraceAssert(ppwszDescription != NULL);
  106. TraceAssert(pdwFlags != NULL);
  107. TraceAssert(IsCSCEnabled());
  108. bSettingsMode = (BOOL)((*pdwFlags) & EVCF_SETTINGSMODE);
  109. *ppwszDisplayName = NULL;
  110. *ppwszDescription = NULL;
  111. *pdwFlags = 0;
  112. // If this isn't the volume containing the CSC database, then we have
  113. // nothing to free. Note that we don't use the space usage data
  114. // returned here.
  115. GetCscSpaceUsageInfo(&sui);
  116. if (!bSettingsMode && !PathIsSameRoot(sui.szVolume, W2CT(pcwszVolume)))
  117. TraceLeaveResult(S_FALSE);
  118. m_PurgerSel.SetFlags(m_fPinned ? PURGE_FLAG_PINNED : (PURGE_FLAG_UNPINNED | PURGE_IGNORE_ACCESS));
  119. m_pPurger = new CCachePurger(m_PurgerSel,
  120. CachePurgerCallback,
  121. this);
  122. if (!m_pPurger)
  123. TraceLeaveResult(E_FAIL);
  124. // If we're freeing auto-cached files, we want to be enabled by default,
  125. // but not if we're freeing pinned files.
  126. *pdwFlags = 0;
  127. if (!m_fPinned)
  128. *pdwFlags = EVCF_ENABLEBYDEFAULT | EVCF_ENABLEBYDEFAULT_AUTO;
  129. // If policy allows, turn on the "Details" button which launches the viewer
  130. if (!CConfig::GetSingleton().NoCacheViewer())
  131. *pdwFlags |= EVCF_HASSETTINGS;
  132. // Load the display name string
  133. CoTaskLoadString(g_hInstance,
  134. m_fPinned ? IDS_APPLICATION : IDS_DISKCLEAN_DISPLAY,
  135. ppwszDisplayName);
  136. // Load the description string
  137. CoTaskLoadString(g_hInstance,
  138. m_fPinned ? IDS_DISKCLEAN_PIN_DESCRIPTION : IDS_DISKCLEAN_DESCRIPTION,
  139. ppwszDescription);
  140. TraceLeaveResult(S_OK);
  141. }
  142. STDMETHODIMP
  143. CCscVolumeCleaner::GetSpaceUsed(DWORDLONG *pdwlSpaceUsed,
  144. LPEMPTYVOLUMECACHECALLBACK picb)
  145. {
  146. m_pDiskCleaner = picb;
  147. m_pPurger->Scan();
  148. if (m_pDiskCleaner)
  149. m_pDiskCleaner->ScanProgress(m_dwlSpaceToFree,
  150. EVCCBF_LASTNOTIFICATION,
  151. NULL);
  152. *pdwlSpaceUsed = m_dwlSpaceToFree;
  153. return S_OK;
  154. }
  155. STDMETHODIMP
  156. CCscVolumeCleaner::Purge(DWORDLONG /*dwlSpaceToFree*/,
  157. LPEMPTYVOLUMECACHECALLBACK picb)
  158. {
  159. m_pDiskCleaner = picb;
  160. m_pPurger->Delete();
  161. if (m_pDiskCleaner)
  162. m_pDiskCleaner->PurgeProgress(m_dwlSpaceFreed,
  163. 0,
  164. EVCCBF_LASTNOTIFICATION,
  165. NULL);
  166. return S_OK;
  167. }
  168. STDMETHODIMP
  169. CCscVolumeCleaner::ShowProperties(HWND /*hwnd*/)
  170. {
  171. // Launch the viewer
  172. COfflineFilesFolder::Open();
  173. return S_FALSE;
  174. }
  175. STDMETHODIMP
  176. CCscVolumeCleaner::Deactivate(LPDWORD /*pdwFlags*/)
  177. {
  178. // nothing to do here
  179. return S_OK;
  180. }
  181. // IEmptyVolumeCache2 method
  182. STDMETHODIMP
  183. CCscVolumeCleaner::InitializeEx(HKEY hkRegKey,
  184. LPCWSTR pcwszVolume,
  185. LPCWSTR pcwszKeyName,
  186. LPWSTR *ppwszDisplayName,
  187. LPWSTR *ppwszDescription,
  188. LPWSTR *ppwszBtnText,
  189. LPDWORD pdwFlags)
  190. {
  191. HRESULT hr = Initialize(hkRegKey,
  192. pcwszVolume,
  193. ppwszDisplayName,
  194. ppwszDescription,
  195. pdwFlags);
  196. if (S_OK == hr)
  197. CoTaskLoadString(g_hInstance, IDS_DISKCLEAN_BTN_TEXT, ppwszBtnText);
  198. return hr;
  199. }
  200. BOOL
  201. CCscVolumeCleaner::ScanCallback(CCachePurger *pPurger)
  202. {
  203. BOOL bContinue = TRUE;
  204. // If the pinned state matches what we're looking for, add the
  205. // size to the total.
  206. if (pPurger->WillDeleteThisFile())
  207. m_dwlSpaceToFree += pPurger->FileBytes();
  208. if (m_pDiskCleaner)
  209. bContinue = SUCCEEDED(m_pDiskCleaner->ScanProgress(m_dwlSpaceToFree,
  210. 0,
  211. NULL));
  212. return bContinue;
  213. }
  214. BOOL
  215. CCscVolumeCleaner::DeleteCallback(CCachePurger *pPurger)
  216. {
  217. BOOL bContinue = TRUE;
  218. // Don't let this go below zero
  219. m_dwlSpaceToFree -= min(pPurger->FileBytes(), m_dwlSpaceToFree);
  220. m_dwlSpaceFreed += pPurger->FileBytes();
  221. if (m_pDiskCleaner)
  222. bContinue = SUCCEEDED(m_pDiskCleaner->PurgeProgress(m_dwlSpaceFreed,
  223. m_dwlSpaceToFree,
  224. 0,
  225. NULL));
  226. return bContinue;
  227. }
  228. BOOL CALLBACK
  229. CCscVolumeCleaner::CachePurgerCallback(CCachePurger *pPurger)
  230. {
  231. PCSCVOLCLEANER pThis = (PCSCVOLCLEANER)pPurger->CallbackData();
  232. switch (pPurger->Phase())
  233. {
  234. case PURGE_PHASE_SCAN:
  235. return pThis->ScanCallback(pPurger);
  236. case PURGE_PHASE_DELETE:
  237. return pThis->DeleteCallback(pPurger);
  238. }
  239. return FALSE;
  240. }