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.

457 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. diskcleaner.c
  5. Abstract:
  6. Implements the code specific to the disk cleaner COM server.
  7. Author:
  8. Jim Schmidt (jimschm) 21-Jan-2001
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. #include "undop.h"
  14. #include "com.h"
  15. /*++
  16. Routine Descriptions:
  17. This constructor is a generic class factory that supports multiple object
  18. types. Upon creation, the object interface pointer ref count is set to zero,
  19. and the global number of objects for the dll is incremented.
  20. The destructor simply decrements the DLL object count.
  21. Arguments:
  22. None.
  23. Return Value:
  24. None.
  25. --*/
  26. CUninstallDiskCleaner::CUninstallDiskCleaner (
  27. VOID
  28. )
  29. {
  30. //
  31. // -Initialize the interface pointer count
  32. // -Increment the DLL's global count of objects
  33. //
  34. _References = 0;
  35. g_DllObjects++;
  36. }
  37. CUninstallDiskCleaner::~CUninstallDiskCleaner (
  38. VOID
  39. )
  40. {
  41. g_DllObjects--;
  42. }
  43. STDMETHODIMP
  44. CUninstallDiskCleaner::QueryInterface (
  45. IN REFIID InterfaceIdRef,
  46. OUT PVOID *InterfacePtr
  47. )
  48. {
  49. HRESULT hr = S_OK;
  50. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Entering"));
  51. __try {
  52. //
  53. // Initialize out arg
  54. //
  55. __try {
  56. *InterfacePtr = NULL;
  57. }
  58. __except(EXCEPTION_EXECUTE_HANDLER) {
  59. hr = E_INVALIDARG;
  60. }
  61. if (hr != S_OK) {
  62. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Invalid InterfacePtr arg"));
  63. __leave;
  64. }
  65. //
  66. // Test for the supported interface
  67. //
  68. if (IsEqualIID (InterfaceIdRef, IID_IUnknown)) {
  69. DEBUGMSG ((DBG_VERBOSE, "Caller requested IUnknown"));
  70. *InterfacePtr = (LPUNKNOWN) this;
  71. AddRef();
  72. __leave;
  73. }
  74. if (IsEqualIID (InterfaceIdRef, IID_IEmptyVolumeCache)) {
  75. DEBUGMSG ((DBG_VERBOSE, "Caller requested IEmptyVolumeCache"));
  76. *InterfacePtr = (IEmptyVolumeCache*) this;
  77. AddRef();
  78. __leave;
  79. }
  80. DEBUGMSG ((DBG_WARNING, "Caller requested unknown interface"));
  81. hr = E_NOINTERFACE;
  82. }
  83. __finally {
  84. }
  85. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Leaving"));
  86. return hr;
  87. }
  88. /*++
  89. Routine Description:
  90. AddRef is the standard IUnknown member function that increments the object
  91. reference count.
  92. Release is the standard IUnknown member function that decrements the object
  93. reference count.
  94. Arguments:
  95. None.
  96. Return Value:
  97. The number of interface references.
  98. --*/
  99. STDMETHODIMP_(ULONG)
  100. CUninstallDiskCleaner::AddRef (
  101. VOID
  102. )
  103. {
  104. return ++_References;
  105. }
  106. STDMETHODIMP_(ULONG)
  107. CUninstallDiskCleaner::Release (
  108. VOID
  109. )
  110. {
  111. if (!_References) {
  112. DEBUGMSG ((DBG_ERROR, "Can't release because there are no references"));
  113. } else {
  114. _References--;
  115. if (!_References) {
  116. delete this;
  117. return 0;
  118. }
  119. }
  120. return _References;
  121. }
  122. STDMETHODIMP
  123. CUninstallDiskCleaner::Initialize (
  124. IN HKEY hRegKey,
  125. IN PCWSTR VolumePath,
  126. OUT PWSTR *DisplayName,
  127. OUT PWSTR *Description,
  128. IN OUT DWORD *Flags
  129. )
  130. /*++
  131. Routine Description:
  132. The Initialize member function does most of the work for the disk cleaner.
  133. It evaluates the backup files, and if they all exist, and the user has the
  134. right to execute an uninstall, and if they are at least 7 days old, then
  135. show the backup items in the list box.
  136. Arguments:
  137. hRegKey - Specifies the registry key for this object, used to store
  138. properties and settings
  139. VolumePath - Specifies the volume path selected by the user when they launch
  140. disk cleanup
  141. DisplayName - Receives the name to put in the disk cleaner list box, or NULL
  142. to use the name stored in the registry
  143. Description - Receives the verbose description to put in the disk cleaner
  144. Details text control, or NULL to use the description stored in the
  145. registry
  146. Flags - Specifies flags that influence the behavior of this disk cleaner
  147. object and flags that indicate which mode the disk cleaner is running
  148. in. Receivies flags that control how the disk cleaner displays this
  149. object's info in its UI.
  150. Return Value:
  151. S_FALSE - The disk cleaner will skip this object
  152. S_OK - The disk cleaner will include this object in its UI
  153. --*/
  154. {
  155. HRESULT hr = S_FALSE;
  156. DWORD inFlags;
  157. ULONGLONG diskSpace;
  158. UNINSTALLSTATUS status;
  159. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Entering"));
  160. __try {
  161. __try{
  162. //
  163. // Initialize
  164. //
  165. inFlags = *Flags;
  166. *DisplayName = NULL; // use the display name stored in the registry
  167. *Description = NULL; // use the description stored in the registry
  168. *Flags = 0; // unchecked by default, no property page
  169. }
  170. __except(EXCEPTION_EXECUTE_HANDLER){
  171. hr = E_INVALIDARG;
  172. }
  173. if (hr != S_OK) {
  174. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Invalid arg(s)"));
  175. __leave;
  176. }
  177. _Purged = FALSE;
  178. //
  179. // Check undo files. If they are not at least 7 days old, don't
  180. // recommend them to be deleted.
  181. //
  182. status = SanityCheck (FAIL_IF_NOT_OLD, VolumePath, &diskSpace);
  183. if (status == Uninstall_NewImage) {
  184. DEBUGMSG ((DBG_WARNING, "OS Backup Image is too new to be listed in the disk cleaner"));
  185. __leave;
  186. }
  187. if (diskSpace == 0) {
  188. DEBUGMSG ((DBG_WARNING, "OS Backup Image is not present, isn't valid, can't be removed, or has missing registry entries"));
  189. __leave;
  190. }
  191. //
  192. // Files are old enough and are present on the machine. Initialize the
  193. // IEmptyVolumeCache interface
  194. //
  195. if (inFlags & EVCF_SETTINGSMODE) {
  196. DEBUGMSG ((DBG_VERBOSE, "We don't support settings mode"));
  197. __leave;
  198. }
  199. hr = S_OK;
  200. DEBUGMSG ((DBG_VERBOSE, "Successful initialization"));
  201. }
  202. __finally {
  203. }
  204. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Leaving"));
  205. return hr;
  206. }
  207. STDMETHODIMP
  208. CUninstallDiskCleaner::GetSpaceUsed (
  209. OUT DWORDLONG *SpaceUsed,
  210. IN IEmptyVolumeCacheCallBack *Callback
  211. )
  212. /*++
  213. Routine Description:
  214. GetSpaceUsed is called by the disk cleaner after this object has
  215. successfully initialized. Our job is to return the amount of disk space we
  216. can clean up. Since all undo files are on the same drive, we don't care
  217. about the volume restriction passed to the Initialize member function.
  218. Arguments:
  219. SpaceUsed - Receives the amount of disk space that we can recover upon
  220. deletion. We don't take into account cluster savings, but maybe we
  221. should.
  222. Callback - Specifies an object that provides a progress interface. We don't
  223. use this.
  224. Return Value:
  225. S_FALSE - Failed to get disk space values
  226. S_OK - Success
  227. --*/
  228. {
  229. ULONGLONG diskSpace;
  230. HRESULT hr = S_FALSE;
  231. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Entering"));
  232. __try {
  233. __try{
  234. //
  235. // Initialize
  236. //
  237. *SpaceUsed = 0;
  238. }
  239. __except(EXCEPTION_EXECUTE_HANDLER){
  240. hr = E_INVALIDARG;
  241. }
  242. if (hr != S_OK) {
  243. DEBUGMSG ((DBG_ERROR, __FUNCTION__ ": Invalid arg(s)"));
  244. __leave;
  245. }
  246. if (SanityCheck (QUICK_CHECK, NULL, &diskSpace) == Uninstall_NewImage) {
  247. DEBUGMSG ((DBG_ERROR, "Sanity check failed"));
  248. __leave;
  249. }
  250. DEBUGMSG ((DBG_VERBOSE, "Disk space: %I64u", diskSpace));
  251. *SpaceUsed = (DWORDLONG) diskSpace;
  252. hr = S_OK;
  253. }
  254. __finally {
  255. }
  256. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Leaving"));
  257. return hr;
  258. }
  259. STDMETHODIMP
  260. CUninstallDiskCleaner::Purge (
  261. IN DWORDLONG SpaceToFree,
  262. IN IEmptyVolumeCacheCallBack *Callback
  263. )
  264. /*++
  265. Routine Description:
  266. Purge does the deletion. We don't care about the inbound arguments. If we
  267. are called, it is because Initialize succeeded, and GetSpaceUsed returned a
  268. valid number. These two things mean it is OK to remove uninstall capability.
  269. Arguments:
  270. SpaceToFree - Specifies the space to free. We expect this to equal the
  271. value provided in GetSpaceUsed.
  272. Callback - Specifies an interface for progress updates. We don't use this.
  273. Return Value:
  274. S_OK - Success
  275. S_FALSE - Failed
  276. --*/
  277. {
  278. HRESULT hr = S_FALSE;
  279. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Entering"));
  280. __try {
  281. if (!DoCleanup()) {
  282. __leave;
  283. }
  284. _Purged = TRUE;
  285. hr = S_OK;
  286. }
  287. __finally {
  288. }
  289. DEBUGMSG ((DBG_VERBOSE, __FUNCTION__ ": Leaving"));
  290. return hr;
  291. }
  292. //
  293. // NO-OP property page stub
  294. //
  295. STDMETHODIMP
  296. CUninstallDiskCleaner::ShowProperties (
  297. IN HWND hwnd
  298. )
  299. {
  300. MYASSERT (FALSE);
  301. return S_FALSE;
  302. }
  303. STDMETHODIMP
  304. CUninstallDiskCleaner::Deactivate (
  305. OUT DWORD *Flags
  306. )
  307. /*++
  308. Routine Description:
  309. Deactivate indicates if the uninstall list item should be permanently
  310. removed from the disk cleaner or not, based on a successful deletion of the
  311. backup image.
  312. Arguments:
  313. Flags - Receives the indicator to remove the list item from the disk
  314. cleaner list
  315. Return Value:
  316. Always S_OK
  317. --*/
  318. {
  319. //
  320. // Done -- if we deleted uninstall, remove the list item
  321. //
  322. if(!Flags){
  323. MYASSERT(FALSE);
  324. return E_INVALIDARG;
  325. }
  326. *Flags = _Purged ? EVCF_REMOVEFROMLIST : 0;
  327. return S_OK;
  328. }