Enumerating with RegEnumValue

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

LVL 2
MardukLitzerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jaime OlivaresSoftware ArchitectCommented:
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
jkrCommented:
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
Jaime OlivaresSoftware ArchitectCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

MardukLitzerAuthor Commented:
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
itsmeandnobodyelseCommented:
>>>> 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
itsmeandnobodyelseCommented:
>>>> 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
MardukLitzerAuthor Commented:
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
jkrCommented:
Yes, but if you need the cast for '_tcsstr()' and not for 'MessageBox()', there seems to be something wrong...
0
jkrCommented:
... so, what *is* the declaration of that variable? It is hard to spot the problem from only that code snippet.
0
MardukLitzerAuthor Commented:
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
jkrCommented:
Are you sure that UNICODE is set for your project? It somehow seems that you are compiling as ANSI.
0
MardukLitzerAuthor Commented:
jkr, under project properties under general I have "Use UNICODE character set"
0
jkrCommented:
>>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
MardukLitzerAuthor Commented:
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
itsmeandnobodyelseCommented:
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
MardukLitzerAuthor Commented:
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
Jaime OlivaresSoftware ArchitectCommented:
Does my comment was useless?
I see my partial solution in other expert's posts.
0
Jaime OlivaresSoftware ArchitectCommented:
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
modus_operandiCommented:
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
modus_operandiCommented:
Question reopened, and split awarded to participating Experts as recommended in
http://www.experts-exchange.com/Q_23000035.html)

modus_operandi
EE Moderator
0
MardukLitzerAuthor Commented:
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
itsmeandnobodyelseCommented:
>>>> 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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.