在调试和释放模式下调用64位API函数之间的区别

时间:2012-08-27 09:00:03

标签: delphi 32bit-64bit

使用lsaapi.pas unit将32位代码转换为64位代码时出现问题 使用小的PCharPAnsiChar更正。

以下代码适用于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;

3 个答案:

答案 0 :(得分:8)

声明该lsaapi单位中的所有记录都已打包。 Windows API头文件不使用压缩的结构。通过删除所有packed修饰符来修复它。如果进行了更改,则您的功能在32位和64位目标中都会成功。

对于它的价值,您的代码实际上在调用LsaOpenPolicy时失败了。打包记录SizeOf(Attributes)返回40.正确的大小为48,这是您删除packed修饰符时获得的值。

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

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

答案 1 :(得分:2)

您的错误最有可能在调试和运行时发生,但在运行时被吞噬。我已经在各种开发环境中的x86和x64世界中出现了几次。

所以:

  • 确保将正确的文件加载到您的处理空间。
  • 确保对齐和打包是正确的,因为在64位世界中存在其他重要的情况

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

起初我认为这是因为你不能从64位进程调用32位DLL(与你有thunking between 16-bit and 32-bit and vice versa的16/32位情况不同,没有这样的thunking 32/64位案例)。

然后我发现有two versions of the advapi32.dll:一个32位和一个64位。

答案 2 :(得分:2)

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

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