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.

511 lines
14 KiB

  1. /******************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. diskcleanup.cpp -- disk cleanup COM object for SR
  4. Description:
  5. delete datastores from stale builds
  6. ******************************************************************/
  7. #include <nt.h>
  8. #include <ntrtl.h>
  9. #include <nturtl.h>
  10. #include <windef.h>
  11. #include <wtypes.h>
  12. #include <winuser.h>
  13. #include "diskcleanup.h"
  14. #include "resource.h"
  15. #include <utils.h>
  16. #include <srdefs.h>
  17. extern HMODULE ghModule;
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Function: CSREmptyVolumeCache2::LoadBootIni
  21. //
  22. // Synopsis: parse the boot.ini file
  23. //
  24. // Arguments:
  25. //
  26. // History: 20-Jul-2000 HenryLee Created
  27. //
  28. //----------------------------------------------------------------------------
  29. DWORD CSREmptyVolumeCache2::LoadBootIni()
  30. {
  31. HANDLE hFile = INVALID_HANDLE_VALUE;
  32. WCHAR *pwszThisGuid = NULL;
  33. CHAR *pszContent = NULL;
  34. CHAR *pszLine = NULL;
  35. DWORD dwErr = ERROR_SUCCESS;
  36. CHAR szArcName[MAX_PATH];
  37. CHAR szOptions[MAX_PATH];
  38. pwszThisGuid = GetMachineGuid (); // always exclude the current datastore
  39. if (pwszThisGuid != NULL && pwszThisGuid[0] != L'\0')
  40. {
  41. lstrcpyW (_wszGuid[_ulGuids], s_cszRestoreDir);
  42. lstrcatW (_wszGuid[_ulGuids], pwszThisGuid );
  43. _ulGuids++;
  44. }
  45. // Read the contents of the boot.ini file into a string.
  46. hFile = CreateFileW (L"c:\\boot.ini",
  47. GENERIC_READ,
  48. FILE_SHARE_READ,
  49. NULL, OPEN_EXISTING, 0, NULL);
  50. if (INVALID_HANDLE_VALUE == hFile)
  51. {
  52. dwErr = GetLastError();
  53. return dwErr;
  54. }
  55. DWORD dwBytesRead = 0;
  56. DWORD dwBytesToRead = GetFileSize(hFile, NULL);
  57. if (dwBytesToRead == 0xFFFFFFFF || 0 == dwBytesToRead)
  58. {
  59. dwErr = GetLastError();
  60. goto Err;
  61. }
  62. pszContent = new CHAR [dwBytesToRead];
  63. if (pszContent == NULL)
  64. {
  65. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  66. goto Err;
  67. }
  68. if (FALSE==ReadFile(hFile, pszContent, dwBytesToRead, &dwBytesRead, NULL))
  69. {
  70. dwErr = GetLastError();
  71. goto Err;
  72. }
  73. if (dwBytesToRead != dwBytesRead)
  74. {
  75. dwErr = ERROR_READ_FAULT;
  76. goto Err;
  77. }
  78. CloseHandle (hFile);
  79. hFile = INVALID_HANDLE_VALUE;
  80. pszLine = pszContent;
  81. for (UINT i = 0; i < dwBytesRead; i++)
  82. {
  83. if (pszContent[i] == '=') // field indicator
  84. pszContent[i] = '\0'; // process only the 1st field
  85. if (pszContent[i] == '\n') // end-of-line indicator
  86. {
  87. pszContent[i] = '\0';
  88. if (strncmp (pszLine, "multi", 5) == 0)
  89. {
  90. HANDLE hGuidFile;
  91. WCHAR wcsPath[MAX_PATH];
  92. WCHAR wcsGuid [RESTOREGUID_STRLEN];
  93. OBJECT_ATTRIBUTES oa;
  94. UNICODE_STRING us;
  95. IO_STATUS_BLOCK iosb;
  96. wsprintfW (wcsPath, L"\\ArcName\\%hs\\System32\\Restore\\"
  97. L"MachineGuid.txt", pszLine);
  98. RtlInitUnicodeString (&us, wcsPath);
  99. InitializeObjectAttributes ( &oa, &us, OBJ_CASE_INSENSITIVE,
  100. NULL, NULL);
  101. NTSTATUS nts = NtCreateFile (&hGuidFile,
  102. FILE_GENERIC_READ,
  103. &oa,
  104. &iosb,
  105. NULL,
  106. FILE_ATTRIBUTE_NORMAL,
  107. FILE_SHARE_WRITE | FILE_SHARE_DELETE | FILE_SHARE_READ,
  108. FILE_OPEN,
  109. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
  110. NULL,
  111. 0);
  112. if (!NT_SUCCESS(nts))
  113. {
  114. dwErr = RtlNtStatusToDosError (nts);
  115. }
  116. else
  117. {
  118. dwBytesToRead = RESTOREGUID_STRLEN * sizeof(WCHAR);
  119. DWORD dwRead = 0;
  120. dwErr = ERROR_SUCCESS;
  121. if (FALSE == ReadFile (hGuidFile, (BYTE *) wcsGuid,
  122. dwBytesToRead, &dwRead, NULL))
  123. {
  124. dwErr = GetLastError();
  125. }
  126. if (_ulGuids < ARRAYSIZE && ERROR_SUCCESS == dwErr)
  127. {
  128. lstrcpyW (_wszGuid[_ulGuids], s_cszRestoreDir);
  129. lstrcatW (_wszGuid[_ulGuids], (wcsGuid[0]==0xFEFF) ?
  130. &wcsGuid[1] : wcsGuid );
  131. _ulGuids++;
  132. }
  133. NtClose (hGuidFile);
  134. }
  135. }
  136. pszLine = &pszContent [i+1]; // skip to next line
  137. }
  138. }
  139. Err:
  140. if (pszContent != NULL)
  141. delete [] pszContent;
  142. if (hFile != INVALID_HANDLE_VALUE)
  143. CloseHandle (hFile);
  144. return dwErr;
  145. }
  146. //+---------------------------------------------------------------------------
  147. //
  148. // Function: CSREmptyVolumeCache2::EnumDataStores
  149. //
  150. // Synopsis: enumerate the data store on a volume
  151. //
  152. // Arguments:
  153. //
  154. // History: 20-Jul-2000 HenryLee Created
  155. //
  156. //----------------------------------------------------------------------------
  157. DWORD CSREmptyVolumeCache2::EnumDataStores (DWORDLONG *pdwlSpaceUsed,
  158. IEmptyVolumeCacheCallBack *picb,
  159. BOOL fPurge,
  160. WCHAR *pwszVolume)
  161. {
  162. HANDLE hFind = NULL;
  163. DWORD dwErr = ERROR_SUCCESS;
  164. WIN32_FIND_DATA wfd;
  165. WCHAR wcsPath [MAX_PATH];
  166. *pdwlSpaceUsed = 0;
  167. if (pwszVolume == NULL || pwszVolume[0] == L'\0') // no volume defined
  168. return dwErr;
  169. wsprintfW (wcsPath, L"%s%s\\%s*", pwszVolume,
  170. s_cszSysVolInfo, s_cszRestoreDir);
  171. hFind = FindFirstFileW (wcsPath, &wfd);
  172. if (hFind == INVALID_HANDLE_VALUE) // no files
  173. return dwErr;
  174. do
  175. {
  176. if (TRUE == _fStop)
  177. {
  178. FindClose (hFind);
  179. return ERROR_OPERATION_ABORTED;
  180. }
  181. if (!lstrcmp(wfd.cFileName, L".") || !lstrcmp(wfd.cFileName, L".."))
  182. continue;
  183. for (UINT i=0; i < _ulGuids; i++)
  184. {
  185. if (lstrcmpi (_wszGuid[i], wfd.cFileName) == 0)
  186. {
  187. break; // data store match
  188. }
  189. }
  190. if (i >= _ulGuids) // no data store match
  191. {
  192. if (picb != NULL)
  193. {
  194. WCHAR wcsDataStore[MAX_PATH];
  195. lstrcpyW (wcsPath, pwszVolume);
  196. lstrcatW (wcsPath, s_cszSysVolInfo);
  197. lstrcatW (wcsPath, L"\\");
  198. lstrcatW (wcsPath, wfd.cFileName);
  199. if (!fPurge) // calculate space usage
  200. {
  201. dwErr = GetFileSize_Recurse (wcsPath,
  202. (INT64*) pdwlSpaceUsed,
  203. &_fStop);
  204. }
  205. else // delete the data store
  206. {
  207. dwErr = Delnode_Recurse (wcsPath, TRUE, &_fStop);
  208. }
  209. }
  210. else
  211. {
  212. *pdwlSpaceUsed = 1; // indicate something to clean up
  213. }
  214. }
  215. }
  216. while (FindNextFileW (hFind, &wfd));
  217. FindClose (hFind);
  218. if (picb != NULL) // update the progress bar
  219. {
  220. if (!fPurge)
  221. picb->ScanProgress (*pdwlSpaceUsed, EVCCBF_LASTNOTIFICATION , NULL);
  222. else
  223. picb->PurgeProgress (*pdwlSpaceUsed,0,EVCCBF_LASTNOTIFICATION,NULL);
  224. }
  225. return dwErr;
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // Function: CSREmptyVolumeCache2::ForAllMountPoints
  230. //
  231. // Synopsis: call EnumerateDataStores for each mount point
  232. //
  233. // Arguments:
  234. //
  235. // History: 20-Jul-2000 HenryLee Created
  236. //
  237. //----------------------------------------------------------------------------
  238. HRESULT CSREmptyVolumeCache2::ForAllMountPoints (DWORDLONG *pdwlSpaceUsed,
  239. IEmptyVolumeCacheCallBack *picb,
  240. BOOL fPurge)
  241. {
  242. DWORD dwErr = ERROR_SUCCESS;
  243. dwErr = EnumDataStores (pdwlSpaceUsed, picb, fPurge, _wszVolume);
  244. if (ERROR_SUCCESS == dwErr)
  245. {
  246. WCHAR wszMount [MAX_PATH];
  247. HANDLE hFind = FindFirstVolumeMountPoint (_wszVolume,wszMount,MAX_PATH);
  248. if (hFind != INVALID_HANDLE_VALUE)
  249. {
  250. do
  251. {
  252. dwErr = EnumDataStores (pdwlSpaceUsed, picb, fPurge, wszMount);
  253. if (dwErr != ERROR_SUCCESS)
  254. break;
  255. }
  256. while (FindNextVolumeMountPoint (hFind, wszMount, MAX_PATH));
  257. FindVolumeMountPointClose (hFind);
  258. }
  259. }
  260. return HRESULT_FROM_WIN32 (dwErr);
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Function: CSRClassFactory::CreateInstance
  265. //
  266. // Synopsis: create the disk cleanup plugin object
  267. //
  268. // Arguments:
  269. //
  270. // History: 20-Jul-2000 HenryLee Created
  271. //
  272. //----------------------------------------------------------------------------
  273. HRESULT CSRClassFactory::CreateInstance (IUnknown *pUnkOuter,
  274. REFIID riid,
  275. void **ppvObject)
  276. {
  277. HRESULT hr = S_OK;
  278. if (pUnkOuter != NULL)
  279. return CLASS_E_NOAGGREGATION;
  280. CSREmptyVolumeCache2 *pevc = new CSREmptyVolumeCache2();
  281. if (pevc == NULL)
  282. return E_OUTOFMEMORY;
  283. hr = pevc->QueryInterface (riid, ppvObject);
  284. pevc->Release(); // release constructor's reference
  285. return hr;
  286. }
  287. //+---------------------------------------------------------------------------
  288. //
  289. // Function: CSREmptyVolumeCache2::InitializeEx
  290. //
  291. // Synopsis: initialize the disk cleanup plugin object
  292. //
  293. // Arguments:
  294. //
  295. // History: 20-Jul-2000 HenryLee Created
  296. //
  297. //----------------------------------------------------------------------------
  298. HRESULT CSREmptyVolumeCache2::InitializeEx (
  299. HKEY hkRegKey,
  300. const WCHAR *pcwszVolume,
  301. const WCHAR *pcwszKeyName,
  302. WCHAR **ppwszDisplayName,
  303. WCHAR **ppwszDescription,
  304. WCHAR **ppwszBtnText,
  305. DWORD *pdwFlags)
  306. {
  307. DWORDLONG dwlSpaceUsed = 0;
  308. WCHAR *pwszDisplay = NULL;
  309. WCHAR *pwszDescription = NULL;
  310. HRESULT hr=S_OK;
  311. pwszDisplay = (WCHAR *) CoTaskMemAlloc (MAX_PATH / 2 * sizeof(WCHAR));
  312. if (NULL == pwszDisplay)
  313. {
  314. hr = E_OUTOFMEMORY;
  315. goto Err;
  316. }
  317. pwszDescription = (WCHAR *) CoTaskMemAlloc (MAX_PATH * 2 * sizeof(WCHAR));
  318. if (NULL == pwszDescription)
  319. {
  320. hr = E_OUTOFMEMORY;
  321. goto Err;
  322. }
  323. if (0 == LoadStringW (ghModule, IDS_DISKCLEANUP_DISPLAY,
  324. pwszDisplay, MAX_PATH / 2))
  325. {
  326. hr = HRESULT_FROM_WIN32 (GetLastError());
  327. goto Err;
  328. }
  329. if (0 == LoadStringW (ghModule, IDS_DISKCLEANUP_DESCRIPTION,
  330. pwszDescription, MAX_PATH * 2))
  331. {
  332. hr = HRESULT_FROM_WIN32 (GetLastError());
  333. goto Err;
  334. }
  335. lstrcpyW (_wszVolume, pcwszVolume);
  336. LoadBootIni(); // best effort, okay to fail
  337. ForAllMountPoints (&dwlSpaceUsed, NULL, FALSE);
  338. if (pdwFlags)
  339. {
  340. *pdwFlags |= (EVCF_ENABLEBYDEFAULT |
  341. EVCF_ENABLEBYDEFAULT_AUTO |
  342. EVCF_DONTSHOWIFZERO);
  343. }
  344. if (dwlSpaceUsed == 0)
  345. hr = S_FALSE;
  346. Err:
  347. if (FAILED(hr))
  348. {
  349. if (pwszDisplay)
  350. CoTaskMemFree (pwszDisplay);
  351. if (pwszDescription)
  352. CoTaskMemFree (pwszDescription);
  353. if (ppwszDisplayName)
  354. *ppwszDisplayName = NULL;
  355. if (ppwszDescription)
  356. *ppwszDescription = NULL;
  357. }
  358. else
  359. {
  360. if (ppwszDisplayName)
  361. *ppwszDisplayName = pwszDisplay;
  362. if (ppwszDescription)
  363. *ppwszDescription = pwszDescription;
  364. }
  365. if (ppwszBtnText) // no advanced button text
  366. *ppwszBtnText = NULL;
  367. return hr;
  368. }
  369. //+---------------------------------------------------------------------------
  370. //
  371. // Function: CSREmptyVolumeCache2::GetSpaceUsed
  372. //
  373. // Synopsis: returns how much space can be freed on a volume
  374. //
  375. // Arguments:
  376. //
  377. // History: 20-Jul-2000 HenryLee Created
  378. //
  379. //----------------------------------------------------------------------------
  380. HRESULT CSREmptyVolumeCache2::GetSpaceUsed ( DWORDLONG *pdwlSpaceUsed,
  381. IEmptyVolumeCacheCallBack *picb)
  382. {
  383. return ForAllMountPoints (pdwlSpaceUsed, picb, FALSE);
  384. }
  385. //+---------------------------------------------------------------------------
  386. //
  387. // Function: CSREmptyVolumeCache2::Purge
  388. //
  389. // Synopsis: frees the disk space on a volume
  390. //
  391. // Arguments:
  392. //
  393. // History: 20-Jul-2000 HenryLee Created
  394. //
  395. //----------------------------------------------------------------------------
  396. HRESULT CSREmptyVolumeCache2::Purge ( DWORDLONG dwlSpaceToFree,
  397. IEmptyVolumeCacheCallBack *picb)
  398. {
  399. return ForAllMountPoints (&dwlSpaceToFree, picb, TRUE);
  400. }
  401. //+---------------------------------------------------------------------------
  402. //
  403. // Function: CSREmptyVolumeCache2::Deactivate
  404. //
  405. // Synopsis: signal the disk cleanup plugin to stop processing
  406. //
  407. // Arguments:
  408. //
  409. // History: 20-Jul-2000 HenryLee Created
  410. //
  411. //----------------------------------------------------------------------------
  412. HRESULT CSREmptyVolumeCache2::Deactivate (DWORD *pdwFlags)
  413. {
  414. HRESULT hr=S_OK;
  415. if (pdwFlags)
  416. *pdwFlags = 0; // no flags to be returned
  417. _fStop = TRUE;
  418. return hr;
  419. }