How can I read 64-bit registry key from a 32-bit process?

不想你离开。 提交于 2019-12-18 03:41:53

问题


I've been using the value of key MachineGuid from HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography to uniquely identify hosts, but from 32-bit processes running on 64-bit computers, the value appears to be missing. I guess it's searching under Wow6432Node, where it is indeed missing. According to this you should be able to get to the right key by adding a flag, but below code still doesn't appear to do the job. What am I missing?

const
  KEY_WOW64_64KEY=$0100;
var
  r:HKEY;
  s:string;
  i,l:integer;
begin
  //use cryptography machineguid, keep a local copy of this in initialization?
  l:=40;
  if RegOpenKeyEx(HKEY_LOCAL_MACHINE,PChar('Software\Microsoft\Cryptography'),
    0,KEY_QUERY_VALUE,r)=ERROR_SUCCESS then
   begin
    SetLength(s,l);
    if RegQueryValue(r,'MachineGuid',PChar(s),l)=ERROR_SUCCESS then
     begin
      SetLength(s,l);
      RegCloseKey(r);
     end
    else
     begin
      //try from-32-to-64
      RegCloseKey(r);
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE,PChar('Software\Microsoft\Cryptography'),
        0,KEY_QUERY_VALUE or KEY_WOW64_64KEY,r)=ERROR_SUCCESS then
       begin
        l:=40;
        if RegQueryValue(r,'MachineGuid',PChar(s),l)=ERROR_SUCCESS then
          SetLength(s,l)
        else
          l:=0;
        RegCloseKey(r);
       end;
     end;
   end;

回答1:


Your code is needlessly complex, largely because you are not taking advantage of the built-in TRegistry class which shields you from all the complexities of the low-level registry API. For example, consider the following code:

type
  TRegistryView = (rvDefault, rvRegistry64, rvRegistry32);

function RegistryViewAccessFlag(View: TRegistryView): LongWord;
begin
  case View of
  rvDefault:
    Result := 0;
  rvRegistry64:
    Result := KEY_WOW64_64KEY;
  rvRegistry32:
    Result := KEY_WOW64_32KEY;
  end;
end;

function ReadRegStr(const Root: HKEY; const Key, Name: string;
  const View: TRegistryView=rvDefault): string;
var
  Registry: TRegistry;
begin
  Registry := TRegistry.Create(KEY_READ or RegistryViewAccessFlag(View));
  try
    Registry.RootKey := Root;
    if not Registry.OpenKey(Key) then
      raise ERegistryException.CreateFmt('Key not found: %s', [Key]);
    if not Registry.ValueExists(Name) then
      raise ERegistryException.CreateFmt('Name not found: %s\%s', [Key, Name]);
    Result := Registry.ReadString(Name);//will raise exception in case of failure
  finally
    Registry.Free;
  end;
end;

The function ReadRegStr will return the string value named Name from the key Key relative to the root key Root. If there is an error, for example if the key or name do not exists, or if the value is of the wrong type, then an exception will be raised.

The View parameter is an enumeration that makes it simple for you to access native, 32-bit or 64-bit views of the registry. Note that native means native to the process that is running. So it will be the 32-bit view for a 32-bit process and the 64-bit view for a 64-bit process. This enumeration mirrors the equivalent definition in .net.




回答2:


I would suggest you use the IsWow64Process() function to know when you are a 32-process running on a 64-bit OS, and then only apply the KEY_WOW64_64KEY flags in that specific condition. If the app is a 32-bit process on a 32-bit OS, or a 64-bit process on a 64-bit OS, the flags is not needed.

For example:

const 
  KEY_WOW64_64KEY = $0100; 
var 
  key: HKEY; 
  str: string; 
  len: DWORD; 
  flag: REGSAM;
  wow64: BOOL;
begin 
  flag := 0;
  wow64 := 0;
  IsWow64Process(GetCurrentProcess(), @wow64);
  if wow64 <> 0 then flag := KEY_WOW64_64KEY;

  if RegOpenKeyEx(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Cryptography', 0, KEY_QUERY_VALUE or flag, key) = ERROR_SUCCESS then 
  try
    SetLength(str, 40); 
    len := Length(str) * SizeOf(Char); 
    if RegQueryValueEx(key, 'MachineGuid', nil, nil, PByte(Pointer(s)), @len) <> ERROR_SUCCESS then len := 0;
    SetLength(str, len div SizeOf(Char)); 
  finally
    RegCloseKey(key); 
  end; 
end;



回答3:


In my use of this registry key I went a step further. If the value didn't exist I created it: not in HKEY_LOCAL_MACHINE, that would require elevation, but in HKEY_CURRENT_USER. Anyone seeing the introduced key there is unlikely to realise that it's a dummy.

function GetComputerGUID: String;
var
  Reg: TRegistry;
  oGuid: TGUID;
  sGuid: String;
begin
  Result := '';
  // Attempt to retrieve the real key
  Reg := TRegistry.Create(KEY_READ OR KEY_WOW64_64KEY);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Cryptography') and Reg.ValueExists('MachineGuid') then
      Result := Reg.ReadString('MachineGuid');
    Reg.CloseKey;
  finally
    Reg.Free;
  end;
  // If retrieval fails, look for the surrogate
  if Result = '' then begin
    Reg := TRegistry.Create;
    try
      Reg.RootKey := HKEY_CURRENT_USER;
      if Reg.OpenKey('SOFTWARE\Microsoft\Cryptography', True) then begin
        if Reg.ValueExists('MachineGuid') then
          Result := Reg.ReadString('MachineGuid')
        else begin
          // If the surrogate doesn't exist, create it
          if CreateGUID(oGUID) = 0 then begin
            sGuid := Lowercase(GUIDToString(oGUID));
            Reg.WriteString('MachineGuid', Copy(sGuid, 2, Length(sGUID) - 2));
            Result := Reg.ReadString('MachineGuid');
          end;
        end;
      end;
      Reg.CloseKey;
    finally
      Reg.Free;
    end;
  end;
  if Result = '' then
    raise Exception.Create('Unable to access registry value in GetComputerGUID');
end;

That's a good point from @Remy Lebeau - TeamB though; I should mod the above code appropriately.




回答4:


Call reg.exe using this path C:\Windows\sysnative\reg.exe For example:

C:\Windows\sysnative\reg.exe QUERY "HKLM\SOFTWARE\JavaSoft\JDK" /v CurrentVersion

source: https://stackoverflow.com/a/25103599



来源:https://stackoverflow.com/questions/9121044/how-can-i-read-64-bit-registry-key-from-a-32-bit-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!