Solved

Enumerating with RegEnumValue

Posted on 2007-12-03
22
1,702 Views
Last Modified: 2010-05-18
Hello, I', trying to trap and receive a particular value in a register key. The code is exiting after the third loop. Seems like retCode is returning success too soon.Any ideas?
while(retCode == ERROR_SUCCESS)
	{
		retCode = RegEnumValue(hKey, i, (LPWSTR)queryValue, &cchValue, 0, &dataType, (LPBYTE)marqueeInstallDir, &dwSize);
		MessageBox(NULL, queryValue, NULL, MB_OK);
		if((_tcsstr((wchar_t *)queryValue, _T("MarqueeDir\0\0"))) != NULL)
			break;
		i++;
	}

Open in new window

0
Comment
Question by:MardukLitzer
  • 7
  • 5
  • 4
  • +2
22 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20396098
will be useful if you send the values for all parameters.

does i starts with a value of zero?
the 4th parameter should be initialized every time you call the RegEnumValue funtion, since it is overwritten by that function, if not, your buffer could be reduced.
0
 
LVL 86

Expert Comment

by:jkr
ID: 20396254
How is 'queryValue' declared? The cast '(wchar_t *)queryValue' makes me think there is something wrong with that since you are using it with 'MessageBox()' without a cast...
0
 
LVL 55

Accepted Solution

by:
Jaime Olivares earned 167 total points
ID: 20396331
Elaborating my previous post about the cchValue parameter, and assumming it is an array of characters, it should be something like:

while(retCode == ERROR_SUCCESS)
{
                                cchValue = sizeof(queryValue);   // set the size of buffer again
            retCode = RegEnumValue(hKey, i, (LPWSTR)queryValue, &cchValue, 0, &dataType, (LPBYTE)marqueeInstallDir, &dwSize);
                                // etcetera
}
0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
LVL 2

Author Comment

by:MardukLitzer
ID: 20396458
I think the issue is with the RegEnumValue failure, it fails after the third enumeration every time. Any ideas would be great thanks in advance!
#define MAX_VALUE_NAME 1000
 
 
int main(int argc, char **argv[])
{
	DWORD i = 0, dataType = REG_SZ, dwSize = MAX_VALUE_NAME;
	LONG retCode = ERROR_SUCCESS;
	HKEY hKey = 0;
	TCHAR str[MAX_VALUE_NAME];
	TCHAR outText[MAX_VALUE_NAME];
	TCHAR queryValue[255] = TEXT("Marquee\0\0");
	
	DWORD cchValue = MAX_VALUE_NAME;
	FILE *out;
 
	memset(outText, 0, MAX_VALUE_NAME);
	LPBYTE storeRegValue = NULL;
	LPBYTE marqueeInstallDir = NULL;
	marqueeInstallDir = new BYTE[255];
	storeRegValue = new BYTE[MAX_VALUE_NAME];
	wchar_t storeRegValue1[1000];
	memset(storeRegValue, 0, 255);
 
	wsprintf(str, L"Software\\Factset\\File Locations");
	retCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,str, 0, KEY_QUERY_VALUE, &hKey);
 
	if(retCode != ERROR_SUCCESS)
		printf("Could not open %s\n%d\n", str, retCode);
 
	i = 0;
	while(retCode == ERROR_SUCCESS)
	{
		cchValue = MAX_VALUE_NAME;
		retCode = RegEnumValue(hKey, i, (LPTSTR )queryValue, &cchValue, 0, &dataType, (LPBYTE)storeRegValue, &dwSize);
		
		if((_tcsstr((wchar_t *)queryValue, _T("MarqueeDir\0\0"))) != NULL)
			break;
		i++;
	}
......

Open in new window

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20396492
>>>> since you are using it with 'MessageBox()' without a cast...
MessageBox was mapped to MessageBoxW or MessageBoxA depending on UNICODE defined. The _tcsstr wouldn't compile if the arguments had different types.

>>>> (wchar_t *)
The cast should be replaced by (LPTSTR). I t makes no sense to using the 'T' functions but with one exception.

>>>> Seems like retCode is returning success too soon.
That is a misinterpretation. The while loop runs while retCode == ERROR_SUCCESS. So, retCode must be different to ERROR_SUCCESS when it breaks or the "MarqueeDir" was found in one of the values.

>>>> "MarqueeDir\0\0"
The '\0' has no effect. Any literal was terminated by a zero char. In case of UNICODE the _T would make it two zero chars anyhow).

Can you post the contents of the MessageBox before break?

Regards, Alex
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 167 total points
ID: 20396839
>>>> if((_tcsstr((wchar_t *)queryValue, _T("MarqueeDir\0\0"))) != NULL)
That is searching the "MarqueeDir" in the *label* and not in the *value*. Is it intended?

Note, the order of the enumerated values is arbitrary. It must not be the same order as showed with RegEdit.

Can you post both label (queryValue) and value (storeRegValue) ?

>>>> wsprintf(str, L"Software\\Factset\\File Locations");

You were mixing up the 'T' notation with the 'W' notation. You should use either the one or the otherbut not mixing the concepts.

Note, MS made macros like _T, TEXT and types like LPTSTR, TCHAR, LPCTSTR  to let you make code which was using either UNICODE or non-UNICODE strings. For example, TCHAR would map to wchar_t in case of UNICODE and to char else. Also WINAPI functions which have char arrays as arguments, were mapped accordingly, e. g. RegEnumValue maps to RegEnumValueA in case of ANSI chars and RegEnumValueW for UUNICODE. And even class CString actually was typedef'd as CStringT and has a CStringA and CStringW implementation. In the above project you obviously have UNICODE switched on. If you never intend to turn it off, you simply can use the wchar_t, LPCWSTR, L"xyz", wcsstr, ... You also could use the RegEnumValueW and CStringW but that is not so important as you can use the generic names (without any T or W) which were mapped anyhow.

0
 
LVL 2

Author Comment

by:MardukLitzer
ID: 20396918
The MessageBox was there just for me to see where it was in the enumeration. The idea is to break once it has the data of the value so I can output it to a bat txt file for net use.
0
 
LVL 86

Expert Comment

by:jkr
ID: 20396934
Yes, but if you need the cast for '_tcsstr()' and not for 'MessageBox()', there seems to be something wrong...
0
 
LVL 86

Expert Comment

by:jkr
ID: 20396943
... so, what *is* the declaration of that variable? It is hard to spot the problem from only that code snippet.
0
 
LVL 2

Author Comment

by:MardukLitzer
ID: 20396955
Below is the rest of the chunk of code to output the storeRegValue to a txt file. The idea is to stop the loop once it encounters the label, so it dumps it into storeRegValue. Any more ideas, thanks!!!!
if((out = _tfopen(TEXT("C:\\mapdirectories.bat"), L"w")) != NULL)
	{
		_tcscat(outText, L"net use Z: /delete\nnet use Z: \\\\sms\\enumerate\\Marquee");
		_ftprintf(out, TEXT("%s\n"), outText);
		memset(str, 0, MAX_VALUE_NAME);
		wsprintf(str, L"\"%s\"", storeRegValue);
		_ftprintf(out, TEXT("xcopy /Y Z:\\Temp\\*.*"));
		_ftprintf(out, TEXT(" %s\n"), str);
		fclose(out);
	}

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
ID: 20396977
Are you sure that UNICODE is set for your project? It somehow seems that you are compiling as ANSI.
0
 
LVL 2

Author Comment

by:MardukLitzer
ID: 20397036
jkr, under project properties under general I have "Use UNICODE character set"
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 166 total points
ID: 20397043
>>it fails after the third enumeration every time.

Hm, what return value do you get then? Try

        while(retCode == ERROR_SUCCESS)
        {
                cchValue = MAX_VALUE_NAME;
                retCode = RegEnumValue(hKey, i, (LPTSTR )queryValue, &cchValue, 0, &dataType, (LPBYTE)storeRegValue, &dwSize);
               
                if((_tcsstr((wchar_t *)queryValue, _T("MarqueeDir\0\0"))) != NULL)
                        break;
                i++;
        }
        printf("Enumeration stopped with %d\n", retCode);
0
 
LVL 2

Author Comment

by:MardukLitzer
ID: 20397183
I modified the while loop to run for 17 iterations (number of values in the key) and it is skipping two of them, conveniently MarqueeDir is one of them. There is just an empty space. Any idea? The retcode error is coming soon... here is the output

MarqueeUserDir
SDKFilesDir
APWUserDir
APWProgramDir
RedistDir
HelpDir

FactSetDir
ProgramDir
ControlsDir
ExcelFilesDir
MarqueeDir
while(i <= 17)
	{
		cchValue = MAX_VALUE_NAME;
		retCode = RegEnumValue(hKey, i, (LPTSTR )queryValue, &cchValue, 0, &dataType, (LPBYTE)storeRegValue, &dwSize);
		_tprintf(L"\n%s", queryValue);
		if((_tcsstr((LPTSTR)queryValue, TEXT("MarqueeDir"))) != NULL)
			MessageBox(NULL, queryValue, NULL, MB_OK);
			break;
		i++;
	}

Open in new window

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20397194
Is there a reason why you didn't post the values you have in the registry and why you didn't answer to questions?
0
 
LVL 2

Author Comment

by:MardukLitzer
ID: 20402254
Ah yes, the code is working now, apparently when I changed the clause to loop 17 times it picked up and hit the break statement just like I wanted... Not sure what may have caused this but at least it is working.. for the time being :) Thanks all for your posts!!
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20402273
Does my comment was useless?
I see my partial solution in other expert's posts.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20402390
I am refering to my comment:

while(retCode == ERROR_SUCCESS)
{
            cchValue = sizeof(queryValue);   // set the size of buffer again
            retCode = RegEnumValue(hKey, i, (LPWSTR)queryValue, &cchValue, 0, &dataType, (LPBYTE)marqueeInstallDir, &dwSize);
            // etcetera
}
0
 
LVL 1

Expert Comment

by:modus_operandi
ID: 20411936
MardukLitzer,

There has been a request in Community Support for you to explain your
disposition of this question.
(http://www.experts-exchange.com/Q_23000035.html)

Please post an explanation for why you chose the particular posts and
point distribution for the answer.

modus_operandi
Community Support Moderator
0
 
LVL 1

Expert Comment

by:modus_operandi
ID: 20437895
Question reopened, and split awarded to participating Experts as recommended in
http://www.experts-exchange.com/Q_23000035.html)

modus_operandi
EE Moderator
0
 
LVL 2

Author Comment

by:MardukLitzer
ID: 20442601
Hi again all, sorry for my delay with this I have been traveling for work and seem to be all over lately. In response to Jaime? and the moderators' request for clarification... Jamie did indeed point out a bug in my code, but as the discussion continued, this didn't resolve the issue I was having. After having posted the comment in regards to "Iterating 17 times" this was what seemed to make the code work. Before that, the code would only loop 3 times and than exit (even with Jaime's suggestion). The reason I distributed the points as I did was due to the fact that the other members took part in the rest of the discussion until the question was closed, kindly pointing out and addressing any issues I might have been having with Unicode. My apologies if Jaime thinks the point dispersal was unfair, but I awarded them based on the effort I thought was put into the responses. Thanks
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20443209
>>>> Jaime did indeed point out a bug in my code, but as the
>>>> discussion continued, this didn't resolve the issue I was having.

Marduk, as I tried to outline above, I think you are wrong with the statement that Jaime's suggestion didn't solve the issue. There are only two ways to break the while condition: an error return of the RegEnumValue or matching the directory name with the search value. The only reason for a early error return I can see,  is to pass the output buffer with a too short length as you did when not resetting the length within the loop. If you look at the first three values

MarqueeUserDir
SDKFilesDir
APWUserDir

you see that 'SDKFilesDir' is shorter than 'MarqueeUserDir', so that it fits to a buffer with the length of 'MarqueeUserDir'. Same, is with 'APWUserDir' what is shorter than 'SDKFilesDir'. However, the next 'APWProgramDir'  would not fit to a buffer sized for 'APWUserDir', so the RegEnumValue would have an error return signaling that the buffer was too short, and would break therefore from the loop.

There were some other code things which were not good, but the issue Jaime found out, was the one which solved your problem.

Regards, Alex

0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question