Thread: Efficient registry use?

  1. #1
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401

    Efficient registry use?

    This is my first time using the registry, and I was hoping I'm going about it the right way.

    Basically, this code finds the desired registry key, finds the value corresponding to a certain string, then fills a RECT structure with the entry.

    Code:
    RECT GetRegCoords(char *lpCmdLine)
    {
    	RECT rcCoords={-1,-1,-1,-1};
    	HKEY hKeySoftware;
    	HKEY hKeyNote;
    
    	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software",0,KEY_ALL_ACCESS,&hKeySoftware)==ERROR_SUCCESS)
    	{ //Can we open the HKEY_LOCAL_MACHINE\Software key?
    		DWORD dwKeyExists;
    		if (RegCreateKeyEx(hKeySoftware,"Note",0,NULL,REG_OPTION_NON_VOLATILE,
    							KEY_ALL_ACCESS,NULL,&hKeyNote,&dwKeyExists)==ERROR_SUCCESS)
    		{//Can we open/create the Note key?
    			if (dwKeyExists==REG_OPENED_EXISTING_KEY)
    			{//Did the key already exist?
    				int nCount=0;
    				char *lpValue=new char[64];
    				char *lpEntry=new char[32];
    				DWORD cbName=64;
    				DWORD dwSize=32;
    				DWORD dwType;
    				while (RegEnumValue(hKeyNote,nCount,lpValue,&cbName,0,&dwType,(LPBYTE)lpEntry,&dwSize)==ERROR_SUCCESS)
    				{//Are there any values left to enumerate?
    					if (!lstrcmpi(lpValue,lpCmdLine))
    					{//The key name matches the named passed in through the command line
    						char *lpTemp=new char[8];
    						DWORD nStrCount=0;
    						DWORD nRectCount=0;
    						DWORD nStrLen=strlen(lpEntry);
    						lpTemp[0]=0;
    
    						for (UINT i=0;i<(nStrLen+1);i++)
    						{
    							if (nRectCount>3)	//Already found 4 vertices?
    								break;			//Then break the for loop
    							if ( (lpEntry[i]!=',') && (lpEntry[i]!=0) ) //It wasn't a comma or null 
    								lpTemp[nStrCount++]=lpEntry[i];			//so add the number to temp
    							else //Found a comma, so null-terminate temp, and enter it into rcCoords
    							{
    								lpTemp[nStrCount]=0;	
    								((LONG *)&rcCoords)[nRectCount++]=atoi(lpTemp);
    								lpTemp[nStrCount=0]=0; //reset nStrCount and lpTemp
    							}
    						}
    						//Done parsing
    						delete [] lpTemp;
    						break; //Break out the the while loop
    					}
    					//Selected value did not match command line specified file
    					nCount++; //Increase the key enum index
    				}
    				//No subkeys left to enumerate
    				delete [] lpValue;
    				delete [] lpEntry;
    			}
    			else
    			{}//Key didn't already exist, we created it
    		}
    		else{}//We couldn't open or even create the Note key
    	}
    	else{}//We couldn't open the HKEY_LOCAL_MACHINE\Software key
    
    	return rcCoords;
    }
    Can anyone see any ways to reduce my registry code down? I'm pretty sure I'm doing the bare minimum needed.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I'm not sure if I'm right in assuming you just want to retrieve a value, but if you just want to get the value of an existing registry key, which you know the name of then:

    Code:
    HKEY hKey;
    char * szRegKey = "Software\\note";
    char szValue[100];
    DWORD dwType, dwSize = sizeof(szValue);
    
    lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_QUERY_VALUE, &hKey);
    
    if (lResult == ERROR_SUCCESS) {
    	lResult = RegQueryValueEx(hKey, lpCmdLine, 0, &dwType, (LPBYTE) szValue, &dwDataSize );
    	if (lResult == ERROR_SUCCESS && dwType == REG_SZ) {
    		szValue[99] = '\0';
    		// Use the value
    	}
    	RegCloseKey(hKey);
    }
    This will put the value of HKLM\Software\Note\lpCmdLine in szValue.
    It should be noted that the value is not guaranteed to be null terminated. Personally, I would use four REG_DWORD values, left, right, etc.

    I posted some code recently on this board that did everything(allocated memory, retrieved value, null terminated and error checking) with the simple functions:
    Code:
    HRESULT RegGetString(HKEY hKey, LPCTSTR szValueName, LPTSTR * lpszResult)
    HRESULT RegGetDWord(HKEY hKey, LPCTSTR szValueName, DWORD * lpdwResult)
    Do a search.
    If you want to write values then here is some old code:
    Code:
    RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\note",0,NULL,
    				REG_OPTION_NON_VOLATILE,KEY_SET_VALUE,NULL,&hKey,NULL);
    
    RegSetValueEx(hKey,"Value Name",0,REG_DWORD,(LPBYTE) &dwValue, sizeof(DWORD) );
    EDIT: It should be noted that while you may develop with administrator priviliges, most people will not run your program with administrative priviliges. Therefore, they will not be able to write values under HKLM or even open HKLM with KEY_ALL_ACCESS. Unless the value is only written at installation or the program is a service, you should use HKLU.
    Last edited by anonytmouse; 09-27-2003 at 12:35 AM.

  3. #3
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Okay, I took some of your advice and reduced it down some more.

    Code:
    HKEY GetRegNoteKey()
    {
    	HKEY hKeyNote;
    	DWORD dwDisposition;
    	if (RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Note",0,NULL,REG_OPTION_NON_VOLATILE,
    						KEY_ALL_ACCESS,NULL,&hKeyNote,&dwDisposition)==ERROR_SUCCESS)
    	{ //We opened/created the HKEY_CURRENT_USER\Software\Note key
    	}
    	else
    	{//Couldn't open/create Note key
    		hKeyNote=NULL;
    	}
    
    	return hKeyNote;
    }
    
    BOOL StringToRect(char *lpString,RECT *rc)
    {
    	char *lpTemp=new char[8];
    	DWORD nStrCount=0;
    	DWORD nRectCount=0;
    	DWORD nStrLen=strlen(lpString);
    	lpTemp[0]=0;
    
    	for (UINT i=0;i<(nStrLen+1);i++)
    	{
    		if (nRectCount>3)	//Already found 4 vertices?
    			break;			//Then break the for loop
    		if ( (lpString[i]!=',') && (lpString[i]!=0) ) //It wasn't a comma or null 
    			lpTemp[nStrCount++]=lpString[i];			//so add the number to temp
    		else //Found a comma, so null-terminate temp, and enter it into rcCoords
    		{
    			lpTemp[nStrCount]=0;	
    			((LONG *)rc)[nRectCount++]=atoi(lpTemp);
    			lpTemp[nStrCount=0]=0; //reset nStrCount and lpTemp
    		}
    	}
    	//Done parsing
    	delete [] lpTemp;
    
    	return TRUE;
    }
    
    RECT GetRegCoords(char *lpCmdLine)
    {
    	HKEY hKeyNote;
    	RECT rcCoords={-1,-1,-1,-1};
    
    	hKeyNote=GetRegNoteKey();
    	if (hKeyNote)
    	{
    		char *lpEntry=new char[32];
    		DWORD dwSize=32;
    		DWORD dwType;
    		if (RegQueryValueEx(hKeyNote,lpCmdLine,0,&dwType,(LPBYTE)lpEntry,&dwSize)==ERROR_SUCCESS)
    		{//We successfully retrieved the right entry
    			lpEntry[dwSize]=0; //Ensure null-termination
    			StringToRect(lpEntry,&rcCoords); //Convert the entry into a RECT structure
    		}
    		
    		RegCloseKey(hKeyNote);	
    		delete [] lpEntry;
    	}
    
    	return rcCoords;
    }
    I don't want to have a key for each possible set of values, I'd rather just have a value and use the entry to get the dimensions. Is the code better now?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544

    Thumbs up

    Much cleaner.
    Fix lpEntry[dwSize]=0
    Why dynamically allocate such short strings?
    Also, what if a rect dimension is more than seven numbers long?

  5. #5
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Much cleaner.
    Thanks.
    Fix lpEntry[dwSize]=0
    I don't understand. I added that line specifically to fix the problem you pointed out. You said null-termination wasn't guaranteed, so I made sure I added it.
    Why dynamically allocate such short strings?
    I dunno, I always do it that way. Can I ask a question? Is the following correct?
    Code:
    char *a=new char[256];
    char b[256];
    
    //a contains address of block
    //b contains address of block
    I've seen some code where just using 'b' by itself operates as a pointer to the array. In that case, I would stop using dynamically allocated strings.

    Also, what if a rect dimension is more than seven numbers long?
    It wouldn't occur in this case because the RECT refers to screen coordinates. But I see what you're getting at. A little error checking never hurts does it.

    Thanks for the help.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  6. #6
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I think you want:
    lpData[dwSize - 1] = 0;

    >I've seen some code where just using 'b' by itself operates as a pointer to the array.
    Mostly, b can be used like a pointer. Except b itself can not be altered and the & operator can not be used successfully on b.
    Of course b is also freed when the function returns so can not be used to return data from a function.
    Code:
    b++; // won't compile
    b = another pointer; //won't compile
    char ** x = &b; //  x == &b == b!! weird hey!.

  7. #7
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Thanks anonytmouse, I didn't realize that dwSize included the null-terminator that is not always included.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Registry, Regedit
    By franse in forum C++ Programming
    Replies: 21
    Last Post: 01-29-2009, 09:57 AM
  2. Registry Problem
    By guitarist809 in forum Windows Programming
    Replies: 4
    Last Post: 03-21-2008, 02:00 AM
  3. Registry
    By gvector1 in forum C# Programming
    Replies: 0
    Last Post: 07-30-2003, 04:02 PM
  4. how to edit the registry
    By jverkoey in forum Windows Programming
    Replies: 3
    Last Post: 03-28-2003, 04:20 AM
  5. Registry Access
    By ExDigit in forum Windows Programming
    Replies: 3
    Last Post: 01-04-2002, 04:02 AM