Recent

Author Topic: TRegistry.ReadString returns empty string on Win64, not Win32  (Read 16985 times)

ffejrobins30

  • New Member
  • *
  • Posts: 10
TRegistry.ReadString returns empty string on Win64, not Win32
« on: February 10, 2011, 08:06:34 am »
I've got a problem with the following code:

Code: [Select]
procedure TForm1.GetMachineGUID();
var
  fReg:TRegistry;
  GUIDStr:String;
begin
  try
     fReg:=Tregistry.Create;
     fReg.RootKey:=HKEY_LOCAL_MACHINE;
     if fReg.OpenKey('\SOFTWARE\Microsoft\Cryptography', false) then
       begin
          GUIDStr:=freg.ReadString('MachineGuid');
          ShowMessage(GUIDStr);
       end; 
  finally
    fReg.Free;
  end;
end;

If I compile this under the 32-bit version of Lazarus/FPC then it works fine on 32-bit windows machines, but TRegistry.ReadString returns an empty string when run in 64-bit Windows. If I compile it under 64-bit Lazarus/FPC, then it returns the correct string when run in 64-bit windows. This is with no code difference between the two versions, just a different compiler.

Is there something wrong with the code, or is it a bug? I know 100% that the Key exists in the same path on both 32 and 64-bit windows environments.

I am running Windows 7 Ultimate 32-bit
Lazarus ver 0.9.31
FPC ver 2.4.3
SVN 29435

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: TRegistry.ReadString returns empty string on Win64, not Win32
« Reply #1 on: February 10, 2011, 11:16:18 am »
Probably this setting is for the native platform (iow 32-bit on 32-bit windows, and 64-bit on 64-bit windows), and for the 32-bit exe on 64-bit windows you need to do something special.

Some 32-bit subsystems on 64-bit windows are in different placed which is managed by WoW64 (windows on windows emulation, the name for the 32-bit layer of 64-bit windows)

Probably you have to test for this in the 32-bit binary (ifdef!) using the IsWow64Process function, and then specify the alternate registry location where the 32-bit versions are kept on win64.

Such duplicate situations (one for 32-bit one for 64-bit) are typical when the settings also contain references to DLLs, which must be 32-bit or 64-bit.

ffejrobins30

  • New Member
  • *
  • Posts: 10
Re: TRegistry.ReadString returns empty string on Win64, not Win32
« Reply #2 on: February 19, 2011, 10:49:40 pm »
Thanks for the reply. This was he probem. What I found was that 32-Bit apps are run on a "Virtual Machine" aka Windows on Windows Emulation and the VM doesn't have a Local machine Globally Unique ID. There is no alternate path for this, so I actually have to build a 32 and 64 bit app if I want to continue using this registry entry.

dieselnutjob

  • Full Member
  • ***
  • Posts: 217
Re: TRegistry.ReadString returns empty string on Win64, not Win32
« Reply #3 on: March 29, 2011, 02:28:09 pm »
just in case anyone else stumbles across the above code (first google hits for freepascal SOFTWARE\Microsoft\Cryptography )

the code only works if the user running it has admin rights

if you use OpenKeyReadOnly like this:-
Code: [Select]
procedure TForm1.GetMachineGUID();
var
  fReg:TRegistry;
  GUIDStr:String;
begin
  try
     fReg:=Tregistry.Create;
     fReg.RootKey:=HKEY_LOCAL_MACHINE;
     if fReg.OpenKeyReadOnly('\SOFTWARE\Microsoft\Cryptography') then
       begin
          GUIDStr:=freg.ReadString('MachineGuid');
          ShowMessage(GUIDStr);
       end;
  finally
    fReg.Free;
  end;
end; 

then it gives the GUID even if the user doesn't have admin rights.

IPguy

  • Sr. Member
  • ****
  • Posts: 385
Re: TRegistry.ReadString returns empty string on Win64, not Win32
« Reply #4 on: November 13, 2011, 02:58:48 am »
I'm running into the same issue.

I've created a very simple Win-32 program that does a read-only (dieselnutjob, thanks for your hint) of the same key as ffejrobins30 used.

On my Vista-32, N2K VM, Vista-32 VM, Win7-32 VM - I get the expected GUID.

When I run this on my Win7-64 system (real machine, not a VM), I get an empty string.

I have verified that the regedit path and parameter name are identical.

0.9.31-33481-2.5-1-win32, on a Win7-64 system


IPguy

  • Sr. Member
  • ****
  • Posts: 385
Re: TRegistry.ReadString returns empty string on Win64, not Win32
« Reply #5 on: November 13, 2011, 03:31:13 am »
Still snooping, but it appears that the 64 systems handle the registry differently than the 32 bit systems.  This is from an article I found on the topic:
http://www.codeproject.com/KB/system/Reflection.aspx

Still not making sense yet.  Not sure how to use "KEY_WOW64_32KEY".

Quote
There a new flags which can be used to access the alternate registry view in your 32-bit or 64-bit application. With this flag, you can force RegCreateKeyEx, RegDeleteKeyEx and RegOpenKeyEx to explicitly access the 64-bit view (KEY_WOW64_64KEY) or the 32-bit (KEY_WOW64_32KEY) view of the registry, independent of your process' default view. Of course, this only makes sense if you access some keys which will be redirected.

IPguy

  • Sr. Member
  • ****
  • Posts: 385
[Solved] Re: TRegistry.ReadString returns empty string on Win64, not Win32
« Reply #6 on: November 13, 2011, 03:50:02 am »
If you want to run your 32-bit app on a 64-bit machine and extract info from the Windows Registry, modify the following line:

Code: [Select]
from:  fReg:=Tregistry.Create;
to:      fReg:=Tregistry.Create(KEY_READ or $0100);

This works in the same code for a 32-bit system and a 64-bit system (in my very brief testing - your results may be different).

 

TinyPortal © 2005-2018