private static CertificateBinding[] QueryInternal()
        {
            var result = new List <CertificateBinding>();

            HttpApi.CallHttpApi(
                delegate {
                uint token = 0;

                uint retVal;
                do
                {
                    var inputConfigInfoQuery = new HttpApi.HTTP_SERVICE_CONFIG_SSL_QUERY {
                        QueryDesc = HttpApi.HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryNext,
                        dwToken   = token,
                    };

                    IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(
                        Marshal.SizeOf(typeof(HttpApi.HTTP_SERVICE_CONFIG_SSL_QUERY)));
                    Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false);

                    IntPtr pOutputConfigInfo = IntPtr.Zero;
                    int returnLength         = 0;

                    try {
                        int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery);
                        retVal = HttpApi.HttpQueryServiceConfiguration(IntPtr.Zero,
                                                                       HttpApi.HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
                                                                       pInputConfigInfo,
                                                                       inputConfigInfoSize,
                                                                       pOutputConfigInfo,
                                                                       returnLength,
                                                                       out returnLength,
                                                                       IntPtr.Zero);
                        if (HttpApi.ERROR_NO_MORE_ITEMS == retVal)
                        {
                            break;
                        }
                        if (HttpApi.ERROR_INSUFFICIENT_BUFFER == retVal)
                        {
                            pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength);

                            try {
                                retVal = HttpApi.HttpQueryServiceConfiguration(IntPtr.Zero,
                                                                               HttpApi.HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
                                                                               pInputConfigInfo,
                                                                               inputConfigInfoSize,
                                                                               pOutputConfigInfo,
                                                                               returnLength,
                                                                               out returnLength,
                                                                               IntPtr.Zero);
                                HttpApi.ThrowWin32ExceptionIfError(retVal);

                                var outputConfigInfo = (HttpApi.HTTP_SERVICE_CONFIG_SSL_SET)Marshal.PtrToStructure(
                                    pOutputConfigInfo, typeof(HttpApi.HTTP_SERVICE_CONFIG_SSL_SET));
                                var resultItem = CreateCertificateBindingInfo(outputConfigInfo);
                                result.Add(resultItem);
                                token++;
                            } finally {
                                Marshal.FreeCoTaskMem(pOutputConfigInfo);
                            }
                        }
                        else
                        {
                            HttpApi.ThrowWin32ExceptionIfError(retVal);
                        }
                    } finally {
                        Marshal.FreeCoTaskMem(pInputConfigInfo);
                    }
                } while (HttpApi.NOERROR == retVal);
            });

            return(result.ToArray());
        }
        private static CertificateBinding QueryExact(IPEndPoint ipPort)
        {
            CertificateBinding result = null;

            uint retVal;

            HttpApi.CallHttpApi(
                delegate {
                GCHandle sockAddrHandle = SockaddrInterop.CreateSockaddrStructure(ipPort);
                IntPtr pIpPort          = sockAddrHandle.AddrOfPinnedObject();
                var sslKey = new HttpApi.HTTP_SERVICE_CONFIG_SSL_KEY(pIpPort);

                var inputConfigInfoQuery = new HttpApi.HTTP_SERVICE_CONFIG_SSL_QUERY {
                    QueryDesc = HttpApi.HTTP_SERVICE_CONFIG_QUERY_TYPE.HttpServiceConfigQueryExact,
                    KeyDesc   = sslKey
                };

                IntPtr pInputConfigInfo = Marshal.AllocCoTaskMem(
                    Marshal.SizeOf(typeof(HttpApi.HTTP_SERVICE_CONFIG_SSL_QUERY)));
                Marshal.StructureToPtr(inputConfigInfoQuery, pInputConfigInfo, false);

                IntPtr pOutputConfigInfo = IntPtr.Zero;
                int returnLength         = 0;

                try {
                    int inputConfigInfoSize = Marshal.SizeOf(inputConfigInfoQuery);
                    retVal = HttpApi.HttpQueryServiceConfiguration(IntPtr.Zero,
                                                                   HttpApi.HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
                                                                   pInputConfigInfo,
                                                                   inputConfigInfoSize,
                                                                   pOutputConfigInfo,
                                                                   returnLength,
                                                                   out returnLength,
                                                                   IntPtr.Zero);
                    if (retVal == HttpApi.ERROR_FILE_NOT_FOUND)
                    {
                        return;
                    }

                    if (HttpApi.ERROR_INSUFFICIENT_BUFFER == retVal)
                    {
                        pOutputConfigInfo = Marshal.AllocCoTaskMem(returnLength);
                        try {
                            retVal = HttpApi.HttpQueryServiceConfiguration(IntPtr.Zero,
                                                                           HttpApi.HTTP_SERVICE_CONFIG_ID.HttpServiceConfigSSLCertInfo,
                                                                           pInputConfigInfo,
                                                                           inputConfigInfoSize,
                                                                           pOutputConfigInfo,
                                                                           returnLength,
                                                                           out returnLength,
                                                                           IntPtr.Zero);
                            HttpApi.ThrowWin32ExceptionIfError(retVal);

                            var outputConfigInfo =
                                (HttpApi.HTTP_SERVICE_CONFIG_SSL_SET)
                                Marshal.PtrToStructure(pOutputConfigInfo, typeof(HttpApi.HTTP_SERVICE_CONFIG_SSL_SET));
                            result = CreateCertificateBindingInfo(outputConfigInfo);
                        } finally {
                            Marshal.FreeCoTaskMem(pOutputConfigInfo);
                        }
                    }
                    else
                    {
                        HttpApi.ThrowWin32ExceptionIfError(retVal);
                    }
                } finally {
                    Marshal.FreeCoTaskMem(pInputConfigInfo);
                    if (sockAddrHandle.IsAllocated)
                    {
                        sockAddrHandle.Free();
                    }
                }
            });

            return(result);
        }