Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A Cleanup API for Windows

, 24 Aug 2006
Provides a general cleanup API for Windows, ported into Win32 and COM dynamic-link libraries.
cleanup_api_code.zip
Cleanup_DLL_Win32
Release
Cleanup.dll
Cleanup_Win32.lib
Cleanup_Client_COM
Cleanup_COM.tlb
Release
Cleanup_Client_COM.exe
res
Cleanup_Client.ico
Cleanup_Client.manifest
Cleanup_Client_CS
App.ico
bin
Release
Cleanup_Client_CS.exe
Interop.Cleanup_COMLib.dll
Cleanup_Client_C3.csproj.user
Cleanup_Client_CS.csproj.user
Cleanup_Client_MFC
Cleanup_Win32.lib
Release
Cleanup.dll
Cleanup_Client_MFC.exe
res
Cleanup_Client.ico
Cleanup_Client.manifest
Cleanup_DLL_COM
Cleanup_COM.def
Cleanup_COM.rgs
Cleanup_COMps.def
CleanupAPI.rgs
Release
Cleanup.dll
Cleanup_COM.tlb
#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)

Share

About the Author

Marcel Lambert

United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 24 Aug 2006
Article Copyright 2006 by Marcel Lambert
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid