Reading the registry problem

Hello, I am trying to read strings from the registry and compare them to a list of words.I also want it to be done randomly, so this is something I want to keep.
INSTALLKEY is a struct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HKEY hKey = INSTALLKEY.hKey;
	std::string regpath = INSTALLKEY.regpath;
	char buffer[50];
	char size = sizeof(buffer);
	std::string bufferString;
	DWORD regOpen;
	regOpen = RegOpenKeyEx(hKey,(regpath).c_str(),0,KEY_ALL_ACCESS,&hKey);
	if(regOpen == ERROR_SUCCESS)
		printf("good job\n"); else printf("problem\n");
	do {
		int randomNumber = rand()%(INSTALLKEY.number-1);
		RegEnumValue(hKey,randomNumber,(LPTSTR)buffer,(LPDWORD)&size,NULL,NULL,NULL,NULL);
		bufferString = buffer;
		printf("%s\n",buffer);
		system("PAUSE");
	}
	while((bufferString.find("TheNameofMyApp") == -1) && (buffer.String.find("SecondNameofMyApp") == -1));


This does not work and it always print "problem" to the screen. the registry path exists so this is not the problem. I am using Win7 64bit.
Thank you very much
Last edited on
Your call to RegOpenKeyEx() is wrong, first parameter MUST be a valid handle returned by the RegCreateKeyEx or RegOpenKeyEx function, or it can be one of the following predefined keys:
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS.
hello modoran, thank you for answering. here is the way I have defined my struct and the rest of the code:

1
2
3
4
5
6
7
8
9
10

std::string regpath32 = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\";

struct registryTest {
	HKEY hKey;
	std::string regpath;
	int number;
};

registryTest INSTALLKEY = {HKEY_LOCAL_MACHINE, regpath32};


then, some code to initialize INSTALLKEY.number....Can you please explain to me what is wrong?? Since I am declaring a new struct variable as {HKEY_LOCAL_MACHINE, regpath32}.
Now I see that you are using win 7 x64.
Is this application 64-bit native ?
Do you run it as administrator ? This is needed if you want write access in HKEY_LOCAL_MACHINE on windows vista or later. Use KEY_READ flag if you don't need write access instead of KEY_ALL_ACCESS flag.
See also what GetLastError() returns.
Hello, Thank you for answering me.
Honestly I am very new to c++ and programming so i might be mistaken, but I think it is not 64-bit native since the executable runs on my win xp machine. However, I have the same problem using win xp. I will read about GetLastError() on msdn and try. Also, KEY_READ instead of KEY_ALL_ACCESS gives the same error
Last edited on
Here is some more info incase it helps solve the problem. To initialize INSTALLKEY.number, I have written a function that finds the number of entries in a given registry path. It works without problems. Here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void findNumberEntries(registryTest &INSTALLKEY) {

	char buffer[50];
	char size = sizeof(buffer);
	int index = 0;

	if(RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)(INSTALLKEY.regpath.c_str()),0,KEY_ALL_ACCESS,&INSTALLKEY.hKey) == ERROR_SUCCESS) {		

		DWORD readEntry;

		do {
			readEntry = RegEnumValue(INSTALLKEY.hKey,index,(LPTSTR)buffer,(LPDWORD)&size,NULL,NULL,NULL,NULL);
			index++;
		}
		while(readEntry != ERROR_NO_MORE_ITEMS);
	}
	INSTALLKEY.number = index;
	RegCloseKey(INSTALLKEY.hKey);
}


Then, to initialize INSTALLKEY.number, I just do this:
findNumberEntries(INSTALLKEY)

And then I carry on with the code I have written on the first post. I don't understand why it works when I open it the first time to count the entries, but not the second time.
fishingspree2 wrote:
Honestly I am very new to c++ and programming

How new are you with playing with the registry? Do you know the damage that could potentially be done if you corrupt the right key? Do you know how to fix that damage?

Have you verified that your target key exists?

Also MSDN says to use "FormatMessage()" to get errors from this one. I just verified on my system that "GetLastErorr()" returns 0 because the operation DID complete, but the problem is that the data is invalid.
Hello, thank you for answering me. I am new to programming but not to computers. I will try reading on msdn about these commands.
Alright, I have implemented GetLastError and the error I get is: "There are no more files.". Could this be related to my function that counts the number of entries in a registry path?
The "GetLastError()" function returns a status flag that is used by more then a hundred different functions, so it's important to note where you have this coming from.
Hmm Im not sure if it is correct, but I use GetLastError and FormatMessge like this:
1
2
3
4
5
6
7
8
9
10
if(RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)(INSTALLKEY.regpath.c_str()),0,KEY_ALL_ACCESS,&INSTALLKEY.hKey) == ERROR_SUCCESS) {
...some code...
}
else {
LPVOID message; 
		GetLastError();
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL, GetLastError(), NULL,(LPTSTR) &message, 0, NULL );
		MessageBox(NULL,(LPCTSTR)message,"ERROR",MB_OK|MB_ICONINFORMATION);
}
Last edited on
And... What does it say?
Hello, thank you for answering me. It says "There are no more files."
Summary of the problem:
This function finds the number of entries in a registry path. It works perfectly, I have tested it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void findNumberEntries(registryTest &INSTALLKEY) {

	char buffer[50];
	char size = sizeof(buffer);
	int index = 0;

	if(RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)(INSTALLKEY.regpath.c_str()),0,KEY_ALL_ACCESS,&INSTALLKEY.hKey) == ERROR_SUCCESS) {		

		DWORD readEntry;

		do {
			readEntry = RegEnumValue(INSTALLKEY.hKey,index,(LPTSTR)buffer,(LPDWORD)&size,NULL,NULL,NULL,NULL);
			index++;
		}
		while(readEntry != ERROR_NO_MORE_ITEMS);
	}
	INSTALLKEY.number = index;
	RegCloseKey(INSTALLKEY.hKey);
}


now, the main function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
std::string regpath32 = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\";

struct registryTest {
	HKEY hKey;
	std::string regpath;
	int number;
};

registryTest INSTALLKEY = {HKEY_LOCAL_MACHINE, regpath32};
findNumberEntries(INSTALLKEY);
printf("%d\n",INSTALLKEY.number);
system("PAUSE");
//until here everything works as it should

HKEY hKey = INSTALLKEY.hKey;
std::string regpath = INSTALLKEY.regpath;
char buffer[50];
char size = sizeof(buffer);
std::string bufferString;
DWORD regOpen = RegOpenKeyEx(INSTALLKEY.hKey,(LPTSTR)INSTALLKEY.regpath.c_str(),0,KEY_READ,&INSTALLKEY.hKey);
	if(regOpen == ERROR_SUCCESS) //this is the part that fails.
	{
		printf("Registry Key was successfully opened\n");
	}
	else
	{
		printf("Unable to open registry key\n");
		LPVOID message; 
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL, GetLastError(), NULL,(LPTSTR) &message, 0, NULL );
		MessageBox(NULL,(LPCTSTR)message,"ERROR",MB_OK|MB_ICONINFORMATION);
	}

...rest of the code


On runtime, I get the correct number of entries. The problem is the part that tries to open the registry path again to read the entry names. I get "There are no more files" error.
Last edited on
I think the problem is that you are trying to open them twice without closing the handles. Generally Windows does not like this.
Hmm maybe, but look at the end of findNumberEntries(), i use RegCloseKey(INSTALLKEY.hKey);. Am i using it wrong?
Following code works for me, it is in VS documentation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <windows.h>
#include <cstdlib>
#include <cstdio>

//int curl_progress_callback(double )
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383

void QueryKey(HKEY hKey) 
	{ 
	TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
	DWORD    cbName;                   // size of name string 
	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 subkeys, until RegEnumKeyEx fails.

	if (cSubKeys)
		{
		printf( "\nNumber of subkeys: %d\n", cSubKeys);

		for (i=0; i<cSubKeys; i++) 
			{ 
			cbName = MAX_KEY_LENGTH;
			retCode = RegEnumKeyEx(hKey, i,
				achKey, 
				&cbName, 
				NULL, 
				NULL, 
				NULL, 
				&ftLastWriteTime); 
			if (retCode == ERROR_SUCCESS) 
				{
				_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
				}
			}
		} 

	// Enumerate the key values. 

	if (cValues) 
		{
		printf( "\nNumber of values: %d\n", 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 ) 
				{ 
				_tprintf(TEXT("(%d) %s\n"), i+1, achValue); 
				} 
			}
		}
	}


int _tmain(int argc, _TCHAR* argv[])
{
HKEY hKey;
LONG dwRegOPenKey = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\"), 0, KEY_READ, &hKey);
if(dwRegOPenKey == ERROR_SUCCESS){
	printf("RegOpenKeyEx succeeded, error code %d\n", GetLastError());
	QueryKey(hKey);

	} else {
		printf("RegOpenKeyEx failed, error code %d\n", dwRegOPenKey);
	}
	RegCloseKey(hKey);
return 0;
}
I don't actually think it matters but technically "RegOpenKeyEx()" returns a Long.

This is a trickey one, try running it like this though:
Line 20:
 
LONG regOpen = RegOpenKeyEx(INSTALLKEY.hKey, &INSTALLKEY.regpath[0], 0, KEY_READm &INSTALL.hKey);
Topic archived. No new replies allowed.