Как я могу прочитать 64-битный ключ реестра из 32-битного процесса? - PullRequest
8 голосов
/ 03 февраля 2012

Я использовал значение ключа MachineGuid из HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography для уникальной идентификации хостов, но из 32-разрядных процессов, запущенных на 64-разрядных компьютерах, это значение, по-видимому, отсутствует. Я думаю, что это поиск в Wow6432Node, где он действительно отсутствует. Согласно это вы должны иметь возможность добраться до нужной клавиши, добавив флаг, но приведенный ниже код по-прежнему не выполняет эту работу. Чего мне не хватает?

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;

Ответы [ 4 ]

10 голосов
/ 03 февраля 2012

Я бы посоветовал вам использовать функцию IsWow64Process(), чтобы узнать, когда вы работаете в 32-разрядном режиме на 64-битной ОС, а затем применять флаги KEY_WOW64_64KEY только в этом конкретном состоянии.Если приложение представляет собой 32-разрядный процесс в 32-разрядной ОС или 64-разрядный процесс в 64-разрядной ОС, флаги не нужны.

Например:

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;
7 голосов
/ 03 февраля 2012

Ваш код излишне сложен, в основном потому, что вы не пользуетесь встроенным классом TRegistry, который защищает вас от всех сложностей низкоуровневого API реестра.Например, рассмотрим следующий код:

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;

Функция ReadRegStr вернет строковое значение с именем Name из ключа Key относительно корневого ключа Root.Если есть ошибка, например, если ключ или имя не существует, или если значение имеет неправильный тип, то будет сгенерировано исключение.

Параметр View является перечислением, которое делаетдля вас просто получить доступ к собственным, 32-битным или 64-битным представлениям реестра.Обратите внимание, что native означает native для процесса, который выполняется.Таким образом, это будет 32-битное представление для 32-битного процесса и 64-битное представление для 64-битного процесса.Это перечисление отражает эквивалентное определение в .net.

4 голосов
/ 03 февраля 2012

Используя этот ключ реестра, я пошел еще дальше.Если значение не существует, я его создал: не в HKEY_LOCAL_MACHINE, для этого потребуется повышение, а в HKEY_CURRENT_USER.Любой, кто увидит введенный ключ, вряд ли поймет, что это пустышка.

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;

Это хорошая мысль от @Remy Lebeau - TeamB;Я должен изменить вышеуказанный код соответствующим образом.

0 голосов
/ 28 марта 2018

Вызовите reg.exe по этому пути C: \ Windows \ Sysnative \ reg.exe Например:

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

источник: https://stackoverflow.com/a/25103599

...