private static unsafe int FindKeyUsageCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
            uint dwUsages = 0;
            if (!CAPI.CertGetIntendedKeyUsage(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 
                                              pCertContext.pCertInfo, 
                                              new IntPtr(&dwUsages), 
                                              4 /* sizeof(DWORD) */)) 
                return CAPI.S_OK; // no key usage means it is valid for all key usages.

            uint dwCheckUsage = Convert.ToUInt32(pvCallbackData, null);
            if ((dwUsages & dwCheckUsage) == dwCheckUsage)
                return CAPI.S_OK;

            return CAPI.S_FALSE;
        }
        private static unsafe int FindCertificatePolicyCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            string certPolicy = (string) pvCallbackData;
            if (certPolicy.Length == 0)
                return CAPI.S_FALSE;
            CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
            CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));

            IntPtr pExtension = CAPI.CertFindExtension(CAPI.szOID_CERT_POLICIES,
                                                       pCertInfo.cExtension,
                                                       pCertInfo.rgExtension);
            if (pExtension == IntPtr.Zero)
                return CAPI.S_FALSE;

            CAPI.CERT_EXTENSION extension = (CAPI.CERT_EXTENSION) Marshal.PtrToStructure(pExtension, typeof(CAPI.CERT_EXTENSION));
            byte[] rawData = new byte[extension.Value.cbData];
            Marshal.Copy(extension.Value.pbData, rawData, 0, rawData.Length);

            uint cbDecoded = 0;
            SafeLocalAllocHandle decoded = null;
            // Decode the extension.
            bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_CERT_POLICIES), 
                                            rawData,
                                            out decoded,
                                            out cbDecoded);
            if (result) {
                CAPI.CERT_POLICIES_INFO pInfo = (CAPI.CERT_POLICIES_INFO) Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CERT_POLICIES_INFO));
                for (int index = 0; index < pInfo.cPolicyInfo; index++) {
                    IntPtr pPolicyInfoPtr = new IntPtr((long) pInfo.rgPolicyInfo + index * Marshal.SizeOf(typeof(CAPI.CERT_POLICY_INFO)));
                    CAPI.CERT_POLICY_INFO pPolicyInfo = (CAPI.CERT_POLICY_INFO) Marshal.PtrToStructure(pPolicyInfoPtr, typeof(CAPI.CERT_POLICY_INFO));
                    if (String.Compare(certPolicy, pPolicyInfo.pszPolicyIdentifier, StringComparison.OrdinalIgnoreCase) == 0)
                        return CAPI.S_OK;
                }
            }

            return CAPI.S_FALSE;
        }
        private static unsafe int FindExtensionCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
            CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));

            IntPtr pExtension = CAPI.CertFindExtension((string) pvCallbackData,
                                                       pCertInfo.cExtension,
                                                       pCertInfo.rgExtension);
            if (pExtension == IntPtr.Zero)
                return CAPI.S_FALSE;

            return CAPI.S_OK;
        }
        private static unsafe int FindTemplateNameCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            IntPtr pV1Template = IntPtr.Zero;
            IntPtr pV2Template = IntPtr.Zero;

            CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
            CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));

            pV1Template = CAPI.CertFindExtension(CAPI.szOID_ENROLL_CERTTYPE_EXTENSION,
                                                 pCertInfo.cExtension,
                                                 pCertInfo.rgExtension);
            pV2Template = CAPI.CertFindExtension(CAPI.szOID_CERTIFICATE_TEMPLATE,
                                                 pCertInfo.cExtension,
                                                 pCertInfo.rgExtension);

            if (pV1Template == IntPtr.Zero && pV2Template == IntPtr.Zero)
                return CAPI.S_FALSE;

            if (pV1Template != IntPtr.Zero) {
                CAPI.CERT_EXTENSION extension = (CAPI.CERT_EXTENSION) Marshal.PtrToStructure(pV1Template, typeof(CAPI.CERT_EXTENSION));
                byte[] rawData = new byte[extension.Value.cbData];
                Marshal.Copy(extension.Value.pbData, rawData, 0, rawData.Length);

                uint cbDecoded = 0;
                SafeLocalAllocHandle decoded = null;
                // Decode the extension.
                bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_UNICODE_ANY_STRING), 
                                                rawData,
                                                out decoded,
                                                out cbDecoded);
                if (result) {
                    CAPI.CERT_NAME_VALUE pNameValue = (CAPI.CERT_NAME_VALUE) Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CERT_NAME_VALUE));
                    string s = Marshal.PtrToStringUni(pNameValue.Value.pbData);
                    if (String.Compare(s, (string) pvCallbackData, StringComparison.OrdinalIgnoreCase) == 0)
                        return CAPI.S_OK;
                }
            }

            if (pV2Template != IntPtr.Zero) {
                CAPI.CERT_EXTENSION extension = (CAPI.CERT_EXTENSION) Marshal.PtrToStructure(pV2Template, typeof(CAPI.CERT_EXTENSION));
                byte[] rawData = new byte[extension.Value.cbData];
                Marshal.Copy(extension.Value.pbData, rawData, 0, rawData.Length);

                uint cbDecoded = 0;
                SafeLocalAllocHandle decoded = null;
                // Decode the extension.
                bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_CERTIFICATE_TEMPLATE), 
                                                rawData,
                                                out decoded,
                                                out cbDecoded);
                if (result) {
                    CAPI.CERT_TEMPLATE_EXT pTemplate = (CAPI.CERT_TEMPLATE_EXT) Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CERT_TEMPLATE_EXT));
                    // If we were passed the friendly name, retrieve the value string.
                    string oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)pvCallbackData, Cryptography.OidGroup.Template);
                    if (oidValue == null)
                        oidValue = (string) pvCallbackData;
                    if (String.Compare(pTemplate.pszObjId, oidValue, StringComparison.OrdinalIgnoreCase) == 0)
                        return CAPI.S_OK;
                }
            }

            return CAPI.S_FALSE;
        }
        private static unsafe int FindApplicationPolicyCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            string eku = (string) pvCallbackData;
            if (eku.Length == 0)
                return CAPI.S_FALSE;
            IntPtr pCertContext = safeCertContextHandle.DangerousGetHandle();
            int cNumOIDs = 0;
            uint cbOIDs = 0;
            SafeLocalAllocHandle rghOIDs = SafeLocalAllocHandle.InvalidHandle;
            if (!CAPI.CertGetValidUsages(1, new IntPtr(&pCertContext), new IntPtr(&cNumOIDs), rghOIDs, new IntPtr(&cbOIDs))) 
                return CAPI.S_FALSE;

            rghOIDs = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbOIDs));
            if (!CAPI.CertGetValidUsages(1, new IntPtr(&pCertContext), new IntPtr(&cNumOIDs), rghOIDs, new IntPtr(&cbOIDs))) 
                return CAPI.S_FALSE;

            // -1 means the certificate is good for all usages.
            if (cNumOIDs == -1)
                return CAPI.S_OK;

            for (int index = 0; index < cNumOIDs; index++) {
                IntPtr pszOid = Marshal.ReadIntPtr(new IntPtr((long) rghOIDs.DangerousGetHandle() + index * Marshal.SizeOf(typeof(IntPtr))));
                string oidValue = Marshal.PtrToStringAnsi(pszOid);
                if (String.Compare(eku, oidValue, StringComparison.OrdinalIgnoreCase) == 0)
                    return CAPI.S_OK;
            }

            return CAPI.S_FALSE;
        }
        private static unsafe int FindTimeNotBeforeCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            _FILETIME ft = (_FILETIME) pvCallbackData;
            CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
            if (CAPI.CertVerifyTimeValidity(ref ft, pCertContext.pCertInfo) == -1)
                return CAPI.S_OK;

            return CAPI.S_FALSE;
        }
        private static unsafe int FindSerialNumberCallback(Cryptography.SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
            CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
            CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));

            byte[] hex = new byte[pCertInfo.SerialNumber.cbData];
            Marshal.Copy(pCertInfo.SerialNumber.pbData, hex, 0, hex.Length);

            int size = X509Utils.GetHexArraySize(hex);
            byte[] serialNumber = (byte[]) pvCallbackData;
            if (serialNumber.Length != size)
                return CAPI.S_FALSE;

            for (int index = 0; index < serialNumber.Length; index++) {
                if (serialNumber[index] != hex[index])
                    return CAPI.S_FALSE;
            }

            return CAPI.S_OK;
        }
 private static unsafe uint GetVersion (Cryptography.SafeCertContextHandle safeCertContextHandle) {
     CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
     CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));
     return (pCertInfo.dwVersion + 1);
 }
 private static unsafe Oid GetSignatureAlgorithm (Cryptography.SafeCertContextHandle safeCertContextHandle) {
     CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
     CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));
     return new Oid(pCertInfo.SignatureAlgorithm.pszObjId, Cryptography.OidGroup.SignatureAlgorithm, false);
 }
        private static void RemoveCertificateFromStore(Cryptography.SafeCertStoreHandle safeCertStoreHandle, Cryptography.SafeCertContextHandle safeCertContext) {
            if (safeCertContext == null || safeCertContext.IsInvalid)
                return;

            if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid || safeCertStoreHandle.IsClosed)
                throw new CryptographicException(SR.GetString(SR.Cryptography_X509_StoreNotOpen));

            // Find the certificate in the store.
            Cryptography.SafeCertContextHandle safeCertContext2 = CAPI.CertFindCertificateInStore(safeCertStoreHandle, 
                                                                                     CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                                                     0, 
                                                                                     CAPI.CERT_FIND_EXISTING, 
                                                                                     safeCertContext.DangerousGetHandle(),
                                                                                     Cryptography.SafeCertContextHandle.InvalidHandle);

            // The certificate is not present in the store, simply return.
            if (safeCertContext2 == null || safeCertContext2.IsInvalid)
                return;

            // CertDeleteCertificateFromStore always releases the context regardless of success 
            // or failure so we don't need to manually release it
            GC.SuppressFinalize(safeCertContext2);

            // Remove from the store.
            if (!CAPI.CertDeleteCertificateFromStore(safeCertContext2))
                throw new CryptographicException(Marshal.GetLastWin32Error());
        }