Esempio n. 1
0
        public static bool WinHttpGetProxyForUrl(
            SafeWinHttpHandle sessionHandle,
            string url,
            ref Interop.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions,
            out Interop.WinHttp.WINHTTP_PROXY_INFO proxyInfo)
        {
            if (TestControl.PACFileNotDetectedOnNetwork)
            {
                proxyInfo.AccessType  = WINHTTP_ACCESS_TYPE_NO_PROXY;
                proxyInfo.Proxy       = IntPtr.Zero;
                proxyInfo.ProxyBypass = IntPtr.Zero;

                TestControl.LastWin32Error = (int)Interop.WinHttp.ERROR_WINHTTP_AUTODETECTION_FAILED;
                return(false);
            }

            proxyInfo.AccessType  = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
            proxyInfo.Proxy       = Marshal.StringToHGlobalUni(FakeRegistry.WinInetProxySettings.Proxy);
            proxyInfo.ProxyBypass = IntPtr.Zero;

            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the proxy URI. (IWebProxy interface)
        /// </summary>
        public Uri GetProxy(Uri uri)
        {
            if (_proxyHelper.ManualSettingsOnly)
            {
                return(_proxyUri);
            }
            var proxyInfo = new Interop.WinHttp.WINHTTP_PROXY_INFO();

            try
            {
                if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo))
                {
                    return(GetUriFromString(Marshal.PtrToStringUni(proxyInfo.Proxy)));
                }
            }
            finally
            {
                Marshal.FreeHGlobal(proxyInfo.Proxy);
                Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
            }
            return(null);
        }
Esempio n. 3
0
        private void SetRequestHandleProxyOptions(RequestState state)
        {
            // We've already set the proxy on the session handle if we're using no proxy or default proxy settings.
            // We only need to change it on the request handle if we have a specific IWebProxy or need to manually
            // implement Wininet-style auto proxy detection.
            if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy ||
                state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinInetProxy)
            {
                var proxyInfo = new Interop.WinHttp.WINHTTP_PROXY_INFO();
                bool updateProxySettings = false;
                Uri uri = state.RequestMessage.RequestUri;

                try
                {
                    if (state.Proxy != null)
                    {
                        Debug.Assert(state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy);
                        updateProxySettings = true;
                        if (state.Proxy.IsBypassed(uri))
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
                        }
                        else
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                            Uri proxyUri = state.Proxy.GetProxy(uri);
                            string proxyString = string.Format(
                                CultureInfo.InvariantCulture,
                                "{0}://{1}",
                                proxyUri.Scheme,
                                proxyUri.Authority);
                            proxyInfo.Proxy = Marshal.StringToHGlobalUni(proxyString);
                        }
                    }
                    else if (_proxyHelper != null && _proxyHelper.AutoSettingsUsed)
                    {
                        updateProxySettings = true;
                        _proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo);
                    }

                    if (updateProxySettings)
                    {
                        GCHandle pinnedHandle = GCHandle.Alloc(proxyInfo, GCHandleType.Pinned);

                        try
                        {
                            SetWinHttpOption(
                                state.RequestHandle,
                                Interop.WinHttp.WINHTTP_OPTION_PROXY,
                                pinnedHandle.AddrOfPinnedObject(),
                                (uint)Marshal.SizeOf(proxyInfo));
                        }
                        finally
                        {
                            pinnedHandle.Free();
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(proxyInfo.Proxy);
                    Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Gets the proxy URI. (IWebProxy interface)
        /// </summary>
        public Uri GetProxy(Uri uri)
        {
            if (_proxyHelper.ManualSettingsOnly)
            {
                if (_bypassLocal)
                {
                    IPAddress address = null;

                    if (uri.IsLoopback)
                    {
                        // This is optimization for loopback addresses.
                        // Unfortunately this does not work for all local addresses.
                        return(null);
                    }

                    // Pre-Check if host may be IP address to avoid parsing.
                    if (uri.HostNameType == UriHostNameType.IPv6 || uri.HostNameType == UriHostNameType.IPv4)
                    {
                        // RFC1123 allows labels to start with number.
                        // Leading number may or may not be IP address.
                        // IPv6 [::1] notation. '[' is not valid character in names.
                        if (IPAddress.TryParse(uri.IdnHost, out address))
                        {
                            // Host is valid IP address.
                            // Check if it belongs to local system.
                            foreach (IPAddress a in _localIp)
                            {
                                if (a.Equals(address))
                                {
                                    return(null);
                                }
                            }
                        }
                    }
                    if (uri.HostNameType != UriHostNameType.IPv6 && uri.IdnHost.IndexOf('.') == -1)
                    {
                        // Not address and does not have a dot.
                        // Hosts without FQDN are considered local.
                        return(null);
                    }
                }

                // Check if we have other rules for bypass.
                if (_bypass != null)
                {
                    foreach (Regex entry in _bypass)
                    {
                        // IdnHost does not have [].
                        if (entry.IsMatch(uri.IdnHost))
                        {
                            return(null);
                        }
                    }
                }

                // We did not find match on bypass list.
                return((uri.Scheme == UriScheme.Https || uri.Scheme == UriScheme.Wss) ? _secureProxyUri : _insecureProxyUri);
            }

            // For anything else ask WinHTTP.
            var proxyInfo = new Interop.WinHttp.WINHTTP_PROXY_INFO();

            try
            {
                if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo))
                {
                    return(GetUriFromString(Marshal.PtrToStringUni(proxyInfo.Proxy)));
                }
            }
            finally
            {
                Marshal.FreeHGlobal(proxyInfo.Proxy);
                Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
            }
            return(null);
        }
Esempio n. 5
0
        public bool GetProxyForUrl(
            SafeWinHttpHandle?sessionHandle,
            Uri uri,
            out Interop.WinHttp.WINHTTP_PROXY_INFO proxyInfo)
        {
            proxyInfo.AccessType  = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
            proxyInfo.Proxy       = IntPtr.Zero;
            proxyInfo.ProxyBypass = IntPtr.Zero;

            if (!_useProxy)
            {
                return(false);
            }

            bool useProxy = false;

            Interop.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
            autoProxyOptions.AutoConfigUrl   = AutoConfigUrl;
            autoProxyOptions.AutoDetectFlags = AutoDetect ?
                                               (Interop.WinHttp.WINHTTP_AUTO_DETECT_TYPE_DHCP | Interop.WinHttp.WINHTTP_AUTO_DETECT_TYPE_DNS_A) : 0;
            autoProxyOptions.AutoLoginIfChallenged = false;
            autoProxyOptions.Flags =
                (AutoDetect ? Interop.WinHttp.WINHTTP_AUTOPROXY_AUTO_DETECT : 0) |
                (!string.IsNullOrEmpty(AutoConfigUrl) ? Interop.WinHttp.WINHTTP_AUTOPROXY_CONFIG_URL : 0);
            autoProxyOptions.Reserved1 = IntPtr.Zero;
            autoProxyOptions.Reserved2 = 0;

            // AutoProxy Cache.
            // https://docs.microsoft.com/en-us/windows/desktop/WinHttp/autoproxy-cache
            // If the out-of-process service is active when WinHttpGetProxyForUrl is called, the cached autoproxy
            // URL and script are available to the whole computer. However, if the out-of-process service is used,
            // and the fAutoLogonIfChallenged flag in the pAutoProxyOptions structure is true, then the autoproxy
            // URL and script are not cached. Therefore, calling WinHttpGetProxyForUrl with the fAutoLogonIfChallenged
            // member set to TRUE results in additional overhead operations that may affect performance.
            // The following steps can be used to improve performance:
            // 1. Call WinHttpGetProxyForUrl with the fAutoLogonIfChallenged parameter set to false. The autoproxy
            //    URL and script are cached for future calls to WinHttpGetProxyForUrl.
            // 2. If Step 1 fails, with ERROR_WINHTTP_LOGIN_FAILURE, then call WinHttpGetProxyForUrl with the
            //    fAutoLogonIfChallenged member set to TRUE.
            //
            // We match behavior of WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY and ignore errors.

#pragma warning disable CA1845 // file is shared with a build that lacks string.Concat for spans
            // Underlying code does not understand WebSockets so we need to convert it to http or https.
            string destination = uri.AbsoluteUri;
            if (uri.Scheme == UriScheme.Wss)
            {
                destination = UriScheme.Https + destination.Substring(UriScheme.Wss.Length);
            }
            else if (uri.Scheme == UriScheme.Ws)
            {
                destination = UriScheme.Http + destination.Substring(UriScheme.Ws.Length);
            }
#pragma warning restore CA1845

            var repeat = false;
            do
            {
                _autoDetectionFailed = false;
                if (Interop.WinHttp.WinHttpGetProxyForUrl(
                        sessionHandle !,
                        destination,
                        ref autoProxyOptions,
                        out proxyInfo))
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(this, "Using autoconfig proxy settings");
                    }
                    useProxy = true;

                    break;
                }
                else
                {
                    var lastError = Marshal.GetLastWin32Error();
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(this, $"error={lastError}");
                    }

                    if (lastError == Interop.WinHttp.ERROR_WINHTTP_LOGIN_FAILURE)
                    {
                        if (repeat)
                        {
                            // We don't retry more than once.
                            break;
                        }
                        else
                        {
                            repeat = true;
                            autoProxyOptions.AutoLoginIfChallenged = true;
                        }
                    }
                    else
                    {
                        if (lastError == Interop.WinHttp.ERROR_WINHTTP_AUTODETECTION_FAILED)
                        {
                            _autoDetectionFailed         = true;
                            _lastTimeAutoDetectionFailed = Environment.TickCount;
                        }

                        break;
                    }
                }
            } while (repeat);
Esempio n. 6
0
        private void SetRequestHandleProxyOptions(WinHttpRequestState state)
        {
            // We've already set the proxy on the session handle if we're using no proxy or default proxy settings.
            // We only need to change it on the request handle if we have a specific IWebProxy or need to manually
            // implement Wininet-style auto proxy detection.
            if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy ||
                state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinInetProxy)
            {
                var  proxyInfo           = new Interop.WinHttp.WINHTTP_PROXY_INFO();
                bool updateProxySettings = false;
                Uri  uri = state.RequestMessage.RequestUri;

                try
                {
                    if (state.Proxy != null)
                    {
                        Debug.Assert(state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy);
                        updateProxySettings = true;
                        if (state.Proxy.IsBypassed(uri))
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
                        }
                        else
                        {
                            proxyInfo.AccessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                            Uri    proxyUri    = state.Proxy.GetProxy(uri);
                            string proxyString = string.Format(
                                CultureInfo.InvariantCulture,
                                "{0}://{1}",
                                proxyUri.Scheme,
                                proxyUri.Authority);
                            proxyInfo.Proxy = Marshal.StringToHGlobalUni(proxyString);
                        }
                    }
                    else if (_proxyHelper != null && _proxyHelper.AutoSettingsUsed)
                    {
                        updateProxySettings = true;
                        _proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo);
                    }

                    if (updateProxySettings)
                    {
                        GCHandle pinnedHandle = GCHandle.Alloc(proxyInfo, GCHandleType.Pinned);

                        try
                        {
                            SetWinHttpOption(
                                state.RequestHandle,
                                Interop.WinHttp.WINHTTP_OPTION_PROXY,
                                pinnedHandle.AddrOfPinnedObject(),
                                (uint)Marshal.SizeOf(proxyInfo));
                        }
                        finally
                        {
                            pinnedHandle.Free();
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(proxyInfo.Proxy);
                    Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the proxy URIs.
        /// </summary>
        public MultiProxy GetMultiProxy(Uri uri)
        {
            // We need WinHTTP to detect and/or process a PAC (JavaScript) file. This maps to
            // "Automatically detect settings" and/or "Use automatic configuration script" from IE
            // settings. But, calling into WinHTTP can be slow especially when it has to call into
            // the out-of-process service to discover, load, and run the PAC file. So, we skip
            // calling into WinHTTP if there was a recent failure to detect a PAC file on the network.
            // This is a common error. The default IE settings on a Windows machine consist of the
            // single checkbox for "Automatically detect settings" turned on and most networks
            // won't actually discover a PAC file on the network since WPAD protocol isn't configured.
            if (_proxyHelper.AutoSettingsUsed && !_proxyHelper.RecentAutoDetectionFailure)
            {
                Interop.WinHttp.WINHTTP_PROXY_INFO proxyInfo = default;
                try
                {
                    if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo))
                    {
                        // If WinHTTP just specified a Proxy with no ProxyBypass list, then
                        // we can return the Proxy uri directly.
                        if (proxyInfo.ProxyBypass == IntPtr.Zero)
                        {
                            if (proxyInfo.Proxy != IntPtr.Zero)
                            {
                                string proxyStr = Marshal.PtrToStringUni(proxyInfo.Proxy) !;

                                return(MultiProxy.CreateLazy(_failedProxies, proxyStr, IsSecureUri(uri)));
                            }
                            else
                            {
                                return(MultiProxy.Empty);
                            }
                        }

                        // A bypass list was also specified. This means that WinHTTP has fallen back to
                        // using the manual IE settings specified and there is a ProxyBypass list also.
                        // Since we're not really using the full WinHTTP stack, we need to use HttpSystemProxy
                        // to do the computation of the final proxy uri merging the information from the Proxy
                        // and ProxyBypass strings.
                    }
                    else
                    {
                        return(MultiProxy.Empty);
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(proxyInfo.Proxy);
                    Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
                }
            }

            // Fallback to manual settings if present.
            if (_proxyHelper.ManualSettingsUsed)
            {
                if (_bypassLocal)
                {
                    IPAddress?address;

                    if (uri.IsLoopback)
                    {
                        // This is optimization for loopback addresses.
                        // Unfortunately this does not work for all local addresses.
                        return(MultiProxy.Empty);
                    }

                    // Pre-Check if host may be IP address to avoid parsing.
                    if (uri.HostNameType == UriHostNameType.IPv6 || uri.HostNameType == UriHostNameType.IPv4)
                    {
                        // RFC1123 allows labels to start with number.
                        // Leading number may or may not be IP address.
                        // IPv6 [::1] notation. '[' is not valid character in names.
                        if (IPAddress.TryParse(uri.IdnHost, out address))
                        {
                            // Host is valid IP address.
                            // Check if it belongs to local system.
                            foreach (IPAddress a in _localIp !)
                            {
                                if (a.Equals(address))
                                {
                                    return(MultiProxy.Empty);
                                }
                            }
                        }
                    }
                    if (uri.HostNameType != UriHostNameType.IPv6 && !uri.IdnHost.Contains('.'))
                    {
                        // Not address and does not have a dot.
                        // Hosts without FQDN are considered local.
                        return(MultiProxy.Empty);
                    }
                }

                // Check if we have other rules for bypass.
                if (_bypass != null)
                {
                    foreach (string entry in _bypass)
                    {
                        // IdnHost does not have [].
                        if (SimpleRegex.IsMatchWithStarWildcard(uri.IdnHost, entry))
                        {
                            return(MultiProxy.Empty);
                        }
                    }
                }

                // We did not find match on bypass list.
                return(IsSecureUri(uri) ? _secureProxy : _insecureProxy);
            }

            return(MultiProxy.Empty);
        }
Esempio n. 8
0
        public void GetProxyForUrl(SafeWinHttpHandle sessionHandle, Uri uri, out Interop.WinHttp.WINHTTP_PROXY_INFO proxyInfo)
        {
            Interop.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
            autoProxyOptions.AutoConfigUrl         = AutoConfigUrl;
            autoProxyOptions.AutoDetectFlags       = AutoDetect ? (Interop.WinHttp.WINHTTP_AUTO_DETECT_TYPE_DHCP | Interop.WinHttp.WINHTTP_AUTO_DETECT_TYPE_DNS_A) : 0;
            autoProxyOptions.AutoLoginIfChallenged = false;
            autoProxyOptions.Flags =
                (AutoDetect ? Interop.WinHttp.WINHTTP_AUTOPROXY_AUTO_DETECT : 0) |
                (!string.IsNullOrEmpty(AutoConfigUrl) ? Interop.WinHttp.WINHTTP_AUTOPROXY_CONFIG_URL : 0);
            autoProxyOptions.Reserved1 = IntPtr.Zero;
            autoProxyOptions.Reserved2 = 0;

            // AutoProxy Cache.
            // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383153(v=vs.85).aspx
            // If the out-of-process service is active when WinHttpGetProxyForUrl is called, the cached autoproxy
            // URL and script are available to the whole computer. However, if the out-of-process service is used,
            // and the fAutoLogonIfChallenged flag in the pAutoProxyOptions structure is true, then the autoproxy
            // URL and script are not cached. Therefore, calling WinHttpGetProxyForUrl with the fAutoLogonIfChallenged
            // member set to TRUE results in additional overhead operations that may affect performance.
            // The following steps can be used to improve performance:
            // 1. Call WinHttpGetProxyForUrl with the fAutoLogonIfChallenged parameter set to false. The autoproxy
            //    URL and script are cached for future calls to WinHttpGetProxyForUrl.
            // 2. If Step 1 fails, with ERROR_WINHTTP_LOGIN_FAILURE, then call WinHttpGetProxyForUrl with the
            //    fAutoLogonIfChallenged member set to TRUE.
            var repeat = false;

            do
            {
                if (Interop.WinHttp.WinHttpGetProxyForUrl(sessionHandle, uri.AbsoluteUri, ref autoProxyOptions, out proxyInfo))
                {
                    repeat = false;
                }
                else
                {
                    var lastError = Marshal.GetLastWin32Error();
                    if (lastError == Interop.WinHttp.ERROR_WINHTTP_AUTODETECTION_FAILED)
                    {
                        // Fall back to manual settings if available.
                        if (!string.IsNullOrEmpty(Proxy))
                        {
                            proxyInfo.AccessType  = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                            proxyInfo.Proxy       = Marshal.StringToHGlobalUni(Proxy);
                            proxyInfo.ProxyBypass = string.IsNullOrEmpty(ProxyBypass) ? IntPtr.Zero : Marshal.StringToHGlobalUni(ProxyBypass);
                        }
                        else
                        {
                            proxyInfo.AccessType  = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
                            proxyInfo.Proxy       = IntPtr.Zero;
                            proxyInfo.ProxyBypass = IntPtr.Zero;
                        }

                        repeat = false;
                    }
                    else if (lastError == Interop.WinHttp.ERROR_WINHTTP_LOGIN_FAILURE)
                    {
                        if (repeat)
                        {
                            throw WinHttpException.CreateExceptionUsingError(lastError);
                        }

                        repeat = true;
                        autoProxyOptions.AutoLoginIfChallenged = true;
                    }
                    else
                    {
                        WinHttpException.ThrowExceptionUsingLastError();
                    }
                }
            } while (repeat);
        }
        public bool GetProxyForUrl(
            SafeWinHttpHandle sessionHandle,
            Uri uri,
            out Interop.WinHttp.WINHTTP_PROXY_INFO proxyInfo)
        {
            proxyInfo.AccessType  = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
            proxyInfo.Proxy       = IntPtr.Zero;
            proxyInfo.ProxyBypass = IntPtr.Zero;

            if (!_useProxy)
            {
                return(false);
            }

            bool useProxy = false;

            Interop.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
            autoProxyOptions.AutoConfigUrl   = AutoConfigUrl;
            autoProxyOptions.AutoDetectFlags = AutoDetect ?
                                               (Interop.WinHttp.WINHTTP_AUTO_DETECT_TYPE_DHCP | Interop.WinHttp.WINHTTP_AUTO_DETECT_TYPE_DNS_A) : 0;
            autoProxyOptions.AutoLoginIfChallenged = false;
            autoProxyOptions.Flags =
                (AutoDetect ? Interop.WinHttp.WINHTTP_AUTOPROXY_AUTO_DETECT : 0) |
                (!string.IsNullOrEmpty(AutoConfigUrl) ? Interop.WinHttp.WINHTTP_AUTOPROXY_CONFIG_URL : 0);
            autoProxyOptions.Reserved1 = IntPtr.Zero;
            autoProxyOptions.Reserved2 = 0;

            // AutoProxy Cache.
            // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383153(v=vs.85).aspx
            // If the out-of-process service is active when WinHttpGetProxyForUrl is called, the cached autoproxy
            // URL and script are available to the whole computer. However, if the out-of-process service is used,
            // and the fAutoLogonIfChallenged flag in the pAutoProxyOptions structure is true, then the autoproxy
            // URL and script are not cached. Therefore, calling WinHttpGetProxyForUrl with the fAutoLogonIfChallenged
            // member set to TRUE results in additional overhead operations that may affect performance.
            // The following steps can be used to improve performance:
            // 1. Call WinHttpGetProxyForUrl with the fAutoLogonIfChallenged parameter set to false. The autoproxy
            //    URL and script are cached for future calls to WinHttpGetProxyForUrl.
            // 2. If Step 1 fails, with ERROR_WINHTTP_LOGIN_FAILURE, then call WinHttpGetProxyForUrl with the
            //    fAutoLogonIfChallenged member set to TRUE.
            //
            // We match behavior of WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY and ignore errors.
            var repeat = false;

            do
            {
                _autoDetectionFailed = false;
                if (Interop.WinHttp.WinHttpGetProxyForUrl(
                        sessionHandle,
                        uri.AbsoluteUri,
                        ref autoProxyOptions,
                        out proxyInfo))
                {
                    WinHttpTraceHelper.Trace("WinInetProxyHelper.GetProxyForUrl: Using autoconfig proxy settings");
                    useProxy = true;

                    break;
                }
                else
                {
                    var lastError = Marshal.GetLastWin32Error();
                    WinHttpTraceHelper.Trace("WinInetProxyHelper.GetProxyForUrl: error={0}", lastError);

                    if (lastError == Interop.WinHttp.ERROR_WINHTTP_LOGIN_FAILURE)
                    {
                        if (repeat)
                        {
                            // We don't retry more than once.
                            break;
                        }
                        else
                        {
                            repeat = true;
                            autoProxyOptions.AutoLoginIfChallenged = true;
                        }
                    }
                    else
                    {
                        if (lastError == Interop.WinHttp.ERROR_WINHTTP_AUTODETECTION_FAILED)
                        {
                            _autoDetectionFailed         = true;
                            _lastTimeAutoDetectionFailed = Environment.TickCount;
                        }

                        break;
                    }
                }
            } while (repeat);

            // Fall back to manual settings if available.
            if (!useProxy && !string.IsNullOrEmpty(Proxy))
            {
                proxyInfo.AccessType  = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                proxyInfo.Proxy       = Marshal.StringToHGlobalUni(Proxy);
                proxyInfo.ProxyBypass = string.IsNullOrEmpty(ProxyBypass) ?
                                        IntPtr.Zero : Marshal.StringToHGlobalUni(ProxyBypass);

                WinHttpTraceHelper.Trace(
                    "WinInetProxyHelper.GetProxyForUrl: Fallback to Proxy={0}, ProxyBypass={1}",
                    Proxy,
                    ProxyBypass);
                useProxy = true;
            }

            WinHttpTraceHelper.Trace("WinInetProxyHelper.GetProxyForUrl: useProxy={0}", useProxy);

            return(useProxy);
        }