| File: System\Security\Cryptography\X509Certificates\StorePal.Windows.cs | Web Access |
| Project: src\runtime\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Runtime.InteropServices; using Internal.Cryptography; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography.X509Certificates { internal sealed partial class StorePal : IDisposable, IStorePal, IExportPal, ILoaderPal { private SafeCertStoreHandle _certStore; internal static partial IStorePal FromHandle(IntPtr storeHandle) { if (storeHandle == IntPtr.Zero) { throw new ArgumentNullException(nameof(storeHandle)); } SafeCertStoreHandle certStoreHandle = Interop.Crypt32.CertDuplicateStore(storeHandle); if (certStoreHandle == null || certStoreHandle.IsInvalid) { certStoreHandle?.Dispose(); throw new CryptographicException(SR.Cryptography_InvalidStoreHandle, nameof(storeHandle)); } var pal = new StorePal(certStoreHandle); return pal; } public void CloneTo(X509Certificate2Collection collection) { CopyTo(collection); } public void CopyTo(X509Certificate2Collection collection) { Debug.Assert(collection != null); SafeCertContextHandle? pCertContext = null; while (Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext)) { X509Certificate2 cert = new X509Certificate2(pCertContext.DangerousGetHandle()); collection.Add(cert); } } public void Add(ICertificatePal certificate) { using (SafeCertContextHandle certContext = ((CertificatePal)certificate).GetCertContext()) { if (!Interop.Crypt32.CertAddCertificateContextToStore(_certStore, certContext, Interop.Crypt32.CertStoreAddDisposition.CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, IntPtr.Zero)) throw Marshal.GetLastPInvokeError().ToCryptographicException(); } } public unsafe void Remove(ICertificatePal certificate) { using (SafeCertContextHandle existingCertContext = ((CertificatePal)certificate).GetCertContext()) { SafeCertContextHandle? enumCertContext = null; // We can use DangerousCertContext safely here because GetCertContext returns a duplicated context // that we own and doesn't escape. Interop.Crypt32.CERT_CONTEXT* pCertContext = existingCertContext.DangerousCertContext; if (!Interop.crypt32.CertFindCertificateInStore(_certStore, Interop.Crypt32.CertFindType.CERT_FIND_EXISTING, pCertContext, ref enumCertContext)) return; // The certificate is not present in the store, simply return. Interop.Crypt32.CERT_CONTEXT* pCertContextToDelete = enumCertContext.Disconnect(); // CertDeleteCertificateFromContext always frees the context (even on error) enumCertContext.Dispose(); if (!Interop.Crypt32.CertDeleteCertificateFromStore(pCertContextToDelete)) throw Marshal.GetLastPInvokeError().ToCryptographicException(); } } public void Dispose() { SafeCertStoreHandle? certStore = _certStore; if (certStore != null) { _certStore = null!; certStore.Dispose(); } } internal SafeCertStoreHandle SafeCertStoreHandle { get { return _certStore; } } SafeHandle IStorePal.SafeHandle { get { if (_certStore == null || _certStore.IsInvalid || _certStore.IsClosed) throw new CryptographicException(SR.Cryptography_X509_StoreNotOpen); return _certStore; } } internal StorePal(SafeCertStoreHandle certStore) { _certStore = certStore; } } }