public static bool TryCreate(out IWebProxy proxy) { // This will get basic proxy setting from system using existing // WinInetProxyHelper functions. If no proxy is enabled, it will return null. SafeWinHttpHandle sessionHandle = null; proxy = null; WinInetProxyHelper proxyHelper = new WinInetProxyHelper(); if (!proxyHelper.ManualSettingsOnly && !proxyHelper.AutoSettingsUsed) { return(false); } if (proxyHelper.AutoSettingsUsed) { sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, Interop.WinHttp.WINHTTP_NO_PROXY_NAME, Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); if (sessionHandle.IsInvalid) { // Proxy failures are currently ignored by managed handler. return(false); } } proxy = new HttpWindowsProxy(proxyHelper, sessionHandle); return(true); }
public void Dispose() { if (!_disposed) { _disposed = true; if (_sessionHandle != null && !_sessionHandle.IsInvalid) { SafeWinHttpHandle.DisposeAndClearHandle(ref _sessionHandle); } } }
private HttpWindowsProxy(WinInetProxyHelper proxyHelper, SafeWinHttpHandle sessionHandle) { _proxyHelper = proxyHelper; _sessionHandle = sessionHandle; if (proxyHelper.ManualSettingsUsed) { ParseProxyConfig(proxyHelper.Proxy, out _insecureProxyUri, out _secureProxyUri); if (_insecureProxyUri == null && _secureProxyUri == null) { // If advanced parsing by protocol fails, fall-back to simplified parsing. _insecureProxyUri = _secureProxyUri = GetUriFromString(proxyHelper.Proxy); } if (!string.IsNullOrWhiteSpace(proxyHelper.ProxyBypass)) { int idx = 0; int start = 0; string tmp; // Process bypass list for manual setting. // Initial list size is best guess based on string length assuming each entry is at least 5 characters on average. _bypass = new List <Regex>(proxyHelper.ProxyBypass.Length / 5); while (idx < proxyHelper.ProxyBypass.Length) { // Strip leading spaces and scheme if any. while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == ' ') { idx += 1; } ; if (string.Compare(proxyHelper.ProxyBypass, idx, "http://", 0, 7, StringComparison.OrdinalIgnoreCase) == 0) { idx += 7; } else if (string.Compare(proxyHelper.ProxyBypass, idx, "https://", 0, 8, StringComparison.OrdinalIgnoreCase) == 0) { idx += 8; } if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == '[') { // Strip [] from IPv6 so we can use IdnHost laster for matching. idx += 1; } start = idx; while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ' ' && proxyHelper.ProxyBypass[idx] != ';' && proxyHelper.ProxyBypass[idx] != ']') { idx += 1; } ; if (idx == start) { // Empty string. tmp = null; } else if (string.Compare(proxyHelper.ProxyBypass, start, "<local>", 0, 7, StringComparison.OrdinalIgnoreCase) == 0) { _bypassLocal = true; tmp = null; } else { tmp = proxyHelper.ProxyBypass.Substring(start, idx - start); } // Skip trailing characters if any. if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ';') { // Got stopped at space or ']'. Strip until next ';' or end. while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ';') { idx += 1; } ; } if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == ';') { idx++; } if (tmp == null) { continue; } try { // Escape any special characters and unescape * to get wildcard pattern match. Regex re = new Regex(Regex.Escape(tmp).Replace("\\*", ".*?") + "$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); _bypass.Add(re); } catch (Exception ex) { } } if (_bypass.Count == 0) { // Bypass string only had garbage we did not parse. _bypass = null; } } if (_bypassLocal) { _localIp = new List <IPAddress>(); foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) { IPInterfaceProperties ipProps = netInterface.GetIPProperties(); foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) { _localIp.Add(addr.Address); } } } } }
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. var repeat = false; do { _autoDetectionFailed = false; if (Interop.WinHttp.WinHttpGetProxyForUrl( sessionHandle, uri.AbsoluteUri, ref autoProxyOptions, out proxyInfo)) { useProxy = true; break; } else { var lastError = Marshal.GetLastWin32Error(); 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); useProxy = true; } return(useProxy); }