使用lsaapi.pas unit
将32位代码转换为64位代码时出现问题
使用小的PChar
到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;
答案 0 :(得分:8)
声明该lsaapi
单位中的所有记录都已打包。 Windows API头文件不使用压缩的结构。通过删除所有packed
修饰符来修复它。如果进行了更改,则您的功能在32位和64位目标中都会成功。
对于它的价值,您的代码实际上在调用LsaOpenPolicy
时失败了。打包记录SizeOf(Attributes)
返回40.正确的大小为48,这是您删除packed
修饰符时获得的值。
调试此类事情的最简单方法是安装Visual Studio的副本,以便比较等效的C ++代码。
我认为不正确的记录声明是该单元的主要问题。可能还有其他人,但那就像拇指一样突出。
答案 1 :(得分:2)
您的错误最有可能在调试和运行时发生,但在运行时被吞噬。我已经在各种开发环境中的x86和x64世界中出现了几次。
所以:
如果你让它发挥作用,请通知科林你得到他的单位的新版本。
起初我认为这是因为你不能从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),因为它通常具有最佳且经过时间验证的转换。