/// <summary>
        ///     Получить содержимое
        /// </summary>
        /// <param name="hRequest">
        ///     Указатель на HTTPS-запрос
        /// </param>
        /// <param name="result">
        ///     Результат HTTPS-запроса
        /// </param>
        private static void GetContent(IntPtr hRequest, HttpResult result)
        {
            using (var stream = new MemoryStream())
            {
                const uint chunkSize = 1024U;
                using (var buffer = InteropUtil.Alloc(chunkSize))
                {
                    while (true)
                    {
                        var bytesRead = 0U;
                        if (!WinInet.InternetReadFile(hRequest, buffer.Address, chunkSize, ref bytesRead))
                        {
                            ThrowWinInetLastException("InternetReadFile");
                        }

                        for (var i = 0; i < bytesRead; i++)
                        {
                            stream.WriteByte(Marshal.ReadByte(buffer.Address + i));
                        }

                        if (bytesRead <= 0)
                        {
                            break;
                        }
                    }
                }

                result.Content = stream.ToArray();
            }
        }
        /// <summary>
        ///     Получить тип содержимого
        /// </summary>
        /// <param name="hRequest">
        ///     Указатель на HTTPS-запрос
        /// </param>
        /// <param name="result">
        ///     Результат HTTPS-запроса
        /// </param>
        private static void GetContentType(IntPtr hRequest, HttpResult result)
        {
            var statusSize = 256U;

            using (var buffer = InteropUtil.Alloc(statusSize))
            {
                if (!WinInet.HttpQueryInfoW(
                        hRequest,
                        WinInet.HTTP_QUERY_CONTENT_TYPE,
                        buffer.Address,
                        ref statusSize,
                        IntPtr.Zero))
                {
                    ThrowWinInetLastException("HttpQueryInfoW(HTTP_QUERY_CONTENT_TYPE)");
                }

                result.ContentType = Marshal.PtrToStringUni(buffer.Address);
            }
        }
        /// <summary>
        ///     Получить код статуса HTTP
        /// </summary>
        /// <param name="hRequest">
        ///     Указатель на HTTPS-запрос
        /// </param>
        /// <param name="result">
        ///     Результат HTTPS-запроса
        /// </param>
        private static void GetStatusCode(IntPtr hRequest, HttpResult result)
        {
            uint statusSize = sizeof(uint);

            using (var buffer = InteropUtil.Alloc(statusSize))
            {
                if (!WinInet.HttpQueryInfoW(
                        hRequest,
                        WinInet.HTTP_QUERY_FLAG_NUMBER | WinInet.HTTP_QUERY_STATUS_CODE,
                        buffer.Address,
                        ref statusSize,
                        IntPtr.Zero))
                {
                    ThrowWinInetLastException("HttpQueryInfoW(HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE)");
                }

                result.Code = (HttpStatusCode)Marshal.ReadInt32(buffer.Address);
            }
        }
        /// <summary>
        ///     Конструктор
        /// </summary>
        /// <param name="uri">
        ///     Адрес конечной точки
        /// </param>
        /// <param name="certificate">
        ///     Клиентский сертифика
        /// </param>
        public WinInetHttpsClient(Uri uri, X509Certificate2 certificate)
        {
            this.uri = uri;

            #region Инициализация Crypt32

            if (certificate != null)
            {
                // Поиск сертификата
                var hStore = Crypt32.CertOpenSystemStoreW(0, "My");
                var hash   = certificate.GetCertHash();

                Crypt32.CRYPTOAPI_BLOB cryptBlob;
                cryptBlob.cbData = hash.Length;
                using (var hashHandle = InteropUtil.Pin(hash))
                {
                    cryptBlob.pbData = hashHandle.Address;
                    using (var blobHandle = InteropUtil.Pin(cryptBlob))
                    {
                        pCertContext = Crypt32.CertFindCertificateInStore(
                            hStore,
                            Crypt32.X509_ASN_ENCODING | Crypt32.PKCS_7_ASN_ENCODING,
                            0,
                            Crypt32.CERT_FIND_SHA1_HASH,
                            blobHandle.Address,
                            IntPtr.Zero);
                        if (pCertContext == IntPtr.Zero)
                        {
                            ThrowWinInetLastException("CertFindCertificateInStore");
                        }
                    }
                }

                Crypt32.CertCloseStore(hStore, 0);
                hasClientCertificate = true;
            }
            else
            {
                hasClientCertificate = false;
            }

            #endregion

            #region Инициализация WinInet

            // Инициализация WinInet
            hInternet = WinInet.InternetOpenW(
                "WSL_Proxy",
                WinInet.INTERNET_OPEN_TYPE_DIRECT,
                null,
                null,
                0);
            if (hInternet == IntPtr.Zero)
            {
                ThrowWinInetLastException("InternetOpen");
            }

            hConnect = WinInet.InternetConnectW(hInternet, uri.Host, (short)uri.Port, null, null,
                                                WinInet.INTERNET_SERVICE_HTTP, 0, IntPtr.Zero);
            if (hConnect == IntPtr.Zero)
            {
                ThrowWinInetLastException("InternetConnect");
            }

            #endregion
        }