user3365784
user3365784

Reputation: 377

Delphi export HKEY_CURRENT_USER key not working - empty result file

I am trying to export a registry key using either TRegistry.SaveKey or RegSaveKey functions with no luck. All I get is an empty file 0 bytes. I have seen examples online none seems to be working on Windows10.

  reg := TRegistry.Create;

  reg.RootKey := HKEY_CURRENT_USER;
  reg.Access := KEY_ALL_ACCESS;

  if reg.OpenKey('\Software\MyCompanyName\MyApplication\', True) then
  begin
    reg.WriteInteger('background', Self.Color);

    reg.SaveKey('HKEY_CURRENT_USER\Software\MyCompanyName\MyApplication', 'test.txt'); //not working
    RegSaveKey(reg.CurrentKey, 'test.reg', nil); //creates empty file
  end;
  reg.CloseKey;
  reg.Free;

Also if I extract existing key from RegEdit and then try to load it in the application using TRegistry.LoadKey or RegLoadKey nothing is happening

I do have admin right on the machine I run this.

Anyone familiar with the issue?

Upvotes: 3

Views: 1147

Answers (2)

whosrdaddy
whosrdaddy

Reputation: 11859

Here is a working example. Be aware that you must run the program as administrator.

program SO59753973;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Registry,
  Windows,
  System.SysUtils;



function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean;

var
 hToken: THandle;
 TokenPriv: TOKEN_PRIVILEGES;
 PrevTokenPriv: TOKEN_PRIVILEGES;
 ReturnLength: Cardinal;
 errval:Cardinal;
begin
 Result := True;
 errval:=0;
 // Only for Windows NT/2000/XP and later.
 if not (Win32Platform = VER_PLATFORM_WIN32_NT) then Exit;
 Result := False;
 // obtain the processes token
 if OpenProcessToken(GetCurrentProcess(),
 TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
  try
  // Get the locally unique identifier (LUID) .
  if LookupPrivilegeValue(nil, PChar(sPrivilege),TokenPriv.Privileges[0].Luid) then
  begin
   TokenPriv.PrivilegeCount := 1; // one privilege to set
   case bEnabled of
    True: TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    False: TokenPriv.Privileges[0].Attributes := 0;
   end;

  ReturnLength := 0; // replaces a var parameter
  PrevTokenPriv := TokenPriv;
   // enable or disable the privilege
  if AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv),PrevTokenPriv, ReturnLength) then
   Result := True
  else
   begin
    errval:= GetLastError;
    Result := errval = 0;
   end;
  end;
 finally
  CloseHandle(hToken);
 end;
 // test the return value of AdjustTokenPrivileges.
 //Result := GetLastError = ERROR_SUCCESS;
 if not Result then
 raise Exception.Create(SysErrorMessage(errval));
end;

var
  Reg: TRegistry;
  sKeyFileName: String;

begin
 try
  if not NTSetPrivilege('SeBackupPrivilege',true) then
    Exit;
  sKeyFileName := 'C:\temp\tempReg.reg';
  if FileExists(sKeyFileName) then
    DeleteFile(sKeyFileName);
  Reg := TRegistry.Create(KEY_ALL_ACCESS);
   try
    Reg.RootKey := HKEY_CURRENT_USER;
    if Reg.SaveKey('\Software\Microsoft', sKeyFileName)
    then
     Writeln('Registry has been saved!')
    else
     Writeln('Failed to save registry, received error: ' + IntToStr(Reg.LastError) + '!');
   finally
    Reg.Free;
   end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
 Readln;
end.

For restoring the registry, you must enable the SE_RESTORE_NAME in addition to the SE_BACKUP_NAME Privilege.

Code has been taken (and adapted) from this old forum post

Upvotes: 3

kobik
kobik

Reputation: 21252

From the documentation of RegSaveKey:

The calling process must have the SE_BACKUP_NAME privilege enabled.

My guess is that RegSaveKey returning a value other than ERROR_SUCCESS. which your code does not check.

See also:

RegSaveKey returns ERROR_PRIVILEGE_NOT_HELD

Another thing to check for is that the destination file does not exists before you try to save, or else the function will fail (this is also mentioned in the documentation), and obviously that you have write permissions to the file location.

Upvotes: 10

Related Questions