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

后端 未结 4 2001
轻奢々
轻奢々 2020-12-16 03:01

I\'ve been using the value of key MachineGuid from HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Cryptography to uniquely identify hosts, but from 32-b

相关标签:
4条回答
  • 2020-12-16 03:17

    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

    0 讨论(0)
  • 2020-12-16 03:23

    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;
    
    0 讨论(0)
  • 2020-12-16 03:27

    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.

    0 讨论(0)
  • 2020-12-16 03:29

    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.

    0 讨论(0)
提交回复
热议问题