Click here to Skip to main content
15,896,606 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 230.1K   3.7K   84  
Provides a general cleanup API for Windows, ported into Win32 and COM dynamic-link libraries.
#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)


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