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. 打包记录SizeOf(Attributes)返回 40。正确的大小是 48,这就是删除packed修饰符时得到的值。

调试此类事情的最简单方法是安装 Visual Studio 的副本,以便您可以比较等效的 C++ 代码。

我认为不正确的记录声明是该单元的主要问题。可能还有其他人,但那是一个像拇指酸痛一样突出的人。

于 2012-08-27T09:32:38.987 回答
2

您的错误很可能在调试和运行时都发生,但在运行时被吞没了。我在 x86 和 x64 世界的各种开发环境中都发生过几次这种情况。

所以:

  • 确保将正确的加载到您的进程空间中。
  • 确保对齐和打包是正确的,因为在 64 位世界中还有其他情况下这很重要

如果你让它工作,请通知科林你得到了他单位的新版本。

起初我认为这是因为您不能从 64 位进程调用 32 位 DLL(与 16/32 位情况不同,您在 16 位和 32 位之间进行转换,反之亦然,没有这样的转换32/64 位的情况)。

然后我发现advapi32.dll有两个版本:一个 32 位版本和一个 64 位版本。

于 2012-08-27T09:34:30.140 回答
2

正如其他答案已经表明您的记录大小不正确,可能是由于打包语句(winapi 中的结构通常不打包而是对齐)。

我的建议是使用 Jedi Windows ApiLib(在这种情况下为 JwaNtSecApi),因为它通常具有最佳且经过时间证明的转换。

于 2012-08-27T11:23:31.670 回答