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)