Rev 4 | Blame | Compare with Previous | Last modification | View Log
/*Module : HKLM.CPPPurpose: Implementation for a class to provide simpleaccess to the HKEY_LOCAL_MACHINE\Software\Company\MyAppregistry key similiar to the functions MFC providesto access the same settings in HKEY_CURRENT_USERCreated: PJN / 27-07-1998History: PJN / 03-10-1999 Addition of GetProfileStringArray and WriteProfileStringArray methodsPJN / 09-08-2001 1. Updated copyright message2. Fixed an issue where the class fails to read any key that is readonly.This is a problem since Win2000 defaults access to HKLM for "normal"users to readonly. Thanks to Hans-Georg Ulrich for spotting this problem3. Removed an unreferenced function for the hklm header file4. Fixed a memory overwrite problem in CHKLM::SetStringArrayIntoRegistry.Thanks to BoundsChecker on spotting this problem.5. Fixed a problem in CHKLM::SetStringArrayIntoRegistry with thecalculation of the size to be used in the call to RegSetValueEx6. GetStringArrayFromRegistry now use RegQueryValueEx to get the size ofthe data it contains.7. Sample app now uses CWinApp to make it easier for testing.PJN / 12-10-2001 1. Now allows application name to be overridden using new method namely,SetProductNameRegistryKey. Thanks to Rene M. Laviolette for this suggestion.Copyright (c) 1998 - 2001 by PJ Naughter. (Web: www.naughter.com, Email: pjna@naughter.com)All rights reserved.Copyright / Usage Details:You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)when your product is released in binary form. You are allowed to modify the source code in any way you wantexcept you cannot modify the copyright details at the top of each module. If you want to distribute sourcecode with your application, then you are only allowed to distribute versions released by the author. This isto maintain a single distribution point for the source code.*////////////////////////////////// Includes //////////////////////////////////#pragma warning( disable : 4996 )#include "stdafx.h"#include "hklm.h"#pragma warning(disable : 4996)//////////////// Macros //////////////////////////////////////////////#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//////////////// Implementation //////////////////////////////////////void CHKLM::SetRegistryKey(char *lpszRegistryKey){m_sRegistryKey = lpszRegistryKey;}void CHKLM::SetProductNameRegistryKey(LPCTSTR lpszProductNameRegistryKey){m_sProductNameRegistryKey = lpszProductNameRegistryKey;}void CHKLM::SetProductNameRegistryKey(UINT nIDProductNameRegistryKey){CString sKey;VERIFY(sKey.LoadString(nIDProductNameRegistryKey));SetProductNameRegistryKey(sKey);}CString CHKLM::GetProductNameRegistryKey() const{return m_sProductNameRegistryKey;}void CHKLM::SetRegistryKey(UINT nIDRegistryKey){CString sKey;VERIFY(sKey.LoadString(nIDRegistryKey));SetRegistryKey(sKey.GetBuffer());}// returns key for HKEY_LOCAL_MACHINE\"Software"\RegistryKey\ProfileName// creating it if it doesn't exist// responsibility of the caller to call RegCloseKey() on the returned HKEYHKEY CHKLM::GetAppRegistryKey(BOOL bReadOnly){ASSERT(m_sRegistryKey.GetLength());HKEY hAppKey = NULL;HKEY hSoftKey = NULL;HKEY hCompanyKey = NULL;//Setup the access typeREGSAM samDesired = KEY_WRITE | KEY_READ;if (bReadOnly)samDesired = KEY_READ;if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software"), 0, samDesired, &hSoftKey) == ERROR_SUCCESS){DWORD dw;if (RegCreateKeyEx(hSoftKey, m_sRegistryKey, 0, REG_NONE, REG_OPTION_NON_VOLATILE,samDesired, NULL, &hCompanyKey, &dw) == ERROR_SUCCESS){if (m_sProductNameRegistryKey.GetLength()){RegCreateKeyEx(hCompanyKey, m_sProductNameRegistryKey, 0, REG_NONE, REG_OPTION_NON_VOLATILE,samDesired, NULL, &hAppKey, &dw);}else{ASSERT(AfxGetApp());RegCreateKeyEx(hCompanyKey, AfxGetApp()->m_pszAppName, 0, REG_NONE, REG_OPTION_NON_VOLATILE,samDesired, NULL, &hAppKey, &dw);}}}if (hSoftKey != NULL)RegCloseKey(hSoftKey);if (hCompanyKey != NULL)RegCloseKey(hCompanyKey);return hAppKey;}// returns key for:// HKEY_LOCAL_MACHINE\"Software"\RegistryKey\AppName\lpszSection// creating it if it doesn't exist.// responsibility of the caller to call RegCloseKey() on the returned HKEYHKEY CHKLM::GetSectionKey(LPCTSTR lpszSection, BOOL bReadOnly){ASSERT(lpszSection != NULL);HKEY hSectionKey = NULL;HKEY hAppKey = GetAppRegistryKey(bReadOnly);if (hAppKey == NULL)return NULL;//Setup the access typeREGSAM samDesired = KEY_WRITE | KEY_READ;if (bReadOnly)samDesired = KEY_READ;DWORD dw;RegCreateKeyEx(hAppKey, lpszSection, 0, REG_NONE, REG_OPTION_NON_VOLATILE,samDesired, NULL, &hSectionKey, &dw);RegCloseKey(hAppKey);return hSectionKey;}UINT CHKLM::GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault){ASSERT(lpszSection != NULL);ASSERT(lpszEntry != NULL);HKEY hSecKey = GetSectionKey(lpszSection, TRUE);if (hSecKey == NULL)return nDefault;DWORD dwValue;DWORD dwType;DWORD dwCount = sizeof(DWORD);LONG lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType,(LPBYTE)&dwValue, &dwCount);RegCloseKey(hSecKey);if (lResult == ERROR_SUCCESS){ASSERT(dwType == REG_DWORD);ASSERT(dwCount == sizeof(dwValue));return (UINT)dwValue;}return nDefault;}CString CHKLM::GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault){ASSERT(lpszSection != NULL);ASSERT(lpszEntry != NULL);HKEY hSecKey = GetSectionKey(lpszSection, TRUE);if (hSecKey == NULL)return lpszDefault;CString strValue;DWORD dwType, dwCount;LONG lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType,NULL, &dwCount);if (lResult == ERROR_SUCCESS){ASSERT(dwType == REG_SZ);lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType,(LPBYTE)strValue.GetBuffer(dwCount/sizeof(TCHAR)), &dwCount);strValue.ReleaseBuffer();}RegCloseKey(hSecKey);if (lResult == ERROR_SUCCESS){ASSERT(dwType == REG_SZ);return strValue;}return lpszDefault;}BOOL CHKLM::GetProfileBinary(LPCTSTR lpszSection, LPCTSTR lpszEntry, BYTE** ppData, UINT* pBytes){ASSERT(lpszSection != NULL);ASSERT(lpszEntry != NULL);ASSERT(ppData != NULL);ASSERT(pBytes != NULL);*ppData = NULL;*pBytes = 0;HKEY hSecKey = GetSectionKey(lpszSection, TRUE);if (hSecKey == NULL)return FALSE;DWORD dwType, dwCount;LONG lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType, NULL, &dwCount);*pBytes = dwCount;if (lResult == ERROR_SUCCESS){ASSERT(dwType == REG_BINARY);*ppData = new BYTE[*pBytes];lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType,*ppData, &dwCount);}RegCloseKey(hSecKey);if (lResult == ERROR_SUCCESS){ASSERT(dwType == REG_BINARY);return TRUE;}else{delete [] *ppData;*ppData = NULL;}return FALSE;}BOOL CHKLM::GetProfileStringArray(LPCTSTR lpszSection, LPCTSTR lpszEntry, CStringArray& array){ASSERT(lpszSection != NULL);//Empty out the array before we go any furtherarray.RemoveAll();HKEY hSecKey = GetSectionKey(lpszSection, TRUE);if (hSecKey == NULL)return FALSE;BOOL bSuccess = GetStringArrayFromRegistry(hSecKey, lpszEntry, array);RegCloseKey(hSecKey);return bSuccess;}BOOL CHKLM::WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue){ASSERT(lpszSection != NULL);ASSERT(lpszEntry != NULL);HKEY hSecKey = GetSectionKey(lpszSection);if (hSecKey == NULL)return FALSE;LONG lResult = RegSetValueEx(hSecKey, lpszEntry, NULL, REG_DWORD,(LPBYTE)&nValue, sizeof(nValue));RegCloseKey(hSecKey);return lResult == ERROR_SUCCESS;}BOOL CHKLM::WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue){ASSERT(lpszSection != NULL);LONG lResult;if (lpszEntry == NULL) //delete whole section{HKEY hAppKey = GetAppRegistryKey();if (hAppKey == NULL)return FALSE;lResult = ::RegDeleteKey(hAppKey, lpszSection);RegCloseKey(hAppKey);}else if (lpszValue == NULL){HKEY hSecKey = GetSectionKey(lpszSection);if (hSecKey == NULL)return FALSE;// necessary to cast away const belowlResult = ::RegDeleteValue(hSecKey, (LPTSTR)lpszEntry);RegCloseKey(hSecKey);}else{HKEY hSecKey = GetSectionKey(lpszSection);if (hSecKey == NULL)return FALSE;lResult = RegSetValueEx(hSecKey, lpszEntry, NULL, REG_SZ,(LPBYTE)lpszValue, (lstrlen(lpszValue)+1)*sizeof(TCHAR));RegCloseKey(hSecKey);}return lResult == ERROR_SUCCESS;}BOOL CHKLM::WriteProfileBinary(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPBYTE pData, UINT nBytes){ASSERT(lpszSection != NULL);LONG lResult;HKEY hSecKey = GetSectionKey(lpszSection);if (hSecKey == NULL)return FALSE;lResult = RegSetValueEx(hSecKey, lpszEntry, NULL, REG_BINARY,pData, nBytes);RegCloseKey(hSecKey);return lResult == ERROR_SUCCESS;}BOOL CHKLM::WriteProfileStringArray(LPCTSTR lpszSection, LPCTSTR lpszEntry, const CStringArray& array){ASSERT(lpszSection != NULL);HKEY hSecKey = GetSectionKey(lpszSection);if (hSecKey == NULL)return FALSE;BOOL bSuccess = SetStringArrayIntoRegistry(hSecKey, lpszEntry, array);RegCloseKey(hSecKey);return bSuccess;}BOOL CHKLM::GetStringArrayFromRegistry(HKEY hKey, LPCTSTR lpszEntry, CStringArray& array){ASSERT(hKey != NULL);ASSERT(lpszEntry != NULL);//Assume the worstBOOL bSuccess = FALSE;//Empty the array before we go any furtherarray.RemoveAll();DWORD dwType, dwCount;LONG lResult = RegQueryValueEx(hKey, (LPTSTR)lpszEntry, NULL, &dwType, NULL, &dwCount);if (lResult == ERROR_SUCCESS){ASSERT(dwType == REG_MULTI_SZ);LPBYTE lpBuffer = new BYTE[dwCount];lResult = RegQueryValueEx(hKey, (LPTSTR)lpszEntry, NULL, &dwType, lpBuffer, &dwCount);if (lResult == ERROR_SUCCESS){LPTSTR lpszStrings = (LPTSTR) lpBuffer;while (lpszStrings[0] != 0){array.Add((LPCTSTR) lpszStrings);lpszStrings += (_tcslen(lpszStrings ) + 1);}bSuccess = TRUE;}//Tidy up the heap memory we have useddelete [] lpBuffer;}return bSuccess;}BOOL CHKLM::SetStringArrayIntoRegistry(HKEY hKey, LPCTSTR lpszEntry, const CStringArray& array){int i;//Validate our input parametersASSERT(hKey);ASSERT(lpszEntry != NULL);//Work out the size of the buffer we will needDWORD dwSize = 0;int nStrings = array.GetSize();for (i=0; i<nStrings; i++)dwSize += array.GetAt(i).GetLength() + 1; //1 extra for each NULL terminator//Need one second NULL for the double NULL at the enddwSize++;//Convert from BYTE size to character sizedwSize *= sizeof(TCHAR);//Allocate the memory we wantBYTE* lpBuffer = new BYTE[dwSize];::ZeroMemory(lpBuffer, dwSize);//Now copy the strings into the bufferint nCurOffset = 0;LPTSTR lpszString = (LPTSTR) lpBuffer;for (i=0; i<nStrings; i++){CString sText = array.GetAt(i);_tcscpy(&lpszString[nCurOffset], sText);nCurOffset += sText.GetLength();nCurOffset++;}//Don't forgot to doubly NULL terminatelpszString[nCurOffset] = _T('\0');//Finally write it into the registryBOOL bSuccess = (::RegSetValueEx(hKey, lpszEntry, NULL, REG_MULTI_SZ, lpBuffer, dwSize) == ERROR_SUCCESS);//free up the memory we useddelete [] lpBuffer;return bSuccess;}