Welcome to MSDN Blogs Sign in | Join | Help

Decrypt my World

Cryptography, Security, Debugging and more!

News

  • Any of my posts is supported under any Microsoft standard support program or service. They are provided "AS IS" without warranty of any kind, and confer no rights.

Where are my readers?

Locations of visitors to this page

Favorite Posts

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)

Posted: Thursday, November 12, 2009 3:48 PM by alejacma

Comments

No Comments

Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker