internal override unsafe NCryptKeyOrCryptProviderSafeHandle OpenExisting(string keyName, out KeySpec keySpec)
        {
            keySpec = KeySpec.NONE;
            const int DOES_NOT_EXIST = unchecked ((int)0x80090016);
            NCryptKeyOrCryptProviderSafeHandle provider;

            if (!AdvApi32.CryptAcquireContext(out provider, keyName, _providerName, ProviderType.PROV_RSA_AES, 0u))
            {
                var result = Marshal.GetLastWin32Error();
                if (result == DOES_NOT_EXIST)
                {
                    return(null);
                }
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            const uint PP_KEYSPEC    = 0x27;
            uint *     keySpecBuffer = stackalloc uint[1];
            var        dataLength    = (uint)Marshal.SizeOf(typeof(uint));

            if (!AdvApi32.CryptGetProvParam(provider, PP_KEYSPEC, keySpecBuffer, ref dataLength, 0u))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            keySpec = (KeySpec)(*keySpecBuffer);
            return(provider);
        }
        internal override string GetName(NCryptKeyOrCryptProviderSafeHandle handle)
        {
            const int PP_NAME = 0x6;
            uint      size    = 0;

            if (!AdvApi32.CryptGetProvParam(handle, PP_NAME, IntPtr.Zero, ref size, 0u))
            {
                throw new InvalidOperationException("Failed to get property.");
            }
            var buffer = Marshal.AllocHGlobal((int)size);

            try
            {
                if (!AdvApi32.CryptGetProvParam(handle, PP_NAME, buffer, ref size, 0u))
                {
                    throw new InvalidOperationException("Failed to get property.");
                }
                return(Marshal.PtrToStringAnsi(buffer));
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }