Markan
Markan

Reputation: 21

P/Invoke errors only on Windows Server 2008 R2 x64

I have ASP.NET MVC3 application that uses some methods from crypt32.dll using P/Invoke. Everything works fine on Windows XP, Windows 7 (both 32bit and 64bit), Windows Server 2003 (also 32bit and 64bit) but my troubles started when I tried setting the application on Windows Server 2008 R2 x64. Further, when I try to run the project from VS2010 on that same machine, it works fine. Server has latest updates installed, IIS 7.5 and all the other stuff needed.

Application is not giving any error, but just results in "Page not available" or sometimes Error 503 (stopping the application pool).

Here is what I get in Event Viewer:

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

Application pool is used just by this application, it is set to enable 32bit applications, integrated pipeline and correct .Net version. Project is built for x86 platform (even I tried every other possibility) and I even tried to add required DLLs to project, setting Copy to Output Directory to Copy Always, but nothing helps.

Using logs I managed to figure out it breaks at:

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

DLLImport code:

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

Any ideas what might cause the problem?

Here is the rest of the code:

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());
}

Upvotes: 0

Views: 1361

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131393

I just noticed the Exception code: 0xc0000005 in the log. That's an access violation which means that the pointer you provide to the method refers to an invalid address. The pointer itself may be null or zero, or the CERT_CONTEXT structure it should point to has invalid data.

This has nothing to do with ASP.NET or IIS, there is an error in the code or the data. Perhaps the certificate is wrong to begin with.

Upvotes: 2

Related Questions