CredMarshalCredential (advapi32)
Last changed: -63.64.86.1

.
Summary
I've used this function to pass a certificate I've read from a smart card as an argument to LogonUser. That function cannot take a certificate so one has to pass the certificate's marshaled SHA-1 hash code in the lpszUsername parameter.

C# Signature:

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
    static extern bool CredMarshalCredential(int credType,
                    IntPtr credential,
                    // we need to get this as a pointer because we'll have
                    // to release it later on calling CredFree().
                    out IntPtr marshaledCredential);

VB Signature:

Declare Function CredMarshalCredential Lib "advapi32.dll" (TODO) As TODO

User-Defined Types:

    [StructLayout(LayoutKind.Sequential)]
    internal struct CERT_CREDENTIAL_INFO
    {
        public uint cbSize;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
        public byte[] rgbHashOfCert;
    }

    internal static int CertCredential = 1;

Alternative Managed API:

Do you know one? Please contribute it!

Notes:

None.

Tips & Tricks:

One needs to free the string returned in the "out IntPtr marshaledCredential" parameter!

Sample Code:

        NativeMethods.CERT_CREDENTIAL_INFO certInfo =
            new NativeMethods.CERT_CREDENTIAL_INFO();
        certInfo.cbSize = (uint)Marshal.SizeOf(typeof(NativeMethods.CERT_CREDENTIAL_INFO));
        // certCredential.Certificate is an instance of the X509Certificate2 class.
        certInfo.rgbHashOfCert = certCredential.Certificate.GetCertHash();

        int size = Marshal.SizeOf(certInfo);
        IntPtr pCertInfo = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(certInfo, pCertInfo, false);

        IntPtr marshaledCredential = IntPtr.Zero;
        bool result =
            NativeMethods.CredMarshalCredential(NativeMethods.CertCredential,
                            pCertInfo,
                            out marshaledCredential);
        if (result)
        {
            // we need to do this here, before we free marshaledCredential
            domainName = String.Empty;
            userName = Marshal.PtrToStringUni(marshaledCredential);
            password = certCredential.CardPin;
        }

        Marshal.FreeHGlobal(pCertInfo);
        if (marshaledCredential != IntPtr.Zero)
            NativeMethods.CredFree(marshaledCredential);

Documentation