/// <summary>
        /// Helper method to verify that published mp, mpb, or cabinet files have a valid authenticode signature
        /// </summary>
        /// <param name="filePath">Path to the file to check the signature on.</param>
        /// <returns>WinTrustData object</returns>
        private static WinTrustData VerifyFileAuthenticodeSignatureHelper(string filePath, Tracing trace)
        {
            WinTrustData                trustData         = null;
            WinTrustFileInfo            fileInfo          = new WinTrustFileInfo(filePath);
            WINTRUST_SIGNATURE_SETTINGS signatureSettings = null;
            WinVerifyTrustResult        result;

            if (Utility.IsWin8OrAbove())
            {
                // On Windows 8 and above we have the APIs to enforce stronger checks
                const string szOID_CERT_STRONG_SIGN_OS_1 = "1.3.6.1.4.1.311.72.1.1"; //this specifies to enforce SHA-2 based hashes and other strong key requirements
                signatureSettings = new WINTRUST_SIGNATURE_SETTINGS(new CERT_STRONG_SIGN_PARA(szOID_CERT_STRONG_SIGN_OS_1));
                trustData         = new Win8TrustData(fileInfo, signatureSettings);
            }
            else
            {
                // no signature settings
                trustData = new WinTrustData(filePath);
            }

            try
            {
                result = UnsafeNativeMethods.WinVerifyTrust(
                    IntPtr.Zero,
                    UnsafeNativeMethods.WINTRUST_ACTION_GENERIC_VERIFY_V2,
                    trustData);


                if (result == WinVerifyTrustResult.FileNotSigned)
                {
                    throw new VerificationException(string.Format(CultureInfo.CurrentCulture, "File {0} does not have a valid authenticode signature.", filePath));
                }
                else if (result != WinVerifyTrustResult.Success)
                {
                    var winTrustResultErrorString = String.Format("{0} ({1})", GetVerboseWinVerifyTrustResultErrorString(result), ConvertWinVerifyTrustResultToHex(result));
                    throw new VerificationException(string.Format(CultureInfo.CurrentCulture, "WinVerifyTrustWrapper on file {0} failed with unexpected error: {1}", filePath, winTrustResultErrorString));
                }
            }
            catch (Exception ex)
            {
                trace.Error(String.Format("Error occurred while calling WinVerifyTrust: {0}", ex));

                // free all objects (trustData and signatureSettings)
                if (signatureSettings != null)
                {
                    signatureSettings.Dispose();
                }

                trustData.Dispose();
                throw;
            }

            trace.Info(String.Format("File {0} has a valid authenticode signature.", filePath));

            // only free signatureSettings
            if (signatureSettings != null)
            {
                signatureSettings.Dispose();

                // zero out the psignature pointer in trustData to be safe
                Marshal.FreeHGlobal(((Win8TrustData)trustData).pSignatureSettings);
                ((Win8TrustData)trustData).pSignatureSettings = IntPtr.Zero;
            }

            return(trustData);
        }
        /// <summary>
        /// Utility method to verify that mp was signed by Microsoft
        /// </summary>
        /// <param name="filePath">Path to the file to check the signature on.</param>
        public static void VerifyFileSignedByMicrosoft(string filePath, Tracing trace, string expectedEKU = CODE_SIGNING_ENHANCED_KEY_USAGE)
        {
            // proceed with authenticode checks
            WinTrustData winTrustData = VerifyFileAuthenticodeSignatureHelper(filePath, trace);

            try
            {
                IntPtr pProviderData = UnsafeNativeMethods.WTHelperProvDataFromStateData(winTrustData.StateData);
                if (pProviderData == IntPtr.Zero)
                {
                    throw new Win32Exception(string.Format(CultureInfo.CurrentCulture, "File {0} WTHelperProvDataFromStateData returned null.", filePath));
                }

                IntPtr pSigner = UnsafeNativeMethods.WTHelperGetProvSignerFromChain(pProviderData, 0, false, 0);
                if (pSigner == IntPtr.Zero)
                {
                    throw new Win32Exception(string.Format(CultureInfo.CurrentCulture, "File {0} WTHelperGetProvSignerFromChain returned null.", filePath));
                }

                CRYPT_PROVIDER_SGNR provSigner = (CRYPT_PROVIDER_SGNR)Marshal.PtrToStructure(pSigner, typeof(CRYPT_PROVIDER_SGNR));

                CERT_CHAIN_POLICY_PARA   policyPara   = new CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_PARA)));
                CERT_CHAIN_POLICY_STATUS policyStatus = new CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_STATUS)));

                if (!UnsafeNativeMethods.CertVerifyCertificateChainPolicy(
                        new IntPtr(UnsafeNativeMethods.CERT_CHAIN_POLICY_MICROSOFT_ROOT),
                        provSigner.pChainContext,
                        ref policyPara,
                        ref policyStatus))
                {
                    throw new Win32Exception(string.Format(CultureInfo.CurrentCulture, "File {0} CertVerifyCertificateChainPolicy wasn't able to check for the policy", filePath));
                }

                //If using SHA-2 validation the root certificate is different from the older SHA-1 certificate
                if (policyStatus.dwError != 0)
                {
                    policyPara.dwFlags = UnsafeNativeMethods.MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG;
                    if (!UnsafeNativeMethods.CertVerifyCertificateChainPolicy(
                            new IntPtr(UnsafeNativeMethods.CERT_CHAIN_POLICY_MICROSOFT_ROOT),
                            provSigner.pChainContext,
                            ref policyPara,
                            ref policyStatus))
                    {
                        throw new Win32Exception(string.Format(CultureInfo.CurrentCulture, "File {0} CertVerifyCertificateChainPolicy wasn't able to check for the policy", filePath));
                    }

                    if (policyStatus.dwError != 0)
                    {
#if DEBUG
                        {
                            policyPara.dwFlags = UnsafeNativeMethods.MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG;
                            if (!UnsafeNativeMethods.CertVerifyCertificateChainPolicy(
                                    new IntPtr(UnsafeNativeMethods.CERT_CHAIN_POLICY_MICROSOFT_ROOT),
                                    provSigner.pChainContext,
                                    ref policyPara,
                                    ref policyStatus))
                            {
                                throw new Win32Exception(string.Format(CultureInfo.CurrentCulture, "File {0} CertVerifyCertificateChainPolicy wasn't able to check for the policy", filePath));
                            }

                            if (policyStatus.dwError != 0)
                            {
                                trace.Error("policyStatus: " + policyStatus.ToString());
                                trace.Error("policyStatus.pvExtraPolicyStatus: " + policyStatus.pvExtraPolicyStatus);
                                trace.Error(String.Format("Error occurred while calling WinVerifyTrust: {0}", string.Format(CultureInfo.CurrentCulture, "File {0} does not have a valid MS or ms-test signature.", filePath)));
                                // throw new VerificationException(string.Format(CultureInfo.CurrentCulture, "File {0} does not have a valid MS or ms-test signature.", filePath));
                            }
                        }
#else
                        throw new VerificationException(string.Format(CultureInfo.CurrentCulture, "File {0} does not have a valid MS signature.", filePath));
#endif
                    }
                }

                trace.Info(String.Format("File {0} has a valid MS or ms-test signature.", filePath));

                // Get the certificate used to sign the file
                IntPtr pProviderCertificate = UnsafeNativeMethods.WTHelperGetProvCertFromChain(pSigner, 0);
                if (pProviderCertificate == IntPtr.Zero)
                {
                    throw new Win32Exception(string.Format(CultureInfo.CurrentCulture, "WTHelperGetProvCertFromChain returned null."));
                }

                CRYPT_PROVIDER_CERT provCert = (CRYPT_PROVIDER_CERT)Marshal.PtrToStructure(pProviderCertificate, typeof(CRYPT_PROVIDER_CERT));

                // Check for our EKU in the certificate
                using (X509Certificate2 x509Cert = new X509Certificate2(provCert.pCert))
                {
                    if (((X509EnhancedKeyUsageExtension)x509Cert.Extensions[EXTENDED_KEY_USAGE]).EnhancedKeyUsages[expectedEKU] == null)
                    {
                        // throw new exception
                        throw new VerificationException(string.Format(CultureInfo.CurrentCulture, "Authenticode signature for file {0} is not signed with a certificate containing the EKU {1}.", filePath, expectedEKU));
                    }

                    trace.Info(String.Format("Authenticode signature for file {0} is signed with a certificate containing the EKU {1}.", filePath, expectedEKU));
                }
            }
            finally
            {
                // dispose winTrustData object
                winTrustData.Dispose();
            }
        }
 internal static extern WinVerifyTrustResult WinVerifyTrust(
     IntPtr hwnd,
     [MarshalAs(UnmanagedType.LPStruct)] Guid pgActionID,
     [In, Out] WinTrustData pWVTData);