<?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 : WinInet</title><link>http://blogs.msdn.com/alejacma/archive/tags/WinInet/default.aspx</link><description>Tags: WinInet</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></channel></rss>