MORE INFORMATION
Step 1: Initialization
To avoid a conflict between two applications that are trying to restore to
the same registry key, use a mutex to prevent a second restore from
occurring before the first one is completed.
hMutex = CreateMutex( NULL, TRUE, REG_RESTORE);
if ( !hMutex )
return GetLastError();
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
if ((lRet=WaitForSingleObject(hMutex, INFINITE)) != WAIT_OBJECT_0)
return lRet;
}
Step 2: Delete Key Values
First you must delete the specified key's values. To do this, you must
first enumerate the key values using RegEnumValue() and then delete them
using RegDeleteValue().
for (;;)
{
cbValue = REGSTR_MAX_VALUE_LENGTH; // reset value length
// remove this keys old values
lRet = RegEnumValue(hStartKey, // handle of key to query
0, // index of value to query
szValue, // address of buffer for value string
&cbValue, // address for size of value buffer
NULL, // reserved
NULL, // address of buffer for type code
NULL, // address of buffer for value data
NULL // address for size of data buffer
);
if ( ERROR_NO_MORE_ITEMS == lRet ) // all values deleted
{
lRet = ERROR_SUCCESS;
break;
}
else if ( ERROR_SUCCESS == lRet )
{
if ((lRet = RegDeleteValue(
hStartKey, // handle of key
szValue // address of value name
)) != ERROR_SUCCESS)
return lRet;
}
else
return lRet;
} // end for loop
Step 3: Delete Subkeys
After you have deleted the current values you must delete the specified
key's subkeys. Do this by enumerating the subkeys using RegEnumKeyEx and
then deleting them using RegDeleteKey. This deletes the current subkeys and all descendant subkeys. After you have completed the deletion, you can add the new subkeys and values.
// delete all subkeys
for(;;)
{
dwSubKeyLength = MAX_PATH;
lRet=RegEnumKeyEx(
hStartKey,
0,
szSubKey,
&dwSubKeyLength,
NULL,
NULL,
NULL,
NULL
);
if(lRet == ERROR_NO_MORE_ITEMS)
{
lRet = ERROR_SUCCESS;
break;
}
else if(lRet == ERROR_SUCCESS)
{
if((lRet = RegDeleteKey(hStartKey, szSubKey)) != ERROR_SUCCESS)
return lRet;
}
else
return lRet;
} // end for loop
Step 4: Restore New Subkeys
To add the new values and subkeys, use RegLoadKey to duplicate and load the
registry hive into the registry. Once the hive has been loaded, all values
and subkeys are enumerated and copied to the specified restore key.
// Load new hive
lRet = RegLoadKey(HKEY_USERS, "TEMP_HIVE", szNewHive );
DWORD RegCreateTree(HKEY hTree, HKEY hReplacement)
{
DWORD cdwClass, dwSubKeyLength, dwDisposition, dwKeyIndex = 0;
LPTSTR pSubKey = NULL;
TCHAR szSubKey[REGSTR_MAX_VALUE_LENGTH]; // this should be dynamic.
TCHAR szClass[REGSTR_MAX_VALUE_LENGTH]; // this should be dynamic.
HKEY hNewKey, hKey;
DWORD lRet;
for(;;)
{
dwSubKeyLength = REGSTR_MAX_VALUE_LENGTH;
cdwClass = REGSTR_MAX_VALUE_LENGTH;
lRet=RegEnumKeyEx(
hReplacement,
dwKeyIndex,
szSubKey,
&dwSubKeyLength,
NULL,
szClass,
&cdwClass,
NULL
);
if(lRet == ERROR_NO_MORE_ITEMS)
{
lRet = ERROR_SUCCESS;
break;
}
else if(lRet == ERROR_SUCCESS)
{
if ((lRet=RegCreateKeyEx(hTree, szSubKey,0, szClass,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hNewKey, &dwDisposition)) != ERROR_SUCCESS )
break;
else // add key values and recurse
{
if ((lRet=RegCreateValues( hReplacement, szSubKey, hNewKey))
!= ERROR_SUCCESS)
{
CloseHandle(hNewKey);
break;
}
if ( (lRet=RegOpenKeyEx(hReplacement, szSubKey, 0,
KEY_ALL_ACCESS, &hKey )) == ERROR_SUCCESS )
{
lRet=RegCreateTree(hNewKey, hKey);
CloseHandle(hKey);
CloseHandle(hNewKey);
if ( lRet != ERROR_SUCCESS )
break;
}
else
{
CloseHandle(hNewKey);
break;
}
}
}
else
break;
++dwKeyIndex;
} // end for loop
return lRet;
} // end RegCreateTree function
DWORD RegCreateValues(HKEY hReplacement, LPCTSTR lpSubKey, HKEY hNewKey)
{
DWORD cbValue, dwSubKeyIndex=0, dwType, cdwBuf;
DWORD dwValues, cbMaxValueData, i;
LPTSTR pSubKey = NULL;
TCHAR szValue[REGSTR_MAX_VALUE_LENGTH]; // this should be dynamic.
HKEY hKey;
DWORD lRet = ERROR_SUCCESS;
LPBYTE pBuf;
if ((lRet=RegOpenKeyEx(hReplacement, lpSubKey, 0,
KEY_ALL_ACCESS, &hKey )) == ERROR_SUCCESS)
{
if ((lRet=RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL,
NULL, &dwValues,NULL, &cbMaxValueData,
NULL, NULL)) == ERROR_SUCCESS)
{
if ( dwValues )
{
if ((pBuf=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cbMaxValueData )))
{
for (i = 0; i < dwValues ; i++)
{
// get values to create
cbValue = REGSTR_MAX_VALUE_LENGTH;
cdwBuf = cbMaxValueData;
lRet = RegEnumValue(
hKey, // handle of key to query
i, // index of value to query
szValue, // buffer for value string
&cbValue, // address for size of buffer
NULL, // reserved
&dwType, // buffer address for type code
pBuf, // address of buffer for value data
&cdwBuf // address for size of buffer
);
if ( ERROR_SUCCESS == lRet )
{
if( (lRet=RegSetValueEx(hNewKey, szValue, 0,
dwType, (CONST BYTE *)pBuf,
cdwBuf))!= ERROR_SUCCESS)
break;
}
else
break;
} // for loop
}
HeapFree(GetProcessHeap(), 0, pBuf);
}
}
CloseHandle(hKey);
}
return lRet;
} // end of RegCreateValues function
Step 5: Clean Up
When all operations have been completed, the registry hive that was loaded
is unloaded and the mutex is released to allow other restores to begin.
// UnLoad user hive
lRet = RegUnLoadKey(HKEY_USERS, "TEMP_HIVE");
ReleaseMutex(hMutex);