Hi all,
The other day I needed to use the certificate chain context (CERT_CHAIN_CONTEXT structure) returned by a call to InternetQueryOption, in C#.
The call in C++ looks like this:
PCCERT_CHAIN_CONTEXT CertCtx=NULL; … if (InternetQueryOption(hReq, INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT, (LPVOID)&CertCtx, &cbCertSize)) { PCCERT_CHAIN_CONTEXT pChainContext=CertCtx; … }
Some additional info about this call can be found here:
Option Flags
"INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT 105 Retrieves the server’s certificate-chain context as a duplicated PCCERT_CHAIN_CONTEXT. You may pass this duplicated context to any Crypto API function which takes a PCCERT_CHAIN_CONTEXT. You must call CertFreeCertificateChain on the returned PCCERT_CHAIN_CONTEXT when you are done with the certificate-chain context.Version: Requires Internet Explorer 8.0."
I got a good C++ sample from here: “Understanding the new WinInet option INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT”. So I took that sample as a base. I also used some of the p/invoke code I had already created for this C# sample: How to call InternetErrorDlg to deal with certificate issues on SSL connections (C#).
This is the C# sample I created:
<SAMPLE file="form1.cs">
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // Consts const int SIZE = 255; // Variables Win32.CERT_CHAIN_CONTEXT certChainContext = new Win32.CERT_CHAIN_CONTEXT(); Win32.CERT_SIMPLE_CHAIN certSimpleChain = new Win32.CERT_SIMPLE_CHAIN(); //Win32.CERT_CONTEXT certContext = new Win32.CERT_CONTEXT(); Win32.CERT_CHAIN_ELEMENT certChainElement = new Win32.CERT_CHAIN_ELEMENT(); StringBuilder pszSubject = new StringBuilder(SIZE); StringBuilder pszIssuer = new StringBuilder(SIZE); IntPtr hInternet = IntPtr.Zero; IntPtr hConnect = IntPtr.Zero; IntPtr hRequest = IntPtr.Zero; IntPtr lpBufferData = IntPtr.Zero; IntPtr lpBufferChain = IntPtr.Zero; ulong ulOptionMask = 0; int dwContext = 0; int lpdwBufferLength = 0; int dwError = 0; int iResult = 0; int dwNumberOfBytesAvailable = 0; int dwNumberOfBytesRead = 0; int cchNameString = 0; bool bResult = false; try { // Initialize WinINet hInternet = Win32.InternetOpen("alejacma", Win32.INTERNET_OPEN_TYPE_PRECONFIG, null, null, 0); if (hInternet == IntPtr.Zero) { throw new Exception("InternetOpen error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Open HTTP session hConnect = Win32.InternetConnect(hInternet, textBox1.Text, Win32.INTERNET_DEFAULT_HTTPS_PORT, null, null, Win32.INTERNET_SERVICE_HTTP, 0, ref dwContext); if (hConnect == IntPtr.Zero) { throw new Exception("InternetConnect error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Create HTTP request hRequest = Win32.HttpOpenRequest(hConnect, "GET", textBox2.Text, null, null, IntPtr.Zero, Win32.INTERNET_FLAG_SECURE, ref dwContext); if (hRequest == IntPtr.Zero) { throw new Exception("HttpOpenRequest error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Configure request to get combined cert errors ulOptionMask = Win32.INTERNET_ERROR_MASK_COMBINED_SEC_CERT; bResult = Win32.InternetSetOption(hRequest, Win32.INTERNET_OPTION_ERROR_MASK, ref ulOptionMask, Marshal.SizeOf(typeof(IntPtr))); if (!bResult) { throw new Exception("InternetSetOption Error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } do { // Send request to the server bResult = Win32.HttpSendRequest(hRequest, null, 0, IntPtr.Zero, 0); if (bResult == false) { // Deal with possible errors dwError = Marshal.GetLastWin32Error(); switch (dwError) { case Win32.ERROR_INTERNET_SEC_CERT_ERRORS: case Win32.ERROR_INTERNET_INVALID_CA: case Win32.ERROR_INTERNET_SEC_CERT_CN_INVALID: case Win32.ERROR_INTERNET_SEC_CERT_DATE_INVALID: case Win32.ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED: break; default: // Unknown error throw new Exception("HttpSendRequest error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Display cert error dialog box iResult = Win32.InternetErrorDlg(this.Handle, hRequest, dwError, Win32.FLAGS_ERROR_UI_FLAGS_GENERATE_DATA + Win32.FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, IntPtr.Zero); switch (iResult) { case Win32.ERROR_SUCCESS: break; case Win32.ERROR_CANCELLED: throw new Exception("InternetErrorDlg error\nThe function was canceled by the user"); case Win32.ERROR_INTERNET_FORCE_RETRY: throw new Exception("InternetErrorDlg error\nFunction needs to redo its request. In the case of authentication this indicates that the user clicked the OK button."); case Win32.ERROR_INVALID_HANDLE: throw new Exception("InternetErrorDlg error\nThe handle to the parent window is invalid"); default: throw new Exception("InternetErrorDlg error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } } } while (!bResult); // Retrieve the server’s certificate-chain context lpdwBufferLength = Marshal.SizeOf(typeof(IntPtr)); bResult = Win32.InternetQueryOption(hRequest, Win32.INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT, ref lpBufferChain, ref lpdwBufferLength); if (bResult == false) { throw new Exception("InternetQueryOption error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Display some of the contents of the chain certChainContext = (Win32.CERT_CHAIN_CONTEXT)Marshal.PtrToStructure(lpBufferChain, typeof(Win32.CERT_CHAIN_CONTEXT)); switch(certChainContext.TrustStatus.dwErrorStatus) { case Win32.CERT_TRUST_NO_ERROR: MessageBox.Show("No error found for this certificate or chain"); break; case Win32.CERT_TRUST_IS_NOT_TIME_VALID: MessageBox.Show("This certificate or one of the certificates in the certificate chain is not time-valid"); break; case Win32.CERT_TRUST_IS_REVOKED: MessageBox.Show("Trust for this certificate or one of the certificates in the certificate chain has been revoked"); break; case Win32.CERT_TRUST_IS_NOT_SIGNATURE_VALID: MessageBox.Show("The certificate or one of the certificates in the certificate chain does not have a valid signature"); break; case Win32.CERT_TRUST_IS_NOT_VALID_FOR_USAGE: MessageBox.Show("The certificate or certificate chain is not valid in its proposed usage"); break; case Win32.CERT_TRUST_IS_UNTRUSTED_ROOT: MessageBox.Show("The certificate or certificate chain is based on an untrusted root"); break; case Win32.CERT_TRUST_REVOCATION_STATUS_UNKNOWN: MessageBox.Show("The revocation status of the certificate or one of the certificates in the certificate chain is unknown"); break; case Win32.CERT_TRUST_IS_CYCLIC: MessageBox.Show("One of the certificates in the chain was issued by a certification authority that the original certificate had certified"); break; case Win32.CERT_TRUST_IS_PARTIAL_CHAIN: MessageBox.Show("The certificate chain is not complete"); break; case Win32.CERT_TRUST_CTL_IS_NOT_TIME_VALID: MessageBox.Show("A CTL used to create this chain was not time-valid"); break; case Win32.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID: MessageBox.Show("A CTL used to create this chain did not have a valid signature"); break; case Win32.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE: MessageBox.Show("A CTL used to create this chain is not valid for this usage"); break; default: MessageBox.Show("TrustStatus.dwErrorStatus = " + certChainContext.TrustStatus.dwErrorStatus.ToString()); break; } switch (certChainContext.TrustStatus.dwInfoStatus) { case 0: MessageBox.Show("No information status reported"); break; case Win32.CERT_TRUST_HAS_EXACT_MATCH_ISSUER: MessageBox.Show("An exact match issuer certificate has been found for this certificate"); break; case Win32.CERT_TRUST_HAS_KEY_MATCH_ISSUER: MessageBox.Show("A key match issuer certificate has been found for this certificate"); break; case Win32.CERT_TRUST_HAS_NAME_MATCH_ISSUER: MessageBox.Show("A name match issuer certificate has been found for this certificate"); break; case Win32.CERT_TRUST_IS_SELF_SIGNED: MessageBox.Show("This certificate is self-signed"); break; case Win32.CERT_TRUST_IS_COMPLEX_CHAIN: MessageBox.Show("The certificate chain created is a complex chain"); break; case Win32.CERT_TRUST_HAS_PREFERRED_ISSUER: MessageBox.Show("The certificate chain has a preferred issuer"); break; case Win32.CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY: MessageBox.Show("The certificate chain has issuance chain policy"); break; case Win32.CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS: MessageBox.Show("The certificate chain valid name contraints"); break; case Win32.CERT_TRUST_IS_PEER_TRUSTED: MessageBox.Show("The certificate chain is peer trusted"); break; case Win32.CERT_TRUST_HAS_CRL_VALIDITY_EXTENDED: MessageBox.Show("The certificate chain has CRL validity extended"); break; case Win32.CERT_TRUST_IS_FROM_EXCLUSIVE_TRUST_STORE: MessageBox.Show("The certificate chain was found in a store specified by hExclusiveRoot or hExclusiveTrustedPeople"); break; } for (int i = 0; i < certChainContext.cChain; i++) { certSimpleChain = (Win32.CERT_SIMPLE_CHAIN)Marshal.PtrToStructure(Marshal.ReadIntPtr(certChainContext.rgpChain + i * Marshal.SizeOf(typeof(IntPtr))), typeof(Win32.CERT_SIMPLE_CHAIN)); // For each certificate chain in this context... for (int simpleCertChainIndex = 0; simpleCertChainIndex < certSimpleChain.cElement; simpleCertChainIndex++) { // get the certificates in it certChainElement = (Win32.CERT_CHAIN_ELEMENT)Marshal.PtrToStructure(Marshal.ReadIntPtr(certSimpleChain.rgpElement + simpleCertChainIndex * Marshal.SizeOf(typeof(IntPtr))), typeof(Win32.CERT_CHAIN_ELEMENT)); //certContext = (Win32.CERT_CONTEXT)Marshal.PtrToStructure(certChainElement.pCertContext, typeof(Win32.CERT_CONTEXT)); // Find and print the name of the subject of the certificate cchNameString = Win32.CertGetNameString(certChainElement.pCertContext, Win32.CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, IntPtr.Zero, pszSubject, SIZE); if (cchNameString == 0) { throw new Exception("CertGetNameString error"); } // Get the issuer cchNameString = Win32.CertGetNameString(certChainElement.pCertContext, Win32.CERT_NAME_SIMPLE_DISPLAY_TYPE, Win32.CERT_NAME_ISSUER_FLAG, IntPtr.Zero, pszIssuer, SIZE); if (cchNameString == 0) { throw new Exception("CertGetNameString error"); } MessageBox.Show("Chain " + i.ToString() + "\nCert " + simpleCertChainIndex.ToString() + "\nSubject: " + pszSubject.ToString() + "\nIssuer: " + pszIssuer.ToString()); } } // Determine the amount of data available dwNumberOfBytesAvailable = 0; bResult = Win32.InternetQueryDataAvailable(hRequest, ref dwNumberOfBytesAvailable, 0, IntPtr.Zero); if (!bResult) { throw new Exception("InternetQueryDataAvailable error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Read data lpBufferData = Marshal.AllocHGlobal(dwNumberOfBytesAvailable); dwNumberOfBytesRead = 0; bResult = Win32.InternetReadFile(hRequest, lpBufferData, dwNumberOfBytesAvailable, ref dwNumberOfBytesRead); if (bResult == false) { throw new Exception("InternetReadFile error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error())); } // Everything went well. Show data MessageBox.Show(Marshal.PtrToStringAnsi(lpBufferData, dwNumberOfBytesRead)); } catch (Exception ex) { // Show exception if (ex.InnerException != null) { MessageBox.Show(ex.Message + "\n" + ex.InnerException.Message); } else { MessageBox.Show(ex.Message); } } finally { // Clean up stuff if (lpBufferData != IntPtr.Zero) { Marshal.FreeHGlobal(lpBufferData); } if (lpBufferChain != IntPtr.Zero) { Win32.CertFreeCertificateChain(lpBufferChain); } if (hRequest != IntPtr.Zero) { Win32.InternetCloseHandle(hRequest); } if (hConnect != IntPtr.Zero) { Win32.InternetCloseHandle(hConnect); } if (hInternet != IntPtr.Zero) { Win32.InternetCloseHandle(hInternet); } } } } }
</SAMPLE>
<SAMPLE file="win32.cs">
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { class Win32 { #region "CONSTS" public const int INTERNET_OPEN_TYPE_PRECONFIG = 0; public const int INTERNET_DEFAULT_HTTP_PORT = 80; public const int INTERNET_DEFAULT_HTTPS_PORT = 443; public const int INTERNET_SERVICE_HTTP = 3; public const int INTERNET_FLAG_SECURE = 0x00800000; public const int INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105; public const int INTERNET_OPTION_ERROR_MASK = 62; public const ulong INTERNET_ERROR_MASK_COMBINED_SEC_CERT = 0x2; public const int INTERNET_ERROR_BASE = 12000; public const int ERROR_INTERNET_FORCE_RETRY = INTERNET_ERROR_BASE + 32; public const int ERROR_INTERNET_SEC_CERT_DATE_INVALID = INTERNET_ERROR_BASE + 37; public const int ERROR_INTERNET_SEC_CERT_CN_INVALID = INTERNET_ERROR_BASE + 38; public const int ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED = INTERNET_ERROR_BASE + 44; public const int ERROR_INTERNET_SEC_CERT_ERRORS = INTERNET_ERROR_BASE + 55; public const int ERROR_INTERNET_INVALID_CA = INTERNET_ERROR_BASE + 45; public const int FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS = 0x02; public const int FLAGS_ERROR_UI_FLAGS_GENERATE_DATA = 0x04; public const int ERROR_SUCCESS = 0; public const int ERROR_CANCELLED = 1223; public const int ERROR_INVALID_HANDLE = 6; // http://msdn.microsoft.com/en-us/library/windows/desktop/aa377590(v=vs.85).aspx public const int CERT_TRUST_NO_ERROR = 0x00000000; public const int CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001; public const int CERT_TRUST_IS_REVOKED = 0x00000004; public const int CERT_TRUST_IS_NOT_SIGNATURE_VALID = 0x00000008; public const int CERT_TRUST_IS_NOT_VALID_FOR_USAGE = 0x00000010; public const int CERT_TRUST_IS_UNTRUSTED_ROOT = 0x00000020; public const int CERT_TRUST_REVOCATION_STATUS_UNKNOWN = 0x00000040; public const int CERT_TRUST_IS_CYCLIC = 0x00000080; public const int CERT_TRUST_INVALID_EXTENSION = 0x00000100; public const int CERT_TRUST_INVALID_POLICY_CONSTRAINTS = 0x00000200; public const int CERT_TRUST_INVALID_BASIC_CONSTRAINTS = 0x00000400; public const int CERT_TRUST_INVALID_NAME_CONSTRAINTS = 0x00000800; public const int CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT = 0x00001000; public const int CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000; public const int CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000; public const int CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000; public const int CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000; public const int CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000; public const int CERT_TRUST_IS_EXPLICIT_DISTRUST = 0x04000000; public const int CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT = 0x08000000; public const int CERT_TRUST_IS_PARTIAL_CHAIN = 0x00010000; public const int CERT_TRUST_CTL_IS_NOT_TIME_VALID = 0x00020000; public const int CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID = 0x00040000; public const int CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE = 0x00080000; public const int CERT_TRUST_HAS_EXACT_MATCH_ISSUER = 0x00000001; public const int CERT_TRUST_HAS_KEY_MATCH_ISSUER = 0x00000002; public const int CERT_TRUST_HAS_NAME_MATCH_ISSUER = 0x00000004; public const int CERT_TRUST_IS_SELF_SIGNED = 0x00000008; public const int CERT_TRUST_HAS_PREFERRED_ISSUER = 0x00000100; public const int CERT_TRUST_HAS_ISSUANCE_CHAIN_POLICY = 0x00000200; public const int CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS = 0x00000400; public const int CERT_TRUST_IS_PEER_TRUSTED = 0x00000800; public const int CERT_TRUST_HAS_CRL_VALIDITY_EXTENDED = 0x00001000; public const int CERT_TRUST_IS_FROM_EXCLUSIVE_TRUST_STORE = 0x00002000; public const int CERT_TRUST_IS_COMPLEX_CHAIN = 0x00010000; public const int CERT_NAME_SIMPLE_DISPLAY_TYPE = 4; public const int CERT_NAME_ISSUER_FLAG = 0x1; #endregion #region "STRUCTS" [StructLayout(LayoutKind.Sequential)] public struct CERT_TRUST_STATUS { public int dwErrorStatus; public int dwInfoStatus; } [StructLayout(LayoutKind.Sequential)] public struct BLOB { public int cbData; public IntPtr pbData; } [StructLayout(LayoutKind.Sequential)] public struct CRYPT_ALGORITHM_IDENTIFIER { public string pszObjId; public BLOB Parameters; } [StructLayout(LayoutKind.Sequential)] public struct FILETIME { public int dwLowDateTime; public int dwHighDateTime; } [StructLayout(LayoutKind.Sequential)] public struct CRYPT_BIT_BLOB { public int cbData; public IntPtr pbData; public int cUnusedBits; } [StructLayout(LayoutKind.Sequential)] public struct CERT_PUBLIC_KEY_INFO { public CRYPT_ALGORITHM_IDENTIFIER Algorithm; public CRYPT_BIT_BLOB PublicKey; } [StructLayout(LayoutKind.Sequential)] public struct CERT_EXTENSION { public string pszObjId; public bool fCritical; public BLOB Value; } [StructLayout(LayoutKind.Sequential)] public struct CERT_INFO { public int dwVersion; public BLOB SerialNumber; public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; public BLOB Issuer; public FILETIME NotBefore; public FILETIME NotAfter; public BLOB Subject; public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo; public CRYPT_BIT_BLOB IssuerUniqueId; public CRYPT_BIT_BLOB SubjectUniqueId; public int cExtension; public IntPtr rgExtension; } [StructLayout(LayoutKind.Sequential)] public struct CERT_CONTEXT { public int dwCertEncodingType; public IntPtr pbCertEncoded; public int cbCertEncoded; public IntPtr pCertInfo; public IntPtr hCertStore; } [StructLayout(LayoutKind.Sequential)] public struct CERT_REVOCATION_INFO { public int cbSize; public int dwRevocationResult; public string pszRevocationOid; public IntPtr pvOidSpecificInfo; public bool fHasFreshnessTime; public int dwFreshnessTime; } [StructLayout(LayoutKind.Sequential)] public struct CTL_USAGE { public int cUsageIdentifier; public IntPtr rgpszUsageIdentifier; } [StructLayout(LayoutKind.Sequential)] public struct CERT_CHAIN_ELEMENT { public int cbSize; public IntPtr pCertContext; public CERT_TRUST_STATUS TrustStatus; public IntPtr pRevocationInfo; public IntPtr pIssuanceUsage; public IntPtr pApplicationUsage; public string pwszExtendedErrorInfo; } [StructLayout(LayoutKind.Sequential)] public struct CRYPT_ATTRIBUTE { public string pszObjId; public int cValue; public IntPtr rgValue; } [StructLayout(LayoutKind.Sequential)] public struct CTL_ENTRY { public BLOB SubjectIdentifier; public int cAttribute; public IntPtr rgAttribute; } [StructLayout(LayoutKind.Sequential)] public struct CTL_INFO { public int dwVersion; public CTL_USAGE SubjectUsage; public BLOB ListIdentifier; public BLOB SequenceNumber; public FILETIME ThisUpdate; public FILETIME NextUpdate; public CRYPT_ALGORITHM_IDENTIFIER SubjectAlgorithm; public int cCTLEntry; public IntPtr rgCTLEntry; public int cExtension; public IntPtr rgExtension; } [StructLayout(LayoutKind.Sequential)] public struct CTL_CONTEXT { public int dwMsgAndCertEncodingType; public IntPtr pbCtlEncoded; public int cbCtlEncoded; public IntPtr pCtlInfo; public IntPtr hCertStore; public IntPtr hCryptMsg; public IntPtr pbCtlContent; public int cbCtlContent; } [StructLayout(LayoutKind.Sequential)] public struct CERT_TRUST_LIST_INFO { public int cbSize; public IntPtr pCtlEntry; public IntPtr pCtlContext; } [StructLayout(LayoutKind.Sequential)] public struct CERT_SIMPLE_CHAIN { public int cbSize; public CERT_TRUST_STATUS TrustStatus; public int cElement; public IntPtr rgpElement; public IntPtr pTrustListInfo; public bool fHasRevocationFreshnessTime; public int dwRevocationFreshnessTime; } [StructLayout(LayoutKind.Sequential)] public struct CERT_CHAIN_CONTEXT { public int cbSize; public CERT_TRUST_STATUS TrustStatus; public int cChain; public IntPtr rgpChain; public int cLowerQualityChainContext; public IntPtr rgpLowerQualityChainContext; public bool fHasRevocationFreshnessTime; public int dwRevocationFreshnessTime; } #endregion #region "FUNCTIONS" [DllImport("Wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr InternetOpen( string lpszAgent, int dwAccessType, string lpszProxyName, string lpszProxyBypass, int dwFlags ); [DllImport("Wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr InternetCloseHandle( IntPtr hInternet ); [DllImport("Wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr InternetConnect( IntPtr hInternet, string lpszServerName, short nServerPort, string lpszUsername, string lpszPassword, int dwService, int dwFlags, ref int dwContext ); [DllImport("Wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr HttpOpenRequest( IntPtr hConnect, string lpszVerb, string lpszObjectName, string lpszVersion, string lpszReferer, IntPtr lplpszAcceptTypes, int dwFlags, ref int dwContext ); [DllImport("Wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool HttpSendRequest( IntPtr hRequest, string lpszHeaders, int dwHeadersLength, IntPtr lpOptional, int dwOptionalLength ); [DllImport("wininet.dll", SetLastError = true)] public static extern bool InternetSetOption ( IntPtr hInternet, int dwOption, ref ulong lpBuffer, int dwBufferLength ); [DllImport("Wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool InternetQueryOption( IntPtr hInternet, int dwOption, ref IntPtr lpBuffer, ref int lpdwBufferLength ); [DllImport("wininet.dll", SetLastError = true)] public static extern int InternetErrorDlg ( IntPtr hWnd, IntPtr hRequest, int dwError, int dwFlags, IntPtr lppvData ); [DllImport("wininet.dll", SetLastError = true)] public static extern bool InternetQueryDataAvailable ( IntPtr hFile, ref int dwNumberOfBytesAvailable, int dwFlags, IntPtr dwContext ); [DllImport("wininet.dll", SetLastError = true)] public static extern bool InternetReadFile ( IntPtr hFile, IntPtr lpBuffer, int dwNumberOfBytesToRead, ref int dwNumberOfBytesRead ); [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern void CertFreeCertificateChain( IntPtr pChainContext ); [DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int CertGetNameString( IntPtr pCertContext, int dwType, int dwFlags, IntPtr pvTypePara, StringBuilder pszNameString, int cchNameString ); #endregion } }
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)