Delphi调用WinRT的get_Thumbprint触发访问违规,是否遗漏关键步骤?
Delphi调用WinRT get_Thumbprint触发访问违规的解决方法
问题根源
你遇到的访问违规,核心是WinRT中返回字节数组的get_*方法遵循双调用规范:必须先调用方法获取实际所需的字节长度,再分配对应缓冲区获取数据。你的代码直接传入固定长度的缓冲区,跳过了获取长度的步骤,导致内存访问越界。此外,Delphi的WinRT绑定已将这类接口方法封装为更易用的Delphi属性,手动调用底层接口方法容易出错。
正确解决方案
方法1:使用Delphi封装的属性(推荐)
TCertificates_CertificateQuery类已将get_Thumbprint和put_Thumbprint封装为Thumbprint属性,直接通过属性读写即可,无需手动调用底层接口:
program Sample; uses System.SysUtils, System.Classes, System.Win.WinRT, System.NetEncoding, Winapi.Windows, Winapi.ActiveX, Winapi.WinRT.Utils, Winapi.Winrt, Winapi.CommonTypes, Winapi.Security.Cryptography; begin CoInitialize(nil); try var q := TCertificates_CertificateQuery.Create; try // 设置Thumbprint var B := TBytes.Create(1, 2, 3, 4); q.Thumbprint := B; // 获取Thumbprint var D := q.Thumbprint; // 此处可直接使用D数组 finally q.Free; end; finally CoUninitialize; end; end.
方法2:手动调用底层接口的正确流程
如果必须手动调用get_Thumbprint,严格遵循WinRT双调用规则:
- 第一次调用:传入
resultSize=0和resultValue=nil,获取实际需要的字节长度 - 根据获取到的长度分配缓冲区,第二次调用传入正确的长度和缓冲区指针
假设你的Delphi接口声明包含resultSizeNeeded输出参数,示例代码如下:
var NeededSize: Cardinal; var h: HRESULT; // 第一次调用获取所需长度 h := q.get_Thumbprint(0, nil, @NeededSize); if Succeeded(h) and (NeededSize > 0) then begin SetLength(D, NeededSize); // 第二次调用获取实际数据 h := q.get_Thumbprint(NeededSize, @D[0], nil); end;
补充说明
Delphi的WinRT绑定会自动处理WinRT接口的内存管理、参数转换等细节,直接使用封装后的类属性是最安全的方式,能避免手动调用底层接口时的内存访问错误。
内容的提问来源于stack exchange,提问作者Chau Chee Yang
相关产品推荐
相关产品推荐

