Click here to Skip to main content
15,884,472 members
Articles / Programming Languages / C++

A Cleanup API for Windows

Rate me:
Please Sign up or sign in to vote.
4.83/5 (23 votes)
24 Aug 2006CPOL18 min read 228.8K   3.7K   84  
Provides a general cleanup API for Windows, ported into Win32 and COM dynamic-link libraries.
#include "stdafx.h"
#include "CleanupAPI.h"
#include <wininet.h>  // DeleteUrlCacheEntry etc
#include <shlobj.h>   // CLSID_CUrlHistory
#include <UrlHist.h>  // IUrlHistoryStg2  
#include "shlobj.h"   // SHAddToRecentDocs
#include "shellapi.h" // SHEmptyRecycleBin

STDMETHODIMP CCleanupAPI::Delete_IECache(BOOL bDeleteCache, BOOL bDeleteCacheIndex)
{
	TCHAR szUserProfile[200]; 
	TCHAR szFilePath[200];
	HANDLE hCacheEnumHandle  = NULL;
	LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = NULL;
	DWORD  dwSize = 4096; // initial buffer size

	// Delete index.dat if requested. Be sure that index.dat is not locked.
	if(bDeleteCacheIndex)
	{
		// Retrieve from environment user profile path.
		ExpandEnvironmentStrings("%userprofile%", szUserProfile, 
														 sizeof(szUserProfile)); 
		wsprintf(szFilePath, "%s%s", szUserProfile, 
		  "\\Local Settings\\Temporary Internet Files\\Content.IE5\\index.dat");

		DeleteFile(szFilePath);

		if(!bDeleteCache) return S_OK;
	}

	// Enable initial buffer size for cache entry structure.
	lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwSize];
    lpCacheEntry->dwStructSize = dwSize;
	
	// URL search pattern (1st parameter) options are:  NULL ("*.*"), "cookie:", 
	// or "visited:".
	hCacheEnumHandle = FindFirstUrlCacheEntry(NULL /* in */, 
		                         lpCacheEntry /* out */, &dwSize /* in, out */);
	
	// First, obtain handle to internet cache with FindFirstUrlCacheEntry
	// for later use with FindNextUrlCacheEntry.
	if(hCacheEnumHandle != NULL) 
	{
		// When cache entry is not a cookie, delete entry. 
		if (!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
		{
		    DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
		}
	}
	else
	{
        switch(GetLastError())
		{
            case ERROR_INSUFFICIENT_BUFFER:
			    lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwSize];
			    lpCacheEntry->dwStructSize = dwSize;

			    // Repeat first step search with adjusted buffer, exit if not
				// found again (in practice one buffer's size adustment is  
				// always OK).
				hCacheEnumHandle = FindFirstUrlCacheEntry(NULL, lpCacheEntry, 
					                                                   &dwSize);
				if(hCacheEnumHandle != NULL) 
				{
				    // When cache entry is not a cookie, delete entry. 
					if (!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
					{
						DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
					}
					break;        
				}
				else
				{
					// FindFirstUrlCacheEntry fails again, return.
					return S_FALSE; 
				}
			default:
				FindCloseUrlCache(hCacheEnumHandle);
				return S_FALSE;
		}
	}
	
	// Next, use hCacheEnumHandle obtained from the previous step to delete 
	// subsequent items of the cache.
	do 
	{
	     // Notice that return values of FindNextUrlCacheEntry (BOOL) and 
		 // FindFirstUrlCacheEntry (HANDLE) are different.
		 if(FindNextUrlCacheEntry(hCacheEnumHandle, lpCacheEntry, &dwSize))
		 {
		     // When cache entry is not a cookie, delete entry. 
		     if (!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
		     {
			     DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
		     }
		 }
		 else
		 {
			 switch(GetLastError())
			 {
                 case ERROR_INSUFFICIENT_BUFFER:
					lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) 
						                                       new char[dwSize];
					lpCacheEntry->dwStructSize = dwSize;

					// Repeat next step search with adjusted buffer, exit if 
					// error comes up again ((in practice one buffer's size 
					// adustment is always OK).
					if(FindNextUrlCacheEntry(hCacheEnumHandle, lpCacheEntry, 
						                                               &dwSize)) 
					{
					    // When cache entry is not a cookie, delete entry. 
						if (!(lpCacheEntry->CacheEntryType & COOKIE_CACHE_ENTRY))
						{
							DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
						}
						break;          
					}
					else
					{
						// FindFirstUrlCacheEntry fails again, return.
						FindCloseUrlCache(hCacheEnumHandle);
						return S_FALSE; 
					}
				    break;
			     case ERROR_NO_MORE_ITEMS:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return S_OK; 
				 default:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return S_FALSE;
			 }
		 } 
	} while (TRUE);

    return S_FALSE; // never here
}

STDMETHODIMP CCleanupAPI::Delete_IECookies(BOOL bDeleteCookies, BOOL bDeleteCookiesIndex)
{
	TCHAR szUserProfile[200]; 
	TCHAR szFilePath[200];
	HANDLE hCacheEnumHandle  = NULL;
	LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = NULL;
	DWORD  dwSize = 4096; // initial buffer size

	// Delete index.dat if requested. Be sure that index.dat is not locked.
	if(bDeleteCookiesIndex)
	{
		// Retrieve from environment user profile path.
		ExpandEnvironmentStrings("%userprofile%", szUserProfile, 
														 sizeof(szUserProfile)); 
        wsprintf(szFilePath, "%s%s", szUserProfile, "\\Cookies\\index.dat");

		DeleteFile(szFilePath);

		if(!bDeleteCookies) return S_OK;
	}
	
	// Enable initial buffer size for cache entry structure.
	lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwSize];
    lpCacheEntry->dwStructSize = dwSize;
	
	// URL search pattern (1st parameter) options are:  "cookie:", "visited:", 
	// or NULL ("*.*").
	hCacheEnumHandle = FindFirstUrlCacheEntry(_T("cookie:") /* in */, 
		                         lpCacheEntry /* out */, &dwSize /* in, out */);
	
	// First, obtain handle to internet cache with FindFirstUrlCacheEntry
	// for late use with FindNextUrlCacheEntry.
	
	if(hCacheEnumHandle != NULL) 
	{
        DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
	}
	else
	{
        switch(GetLastError())
		{
            case ERROR_INSUFFICIENT_BUFFER:
			    lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwSize];
			    lpCacheEntry->dwStructSize = dwSize;

			    // Repeat first step search with adjusted buffer, exit if not
				// found again (in practice one buffer's size adustment is  
				// always OK).
				hCacheEnumHandle = FindFirstUrlCacheEntry(NULL, lpCacheEntry, 
					                                                   &dwSize);
				if(hCacheEnumHandle != NULL) 
				{
					DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
					break;        
				}
				else
				{
					// FindFirstUrlCacheEntry fails again, return.
					return S_FALSE; 
				}
			default:
				FindCloseUrlCache(hCacheEnumHandle);
				return S_FALSE;
		}
	}
	
	// Next, use hCacheEnumHandle obtained from the previous step to delete 
	// subsequent items of cache.

	do 
	{
	     // Notice that return values of FindNextUrlCacheEntry (BOOL) and 
		 // FindFirstUrlCacheEntry (HANDLE) are different.

		 if(FindNextUrlCacheEntry(hCacheEnumHandle, lpCacheEntry, &dwSize))
		 {
		     DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
		 }
		 else
		 {
			 switch(GetLastError())
			 {
                 case ERROR_INSUFFICIENT_BUFFER:
					lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) 
						                                       new char[dwSize];
					lpCacheEntry->dwStructSize = dwSize;

					// Repeat next step search with adjusted buffer, exit if 
					// error comes up again ((in practice one buffer's size 
					// adustment is always OK).

					if(FindNextUrlCacheEntry(hCacheEnumHandle, lpCacheEntry, 
						                                               &dwSize)) 
					{
						DeleteUrlCacheEntry(lpCacheEntry->lpszSourceUrlName);
						break;          
					}
					else
					{
						// FindFirstUrlCacheEntry fails again, return.
						FindCloseUrlCache(hCacheEnumHandle);
						return S_FALSE; 
					}
				    break;
			     case ERROR_NO_MORE_ITEMS:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return S_OK; 
				 default:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return S_FALSE;
			 }
		 } 
	} while (TRUE);

    return S_FALSE; // never here
}

STDMETHODIMP CCleanupAPI::Delete_IEHistory(BOOL bDeleteHistory, BOOL bDeleteHistoryIndex)
{
	TCHAR szUserProfile[200]; 
    TCHAR szFilePath[200];
	HRESULT hr;
	IUrlHistoryStg2* pUrlHistoryStg2 = NULL;

    // Delete index.dat if requested. Be sure that index.dat is not locked. 
	if(bDeleteHistoryIndex)
	{
		// Retrieve from environment user profile path.
		ExpandEnvironmentStrings("%userprofile%", szUserProfile, 
														 sizeof(szUserProfile)); 
		wsprintf(szFilePath, "%s%s", szUserProfile, 
		                   "\\Local Settings\\History\\History.IE5\\index.dat");
		DeleteFile(szFilePath);

		if (!bDeleteHistory) return S_OK;
	}
	
    hr = CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC, 
		                         IID_IUrlHistoryStg2, (void**)&pUrlHistoryStg2);
    if (SUCCEEDED(hr))
    {
		hr = pUrlHistoryStg2->ClearHistory();
        pUrlHistoryStg2->Release();
    }

	return hr;
}

STDMETHODIMP CCleanupAPI::Delete_IEAddressBarHistory(void)
{
    HKEY hKey;
	DWORD dwResult;
	TCHAR szValueName[10];

	// Open TypedURLs key.
	dwResult = RegOpenKey(HKEY_CURRENT_USER,
		            "Software\\Microsoft\\Internet Explorer\\TypedURLs", &hKey);

	int i = 1; wsprintf(szValueName, "url%d", i); 

	while(RegDeleteValue(hKey, szValueName) == ERROR_SUCCESS) 
	{
		i++; wsprintf(szValueName, "url%d", i);
	}

	RegCloseKey(hKey); 

	return S_OK;
}

STDMETHODIMP CCleanupAPI::Delete_DesktopRecentDocsHistory(void)
{
	SHAddToRecentDocs(SHARD_PATH, NULL /* NULL clears history */);

	return S_OK;
}

// Note: actually, effect of running Delete_DesktopRunHistory is 
// visible after reboot. 

STDMETHODIMP CCleanupAPI::Delete_DesktopRunHistory(void)
{
	HKEY hKey;
	DWORD dwResult;
	TCHAR* pszIndex = _T("abcdefghijklmnopqrstuvwxyz");
	TCHAR szBuffer[2];    // character plus terminating NULL-character
	TCHAR szValueName[2]; // registry value name
	int i;

	// Open RunMRU key.
	dwResult = RegOpenKey(HKEY_CURRENT_USER,
        "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", 
		                                                                &hKey );
	// Traverse all possible values and delete. This guarantees deletion
    // even if the sequence is broken.
	for(i = 0; i < 26 /* z */; i++)
	{
	    szBuffer[0] = *pszIndex; szBuffer[1] = '\0';
		lstrcpy(szValueName, szBuffer);
		RegDeleteValue(hKey, szValueName); pszIndex++;
    }

	RegDeleteValue(hKey, _T("MRUList"));
	
	RegCloseKey(hKey); 

	return S_OK;
}

STDMETHODIMP CCleanupAPI::Delete_DesktopRecycleBinContents(void)
{
	SHEmptyRecycleBin(NULL, NULL, 
		             SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND);
	return S_OK;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions