views:

272

answers:

3

I have got a dll that I load in my program which reads and writes its settings to the registry (hkcu). My program changes these settings prior to loading the dll so it uses the settings my program wants it to use which works fine.

Unfortunately I need to run several instances of my program with different settings for the dll. Now the approach I have used so far no longer works reliably because it is possible for one instance of the program to overwrite the settings that another instance just wrote before the dll has a chance to read them.

I haven't got the source of the dll in question and I cannot ask the programmer who wrote it to change it.

One idea I had, was to hook registry access functions and redirect them to a different branch of the registry which is specific to the instance of my program (e.g. use the process id as part of the path). I think this should work but maybe you have got a different / more elegant.

In case it matters: I am using Delphi 2007 for my program, the dll is probably written in C or C++.

+3  A: 

Instead of hooking the registry access for the dll, you can use an inter-process lock mechanism for writing the values to the registry for your own app. The idea being that the lock acquired by instance1 isn't released until its dll "instance" has read the values, so that when instance2 starts it won't acquire the lock until instance1 has finished. You'd need a locking mechanism that works between processes for this to work. For example mutexes.


To create mutexes:

procedure CreateMutexes(const MutexName: string);
  //Creates the two mutexes checked for by the installer/uninstaller to see if
  //the program is still running.
  //One of the mutexes is created in the global name space (which makes it
  //possible to access the mutex across user sessions in Windows XP); the other
  //is created in the session name space (because versions of Windows NT prior
  //to 4.0 TSE don't have a global name space and don't support the 'Global\'
  //prefix). 
const
  SECURITY_DESCRIPTOR_REVISION = 1;  // Win32 constant not defined in Delphi 3 
var
  SecurityDesc: TSecurityDescriptor;
  SecurityAttr: TSecurityAttributes;
begin
  // By default on Windows NT, created mutexes are accessible only by the user
  // running the process. We need our mutexes to be accessible to all users, so
  // that the mutex detection can work across user sessions in Windows XP. To
  // do this we use a security descriptor with a null DACL. 
  InitializeSecurityDescriptor(@SecurityDesc, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(@SecurityDesc, True, nil, False);
  SecurityAttr.nLength := SizeOf(SecurityAttr);
  SecurityAttr.lpSecurityDescriptor := @SecurityDesc;
  SecurityAttr.bInheritHandle := False;
  CreateMutex(@SecurityAttr, False, PChar(MutexName));
  CreateMutex(@SecurityAttr, False, PChar('Global\' + MutexName));
end;

To release a mutex, you'd use the ReleaseMutex API and to acquire a created mutex, you'd use the OpenMutex API.

For CreateMutex see: http://msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx

For OpenMutex see: http://msdn.microsoft.com/en-us/library/ms684315(v=VS.85).aspx

For ReleaseMutex see: http://msdn.microsoft.com/en-us/library/ms685066(v=VS.85).aspx

Marjan Venema
Does a global mutex require admin privileges and/or elevation?
Remko
Don't think so. Using it in one of my apps running without elevation and it doesn't moan about needing elevation. Of course I am an administrator on my system, but as it is used as an inter-process lock mechanism, and as such used frequently as a means to prevent an app starting twice, I can't see why a global mutex would require amdin priviliges.
Marjan Venema
@Marjan: Thanks for the suggestion, but unfortunately this does not solve my problem because I do not know when the dll might access these settings. It might be when it is being loaded or when it is called or at some other time. (Also Delphi has got a TMutex class in unit SyncObjs which would make using one a bit more convenient that using the Windows API as in your example.)
dummzeuch
@dummzeuch: In that case there is not much else you can do besides hooking the registry access API's. You could have a look at some hooking libraries, such as madCodeHook (highly recommended) (commercial: madshi.net), KBASM (open source) or the jcl or jedi-win32api (open source).
Marjan Venema
@RRUZ: thanks for the edit. Code formatter does do a better job now and the links are very helpful too.
Marjan Venema
No problem ;) .
RRUZ
+3  A: 

As an alternative to API hooking, perhaps you could use RegOverridePredefKey API.

TOndrej
That's an interesting idea. I'll give it a whirl. Thanks.
dummzeuch
A: 

dirty method: open the dll in a hexeditor and change/alter the registry-path from the original hive to any other you want to use or have your proper settings.

lImbus