Solved

Enumerating with RegEnumValue

Posted on 2007-12-03
22
1,699 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 2

Author Comment

by:MardukLitzer
Comment Utility
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
Comment Utility
>>>> 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
Comment Utility
>>>> 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
Comment Utility
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
Comment Utility
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
Comment Utility
... 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
Comment Utility
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
Comment Utility
Are you sure that UNICODE is set for your project? It somehow seems that you are compiling as ANSI.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 2

Author Comment

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

Assisted Solution

by:jkr
jkr earned 166 total points
Comment Utility
>>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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Does my comment was useless?
I see my partial solution in other expert's posts.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
>>>> 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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

762 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now