2

lsaapi.pas unit 小さな UnicodePCharを使用して 32 ビット コードを 64 ビット コードに変換する際に問題がありPAnsiCharます。

次のコードは 32 ビット モードでは機能しますが、64 ビット モードでは機能しません。プロシージャを実行し (64 ビット デバッグ モードではありません!)、 invalid parameter呼び出してエラー メッセージを取得します。LsaQueryInformationPolicy()

アイデアはありますか?何が問題なのですか?
このコードを 64 ビット デバッグ モードと非デバッグ モードで実行すると、動作が異なるのはなぜですか?
64 ビットでのレコードの位置合わせの問題でしょうか。

コードは次のとおりです。

uses
  lsaapi;

function GetDomainName: string;
var
  Buffer: Pointer;
  Status: NTStatus;
  PolicyHandle: LSA_HANDLE;
  ComputerName: TLsaUnicodeStr;
  Attributes: TLsaObjectAttributes;
  PolicyAccountDomainInfo: PPolicyAccountDomainInfo;
begin
  ComputerName := TLsaUnicodeStr.CreateFromStr('');
  try
    FillChar(Attributes, SizeOf(Attributes), 0);    
    Status := LsaOpenPolicy(ComputerName.Value, Attributes, 
      POLICY_VIEW_LOCAL_INFORMATION, PolicyHandle);
    if Status <> STATUS_SUCCESS then
      raise Exception.Create('LsaOpenPolicy Failed: ' + 
        SysErrorMessage(LsaNtStatusToWinError(Status)));    
    try
      Status := LsaQueryInformationPolicy(PolicyHandle, 
        PolicyPrimaryDomainInformation, Buffer);
      if Status <> STATUS_SUCCESS then
        raise Exception.Create('LsaQueryInformationPolicy Failed: ' +
          SysErrorMessage(LsaNtStatusToWinError(Status)));    
      try
        PolicyAccountDomainInfo := Buffer;
        Result := PolicyAccountDomainInfo.DomainName.Buffer;
      finally
        LsaFreeMemory(Buffer)
      end;
    finally
      LsaClose(PolicyHandle)
    end;
  finally
    ComputerName.Free;
  end;
end;
4

3 に答える 3

8

そのユニット内のすべてのレコードは、lsaapiパックされるように宣言されています。Windows APIヘッダーファイルは、パックされた構造体を使用しません。packedすべての修飾子を削除して修正します。この変更を行うと、関数は32ビットターゲットと64ビットターゲットの両方で成功します。

価値があるのは、コードが実際にへの呼び出しに失敗していることLsaOpenPolicyです。パックされたレコードでは40が返されます。正しいサイズは48であり、これは修飾子SizeOf(Attributes)を削除したときに得られる値です。packed

この種のものをデバッグする最も簡単な方法は、同等のC ++コードを比較できるように、VisualStudioのコピーをインストールすることです。

誤ったレコード宣言がそのユニットの主な問題であると思います。他にもあるかもしれませんが、それは親指の痛みのように突き出ているものです。

于 2012-08-27T09:32:38.987 に答える
2

他の回答がすでに示しているように、おそらくパックされたステートメントが原因で、レコードのサイズが正しくありません(winapiの構造体は通常、パックされていませんが整列されています)。

私のアドバイスは、Jedi Windows ApiLib(この場合はJwaNtSecApi)を使用することです。これは、一般的に、最も優れた、実績のある変換を備えているためです。

于 2012-08-27T11:23:31.670 に答える
2

エラーは、デバッグ時と実行時の両方で発生している可能性がありますが、実行時に飲み込まれます。これは、さまざまな開発環境のx86とx64の両方の世界で数回発生しました。

それで:

  • 適切なものがプロセススペースにロードされていることを確認してください。
  • 64ビットの世界でこれが重要になる他のケースがあったので、位置合わせとパッキングが正しいことを確認してください

それが機能するようになったら、彼のユニットの新しいバージョンを入手したことをコリンに通知してください。

最初は、64ビットプロセスから32ビットDLLを呼び出すことができないためだと思いました( 16ビットと32ビットの間でサンクした16/32ビットの場合とは異なり、そのようなサンクはありません) 32/64ビットの場合)。

次に、advapi32.dllには32ビットバージョンと64ビットバージョンの2つのバージョンがあることがわかりました。

于 2012-08-27T09:34:30.140 に答える