/// <summary>
        /// Does not throw on error. Returns null ChainPal instead.
        /// </summary>
        internal static partial IChainPal?BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection?applicationPolicy,
            OidCollection?certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection?customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            CertificatePal certificatePal = (CertificatePal)cert;

            unsafe
            {
                using (SafeChainEngineHandle storeHandle = GetChainEngine(trustMode, customTrustStore, useMachineContext))
                    using (SafeCertStoreHandle extraStoreHandle = ConvertStoreToSafeHandle(extraStore))
                    {
                        Interop.Crypt32.CERT_CHAIN_PARA chainPara = default;
                        chainPara.cbSize = Marshal.SizeOf <Interop.Crypt32.CERT_CHAIN_PARA>();

                        int applicationPolicyCount;
                        using (SafeHandle applicationPolicyOids = applicationPolicy !.ToLpstrArray(out applicationPolicyCount))
                        {
                            if (!applicationPolicyOids.IsInvalid)
                            {
                                chainPara.RequestedUsage.dwType = Interop.Crypt32.CertUsageMatchType.USAGE_MATCH_TYPE_AND;
                                chainPara.RequestedUsage.Usage.cUsageIdentifier     = applicationPolicyCount;
                                chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyOids.DangerousGetHandle();
                            }

                            int certificatePolicyCount;
                            using (SafeHandle certificatePolicyOids = certificatePolicy !.ToLpstrArray(out certificatePolicyCount))
                            {
                                if (!certificatePolicyOids.IsInvalid)
                                {
                                    chainPara.RequestedIssuancePolicy.dwType = Interop.Crypt32.CertUsageMatchType.USAGE_MATCH_TYPE_AND;
                                    chainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier     = certificatePolicyCount;
                                    chainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyOids.DangerousGetHandle();
                                }

                                chainPara.dwUrlRetrievalTimeout = (int)Math.Floor(timeout.TotalMilliseconds);

                                Interop.Crypt32.FILETIME       ft    = Interop.Crypt32.FILETIME.FromDateTime(verificationTime);
                                Interop.Crypt32.CertChainFlags flags = MapRevocationFlags(revocationMode, revocationFlag, disableAia);
                                SafeX509ChainHandle            chain;
                                if (!Interop.Crypt32.CertGetCertificateChain(storeHandle.DangerousGetHandle(), certificatePal.CertContext, &ft, extraStoreHandle, ref chainPara, flags, IntPtr.Zero, out chain))
                                {
                                    return(null);
                                }

                                return(new ChainPal(chain));
                            }
                        }
                    }
            }
        }
        private byte[] PropagateKeyAlgorithmParametersFromChain()
        {
            unsafe
            {
                SafeX509ChainHandle?certChainContext = null;
                try
                {
                    int cbData = 0;
                    if (!Interop.Crypt32.CertGetCertificateContextProperty(_certContext, Interop.Crypt32.CertContextPropId.CERT_PUBKEY_ALG_PARA_PROP_ID, null, ref cbData))
                    {
                        Interop.Crypt32.CERT_CHAIN_PARA chainPara = default;
                        chainPara.cbSize = sizeof(Interop.Crypt32.CERT_CHAIN_PARA);
                        if (!Interop.Crypt32.CertGetCertificateChain((IntPtr)Interop.Crypt32.ChainEngine.HCCE_CURRENT_USER, _certContext, null, SafeCertStoreHandle.InvalidHandle, ref chainPara, Interop.Crypt32.CertChainFlags.None, IntPtr.Zero, out certChainContext))
                        {
                            throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                        }
                        if (!Interop.Crypt32.CertGetCertificateContextProperty(_certContext, Interop.Crypt32.CertContextPropId.CERT_PUBKEY_ALG_PARA_PROP_ID, null, ref cbData))
                        {
                            throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                        }
                    }

                    byte[] keyAlgorithmParameters = new byte[cbData];
                    if (!Interop.Crypt32.CertGetCertificateContextProperty(_certContext, Interop.Crypt32.CertContextPropId.CERT_PUBKEY_ALG_PARA_PROP_ID, keyAlgorithmParameters, ref cbData))
                    {
                        throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    }

                    return(keyAlgorithmParameters);
                }
                finally
                {
                    if (certChainContext != null)
                    {
                        certChainContext.Dispose();
                    }
                }
            }
        }