0

我有 ASP.NET MVC3 应用程序,它使用 crypt32.dll 中的一些方法,使用 P/Invoke。在 Windows XP、Windows 7(32 位和 64 位)、Windows Server 2003(也是 32 位和 64 位)上一切正常,但是当我尝试在 Windows Server 2008 R2 x64 上设置应用程序时,我的麻烦就开始了。此外,当我尝试在同一台机器上从 VS2010 运行项目时,它工作正常。服务器已安装最新更新、IIS 7.5 和所有其他所需的东西。

应用程序没有给出任何错误,而只是导致“页面不可用”或有时出现错误 503(停止应用程序池)。

这是我在事件查看器中得到的:

Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7a5f8
Faulting module name: CRYPT32.dll, version: 6.1.7601.17514, time stamp: 0x4ce7b841
Exception code: 0xc0000005
Fault offset: 0x00010cf3
Faulting process id: 0xc4c
Faulting application start time: 0x01cd3f0fac5721fb
Faulting application path: C:\Windows\SysWOW64\inetsrv\w3wp.exe
Faulting module path: C:\Windows\syswow64\CRYPT32.dll
Report Id: ee39118a-ab02-11e1-8d06-000c297e9eda

应用程序池仅由该应用程序使用,它设置为启用 32 位应用程序、集成管道和正确的 .Net 版本。项目是为 x86 平台构建的(即使我尝试了所有其他可能性),我什至尝试将所需的 DLL 添加到项目中,将复制到输出目录设置为始终复制,但没有任何帮助。

使用日志我设法弄清楚它在以下位置中断:

if (!CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, IntPtr.Zero, ref cbData))
{
    Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}

DLL导入代码:

[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CertGetCertificateContextProperty(
    IntPtr pCertContext,
    uint dwPropId,
    IntPtr pvData,
    ref uint pcbData
);

任何想法可能导致问题?

这是其余的代码:

CERT_NAME_BLOB cnbCertificate;
CRYPT_DATA_BLOB certificate;
IntPtr hCertStore = IntPtr.Zero;
IntPtr pCertContext = IntPtr.Zero;
uint cbData = 0;

byte[] encoded = Encode(cert.Subject);

GCHandle pinnedArray = new GCHandle();
pinnedArray = GCHandle.Alloc(cBuffer, GCHandleType.Pinned);

certificate.cbData = cBuffer.Length;
certificate.pbData = pinnedArray.AddrOfPinnedObject();
pinnedArray.Free();
hCertStore = PFXImportCertStore(ref certificate, password, CRYPT_USER_KEYSET | CRYPT_EXPORTABLE);
cnbCertificate.cbData = (uint)encoded.Length;
GCHandle h1;

if (hCertStore != IntPtr.Zero)
{
    try
    {
        h1 = GCHandle.Alloc(encoded, GCHandleType.Pinned);
        cnbCertificate.pbData = h1.AddrOfPinnedObject();

        dataHandle = GCHandle.Alloc(cnbCertificate, GCHandleType.Pinned);
        pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, dataHandle.AddrOfPinnedObject(), IntPtr.Zero);
        if (h1 != null) h1.Free();
    }
    catch (Exception exp)
    {
        log.Error("Marshall error1: " + exp.Message + " " + Marshal.GetLastWin32Error());
    }
    finally
    {
    }
}

if (!CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, IntPtr.Zero, ref cbData))
{
    Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
4

1 回答 1

2

我刚刚注意到日志中的异常代码:0xc0000005。这是访问冲突,这意味着您提供给该方法的指针引用了无效地址。指针本身可能为空或零,或者它应该指向的CERT_CONTEXT结构包含无效数据。

这与 ASP.NET 或 IIS 无关,代码或数据有错误。也许证书一开始就是错误的。

于 2012-06-01T11:35:09.587 回答