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 CPOL
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 "cleanup_interface.h"
#include <string>     // Delete_DesktopRunHistory()
#include <wininet.h>  // DeleteUrlCacheEntry etc
#include <UrlHist.h>  // IUrlHistoryStg2 
#include "shlobj.h"   // CLSID_CUrlHistory, SHAddToRecentDocs
#include "shellapi.h" // SHEmptyRecycleBin
#include "tchar.h"    // _T macro

using namespace std; 

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, 
                                                              LPVOID lpReserved)
{
    return TRUE;
}

__declspec( dllexport ) BOOL 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 TRUE;
	}

	// 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 FALSE; 
				}
			default:
				FindCloseUrlCache(hCacheEnumHandle);
				return 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 FALSE; 
					}
				    break;
			     case ERROR_NO_MORE_ITEMS:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return TRUE; 
				 default:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return FALSE;
			 }
		 } 
	} while (TRUE);

    return FALSE; // never here
}

__declspec( dllexport ) BOOL 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 TRUE;
	}
	
	// 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 FALSE; 
				}
			default:
				FindCloseUrlCache(hCacheEnumHandle);
				return 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 FALSE; 
					}
				    break;
			     case ERROR_NO_MORE_ITEMS:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return TRUE; 
				 default:
					 FindCloseUrlCache(hCacheEnumHandle);
					 return FALSE;
			 }
		 } 
	} while (TRUE);

    return FALSE; // never here
}

__declspec( dllexport ) HRESULT Delete_IEHistory(BOOL bDeleteHistory, 
											           BOOL bDeleteHistoryIndex)
{
	TCHAR szUserProfile[200]; 
    TCHAR szFilePath[200];
	HRESULT hr;

    // 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;
	}
	
	CoInitialize(NULL);

    IUrlHistoryStg2* pUrlHistoryStg2 = NULL;
    hr = CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC, 
		                         IID_IUrlHistoryStg2, (void**)&pUrlHistoryStg2);
    if (SUCCEEDED(hr))
    {
		hr = pUrlHistoryStg2->ClearHistory();
        pUrlHistoryStg2->Release();
    }
	CoUninitialize();

	return hr;
}

__declspec( dllexport ) void Delete_IEAddressBarHistory()
{
    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); 
}

__declspec( dllexport ) void Delete_DesktopRecentDocsHistory()
{
    SHAddToRecentDocs(SHARD_PATH, NULL /* NULL clears history */);
}

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

__declspec( dllexport ) void Delete_DesktopRunHistory()
{
	HKEY hKey;
	DWORD dwResult;
	TCHAR szValueName[10];
	string c, s;
	s = "abcdefghijklmnopqrstuvwxyz";
	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 in broken.
	for(i = 0; i < 26 /* z */; i++)
	{
		c = s.at(i); wsprintf(szValueName, "%s", c.c_str());
		RegDeleteValue(hKey, szValueName);
	}

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

	RegCloseKey(hKey); 
}

__declspec( dllexport ) void Delete_DesktopRecycleBinContents()
{
    SHEmptyRecycleBin(NULL, NULL, 
		             SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND);
}


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 | Terms of Use | Mobile
Web02 | 2.8.141216.1 | Last Updated 24 Aug 2006
Article Copyright 2006 by Marcel Lambert
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid