2

CreateComObject(...)レジストリエントリHKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\...\LocalServer32が有効であることを確認した後に基本的に呼び出すコードがいくつかあります。

問題は、レジストリ キーをチェックしないと、COM サーバーが正しく読み込まれないことです。

そんなことがあるものか?

const
  csLibGuid                 : TGUID  = '...';
  csLibMd5Sum               : string = '...';
  csLibRegKeyFormatRegular  : string = '\SOFTWARE\Classes\CLSID\%s\LocalServer32';
  csLibRegKeyFormatWow64    : string = '\SOFTWARE\Classes\Wow6432Node\CLSID\%s\LocalServer32';
  csLibClassName            : string = '...';

procedure TLibLoader.CheckLibraryChecksum;
var
  FileNames  : TStringList;
  Registry   : TRegistry;

  procedure AddFileName(AHKEY: HKEY; const AFormat: string);
  begin
    Registry.RootKey := AHKEY;
    Registry.OpenKey(
        Format(AFormat, [GUIDToString(csLibGuid)])
      , False
    );
    try
      FileName := Registry.ReadString(csEmpty);
      if Trim(FileName) > csEmpty then begin
        FileNames.Add(FileName);
      end;
    finally
      Registry.CloseKey;
    end;
  end;

var
  FileName   : string;
  FileDigest : string;
begin
  Registry := TRegistry.Create(KEY_EXECUTE);
  try
    FileNames := TStringList.Create;
    try
      FileNames.Duplicates := dupIgnore;
      FileNames.Sorted     := True;
      AddFileName(HKEY_LOCAL_MACHINE, csLibRegKeyFormatRegular);
      AddFileName(HKEY_LOCAL_MACHINE, csLibRegKeyFormatWoW64);
      AddFileName(HKEY_CURRENT_USER , csLibRegKeyFormatRegular);
      AddFileName(HKEY_CURRENT_USER , csLibRegKeyFormatWoW64);
      if FileNames.Count = 0 then begin
        raise EProtector.Create('All registry keys are empty');
      end;
      for FileName in FileNames do begin
        if not FileExists(FileName) then begin
          raise Exception.Create(Format('File "%s" does not exist', [FileName]));
        end;
        FileDigest := TMD5.HashFile(FileName);
        if not AnsiSameText(FileDigest, csLibMd5Sum) then begin
          raise Exception.Create(Format('File "%s" is not valid', [FileName]));
        end;
      end;
    finally
      FileNames.Free;
    end;
  finally
    Registry.Free;
  end;
end;

CheckLibraryChecksum;
CreateComObject(csLibGuid);
4

1 に答える 1

4

の戻り値をチェックしていませんOpenKey。そうする必要があり、 がOpenKey返された場合にのみ値を読み取りますTrue

これらのキーのいくつかは存在しないと思われます。False次に、から返される を無視してOpenKey、とにかく値を読み取ろうとします。これにより、例外が発生します。

したがって、関数は次のようになります。

procedure AddFileName(AHKEY: HKEY; const AFormat: string);
begin
  Registry.RootKey := AHKEY;
  if Registry.OpenKey(
      Format(AFormat, [GUIDToString(csLibGuid)])
    , False
  ) then begin
    try
      FileName := Registry.ReadString(csEmpty);
      if Trim(FileName) > csEmpty then begin
        FileNames.Add(FileName);
      end;
    finally
      Registry.CloseKey;
    end;
  end;
end;

個人OpenKeyReadOnly的には、より明示的だと思うので使用します。と同じ値を使用KEY_EXECUTEしていることに気づきました。人間の読者が意図を確認しやすくなると感じています。AccessKEY_READOpenKeyReadOnly

于 2013-02-07T17:00:26.243 に答える