4

Using the code below I try to set a value in the HKEY_LOCAL_MACHINE section of registry but I get an error 'Failed to set data for.....' If I use HKEY_CURRENT_USER there is no problem.

What might I be missing here.

(The code is not complete, but I think it is the important parts of it)

type
  TTypWinBits = (Bit32, Bit64);

function WinBits: TTypWinBits;
type
  TIsWow64Process = function(Handle:THandle; var IsWow64 : BOOL) : BOOL; stdcall;
var
  hKernel32 : Integer;
  IsWow64Process : TIsWow64Process;
  IsWow64 : BOOL;
begin
  Result := Bit32;
  hKernel32 := LoadLibrary('kernel32.dll');
  if (hKernel32 = 0) then RaiseLastOSError;
  @IsWow64Process := GetProcAddress(hkernel32, 'IsWow64Process');
  if Assigned(IsWow64Process) then
    begin
      IsWow64 := False;
      if (IsWow64Process(GetCurrentProcess, IsWow64)) then
        Result := Bit64
      else
        RaiseLastOSError;
    end;
  FreeLibrary(hKernel32);
end;

function TFastRegistry.CreateConnection: TRegistry;
begin
  Result := TRegistry.Create;
  try
    case WinBits of
      Bit32: Result := TRegistry.Create;
      Bit64: Result := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY);
    end;
  except
    on E: exception do
      Result := nil;
  end;
end;

procedure TFastRegistry.RunAdd(aDesc, aName: string);
var
  Reg: TRegistry;
  sRegKey: String;
begin
  sRegKey := 'Software\Microsoft\Windows\CurrentVersion\Run';
  Reg := CreateConnection;
  with Reg do
    begin
      try
        RootKey := HKEY_LOCAL_MACHINE;
        if not KeyExists(sRegKey) then
          OpenKey(sRegKey, True)
        else
          OpenKey(sRegKey, False);
        WriteString(aDesc, aName);
      finally
        CloseKey;
        Free;
      end;
    end;
end;
OZ8HP
  • 1,443
  • 4
  • 31
  • 61
  • 4
    Probably you haven't system registry write rights and/or your app need permissions elevation. – Marcodor Jul 28 '12 at 09:50
  • check this Question -[registry access in non admin mode](http://stackoverflow.com/questions/1681434/registry-access-in-non-admin-mode) – PresleyDias Jul 28 '12 at 10:04
  • Consider creating a shortcut in the 'Autostart' folder of the users start menu. This requires no administrator rights, while writing to HKLM does. Additionally, it gives him more control. – Chris Jul 28 '12 at 10:42
  • @Jay, the registry API functions don't use GetLastError; they return the error code directly, and that code is represented in the exception object. – Rob Kennedy Jul 28 '12 at 13:52
  • 2
    @Jay: in Delphi XE2, `TRegistry` has new `LastError` and `LastErrorMsg` properties for getting the error code and error text of the last performed registry operation. – Remy Lebeau Jul 28 '12 at 18:34
  • @Chris for what i remember HKCU branch also has autorun section. While he might make LNK files in user menu (and it might be easier to advanced user to administer it later) he can still do with registry. – Arioch 'The Jul 30 '12 at 09:19
  • TFastRegistry.CreateConnection leaks in the event of an exception – David Heffernan Jul 30 '12 at 12:49
  • @David Heffernan EurekaLog told me that as soon as I turne it on :-) – OZ8HP Aug 01 '12 at 04:10
  • @Chris I could create a shortcut as you describe, but I think it is easier to create the key (and delete it) and in my experience the entries i registry are executed before the shortcuts. And that is important in this case – OZ8HP Aug 01 '12 at 04:10
  • @Jay If not to use TRegistry what then to use to access registry? – OZ8HP Aug 01 '12 at 04:10

2 Answers2

6

A program requires elevated privileges to write to the local-machine key. Without that, functions will fail, as you've observed. If your program is supposed to be an administrative tool, then use a manifest file so the OS will prompt for permission. If you don't need that, then write to the current-user key instead so it doesn't affect all accounts on the system.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • Therefore, you should create the registry like `Reg:= TRegistry.Create(KEY_READ or KEY_WRITE);` using the appropriate access flags for your scenario. – Jerry Dodge Jul 29 '12 at 22:23
  • That's generally good advice, @Jerry, but it doesn't follow from what I wrote. Requesting write access to the machine key only grants write access if your process already has elevated privileges. – Rob Kennedy Jul 30 '12 at 05:16
0

You just need to release the handle by the "Free" and for the next entry in the register to recreate it, and not keep it permanently set up and open and close them through OpenKey and CloseKey! It looks like a bug :-)