<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Decrypt my World : P/Invoke</title><link>http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx</link><description>Tags: P/Invoke</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>How to call InternetErrorDlg to deal with certificate issues on SSL connections (C#)</title><link>http://blogs.msdn.com/alejacma/archive/2009/06/23/how-to-call-interneterrordlg-to-deal-with-certificate-issues-on-ssl-connections-c.aspx</link><pubDate>Tue, 23 Jun 2009 12:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9799146</guid><dc:creator>alejacma</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9799146.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9799146</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;The following &lt;STRONG&gt;C# sample&lt;/STRONG&gt; shows how to call &lt;STRONG&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa385331(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa385331(VS.85).aspx"&gt;WinInet&lt;/A&gt; APIs&lt;/STRONG&gt; to make an &lt;STRONG&gt;SSL request&lt;/STRONG&gt; and deal with possible &lt;STRONG&gt;certificate issues&lt;/STRONG&gt; with &lt;A href="http://msdn.microsoft.com/en-us/library/aa384694.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa384694.aspx"&gt;InternetErrorDlg&lt;/A&gt; (which will show the same standard dialogs that Internet Explorer shows when something is wrong with server or client certs): &lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Net;

namespace WindowsApplication1
{
    class Tester
    {
        public static string &lt;STRONG&gt;TestSSLRequest&lt;/STRONG&gt;(IntPtr hWnd, string lpszServerName, short nServerPort, string lpszUrl)
        {
            // Variables
            IntPtr hInternet = IntPtr.Zero;
            string lpszAgent;
            int dwAccessType = 0;
            string lpszProxyName;
            string lpszProxyBypass;
            int dwFlags = 0;
            string lpszUserName;
            string lpszPassword;
            int dwService = 0;
            IntPtr dwContext = IntPtr.Zero;
            IntPtr hConnect = IntPtr.Zero;
            string lpszVerb;
            string lpszObjectName;
            string lpszVersion;
            string lpszReferer;
            IntPtr lplpszAcceptTypes = IntPtr.Zero;
            IntPtr hRequest = IntPtr.Zero;
            IntPtr lpOptional = IntPtr.Zero;
            int dwError = 0;
            string lpszHeaders;
            int dwHeadersLength = 0;
            int dwOptionalLength = 0;
            IntPtr lppvData = IntPtr.Zero;
            int dwNumberOfBytesAvailable = 0;
            IntPtr lpBuffer = IntPtr.Zero;
            int dwOption = 0;
            ulong ulOptionMask = 0;
            int dwBufferLength = 0;
            int dwNumberOfBytesToRead = 0;
            int dwNumberOfBytesRead = 0;

            bool bResult = false;
            int iResult = 0;

            // Let's begin!!!
            try
            {
                // Initializes the app's use of the WinINet functions
                lpszAgent = "AlejaCMa";
                dwAccessType = Win32API.INTERNET_OPEN_TYPE_PRECONFIG;
                lpszProxyName = null;
                lpszProxyBypass = null;
                dwFlags = 0;
                hInternet = Win32API.&lt;STRONG&gt;InternetOpen&lt;/STRONG&gt;(lpszAgent, dwAccessType, lpszProxyName, lpszProxyBypass, dwFlags);
                if (hInternet.Equals(IntPtr.Zero))
                {
                    throw new Exception("InternetOpen: Error #" + Marshal.GetLastWin32Error().ToString());
                }

                // Opens HTTP session for the site
                lpszUserName = null;
                lpszPassword = null;
                dwService = Win32API.&lt;STRONG&gt;INTERNET_SERVICE_HTTP&lt;/STRONG&gt;;
                dwFlags = 0;
                dwContext = IntPtr.Zero;
                hConnect = Win32API.&lt;STRONG&gt;InternetConnect&lt;/STRONG&gt;(hInternet, lpszServerName, nServerPort, lpszUserName, lpszPassword, dwService, dwFlags, dwContext);
                if (hConnect.Equals(IntPtr.Zero))
                {
                    throw new Exception("InternetConnect: Error #" + Marshal.GetLastWin32Error().ToString());
                }

                // Create HTTP request handle
                lpszVerb = "&lt;STRONG&gt;GET&lt;/STRONG&gt;";
                lpszObjectName = lpszUrl;
                lpszVersion = null;
                lpszReferer = null;
                lplpszAcceptTypes = IntPtr.Zero;
                dwFlags = Win32API.&lt;STRONG&gt;INTERNET_FLAG_SECURE&lt;/STRONG&gt;;
                dwContext = IntPtr.Zero;
                hRequest = Win32API.&lt;STRONG&gt;HttpOpenRequest&lt;/STRONG&gt;(hConnect, lpszVerb, lpszObjectName, lpszVersion, lpszReferer, lplpszAcceptTypes, dwFlags, dwContext);
                if (hRequest.Equals(IntPtr.Zero))
                {
                    throw new Exception("HttpOpenRequest: Error #" + Marshal.GetLastWin32Error().ToString());
                }
                
                // Configure request to get combined cert errors
                dwOption = Win32API.&lt;STRONG&gt;INTERNET_OPTION_ERROR_MASK&lt;/STRONG&gt;;
                ulOptionMask = Win32API.&lt;STRONG&gt;INTERNET_ERROR_MASK_COMBINED_SEC_CERT&lt;/STRONG&gt;;
                dwBufferLength = Marshal.SizeOf(lpBuffer);
                bResult = Win32API.&lt;STRONG&gt;InternetSetOption&lt;/STRONG&gt;(hRequest, dwOption, ref ulOptionMask, dwBufferLength);
                if (!bResult)
                {
                    throw new Exception("InternetSetOption: Error #" + Marshal.GetLastWin32Error().ToString());
                }

                do
                {
                    // Send request to the server
                    lpszHeaders = null;
                    dwHeadersLength = 0;
                    lpOptional = IntPtr.Zero;
                    dwOptionalLength = 0;
                    bResult = Win32API.&lt;STRONG&gt;HttpSendRequest&lt;/STRONG&gt;(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);

                    if (!bResult)
                    {
                        // Deal with possible errors
                        switch (Marshal.GetLastWin32Error())
                        {
                            case Win32API.&lt;STRONG&gt;ERROR_INTERNET_SEC_CERT_ERRORS&lt;/STRONG&gt;:
                                dwError = Win32API.&lt;STRONG&gt;ERROR_INTERNET_SEC_CERT_ERRORS&lt;/STRONG&gt;;
                                break;
                            case Win32API.ERROR_INTERNET_INVALID_CA:
                                dwError = Win32API.ERROR_INTERNET_INVALID_CA;
                                break;
                            case Win32API.ERROR_INTERNET_SEC_CERT_CN_INVALID:
                                dwError = Win32API.ERROR_INTERNET_SEC_CERT_CN_INVALID;
                                break;
                            case Win32API.ERROR_INTERNET_SEC_CERT_DATE_INVALID:
                                dwError = Win32API.ERROR_INTERNET_SEC_CERT_DATE_INVALID;
                                break;
                            case Win32API.ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
                                dwError = Win32API.ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED;
                                break;
                            default:
                                // Unknown error
                                throw new Exception("HttpSendRequest: Error #" + Marshal.GetLastWin32Error().ToString());
                        }

                        // Display cert error dialog box
                        dwFlags = Win32API.&lt;STRONG&gt;FLAGS_ERROR_UI_FLAGS_GENERATE_DATA&lt;/STRONG&gt; + Win32API.&lt;STRONG&gt;FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS&lt;/STRONG&gt;;
                        lppvData = IntPtr.Zero;
                        iResult = Win32API.&lt;STRONG&gt;InternetErrorDlg&lt;/STRONG&gt;(hWnd, hRequest, dwError, dwFlags, lppvData);
                        switch (iResult)
                        {
                            case Win32API.ERROR_SUCCESS:
                                break;
                            case Win32API.ERROR_CANCELLED:
                                throw new Exception("InternetErrorDlg: The function was canceled by the user");
                            case Win32API.ERROR_INTERNET_FORCE_RETRY:
                                throw new Exception("InternetErrorDlg: Function needs to redo its request. In the case of authentication this indicates that the user clicked the OK button.");
                            case Win32API.ERROR_INVALID_HANDLE:
                                throw new Exception("InternetErrorDlg: The handle to the parent window is invalid");
                            default:
                                throw new Exception("InternetErrorDlg: Error #" + iResult.ToString());
                        }
                    }
                } while (!bResult);

                // Determine the amount of data available
                dwNumberOfBytesAvailable = 0;
                dwFlags = 0;
                dwContext = IntPtr.Zero;
                bResult = Win32API.&lt;STRONG&gt;InternetQueryDataAvailable&lt;/STRONG&gt;(hRequest, ref dwNumberOfBytesAvailable, dwFlags, dwContext);
                if (!bResult)
                {
                    throw new Exception("InternetQueryDataAvailable: Error #" + Marshal.GetLastWin32Error().ToString());
                }

                // Read data
                lpBuffer = Marshal.&lt;STRONG&gt;AllocHGlobal&lt;/STRONG&gt;(dwNumberOfBytesAvailable);
                dwNumberOfBytesToRead = dwNumberOfBytesAvailable;
                dwNumberOfBytesRead = 0;
                bResult = Win32API.&lt;STRONG&gt;InternetReadFile&lt;/STRONG&gt;(hRequest, lpBuffer, dwNumberOfBytesToRead, ref dwNumberOfBytesRead);
                if (!bResult)
                {
                    throw new Exception("InternetReadFile: Error #" + Marshal.GetLastWin32Error().ToString());
                }
               
                // Everything went well. Return data
                return &lt;STRONG&gt;Marshal.PtrToStringAnsi&lt;/STRONG&gt;(lpBuffer, dwNumberOfBytesRead);
            }
            catch (Exception ex)
            {
                // Show error
                MessageBox.Show("Exception: " + ex.Message);
                return "";
            }
            finally
            {
                // Clean up
                if (!lpBuffer.Equals(IntPtr.Zero))
                {
                    Marshal.&lt;STRONG&gt;FreeHGlobal&lt;/STRONG&gt;(lpBuffer);
                }
                if (!hInternet.Equals(IntPtr.Zero))
                {
                    Win32API.&lt;STRONG&gt;InternetCloseHandle&lt;/STRONG&gt;(hInternet);
                }
                if (!hConnect.Equals(IntPtr.Zero))
                {
                    Win32API.InternetCloseHandle(hConnect);
                }
                if (!hRequest.Equals(IntPtr.Zero))
                {
                    Win32API.InternetCloseHandle(hRequest);
                }
            }
        }
    }
}

&lt;/PRE&gt;
&lt;P&gt;These are the &lt;STRONG&gt;P/Invoke declarations&lt;/STRONG&gt; of the APIs that I've used before:&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace WindowsApplication1
{
    class Win32API
    {
        // #define INTERNET_OPEN_TYPE_DIRECT                       1 
        public const int INTERNET_OPEN_TYPE_DIRECT = 1;

        //#define INTERNET_OPEN_TYPE_PRECONFIG                    0
        public const int INTERNET_OPEN_TYPE_PRECONFIG = 0;

        // #define INTERNET_SERVICE_HTTP   3
        public const int INTERNET_SERVICE_HTTP = 3;

        // #define INTERNET_FLAG_SECURE            0x00800000 
        public const int INTERNET_FLAG_SECURE = 0x00800000;

        // #define INTERNET_OPTION_SECURITY_CERTIFICATE    35
        public const int INTERNET_OPTION_SECURITY_CERTIFICATE = 35;

        // #define ERROR_SUCCESS                    0L
        public const int ERROR_SUCCESS = 0;

        // #define ERROR_INVALID_HANDLE             6L 
        public const int ERROR_INVALID_HANDLE = 6;

        // #define ERROR_INSUFFICIENT_BUFFER        122L  
        public const int ERROR_INSUFFICIENT_BUFFER = 122;
        
        // #define ERROR_CANCELLED                  1223L 
        public const int ERROR_CANCELLED = 1223;
        
        // #define INTERNET_OPTION_ERROR_MASK       62
        public const int INTERNET_OPTION_ERROR_MASK = 62;

        // #define INTERNET_ERROR_MASK_COMBINED_SEC_CERT       0x2
        public const ulong INTERNET_ERROR_MASK_COMBINED_SEC_CERT = 0x2;

        // #define INTERNET_ERROR_BASE                     12000
        public const int INTERNET_ERROR_BASE = 12000;

        // #define ERROR_INTERNET_FORCE_RETRY              (INTERNET_ERROR_BASE + 32)
        public const int ERROR_INTERNET_FORCE_RETRY = INTERNET_ERROR_BASE + 32;

        // #define ERROR_INTERNET_SEC_CERT_DATE_INVALID              (INTERNET_ERROR_BASE + 37)
        public const int ERROR_INTERNET_SEC_CERT_DATE_INVALID = INTERNET_ERROR_BASE + 37;

        // #define ERROR_INTERNET_SEC_CERT_CN_INVALID              (INTERNET_ERROR_BASE + 38)
        public const int ERROR_INTERNET_SEC_CERT_CN_INVALID = INTERNET_ERROR_BASE + 38;

        // #define ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED              (INTERNET_ERROR_BASE + 44)
        public const int ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED = INTERNET_ERROR_BASE + 44;

        // #define ERROR_INTERNET_SEC_CERT_ERRORS              (INTERNET_ERROR_BASE + 55)
        public const int ERROR_INTERNET_SEC_CERT_ERRORS = INTERNET_ERROR_BASE + 55;       
        

        //#define ERROR_INTERNET_INVALID_CA               (INTERNET_ERROR_BASE + 45)
        public const int ERROR_INTERNET_INVALID_CA = INTERNET_ERROR_BASE + 45;

        // #define FLAGS_ERROR_UI_FILTER_FOR_ERRORS        0x01
        public const int FLAGS_ERROR_UI_FILTER_FOR_ERRORS = 0x01;

        // #define FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS     0x02
        public const int FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS = 0x02;

        // #define FLAGS_ERROR_UI_FLAGS_GENERATE_DATA      0x04
        public const int FLAGS_ERROR_UI_FLAGS_GENERATE_DATA = 0x04;

        // DWORD InternetErrorDlg(
        //  __in     HWND hWnd,
        //  __inout  HINTERNET hRequest,
        //  __in     DWORD dwError,
        //  __in     DWORD dwFlags,
        //  __inout  LPVOID *lppvData
        // );
        [DllImport("wininet.dll", SetLastError = true)]
        public extern static int &lt;STRONG&gt;InternetErrorDlg&lt;/STRONG&gt;
        (
            IntPtr hWnd,
            IntPtr hRequest,
            int dwError,
            int dwFlags,
            IntPtr lppvData
        );

        // BOOL HttpSendRequest(
        //  __in  HINTERNET hRequest,
        //  __in  LPCTSTR lpszHeaders,
        //  __in  DWORD dwHeadersLength,
        //  __in  LPVOID lpOptional,
        //  __in  DWORD dwOptionalLength
        // );
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool &lt;STRONG&gt;HttpSendRequest&lt;/STRONG&gt;
        (
            IntPtr hRequest,
            string lpszHeaders,
            int dwHeadersLength,
            IntPtr lpOptional,
            int dwOptionalLength
        );

        // HINTERNET HttpOpenRequest(
        //  __in  HINTERNET hConnect,
        //  __in  LPCTSTR lpszVerb,
        //  __in  LPCTSTR lpszObjectName,
        //  __in  LPCTSTR lpszVersion,
        //  __in  LPCTSTR lpszReferer,
        //  __in  LPCTSTR *lplpszAcceptTypes,
        //  __in  DWORD dwFlags,
        //  __in  DWORD_PTR dwContext
        // );
        [DllImport("wininet.dll", CharSet=CharSet.Auto, SetLastError = true)]
        public extern static IntPtr &lt;STRONG&gt;HttpOpenRequest&lt;/STRONG&gt;
        (
            IntPtr hConnect,
            string lpszVerb,
            string lpszObjectName,
            string lpszVersion,
            string lpszReferer,
            IntPtr lplpszAcceptTypes,
            int dwFlags,
            IntPtr dwContext
        );

        // HINTERNET InternetConnect(
        //  __in  HINTERNET hInternet,
        //  __in  LPCTSTR lpszServerName,
        //  __in  INTERNET_PORT nServerPort,
        //  __in  LPCTSTR lpszUsername,
        //  __in  LPCTSTR lpszPassword,
        //  __in  DWORD dwService,
        //  __in  DWORD dwFlags,
        //  __in  DWORD_PTR dwContext
        // );
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static IntPtr &lt;STRONG&gt;InternetConnect&lt;/STRONG&gt;
        (
            IntPtr hInternet,
            string lpszServerName,
            short nServerPort,
            string lpszUsername,
            string lpszPassword,
            int dwService,
            int dwFlags,
            IntPtr dwContext
        );

        // BOOL WINAPI InternetCloseHandle(
        //  HINTERNET hInternet
        // );
        [DllImport("wininet.dll", SetLastError = true)]
        public extern static bool &lt;STRONG&gt;InternetCloseHandle&lt;/STRONG&gt;
        (
            IntPtr hInternet
        );

        // HINTERNET InternetOpen(
        //  __in  LPCTSTR lpszAgent,
        //  __in  DWORD dwAccessType,
        //  __in  LPCTSTR lpszProxyName,
        //  __in  LPCTSTR lpszProxyBypass,
        //  __in  DWORD dwFlags
        //);
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static IntPtr &lt;STRONG&gt;InternetOpen&lt;/STRONG&gt;
        (
            string lpszAgent,
            int dwAccessType,
            string lpszProxyName,
            string lpszProxyBypass,
            int dwFlags
        );

        // BOOL InternetReadFile(
        //  __in   HINTERNET hFile,
        //  __out  LPVOID lpBuffer,
        //  __in   DWORD dwNumberOfBytesToRead,
        //  __out  LPDWORD lpdwNumberOfBytesRead
        // );
        [DllImport("wininet.dll", SetLastError = true)]
        public extern static bool &lt;STRONG&gt;InternetReadFile&lt;/STRONG&gt;
        (
            IntPtr hFile,
            IntPtr lpBuffer,
            int dwNumberOfBytesToRead,
            ref int dwNumberOfBytesRead
        );

        // BOOL InternetQueryDataAvailable(
        //  __in   HINTERNET hFile,
        //  __out  LPDWORD lpdwNumberOfBytesAvailable,
        //  __in   DWORD dwFlags,
        //  __in   DWORD_PTR dwContext
        // );
        [DllImport("wininet.dll", SetLastError = true)]
        public extern static bool &lt;STRONG&gt;InternetQueryDataAvailable&lt;/STRONG&gt;
        (
            IntPtr hFile,
            ref int dwNumberOfBytesAvailable,
            int dwFlags,
            IntPtr dwContext
        );

        // BOOL InternetSetOption(
        //  __in  HINTERNET hInternet,
        //  __in  DWORD dwOption,
        //  __in  LPVOID lpBuffer,
        //  __in  DWORD dwBufferLength
        // );
        [DllImport("wininet.dll", SetLastError = true)]
        public extern static bool &lt;STRONG&gt;InternetSetOption&lt;/STRONG&gt;
        (
            IntPtr hInternet,
            int dwOption,
            ref ulong lpBuffer,
            int dwBufferLength
        );
    }
}
&lt;/PRE&gt;
&lt;P&gt;And this is a &lt;STRONG&gt;sample Form&lt;/STRONG&gt; that shows how to use my sample code:&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.textBox1.Text = Tester.&lt;STRONG&gt;TestSSLRequest&lt;/STRONG&gt;(this.Handle, "127.0.0.1", &lt;STRONG&gt;443&lt;/STRONG&gt;, "TEST.ASPX");
        }
    }
}
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9799146" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/WinInet/default.aspx">WinInet</category></item><item><title>How to get information from a CRL (.NET)</title><link>http://blogs.msdn.com/alejacma/archive/2009/04/01/how-to-get-information-from-a-crl-net.aspx</link><pubDate>Wed, 01 Apr 2009 12:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9525923</guid><dc:creator>alejacma</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9525923.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9525923</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;C# sample&lt;/STRONG&gt; uses &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt; to read the info of a &lt;STRONG&gt;CRL&lt;/STRONG&gt; (&lt;STRONG&gt;Certificate Revocation List&lt;/STRONG&gt;)&amp;nbsp;stored in a file:&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GetCRLInfo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void getInfoButton_Click(object sender, EventArgs e)
        {
            // Variables
            //
            Boolean bResult = false;
            IntPtr pvContext = IntPtr.Zero;
            Win32.CRL_CONTEXT CRLContext;
            Win32.CRL_INFO CRLInfo;
            Int32 csz = 0;
            StringBuilder psz = null;
            IntPtr rgCRLEntry = IntPtr.Zero;
            Win32.CRL_ENTRY CRLEntry;
            String strSerialNumber = "";
            IntPtr pByte = IntPtr.Zero;
            Byte bByte = 0;
            IntPtr rgExtension = IntPtr.Zero;
            Win32.CERT_EXTENSION CRLExtension;
            Int32 cbFormat = 0;
            StringBuilder pbFormat = null;
            String strCRLReasonCode = "";
            
            // Clean screen
            //
            issuerTextBox.Text = "";
            revocationListBox.Items.Clear();

            try
            {
                // Get CRL context
                //
                bResult = Win32.&lt;STRONG&gt;CryptQueryObject&lt;/STRONG&gt;(
                    Win32.CERT_QUERY_OBJECT_FILE,
                    fileTextBox.Text,
                    Win32.CERT_QUERY_CONTENT_FLAG_CRL,
                    Win32.CERT_QUERY_FORMAT_FLAG_BINARY,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref pvContext
                );
                if (!bResult)
                {
                    throw new Exception("CryptQueryObject error #" + Marshal.GetLastWin32Error());
                }

                CRLContext = (Win32.CRL_CONTEXT)Marshal.PtrToStructure(pvContext, typeof(Win32.&lt;STRONG&gt;CRL_CONTEXT&lt;/STRONG&gt;));

                // Get CRL info
                //
                CRLInfo = (Win32.CRL_INFO)Marshal.PtrToStructure(CRLContext.pCrlInfo, typeof(Win32.&lt;STRONG&gt;CRL_INFO&lt;/STRONG&gt;));

                // Get CRL issuer
                //
                csz = Win32.CertNameToStr(
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    ref CRLInfo.Issuer,
                    Win32.CERT_X500_NAME_STR,
                    null,
                    0
                );
                if (csz &amp;lt;= 0)
                {
                    throw new Exception("CertNameToStr error #" + Marshal.GetLastWin32Error());
                }

                psz = new StringBuilder(csz);

                csz = Win32.&lt;STRONG&gt;CertNameToStr&lt;/STRONG&gt;(
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    ref CRLInfo.Issuer,
                    Win32.CERT_X500_NAME_STR,
                    psz,
                    csz
                );
                if (csz &amp;lt;= 0)
                {
                    throw new Exception("CertNameToStr error #" + Marshal.GetLastWin32Error());
                }

                // Show CRL issuer
                //
                issuerTextBox.Text = psz.ToString();

                // Get revocation list
                //
                rgCRLEntry = CRLInfo.rgCRLEntry;
                for (int i = 0; i &amp;lt; CRLInfo.cCRLEntry; i++)
                {
                    // Get the serial number of one revoked certificate
                    //
                    strSerialNumber = "";

                    CRLEntry = (Win32.CRL_ENTRY)Marshal.PtrToStructure(rgCRLEntry, typeof(Win32.&lt;STRONG&gt;CRL_ENTRY&lt;/STRONG&gt;));

                    pByte = CRLEntry.SerialNumber.pbData;
                    for (int j = 0; j &amp;lt; CRLEntry.SerialNumber.cbData; j++)
                    {
                        bByte = Marshal.ReadByte(pByte);
                        strSerialNumber = bByte.ToString("X").PadLeft(2, '0') + " " + strSerialNumber;
                        pByte = (IntPtr)((Int32)pByte + Marshal.SizeOf(typeof(Byte)));
                    }

                    // Get the CRL Reason Code of that revoked certificate
                    //
                    strCRLReasonCode = "";

                    rgExtension = Win32.&lt;STRONG&gt;CertFindExtension&lt;/STRONG&gt;(
                        Win32.szOID_CRL_REASON_CODE,
                        CRLEntry.cExtension,
                        CRLEntry.rgExtension
                    );
                    if (rgExtension.Equals(IntPtr.Zero))
                    {
                        throw new Exception("CertFindExtension found no CRL Reason Code");
                    }
                    
                    CRLExtension = (Win32.CERT_EXTENSION)Marshal.PtrToStructure(rgExtension, typeof(Win32.&lt;STRONG&gt;CERT_EXTENSION&lt;/STRONG&gt;));

                    // Format that CRL Reason Code so we can show it
                    //
                    cbFormat = 0;
                    pbFormat = null;
                    bResult = Win32.&lt;STRONG&gt;CryptFormatObject&lt;/STRONG&gt;(
                        Win32.X509_ASN_ENCODING,
                        0,
                        0,
                        IntPtr.Zero,
                        Win32.szOID_CRL_REASON_CODE,
                        CRLExtension.Value.pbData,
                        CRLExtension.Value.cbData,
                        null,
                        ref cbFormat
                    );
                    if (!bResult)
                    {
                        throw new Exception("CryptFormatObject error #" + Marshal.GetLastWin32Error());
                    }

                    pbFormat = new StringBuilder(cbFormat);

                    bResult = Win32.&lt;STRONG&gt;CryptFormatObject&lt;/STRONG&gt;(
                        Win32.X509_ASN_ENCODING,
                        0,
                        0,
                        IntPtr.Zero,
                        Win32.szOID_CRL_REASON_CODE,
                        CRLExtension.Value.pbData,
                        CRLExtension.Value.cbData,
                        pbFormat,
                        ref cbFormat
                    );
                    if (!bResult)
                    {
                        throw new Exception("CryptFormatObject error #" + Marshal.GetLastWin32Error());
                    }

                    strCRLReasonCode = pbFormat.ToString();

                    // Show Serial Number and CRL Reason Code
                    //
                    revocationListBox.Items.Add(strSerialNumber + "\t--&amp;gt;\t" + strCRLReasonCode);

                    // Continue with the next entry in the list
                    //
                    rgCRLEntry = (IntPtr)((Int32)rgCRLEntry + Marshal.SizeOf(typeof(Win32.&lt;STRONG&gt;CRL_ENTRY&lt;/STRONG&gt;)));
                }
            }
            catch (Exception ex)
            {
                // Show errors
                //
                MessageBox.Show(ex.Message);
            }
            finally
            {
                // Do some clean up
                //
                if (!pvContext.Equals(IntPtr.Zero))
                {
                    Win32.&lt;STRONG&gt;CertFreeCRLContext&lt;/STRONG&gt;(pvContext);
                }
            }
        }
    }
}

public class Win32
{
    #region APIs

    [DllImport("CRYPT32.DLL", EntryPoint = "CryptQueryObject", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern Boolean &lt;STRONG&gt;CryptQueryObject&lt;/STRONG&gt;(
        Int32 dwObjectType,
        [MarshalAs(UnmanagedType.LPWStr)]String pvObject,
        Int32 dwExpectedContentTypeFlags,
        Int32 dwExpectedFormatTypeFlags,
        Int32 dwFlags,
        IntPtr pdwMsgAndCertEncodingType,
        IntPtr pdwContentType,
        IntPtr pdwFormatType,
        IntPtr phCertStore,
        IntPtr phMsg,
        ref IntPtr ppvContext
        );

    [DllImport("CRYPT32.DLL", EntryPoint = "CertFreeCRLContext", SetLastError = true)]
    public static extern Boolean &lt;STRONG&gt;CertFreeCRLContext&lt;/STRONG&gt;(
        IntPtr pCrlContext
    );

    [DllImport("CRYPT32.DLL", EntryPoint = "CertNameToStr", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern Int32 &lt;STRONG&gt;CertNameToStr&lt;/STRONG&gt;(
        Int32 dwCertEncodingType,
        ref CRYPTOAPI_BLOB pName,
        Int32 dwStrType,
        StringBuilder psz,
        Int32 csz
    );

    [DllImport("CRYPT32.DLL", EntryPoint = "CertFindExtension", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr &lt;STRONG&gt;CertFindExtension&lt;/STRONG&gt;(
        [MarshalAs(UnmanagedType.LPStr)]String pszObjId,
        Int32 cExtensions,
        IntPtr rgExtensions
    );

    [DllImport("CRYPT32.DLL", EntryPoint = "CryptFormatObject", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern Boolean &lt;STRONG&gt;CryptFormatObject&lt;/STRONG&gt;(
        Int32 dwCertEncodingType,
        Int32 dwFormatType,
        Int32 dwFormatStrType,
        IntPtr pFormatStruct,
        [MarshalAs(UnmanagedType.LPStr)]String lpszStructType,
        IntPtr pbEncoded,
        Int32 cbEncoded,
        StringBuilder pbFormat,
        ref Int32 pcbFormat
    );

    #endregion APIs

    #region Structs

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;CRL_CONTEXT&lt;/STRONG&gt;
    {
        public Int32 dwCertEncodingType;
        public IntPtr pbCrlEncoded;
        public Int32 cbCrlEncoded;
        public IntPtr pCrlInfo;
        public IntPtr hCertStore;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;CRL_INFO&lt;/STRONG&gt;
    {
        public Int32 dwVersion;
        public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
        public CRYPTOAPI_BLOB Issuer;
        public FILETIME ThisUpdate;
        public FILETIME NextUpdate;
        public Int32 cCRLEntry;
        public IntPtr rgCRLEntry;
        public Int32 cExtension;
        public IntPtr rgExtension;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;CRYPT_ALGORITHM_IDENTIFIER&lt;/STRONG&gt;
    {
        [MarshalAs(UnmanagedType.LPStr)]public String pszObjId;
        public CRYPTOAPI_BLOB Parameters;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;CRYPTOAPI_BLOB&lt;/STRONG&gt;
    {
        public Int32 cbData;
        public IntPtr pbData;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;FILETIME&lt;/STRONG&gt;
    {
        public Int32 dwLowDateTime;
        public Int32 dwHighDateTime;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;CRL_ENTRY&lt;/STRONG&gt;
    {
        public CRYPTOAPI_BLOB SerialNumber;
        public FILETIME RevocationDate;
        public Int32 cExtension;
        public IntPtr rgExtension;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct &lt;STRONG&gt;CERT_EXTENSION&lt;/STRONG&gt;
    {
        [MarshalAs(UnmanagedType.LPStr)]public String pszObjId;
        public Boolean fCritical;
        public CRYPTOAPI_BLOB Value;
    }

    #endregion Structs

    #region Consts

    public const Int32 &lt;STRONG&gt;CERT_QUERY_OBJECT_FILE&lt;/STRONG&gt; = 0x00000001;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_CONTENT_CRL&lt;/STRONG&gt; = 3;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_CONTENT_FLAG_CRL&lt;/STRONG&gt; = 1 &amp;lt;&amp;lt; CERT_QUERY_CONTENT_CRL;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_BINARY&lt;/STRONG&gt; = 1;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_BASE64_ENCODED&lt;/STRONG&gt; = 2;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED&lt;/STRONG&gt; = 3;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_FLAG_BINARY&lt;/STRONG&gt; = 1 &amp;lt;&amp;lt; CERT_QUERY_FORMAT_BINARY;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED&lt;/STRONG&gt; = 1 &amp;lt;&amp;lt; CERT_QUERY_FORMAT_BASE64_ENCODED;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED&lt;/STRONG&gt; = 1 &amp;lt;&amp;lt; CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED;
    public const Int32 &lt;STRONG&gt;CERT_QUERY_FORMAT_FLAG_ALL&lt;/STRONG&gt; = CERT_QUERY_FORMAT_FLAG_BINARY | CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED | CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED;

    public const Int32 &lt;STRONG&gt;X509_ASN_ENCODING&lt;/STRONG&gt; = 0x00000001;
    public const Int32 &lt;STRONG&gt;PKCS_7_ASN_ENCODING&lt;/STRONG&gt; = 0x00010000;

    public const Int32 &lt;STRONG&gt;X509_NAME&lt;/STRONG&gt; = 7;

    public const Int32 &lt;STRONG&gt;CERT_SIMPLE_NAME_STR&lt;/STRONG&gt; = 1;
    public const Int32 &lt;STRONG&gt;CERT_OID_NAME_STR&lt;/STRONG&gt; = 2;
    public const Int32 &lt;STRONG&gt;CERT_X500_NAME_STR&lt;/STRONG&gt; = 3;

    public const String &lt;STRONG&gt;szOID_CRL_REASON_CODE&lt;/STRONG&gt; = "2.5.29.21";

    #endregion
}

&lt;/PRE&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9525923" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category></item><item><title>How to view a certificate programatically (C#)</title><link>http://blogs.msdn.com/alejacma/archive/2009/02/13/how-to-view-a-certificate-programatically-c.aspx</link><pubDate>Fri, 13 Feb 2009 11:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9418026</guid><dc:creator>alejacma</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9418026.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9418026</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;C#&lt;/STRONG&gt; sample shows a &lt;STRONG&gt;dialog&lt;/STRONG&gt; to &lt;STRONG&gt;view&lt;/STRONG&gt; a &lt;STRONG&gt;certificate&lt;/STRONG&gt;&amp;nbsp;and its &lt;STRONG&gt;properties&lt;/STRONG&gt;. This is the same dialog that appears when we double-click on the cert file in Explorer. I'll use &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa380289(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa380289(VS.85).aspx"&gt;CryptUIDlgViewCertificate&lt;/A&gt; API and its &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa380645(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa380645(VS.85).aspx"&gt;CRYPTUI_VIEWCERTIFICATE_STRUCT&lt;/A&gt; structure to achieve this:&lt;/P&gt;&lt;PRE&gt;...
using System.Security.Cryptography.X509Certificates;
using System.Runtime.InteropServices;

namespace MyNamespace
{
    public partial class MyClass
    {
...
        public const int &lt;STRONG&gt;CRYPTUI_DISABLE_ADDTOSTORE&lt;/STRONG&gt; = 0x00000010;

        [DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean &lt;STRONG&gt;CryptUIDlgViewCertificate&lt;/STRONG&gt;(
            ref CRYPTUI_VIEWCERTIFICATE_STRUCT pCertViewInfo,
            ref bool pfPropertiesChanged
        );

        public struct &lt;STRONG&gt;CRYPTUI_VIEWCERTIFICATE_STRUCT&lt;/STRONG&gt;
        {
            public int dwSize;
            public IntPtr hwndParent;
            public int dwFlags;
            [MarshalAs(UnmanagedType.LPWStr)]
            public String szTitle;
            public IntPtr pCertContext;
            public IntPtr rgszPurposes;
            public int cPurposes;
            public IntPtr pCryptProviderData; // or hWVTStateData
            public Boolean fpCryptProviderDataTrustedUsage;
            public int idxSigner;
            public int idxCert;
            public Boolean fCounterSigner;
            public int idxCounterSigner;
            public int cStores;
            public IntPtr rghStores;
            public int cPropSheetPages;
            public IntPtr rgPropSheetPages;
            public int nStartPage;
        }

        private void MySampleFunction()
        {
            // Get the cert
            X509Certificate2 cert = new &lt;STRONG&gt;X509Certificate2&lt;/STRONG&gt;(@"C:\temp\mycert.cer");

            // Show the cert
            CRYPTUI_VIEWCERTIFICATE_STRUCT certViewInfo = new CRYPTUI_VIEWCERTIFICATE_STRUCT();
            certViewInfo.dwSize = Marshal.SizeOf(certViewInfo);
            certViewInfo.pCertContext = cert.Handle;
            certViewInfo.szTitle = "Certificate Info";
            certViewInfo.dwFlags = CRYPTUI_DISABLE_ADDTOSTORE;
            certViewInfo.nStartPage = 0;
            bool fPropertiesChanged = false;
            if (!&lt;STRONG&gt;CryptUIDlgViewCertificate&lt;/STRONG&gt;(ref certViewInfo, ref fPropertiesChanged))
            {
                int error = Marshal.GetLastWin32Error();
                MessageBox.Show(error.ToString());
            }
        }
    }
}
&lt;/PRE&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9418026" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.Security/default.aspx">System.Security</category></item><item><title>How to sign EXE files with an Authenticode certificate (part 2)</title><link>http://blogs.msdn.com/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx</link><pubDate>Thu, 11 Dec 2008 12:59:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9196078</guid><dc:creator>alejacma</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9196078.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9196078</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P&gt;The other day a customer of mine was having an &lt;STRONG&gt;issue&lt;/STRONG&gt; with &lt;STRONG&gt;SignTool.exe&lt;/STRONG&gt; when &lt;STRONG&gt;signing&lt;/STRONG&gt; an &lt;STRONG&gt;EXE&lt;/STRONG&gt; file. The EXE file was getting &lt;STRONG&gt;corrupted&lt;/STRONG&gt;/unusable after signing it.&lt;/P&gt;
&lt;P&gt;When troubleshooting this issue, I had the chance to play a bit more&amp;nbsp;with SignTool and check what it does behind the scenes. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Note: I already talked a bit about signing EXEs in post &lt;/EM&gt;&lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx"&gt;&lt;EM&gt;How to sign EXE files with an Authenticode certificate (VB.NET)&lt;/EM&gt;&lt;/A&gt;&lt;EM&gt;. This new post will add more details and samples.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SignTool.exe&lt;/STRONG&gt; uses &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387712(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387712(VS.85).aspx"&gt;CAPICOM.SignedCode&lt;/A&gt; class and its &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387717(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387717(VS.85).aspx"&gt;Sign&lt;/A&gt; method to do the signing.&lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;VBScript&lt;/STRONG&gt; shows how we may use &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt; to do the signing programmatically:&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;Option Explicit

Dim szCertName, szExeToSign
szCertName = "My cert Subject"
szExeToSign = "MyApplication.exe"

Const CAPICOM_CURRENT_USER_STORE = 2
Const CAPICOM_STORE_OPEN_READ_ONLY = 0
Const CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1
Const CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION = 2

' Get certificate for signing
'
Dim objStore
Set objStore = WScript.CreateObject("&lt;STRONG&gt;CAPICOM.Store&lt;/STRONG&gt;")
objStore.Open CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY
Dim objSigningCert
Set objSigningCert = objStore.&lt;STRONG&gt;Certificates.Find&lt;/STRONG&gt;(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, szCertName).Item(1)

' Create a signer for the code
'
Dim objSigner
Set objSigner = WScript.CreateObject("&lt;STRONG&gt;CAPICOM.Signer&lt;/STRONG&gt;")
objSigner.&lt;STRONG&gt;Certificate&lt;/STRONG&gt; = objSigningCert

' Sign the file
'
Dim objSignedCode
Set objSignedCode = WScript.CreateObject("&lt;STRONG&gt;CAPICOM.SignedCode&lt;/STRONG&gt;")
objSignedCode.&lt;STRONG&gt;FileName&lt;/STRONG&gt; = szExeToSign
objSignedCode.&lt;STRONG&gt;Sign&lt;/STRONG&gt; objSigner
objSignedCode.&lt;STRONG&gt;TimeStamp&lt;/STRONG&gt; "http://timestamp.globalsign.com/scripts/timstamp.dll"

WScript.Echo "Done!"
&lt;/PRE&gt;
&lt;P&gt;Note that&amp;nbsp;this sample also shows how to &lt;STRONG&gt;time stamp a signature&lt;/STRONG&gt; programmatically.&lt;/P&gt;
&lt;P&gt;This sample was also reproducing my customer's issue. So&amp;nbsp;I checked what CAPICOM does behind the scenes to further troubleshoot the issue.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;CAPICOM.SignedCode.Sign&lt;/STRONG&gt; uses &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa380292(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa380292(VS.85).aspx"&gt;CryptUIWizDigitalSign&lt;/A&gt; API to do the signing. &lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;VB.NET &lt;/STRONG&gt;sample uses &lt;STRONG&gt;CryptUIWizDigitalSign &lt;/STRONG&gt;through &lt;STRONG&gt;P/Invoke&lt;/STRONG&gt; to do the signing programmatically:&lt;/P&gt;&lt;PRE&gt;&amp;lt;SAMPLE file="Crypto.vb"&amp;gt;

Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class Crypto

    ' #define CRYPTUI_WIZ_NO_UI     1
    Public Const &lt;STRONG&gt;CRYPTUI_WIZ_NO_UI&lt;/STRONG&gt; As Int32 = 1

    ' #define CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE     0x01
    Public Const &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE&lt;/STRONG&gt; As Int32 = 1

    ' #define CRYPTUI_WIZ_DIGITAL_SIGN_CERT                    0x01
    Public Const &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_CERT&lt;/STRONG&gt; As Int32 = 1

    ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_INFO {  
    '   DWORD dwSize;  
    '   DWORD dwSubjectChoice;  
    '   union {    
    '       LPCWSTR pwszFileName;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO pSignBlobInfo;  
    '   };  
    '   DWORD dwSigningCertChoice;  
    '   union {    
    '       PCCERT_CONTEXT pSigningCertContext;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO pSigningCertStore;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pSigningCertPvkInfo;  
    '   };  
    '   LPCWSTR pwszTimestampURL;  
    '   DWORD dwAdditionalCertChoice;  
    '   PCCRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO pSignExtInfo;
    ' } CRYPTUI_WIZ_DIGITAL_SIGN_INFO;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_INFO&lt;/STRONG&gt;
        Public dwSize As Int32
        Public dwSubjectChoice As Int32
        &amp;lt;MarshalAs(UnmanagedType.LPWStr)&amp;gt; Public pwszFileName As String
        Public dwSigningCertChoice As Int32
        Public pSigningCertContext As IntPtr
        Public pwszTimestampURL As String
        Public dwAdditionalCertChoice As Int32
        Public pSignExtInfo As IntPtr
    End Structure

    ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT {  
    '      DWORD dwSize;  
    '      DWORD cbBlob;  
    '      BYTE* pbBlob;
    ' } CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure &lt;STRONG&gt;CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT&lt;/STRONG&gt;
        Public dwSize As Int32
        Public cbBlob As Int32
        Public pbBlob As IntPtr
    End Structure

    ' BOOL WINAPI CryptUIWizDigitalSign(
    '      DWORD dwFlags,
    '      HWND hwndParent,
    '      LPCWSTR pwszWizardTitle,
    '      PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo,
    '      PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT* ppSignContext
    ' );
    &amp;lt;DllImport("Cryptui.dll", CharSet:=CharSet.Unicode, SetLastError:=True)&amp;gt; _
    Public Shared Function &lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt;( _
        ByVal dwFlags As Int32, _
        ByVal hwndParent As IntPtr, _
        ByVal pwszWizardTitle As String, _
        ByRef pDigitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO, _
        ByRef ppSignContext As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptUIWizFreeDigitalSignContext(
    '   PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT pSignContext
    ' );
    &amp;lt;DllImport("Cryptui.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function &lt;STRONG&gt;CryptUIWizFreeDigitalSignContext&lt;/STRONG&gt;( _
        ByVal pSignContext As IntPtr _
    ) As Boolean
    End Function

End Class

&amp;lt;/SAMPLE&amp;gt;

&amp;lt;SAMPLE file="Module1.vb"&amp;gt;

Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports SignExe.Crypto
Imports System.Security.Cryptography.X509Certificates
Imports System.IO

Module Module1

    Sub Main()

        ' Parameters
        Dim certPath As String = "MyCert.pfx"
        Dim exePath As String = "MyApplication.exe"
        Dim sigPath As String = "signature.sig"

        ' Variables
        '
        Dim cert As X509Certificate2
        Dim digitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO
        Dim pSignContext As IntPtr
        Dim pSigningCertContext As IntPtr
        Dim signContext As CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
        Dim fileOut As FileStream
        Dim binWriter As BinaryWriter
        Dim blob() As Byte

        Try
            ' Get certificate context
            '
            cert = New &lt;STRONG&gt;X509Certificate2&lt;/STRONG&gt;(certPath, "")
            pSigningCertContext = cert.Handle

            ' Prepare signing info: exe and cert
            '
            digitalSignInfo = New CRYPTUI_WIZ_DIGITAL_SIGN_INFO
            digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo)
            digitalSignInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE
            digitalSignInfo.pwszFileName = exePath
            digitalSignInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT
            digitalSignInfo.pSigningCertContext = pSigningCertContext
            digitalSignInfo.pwszTimestampURL = vbNullString
            digitalSignInfo.dwAdditionalCertChoice = 0
            digitalSignInfo.pSignExtInfo = IntPtr.Zero

            ' Sign exe
            '
            If (Not &lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt;( _
                CRYPTUI_WIZ_NO_UI, _
                IntPtr.Zero, _
                vbNullString, _
                digitalSignInfo, _
                pSignContext _
            )) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizDigitalSign")
            End If

            ' Get the blob with the signature
            '
            signContext = Marshal.PtrToStructure(pSignContext, GetType(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT))
            blob = New Byte(signContext.cbBlob) {}
            Marshal.Copy(signContext.pbBlob, blob, 0, signContext.cbBlob)

            ' Store the signature in a new file
            '
            fileOut = File.Open(sigPath, FileMode.Create)
            binWriter = New BinaryWriter(fileOut)
            binWriter.Write(blob)
            binWriter.Close()
            fileOut.Close()

            ' Free blob
            '
            If (Not &lt;STRONG&gt;CryptUIWizFreeDigitalSignContext&lt;/STRONG&gt;(pSignContext)) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizFreeDigitalSignContext")
            End If

            ' We are done
            Console.WriteLine("Done!!!")

        Catch ex As Win32Exception
            ' Any expected errors?
            '
            Console.WriteLine(ex.Message + " error#" + ex.NativeErrorCode.ToString)
        Catch ex As Exception
            ' Any unexpected errors?
            '
            Console.WriteLine(ex.Message)
        End Try

        ' We are done
        '
        Console.WriteLine("&amp;lt;&amp;lt; Press any key to continue &amp;gt;&amp;gt;")
        Console.ReadKey()

    End Sub

End Module

&amp;lt;/SAMPLE&amp;gt;&lt;/PRE&gt;
&lt;P&gt;This sample was also reproducing the issue. So I checked what CryptUIWizDigitalSign does behind the scenes.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt; API uses &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa387734(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa387734(VS.85).aspx"&gt;SignerSignEx&lt;/A&gt; API to do the signing.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following &lt;STRONG&gt;VC++&lt;/STRONG&gt; sample uses &lt;STRONG&gt;SignerSignEx&lt;/STRONG&gt; API to do the signing programmatically:&lt;/P&gt;&lt;PRE&gt;#include "windows.h"
#include "Wincrypt.h"
#include "stdio.h"
#include "conio.h"


// STRUCTS

typedef &lt;STRONG&gt;struct _SIGNER_FILE_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	LPCWSTR pwszFileName;  
	HANDLE hFile;
} SIGNER_FILE_INFO,  *PSIGNER_FILE_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_BLOB_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	GUID *pGuidSubject;  
	DWORD cbBlob;  
	BYTE *pbBlob;  
	LPCWSTR pwszDisplayName;
} SIGNER_BLOB_INFO,  *PSIGNER_BLOB_INFO;

typedef&lt;STRONG&gt; struct _SIGNER_SUBJECT_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	DWORD *pdwIndex;  
	DWORD dwSubjectChoice;  
	union {    
		SIGNER_FILE_INFO *pSignerFileInfo;    
		SIGNER_BLOB_INFO *pSignerBlobInfo;  
	} ;
} SIGNER_SUBJECT_INFO,  *PSIGNER_SUBJECT_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_CERT_STORE_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	PCCERT_CONTEXT pSigningCert;  
	DWORD dwCertPolicy;  
	HCERTSTORE hCertStore;
} SIGNER_CERT_STORE_INFO,  *PSIGNER_CERT_STORE_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_SPC_CHAIN_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	LPCWSTR pwszSpcFile;  
	DWORD dwCertPolicy;  
	HCERTSTORE hCertStore;
} SIGNER_SPC_CHAIN_INFO,  *PSIGNER_SPC_CHAIN_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_CERT&lt;/STRONG&gt; {  
	DWORD cbSize;  
	DWORD dwCertChoice;  
	union {    
		LPCWSTR pwszSpcFile;    
		SIGNER_CERT_STORE_INFO *pCertStoreInfo;    
		SIGNER_SPC_CHAIN_INFO *pSpcChainInfo;  
	} ;  
	HWND hwnd;
} SIGNER_CERT,  *PSIGNER_CERT;

typedef&lt;STRONG&gt; struct _SIGNER_ATTR_AUTHCODE&lt;/STRONG&gt; {  
	DWORD cbSize;  
	BOOL fCommercial;  
	BOOL fIndividual;  
	LPCWSTR pwszName;  
	LPCWSTR pwszInfo;
} SIGNER_ATTR_AUTHCODE,  *PSIGNER_ATTR_AUTHCODE;

typedef &lt;STRONG&gt;struct _SIGNER_SIGNATURE_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	ALG_ID algidHash;  
	DWORD dwAttrChoice;  
	union {    
		SIGNER_ATTR_AUTHCODE *pAttrAuthcode;  
	} ;  
	PCRYPT_ATTRIBUTES psAuthenticated;  
	PCRYPT_ATTRIBUTES psUnauthenticated;
} SIGNER_SIGNATURE_INFO,  *PSIGNER_SIGNATURE_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_PROVIDER_INFO&lt;/STRONG&gt; {  
	DWORD cbSize;  
	LPCWSTR pwszProviderName;  
	DWORD dwProviderType;  
	DWORD dwKeySpec;  
	DWORD dwPvkChoice;  
	union {    
		LPWSTR pwszPvkFileName;    
		LPWSTR pwszKeyContainer;  
	} ;
} SIGNER_PROVIDER_INFO,  *PSIGNER_PROVIDER_INFO;

typedef &lt;STRONG&gt;struct _SIGNER_CONTEXT&lt;/STRONG&gt; {  
	DWORD cbSize;  
	DWORD cbBlob;  
	BYTE *pbBlob;
} SIGNER_CONTEXT,  *PSIGNER_CONTEXT;


// EXPORTS 

typedef HRESULT (WINAPI* &lt;STRONG&gt;SignerFreeSignerContextType&lt;/STRONG&gt;)(
  __in  SIGNER_CONTEXT *pSignerContext
);

typedef HRESULT (WINAPI *&lt;STRONG&gt;SignerSignExType&lt;/STRONG&gt;)(
  __in      DWORD dwFlags,
  __in      SIGNER_SUBJECT_INFO *pSubjectInfo,
  __in      SIGNER_CERT *pSignerCert,
  __in      SIGNER_SIGNATURE_INFO *pSignatureInfo,
  __in_opt  SIGNER_PROVIDER_INFO *pProviderInfo,
  __in_opt  LPCWSTR pwszHttpTimeStamp,
  __in_opt  PCRYPT_ATTRIBUTES psRequest,
  __in_opt  LPVOID pSipData,
  __out     SIGNER_CONTEXT **ppSignerContext
);


// MAIN

void main()
{
	// PARAMETERS

	// File to sign
	LPCWSTR pwszFileName = L"C:\\TEST\\MyApplication.exe";

	// Signing Cert Subject
	LPCWSTR pwszCertSubject = L"My cert Subject";

	// VARIABLES
	HRESULT hResult = S_OK;
	BOOL bResult = TRUE;
	HMODULE hMssign32 = NULL;
	SignerSignExType pfSignerSignEx = NULL;
	SignerFreeSignerContextType pfSignerFreeSignerContext = NULL;
	HANDLE hFile = NULL;
	HCERTSTORE hCertStore = NULL; 
	PCCERT_CONTEXT pCertContext = NULL;
	DWORD dwIndex = 0;
	SIGNER_FILE_INFO signerFileInfo;
	SIGNER_SUBJECT_INFO signerSubjectInfo;
	SIGNER_CERT_STORE_INFO signerCertStoreInfo;
	SIGNER_CERT signerCert;
	SIGNER_SIGNATURE_INFO signerSignatureInfo;
	SIGNER_CONTEXT * pSignerContext = NULL;

	// MAIN

	// Attach a debugger now!
	printf("&amp;lt;&amp;lt; Press any key to continue&amp;gt;&amp;gt;\n");
	_getch();

	// Load library containing SignerSignEx and SignerFreeSignerContext
	printf("LoadLibrary...");
	hMssign32 = &lt;STRONG&gt;LoadLibrary&lt;/STRONG&gt;(L"&lt;STRONG&gt;Mssign32.dll&lt;/STRONG&gt;");
	if (!hMssign32)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Get SignerSignEx function
	printf("GetProcAddress(SignerSignEx)...");
	pfSignerSignEx = (SignerSignExType) &lt;STRONG&gt;GetProcAddress&lt;/STRONG&gt;(hMssign32, "&lt;STRONG&gt;SignerSignEx&lt;/STRONG&gt;");
	if (!pfSignerSignEx)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Get SignerFreeSignerContext function
	printf("GetProcAddress(SignerFreeSignerContext)...");
	pfSignerFreeSignerContext = (SignerFreeSignerContextType) &lt;STRONG&gt;GetProcAddress&lt;/STRONG&gt;(hMssign32, "&lt;STRONG&gt;SignerFreeSignerContext&lt;/STRONG&gt;");
	if (!pfSignerFreeSignerContext)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Open file to sign
	printf("CreateFile...");
	hFile = &lt;STRONG&gt;CreateFile&lt;/STRONG&gt;(
		pwszFileName,
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);
	if (!hFile)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Open MY cert store
	printf("CertOpenStore...");
	hCertStore = &lt;STRONG&gt;CertOpenStore&lt;/STRONG&gt;(
		CERT_STORE_PROV_SYSTEM, 
		0,
		NULL,
		CERT_SYSTEM_STORE_CURRENT_USER,
		L"MY"
	);                 
	if (!hCertStore)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Find signing cert in MY cert store
	printf("CertFindCertificateInStore...");
	pCertContext = &lt;STRONG&gt;CertFindCertificateInStore&lt;/STRONG&gt;(
		hCertStore,
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		0,
		CERT_FIND_SUBJECT_STR,
		(void *)pwszCertSubject,
		NULL
	);
	if (!pCertContext)
	{
		printf("Error #%d\n", GetLastError()); goto cleanup;
	}
	printf("Done!\n");

	// Prepare SIGNER_FILE_INFO struct
	signerFileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
	signerFileInfo.pwszFileName = pwszFileName;
	signerFileInfo.hFile = hFile;

	// Prepare SIGNER_SUBJECT_INFO struct
	signerSubjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
	dwIndex = 0;
	signerSubjectInfo.pdwIndex = &amp;amp;dwIndex;
	signerSubjectInfo.dwSubjectChoice = 1; // SIGNER_SUBJECT_FILE
	signerSubjectInfo.pSignerFileInfo = &amp;amp;signerFileInfo;

	// Prepare SIGNER_CERT_STORE_INFO struct
	signerCertStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
	signerCertStoreInfo.pSigningCert = pCertContext;
	signerCertStoreInfo.dwCertPolicy = 2; // SIGNER_CERT_POLICY_CHAIN
	signerCertStoreInfo.hCertStore = NULL;

	// Prepare SIGNER_CERT struct
	signerCert.cbSize = sizeof(SIGNER_CERT);
	signerCert.dwCertChoice = 2; // SIGNER_CERT_STORE
	signerCert.pCertStoreInfo = &amp;amp;signerCertStoreInfo;
	signerCert.hwnd = NULL;

	// Prepare SIGNER_SIGNATURE_INFO struct
	signerSignatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
	signerSignatureInfo.algidHash = CALG_SHA1;
	signerSignatureInfo.dwAttrChoice = 0; // SIGNER_NO_ATTR
	signerSignatureInfo.pAttrAuthcode = NULL;
	signerSignatureInfo.psAuthenticated = NULL;
	signerSignatureInfo.psUnauthenticated = NULL;

	// Sign file with cert
	printf("SignerSignEx...");
	hResult = pf&lt;STRONG&gt;SignerSignEx&lt;/STRONG&gt;(
		0,
		&amp;amp;signerSubjectInfo,
		&amp;amp;signerCert,
		&amp;amp;signerSignatureInfo,
		NULL,
		NULL,
		NULL,
		NULL,
		&amp;amp;pSignerContext
	);
	if (S_OK != hResult)
	{
		printf("Error #%d\n", hResult); goto cleanup;
	}
	printf("Done!\n");

	printf("\nSUCCESS!!!\n");

	// Clean up
cleanup:

	if (pSignerContext)
	{
		hResult = pf&lt;STRONG&gt;SignerFreeSignerContext&lt;/STRONG&gt;(pSignerContext);
	}

	if (pCertContext)
	{
		bResult = &lt;STRONG&gt;CertFreeCertificateContext&lt;/STRONG&gt;(pCertContext);
	}

	if (hCertStore)
	{
		bResult = &lt;STRONG&gt;CertCloseStore&lt;/STRONG&gt;(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
	}

	if (hFile)
	{
		bResult = &lt;STRONG&gt;CloseHandle&lt;/STRONG&gt;(hFile);
	}

	if (hMssign32)
	{
		bResult = &lt;STRONG&gt;FreeLibrary&lt;/STRONG&gt;(hMssign32);
	}

	// Exit
	printf("&amp;lt;&amp;lt; Press any key to exit &amp;gt;&amp;gt;\n");
	_getch();
	return;
}
&lt;/PRE&gt;
&lt;P&gt;This sample was also reproducing the issue.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Finally we saw that the &lt;STRONG&gt;issue&lt;/STRONG&gt; was not in SignTool.exe / CAPICOM.SignCode.Sign / CryptUIWizDigitalSign / SignerSignEx, but in the &lt;STRONG&gt;EXE itself&lt;/STRONG&gt;!&lt;/P&gt;
&lt;P&gt;I run Visual Studio's &lt;A class="" href="http://support.microsoft.com/kb/177429/en-us" mce_href="http://support.microsoft.com/kb/177429/en-us"&gt;Dumpbin.exe&lt;/A&gt; with its &lt;STRONG&gt;"/HEADER"&lt;/STRONG&gt; parameter to list the problematic EXE's &lt;STRONG&gt;PE&lt;/STRONG&gt; &lt;STRONG&gt;header&lt;/STRONG&gt; information before and after signing it (the &lt;A class="" href="http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx" mce_href="http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx"&gt;Microsoft Portable Executable and Common Object File Format Specification &lt;/A&gt;gives detailed information about PE header information).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Before signing&lt;/STRONG&gt;, I could see the following &lt;STRONG&gt;Optional Header Value&lt;/STRONG&gt;:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;STRONG&gt;1400&lt;/STRONG&gt; [ &lt;STRONG&gt;C40&lt;/STRONG&gt;] RVA [size] of &lt;STRONG&gt;Certificates Directory&lt;/STRONG&gt;&lt;BR&gt;&lt;/EM&gt;&lt;BR&gt;&lt;STRONG&gt;After signing&lt;/STRONG&gt;, I could see the following value:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;STRONG&gt;1400&lt;/STRONG&gt; [ &lt;STRONG&gt;1650&lt;/STRONG&gt;] RVA [size] of &lt;STRONG&gt;Certificates Directory&lt;/STRONG&gt;&lt;BR&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Certificates Directory &lt;/STRONG&gt;points to the &lt;STRONG&gt;location of the code signing signature in the binary&lt;/STRONG&gt;. So an &lt;STRONG&gt;EXE which has not been signed&lt;/STRONG&gt; should contain the following values:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;&lt;STRONG&gt;0&lt;/STRONG&gt; [ &lt;STRONG&gt;0&lt;/STRONG&gt;] RVA [size] of &lt;STRONG&gt;Certificates Directory&lt;/STRONG&gt;&lt;/EM&gt;&lt;BR&gt;&lt;BR&gt;Which was not our case. So SignerSignEx was not corrupting the EXE when signing it. It was already corrupted before that, even if it was successfully running before signing!&lt;/P&gt;
&lt;P&gt;Just for testing, I opened the problematic EXE with a &lt;STRONG&gt;binary editor&lt;/STRONG&gt; before signing it. I looked for "00 14 00 00 04 0c 00 00" bytes (correspondent to "1400 [ C40] RVA [size] of Certificates Directory" values), changed them to "00 00 00 00 00 00 00 00" and signed the EXE. It worked! Now the EXE is not corrupted and I can see the Digital Signature in Explorer, the certificate I used to sign, launch the EXE and run it as expected.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Manually modifying the PE header is not supported by Microsoft.&lt;/STRONG&gt; If you face a similar issue, you should work with the team that developed the EXE and focus on why the EXE got generated with an invalid PE header in the first place. &lt;/P&gt;
&lt;P&gt;I looked on the Internet and found that there are some &lt;STRONG&gt;third-party tools&lt;/STRONG&gt; which may help us to &lt;STRONG&gt;see&lt;/STRONG&gt; &lt;STRONG&gt;and modify the PE header&lt;/STRONG&gt; if needed for testing purposes, for example &lt;A class="" href="http://www.pazera-software.com/products/peinfo/" mce_href="http://www.pazera-software.com/products/peinfo/"&gt;PEInfo 0.9 BETA&lt;/A&gt; which I haven't tried so I can't neither recommend nor discourage its use.&lt;/P&gt;
&lt;P&gt;I&amp;nbsp;hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;A href="http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9196078" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/VBScript/default.aspx">VBScript</category></item><item><title>How to change Windows Theme programmatically in XP</title><link>http://blogs.msdn.com/alejacma/archive/2008/11/26/how-to-change-windows-theme-programmatically-in-xp.aspx</link><pubDate>Wed, 26 Nov 2008 18:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9144706</guid><dc:creator>alejacma</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9144706.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9144706</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;You may know already that there is no i.e. COM object or .NET class we can use to &lt;STRONG&gt;change&lt;/STRONG&gt; the &lt;STRONG&gt;Windows Theme&lt;/STRONG&gt; programmatically on &lt;STRONG&gt;Windows XP&lt;/STRONG&gt;. You may also know the following &lt;STRONG&gt;VBScript&lt;/STRONG&gt; which can be used to do this change without user intervention:&lt;/P&gt;&lt;PRE&gt;Set OSHApp = CreateObject("&lt;STRONG&gt;Shell.Application&lt;/STRONG&gt;")
Set oShell = CreateObject("Wscript.Shell")

' Set the Path to the Theme file
'
Theme = "\\SERVER\SHAREDFOLDER\FILE.THEME"
Theme = """" + Theme + """"
' Open the Theme in Display Properties
'
oSHApp.&lt;STRONG&gt;ControlPanelItem&lt;/STRONG&gt; cstr("&lt;STRONG&gt;desk.cpl desk,@Themes /Action:OpenTheme /file:&lt;/STRONG&gt;" &amp;amp; Theme)

' Loop and wait until Display Properties is loaded.
'
While OShell.AppActivate ("Display Properties") = FALSE
Wscript.Sleep 1000
Wend

' Loop and send the Enter key to Display Properties until Theme is applied 
'
While OShell.AppActivate ("Display Properties") = TRUE
    oShell.AppActivate "Display Properties"
    Wscript.Sleep 200
    oShell.sendkeys "{ENTER}"
Wend
&lt;/PRE&gt;
&lt;P&gt;If you try this script,&amp;nbsp;it will sometimes fail. In some situations, the Display Properties dialog won't be closed automatically. You may "play" with the Sleep times and solve the issue in several machines, but it won't necessarily work in all of them.&lt;/P&gt;
&lt;P&gt;The issue here is that "oShell.sendkeys "{ENTER}"" is not getting to the right window and there is any guarantee that it will do it.&lt;/P&gt;
&lt;P&gt;Fortunately there is an &lt;STRONG&gt;alternate solution&lt;/STRONG&gt; to this script and its SendKeys: &lt;STRONG&gt;send a&lt;/STRONG&gt; &lt;STRONG&gt;BM_CLICK&lt;/STRONG&gt; &lt;STRONG&gt;window message&lt;/STRONG&gt; to the button we need to press in the required &lt;STRONG&gt;Theme window&lt;/STRONG&gt;. This way we can warrantee that we close the right window by pressing the right button.&lt;/P&gt;
&lt;P&gt;You will find a&lt;STRONG&gt; VB.NET&lt;/STRONG&gt; sample below which gets &lt;STRONG&gt;all windows in the desktop&lt;/STRONG&gt; (visible and invisible), the way &lt;STRONG&gt;Spy++&lt;/STRONG&gt; does it, in a tree. Then the sample also shows how if we select one of those windows in the tree manually (i.e. the print dialog of notepad), we can&amp;nbsp;interact with it programmatically&amp;nbsp;(i.e. changing the editbox with the number of copies to print and pressing the Print button). &lt;/P&gt;
&lt;P&gt;It should be easy to adapt this sample to our needs so it first launches the Theme console to change the theme the way the script above does it (i.e. &lt;A class="" href="http://www.codeguru.com/vb/gen/vb_system/win32/print.php/c13963" mce_href="http://www.codeguru.com/vb/gen/vb_system/win32/print.php/c13963"&gt;Running Windows XP Control Panel Applets from Visual Basic.NET 2005&lt;/A&gt;), and then it looks for the window we need to close, locates its OK button and sends a BM_CLICK message to it in order to close the window.&lt;/P&gt;
&lt;P&gt;Here is the sample:&lt;/P&gt;&lt;PRE&gt;Imports System.Runtime.InteropServices

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

        ' Get all windows and show them in the tree
        '
        GetWindows()
        TreeView1.Nodes.Item(0).Expand()
    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents TreeView1 As System.Windows.Forms.TreeView
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    &lt;SYSTEM.DIAGNOSTICS.DEBUGGERSTEPTHROUGH()&gt; Private Sub InitializeComponent()
        Me.TreeView1 = New System.Windows.Forms.TreeView
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'TreeView1
        '
        Me.TreeView1.HideSelection = False
        Me.TreeView1.ImageIndex = -1
        Me.TreeView1.Location = New System.Drawing.Point(8, 48)
        Me.TreeView1.Name = "TreeView1"
        Me.TreeView1.SelectedImageIndex = -1
        Me.TreeView1.Size = New System.Drawing.Size(640, 504)
        Me.TreeView1.TabIndex = 0
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(8, 8)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(160, 32)
        Me.Button1.TabIndex = 1
        Me.Button1.Text = "Refresh"
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(176, 8)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(472, 32)
        Me.Button2.TabIndex = 2
        Me.Button2.Text = "Set ""Number of copies"" and click ""Print"" in selected notepad's Print dialog"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(656, 558)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.TreeView1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

#End Region

#Region "AlejaCMa"

    ' Constants
    '
    Private Const GW_CHILD = 5
    Private Const GW_HWNDNEXT = 2

    Private Const WM_SETTEXT = &amp;amp;HC
    Private Const BM_CLICK = &amp;amp;HF5

    ' API declarations
    '
    Private Declare Function GetDesktopWindow Lib "user32" () As IntPtr

    Private Declare Function GetWindow Lib "user32" ( _
        ByVal hWnd As IntPtr, _
        ByVal uCmd As Int32) _
    As IntPtr

    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
        ByVal hWnd As IntPtr, _
        ByVal lpString As String, _
        ByVal nMaxCount As Int32) _
    As Int32

    Public Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" ( _
        ByVal hwnd As IntPtr, _
        ByRef lpdwProcessId As Int32) _
    As Int32

    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
        ByVal hWnd As IntPtr, _
        ByVal lpClassName As String, _
        ByVal nMaxCount As Int32) _
    As Int32

    Private Declare Function IsWindowVisible Lib "user32" ( _
        ByVal hWnd As IntPtr) _
    As Int32

    Public Declare Auto Function SendMessage Lib "user32" Alias "SendMessageA" ( _
        ByVal hWnd As IntPtr, _
        ByVal wMsg As Int32, _
        ByVal wParam As Int32, _
        &lt;MARSHALAS(UNMANAGEDTYPE.ANSIBSTR)&gt; ByVal lParam As String) _
    As Int32

    ' Get windows, and show them in the tree
    '
    Private Sub GetWindows()
        ' Variables
        '
        Dim hWnd As IntPtr
        Dim node As TreeNode
        Dim windowText As String
        Dim className As String
        Dim c As Int32
        Dim nodeText As String

        ' Get desktop window
        '
        hWnd = GetDesktopWindow()

        ' Get window text and class name
        '
        windowText = Space(255)
        c = GetWindowText(hWnd, windowText, 255)
        windowText = Microsoft.VisualBasic.Left(windowText, c)

        className = Space(255)
        c = GetClassName(hWnd, className, 255)
        className = Microsoft.VisualBasic.Left(className, c)

        ' Add window to the tree
        '
        nodeText = String.Format("{0:X8} ""{1}"" {2} (Desktop)", hWnd.ToInt32, windowText, className)
        node = TreeView1.Nodes.Add(nodeText)
        node.ForeColor = Color.Black

        ' Search children by recursion
        '
        GetWindows(hWnd, node)
    End Sub

    Private Sub GetWindows(ByVal hParentWnd As IntPtr, ByVal parentNode As TreeNode)
        ' Variables
        '
        Dim hWnd As IntPtr
        Dim node As TreeNode
        Dim windowText As String
        Dim className As String
        Dim c As Int32
        Dim nodeText As String

        ' Get first child window
        '
        hWnd = GetWindow(hParentWnd, GW_CHILD)

        Do Until hWnd.Equals(IntPtr.Zero)
            ' Get the window text and class name
            '
            windowText = Space(255)
            c = GetWindowText(hWnd, windowText, 255)
            windowText = Microsoft.VisualBasic.Left(windowText, c)

            className = Space(255)
            c = GetClassName(hWnd, className, 255)
            className = Microsoft.VisualBasic.Left(className, c)

            ' Add window to the tree
            '
            nodeText = String.Format("{0:X8} ""{1}"" {2}", hWnd.ToInt32, windowText, className)
            node = parentNode.Nodes.Add(nodeText)
            If (IsWindowVisible(hWnd)) Then
                ' Visible windows are shown in black
                '
                node.ForeColor = Color.Black
            Else
                ' Invisible windows are shown in red
                '
                node.ForeColor = Color.Red
            End If

            ' Search children by recursion
            '
            GetWindows(hWnd, node)

            ' Get next child window
            '
            hWnd = GetWindow(hWnd, GW_HWNDNEXT)
        Loop
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ' Get all windows and show them in the tree
        '
        TreeView1.Nodes.Clear()
        GetWindows()
        TreeView1.Nodes.Item(0).Expand()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        ' Variables
        '
        Dim node As TreeNode
        Dim windowInfo As String
        Dim hWnd As IntPtr
        Dim pid As Int32
        Dim processName As String

        ' Get the selected window in the tree
        '
        node = TreeView1.SelectedNode

        ' Get PID (Process ID) for the selected window
        '
        hWnd = New IntPtr(CInt("&amp;amp;H" + Microsoft.VisualBasic.Left(node.Text, 8)))
        GetWindowThreadProcessId(hWnd, pid)

        ' Get process name from PID
        '
        processName = Process.GetProcessById(pid).ProcessName

        ' Check if the selected window in the tree is notepad's Print dialog:
        '   Window Handle = xxxxxxxx (variable)
        '   Window Text   = Print
        '   Class Name    = #32770
        '   Process Name  = "notepad"
        '
        windowInfo = Microsoft.VisualBasic.Right(node.Text, node.Text.Length - 9)
        If (windowInfo = """Print"" #32770" And processName = "notepad") Then
            ' The selected window is notepad's Print dialog

            ' Change the number of copies in "Number of &amp;amp;copies" edit box 
            '
            ' xxxxxxxx "Print" #32770       &amp;lt;-- Selected node
            '   - xxxxxxxx "General" #32770
            '       - xxxxxxxx "" #32770
            '            xxxxxxxx "" Edit   &amp;lt;-- We have to write here
            '
            hWnd = New IntPtr(CInt("&amp;amp;H" + Microsoft.VisualBasic.Left(node.Nodes(0).Nodes(13).Nodes(10).Text, 8)))
            SendMessage(hWnd, WM_SETTEXT, 0, "2")

            ' Press the print button
            '
            ' xxxxxxxx "Print" #32770       &amp;lt;-- Selected node
            '    xxxxxxxx "&amp;amp;Print" Button   &amp;lt;-- We have to press here
            '
            hWnd = New IntPtr(CInt("&amp;amp;H" + Microsoft.VisualBasic.Left(node.Nodes(1).Text, 8)))
            SendMessage(hWnd, BM_CLICK, 0, Nothing)
        Else
            ' The selected window is not notepad's Print dialog
            '
            MessageBox.Show("The selected window is not a notepad's Print dialog")
        End If
    End Sub
#End Region

End Class

&lt;/PRE&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9144706" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Windows+XP/default.aspx">Windows XP</category></item><item><title>How to sign a message and verify a message signature (C#)</title><link>http://blogs.msdn.com/alejacma/archive/2008/02/21/how-to-sign-a-message-and-verify-a-message-signature-c.aspx</link><pubDate>Thu, 21 Feb 2008 20:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7839988</guid><dc:creator>alejacma</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/7839988.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=7839988</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P&gt;Today we'll do some more &lt;STRONG&gt;P/Invoke&lt;/STRONG&gt; with &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt; and &lt;STRONG&gt;C#&lt;/STRONG&gt;. The following sample is a conversion to &lt;STRONG&gt;C# &lt;/STRONG&gt;of the C++ sample in &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa382372.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa382372.aspx"&gt;Example C Program: Signing a Message and Verifying a Message Signature&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE file="Class1.cs"&amp;gt;&lt;/P&gt;&lt;PRE class=code&gt;using System;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
  class Class1
  {
    [STAThread]
    static void Main(string[] args)
    {
      // Parameters.
      //
      String sSignerName = "ALEJANDRO CAMPOS MAGENCIO";
      String sMessage = "CryptoAPI is a good way to handle security";

      // Variables.
      //
      Byte[] pbMessage = null;
      Int32 cbMessage = 0;
      IntPtr[] MessageArray = null;
      Int32[] MessageSizeArray = null;
      IntPtr hStoreHandle = IntPtr.Zero;   
      IntPtr pSignerCert = IntPtr.Zero;
      Crypto.CRYPT_SIGN_MESSAGE_PARA SigParams;
      Boolean res = false;
      Int32 cbSignedMessageBlob = 0;
      Byte[] pbSignedMessageBlob = null;
      Crypto.CRYPT_VERIFY_MESSAGE_PARA VerifyParams;
      Int32 cbDecodedMessageBlob = 0;
      Byte[] pbDecodedMessageBlob = null;

      try 
      {
        // Begin processing. Display the original message.
        //
        Console.WriteLine("-------------------------------------");
        Console.WriteLine("MESSAGE TO SIGN:\n");
        Console.WriteLine(sMessage + "\n\n");

        // Size of message.
        //
        pbMessage = (new UnicodeEncoding()).GetBytes(sMessage);
        cbMessage = pbMessage.Length;

        // Create the MessageArray and the MessageSizeArray.
        //        
        MessageArray = new IntPtr[1];
        MessageArray[0] = Marshal.AllocHGlobal(pbMessage.Length);
        Marshal.Copy(pbMessage, 0, MessageArray[0], pbMessage.Length);
        MessageSizeArray = new Int32[1];
        MessageSizeArray[0] = cbMessage;

        // Open a certificate store.
        //
        hStoreHandle = Crypto.CertOpenStore(
          Crypto.CERT_STORE_PROV_SYSTEM,
          0,
          IntPtr.Zero,
          Crypto.CERT_SYSTEM_STORE_CURRENT_USER,
          Crypto.CERT_PERSONAL_STORE_NAME
        );
        if (hStoreHandle == IntPtr.Zero)
        {
          throw new Exception("CertOpenStore error", new Win32Exception(Marshal.GetLastWin32Error()));
        }

        // Get a pointer to the signer's certificate.
        // This certificate must have access to the signer's private key.
        pSignerCert = Crypto.CertFindCertificateInStore(
          hStoreHandle,
          Crypto.MY_TYPE,
          0,
          Crypto.CERT_FIND_SUBJECT_STR,
          sSignerName,
          IntPtr.Zero
        );
        if (pSignerCert == IntPtr.Zero)
        {
          throw new Exception("CertFindCertificateInStore error", new Win32Exception(Marshal.GetLastWin32Error()));
        }

        // Initialize the signature structure.
        //
        SigParams = new Crypto.CRYPT_SIGN_MESSAGE_PARA();
        SigParams.cbSize = Marshal.SizeOf(SigParams);
        SigParams.dwMsgEncodingType = Crypto.MY_TYPE;
        SigParams.pSigningCert = pSignerCert;
        SigParams.HashAlgorithm.pszObjId = Crypto.szOID_OIWSEC_sha1;
        SigParams.HashAlgorithm.Parameters.pbData = IntPtr.Zero;
        SigParams.HashAlgorithm.Parameters.cbData = 0;
        SigParams.pvHashAuxInfo = IntPtr.Zero;
        SigParams.cMsgCert = 1;

        GCHandle GC = GCHandle.Alloc(pSignerCert, GCHandleType.Pinned);
        SigParams.rgpMsgCert = GC.AddrOfPinnedObject();
        GC.Free();

        SigParams.cMsgCrl = 0;
        SigParams.rgpMsgCrl = IntPtr.Zero;
        SigParams.cAuthAttr = 0;
        SigParams.rgAuthAttr = IntPtr.Zero;
        SigParams.cUnauthAttr = 0;
        SigParams.rgUnauthAttr = IntPtr.Zero;
        SigParams.dwFlags = 0;
        SigParams.dwInnerContentType = 0;

        // With two calls to CryptSignMessage, sign the message.
        // First, get the size of the output signed BLOB.
        //
        res = Crypto.CryptSignMessage(
          ref SigParams,      // Signature parameters
          false,          // Not detached
          1,            // Number of messages
          MessageArray,      // Messages to be signed
          MessageSizeArray,    // Size of messages
          null,          // Buffer for signed message
          ref cbSignedMessageBlob  // Size of buffer
        );
        if (res == false)
        {
          throw new Exception("CryptSignMessage error", new Win32Exception(Marshal.GetLastWin32Error()));
        }

        // Allocate memory for the signed BLOB.
        //
        pbSignedMessageBlob = new Byte[cbSignedMessageBlob];

        // Get the SignedMessageBlob.
        //
        res = Crypto.CryptSignMessage(
          ref SigParams,      // Signature parameters
          false,          // Not detached
          1,            // Number of messages
          MessageArray,      // Messages to be signed
          MessageSizeArray,    // Size of messages
          pbSignedMessageBlob,  // Buffer for signed message
          ref cbSignedMessageBlob // Size of buffer
        );
        if (res == false)
        {
          throw new Exception("CryptSignMessage error", new Win32Exception(Marshal.GetLastWin32Error()));
        }

        // pbSignedMessageBlob points to the signed BLOB. Display the signature.
        //
        Console.WriteLine("-------------------------------------");
        Console.WriteLine("SIGNATURE:\n");
        Console.WriteLine(Convert.ToBase64String(pbSignedMessageBlob) + "\n\n");

        //  Verify the message signature. Usually, this
        //  would be done in a separate program. 
        //

        //  Initialize the VerifyParams data structure.
        //
        VerifyParams = new Crypto.CRYPT_VERIFY_MESSAGE_PARA();
        VerifyParams.cbSize = Marshal.SizeOf(VerifyParams);
        VerifyParams.dwMsgAndCertEncodingType = Crypto.MY_TYPE;
        VerifyParams.hCryptProv = IntPtr.Zero;
        VerifyParams.pfnGetSignerCertificate = IntPtr.Zero;
        VerifyParams.pvGetArg = IntPtr.Zero;

        // With two calls to CryptVerifyMessageSignature, verify and decode
        // the signed message.
        // First, call CryptVerifyMessageSignature to get the length of the
        // buffer needed to hold the decoded message.
        //
        res = Crypto.CryptVerifyMessageSignature(
          ref VerifyParams,      // Verify parameters.
          0,              // Signer index.
          pbSignedMessageBlob,    // Pointer to signed BLOB.
          cbSignedMessageBlob,    // Size of signed BLOB.
          null,            // Buffer for decoded message.
          ref cbDecodedMessageBlob,  // Size of buffer.
          IntPtr.Zero          // Pointer to signer certificate.
        );
        if (res == false)
        {
          throw new Exception("CryptVerifyMessageSignature error", new Win32Exception(Marshal.GetLastWin32Error()));
        }

        //   Allocate memory for the buffer.
        //
        pbDecodedMessageBlob = new Byte[cbDecodedMessageBlob];

        //  Call CryptVerifyMessageSignature again to copy the message into
        //  the buffer.
        //
        res = Crypto.CryptVerifyMessageSignature(
          ref VerifyParams,      // Verify parameters.
          0,              // Signer index.
          pbSignedMessageBlob,    // Pointer to signed BLOB.
          cbSignedMessageBlob,    // Size of signed BLOB.
          pbDecodedMessageBlob,    // Buffer for decoded message.
          ref cbDecodedMessageBlob,  // Size of buffer.
          IntPtr.Zero          // Pointer to signer certificate.
        );
        if (res == false)
        {
          throw new Exception("CryptVerifyMessageSignature error", new Win32Exception(Marshal.GetLastWin32Error()));
        } 
        else 
        {
          // Display attached message to signature.
          //
          Console.WriteLine("-------------------------------------");
          Console.WriteLine("SIGNATURE VERIFIED!!!\n\n");

          Console.WriteLine("-------------------------------------");
          Console.WriteLine("ATTACHED MESSAGE:\n");
          Console.WriteLine((new UnicodeEncoding()).GetString(pbDecodedMessageBlob) + "\n\n");
        }
      }
      catch (Exception ex)
      {
        // Any errors? Show them.
        //
        if (ex.InnerException == null) 
        {
          Console.WriteLine(ex.Message + "\n\n");
        }
        else 
        {
          Console.WriteLine(ex.Message + " --&amp;gt; " + ex.InnerException.Message + "\n\n");
        }
      }
      finally
      {
        // Clean up and free memory.
        //
        if (MessageArray[0] != IntPtr.Zero) 
        {
          Marshal.FreeHGlobal(MessageArray[0]);
        }
        if (pSignerCert != IntPtr.Zero)
        {
          Crypto.CertFreeCertificateContext(pSignerCert);
        }
        if (hStoreHandle != IntPtr.Zero) 
        {
          Crypto.CertCloseStore(
            hStoreHandle, 
            Crypto.CERT_CLOSE_STORE_CHECK_FLAG
          );
        }
      }

      Console.WriteLine("&amp;lt;&amp;lt;Press ENTER to continue&amp;gt;&amp;gt;" + "\n");
      Console.ReadLine();
    }
  }
}
&lt;/PRE&gt;
&lt;P&gt;&amp;lt;/SAMPLE&amp;gt;&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE file="Crypto.cs"&amp;gt;&lt;/P&gt;&lt;PRE class=code&gt;using System;
using System.Runtime.InteropServices;

public class Crypto
{
  #region CONSTS

  // #define CERT_PERSONAL_STORE_NAME      L"My"
  public const string CERT_PERSONAL_STORE_NAME = "My";

  // #define CERT_COMPARE_NAME   2
  public const Int32 CERT_COMPARE_NAME = 2;

  // #define CERT_INFO_SUBJECT_FLAG  7
  public const Int32 CERT_INFO_SUBJECT_FLAG = 7;

  // #define CERT_COMPARE_SHIFT        16
  public const Int32 CERT_COMPARE_SHIFT = 16;

  // #define CERT_FIND_SUBJECT_NAME    (CERT_COMPARE_NAME &amp;lt;&amp;lt; CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
  public const Int32 CERT_FIND_SUBJECT_NAME = 
    (CERT_COMPARE_NAME &amp;lt;&amp;lt; CERT_COMPARE_SHIFT) | CERT_INFO_SUBJECT_FLAG;

  // #define CERT_COMPARE_NAME_STR_W     8
  public const Int32 CERT_COMPARE_NAME_STR_W = 8;

  // #define CERT_FIND_SUBJECT_STR_W     //   (CERT_COMPARE_NAME_STR_W &amp;lt;&amp;lt; CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
  public const Int32 CERT_FIND_SUBJECT_STR_W = 
    (CERT_COMPARE_NAME_STR_W &amp;lt;&amp;lt; CERT_COMPARE_SHIFT) | CERT_INFO_SUBJECT_FLAG;

  // #define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W
  public const Int32 CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W;

  // #define CERT_STORE_PROV_SYSTEM_W      ((LPCSTR) 10)
  public const Int32 CERT_STORE_PROV_SYSTEM_W = 10;

  // #define CERT_STORE_PROV_SYSTEM        CERT_STORE_PROV_SYSTEM_W
  public const Int32 CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W;
  
  // #define CERT_SYSTEM_STORE_CURRENT_USER_ID     1
  public const Int32 CERT_SYSTEM_STORE_CURRENT_USER_ID = 1;

  // #define CERT_SYSTEM_STORE_LOCATION_SHIFT      16
  public const Int32 CERT_SYSTEM_STORE_LOCATION_SHIFT = 16;

  // #define CERT_SYSTEM_STORE_CURRENT_USER          //   (CERT_SYSTEM_STORE_CURRENT_USER_ID &amp;lt;&amp;lt; CERT_SYSTEM_STORE_LOCATION_SHIFT)
  public const Int32 CERT_SYSTEM_STORE_CURRENT_USER = 
    CERT_SYSTEM_STORE_CURRENT_USER_ID &amp;lt;&amp;lt; CERT_SYSTEM_STORE_LOCATION_SHIFT;

  // #define CERT_CLOSE_STORE_CHECK_FLAG       0x00000002
  public const Int32 CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002;

  // #define ALG_CLASS_HASH                  (4 &amp;lt;&amp;lt; 13)
  // #define ALG_TYPE_ANY                    (0)
  // #define ALG_SID_SHA1                    4
  // #define CALG_SHA1               (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
  public const Int32 CALG_SHA1 = (4 &amp;lt;&amp;lt; 13) | 4;

  // #define ALG_CLASS_SIGNATURE             (1 &amp;lt;&amp;lt; 13)
  // #define ALG_TYPE_RSA                    (2 &amp;lt;&amp;lt; 9)
  // #define ALG_SID_RSA_ANY                 0
  // #define CALG_RSA_SIGN           (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY)
  public const Int32 CALG_RSA_SIGN = (1 &amp;lt;&amp;lt; 13) | (2 &amp;lt;&amp;lt; 9);

  // #define PROV_RSA_FULL           1
  public const Int32 PROV_RSA_FULL = 0x00000001;

  // #define CRYPT_VERIFYCONTEXT     0xF0000000
  public const UInt32 CRYPT_VERIFYCONTEXT = 0xF0000000; //No private key access required

  // #define X509_ASN_ENCODING           0x00000001
  public const Int32 X509_ASN_ENCODING = 0x00000001;

  // #define PKCS_7_ASN_ENCODING         0x00010000
  public const Int32 PKCS_7_ASN_ENCODING = 0x00010000;

  // #define MY_TYPE       (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
  public const Int32 MY_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;

  // #define HP_HASHVAL              0x0002
  public const Int32 HP_HASHVAL = 0x00000002;

  // #define HP_HASHSIZE             0x0004
  public const Int32 HP_HASHSIZE = 0x00000004;

  // #define PUBLICKEYBLOBEX 0xA
  public const Int32 PUBLICKEYBLOBEX = 0x0A;

  // #define PUBLICKEYBLOB           0x6
  public const Int32 PUBLICKEYBLOB = 0x06;

  // #define CUR_BLOB_VERSION 0x02
  public const Int32 CUR_BLOB_VERSION = 0x02;

  // #define CRYPT_EXPORTABLE        0x00000001
  public const Int32 CRYPT_EXPORTABLE = 0x00000001;

  // #define szOID_RSA_MD5           "1.2.840.113549.2.5"
  public const String szOID_RSA_MD5 = "1.2.840.113549.2.5";

  // #define szOID_RSA_MD5RSA        "1.2.840.113549.1.1.4"
  public const String szOID_RSA_MD5RSA = "1.2.840.113549.1.1.4";

  // #define szOID_OIWSEC_sha1       "1.3.14.3.2.26"
  public const String szOID_OIWSEC_sha1 = "1.3.14.3.2.26";

  #endregion

  #region STRUCTS

  // typedef struct _PUBLICKEYSTRUC 
  // {
  //    BYTE bType;  
  //    BYTE bVersion;  
  //    WORD reserved;  
  //    ALG_ID aiKeyAlg;
  // } BLOBHEADER, PUBLICKEYSTRUC;
  [StructLayout(LayoutKind.Sequential)]
  public struct PUBLICKEYSTRUC
  {
    public Byte bType;
    public Byte bVersion;
    public Int16 reserved;
    public Int32 aiKeyAlg;
  }

  // typedef struct _RSAPUBKEY 
  // {
  //    DWORD magic;
  //    DWORD bitlen;
  //    DWORD pubexp;
  // } RSAPUBKEY;
  [StructLayout(LayoutKind.Sequential)]
  public struct RSAPUBKEY 
  {
    public Int32 magic;
    public Int32 bitlen;
    public Int32 pubexp;
  }

  // typedef struct _CRYPTOAPI_BLOB 
  // {
  //    DWORD   cbData;
  //    BYTE    *pbData;
  // } CRYPT_HASH_BLOB, CRYPT_INTEGER_BLOB, 
  //   CRYPT_OBJID_BLOB, CERT_NAME_BLOB;
  [StructLayout(LayoutKind.Sequential)]
  public struct CRYPTOAPI_BLOB
  {
    public Int32 cbData;
    public IntPtr pbData;
  }

  // typedef struct _CRYPT_ALGORITHM_IDENTIFIER 
  // {
  //    LPSTR pszObjId;
  //    CRYPT_OBJID_BLOB Parameters;
  // } CRYPT_ALGORITHM_IDENTIFIER;
  [StructLayout(LayoutKind.Sequential)]
  public struct CRYPT_ALGORITHM_IDENTIFIER
  {
    [MarshalAs(UnmanagedType.LPStr)]public String pszObjId;
    public CRYPTOAPI_BLOB Parameters;
  }

  // typedef struct _CRYPT_SIGN_MESSAGE_PARA 
  // {
  //    DWORD cbSize;
  //    DWORD dwMsgEncodingType;
  //    PCCERT_CONTEXT pSigningCert;
  //    CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
  //    void *pvHashAuxInfo;
  //    DWORD cMsgCert;
  //    PCCERT_CONTEXT *rgpMsgCert;
  //    DWORD cMsgCrl;
  //    PCCRL_CONTEXT *rgpMsgCrl;
  //    DWORD cAuthAttr;
  //    PCRYPT_ATTRIBUTE rgAuthAttr;
  //    DWORD cUnauthAttr;
  //    PCRYPT_ATTRIBUTE rgUnauthAttr;
  //    DWORD dwFlags;
  //    DWORD dwInnerContentType;
  // } CRYPT_SIGN_MESSAGE_PARA;
  [StructLayout(LayoutKind.Sequential)]
  public struct CRYPT_SIGN_MESSAGE_PARA 
  {
    public Int32 cbSize;
    public Int32 dwMsgEncodingType;
    public IntPtr pSigningCert;
    public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
    public IntPtr pvHashAuxInfo;
    public Int32 cMsgCert;
    public IntPtr rgpMsgCert;
    public Int32 cMsgCrl;
    public IntPtr rgpMsgCrl;
    public Int32 cAuthAttr;
    public IntPtr rgAuthAttr;
    public Int32 cUnauthAttr;
    public IntPtr rgUnauthAttr;
    public Int32 dwFlags;
    public Int32 dwInnerContentType;
  }

  // typedef struct _CRYPT_VERIFY_MESSAGE_PARA 
  // {
  //    DWORD cbSize;
  //    DWORD dwMsgAndCertEncodingType;
  //    HCRYPTPROV hCryptProv;
  //    PFN_CRYPT_GET_SIGNER_CERTIFICATE pfnGetSignerCertificate;
  //    void *pvGetArg;
  // } CRYPT_VERIFY_MESSAGE_PARA;
  [StructLayout(LayoutKind.Sequential)]
  public struct CRYPT_VERIFY_MESSAGE_PARA 
  {
    public Int32 cbSize;
    public Int32 dwMsgAndCertEncodingType;
    public IntPtr hCryptProv;
    public IntPtr pfnGetSignerCertificate;
    public IntPtr pvGetArg;
  }

  #endregion

  #region FUNCTIONS (IMPORTS)

  // HCERTSTORE WINAPI CertOpenStore(
  //    LPCSTR lpszStoreProvider,
  //    DWORD dwMsgAndCertEncodingType,
  //    HCRYPTPROV hCryptProv,
  //    DWORD dwFlags,
  //    const void* pvPara
  // );
  [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public static extern IntPtr CertOpenStore(
    Int32 lpszStoreProvider,
    Int32 dwMsgAndCertEncodingType,
    IntPtr hCryptProv, 
    Int32 dwFlags, 
    String pvPara
  ); 

  // HCERTSTORE WINAPI CertOpenSystemStore(
  //    HCRYPTPROV hprov,
  //    LPTCSTR szSubsystemProtocol
  // );
  [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public static extern IntPtr CertOpenSystemStore(
    IntPtr hprov, 
    String szSubsystemProtocol
  );

  // BOOL WINAPI CertCloseStore(
  //    HCERTSTORE hCertStore,
  //    DWORD dwFlags
  // );
  [DllImport("Crypt32.dll", SetLastError=true)]
  public static extern Boolean CertCloseStore( 
    IntPtr hCertStore,
    Int32 dwFlags
  );     

  // BOOL WINAPI CryptAcquireContext(
  //    HCRYPTPROV* phProv,
  //    LPCTSTR pszContainer,
  //    LPCTSTR pszProvider,
  //    DWORD dwProvType,
  //    DWORD dwFlags
  // );
  [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public static extern bool CryptAcquireContext(
    ref IntPtr hProv,
    String pszContainer,
    String pszProvider,
    Int32 dwProvType,
    Int32 dwFlags
  );

  // BOOL WINAPI CryptCreateHash(
  //    HCRYPTPROV hProv,
  //    ALG_ID Algid,
  //    HCRYPTKEY hKey,
  //    DWORD dwFlags,
  //    HCRYPTHASH* phHash
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptCreateHash(
    IntPtr hProv,
    Int32 Algid,
    IntPtr hKey,
    Int32 dwFlags,
    ref IntPtr phHash
  );

  // BOOL WINAPI CryptGetHashParam(
  //    HCRYPTHASH hHash,
  //    DWORD dwParam,
  //    BYTE* pbData,
  //    DWORD* pdwDataLen,
  //    DWORD dwFlags
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptGetHashParam(
    IntPtr hHash,
    Int32 dwParam,
    ref Int32 pbData,
    ref Int32 pdwDataLen,
    Int32 dwFlags
  );

  // BOOL WINAPI CryptSetHashParam(
  //    HCRYPTHASH hHash,
  //    DWORD dwParam,
  //    BYTE* pbData,
  //    DWORD dwFlags
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptSetHashParam(
    IntPtr hHash,
    Int32 dwParam,
    Byte[] pbData,
    Int32 dwFlags
  );

  // BOOL WINAPI CryptImportPublicKeyInfo(
  //    HCRYPTPROV hCryptProv,
  //    DWORD dwCertEncodingType,
  //    PCERT_PUBLIC_KEY_INFO pInfo,
  //    HCRYPTKEY* phKey
  // );
  [DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public static extern bool CryptImportPublicKeyInfo(
    IntPtr hCryptProv,
    Int32 dwCertEncodingType,
    IntPtr pInfo,
    ref IntPtr phKey
  );

  // BOOL WINAPI CryptImportKey(
  //    HCRYPTPROV hProv,
  //    BYTE* pbData,
  //    DWORD dwDataLen,
  //    HCRYPTKEY hPubKey,
  //    DWORD dwFlags,
  //    HCRYPTKEY* phKey
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptImportKey(
    IntPtr hProv,
    Byte[] pbData,
    Int32 dwDataLen,
    IntPtr hPubKey,
    Int32 dwFlags,
    ref IntPtr phKey
  );

  // BOOL WINAPI CryptVerifySignature(
  //    HCRYPTHASH hHash,
  //    BYTE* pbSignature,
  //    DWORD dwSigLen,
  //    HCRYPTKEY hPubKey,
  //    LPCTSTR sDescription,
  //    DWORD dwFlags
  // );
  [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public static extern bool CryptVerifySignature(
    IntPtr hHash,
    Byte[] pbSignature,
    Int32 dwSigLen,
    IntPtr hPubKey,
    String sDescription,
    Int32 dwFlags
  );

  // BOOL WINAPI CryptDestroyKey(
  //    HCRYPTKEY hKey
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptDestroyKey(
    IntPtr hKey
  );

  // BOOL WINAPI CryptDestroyHash(
  //    HCRYPTHASH hHash
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptDestroyHash(
    IntPtr hHash
  );

  // BOOL WINAPI CryptReleaseContext(
  //    HCRYPTPROV hProv,
  //    DWORD dwFlags
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptReleaseContext(
    IntPtr hProv,
    Int32 dwFlags
  );

  // BOOL WINAPI CryptGenKey(
  //    HCRYPTPROV hProv,
  //    ALG_ID Algid,
  //    DWORD dwFlags,
  //    HCRYPTKEY* phKey
  // );  
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptGenKey(
    IntPtr hProv,
    Int32 Algid,
    Int32 dwFlags,
    ref IntPtr phKey
  );

  // BOOL WINAPI CryptExportKey(
  //    HCRYPTKEY hKey,
  //    HCRYPTKEY hExpKey,
  //    DWORD dwBlobType,
  //    DWORD dwFlags,
  //    BYTE* pbData,
  //    DWORD* pdwDataLen
  // );
  [DllImport("advapi32.dll", SetLastError=true)]
  public static extern bool CryptExportKey(
    IntPtr hKey,
    IntPtr hExpKey,
    Int32 dwBlobType,
    Int32 dwFlags,
    Byte[] pbData,
    ref Int32 pdwDataLen
  );

  // PCCERT_CONTEXT WINAPI CertFindCertificateInStore(
  //    HCERTSTORE hCertStore,
  //    DWORD dwCertEncodingType,
  //    DWORD dwFindFlags,
  //    DWORD dwFindType,
  //    const void* pvFindPara,
  //    PCCERT_CONTEXT pPrevCertContext
  // );
  [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
  public static extern IntPtr CertFindCertificateInStore(
    IntPtr hCertStore, 
    Int32 dwCertEncodingType,
    Int32 dwFindFlags,
    Int32 dwFindType,
    String pvFindPara,
    IntPtr pPrevCertContext
  );

  // BOOL WINAPI CertFreeCertificateContext(
  //    PCCERT_CONTEXT pCertContext
  // );
  [DllImport("Crypt32.dll", SetLastError=true)]
  public static extern Boolean CertFreeCertificateContext(
    IntPtr pCertContext
  );

  // BOOL WINAPI CryptSignMessage(
  //    PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  //    BOOL fDetachedSignature,
  //    DWORD cToBeSigned,
  //    const BYTE* rgpbToBeSigned[],
  //    DWORD rgcbToBeSigned[],
  //    BYTE* pbSignedBlob,
  //    DWORD* pcbSignedBlob
  // );
  [DllImport("Crypt32.dll", SetLastError=true)]
  public static extern Boolean CryptSignMessage (
    ref CRYPT_SIGN_MESSAGE_PARA pSignPara,
    Boolean fDetachedSignature,
    Int32 cToBeSigned,
    IntPtr[] rgpbToBeSigned,
    Int32[] rgcbToBeSigned,
    Byte[] pbSignedBlob,
    ref Int32 pcbSignedBlob
  );

  // BOOL WINAPI CryptVerifyMessageSignature(
  //    PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  //    DWORD dwSignerIndex,
  //    const BYTE* pbSignedBlob,
  //    DWORD cbSignedBlob,
  //    BYTE* pbDecoded,
  //    DWORD* pcbDecoded,
  //    PCCERT_CONTEXT* ppSignerCert
  // );
  [DllImport("Crypt32.dll", SetLastError=true)]
  public static extern Boolean CryptVerifyMessageSignature (
    ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
    Int32 dwSignerIndex,
    Byte[] pbSignedBlob,
    Int32 cbSignedBlob,
    Byte[] pbDecoded,
    ref Int32 pcbDecoded,
    IntPtr ppSignerCert
  );

  #endregion 

  #region FUNTIONS

  // Helper function to convert struts &amp;amp; classes to byte array
  public static byte[] RawSerialize(object anything) 
  { 
    int rawsize = Marshal.SizeOf(anything); 
    IntPtr buffer = Marshal.AllocHGlobal(rawsize); 
    Marshal.StructureToPtr(anything, buffer, false); 
    byte[] rawdatas = new byte[rawsize]; 
    Marshal.Copy(buffer, rawdatas, 0, rawsize); 
    Marshal.FreeHGlobal(buffer); 
    return rawdatas; 
  } 

  #endregion

}
&lt;/PRE&gt;
&lt;P&gt;&amp;lt;/SAMPLE&amp;gt;&lt;BR&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Note: I know there are easier ways now in .NET to handle certificate stores (&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.aspx"&gt;X509Store&lt;/A&gt;) and certificates (&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx"&gt;X509Certificate2&lt;/A&gt;), but I decided to include the P/Invoke declarations in case you need them and for illustration purposes.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7839988" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category></item><item><title>How to sign EXE files with an Authenticode certificate (VB.NET)</title><link>http://blogs.msdn.com/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx</link><pubDate>Wed, 20 Feb 2008 11:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7813173</guid><dc:creator>alejacma</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/7813173.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=7813173</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;Sorry it took me so long to write a new post. I'm visiting my colleagues at Milano, and I'm horribly busy these days.&lt;/P&gt;
&lt;P&gt;For Windows platforms, below are the only supported methods we can use to digitally sign &lt;STRONG&gt;Authenticode&lt;/STRONG&gt; executables:&lt;/P&gt;
&lt;P&gt;1) We can use the old &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/9sh96ycy(vs.80).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/9sh96ycy(vs.80).aspx"&gt;SignCode.exe&lt;/A&gt; tool (shipped with Authenticode tool for IE or SDK or VS.NET) for signing. SignCode.exe is an old tool from Microsoft to sign Authenticode executables (EXE, DLL, MSI). Newer version of the tool is named &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa387764.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa387764.aspx"&gt;SignTool.exe&lt;/A&gt;. SignTool.exe is shipped with Microsoft Platform SDK. It is preferred to use the newer SignTool.exe tool. Please note that the command line options for SignTool.exe are different from SignCode.exe. &lt;/P&gt;
&lt;P&gt;2) We can programmatically use &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa380292(VS.85).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa380292(VS.85).aspx"&gt;CryptUIWizDigitalSign&lt;/A&gt; API for signing Authenticode executables (MSI, EXE, DLL) (Note this API is only available on Windows XP or above). Additionally, &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa387712(VS.85).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa387712(VS.85).aspx"&gt;CAPICOM.SignedCode&lt;/A&gt; essentially does the same thing.&lt;/P&gt;
&lt;P&gt;The following sample shows how to use &lt;STRONG&gt;CryptUIWizDigitalSign&lt;/STRONG&gt; in &lt;STRONG&gt;.NET 2.0&lt;/STRONG&gt;&amp;nbsp;through &lt;STRONG&gt;P/Invoke&lt;/STRONG&gt;:&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE file="Crypto.vb"&amp;gt;&lt;/P&gt;&lt;PRE&gt;Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class Crypto

    ' #define CRYPTUI_WIZ_NO_UI     1
    Public Const CRYPTUI_WIZ_NO_UI As Int32 = 1

    ' #define CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE     0x01
    Public Const CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE As Int32 = 1

    ' #define CRYPTUI_WIZ_DIGITAL_SIGN_CERT                    0x01
    Public Const CRYPTUI_WIZ_DIGITAL_SIGN_CERT As Int32 = 1

    ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_INFO {  
    '   DWORD dwSize;  
    '   DWORD dwSubjectChoice;  
    '   union {    
    '       LPCWSTR pwszFileName;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO pSignBlobInfo;  
    '   };  
    '   DWORD dwSigningCertChoice;  
    '   union {    
    '       PCCERT_CONTEXT pSigningCertContext;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO pSigningCertStore;    
    '       PCCRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pSigningCertPvkInfo;  
    '   };  
    '   LPCWSTR pwszTimestampURL;  
    '   DWORD dwAdditionalCertChoice;  
    '   PCCRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO pSignExtInfo;
    ' } CRYPTUI_WIZ_DIGITAL_SIGN_INFO;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CRYPTUI_WIZ_DIGITAL_SIGN_INFO
        Public dwSize As Int32
        Public dwSubjectChoice As Int32
        &amp;lt;MarshalAs(UnmanagedType.LPWStr)&amp;gt; Public pwszFileName As String
        Public dwSigningCertChoice As Int32
        Public pSigningCertContext As IntPtr
        Public pwszTimestampURL As String
        Public dwAdditionalCertChoice As Int32
        Public pSignExtInfo As IntPtr
    End Structure

    ' typedef struct _CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT {  
    '      DWORD dwSize;  
    '      DWORD cbBlob;  
    '      BYTE* pbBlob;
    ' } CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
        Public dwSize As Int32
        Public cbBlob As Int32
        Public pbBlob As IntPtr
    End Structure

    ' BOOL WINAPI CryptUIWizDigitalSign(
    '      DWORD dwFlags,
    '      HWND hwndParent,
    '      LPCWSTR pwszWizardTitle,
    '      PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO pDigitalSignInfo,
    '      PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT* ppSignContext
    ' );
    &amp;lt;DllImport("Cryptui.dll", CharSet:=CharSet.Unicode, SetLastError:=True)&amp;gt; _
    Public Shared Function CryptUIWizDigitalSign( _
        ByVal dwFlags As Int32, _
        ByVal hwndParent As IntPtr, _
        ByVal pwszWizardTitle As String, _
        ByRef pDigitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO, _
        ByRef ppSignContext As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptUIWizFreeDigitalSignContext(
    '   PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT pSignContext
    ' );
    &amp;lt;DllImport("Cryptui.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CryptUIWizFreeDigitalSignContext( _
        ByVal pSignContext As IntPtr _
    ) As Boolean
    End Function

End Class
&lt;/PRE&gt;
&lt;P&gt;&amp;lt;/SAMPLE&amp;gt;&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE file="Module1.vb"&amp;gt;&lt;/P&gt;&lt;PRE&gt;Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports SignExe.Crypto
Imports System.Security.Cryptography.X509Certificates
Imports System.IO

Module Module1

    Sub Main()
        ' Variables
        '
        Dim cert As X509Certificate2
        Dim digitalSignInfo As CRYPTUI_WIZ_DIGITAL_SIGN_INFO
        Dim pSignContext As IntPtr
        Dim pSigningCertContext As IntPtr
        Dim signContext As CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
        Dim fileOut As FileStream
        Dim binWriter As BinaryWriter
        Dim blob() As Byte

        Try
            ' Get certificate context
            '
            cert = New X509Certificate2("C:\Test\MyCert.pfx", "")
            pSigningCertContext = cert.Handle

            ' Prepare signing info: exe and cert
            '
            digitalSignInfo = New CRYPTUI_WIZ_DIGITAL_SIGN_INFO
            digitalSignInfo.dwSize = Marshal.SizeOf(digitalSignInfo)
            digitalSignInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE
            digitalSignInfo.pwszFileName = "C:\Test\notepad.exe"
            digitalSignInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_CERT
            digitalSignInfo.pSigningCertContext = pSigningCertContext
            digitalSignInfo.pwszTimestampURL = vbNullString
            digitalSignInfo.dwAdditionalCertChoice = 0
            digitalSignInfo.pSignExtInfo = IntPtr.Zero

            ' Sign exe
            '
            If (Not CryptUIWizDigitalSign( _
                CRYPTUI_WIZ_NO_UI, _
                IntPtr.Zero, _
                vbNullString, _
                digitalSignInfo, _
                pSignContext _
            )) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizDigitalSign")
            End If

            ' Get the blob with the signature
            '
            signContext = Marshal.PtrToStructure(pSignContext, GetType(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT))
            blob = New Byte(signContext.cbBlob) {}
            Marshal.Copy(signContext.pbBlob, blob, 0, signContext.cbBlob)

            ' Store the signature in a new file
            '
            fileOut = File.Open("C:\Test\signature.sig", FileMode.Create)
            binWriter = New BinaryWriter(fileOut)
            binWriter.Write(blob)
            binWriter.Close()
            fileOut.Close()

            ' Free blob
            '
            If (Not CryptUIWizFreeDigitalSignContext(pSignContext)) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error(), "CryptUIWizFreeDigitalSignContext")
            End If

            ' We are done
            Console.WriteLine("Done!!!")

        Catch ex As Win32Exception
            ' Any expected errors?
            '
            Console.WriteLine(ex.Message + " error#" + ex.NativeErrorCode.ToString)
        Catch ex As Exception
            ' Any unexpected errors?
            '
            Console.WriteLine(ex.Message)
        End Try

        ' We are done
        '
        Console.WriteLine("&amp;lt;&amp;lt; Press any key to continue &amp;gt;&amp;gt;")
        Console.ReadKey()

    End Sub

End Module
&lt;/PRE&gt;
&lt;P&gt;&amp;lt;/SAMPLE&amp;gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PS: You may find more info and samples about this on &lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx"&gt;How to sign EXE files with an Authenticode certificate (part 2) &lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7813173" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category></item><item><title>How to call CreateProcessWithLogonW &amp; CreateProcessAsUser in .NET</title><link>http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx</link><pubDate>Thu, 20 Dec 2007 16:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6817283</guid><dc:creator>alejacma</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/6817283.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=6817283</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;Sometimes&amp;nbsp;&lt;STRONG&gt;.NET&lt;/STRONG&gt;'s &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.aspx"&gt;System.Diagnostics.Process&lt;/A&gt; class and its &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.start.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.process.start.aspx"&gt;Start &lt;/A&gt;method are not enough for our purposes and we need to call Win32 API directly from .NET (&lt;STRONG&gt;P/Invoke&lt;/STRONG&gt; mechanism) to be able to create a process the way we need. Here you have a sample you might find useful. It includes P/Invoke declarations and usage samples of some very famous API: &lt;STRONG&gt;LogonUser&lt;/STRONG&gt;, &lt;STRONG&gt;CreateProcessAsUser&lt;/STRONG&gt; and &lt;STRONG&gt;CreateProcessWithLogonW&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE&amp;gt;&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Text;

namespace CreateProcessSample
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Test with CreateProcessWithLogonW...");
                Win32.LaunchCommand1("\\\\server\\tests\\Batch.cmd", "domain", "user", "password");
                Console.WriteLine("Test with CreateProcessAsUser...");
                Win32.LaunchCommand2("\\\\server\\tests\\Batch.cmd", "domain", "user", "password");
            }
            catch (Exception ex)
            {
                Console.WriteLine("LaunchCommand error: " + ex.Message);
            }
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

//--------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;

namespace CreateProcessSample
{
    class Win32
    {
        #region "CONTS"

        const UInt32 INFINITE = 0xFFFFFFFF;
        const UInt32 WAIT_FAILED = 0xFFFFFFFF;

        #endregion

        #region "ENUMS"

        [Flags]
        public enum LogonType
        {
            LOGON32_LOGON_INTERACTIVE = 2,
            LOGON32_LOGON_NETWORK = 3,
            LOGON32_LOGON_BATCH = 4,
            LOGON32_LOGON_SERVICE = 5,
            LOGON32_LOGON_UNLOCK = 7,
            LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
            LOGON32_LOGON_NEW_CREDENTIALS = 9
        }

        [Flags]
        public enum LogonProvider
        {
            LOGON32_PROVIDER_DEFAULT = 0,
            LOGON32_PROVIDER_WINNT35,
            LOGON32_PROVIDER_WINNT40,
            LOGON32_PROVIDER_WINNT50
        }

        #endregion

        #region "STRUCTS"

        [StructLayout(LayoutKind.Sequential)]
        public struct STARTUPINFO
        {
            public Int32 cb;
            public String lpReserved;
            public String lpDesktop;
            public String lpTitle;
            public Int32 dwX;
            public Int32 dwY;
            public Int32 dwXSize;
            public Int32 dwYSize;
            public Int32 dwXCountChars;
            public Int32 dwYCountChars;
            public Int32 dwFillAttribute;
            public Int32 dwFlags;
            public Int16 wShowWindow;
            public Int16 cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public Int32 dwProcessId;
            public Int32 dwThreadId;
        }

        #endregion

        #region "FUNCTIONS (P/INVOKE)"

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern Boolean LogonUser 
        (
            String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            LogonType dwLogonType,
            LogonProvider dwLogonProvider,
            out IntPtr phToken
        );

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean CreateProcessAsUser 
        (
            IntPtr hToken,
            String lpApplicationName,
            String lpCommandLine,
            IntPtr lpProcessAttributes,
            IntPtr lpThreadAttributes,
            Boolean bInheritHandles,
            Int32 dwCreationFlags,
            IntPtr lpEnvironment,
            String lpCurrentDirectory,
            ref STARTUPINFO lpStartupInfo,
            out PROCESS_INFORMATION lpProcessInformation
        );

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern Boolean CreateProcessWithLogonW 
        (
            String lpszUsername, 
            String lpszDomain, 
            String lpszPassword,
            Int32 dwLogonFlags, 
            String applicationName, 
            String commandLine,
            Int32 creationFlags, 
            IntPtr environment,
            String currentDirectory,
            ref STARTUPINFO sui,
            out PROCESS_INFORMATION processInfo
        );

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern UInt32 WaitForSingleObject 
        (
            IntPtr hHandle,
            UInt32 dwMilliseconds
        );

        [DllImport("kernel32", SetLastError=true)]
        public static extern Boolean CloseHandle (IntPtr handle);
 
        #endregion

        #region "FUNCTIONS"

        public static void LaunchCommand1(string strCommand, string strDomain, string strName, string strPassword)
        {
            // Variables
            PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
            STARTUPINFO startInfo = new STARTUPINFO();
            bool bResult = false;
            UInt32 uiResultWait = WAIT_FAILED;

            try 
            {
                // Create process
                startInfo.cb = Marshal.SizeOf(startInfo);

                bResult = CreateProcessWithLogonW(
                    strName, 
                    strDomain, 
                    strPassword, 
                    0, 
                    null,
                    strCommand, 
                    0, 
                    IntPtr.Zero, 
                    null, 
                    ref startInfo, 
                    out processInfo
                );
                if (!bResult) { throw new Exception("CreateProcessWithLogonW error #" + Marshal.GetLastWin32Error().ToString()); }

                // Wait for process to end
                uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
                if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }

            } 
            finally
            {
                // Close all handles
                CloseHandle(processInfo.hProcess);
                CloseHandle(processInfo.hThread);
            }
        }

        public static void LaunchCommand2(string strCommand, string strDomain, string strName, string strPassword)
        {
            // Variables
            PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
            STARTUPINFO startInfo = new STARTUPINFO();
            Boolean bResult = false;
            IntPtr hToken = IntPtr.Zero;
            UInt32 uiResultWait = WAIT_FAILED;
            
            try 
            {
                // Logon user
                bResult = Win32.LogonUser(
                    strName,
                    strDomain,
                    strPassword,
                    Win32.LogonType.LOGON32_LOGON_INTERACTIVE,
                    Win32.LogonProvider.LOGON32_PROVIDER_DEFAULT,
                    out hToken
                );
                if (!bResult) { throw new Exception("Logon error #" + Marshal.GetLastWin32Error()); }

                // Create process
                startInfo.cb = Marshal.SizeOf(startInfo);
                startInfo.lpDesktop = "winsta0\\default";

                bResult = Win32.CreateProcessAsUser(
                    hToken, 
                    null, 
                    strCommand, 
                    IntPtr.Zero,
                    IntPtr.Zero,
                    false,
                    0,
                    IntPtr.Zero,
                    null,
                    ref startInfo,
                    out processInfo
                );
                if (!bResult) { throw new Exception("CreateProcessAsUser error #" + Marshal.GetLastWin32Error()); }

                // Wait for process to end
                uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
                if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }
            }
            finally 
            {
                // Close all handles
                CloseHandle(hToken);
                CloseHandle(processInfo.hProcess);
                CloseHandle(processInfo.hThread);
            }
        }

        #endregion
    }
}
&lt;/PRE&gt;
&lt;P&gt;&lt;BR&gt;&amp;lt;/SAMPLE&amp;gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6817283" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category></item><item><title>P/Invoking CryptoAPI in .NET (VB.NET version) </title><link>http://blogs.msdn.com/alejacma/archive/2007/11/26/p-invoking-cryptoapi-in-net-vb-net-version.aspx</link><pubDate>Mon, 26 Nov 2007 14:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6484629</guid><dc:creator>alejacma</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/6484629.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=6484629</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;This is a continuation of my previous post, &lt;A class="" title="P/Invoking CryptoAPI in .NET (C# version)" href="http://blogs.msdn.com/alejacma/archive/2007/11/23/p-invoking-cryptoapi-in-net-c-version.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/11/23/p-invoking-cryptoapi-in-net-c-version.aspx"&gt;P/Invoking CryptoAPI in .NET (C# version)&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Here you have the&amp;nbsp;most common &lt;STRONG&gt;P/Invoke&lt;/STRONG&gt; CryptoAPI declarations I've successfully used in the past, but this time for &lt;STRONG&gt;VB.NET (&lt;/STRONG&gt;Note: I've included a couple&amp;nbsp;of auxiliary functions which may&amp;nbsp;be of help, too.&amp;nbsp;&lt;STRONG&gt;CertContextFromCertSubject&lt;/STRONG&gt; gets&amp;nbsp;a certificate context from a certificate in&amp;nbsp;MY/Personal certificate store, and&amp;nbsp;&lt;STRONG&gt;RSACryptoServiceProviderFromCertContext&lt;/STRONG&gt; creates an RSACryptoServiceProvider object from that certificate context. I don't have them in C#, but they should be easy to convert):&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE&amp;gt;&lt;/P&gt;&lt;PRE&gt;Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports System.ComponentModel

Public Class Crypto

#Region "CONSTS"

    ' #define BUFSIZE   1024
    Public Const BUFSIZE As Int32 = 1024

    ' #define AT_KEYEXCHANGE        1
    Public Const AT_KEYEXCHANGE As Int32 = 1

    ' #define AT_SIGNATURE      2
    Public Const AT_SIGNATURE As Int32 = 2

    ' #define CERT_STORE_PROV_SYSTEM_W      ((LPCSTR) 10)
    Public Const CERT_STORE_PROV_SYSTEM_W As Int32 = 10

    ' #define CERT_STORE_PROV_SYSTEM        CERT_STORE_PROV_SYSTEM_W
    Public Const CERT_STORE_PROV_SYSTEM As Int32 = CERT_STORE_PROV_SYSTEM_W

    ' #define CERT_SYSTEM_STORE_CURRENT_USER_ID     1
    Public Const CERT_SYSTEM_STORE_CURRENT_USER_ID As Int32 = 1

    ' #define CERT_SYSTEM_STORE_LOCATION_SHIFT      16
    Public Const CERT_SYSTEM_STORE_LOCATION_SHIFT As Int32 = 16

    ' #define CERT_SYSTEM_STORE_CURRENT_USER        \
    '   (CERT_SYSTEM_STORE_CURRENT_USER_ID &amp;lt;&amp;lt; CERT_SYSTEM_STORE_LOCATION_SHIFT)
    Public Const CERT_SYSTEM_STORE_CURRENT_USER As Int32 = _
        CERT_SYSTEM_STORE_CURRENT_USER_ID &amp;lt;&amp;lt; CERT_SYSTEM_STORE_LOCATION_SHIFT

    ' #define CERT_PERSONAL_STORE_NAME      L"My"
    Public Const CERT_PERSONAL_STORE_NAME As String = "My"

    ' #define X509_ASN_ENCODING     0x00000001
    Public Const X509_ASN_ENCODING As Int32 = &amp;amp;H1

    ' #define PKCS_7_ASN_ENCODING       0x00010000
    Public Const PKCS_7_ASN_ENCODING As Int32 = &amp;amp;H10000

    ' #define MY_TYPE       (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
    Public Const MY_TYPE As Int32 = PKCS_7_ASN_ENCODING + X509_ASN_ENCODING

    ' #define CERT_COMPARE_ANY      0
    Public Const CERT_COMPARE_ANY As Int32 = 0

    ' #define CERT_COMPARE_SHA1_HASH        1
    Public Const CERT_COMPARE_SHA1_HASH As Int32 = 1

    ' #define CERT_COMPARE_SHIFT        16
    Public Const CERT_COMPARE_SHIFT As Int32 = 16

    ' #define CERT_FIND_SHA1_HASH       (CERT_COMPARE_SHA1_HASH &amp;lt;&amp;lt; CERT_COMPARE_SHIFT)
    Public Const CERT_FIND_SHA1_HASH As Int32 = CERT_COMPARE_SHA1_HASH &amp;lt;&amp;lt; CERT_COMPARE_SHIFT

    ' #define CERT_FIND_HASH        CERT_FIND_SHA1_HASH
    Public Const CERT_FIND_HASH As Int32 = CERT_FIND_SHA1_HASH

    ' #define CERT_FIND_ANY     (CERT_COMPARE_ANY &amp;lt;&amp;lt; CERT_COMPARE_SHIFT)
    Public Const CERT_FIND_ANY As Int32 = CERT_COMPARE_ANY &amp;lt;&amp;lt; CERT_COMPARE_SHIFT

    ' #define CERT_COMPARE_NAME   2
    Public Const CERT_COMPARE_NAME As Int32 = 2

    ' #define CERT_INFO_SUBJECT_FLAG  7
    Public Const CERT_INFO_SUBJECT_FLAG As Int32 = 7

    ' #define CERT_FIND_SUBJECT_NAME    (CERT_COMPARE_NAME &amp;lt;&amp;lt; CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
    Public Const CERT_FIND_SUBJECT_NAME As Int32 = (CERT_COMPARE_NAME &amp;lt;&amp;lt; CERT_COMPARE_SHIFT) + CERT_INFO_SUBJECT_FLAG

    ' #define CERT_COMPARE_NAME_STR_W     8
    Public Const CERT_COMPARE_NAME_STR_W As Int32 = 8

    ' #define CERT_FIND_SUBJECT_STR_W   \
    '   (CERT_COMPARE_NAME_STR_W &amp;lt;&amp;lt; CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
    Public Const CERT_FIND_SUBJECT_STR_W As Int32 = (CERT_COMPARE_NAME_STR_W &amp;lt;&amp;lt; CERT_COMPARE_SHIFT) + CERT_INFO_SUBJECT_FLAG

    ' #define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W
    Public Const CERT_FIND_SUBJECT_STR As Int32 = CERT_FIND_SUBJECT_STR_W

    ' #define CERT_CLOSE_STORE_CHECK_FLAG       0x00000002
    Public Const CERT_CLOSE_STORE_CHECK_FLAG As Int32 = &amp;amp;H2

    ' #define ALG_CLASS_HASH        (4 &amp;lt;&amp;lt; 13)
    Public Const ALG_CLASS_HASH As Int32 = 4 &amp;lt;&amp;lt; 13

    ' #define ALG_TYPE_ANY      (0)
    Public Const ALG_TYPE_ANY As Int32 = 0

    ' #define ALG_SID_MD5       3
    Public Const ALG_SID_MD5 As Int32 = 3

    ' #define ALG_SID_SHA1      4
    Public Const ALG_SID_SHA1 As Int32 = 4

    ' #define CALG_MD5      (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5)
    Public Const CALG_MD5 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_MD5

    ' #define CALG_SHA1     (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
    Public Const CALG_SHA1 As Int32 = ALG_CLASS_HASH + ALG_TYPE_ANY + ALG_SID_SHA1

    ' #define PP_KEYEXCHANGE_PIN        32
    Public Const PP_KEYEXCHANGE_PIN As Int32 = 32

    ' #define PP_SIGNATURE_PIN      33
    Public Const PP_SIGNATURE_PIN As Int32 = 33

    ' #define PROV_RSA_FULL     1
    Public Const PROV_RSA_FULL As Int32 = &amp;amp;H1

    ' #define CRYPT_VERIFYCONTEXT       0xF0000000
    Public Const CRYPT_VERIFYCONTEXT As Int32 = &amp;amp;HF0000000

    ' #define CERT_KEY_PROV_INFO_PROP_ID    2
    Public Const CERT_KEY_PROV_INFO_PROP_ID As Int32 = 2

#End Region

#Region "STRUCTS"

    ' typedef struct _CRYPTOAPI_BLOB {
    '   DWORD   cbData;
    '   BYTE    *pbData;
    ' } CRYPT_HASH_BLOB, CRYPT_INTEGER_BLOB, 
    '   CRYPT_OBJID_BLOB, CERT_NAME_BLOB;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CRYPTOAPI_BLOB
        Public cbData As Int32
        Public pbData As IntPtr
    End Structure

    ' typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
    '   LPSTR               pszObjId;
    '   CRYPT_OBJID_BLOB    Parameters;
    ' } CRYPT_ALGORITHM_IDENTIFIER;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CRYPT_ALGORITHM_IDENTIFIER
        &amp;lt;MarshalAs(UnmanagedType.LPStr)&amp;gt; Public pszObjId As String
        Public Parameters As CRYPTOAPI_BLOB
    End Structure

    ' typedef struct _FILETIME {
    '   DWORD dwLowDateTime;
    '   DWORD dwHighDateTime;
    ' } FILETIME;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure FILETIME
        Public dwLowDateTime As Int32
        Public dwHighDateTime As Int32
    End Structure

    ' typedef struct _CRYPT_BIT_BLOB {
    '   DWORD   cbData;
    '   BYTE    *pbData;
    '   DWORD   cUnusedBits;
    ' } CRYPT_BIT_BLOB;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CRYPT_BIT_BLOB
        Public cbData As Int32
        Public pbData As Byte()
        Public cUnusedBits As Int32
    End Structure

    ' typedef struct _CERT_PUBLIC_KEY_INFO {
    '   CRYPT_ALGORITHM_IDENTIFIER    Algorithm;
    '   CRYPT_BIT_BLOB                PublicKey;
    ' } CERT_PUBLIC_KEY_INFO;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CERT_PUBLIC_KEY_INFO
        Public Algorithm As CRYPT_ALGORITHM_IDENTIFIER
        Public PublicKey As CRYPT_BIT_BLOB
    End Structure

    ' typedef struct _CERT_INFO {
    '   DWORD                       dwVersion;
    '   CRYPT_INTEGER_BLOB          SerialNumber;
    '   CRYPT_ALGORITHM_IDENTIFIER  SignatureAlgorithm;
    '   CERT_NAME_BLOB              Issuer;
    '   FILETIME                    NotBefore;
    '   FILETIME                    NotAfter;
    '   CERT_NAME_BLOB              Subject;
    '   CERT_PUBLIC_KEY_INFO        SubjectPublicKeyInfo;
    '   CRYPT_BIT_BLOB              IssuerUniqueId;
    '   CRYPT_BIT_BLOB              SubjectUniqueId;
    '   DWORD                       cExtension;
    '   PCERT_EXTENSION             rgExtension;
    ' } CERT_INFO;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CERT_INFO
        Public dwVersion As Int32
        Public SerialNumber As CRYPTOAPI_BLOB
        Public SignatureAlgorithm As CRYPT_ALGORITHM_IDENTIFIER
        Public Issuer As CRYPTOAPI_BLOB
        Public NotBefore As FILETIME
        Public NotAfter As FILETIME
        Public Subject As CRYPTOAPI_BLOB
        Public SubjectPublicKeyInfo As CERT_PUBLIC_KEY_INFO
        Public IssuerUniqueId As CRYPT_BIT_BLOB
        Public SubjectUniqueId As CRYPT_BIT_BLOB
        Public cExtension As Int32
        Public rgExtension As IntPtr
    End Structure

    ' typedef struct _CERT_CONTEXT {
    '   DWORD                   dwCertEncodingType;
    '   BYTE                    *pbCertEncoded;
    '   DWORD                   cbCertEncoded;
    '   PCERT_INFO              pCertInfo;
    '   HCERTSTORE              hCertStore;
    ' } CERT_CONTEXT;
    &amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt; _
    Public Structure CERT_CONTEXT
        Public dwCertEncodingType As Int32
        Public pbCertEncoded As Byte()
        Public cbCertEncoded As Int32
        Public pCertInfo As IntPtr
        Public hCertStore As IntPtr
    End Structure

#End Region

#Region "FUNCTIONS (IMPORTS)"

    ' HCERTSTORE WINAPI CertOpenStore(
    '   LPCSTR lpszStoreProvider,
    '   DWORD dwMsgAndCertEncodingType,
    '   HCRYPTPROV hCryptProv,
    '   DWORD dwFlags,
    '   const void* pvPara
    ' );
    &amp;lt;DllImport("Crypt32.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CertOpenStore( _
        ByVal lpszStoreProvider As Int32, _
        ByVal dwMsgAndCertEncodingType As Int32, _
        ByVal hCryptProv As IntPtr, _
        ByVal dwFlags As Int32, _
        ByVal pvPara As String _
    ) As IntPtr
    End Function

    ' HCERTSTORE WINAPI CertOpenSystemStore(
    '   HCRYPTPROV hprov,
    '   LPTCSTR szSubsystemProtocol
    ');
    &amp;lt;DllImport("Crypt32.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CertOpenSystemStore( _
        ByVal hprov As IntPtr, _
        ByVal szSubsystemProtocol As String _
    ) As IntPtr
    End Function

    ' PCCERT_CONTEXT WINAPI CertFindCertificateInStore(
    '   HCERTSTORE hCertStore,
    '   DWORD dwCertEncodingType,
    '   DWORD dwFindFlags,
    '   DWORD dwFindType,
    '   const void* pvFindPara,
    '   PCCERT_CONTEXT pPrevCertContext
    ' );
    '&amp;lt;DllImport("Crypt32.dll", SetLastError:=True)&amp;gt; _
    'Public Shared Function CertFindCertificateInStore( _
    '    ByVal hCertStore As IntPtr, _
    '    ByVal dwCertEncodingType As Int32, _
    '    ByVal dwFindFlags As Int32, _
    '    ByVal dwFindType As Int32, _
    '    ByRef pvFindPara As CRYPTOAPI_BLOB, _
    '    ByVal pPrevCertContext As IntPtr _
    ') As IntPtr
    'End Function
    &amp;lt;DllImport("Crypt32.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CertFindCertificateInStore( _
        ByVal hCertStore As IntPtr, _
        ByVal dwCertEncodingType As Int32, _
        ByVal dwFindFlags As Int32, _
        ByVal dwFindType As Int32, _
        ByVal pvFindPara As String, _
        ByVal pPrevCertContext As IntPtr _
    ) As IntPtr
    End Function

    ' BOOL WINAPI CryptAcquireCertificatePrivateKey(
    '   PCCERT_CONTEXT pCert,
    '   DWORD dwFlags,
    '   void* pvReserved,
    '   HCRYPTPROV* phCryptProv,
    '   DWORD* pdwKeySpec,
    '   BOOL* pfCallerFreeProv
    ' );
    &amp;lt;DllImport("Crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptAcquireCertificatePrivateKey( _
        ByVal pCert As IntPtr, _
        ByVal dwFlags As Int32, _
        ByVal pvReserverd As IntPtr, _
        ByRef phCryptProv As IntPtr, _
        ByRef pdwKeySpec As Int32, _
        ByRef pfCallerFreeProv As Boolean _
    ) As Boolean
    End Function

    ' BOOL WINAPI CertCloseStore(
    '   HCERTSTORE hCertStore,
    '   DWORD dwFlags
    ' );
    &amp;lt;DllImport("Crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CertCloseStore( _
        ByVal hCertStore As IntPtr, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptReleaseContext(
    '   HCRYPTPROV hProv,
    '   DWORD dwFlags
    ' );
    &amp;lt;DllImport("Advapi32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptReleaseContext( _
        ByVal hProv As IntPtr, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptCreateHash(
    '   HCRYPTPROV hProv,
    '   ALG_ID Algid,
    '   HCRYPTKEY hKey,
    '   DWORD dwFlags,
    '   HCRYPTHASH* phHash
    ' );
    &amp;lt;DllImport("advapi32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptCreateHash( _
        ByVal hProv As IntPtr, _
        ByVal Algid As Int32, _
        ByVal hKey As IntPtr, _
        ByVal dwFlags As Int32, _
        ByRef phHash As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptDestroyHash(
    '   HCRYPTHASH hHash
    ' );
    &amp;lt;DllImport("advapi32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptDestroyHash( _
        ByVal hHash As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptSetProvParam(
    '   HCRYPTPROV hProv,
    '   DWORD dwParam,
    '   BYTE* pbData,
    '   DWORD dwFlags
    ' );
    &amp;lt;DllImport("advapi32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptSetProvParam( _
        ByVal hProv As IntPtr, _
        ByVal dwParam As Int32, _
        ByVal pbData As Byte(), _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptHashData(
    '   HCRYPTHASH hHash,
    '   BYTE* pbData,
    '   DWORD dwDataLen,
    '   DWORD dwFlags
    ' ); 
    &amp;lt;DllImport("advapi32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptHashData( _
        ByVal hHash As IntPtr, _
        ByVal pbData As Byte(), _
        ByVal dwDataLen As Int32, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptSignHash(
    '   HCRYPTHASH hHash,
    '   DWORD dwKeySpec,
    '   LPCTSTR sDescription,
    '   DWORD dwFlags,
    '   BYTE* pbSignature,
    '   DWORD* pdwSigLen
    ' );
    &amp;lt;DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CryptSignHash( _
        ByVal hHash As IntPtr, _
        ByVal dwKeySpec As Int32, _
        ByVal sDescription As String, _
        ByVal dwFlags As Int32, _
        ByVal pbSignature As Byte(), _
        ByRef pdwSigLen As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CertFreeCertificateContext(
    '   PCCERT_CONTEXT pCertContext
    ' );
    &amp;lt;DllImport("Crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CertFreeCertificateContext( _
        ByVal pCertContext As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptAcquireContext(
    '   HCRYPTPROV* phProv,
    '   LPCTSTR pszContainer,
    '   LPCTSTR pszProvider,
    '   DWORD dwProvType,
    '   DWORD dwFlags
    ' );
    &amp;lt;DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CryptAcquireContext( _
        ByRef hProv As IntPtr, _
        ByVal pszContainer As String, _
        ByVal pszProvider As String, _
        ByVal dwProvType As Int32, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptImportPublicKeyInfo(
    '   HCRYPTPROV hCryptProv,
    '   DWORD dwCertEncodingType,
    '   PCERT_PUBLIC_KEY_INFO pInfo,
    '   HCRYPTKEY* phKey
    ' );
    &amp;lt;DllImport("crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptImportPublicKeyInfo( _
        ByVal hCryptProv As IntPtr, _
        ByVal dwCertEncodingType As Int32, _
        ByVal pInfo As IntPtr, _
        ByRef phKey As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptVerifySignature(
    '   HCRYPTHASH hHash,
    '   BYTE* pbSignature,
    '   DWORD dwSigLen,
    '   HCRYPTKEY hPubKey,
    '   LPCTSTR sDescription,
    '   DWORD dwFlags
    ' );
    &amp;lt;DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)&amp;gt; _
    Public Shared Function CryptVerifySignature( _
        ByVal hHash As IntPtr, _
        ByVal pbSignature As Byte(), _
        ByVal dwSigLen As Int32, _
        ByVal hPubKey As IntPtr, _
        ByVal sDescription As String, _
        ByVal dwFlags As Int32 _
    ) As Boolean
    End Function

    ' BOOL WINAPI CryptDestroyKey(
    '   HCRYPTKEY hKey
    ' );
    &amp;lt;DllImport("advapi32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CryptDestroyKey( _
        ByVal hKey As IntPtr _
    ) As Boolean
    End Function

    ' BOOL WINAPI CertGetCertificateContextProperty(
    '   PCCERT_CONTEXT pCertContext,
    '   DWORD dwPropId,
    '   void* pvData,
    '   DWORD* pcbData
    ' );
    &amp;lt;DllImport("crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CertGetCertificateContextProperty( _
        ByVal pCertContext As IntPtr, _
        ByVal dwPropId As Int32, _
        ByVal pvData As IntPtr, _
        ByRef pcbData As Int32 _
    ) As Boolean
    End Function

    ' PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(
    '   HCERTSTORE hCertStore,
    '   PCCERT_CONTEXT pPrevCertContext
    ');
    &amp;lt;DllImport("crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CertEnumCertificatesInStore( _
        ByVal hCertStore As IntPtr, _
        ByVal pPrevCertContext As IntPtr _
    ) As IntPtr
    End Function

    ' PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
    '   PCCERT_CONTEXT pCertContext
    ');
    &amp;lt;DllImport("crypt32.dll", SetLastError:=True)&amp;gt; _
    Public Shared Function CertDuplicateCertificateContext( _
        ByVal pCertContext As IntPtr _
    ) As IntPtr
    End Function

#End Region

#Region "FUNCTIONS"

    Public Shared Function CertContextFromCertSubject(ByVal subject As String) As IntPtr

        ' Variables
        '
        Dim bResult As Boolean = False
        Dim hStoreHandle As IntPtr = IntPtr.Zero
        Dim pCertContext As IntPtr = IntPtr.Zero

        Try

            ' Open the certificate store.
            '
            hStoreHandle = CertOpenSystemStore( _
                0, _
                CERT_PERSONAL_STORE_NAME _
            )
            If (hStoreHandle.Equals(IntPtr.Zero)) Then
                Throw New Exception("CertOpenStore error", New Win32Exception(Marshal.GetLastWin32Error()))
            End If

            ' Get a certificate that matches the search criteria.
            ' 
            pCertContext = CertFindCertificateInStore( _
                hStoreHandle, _
                MY_TYPE, _
                0, _
                CERT_FIND_SUBJECT_STR, _
                subject, _
                IntPtr.Zero _
            )
            If (pCertContext.Equals(IntPtr.Zero)) Then
                Throw New Exception("CertFindCertificateInStore error", New Win32Exception(Marshal.GetLastWin32Error()))
            End If

            Return pCertContext

        Catch ex As Exception

            ' Any errors? Show them.
            '
            If (ex.InnerException Is Nothing) Then
                MessageBox.Show(ex.Message)
            Else
                MessageBox.Show(ex.Message + " --&amp;gt; " + ex.InnerException.Message)
            End If

        Finally

            ' Clean up and free memory.
            '
            If (Not hStoreHandle.Equals(IntPtr.Zero)) Then
                bResult = CertCloseStore( _
                    hStoreHandle, _
                    CERT_CLOSE_STORE_CHECK_FLAG _
                )
            End If

        End Try

        Return Nothing

    End Function

    ' Converted to VB.NET from KB article 320602
    '
    Public Shared Function RSACryptoServiceProviderFromCertContext(ByVal pCertContext As IntPtr) As RSACryptoServiceProvider

        'Determine the size of the buffer that you need to allocate.
        '
        Dim cbData As Int32 = 0
        Dim fStatus As Boolean = CertGetCertificateContextProperty( _
            pCertContext, _
            CERT_KEY_PROV_INFO_PROP_ID, _
            0, _
            cbData)

        If (Not fStatus) Then
            MessageBox.Show("CertGetCertificateContextProperty error --&amp;gt; " + Marshal.GetLastWin32Error().ToString())

            ' Get the CERT_KEY_PROV_HANDLE_PROP_ID value and the HCRYPTPROV value.
            '
            cbData = 4
            Dim pCryptKeyProvInfo As IntPtr = Marshal.AllocHGlobal(New IntPtr(cbData))
            fStatus = CertGetCertificateContextProperty( _
                pCertContext, _
                CERT_KEY_PROV_INFO_PROP_ID, _
                pCryptKeyProvInfo, _
                cbData)

            If (Not fStatus) Then
                MessageBox.Show("CertGetCertificateContextProperty error --&amp;gt; " + Marshal.GetLastWin32Error().ToString())
            End If
            Return Nothing

        End If

        If (Not cbData = 0) Then

            ' Allocate an unmanaged buffer to store the CRYPT_KEY_PROV_INFO structure.
            '
            Dim pCryptKeyProvInfo As IntPtr = Marshal.AllocHGlobal(cbData)

            ' Get the CRYPT_KEY_PROV_INFO structure.
            '
            fStatus = CertGetCertificateContextProperty( _
                pCertContext, _
                CERT_KEY_PROV_INFO_PROP_ID, _
                pCryptKeyProvInfo, _
                cbData)

            If (Not fStatus) Then
                MessageBox.Show("CertGetCertificateContextProperty failed: " + Marshal.GetLastWin32Error().ToString())
                Marshal.FreeHGlobal(pCryptKeyProvInfo)
            Else

                ' Build a CspParameters object with the provider type, the provider name,
                ' and the container name from the CRYPT_KEY_PROV_INFO structure.
                ' The pointer to the container name is the first DWORD in the CRYPT_KEY_PROV_INFO
                ' structure, the pointer to the provider name is the second DWORD, and
                ' the provider type is the third DWORD.
                '
                Try
                    Dim CspParams As CspParameters = New CspParameters( _
                        Marshal.ReadInt32(New IntPtr(pCryptKeyProvInfo.ToInt32 + 8)), _
                        Marshal.PtrToStringUni(New IntPtr(Marshal.ReadInt32(New IntPtr(pCryptKeyProvInfo.ToInt32 + 4)))), _
                        Marshal.PtrToStringUni(New IntPtr(Marshal.ReadInt32(pCryptKeyProvInfo))))

                    ' Free the unmanaged CRYPT_KEY_PROV_INFO buffer.
                    '
                    Marshal.FreeHGlobal(pCryptKeyProvInfo)
                    Return New RSACryptoServiceProvider(CspParams)

                Catch ex As Exception
                    MessageBox.Show(ex.Message)
                End Try

            End If
        End If
        Return Nothing

    End Function

#End Region

End Class

&lt;/PRE&gt;
&lt;P&gt;&amp;lt;/SAMPLE&amp;gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6484629" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category></item><item><title>P/Invoking CryptoAPI in .NET (C# version)</title><link>http://blogs.msdn.com/alejacma/archive/2007/11/23/p-invoking-cryptoapi-in-net-c-version.aspx</link><pubDate>Fri, 23 Nov 2007 14:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6483144</guid><dc:creator>alejacma</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/6483144.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=6483144</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;Sometimes we&amp;nbsp;need to call &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt;&amp;nbsp;from &lt;STRONG&gt;.NET&lt;/STRONG&gt; because&amp;nbsp;classes in&amp;nbsp;&lt;STRONG&gt;System.Security.Cryptography&lt;/STRONG&gt; namespace have their limitations.&amp;nbsp;For instance, we can't&amp;nbsp;create a temporary key container with RSACryptoServiceProvider, but we can do it with CRYPT_VERIFYCONTEXT flag and &lt;A class="" title=CryptAcquireContext href="http://msdn2.microsoft.com/en-US/library/aa379886.aspx" mce_href="http://msdn2.microsoft.com/en-US/library/aa379886.aspx"&gt;CryptAcquireContext&lt;/A&gt; API. RSACryptoServiceProvider will end up calling CryptAcquireContext, but we can't pass CRYPT_VERIFYCONTEXT&amp;nbsp;to it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can find more info about all this here in MSDN:&lt;/P&gt;
&lt;P&gt;&lt;A class="" title="Extending .NET Cryptography with CAPICOM and P/Invoke" href="http://msdn2.microsoft.com/en-us/library/ms867087.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms867087.aspx"&gt;Extending .NET Cryptography with CAPICOM and P/Invoke&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here you have the&amp;nbsp;most common &lt;STRONG&gt;P/Invoke&lt;/STRONG&gt; CryptoAPI declarations I've successfully used in the past:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;lt;SAMPLE&amp;gt;&lt;/P&gt;&lt;PRE&gt;using System;
using System.Runtime.InteropServices;

public class Crypto
{
#region CONSTS

// #define PRIVATEKEYBLOB		0x7
public const Int32 PRIVATEKEYBLOB = 0x7;

// #define AT_KEYEXCHANGE		1
public const Int32 AT_KEYEXCHANGE = 1;

// #define AT_SIGNATURE		2
public const Int32 AT_SIGNATURE = 2;

//#define CRYPT_E_NOT_FOUND		_HRESULT_TYPEDEF_(0x80092004L)
public const Int32 CRYPT_E_NOT_FOUND = -2146885628;

// #define CERT_PERSONAL_STORE_NAME      L"My"
public const string CERT_PERSONAL_STORE_NAME = "My";

// #define CERT_COMPARE_ANY		0
public const Int32 CERT_COMPARE_ANY = 0;

// #define CERT_COMPARE_NAME   2
public const Int32 CERT_COMPARE_NAME = 2;

// #define CERT_INFO_SUBJECT_FLAG  7
public const Int32 CERT_INFO_SUBJECT_FLAG = 7;

// #define CERT_COMPARE_SHIFT        16
public const Int32 CERT_COMPARE_SHIFT = 16;

// #define CERT_FIND_SUBJECT_NAME    (CERT_COMPARE_NAME &amp;lt;&amp;lt; CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
public const Int32 CERT_FIND_SUBJECT_NAME = 
	(CERT_COMPARE_NAME &amp;lt;&amp;lt; CERT_COMPARE_SHIFT) | CERT_INFO_SUBJECT_FLAG;

// #define CERT_FIND_ANY	(CERT_COMPARE_ANY &amp;lt;&amp;lt; CERT_COMPARE_SHIFT)
public const Int32 CERT_FIND_ANY = CERT_COMPARE_ANY &amp;lt;&amp;lt; CERT_COMPARE_SHIFT;

// #define CERT_COMPARE_NAME_STR_W     8
public const Int32 CERT_COMPARE_NAME_STR_W = 8;

// #define CERT_FIND_SUBJECT_STR_W   \
//   (CERT_COMPARE_NAME_STR_W &amp;lt;&amp;lt; CERT_COMPARE_SHIFT | CERT_INFO_SUBJECT_FLAG)
public const Int32 CERT_FIND_SUBJECT_STR_W = 
	(CERT_COMPARE_NAME_STR_W &amp;lt;&amp;lt; CERT_COMPARE_SHIFT) | CERT_INFO_SUBJECT_FLAG;

// #define CERT_FIND_SUBJECT_STR CERT_FIND_SUBJECT_STR_W
public const Int32 CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W;

// #define CERT_STORE_PROV_SYSTEM_W      ((LPCSTR) 10)
public const Int32 CERT_STORE_PROV_SYSTEM_W = 10;

// #define CERT_STORE_PROV_SYSTEM        CERT_STORE_PROV_SYSTEM_W
public const Int32 CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W;

// #define CERT_SYSTEM_STORE_CURRENT_USER_ID     1
public const Int32 CERT_SYSTEM_STORE_CURRENT_USER_ID = 1;

// #define CERT_SYSTEM_STORE_LOCATION_SHIFT      16
public const Int32 CERT_SYSTEM_STORE_LOCATION_SHIFT = 16;

// #define CERT_SYSTEM_STORE_CURRENT_USER        \
//   (CERT_SYSTEM_STORE_CURRENT_USER_ID &amp;lt;&amp;lt; CERT_SYSTEM_STORE_LOCATION_SHIFT)
public const Int32 CERT_SYSTEM_STORE_CURRENT_USER = 
	CERT_SYSTEM_STORE_CURRENT_USER_ID &amp;lt;&amp;lt; CERT_SYSTEM_STORE_LOCATION_SHIFT;

// #define CERT_CLOSE_STORE_CHECK_FLAG       0x00000002
public const Int32 CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002;

// #define ALG_CLASS_HASH                  (4 &amp;lt;&amp;lt; 13)
// #define ALG_TYPE_ANY                    (0)
// #define ALG_SID_SHA1                    4
// #define CALG_SHA1               (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1)
public const Int32 CALG_SHA1 = (4 &amp;lt;&amp;lt; 13) | 4;

// #define ALG_CLASS_SIGNATURE             (1 &amp;lt;&amp;lt; 13)
// #define ALG_TYPE_RSA                    (2 &amp;lt;&amp;lt; 9)
// #define ALG_SID_RSA_ANY                 0
// #define CALG_RSA_SIGN           (ALG_CLASS_SIGNATURE | ALG_TYPE_RSA | ALG_SID_RSA_ANY)
public const Int32 CALG_RSA_SIGN = (1 &amp;lt;&amp;lt; 13) | (2 &amp;lt;&amp;lt; 9);

// #define PROV_RSA_FULL           1
public const Int32 PROV_RSA_FULL = 0x00000001;

// #define CRYPT_VERIFYCONTEXT     0xF0000000
public const Int32 CRYPT_VERIFYCONTEXT = -268435456; //No private key access required

// #define X509_ASN_ENCODING           0x00000001
public const Int32 X509_ASN_ENCODING = 0x00000001;

// #define PKCS_7_ASN_ENCODING         0x00010000
public const Int32 PKCS_7_ASN_ENCODING = 0x00010000;

// #define MY_TYPE       (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
public const Int32 MY_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;

// #define HP_HASHVAL              0x0002
public const Int32 HP_HASHVAL = 0x00000002;

// #define HP_HASHSIZE             0x0004
public const Int32 HP_HASHSIZE = 0x00000004;

// #define PUBLICKEYBLOBEX 0xA
public const Int32 PUBLICKEYBLOBEX = 0x0A;

// #define PUBLICKEYBLOB           0x6
public const Int32 PUBLICKEYBLOB = 0x06;

// #define CUR_BLOB_VERSION 0x02
public const Int32 CUR_BLOB_VERSION = 0x02;

// #define CRYPT_EXPORTABLE        0x00000001
public const Int32 CRYPT_EXPORTABLE = 0x00000001;

// #define szOID_RSA_RSA           "1.2.840.113549.1.1.1"
public const String szOID_RSA_RSA = "1.2.840.113549.1.1.1";

// #define szOID_RSA_MD5           "1.2.840.113549.2.5"
public const String szOID_RSA_MD5 = "1.2.840.113549.2.5";

// #define szOID_RSA_MD5RSA        "1.2.840.113549.1.1.4"
public const String szOID_RSA_MD5RSA = "1.2.840.113549.1.1.4";

// #define szOID_OIWSEC_sha1       "1.3.14.3.2.26"
public const String szOID_OIWSEC_sha1 = "1.3.14.3.2.26";

// #define RSA_CSP_PUBLICKEYBLOB               ((LPCSTR) 19)
public const Int32 RSA_CSP_PUBLICKEYBLOB = 19;

// #define X509_PUBLIC_KEY_INFO                ((LPCSTR) 8)
public const Int32 X509_PUBLIC_KEY_INFO = 8;

#endregion

#region STRUCTS

// typedef struct _PUBLICKEYSTRUC 
// {
//		BYTE bType;  
//		BYTE bVersion;  
//		WORD reserved;  
//		ALG_ID aiKeyAlg;
// } BLOBHEADER, PUBLICKEYSTRUC;
[StructLayout(LayoutKind.Sequential)]
public struct PUBLICKEYSTRUC
{
	public Byte bType;
	public Byte bVersion;
	public Int16 reserved;
	public Int32 aiKeyAlg;
}

// typedef struct _RSAPUBKEY 
// {
//		DWORD magic;
//		DWORD bitlen;
//		DWORD pubexp;
// } RSAPUBKEY;
[StructLayout(LayoutKind.Sequential)]
public struct RSAPUBKEY 
{
	public Int32 magic;
	public Int32 bitlen;
	public Int32 pubexp;
}

// typedef struct _CRYPTOAPI_BLOB 
// {
//		DWORD   cbData;
//		BYTE    *pbData;
// } CRYPT_HASH_BLOB, CRYPT_INTEGER_BLOB, 
//   CRYPT_OBJID_BLOB, CERT_NAME_BLOB;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPTOAPI_BLOB
{
	public Int32 cbData;
	public Byte[] pbData;
}

// typedef struct _CRYPT_ALGORITHM_IDENTIFIER 
// {
//		LPSTR pszObjId;
//		CRYPT_OBJID_BLOB Parameters;
// } CRYPT_ALGORITHM_IDENTIFIER;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_ALGORITHM_IDENTIFIER
{
	[MarshalAs(UnmanagedType.LPStr)]public String pszObjId;
	public CRYPTOAPI_BLOB Parameters;
}

// typedef struct _CRYPT_SIGN_MESSAGE_PARA 
// {
//		DWORD cbSize;
//		DWORD dwMsgEncodingType;
//		PCCERT_CONTEXT pSigningCert;
//		CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
//		void *pvHashAuxInfo;
//		DWORD cMsgCert;
//		PCCERT_CONTEXT *rgpMsgCert;
//		DWORD cMsgCrl;
//		PCCRL_CONTEXT *rgpMsgCrl;
//		DWORD cAuthAttr;
//		PCRYPT_ATTRIBUTE rgAuthAttr;
//		DWORD cUnauthAttr;
//		PCRYPT_ATTRIBUTE rgUnauthAttr;
//		DWORD dwFlags;
//		DWORD dwInnerContentType;
// } CRYPT_SIGN_MESSAGE_PARA;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_SIGN_MESSAGE_PARA 
{
	public Int32 cbSize;
	public Int32 dwMsgEncodingType;
	public IntPtr pSigningCert;
	public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
	public IntPtr pvHashAuxInfo;
	public Int32 cMsgCert;
	public IntPtr rgpMsgCert;
	public Int32 cMsgCrl;
	public IntPtr rgpMsgCrl;
	public Int32 cAuthAttr;
	public IntPtr rgAuthAttr;
	public Int32 cUnauthAttr;
	public IntPtr rgUnauthAttr;
	public Int32 dwFlags;
	public Int32 dwInnerContentType;
}

// typedef struct _CRYPT_VERIFY_MESSAGE_PARA 
// {
//		DWORD cbSize;
//		DWORD dwMsgAndCertEncodingType;
//		HCRYPTPROV hCryptProv;
//		PFN_CRYPT_GET_SIGNER_CERTIFICATE pfnGetSignerCertificate;
//		void *pvGetArg;
// } CRYPT_VERIFY_MESSAGE_PARA;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_VERIFY_MESSAGE_PARA 
{
	public Int32 cbSize;
	public Int32 dwMsgAndCertEncodingType;
	public IntPtr hCryptProv;
	public IntPtr pfnGetSignerCertificate;
	public IntPtr pvGetArg;
}

// typedef struct _CRYPT_BIT_BLOB 
// {
//		DWORD cbData;
//		BYTE *pbData;
//		DWORD cUnusedBits;
// } CRYPT_BIT_BLOB;
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_BIT_BLOB 
{
	public Int32 cbData;
	public IntPtr pbData;
	public Int32 cUnusedBits;
}

// typedef struct _CERT_PUBLIC_KEY_INFO 
// {
//		CRYPT_ALGORITHM_IDENTIFIER Algorithm;
//		CRYPT_BIT_BLOB PublicKey;
// } CERT_PUBLIC_KEY_INFO;
[StructLayout(LayoutKind.Sequential)]
public struct CERT_PUBLIC_KEY_INFO 
{
	public CRYPT_ALGORITHM_IDENTIFIER Algorithm;
	public CRYPT_BIT_BLOB PublicKey;
}

#endregion

#region FUNCTIONS (IMPORTS)

// HCERTSTORE WINAPI CertOpenStore(
//		LPCSTR lpszStoreProvider,
//		DWORD dwMsgAndCertEncodingType,
//		HCRYPTPROV hCryptProv,
//		DWORD dwFlags,
//		const void* pvPara
// );
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CertOpenStore(
	Int32 lpszStoreProvider,
	Int32 dwMsgAndCertEncodingType,
	IntPtr hCryptProv, 
	Int32 dwFlags, 
	String pvPara
); 

// HCERTSTORE WINAPI CertOpenSystemStore(
//		HCRYPTPROV hprov,
//		LPTCSTR szSubsystemProtocol
// );
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CertOpenSystemStore(
	IntPtr hprov, 
	String szSubsystemProtocol
);

// BOOL WINAPI CertCloseStore(
//		HCERTSTORE hCertStore,
//		DWORD dwFlags
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CertCloseStore( 
	IntPtr hCertStore,
	Int32 dwFlags
); 		

// BOOL WINAPI CryptAcquireContext(
//		HCRYPTPROV* phProv,
//		LPCTSTR pszContainer,
//		LPCTSTR pszProvider,
//		DWORD dwProvType,
//		DWORD dwFlags
// );
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CryptAcquireContext(
	ref IntPtr hProv,
	String pszContainer,
	String pszProvider,
	Int32 dwProvType,
	Int32 dwFlags
);

// BOOL WINAPI CryptCreateHash(
//		HCRYPTPROV hProv,
//		ALG_ID Algid,
//		HCRYPTKEY hKey,
//		DWORD dwFlags,
//		HCRYPTHASH* phHash
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptCreateHash(
	IntPtr hProv,
	Int32 Algid,
	IntPtr hKey,
	Int32 dwFlags,
	ref IntPtr phHash
);

// BOOL WINAPI CryptGetHashParam(
//		HCRYPTHASH hHash,
//		DWORD dwParam,
//		BYTE* pbData,
//		DWORD* pdwDataLen,
//		DWORD dwFlags
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptGetHashParam(
	IntPtr hHash,
	Int32 dwParam,
	ref Int32 pbData,
	ref Int32 pdwDataLen,
	Int32 dwFlags
);

// BOOL WINAPI CryptSetHashParam(
//		HCRYPTHASH hHash,
//		DWORD dwParam,
//		BYTE* pbData,
//		DWORD dwFlags
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptSetHashParam(
	IntPtr hHash,
	Int32 dwParam,
	Byte[] pbData,
	Int32 dwFlags
);

// BOOL WINAPI CryptImportPublicKeyInfo(
//		HCRYPTPROV hCryptProv,
//		DWORD dwCertEncodingType,
//		PCERT_PUBLIC_KEY_INFO pInfo,
//		HCRYPTKEY* phKey
// );
[DllImport("crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CryptImportPublicKeyInfo(
	IntPtr hCryptProv,
	Int32 dwCertEncodingType,
	IntPtr pInfo,
	ref IntPtr phKey
);

// BOOL WINAPI CryptImportKey(
//		HCRYPTPROV hProv,
//		BYTE* pbData,
//		DWORD dwDataLen,
//		HCRYPTKEY hPubKey,
//		DWORD dwFlags,
//		HCRYPTKEY* phKey
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptImportKey(
	IntPtr hProv,
	Byte[] pbData,
	Int32 dwDataLen,
	IntPtr hPubKey,
	Int32 dwFlags,
	ref IntPtr phKey
);

// BOOL WINAPI CryptVerifySignature(
//		HCRYPTHASH hHash,
//		BYTE* pbSignature,
//		DWORD dwSigLen,
//		HCRYPTKEY hPubKey,
//		LPCTSTR sDescription,
//		DWORD dwFlags
// );
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CryptVerifySignature(
	IntPtr hHash,
	Byte[] pbSignature,
	Int32 dwSigLen,
	IntPtr hPubKey,
	String sDescription,
	Int32 dwFlags
);

// BOOL WINAPI CryptDestroyKey(
//		HCRYPTKEY hKey
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptDestroyKey(
	IntPtr hKey
);

// BOOL WINAPI CryptDestroyHash(
//		HCRYPTHASH hHash
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptDestroyHash(
	IntPtr hHash
);

// BOOL WINAPI CryptReleaseContext(
//		HCRYPTPROV hProv,
//		DWORD dwFlags
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptReleaseContext(
	IntPtr hProv,
	Int32 dwFlags
);

// BOOL WINAPI CryptGenKey(
//		HCRYPTPROV hProv,
//		ALG_ID Algid,
//		DWORD dwFlags,
//		HCRYPTKEY* phKey
// );	
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptGenKey(
	IntPtr hProv,
	Int32 Algid,
	Int32 dwFlags,
	ref IntPtr phKey
);

// BOOL WINAPI CryptExportKey(
//		HCRYPTKEY hKey,
//		HCRYPTKEY hExpKey,
//		DWORD dwBlobType,
//		DWORD dwFlags,
//		BYTE* pbData,
//		DWORD* pdwDataLen
// );
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool CryptExportKey(
	IntPtr hKey,
	IntPtr hExpKey,
	Int32 dwBlobType,
	Int32 dwFlags,
	Byte[] pbData,
	ref Int32 pdwDataLen
);

// PCCERT_CONTEXT WINAPI CertFindCertificateInStore(
//		HCERTSTORE hCertStore,
//		DWORD dwCertEncodingType,
//		DWORD dwFindFlags,
//		DWORD dwFindType,
//		const void* pvFindPara,
//		PCCERT_CONTEXT pPrevCertContext
// );
[DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CertFindCertificateInStore(
	IntPtr hCertStore, 
	Int32 dwCertEncodingType,
	Int32 dwFindFlags,
	Int32 dwFindType,
	String pvFindPara,
	IntPtr pPrevCertContext
);

// BOOL WINAPI CertFreeCertificateContext(
//		PCCERT_CONTEXT pCertContext
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CertFreeCertificateContext(
	IntPtr pCertContext
);

// BOOL WINAPI CryptSignMessage(
//		PCRYPT_SIGN_MESSAGE_PARA pSignPara,
//		BOOL fDetachedSignature,
//		DWORD cToBeSigned,
//		const BYTE* rgpbToBeSigned[],
//		DWORD rgcbToBeSigned[],
//		BYTE* pbSignedBlob,
//		DWORD* pcbSignedBlob
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptSignMessage (
	ref CRYPT_SIGN_MESSAGE_PARA pSignPara,
	Boolean fDetachedSignature,
	Int32 cToBeSigned,
	IntPtr[] rgpbToBeSigned,
	Int32[] rgcbToBeSigned,
	Byte[] pbSignedBlob,
	ref Int32 pcbSignedBlob
);

// BOOL WINAPI CryptVerifyMessageSignature(
//		PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
//		DWORD dwSignerIndex,
//		const BYTE* pbSignedBlob,
//		DWORD cbSignedBlob,
//		BYTE* pbDecoded,
//		DWORD* pcbDecoded,
//		PCCERT_CONTEXT* ppSignerCert
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptVerifyMessageSignature (
	ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
	Int32 dwSignerIndex,
	Byte[] pbSignedBlob,
	Int32 cbSignedBlob,
	Byte[] pbDecoded,
	ref Int32 pcbDecoded,
	IntPtr ppSignerCert
);

// BOOL WINAPI CryptEncodeObject(
//		DWORD dwCertEncodingType,
//		LPCSTR lpszStructType,
//		const void* pvStructInfo,
//		BYTE* pbEncoded,
//		DWORD* pcbEncoded
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptEncodeObject (
	Int32 dwCertEncodingType,
	Int32 lpszStructType,
	ref CERT_PUBLIC_KEY_INFO pvStructInfo,
	Byte[] pbEncoded,
	ref Int32 pcbEncoded
);		

[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptEncodeObject (
	Int32 dwCertEncodingType,
	Int32 lpszStructType,
	Byte[] pvStructInfo,
	IntPtr pbEncoded,
	ref Int32 pcbEncoded
);	

// PCCERT_CONTEXT WINAPI CertCreateCertificateContext(
//		DWORD dwCertEncodingType,
//		const BYTE* pbCertEncoded,
//		DWORD cbCertEncoded
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern IntPtr CertCreateCertificateContext (
	Int32 dwCertEncodingType,
	Byte[] pbCertEncoded,
	Int32 cbCertEncoded
);	

// BOOL WINAPI CryptAcquireCertificatePrivateKey(
//		PCCERT_CONTEXT pCert,
//		DWORD dwFlags,
//		void* pvReserved,
//		HCRYPTPROV* phCryptProv,
//		DWORD* pdwKeySpec,
//		BOOL* pfCallerFreeProv
// );
[DllImport("Crypt32.dll", SetLastError=true)]
public static extern Boolean CryptAcquireCertificatePrivateKey (
	IntPtr pCert,
	Int32 dwFlags,
	IntPtr pvReserved,
	ref IntPtr phCryptProv,
	ref Int32 pdwKeySpec,
	ref Boolean pfCallerFreeProv
);	

// BOOL WINAPI CryptHashData(
//		HCRYPTHASH hHash,
//		BYTE* pbData,
//		DWORD dwDataLen,
//		DWORD dwFlags
// );
[DllImport("Advapi32.dll", SetLastError=true)]
public static extern Boolean CryptHashData (
	IntPtr hHash,
	Byte[] pbData,
	Int32 dwDataLen,
	Int32 dwFlags
);

// BOOL WINAPI CryptSignHash(
//		HCRYPTHASH hHash,
//		DWORD dwKeySpec,
//		LPCTSTR sDescription,
//		DWORD dwFlags,
//		BYTE* pbSignature,
//		DWORD* pdwSigLen
// );
[DllImport("Advapi32.dll", SetLastError=true)]
public static extern Boolean CryptSignHash(
	IntPtr hHash,
	Int32 dwKeySpec,
	String sDescription,
	Int32 dwFlags,
	Byte[] pbSignature,
	ref Int32 pdwSigLen
);

// BOOL WINAPI CryptGetUserKey(
//		HCRYPTPROV hProv,
//		DWORD dwKeySpec,
//		HCRYPTKEY* phUserKey
// );
[DllImport("Advapi32.dll", SetLastError=true)]
public static extern Boolean CryptGetUserKey(
	IntPtr hProv,
	Int32 dwKeySpec,
	ref IntPtr phUserKey
);

#endregion 

}
&lt;/PRE&gt;&lt;PRE&gt;&amp;lt;/SAMPLE&amp;gt;
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;PS:&amp;nbsp; A new version of .NET Framework is coming out while you read this. Hopefully we won't need to use CryptoAPI directly as often as we did with .NET Framework 1.1/2.0.&lt;/P&gt;
&lt;P&gt;PS: I also have VB.NET declarations. I will post them soon.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6483144" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/P_2F00_Invoke/default.aspx">P/Invoke</category></item></channel></rss>