如何手动将BSTR从.NET转换为COM?
我正在尝试将存储在SecureString中的密码从我的.NET应用程序传递到COM对象的方法。我想避免将SecureString转换为String,因为这不是使用SecureString的正确方法。密码会以明文形式保存在托管内存中,并在那里长时间存在。相反,我正在尝试以正确的方式进行转换:将其转换为未托管内存中的BSTR,将其传递给COM方法,然后使用Marshal.ZeroFreeBSTR清除BSTR,以便密码仅暴露一段有限的时间。
这个方法是可行的 - 但我必须将
我正在尝试将存储在SecureString中的密码从我的.NET应用程序传递到COM对象的方法。我想避免将SecureString转换为String,因为这不是使用SecureString的正确方法。密码会以明文形式保存在托管内存中,并在那里长时间存在。相反,我正在尝试以正确的方式进行转换:将其转换为未托管内存中的BSTR,将其传递给COM方法,然后使用Marshal.ZeroFreeBSTR清除BSTR,以便密码仅暴露一段有限的时间。
TblImp.exe生成的用于此COM对象的.NET接口期望将密码作为String
传递,然后将其封送到BSTR。这不是我想要的,因为它意味着我必须将我的密码放在String
中,所以根据调用COM的精益方法,我创建了自己的接口,以便我可以自定义它并摆脱String
。以下是我开始使用的内容:
[ComImport, Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ITheComObjectDispatcher
{ // +--- the naughty string
[return: MarshalAs(UnmanagedType.BStr)] // |
[DispId(1)] // V
string TheMethod([In, MarshalAs(UnmanagedType.BStr)] string secret);
}
[ComImport, Guid("YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY")]
public class TheComObject
{}
这个方法是可行的 - 但我必须将
SecureString
转换为 String
才能使用它,像这样:private string UseTheMethod(SecureString secret)
{
var comObject = new TheComObject();
var comObjectDispatcher = (ITheComObjectDispatcher)comObject;
var secretAsString = NaughtilyConvertSecureStringToString(secret);
return comObjectDispatcher.TheMethod(secretAsString);
}
private static string NaughtilyConvertSecureStringToString(SecureString value)
{
var valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
try
{
return Marshal.PtrToStringUni(valuePtr); // now the secret is in managed memory :(
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
}
}
相反,我希望使用类似于Marshal.SecureStringToBSTR
的方法并跳过转换为String
。我已经尝试过这个...
[return: MarshalAs(UnmanagedType.BStr)]
[DispId(1)]
string TheMethod([In, MarshalAs(UnmanagedType.BStr)] IntPtr secret);
...和这个...
[return: MarshalAs(UnmanagedType.BStr)]
[DispId(1)]
string TheMethod([In] IntPtr secret);
...使用此调用代码...
private string UseTheMethod(SecureString secret)
{
var comObject = new TheComObject();
var comObjectDispatcher = (ITheComObjectDispatcher)comObject;
var secretPtr = Marshal.SecureStringToBSTR(secret);
try
{
return comObjectDispatcher.TheMethod(secretPtr);
}
finally
{
Marshal.ZeroFreeBSTR(secretPtr);
}
}
...但它不起作用:错误的值被传递给了COM方法。它没有出现错误,只是给出了不同的结果。
问题:
- 我可以像这样直接将BSTR作为IntPtr传递吗?我做错了什么?
- 有没有一种调试封送过程以查看传递的值的方法?