编程语言
首页 > 编程语言> > c#-将字符缓冲区从.NET传递到COM并重新更新

c#-将字符缓冲区从.NET传递到COM并重新更新

作者:互联网

我有以下从C#调用的COM方法,该方法在提供的缓冲区pchText中返回一个字符串(不一定以零结尾),并在pcch中复制字符数:

HRESULT Next([in, out] long* pcch, [out, size_is(*pcch)] OLECHAR* pchText);

如何为互操作定义C#签名?

到目前为止,我已经尝试过了:

void Next(ref int pcch,
    [MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 0)]
    System.Text.StringBuilder pchText);

它似乎可以工作,但是我不确定SizeParamIndex是否对StringBuilder有影响.

解决方法:

好吧,正确调用当然是一个困难的函数.您的声明大致上是可以的,您只需要应用[PreserveSig]属性并将返回值类型设置为int,就可以发现一个S_FALSE返回值,该值指示没有下一个元素.

困难在于必须预先猜测要传递多少StringBuilder.本机代码获取指向GC堆的原始指针,指向构建器缓冲区,因此事故非常致命.您必须预先猜测构建器的适当容量,并将其作为初始pcch参数传递.

函数返回后,编组器确实注意SizeParamIndex.它将仅复制ppch指示的字符.如果由于某种原因写入的内容超出了缓冲区的容量,则该程序将立即终止,并显示ExecutionEngineException,因为这表明GC堆已损坏.

请注意,如果您猜测容量太低,则不一定能发现这一点.当函数仅复制适合的多个字符且不返回错误代码时,您可能会得到截断的字符串.找出是否存在问题的最佳方法是仅对其进行测试并有意通过一个小型构建器.注意返回值.

值得一提的是,该功能签名击中了COM早期的一种常见攻击,实际上是通过OLECHAR *返回二进制数据而不是文本.有一个很强的提示,因为不能保证该字符串以零结尾.在.NET中,这并不能很好地完成,当对字符串进行规范化时,数据将被破坏.当数据碰巧匹配utf-16代理字符之一时,使程序崩溃.如果是这种情况,则需要short []而不是StringBuilder.

标签:com,com-interop,c,net
来源: https://codeday.me/bug/20191029/1958959.html