You are here

Keep Your Registry Clean

11 posts / 0 new
Last post
lamer
Offline
Last seen: 3 years 3 months ago
Joined: 2007-08-02 07:01
Keep Your Registry Clean

Hi!
This is the First Commandment of portable software, isn't it? Well, may be Second. But any way, at the top of Ten Commandments.
While testing some apps on BetaTesting forum (and my own one, nobody is absolute :)), I noticed that many of them left traces in registry, in very common places like OpenWithList, MRUCache and so on. As for me, I just forgot to call the cleaning procedure after adding some new features to my app.
So I had to write a couple of function to keep the registry clean after program's exit and thought they might be helpful for somebody else. They will just clean the most common places from any record of your program. Here you are:


//I just did not succeed to insert angle brackets for include, 
//because of HTML, not because I'm geek :).

#include windows.h
#include shlwapi.h

//***********    cleans Software\Microsoft\Windows\ShellNoRoam\MUICache    ***********
void CleanRegMUICache(const char * lpcProgName){

	HKEY		hKey;			//main key
	LONG		result;			//result
	DWORD		index = 0;		//index
	DWORD 		cb = 512;		//buffer size
	char		szValue[512];	//buffer

	//open main key
	result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache", 0, KEY_ALL_ACCESS, &hKey);
	if(result == ERROR_SUCCESS){
		//loop through values
		result = RegEnumValue(hKey, index, szValue, &cb, NULL, NULL, NULL, NULL);
		while(result == ERROR_SUCCESS){
			//if there is our program name in value name - delete this value
			if(strstr(szValue, lpcProgName)){
				RegDeleteValue(hKey, szValue);
				break;
			}
			//increase index
			index++;
			//reset size, since it has been changed in previous function call
			cb = 512;
			//loop
			result = RegEnumValue(hKey, index, szValue, &cb, NULL, NULL, NULL, NULL);
		}
		//close main key
		RegCloseKey(hKey);
	}
}

//***********    cleans Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU    **********
void CleanRegMRU(const char * lpcProgName){
	HKEY		hKey;						//main key
	LONG		result;						//result
	DWORD		index = 0;					//index
	DWORD		cb = 512, cbValue = 512;	//buffers sizes
	char		szValue[512];				//buffer
	char		szBuffer[512];				//buffer

	//open main key
	result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", 0, KEY_ALL_ACCESS, &hKey);
	if(result == ERROR_SUCCESS){
		//loop through values
		result = RegEnumValue(hKey, index, szValue, &cb, NULL, NULL, NULL, NULL);
		while(result == ERROR_SUCCESS){
			//increase index
			index++;
			//get value's data
			if(RegQueryValueEx(hKey, szValue, NULL, NULL, szBuffer, &cbValue) == ERROR_SUCCESS){
				if(strstr(szBuffer, lpcProgName)){
					//if value's data contains our program name - delete this value
					RegDeleteValue(hKey, szValue);
					//return index back
					index--;
				}
			}
			//reset sizes, since they are changed in previous functions calls
			cbValue = 512;
			cb = 512;
			//loop
			result = RegEnumValue(hKey, index, szValue, &cb, NULL, NULL, NULL, NULL);
		}
		//close main key
		RegCloseKey(hKey);
	}
}

//***********    cleans Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts    ***********
void CleanRegOpenWithList(const char * lpcProgName){

	HKEY		hKey;								//main key
	HKEY		hKeyExt;							//extention key
	HKEY		hKeyOpen;							//extension subkey
	LONG		result, resultExt, resultOpen;		//results
	DWORD		index = 0, indexExt, indexOpen;		//indexes
	DWORD		cb = 512, cbO = 512; 				//buffers sizes
	DWORD		cbValueExt = 512, cbValueOpen;		//buffers sizes
	char		szValue[512], szValueExt[512];		//buffers
	char		szValueOpen[512], szBuffer[512];	//buffers

	//open FileExts key
	result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts", 0, KEY_ALL_ACCESS, &hKey);
	if(result == ERROR_SUCCESS){
		//check each extension
		result = RegEnumKeyEx(hKey, index, szValue, &cb, NULL, NULL, NULL, NULL);
		while(result == ERROR_SUCCESS){
			//open extension key
			if(RegOpenKeyEx(hKey, szValue, 0, KEY_ALL_ACCESS, &hKeyExt) == ERROR_SUCCESS){
				indexExt = 0;
				//check each subkey of extension; usually includes OpenWithList and/or OpenWithProgids
				resultExt = RegEnumKeyEx(hKeyExt, indexExt, szValueExt, &cbValueExt, NULL, NULL, NULL, NULL);
				while(resultExt == ERROR_SUCCESS){
					//increase index
					indexExt++;
					//open each subkey
					if(RegOpenKeyEx(hKeyExt, szValueExt, 0, KEY_ALL_ACCESS, &hKeyOpen) == ERROR_SUCCESS){
						indexOpen = 0;
						//check all subkey values
						resultOpen = RegEnumValue(hKeyOpen, indexOpen, szValueOpen, &cbValueOpen, NULL, NULL, NULL, NULL);
						while(resultOpen == ERROR_SUCCESS){
							//increase index
							indexOpen++;
							//get value's data
							if(RegQueryValueEx(hKeyOpen, szValueOpen, NULL, NULL, szBuffer, &cbO) == ERROR_SUCCESS){
								if(strstr(szBuffer, lpcProgName)){
									//if there is our program name in value's data - delete this value
									RegDeleteValue(hKeyOpen, szValueOpen);
									//empty buffer
									szBuffer[0] = '\0';
									//return index one position back, in order not to miss the next value
									indexOpen--;
								}
							}
							//restore default sizes, since they are changed in previous functions calls
							cbO = 512;
							cbValueOpen = 512;
							//loop
							resultOpen = RegEnumValue(hKeyOpen, indexOpen, szValueOpen, &cbValueOpen, NULL, NULL, NULL, NULL);
						}
						//close subkey
						RegCloseKey(hKeyOpen);
					}
					//restore default size, since it is changed in previous functions calls
					cbValueExt = 512;
					//loop
					resultExt = RegEnumKeyEx(hKeyExt, indexExt, szValueExt, &cbValueExt, NULL, NULL, NULL, NULL);
				}
				//close extension subkey
				RegCloseKey(hKeyExt);
			}
			//increase index
			index++;
			//restore default size, since it is changed in previous functions calls
			cb = 512;
			//loop
			result = RegEnumKeyEx(hKey, index, szValue, &cb, NULL, NULL, NULL, NULL);
		}
		//close main key
		RegCloseKey(hKey);
	}
}

//*********** cleans    Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSaveMRU    ***********
void CleanRegOpenSaveMRU(const char * lpcProgName){
	
	HKEY		hKey;							//main key
	HKEY		hKeyExt;						//extention key
	LONG		result, resultExt;				//results
	DWORD		index = 0, indexExt = 0;		//indexes
	DWORD		cb = 512, cbO = 512; 			//buffers sizes
	DWORD		cbValueExt = 512;				//buffers sizes
	char		szValue[512], szValueExt[512];	//buffers
	char		szBuffer[512];					//buffers

	//open ComDlg32\OpenSaveMRU key
	result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSaveMRU", 0, KEY_ALL_ACCESS, &hKey);
	if(result == ERROR_SUCCESS){
		//check each extension
		resultExt = RegEnumKeyEx(hKey, indexExt, szValueExt, &cbValueExt, NULL, NULL, NULL, NULL);
		while(resultExt == ERROR_SUCCESS){
			//open extension key
			if(RegOpenKeyEx(hKey, szValueExt, 0, KEY_ALL_ACCESS, &hKeyExt) == ERROR_SUCCESS){
				index = 0;
				//loop through each subkey
				result = RegEnumValue(hKeyExt, index, szValue, &cb, NULL, NULL, NULL, NULL);
				while(result == ERROR_SUCCESS){
					//increase index
					index++;
					//get value's data
					if(RegQueryValueEx(hKeyExt, szValue, NULL, NULL, szBuffer, &cbO) == ERROR_SUCCESS){
						if(strstr(szBuffer, lpcProgName)){
							//if there is our program name in value's data - delete this value
							RegDeleteValue(hKeyExt, szValue);
							//empty buffer
							szBuffer[0] = '\0';
							//return index one position back, in order not to miss the next value
							index--;
						}
					}
					//restore default sizes, since they are changed in previous functions calls
					cbO = 512;
					cb = 512;
					//loop
					result = RegEnumValue(hKeyExt, index, szValue, &cb, NULL, NULL, NULL, NULL);
				}
				//close extension subkey
				RegCloseKey(hKeyExt);
			}
			//increase index
			indexExt++;
			//restore default size, since it is changed in previous functions calls
			cbValueExt = 512;
			//loop
			resultExt = RegEnumKeyEx(hKey, indexExt, szValueExt, &cbValueExt, NULL, NULL, NULL, NULL);
		}
		//close main key
		RegCloseKey(hKey);
	}
}

Ryan McCue
Ryan McCue's picture
Offline
Last seen: 14 years 6 months ago
Joined: 2006-01-06 21:27
.

Well, we could do it ourselves, but it's a lot less trouble to not do it Smile

That said, I'll compile this into a DLL so you can use it in NSIS if anyone wants.
----
Ryan McCue.
Blog.
So all that Airbus-delay trouble over here in Europe is because of YOU!
Simeon.

"If you're not part of the solution, you're part of the precipitate."

lamer
Offline
Last seen: 3 years 3 months ago
Joined: 2007-08-02 07:01
That's exactly was a

That's exactly was a suggestion, not to show how smart I am and what a pretty code can I write Smile Just cannot come and say to others - I have the perfect DLL, get it and use it Smile They will wonder in source and will be right...

SamK
Offline
Last seen: 14 years 7 months ago
Joined: 2007-07-06 07:04
Just Curious

I'm not a programmer - and therefore might be asking a question that is obvious to those who are.
Why is this cleaning/removal not used as standard practice at PA.com? I understand that it is
acting on non-critical areas of the registry. If it is simple to implement is it not preferable/polite
to leave a guest PC in the same condition it was found in?

Ryan McCue
Ryan McCue's picture
Offline
Last seen: 14 years 6 months ago
Joined: 2006-01-06 21:27
Because

It may have non-standard effects on non-XP systems or locked down systems. Plus, there is the chance of corruption and some programs may use information from there.
----
Ryan McCue.
Blog.
So all that Airbus-delay trouble over here in Europe is because of YOU!
Simeon.

"If you're not part of the solution, you're part of the precipitate."

SamK
Offline
Last seen: 14 years 7 months ago
Joined: 2007-07-06 07:04
Further Curiosity

Bearing in mind my lack of programming knowledge some quick follow-up questions.

"...locked down systems."

  • Would a locked down system allow the creation of such registry changes?
  • If so would it allow the changes back to the original condition?

"...there is the chance of corruption..."

  • What gives rise to this possible corruption?
  • Is it any more likely than normal read/write activity?
  • Is this risk mitigated at all by the non-critical nature of the data?

"...some programs may use information from there."
Not quite sure I understand this fully.

  • If the entries being removed are those created by a specific application
    is it likely other programs will depend on them?
Ryan McCue
Ryan McCue's picture
Offline
Last seen: 14 years 6 months ago
Joined: 2006-01-06 21:27
.
  1. Yes, because it's controlled by the OS. And no, since it's a program doing it
  2. Anything editing the registry can possibly corrupt something. It could also delete something accidentally.
  3. Yeh, I didn't read it properly. Oops Biggrin

----
Ryan McCue.
Blog.
So all that Airbus-delay trouble over here in Europe is because of YOU!
Simeon.

"If you're not part of the solution, you're part of the precipitate."

SamK
Offline
Last seen: 14 years 7 months ago
Joined: 2007-07-06 07:04
Really Curious

"And no, since it's a program doing it"
Is this program dependent in some way? I have just created a test user with restricted (non-administrative) privileges.
Running RegSeeker under this account I was able to delete registry entries.
Is this not similar to the cleaning/removal mentioned above?

yurzub
Offline
Last seen: 15 years 8 months ago
Joined: 2007-06-04 12:21
System reg entries, or user

System reg entries, or user reg entries? Every user has a registry storing their settings, and they have full access to that registry. but the mchine/system has its own registry portions, that can't be modified without admin access.

SamK
Offline
Last seen: 14 years 7 months ago
Joined: 2007-07-06 07:04
Removed These

Using RegSeeker under the restricted account I was able to remove keys from 4 of the 5 root branches as shown below.
RegSeeker does not search HK_CURRENT_CONFIG

HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Windows XP Service Pack
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\OptimalLayout
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\UPnP Device Host\HTTP Server\VROOTS\/upnphost
HKEY_CURRENT_USER\Software\Intel
HKEY_CLASSES_ROOT\.1

Many others were also removed the list is simply representative.

TaffinFoxcroft
TaffinFoxcroft's picture
Offline
Last seen: 10 years 4 months ago
Developer
Joined: 2006-12-14 17:24
clap, clap, clap. nice job!

clap, clap, clap. nice job!

But there’s no sense crying over every mistake,
You just keep on trying till you run out of cake.

Log in or register to post comments