Page 1 of 1

Saving Registery Key to a file

PostPosted: May 22nd, 2009, 2:35 pm
by SaeedShekari
Hi All
I am trying to save a key from registery, but strangely it saves a file with 0 byte length!
Any suggestion?

Below is a sample of what I am doing:

Code: Select all
procedure SaveKeyTest;
Var
  R: TRegistry;
begin
  R:= TRegistry.Create;
  R.RootKey:= HKEY_CURRENT_USER;
  If R.OpenKey('Software\MyKey', false) Then
  Begin
    R.CloseKey; //I also tried without closing the key
                // help file said SaveKey opens the key itself
                //But no luck
    R.SaveKey('Software\MyKey', 'SavedKeyFile.reg');
               //I also tried a name without extension, again no luck
  End;
  R.Free;
end;

Re: Saving Registery Key to a file

PostPosted: May 22nd, 2009, 3:18 pm
by Kambiz
Try this:

Code: Select all
procedure SaveKeyTest;
var
  R: TRegistry;
begin
  R:= TRegistry.Create;
  try
    R.RootKey := HKEY_CURRENT_USER;
    R.SaveKey('\Software\MyKey', 'SavedKeyFile.reg');
  finally
    R.Free;
  end;
end;

The key must exist.

Re: Saving Registery Key to a file

PostPosted: May 22nd, 2009, 3:55 pm
by SaeedShekari
Hi Kambiz,

Your code had the same result, it saves a file with 0byte in length.
I changed that line to R.SaveKey('\Software\Borland', 'SavedKeyFile.reg');
just to make sure that it may work, that Borland key does exist, but strangely nothing is saved!

What do you think might be wrong? I am using Win XP Pro SP3

Thanks

Re: Saving Registery Key to a file

PostPosted: May 22nd, 2009, 5:54 pm
by Kambiz
The calling process must have the SE_BACKUP_NAME privilege.

If GetLastEerror returns 1314, it means lack of privilege.
If GetLastEerror returns 183, it means file already exists.

But you cannot check the last error after Delphi call. You have to check it after the API call. Try this code:

Code: Select all
procedure SaveKeyTest;
var
  R: TRegistry;
  ErrorCode: Integer;
begin
  R:= TRegistry.Create;
  try
    R.RootKey := HKEY_CURRENT_USER;
    if R.OpenKeyReadOnly('\Software\MyKey') then
    begin
      ErrorCode := RegSaveKey(R.CurrentKey, 'SavedKeyFile.reg', nil);
      R.CloseKey;
      if ErrorCode <> ERROR_SUCCESS then
        raise Exception.CreateFmt('Error Code: %u', [ErrorCode]);
    end
    else
      raise Exception.Create('Key does not exist');
  finally
    R.Free;
  end;
end;

Re: Saving Registery Key to a file

PostPosted: May 22nd, 2009, 7:59 pm
by SaeedShekari
You were right, that was because of access privilege,
I wonder why saving a key to a file needs that privilege while reading, writing or even deleting a key within a program is done without that!!!
Anyhow I fixed the problem by below codes, I pose it in here in case if someone is interested in this topic.
I also mentioned a small useful function for moving a file to recycle bin , that is better than using DeleteFile function!
Code: Select all
procedure SaveKeyTest;
Var
  R: TRegistry;
begin
  R:= TRegistry.Create;
  Try
    R.RootKey:= HKEY_CURRENT_USER;
    If R.OpenKeyReadOnly('Softare\MyKey') Then
    Begin
      R.CloseKey;
      EnableNTPrivilege('SeBackupPrivilege', SE_PRIVILEGE_ENABLED); //See below for this function
      If FileExists('SavedKeyFile.reg') Then
        SendToRecycleBin('SavedKeyFile.reg', False); //See Below or this function

      // This saves the key in binaro format, To read the
      // same key, set the privilege as above and use
      //R.RestoreKey('Software\MyKey', 'SavedKeyFile.reg')
      If R.SaveKey('Softare\MyKey', 'SavedKeyFile.reg') Then
      Begin
         //worked!!! Yippee!! woowoo!!  Saved!
      End
      Else
      Begin
        //Sorry  Failed!
      End;
    End;
  Finally
    R.Free;
  End;
End;

// Setting Access Privilage
Function SetAccessPrivilege(Const PrivilegeStr : String; State : Integer):Integer;
Var
  hToken : THandle;
  aluid : TLargeInteger;
  cbPrevTP : DWORD;
  tp, fPrevTP : PTokenPrivileges;
Begin
  result := 0;
  If OpenProcessToken (GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES Or
      TOKEN_QUERY, hToken) Then
  Try
    LookupPrivilegeValue (Nil, PChar (PrivilegeStr), aluid);
    cbPrevTP := SizeOf (TTokenPrivileges) + sizeof (TLUIDAndAttributes);
    GetMem (tp, cbPrevTP);
    GetMem (fPrevTP, cbPrevTP);
    Try
      tp^.PrivilegeCount := 1;
      tp^.Privileges [0].Luid := aLuid;
      tp^.Privileges [0].Attributes := State;
      If Not AdjustTokenPrivileges (hToken, False, tp^, cbPrevTP, fPrevTP^, cbPrevTP) Then
        RaiseLastWin32Error;
      Result := fPrevTP^.Privileges [0].Attributes;
    Finally
      FreeMem (fPrevTP);
      FreeMem (tp);
    End
  Finally
   CloseHandle (hToken);
  End
End;

// Sending a file to recucle bin
Function SendToRecycleBin(FileName: String; DoConfirm: Boolean): boolean;
Var
  fos: TSHFileOpStruct;
  i: Integer;
Begin
  FillChar(fos, SizeOf(fos), 0);
  With fos Do
  Begin
    wFunc:= FO_DELETE;
    FileName:= FileName + #0 + #0;
    pFrom:= @FileName[1];
    fFlags:= FOF_ALLOWUNDO or FOF_SILENT;
    If Not DoConfirm Then fFlags:= fFlags Or FOF_NOCONFIRMATION;
  End;
  i:= ShFileOperation(fos);
  Result:= (i = 0);
End;

Re: Saving Registery Key to a file

PostPosted: May 22nd, 2009, 9:29 pm
by Kambiz
Very useful functions, thanks for sharing.

Re: Saving Registery Key to a file

PostPosted: May 22nd, 2009, 10:24 pm
by SaeedShekari
I just noticed restoring that Registry key from a file is also a bit of head ache!
Below function can restore a saved registry key from a file. Note that access privilege string is different from saving.

Code: Select all
Procedure ReadMyKey;
Var
  R: TRegistry;
Begin
  R:= TRegistry.Create;
  try
    R.RootKey:= HKEY_CURRENT_USER;
    // the key must exist
    // do necessary checks
    R.OpenKey('Software\Mykey', True);
    R.CloseKey;// Do not forget to close the key
    SetAccessPrivilege('SerestorePrivilege',SE_PRIVILEGE_ENABLED);
    //This will overwtite all keys and values if they already exist
    If R.RestoreKey('Software\Mykey', 'SavedRegKey.reg') Then
    Begin
      //Done! Do needful
    End
    Else
    Begin
      // Something is wrong!
      //As I checked if the registry is open and if it exists and
      // it is selected by you, then this restore will fail
    End;
  Finally
    R.Free;
  End;
End;