Using C++ Builder 11.1.5. This is for a Windows VCL 64-bit application.
I am trying to write a key from the registry (and all subkeys and values) to a backup file so it can be restored at a later time. The key values are under HKEY_LOCAL_MACHINE\Software
.
So far, I have successfully created the backup using the TRegistry::SaveKey()
method, and it works so long as I call SetPrivilege()
and specify SE_BACKUP_NAME
.
Here is the routine I use for saving the registry key to a backup file:
void SaveRegistryKeyToFile(const UnicodeString& key, const UnicodeString& fileName)
{
TRegistry *reg=new TRegistry(KEY_READ);
HANDLE ProcessToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
TRegistry *reg=new TRegistry(KEY_READ);
reg->RootKey=HKEY_LOCAL_MACHINE;
reg->SaveKey(key,fileName);
delete reg;
}
}
Now I am trying to restore the keys to the registry using the TRegistry::LoadKey()
method. I am first setting the privilege for SE_BACKUP_NAME
, and then trying to load the key, but it does not work. Every time I call LoadKey()
, it returns false (failure to work).
Here is the code I am using to do this:
void LoadRegistryKeyFromFile(const UnicodeString& key, const UnicodeString& fileName)
{
TRegistry *reg;
HANDLE ProcessToken;
bool Result;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
reg = new TRegistry(KEY_WRITE)
reg->RootKey=HKEY_LOCAL_MACHINE;
if(FileExists(fileName)) {
Result = reg->LoadKey(key,fileName);
}
delete reg;
}
}
If anyone could assist in pointing me in the right direction on the restoring procedure, it would be greatly appreciated.
Using C++ Builder 11.1.5. This is for a Windows VCL 64-bit application.
I am trying to write a key from the registry (and all subkeys and values) to a backup file so it can be restored at a later time. The key values are under HKEY_LOCAL_MACHINE\Software
.
So far, I have successfully created the backup using the TRegistry::SaveKey()
method, and it works so long as I call SetPrivilege()
and specify SE_BACKUP_NAME
.
Here is the routine I use for saving the registry key to a backup file:
void SaveRegistryKeyToFile(const UnicodeString& key, const UnicodeString& fileName)
{
TRegistry *reg=new TRegistry(KEY_READ);
HANDLE ProcessToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
TRegistry *reg=new TRegistry(KEY_READ);
reg->RootKey=HKEY_LOCAL_MACHINE;
reg->SaveKey(key,fileName);
delete reg;
}
}
Now I am trying to restore the keys to the registry using the TRegistry::LoadKey()
method. I am first setting the privilege for SE_BACKUP_NAME
, and then trying to load the key, but it does not work. Every time I call LoadKey()
, it returns false (failure to work).
Here is the code I am using to do this:
void LoadRegistryKeyFromFile(const UnicodeString& key, const UnicodeString& fileName)
{
TRegistry *reg;
HANDLE ProcessToken;
bool Result;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
reg = new TRegistry(KEY_WRITE)
reg->RootKey=HKEY_LOCAL_MACHINE;
if(FileExists(fileName)) {
Result = reg->LoadKey(key,fileName);
}
delete reg;
}
}
If anyone could assist in pointing me in the right direction on the restoring procedure, it would be greatly appreciated.
Share Improve this question edited 11 hours ago Remy Lebeau 597k36 gold badges500 silver badges844 bronze badges asked 23 hours ago Andrew LeggettAndrew Leggett 11 Answer
Reset to default 0TRegistry::SaveKey()
simply calls the Win32 RegSaveKey()
function, and TRegistry::LoadKey()
calls RegLoadKey()
. Per the RegLoadKey
documentation:
If the function fails, the return value is a nonzero error code defined in Winerror.h. You can use the FormatMessage function with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a generic description of the error.
You can get that error code from the TRegistry::LastError
property, and the formatted message from the TRegistry::LastErrorMsg
property, eg:
if (!reg->LoadKey(key, fileName)) {
ShowMessage(_D("CANT LOAD KEY!\nError: (") + String(reg->LastError) + _D(") ") + reg->LastErrorMsg);
}
Note, the RegLoadKey()
documentation also says:
The calling process must have the SE_RESTORE_NAME and SE_BACKUP_NAME privileges on the computer in which the registry resides. For more information, see Running with Special Privileges. To load a hive without requiring these special privileges, use the RegLoadAppKey function.
You are not enabling the SE_RESTORE_NAME
privilege when loading the key, so RegLoadKey()
is likely failing with an ERROR_PRIVILEGE_NOT_HELD
(1314) error.
Try adding that privlege, eg:
SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE); // <-- ADD THIS
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
Result = reg->LoadKey(key, fileName);
On a side note: Both of your functions are leaking memory. SaveRegistryKeyToFile()
leaks an unused TRegistry
object, and leaks the opened HANDLE
from OpenProcessToken()
. LoadRegistryKeyFromFile()
leaks the opened HANDLE
from OpenProcessToken()
. So, you need to fix that, eg:
bool SaveRegistryKeyToFile(const String& key, const String& fileName)
{
HANDLE ProcessToken;
bool Result = false;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
TRegistry *reg = new TRegistry(KEY_READ);
reg->RootKey = HKEY_LOCAL_MACHINE;
Result = reg->SaveKey(key, fileName);
delete reg;
CloseHandle(ProcessToken);
}
return Result;
}
bool LoadRegistryKeyFromFile(const String& key, const String& fileName)
{
HANDLE ProcessToken;
bool Result = false;
if (FileExists(fileName)) {
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken)) {
SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
TRegistry *reg = new TRegistry(KEY_WRITE);
reg->RootKey = HKEY_LOCAL_MACHINE;
Result = reg->LoadKey(key, fileName);
delete reg;
CloseHandle(ProcessToken);
}
}
return Result;
}