当从.net应用程序通过IMSAdminBase传递字节数组编译到AnyCPU时,inetinfo.exe内部的访问冲突



考虑以下一段。net代码:

byte[] hash = { 0x60, 0x2B, 0x45, 0x9D, 0xA0, 0x6D, 0xD5, 0x02, 0x43, 0x86, 0xC1, 0xBA, 0x6B, 0x14, 0x37, 0x88, 0x63, 0x08, 0x39, 0xA0 };
using (var adminBase = TemporaryComObject.Wrap(new MSAdminBase_W()))
using (var ptrHash = new AllocHGlobal(hash))
{
  using (var siteKey = new AdminBaseKey(adminBase.Com, adminBase.Com.OpenKey(METADATA_MASTER_ROOT_HANDLE, "/LM/W3SVC/1", METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10000)))
  {
    var record = new METADATA_RECORD
    {
      dwMDIdentifier = 5506,
      dwMDAttributes = METADATA_INHERIT,
      dwMDUserType = IIS_MD_UT_SERVER,
      dwMDDataType = BINARY_METADATA,
      pbMDData = ptrHash.Buffer,
      dwMDDataLen = hash.Length
    };
    adminBase.Com.SetData(siteKey.Handle, string.Empty, ref record);
  }
  adminBase.Com.SaveData();
}

这段代码试图从。net设置SSLCertHash IIS6元数据库属性。

如果.NET应用程序是为x86编译的,则它运行得非常好,这意味着在相应的.csproj文件中可以找到以下行:

<PlatformTarget>x86</PlatformTarget>

然而,当我省略这一行并为AnyCPU编译时,就会出现龙。也就是说,发生的情况是inetinfo.exe因访问冲突而崩溃。以下是windbg输出窗口的相关快照:

(24f0.cbc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
msvcrt!memmove+0x1e5:
000007fe`fe371111 8b040a          mov     eax,dword ptr [rdx+rcx] ds:00000000`00000010=????????
0:001> k
Child-SP          RetAddr           Call Site
00000000`008ee1f8 000007fe`f5a64e71 msvcrt!memmove+0x1e5
00000000`008ee200 000007fe`f5a64da0 abocomp!PROPERTY_ENTRY::Create+0x79
00000000`008ee230 000007fe`f5a5c21b abocomp!PROPERTY_BAG::SetData+0xbc
00000000`008ee270 000007fe`f5a6088a abocomp!ABO_NODE::SetData+0xa3
00000000`008ee2a0 000007fe`f5a9456f abocomp!ABO_WRAPPER::SetData+0x1ca
00000000`008ee580 000007fe`f5ad3e54 COADMIN!CADMCOMW::SetData+0x127
00000000`008ee630 000007fe`fdfd51d0 ADMWPROX!IMSAdminBaseW_R_SetData_Thunk+0xb4
00000000`008ee6b0 000007fe`fdedf16e RPCRT4!NdrStubCall2+0xa36
00000000`008eecd0 000007fe`fdee0ccd ole32!CStdStubBuffer_Invoke+0x8b
00000000`008eed00 000007fe`fdee0c43 ole32!SyncStubInvoke+0x5d
00000000`008eed70 000007fe`fdd9a4f0 ole32!StubInvoke+0xdb
00000000`008eee20 000007fe`fdee14d6 ole32!CCtxComChnl::ContextInvoke+0x190
00000000`008eefb0 000007fe`fdee122b ole32!AppInvoke+0xc2
00000000`008ef020 000007fe`fdedfd6d ole32!ComInvokeWithLockAndIPID+0x52b
00000000`008ef1b0 000007fe`fdfa50f4 ole32!ThreadInvoke+0x30d
00000000`008ef250 000007fe`fdfa4f56 RPCRT4!DispatchToStubInCNoAvrf+0x14
00000000`008ef280 000007fe`fdfa775b RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x146
00000000`008ef3a0 000007fe`fdfa769b RPCRT4!RPC_INTERFACE::DispatchToStub+0x9b
00000000`008ef3e0 000007fe`fdfa7632 RPCRT4!RPC_INTERFACE::DispatchToStubWithObject+0x5b
00000000`008ef460 000007fe`fdfa532d RPCRT4!LRPC_SCALL::DispatchRequest+0x422
00000000`008ef540 000007fe`fdfc2e7f RPCRT4!LRPC_SCALL::HandleRequest+0x20d
00000000`008ef670 000007fe`fdfc2a35 RPCRT4!LRPC_ADDRESS::ProcessIO+0x3bf
00000000`008ef7b0 00000000`7753b68b RPCRT4!LrpcIoComplete+0xa5
00000000`008ef840 00000000`7753feff ntdll!TppAlpcpExecuteCallback+0x26b
00000000`008ef8d0 00000000`76e5652d ntdll!TppWorkerThread+0x3f8
00000000`008efbd0 00000000`7754c521 kernel32!BaseThreadInitThunk+0xd
00000000`008efc00 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
0:001> g
(24f0.cbc): Access violation - code c0000005 (!!! second chance !!!)
msvcrt!memmove+0x1e5:
000007fe`fe371111 8b040a          mov     eax,dword ptr [rdx+rcx] ds:00000000`00000010=????????
我完全不知道发生了什么事。你呢?

  1. 我正在运行Windows 7 64位,IIS 7.5与IIS6元数据库启用
  2. 我不使用System.DirectoryServices来修改SSLCertHash元数据库属性,因为这是不可能的- http://support.microsoft.com/kb/313624解释了它。本文包含有关该主题的更多有用信息。
  3. TemporaryComObject, AllocHGlobal, AdminBaseKey类型确保COM对象,非托管内存和管理基键被属性释放/关闭。
  4. MSAdminBase COM对象的互操作程序集是使用此处描述的技术的一种变体- http://www.moserware.com/2009/04/using-obscure-windows-com-apis-in-net.html获得的。只是我没有重新创建互操作代码,而是重新创建相应的IDL文件。然后我用MIDL编译它以生成相应的TLB文件,我将该文件传递给TlbImp以生成互操作程序集。

METADATA_RECORD类型的C定义在SDK的mddefw.h文件中找到:

typedef struct _METADATA_RECORD
{
  DWORD dwMDIdentifier;
  DWORD dwMDAttributes;
  DWORD dwMDUserType;
  DWORD dwMDDataType;
  DWORD dwMDDataLen;
  unsigned char *pbMDData;
  DWORD dwMDDataTag;
} METADATA_RECORD;

在我生成的互操作程序集中,类型声明如下:

[StructLayout(LayoutKind.Sequential, Pack=4), ComConversionLoss]
public struct METADATA_RECORD
{
    public int dwMDIdentifier;
    public int dwMDAttributes;
    public int dwMDUserType;
    public int dwMDDataType;
    public int dwMDDataLen;
    [ComConversionLoss]
    public IntPtr pbMDData;
    public int dwMDDataTag;
}

注意ComConversionLoss属性的存在。我不知道它是否重要,但是当我创建互操作程序集时,我得到了以下警告:

TlbImp : warning TI3016: The type library importer could not convert the signature for the member 'MSAdminBaseLib.METADATA_RECORD.pbMDData'. [C:WorkIISCertObjSimpleNCServerSecurity.csproj]

我的另一篇文章(尚未回复)确切地处理了这个问题。

非常感谢。

编辑

我有一种感觉,这与StructLayout.Pack = 4有关。我还在学习如何使TlbImp不插入它…

EDIT2

事实上,这就是问题所在。事实证明,TlbImp产生的输出需要进一步调整。我必须用反射器把它拆开。. NET并删除显式的Pack语句。

我发现了问题——Pack = 4确实解决了这个问题。

最新更新