6
votes

I've several long-standing apps written in Delphi that persist their settings in the registry. I've used HKEY_LOCAL_MACHINE for 'hard' settings such as configuration preferences and HKEY_CURRENT_USER for 'soft' info such as window positions, MRU lists etc.

Now my users are telling me that in non-admin (standard user) mode the apps dont work. Looking, I see that I'm not able to read a setting put into HKEY_LOCAL_MACHINE when the app was in admin mode.

What are my options for this? I know little about standard mode and how this affects access to the registry at all. Any info appreciated.

6
Tip: You might want to try developing under a non-power-user account. Yes, it can be a bit of a nuisance sometimes, but this way you make sure "surprises" like you just encountered don't hit you in the face. It's corporate policy at a lot of development shops for good reason.Paul-Jan
How would your application behave under Windows 2000 or Windows XP as a standard user? That will guide you how it should behave under Windows Vista or Windows 7 as a standard user.Ian Boyd

6 Answers

17
votes

You can read from HKLM as a non-admin user; you just can't write to it.

Use TRegistry.Create(KEY_READ) when constructing it, and set the RootKey to HKLM.

var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_READ)
  try
    Reg.RootKey := HKLM;
    // Read value here
  finally
    Reg.Free;
  end;
end;

You can also use TRegistry.OpenKeyReadOnly() when opening a specific registry key; this helps with non-admin access to areas of the registry as well.

2
votes

The other thing that nobody's mentioned here is the issue of registry virtualization on Vista & Win7 (at least). It may not be an issue in your particular scenario, but I thought I'd mention it anyway in case it is relevant.
Even if your user has admin rights, if your application is NOT running "elevated" on Vista/Win7, your app still won't be able to write to the "real" HKLM key that you think it is. It will be being read and written to a virtualized copy of the appropriate HKLM key that only that particular user sees.
By "elevated", I mean that you will have been prompted with a UAC prompt on Vista/Win7. Run Regedit.exe for example on Vista/Win7, and you will be prompted with a UAC prompt.
If you're on Vista/Win7, it's possible that this is the issue you describe when you say it's not possible to read a key/value that was written in admin mode. If so, this would be because your app has at some stage written what is now a virtualized key/value; your app will now only ever see that key/value, even if an administrator modifies the "real" value.
As others have said, your app should not try to write to HKLM. If you feel it does need to write to HKLM, then on Vista/Win7 your options are (and these options can be made to work fine on XP too):

  • Add a manifest to your app requiring elevated admin rights as per this example.
  • Split your functionality requiring HKLM access out into a separate COM library and instantiate it as an elevated COM object as and when you need it. This is more complicated, but is a reasonable way to refactor existing functionality.

Here's another SO question that addresses some of these issues.

1
votes

One option, which I don't favour but will mention, is to give everyone (or a defined group etc) permission to access your key. There are various ways to do this, and there is code in the JCL that will do it, or you can use Regedit. But if you give permission (to that specific branch of HKLM) then it will work as you intended.

1
votes

From a developer perspective Windows's UAC can be problematic for some parts of your Delphi application, if the application is not being run by an administartor. One such operation is writing to the Registry database.

You have to "request admin rights" by creating an application manifest file....

Windows Vista/7 - User Account Control

User Account Control is a security component in Windows Vista. UAC enables users to perform common tasks as non-administrators, called standard users in Windows Vista, and as administrators without having to switch users, log off, or use Run As. To help prevent malicious software from silently installing and causing computer-wide infection, Microsoft developed the UAC feature.

From a developer perspective the following UAC features are important:

All processes are started as Standard User as default A Standard User can not: Change files in Program Files folders Change files in Windows or System32 folders Change registry under HKLM\Software Change the local machines date and time ...the list continues...

Programmatically Edit Registry to Run Your Delphi Application on Windows Startup

By programmatically editing the Windows Registry, using the TRegistry object, you can you can "automagically" start programs whenever Windows launches. The procedure you can use to force "auto-run-on-Windows-startup" for your application might look like:

 procedure RunOnStartup(const sCmdLine: string; bRunOnce: boolean = false; Remove: Boolean = false) ;
 var
   sKey: string;
   Section: string;
 const
   ApplicationTitle = ”Your Application TITLE”;
 begin
   if (bRunOnce) then
     sKey := 'Once'
   else
     sKey := '';

   Section := 'Software\Microsoft\Windows\CurrentVersion\Run' + sKey + #0;

   with TRegIniFile.Create('') do
     try
       RootKey := HKEY_LOCAL_MACHINE;
       if Remove then
         DeleteKey(Section, ApplicationTitle)
       else
         WriteString(Section, ApplicationTitle, sCmdLine) ;
     finally
       Free;
     end;
 end;

On Vista/7, if the user running the application does not have admin rights the above code would fail, due to UAC!

Faking UAC Rights - How to Request Execution Level

Even if the user running the above code is not an admin, you can, as a developer arm your application with a special kind of embedded resource: application manifest file. Having the manifest file will ensure Vista's UAC will allow your code to execute.

Here are the steps:

Create XML file with following content:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0]
  <assemblyIdentity version="1.1.1.1"
   processorArchitecture="X86"
   name="YourApplicationExeName"
   type="win32"/>
  <description>elevate execution level</description>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2]
  <security>
   <requestedPrivileges>
    <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
   </requestedPrivileges>
  </security>
  </trustInfo>
 </assembly>

Name this XML file as YourApplicationName.manifest Create a text file with following content: 1 24 "YourApplicationName.manifest"

Name this text file as YourApplicationName.RC using the command line execute following command: brcc32 YourApplicationName.RC -foYourApplicationName.REC

This will create a new resource file called YourApplicationName.REC

Copy this YourApplicationName.REC file in to the resource path of your application. Include this resource file into the DPR of you application, as like: {$R YourApplicationName.REC}

Finally build your application - it is now ready to get admin rights on Windows Vista. Note 1: in the above steps, replace "YourApplicationExeName" with your actual application name. Note 2: Above steps create a resource file to be stored inside the EXE file of your application. More on Resources in Delphi applications.

read more in http://delphi.about.com/od/delphitips2009/qt/delphi-vista-registry-run-on-startup.htm

0
votes

Your options include (a) use an INI/XML config file in a location that doesn't require admin rights to access, or (b) modify the security on your own subkey in HKLM using a tool like SetACL (public domain).

The problem with option a is the change in folder arrangements between XP and Vista/W7. I believe Vista tightened up access to CSIDL COMMON APPDATA - standard users don't have write acess if memory serves. You may have to store them in your own folder and arrange access rights yourself. Annoying.

One interesting problem with option b is that there are now officious little tools in use in corporate environments that crawl the registry and "correct" access rights they think are wrong. We haven't encountered a problem with customers using these yet, but we are aware they exist. Given the performance of the registry, we still prefer the modified HKLM approach and will continue to do it for the foreseeable future.