Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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:
" 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;
// https://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
}
}
</SAMPLE>
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)