Read Registry only works in debug

hi im trying to read from the registry

it seems to work fine.
but as soon as i try to run my program from release this code dont seem to work
what its ment to do is read the folder under my programs name in the reg.
then read the string data in each folder

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
unordered_map< string, vector<string> > REG_TABLE;


HKEY hKey;
LONG dwRegOPenKey = RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\MyProgram", 0, KEY_READ, &hKey);
if(dwRegOPenKey == ERROR_SUCCESS)
{
	Output("RegOpenKeyEx succeeded, error code %d\n", GetLastError());
	QueryKey(hKey, "SOFTWARE\\MyProgram");
} else 
{
	Output("RegOpenKeyEx failed, error code %d\n", dwRegOPenKey);
}
RegCloseKey(hKey);



void QueryKey(HKEY hKey1, LPCSTR STR) 
{
	TCHAR    achKey[MAX_PATH];
	DWORD    cbName;
	TCHAR    achClass[MAX_PATH] = TEXT("");
	DWORD    cchClassName = MAX_PATH;
	DWORD    cSubKeys = NULL;
	DWORD    cbMaxSubKey;
	DWORD    cchMaxClass;
	DWORD    cValues;
	DWORD    cchMaxValue;
	DWORD    cbMaxValueData;
	DWORD    cbSecurityDescriptor;
	FILETIME ftLastWriteTime;

	RegQueryInfoKey( hKey1, achClass, &cchClassName, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, &cValues, &cchMaxValue, &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);

	if (cSubKeys)
	{
		for (DWORD dw = 0; dw < cSubKeys; dw++){
			cbName = MAX_PATH;
			while(RegEnumKeyEx(hKey1, dw, achKey, &cbName, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
			{
				Output("subkeys(%d) %s\n", dw+1, achKey);

				HKEY HKey2 = 0;
				char buf[MAX_PATH];
				DWORD dwBufSize = sizeof(buf);

				char* subKeyPath = new char[sizeof(STR) + cbName];
				sprintf(subKeyPath, "%s\\%s", STR, achKey);
				vector<string> key;
				if( RegOpenKey(HKEY_CURRENT_USER,subKeyPath,&HKey2) == ERROR_SUCCESS )
				{
					int i = 0;
					while( RegEnumValue(HKey2, i++, buf, &dwBufSize, 0, 0, 0, 0) == ERROR_SUCCESS )
					{
						dwBufSize = sizeof(buf);

						TCHAR value[MAX_PATH];
						DWORD value_length = sizeof(buf);
						if( RegQueryValueEx(HKey2, buf, NULL, NULL, (LPBYTE)&value, &value_length) == ERROR_SUCCESS ){
							Output("(%d) %s - %s\n", i, buf, value);
							key.push_back(value);
						}
					}
					RegCloseKey(HKey2);
				}
				REG_TABLE[achKey] = key;
			}
		}
	} 
}
Last edited on
closed account (G309216C)
Add this code becuase maybe we aquire Debug rights needed to simulate debug mode while running parrel (relase) mode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

int privileges(){
  HANDLE Token;
  TOKEN_PRIVILEGES tp;
  if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token))
  {
	LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
	tp.PrivilegeCount = 1;
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL)==0){
   		 return 1; //FAIL
		}else{
   		 return 0; //SUCCESS
		}
   }	  
   return 1;
}


A guess tell me if this works.
@poohpooh

You're using RegOpenKey rather than RegOpenKeyEx on line 50, which might be a problem. The old RegOpenKey function might be trying to open the key with KEY_ALL_ACCESS rather than the KEY_READ you require.

And I can see code to output the return code from RegOpenKeyEx. Is it failing? If so, with what error code?

If not, you should modify your code so you can get at the return codes from the other calls and find out what's going on there.

(Are you talking about the difference between the debug and release builds, or running under the debugger versus running your app normally?)

Andy

PS It would better to inititlize all the variables you're passing to RegQueryInfoKey, etc. (And you do know you can pass NULL for class name to RegQueryInfoKey if you don't want it, etc.)
Last edited on
hey thanks for the reply
i ended up changing it to RegOpenKeyEx
i havent been able to find any error codes as of yet

could this be anything to do with using 64 bit windows 8?

also what happens is that when i run my program in visual studio in (debug) an (release) with the F5 key the program runs fine how it should.
but when i open my program from the release folder it dont run like it should.
but it works fine when i run it from the debug folder

thats weird it sometimes works now but not offten

i set my solution Platform to x64 an it seems to work
what could be causing this?
Last edited on
thats weird it sometimes works now but not offten

If you're saying that the release build sometimes runs, but not always, that's pointing at something like an uninit variable problem.

The difference between the debug and release build is that the debug version of the Microsoft CRT fills new memory with a pattern to help with debugging, so uninit vars will actually be initialized to a known value. In the release build they just contain whatever random values were in that bit of memory.

Andy
I've just tried your code and it crashes in debug mode.

The reason it crashes because the buffer allocated on line 47 is too small.

char* subKeyPath = new char[sizeof(STR) + cbName];

It's using a size of sizeof(STR) + cbName where STR is an LPCSTR, i.e. a pointer. And sizeof() any pointer type is going to be 8 bytes (if compiled 64-bit) or 4 bytes (for 32-bit). Which is not enough space.

What you need is strlen(STR) (for the length of the string pointed to by STR) plus space for the \ and the null terminator.

char* subKeyPath = new char[strlen(STR) + cbName + 2]; // +2 for \ and null term

Andy

PS That is probably it. But I think you should prob get rid of the RegQueryInfoKey call and use RegEnumKeyEx in the same way as you do RegEnumValue.

This works for me (the above buffer fix, plus freeing memory, plus eliminating all unused variables.)

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
108
#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <cstdlib>
#include <cstdio> // for vprintf
using namespace std;

unordered_map< string, vector<string> > REG_TABLE;

void QueryKey(HKEY hKey1, LPCSTR STR);
void Test();

void __cdecl Output(const char* fmt, ...)
{
	va_list va;
	va_start(va, fmt);
	vprintf(fmt, va);
	va_end(va);
}

void Test()
{
	HKEY hKey = NULL; // was uninit
	LONG dwRegOPenKey = RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\MyProgram", 0, KEY_READ, &hKey);
	if(dwRegOPenKey == ERROR_SUCCESS)
	{
		// RegOpenKeyEx doesn't use last error, so no point reporting random last error...
		//Output("RegOpenKeyEx succeeded, error code %d\n", GetLastError());
		Output("RegOpenKeyEx succeeded\n");
		QueryKey(hKey, "SOFTWARE\\MyProgram");
	} else 
	{
		Output("RegOpenKeyEx failed, error code %d\n", dwRegOPenKey);
	}
	RegCloseKey(hKey);
}

void QueryKey(HKEY hKey1, LPCSTR STR) 
{
	//moved//TCHAR    achKey[MAX_PATH];
	//moved//DWORD    cbName;
	//gone//TCHAR    achClass[MAX_PATH] = TEXT("");
	//gone//DWORD    cchClassName = MAX_PATH;
	DWORD    cSubKeys = 0; // not NULL (it's not a pointer)
	//gone//DWORD    cbMaxSubKey;
	//gone//DWORD    cchMaxClass;
	//gone//DWORD    cValues;
	//gone//DWORD    cchMaxValue;
	//gone//DWORD    cbMaxValueData;
	//gone//DWORD    cbSecurityDescriptor;
	//gone//FILETIME ftLastWriteTime;

	//RegQueryInfoKey( hKey1, achClass, &cchClassName, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, &cValues, &cchMaxValue, &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
	RegQueryInfoKey( hKey1, NULL, NULL, NULL, &cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

	if (cSubKeys)
	{
		TCHAR achKey[MAX_PATH];  // moved here
		DWORD cbName = MAX_PATH; // moved here
		for (DWORD dw = 0; dw < cSubKeys; dw++){
			cbName = MAX_PATH;
			//while(RegEnumKeyEx(hKey1, dw, achKey, &cbName, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
			while(RegEnumKeyEx(hKey1, dw, achKey, &cbName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
			{
				Output("subkeys(%d) %s\n", dw+1, achKey);

				HKEY HKey2 = NULL; // NULL is better that 0 for pointers
				//moved//char buf[MAX_PATH];
				//moved//DWORD dwBufSize = MAX_PATH; // sizeof(buf);

				//char* subKeyPath = new char[sizeof(STR) + cbName];
				char* subKeyPath = new char[strlen(STR) + cbName + 2]; // + 2 for \ and null term
				sprintf(subKeyPath, "%s\\%s", STR, achKey);
				vector<string> key;
				//if( RegOpenKey(HKEY_CURRENT_USER,subKeyPath,&HKey2) == ERROR_SUCCESS )
				if( RegOpenKeyEx(HKEY_CURRENT_USER,subKeyPath,0,KEY_READ,&HKey2) == ERROR_SUCCESS )
				{
					char buf[MAX_PATH];         // moved here
					DWORD dwBufSize = MAX_PATH; // moved here
					int i = 0;
					while( RegEnumValue(HKey2, i++, buf, &dwBufSize, 0, 0, 0, 0) == ERROR_SUCCESS )
					{
						dwBufSize = sizeof(buf);

						TCHAR value[MAX_PATH];
						DWORD value_length = MAX_PATH; // was sizeof(buf);
						if( RegQueryValueEx(HKey2, buf, NULL, NULL, (LPBYTE)&value, &value_length) == ERROR_SUCCESS ){
							Output("(%d) %s - %s\n", i, buf, value);
							key.push_back(value);
						}
					}
					RegCloseKey(HKey2);
				}
				REG_TABLE[achKey] = key;
				delete [] subKeyPath; // free memory, so we don't leak and leak
			}
		}
	} 
}

int main ()
{
    Test();
    return 0;
}


thanks heaps for the help.
think that has helped me out heaps
thanks for teaching me something :)
Topic archived. No new replies allowed.