QA: How to copy registry key recursively?
October 28th, 2004 by Andrey Yatsyk

Question

How to copy registry key recursively with all subkeys and values?

Answer

Sometimes it is need to copy a registry key with all sub keys into other place in registry. It can be useful when your program’s setup changes some standard registry key and you want that your program will restore changed key after removing. Microsoft strictly recommends that your program should be polite and restore registry state after uninstalling. Unfortunately there is no way to copy a key with sub keys by one Win API function call and you should write key traversing and coping code by hand.
I have written a function that does all dirty work for you and you should just execute this function for deep registry copy. At first you should download and add to your workspace RegUtil source and header files. There is one function defined in that source code:

BOOL CopyRegistryKey(HKEY hkRootFrom, const CString& strFromPath,
HKEY hkRootTo, const CString& strToPath);

where hkRootFrom and hkRootTo are source and destination root folders and strFromPath and strToPath are source and destination paths.

Sources

Here is source code for the CopyRegistryKey function:

const static int nMaxValueNameSize = MAX_PATH;
const static int nMaxValueValueSize = 4096;
const static int nMaxClassSize = MAX_PATH;
const static int nMaxKeyNameSize = MAX_PATH;

static BOOL CopyKeys(HKEY hkFrom, HKEY hkTo)
{
TCHAR lpstrName[nMaxKeyNameSize];
TCHAR lpstrClass[nMaxClassSize];

for (int i = 0;;i++) {
DWORD nNameSize = nMaxKeyNameSize;
DWORD nClassSize = nMaxClassSize;
LONG res = ::RegEnumKeyEx(hkFrom, i, lpstrName, &nNameSize, 0,
lpstrClass, &nClassSize, 0);

if (ERROR_NO_MORE_ITEMS == res) {
break;
}
HKEY hkNew;
res = ::RegCreateKeyEx(hkTo, lpstrName, 0, lpstrClass,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hkNew, 0);
if (ERROR_SUCCESS != res) {
return FALSE;
}
::RegCloseKey(hkNew);
BOOL bRes = CopyRegistryKey(hkFrom, lpstrName, hkTo, lpstrName);
if (! bRes) {
return FALSE;
}
}

return TRUE;
}

static BOOL CopyValues(HKEY hkFrom, HKEY hkTo)
{
TCHAR lpstrName[nMaxValueNameSize];
BYTE pValue[nMaxValueValueSize];

for (int i = 0;;i++) {
DWORD nType;
DWORD nNameSize = nMaxValueNameSize;
DWORD nValueSize = nMaxValueValueSize;
LONG res = ::RegEnumValue(hkFrom, i, lpstrName, &nNameSize, 0,
&nType, pValue, &nValueSize);
if (ERROR_NO_MORE_ITEMS == res) {
break;
}
res = ::RegSetValueEx(hkTo, lpstrName, 0, nType, pValue, nValueSize);
if (ERROR_SUCCESS != res) {
return FALSE;
}
}

return TRUE;
}

BOOL CopyRegistryKey(HKEY hkRootFrom, const CString& strFromPath,
HKEY hkRootTo, const CString& strToPath)
{
HKEY hkFrom;
LONG res = ::RegOpenKeyEx(hkRootFrom, strFromPath, 0, KEY_READ, &hkFrom);
if (ERROR_SUCCESS != res) {
return FALSE;
}
HKEY hkTo;
res = ::RegCreateKeyEx(hkRootTo, strToPath, 0, 0, REG_OPTION_NON_VOLATILE,
KEY_WRITE, 0, &hkTo, 0);
if (ERROR_SUCCESS != res) {
::RegCloseKey(hkFrom);
return FALSE;
}
BOOL bRes = CopyKeys(hkFrom, hkTo) && CopyValues(hkFrom, hkTo);

::RegCloseKey(hkFrom);
::RegCloseKey(hkTo);

return bRes;
}

Related resources:

Section: Files and Registry
Article: Working with registry on Pocket PC
Library: VORegistry
Control: vbceUtil v2
Control: IDSSAPI
Article: Using the Registry in a C++ Application
Article: Windows CE Registry FAQ
Article: eVB sample accessing the Pocket PC Windows CE Registry
Article: Edit Pocket PC Windows CE Registry using eVB (eMbedded Visual Basic) and Windows CE API calls

(Discuss in forum)

Leave a Reply