RegEnumValue not reading all values in Registry.

harsha_james
harsha_james used Ask the Experts™
on
Hi,
I have first called RegSetValueEx() function to write a value to a registry key. The  HKEY was opened using KEY_SET_VALUE access right.
Now, I try to enumerate all values from this registry key using RegEnumValue() function. The HKEY for this was opened with KEY_QUERY_VALUE access right.
But I saw that all values except the one I added using RegSetValueEx(), are read.
I've attached the call to RegEnumValue();

Here, 'achValue' gets  all values right, but when it reaches the value written using RegSetValueEx(), it just gets an empty string.

Can anyone explain why this happens?

Warm regards,
hj
for (i=0, retCode=ERROR_SUCCESS; i < cValues; i++) 
{ 
cchValue = MAX_VALUE_NAME; 
achValue[0] = '\0'; 
retCode = RegEnumValue(hkey, i, 
		achValue, 
		&cchValue, 
		NULL, 
		NULL,
		NULL,
		NULL);
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
fridomCEO/Programmer

Commented:
Your code ist completely uncomplete. One can not compile it and one does not even have an idea
what hkey is. So I bet that there have been somethin you've forgotten. If you do not care to send the complete code example which shows what you mean, you hardly can expect a somehat more decent answer.
Commented:
I attached a console app that reads values in Run (same RegEnumValue). Compare with your code.
 

#include <Windows.h>
#include <wchar.h>
 
static const LPCWSTR s_szRunOnce = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
 
int main()
{
	HKEY hKey = NULL;
	LONG nRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, s_szRunOnce, 
		0, KEY_QUERY_VALUE, &hKey);
 
	if (hKey == NULL)
		return 0;
 
	DWORD nCnt = 0;
	nRet = ERROR_SUCCESS;
	DWORD nValueLength = MAX_PATH;
	WCHAR szValue[MAX_PATH] = { 0 };
	DWORD nSize = 0;
	do 
	{
		nValueLength = MAX_PATH;
		nRet = RegEnumValue(hKey, nCnt, szValue, &nValueLength, 0, NULL, 
			NULL, &nSize);
 
		if (nRet == ERROR_SUCCESS)
			wprintf(L"%d. %s\n", nCnt, szValue);
 
		nCnt++;
	} while(nRet == ERROR_SUCCESS);
 
	RegCloseKey(hKey);
	return 0;
}

Open in new window

Author

Commented:
ok, here goes:
LONG Registry::set_Reg_Val(char *val)
{
	HKEY   hkey;
 
	//Open the registry Key
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE , TEXT("SOFTWARE\\ABC\\ONE\\COUNTRIES") , 0 , KEY_SET_VALUE , &hkey) ==
		ERROR_SUCCESS)
	{
		//Write the new value
		if(ERROR_SUCCESS != RegSetValueEx (hkey , val , 0 , REG_SZ , (BYTE *)"Y" , 2) )
		{
			return REGDB_E_INVALIDVALUE;
		}
		RegCloseKey(hkey);
	}
	else
	{
		return ERROR_CANTREAD;
	}
	return ERROR_SUCCESS;
}
 
LONG Registry::search_Reg_Val(char *Ini_val)
{
	HKEY   hkey;
	DWORD dwsize = 10;
	DWORD dwType = REG_SZ;
 
	if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE ,
		                     TEXT("SOFTWARE\\ABC\\ONE\\COUNTRIES") , 0 ,
		                     KEY_QUERY_VALUE , &hkey) )
	{
		TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
		DWORD    cchClassName = MAX_PATH;  // size of class string 
		DWORD    cSubKeys=0;               // number of subkeys 
		DWORD    cbMaxSubKey;              // longest subkey size 
		DWORD    cchMaxClass;              // longest class string 
		DWORD    cValues;              // number of values for key 
		DWORD    cchMaxValue;          // longest value name 
		DWORD    cbMaxValueData;       // longest value data 
		DWORD    cbSecurityDescriptor; // size of security descriptor 
		FILETIME ftLastWriteTime;      // last write time 
	 
		DWORD i, retCode; 
	  
		TCHAR  achValue[MAX_VALUE_NAME]; 
		DWORD cchValue = MAX_VALUE_NAME; 
	 
		// Get the class name and the value count. 
		retCode = RegQueryInfoKey(
			hkey,                    // key handle 
			achClass,                // buffer for class name 
			&cchClassName,           // size of class string 
			NULL,                    // reserved 
			&cSubKeys,               // number of subkeys 
			&cbMaxSubKey,            // longest subkey size 
			&cchMaxClass,            // longest class string 
			&cValues,                // number of values for this key 
			&cchMaxValue,            // longest value name 
			&cbMaxValueData,         // longest value data 
			&cbSecurityDescriptor,   // security descriptor 
			&ftLastWriteTime);       // last write time 
 
		    // Enumerate the key values. 
 
		if (cValues)
		{
			for (i=0, retCode=ERROR_SUCCESS; i < cValues; i++) 
			{ 
				cchValue = MAX_VALUE_NAME; 
				achValue[0] = '\0'; 
				retCode = RegEnumValue(hkey, i, 
					achValue, 
					&cchValue, 
					NULL, 
					NULL,
					NULL,
					NULL);
	 
				if (retCode == ERROR_SUCCESS ) 
				{ 
                                         if(!strcmp(achValue, Ini_val)
                                               //Do something
                                     }
}

Open in new window

Become a Certified Penetration Testing Engineer

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

Commented:
In order to test the code you posted, I made few very  small modifications. I attached the app. It works.
 
 

#include <Windows.h>
 
#define MAX_VALUE_NAME MAX_PATH
 
const TCHAR s_szSection[] = TEXT("SOFTWARE\\Whole Tomato");
 
LONG set_Reg_Val(char *val)
{
	HKEY   hkey;
 
	//Open the registry Key
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE , s_szSection , 0 , KEY_SET_VALUE , &hkey) ==
		ERROR_SUCCESS)
	{
		//Write the new value
		if(ERROR_SUCCESS != RegSetValueEx (hkey , val , 0 , REG_SZ , (BYTE *)"Y" , 2) )
		{
			return REGDB_E_INVALIDVALUE;
		}
		RegCloseKey(hkey);
	}
	else
	{
		return ERROR_CANTREAD;
	}
	return ERROR_SUCCESS;
}
 
LONG search_Reg_Val(char *Ini_val)
{
	HKEY   hkey;
	DWORD dwsize = 10;
	DWORD dwType = REG_SZ;
 
	if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE ,
		s_szSection , 0 ,
		KEY_QUERY_VALUE , &hkey) )
	{
		TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
		DWORD    cchClassName = MAX_PATH;  // size of class string 
		DWORD    cSubKeys=0;               // number of subkeys 
		DWORD    cbMaxSubKey;              // longest subkey size 
		DWORD    cchMaxClass;              // longest class string 
		DWORD    cValues;              // number of values for key 
		DWORD    cchMaxValue;          // longest value name 
		DWORD    cbMaxValueData;       // longest value data 
		DWORD    cbSecurityDescriptor; // size of security descriptor 
		FILETIME ftLastWriteTime;      // last write time 
 
		DWORD i, retCode; 
 
		TCHAR  achValue[MAX_VALUE_NAME]; 
		DWORD cchValue = MAX_VALUE_NAME; 
 
		// Get the class name and the value count. 
		retCode = RegQueryInfoKey(
			hkey,                    // key handle 
			achClass,                // buffer for class name 
			&cchClassName,           // size of class string 
			NULL,                    // reserved 
			&cSubKeys,               // number of subkeys 
			&cbMaxSubKey,            // longest subkey size 
			&cchMaxClass,            // longest class string 
			&cValues,                // number of values for this key 
			&cchMaxValue,            // longest value name 
			&cbMaxValueData,         // longest value data 
			&cbSecurityDescriptor,   // security descriptor 
			&ftLastWriteTime);       // last write time 
 
		// Enumerate the key values. 
 
		if (cValues)
		{
			for (i=0, retCode=ERROR_SUCCESS; i < cValues; i++) 
			{ 
				cchValue = MAX_VALUE_NAME; 
				achValue[0] = '\0'; 
				retCode = RegEnumValue(hkey, i, 
					achValue, 
					&cchValue, 
					NULL, 
					NULL,
					NULL,
					NULL);
 
				if (retCode == ERROR_SUCCESS ) 
				{ 
					if(!strcmp(achValue, Ini_val))
					{
						//Do something
						return i;
					}
				}
			}
		}
	}
	return 0;
}
 
int main()
{
	set_Reg_Val("hello");
	int nFound = search_Reg_Val("hello");
	return 0;
}

Open in new window

Author

Commented:
Hi pgnatyuk,
your code seems the same as mine, except for the function signatures, and your use of 'szSection'.
Am I right?

Did you first write a value using set_Reg_Val() and then try to pass the written value to search_Reg_Val() and see if it gets read from the registry?

If so, its strange that the same code doesn't work for me.

But I noticed something:
I first write the value using set_Reg_Val() (Lets call the value 'AB' ).
Then, I delete another value in the same registry key and write it back, both directly from the registry without using any APIs (Right click, delete; Right click, new string value).
Now, I try to read 'AB' using search_Reg_Val() and I see that RegEnumValue() reads 'AB' now.

I hope its clear.
So is it that some buffer needs to be flushed out after writing to the registry, or something like that?

Commented:
>> Am I right?
Yes. I understood so. If you will read your question now, you will understand the same.
Use RegFlushKey:
http://msdn.microsoft.com/en-us/library/ms724867(VS.85).aspx
and do not forget  RegCloseKey as I did it the last code I posted (there is return without RegCloseKey).

 

Commented:
Just like here:
RegSetValueEx(key, "Favorites", 0, type, originalPath, strlen(originalPath) + 1);
RegFlushKey(key);

Here is a wrapper:
http://www.codeproject.com/KB/system/CRegistry.aspx
 

Author

Commented:
Thanks for your suggestion, pgnatyuk. But RegFlushKey does not solve my problem.
I'll have a look at the wrapper, and let you know if anything clicks.
Commented:
If you delete/modify something in the registry, you may call RegFlushKey.
To be sure, you can add RegCloseKey and re-open the key.
I'm afraid you have a mistake/bug somewhere in the code.

Author

Commented:
Thanks a lot for your help, pgnatyuk. But the problem still exists.
Does anyone else have any suggestions?

Author

Commented:
My problem has been solved. I'm not sure how, though.

I moved the comparison part (strcmp(achValue, Ini_val)) to outside the search_Reg_Val() function, in main.
Now, RegEnumValue seems to be reading fine, although I didn't touch it!

Does someone understand what happened here?

Thanks for all your help.

regards,
hj

Commented:
ID:25660095 - this is the correct answer for the question, it contains a sample of RegEnumValue. As it was aksed.
ID:25660186 - it's a test of the code posted by the asker.
In comment ID:25660622, I said that there is a mistake in another place in the code.


Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial