How to manipulate REG_MULTI_SZ values from the registry (C++)


Hi all,


The other day I had to develop a small C++ sample which shows how to read the list of values of a REG_MULTI_SZ from the registry, and add a new value just after one of the values of the list. Additionally, I used methods and constants from tchar.h extensively, so it didn’t matter if I compiled the code as UNICODE or ANSI. Here is the code:


 

#include “windows.h”
#include “tchar.h”
#include “conio.h”
#include “stdio.h”

#define MY_KEY _T(“PathToMyRegistryKey\\MyRegistryKey”) // Registry key
#define MY_VALUES _T(“NameOfTheREG_MULTI_SZListOfValues”) // Registry values
#define NEW_VALUE _T(“MyNewValue”) // New value
#define FIND_VALUE _T(“AnExistingValue”) // We will insert the new value after this one

int _tmain(int argc, _TCHAR* argv[])
{
LONG lResult = 0;
HKEY hKey = NULL;
LPTSTR lpValues = NULL;
LPTSTR lpValue = NULL;
LPTSTR lpNewValues = NULL;
LPTSTR lpNewValue = NULL;
DWORD cbValues = 0;
DWORD cbNewValues = 0;
DWORD cbNewValue = 0;
BOOL bFound = FALSE;

__try
{
// OPEN THE REGISTRY KEY
//
_tprintf(_T(“RegOpenKeyEx…”));
lResult = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
MY_KEY,
0,
KEY_ALL_ACCESS,
&hKey
);
if (ERROR_SUCCESS != lResult) { _tprintf(_T(“ERROR 0x%x\n”), lResult); return 1; }
_tprintf(_T(“SUCCESS\n”));

// READ THE REG_MULTI_SZ VALUES
//
// Get size of the buffer for the values
_tprintf(_T(“RegQueryValueEx…”));
lResult = RegQueryValueEx(
hKey,
MY_VALUES,
NULL,
NULL,
NULL,
&cbValues
);
if (ERROR_SUCCESS != lResult) { _tprintf(_T(“ERROR 0x%x\n”), lResult); return 1; }
_tprintf(_T(“SUCCESS\n”));

// Allocate the buffer
_tprintf(_T(“malloc…”));
lpValues = (LPTSTR)malloc(cbValues);
if (NULL == lpValues) { _tprintf(_T(“ERROR 0x%x\n”), GetLastError()); return 1; }
_tprintf(_T(“SUCCESS\n”));

// Get the values
_tprintf(_T(“RegQueryValueEx…”));
lResult = RegQueryValueEx(
hKey,
MY_VALUES,
NULL,
NULL,
(LPBYTE)lpValues,
&cbValues
);
if (ERROR_SUCCESS != lResult) { _tprintf(_T(“ERROR 0x%x\n”), lResult); return 1; }
_tprintf(_T(“SUCCESS\n”));

// SHOW THE VALUES
//
_tprintf(_T(“\n**************************\n”));
_tprintf(_T(“OLD VALUES\n”));
_tprintf(_T(“**************************\n\n”));
lpValue = lpValues;
for (; ‘\0’ != *lpValue; lpValue += _tcslen(lpValue) + 1)
{
// Show one value
_tprintf(_T(“%s\n”), lpValue);
}
_tprintf(_T(“\n**************************\n\n”));

// INSERT A NEW VALUE AFTER A SPECIFIC VALUE IN THE LIST OF VALUES
//
// Allocate a new buffer for the old values plus the new one
_tprintf(_T(“malloc…”));
cbNewValue = (_tcslen(NEW_VALUE) + 1) * sizeof(TCHAR);
cbNewValues = cbValues + cbNewValue;
lpNewValues = (LPTSTR)malloc(cbNewValues);
if (NULL == lpNewValues) { _tprintf(_T(“ERROR 0x%x\n”), GetLastError()); return 1; }
_tprintf(_T(“SUCCESS\n”));

// Find the value after which we will insert the new one
lpValue = lpValues;
lpNewValue = lpNewValues;
bFound = FALSE;
for (; ‘\0’ != *lpValue; lpValue += _tcslen(lpValue) + 1)
{
// Copy the current value to the target buffer
memcpy(lpNewValue, lpValue, (_tcslen(lpValue) + 1) * sizeof(TCHAR));

if (0 == _tcscmp(lpValue, FIND_VALUE))
{
// The current value is the one we wanted to find
bFound = TRUE;

// Copy the new value to the target buffer
lpNewValue += _tcslen(lpValue) + 1;
memcpy(lpNewValue, NEW_VALUE, (_tcslen(NEW_VALUE) + 1) * sizeof(TCHAR));
lpNewValue += _tcslen(NEW_VALUE) + 1;
}
else
{
// This is not the value we want, continue to the next one
lpNewValue += _tcslen(lpValue) + 1;
}
}
if (!bFound)
{
// We didn’t find the value we wanted. Insert the new value at the end
memcpy(lpNewValue, NEW_VALUE, (_tcslen(NEW_VALUE) + 1) * sizeof(TCHAR));
lpNewValue += _tcslen(NEW_VALUE) + 1;
}
*lpNewValue = *lpValue;

// SHOW THE NEW VALUES
//
_tprintf(_T(“\n**************************\n”));
_tprintf(_T(“NEW VALUES\n”));
_tprintf(_T(“**************************\n\n”));
lpNewValue = lpNewValues;
for (; ‘\0’ != *lpNewValue; lpNewValue += _tcslen(lpNewValue) + 1)
{
// Show one value
_tprintf(_T(“%s\n”), lpNewValue);
}
_tprintf(_T(“\n**************************\n\n”));

// WRITE THE NEW VALUES BACK TO THE KEY
//
_tprintf(_T(“RegSetValueEx…”));
lResult = RegSetValueEx(
hKey,
MY_VALUES,
NULL,
REG_MULTI_SZ,
(LPBYTE)lpNewValues,
cbNewValues
);
if (ERROR_SUCCESS != lResult) { _tprintf(_T(“ERROR 0x%x\n”), lResult); return 1; }
_tprintf(_T(“SUCCESS\n”));
}
__finally
{
// Clean up
//
if (NULL != lpValues) { free(lpValues); }
if (NULL != lpNewValues) { free(lpNewValues); }
if (NULL != hKey) { RegCloseKey(hKey); }

//_tprintf(_T(“\n<<PRESS ANY KEY>>\n”));
//_getch();
}

return 0;
}


Regards,


 


Alex (Alejandro Campos Magencio)


Comments (0)