//
        // Builds a certificate chain.
        //

        internal static unsafe int BuildChain(IntPtr hChainEngine,
                                              SafeCertContextHandle pCertContext,
                                              X509Certificate2Collection extraStore,
                                              OidCollection applicationPolicy,
                                              OidCollection certificatePolicy,
                                              X509RevocationMode revocationMode,
                                              X509RevocationFlag revocationFlag,
                                              DateTime verificationTime,
                                              TimeSpan timeout,
                                              ref SafeCertChainHandle ppChainContext)
        {
            if (pCertContext == null || pCertContext.IsInvalid)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidContextHandle), "pCertContext");
            }

            SafeCertStoreHandle hCertStore = SafeCertStoreHandle.InvalidHandle;

            if (extraStore != null && extraStore.Count > 0)
            {
                hCertStore = X509Utils.ExportToMemoryStore(extraStore);
            }

            CAPI.CERT_CHAIN_PARA ChainPara = new CAPI.CERT_CHAIN_PARA();

            // Initialize the structure size.
            ChainPara.cbSize = (uint)Marshal.SizeOf(ChainPara);

            SafeLocalAllocHandle applicationPolicyHandle = SafeLocalAllocHandle.InvalidHandle;
            SafeLocalAllocHandle certificatePolicyHandle = SafeLocalAllocHandle.InvalidHandle;

            try {
                // Application policy
                if (applicationPolicy != null && applicationPolicy.Count > 0)
                {
                    ChainPara.RequestedUsage.dwType = CAPI.USAGE_MATCH_TYPE_AND;
                    ChainPara.RequestedUsage.Usage.cUsageIdentifier = (uint)applicationPolicy.Count;
                    applicationPolicyHandle = X509Utils.CopyOidsToUnmanagedMemory(applicationPolicy);
                    ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyHandle.DangerousGetHandle();
                }

                // Certificate policy
                if (certificatePolicy != null && certificatePolicy.Count > 0)
                {
                    ChainPara.RequestedIssuancePolicy.dwType = CAPI.USAGE_MATCH_TYPE_AND;
                    ChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = (uint)certificatePolicy.Count;
                    certificatePolicyHandle = X509Utils.CopyOidsToUnmanagedMemory(certificatePolicy);
                    ChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle();
                }

                ChainPara.dwUrlRetrievalTimeout = (uint)Math.Floor(timeout.TotalMilliseconds);

                _FILETIME ft = new _FILETIME();
                *((long *)&ft) = verificationTime.ToFileTime();

                uint flags = X509Utils.MapRevocationFlags(revocationMode, revocationFlag);

                // Build the chain.
                if (!CAPI.CertGetCertificateChain(hChainEngine,
                                                  pCertContext,
                                                  ref ft,
                                                  hCertStore,
                                                  ref ChainPara,
                                                  flags,
                                                  IntPtr.Zero,
                                                  ref ppChainContext))
                {
                    return(Marshal.GetHRForLastWin32Error());
                }
            }
            finally {
                applicationPolicyHandle.Dispose();
                certificatePolicyHandle.Dispose();
            }

            return(CAPI.S_OK);
        }
        static unsafe void BuildChain(IntPtr hChainEngine,
                                      IntPtr pCertContext,
                                      X509Certificate2Collection extraStore,
                                      OidCollection applicationPolicy,
                                      OidCollection certificatePolicy,
                                      X509RevocationMode revocationMode,
                                      X509RevocationFlag revocationFlag,
                                      DateTime verificationTime,
                                      TimeSpan timeout,
                                      out SafeCertChainHandle ppChainContext)
        {
            SafeCertStoreHandle hCertStore = ExportToMemoryStore(extraStore, pCertContext);

            CAPI.CERT_CHAIN_PARA ChainPara = new CAPI.CERT_CHAIN_PARA();
            ChainPara.cbSize = (uint)Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_PARA));

            // Application policy
            SafeHGlobalHandle applicationPolicyHandle = SafeHGlobalHandle.InvalidHandle;
            SafeHGlobalHandle certificatePolicyHandle = SafeHGlobalHandle.InvalidHandle;

            try
            {
                if (applicationPolicy != null && applicationPolicy.Count > 0)
                {
                    ChainPara.RequestedUsage.dwType = CAPI.USAGE_MATCH_TYPE_AND;
                    ChainPara.RequestedUsage.Usage.cUsageIdentifier = (uint)applicationPolicy.Count;
                    applicationPolicyHandle = CopyOidsToUnmanagedMemory(applicationPolicy);
                    ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyHandle.DangerousGetHandle();
                }

                // Certificate policy
                if (certificatePolicy != null && certificatePolicy.Count > 0)
                {
                    ChainPara.RequestedIssuancePolicy.dwType = CAPI.USAGE_MATCH_TYPE_AND;
                    ChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = (uint)certificatePolicy.Count;
                    certificatePolicyHandle = CopyOidsToUnmanagedMemory(certificatePolicy);
                    ChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle();
                }

                ChainPara.dwUrlRetrievalTimeout = (uint)timeout.Milliseconds;

                FILETIME ft = new FILETIME();
                *((long *)&ft) = verificationTime.ToFileTime();

                uint flags = MapRevocationFlags(revocationMode, revocationFlag);

                // Build the chain.
                if (!CAPI.CertGetCertificateChain(hChainEngine,
                                                  pCertContext,
                                                  ref ft,
                                                  hCertStore,
                                                  ref ChainPara,
                                                  flags,
                                                  IntPtr.Zero,
                                                  out ppChainContext))
                {
                    int error = Marshal.GetLastWin32Error();
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error));
                }
            }
            finally
            {
                if (applicationPolicyHandle != null)
                {
                    applicationPolicyHandle.Dispose();
                }
                if (certificatePolicyHandle != null)
                {
                    certificatePolicyHandle.Dispose();
                }
                hCertStore.Close();
            }
        }