private void EnsureSessionHandleExists(WinHttpRequestState state)
{
if (_sessionHandle == null)
{
lock (_lockObject)
{
if (_sessionHandle == null)
{
SafeWinHttpHandle sessionHandle;
uint accessType;
// If a custom proxy is specified and it is really the system web proxy
// (initial WebRequest.DefaultWebProxy) then we need to update the settings
// since that object is only a sentinel.
if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy)
{
Debug.Assert(state.Proxy != null);
try
{
state.Proxy.GetProxy(state.RequestMessage.RequestUri);
}
catch (PlatformNotSupportedException)
{
// This is the system web proxy.
state.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy;
state.Proxy = null;
}
}
if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.DoNotUseProxy ||
state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy)
{
// Either no proxy at all or a custom IWebProxy proxy is specified.
// For a custom IWebProxy, we'll need to calculate and set the proxy
// on a per request handle basis using the request Uri. For now,
// we set the session handle to have no proxy.
accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY;
}
else if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinHttpProxy)
{
// Use WinHTTP per-machine proxy settings which are set using the "netsh winhttp" command.
accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
}
else
{
// Use WinInet per-user proxy settings.
accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY;
}
WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: proxy accessType={0}", accessType);
sessionHandle = Interop.WinHttp.WinHttpOpen(
IntPtr.Zero,
accessType,
Interop.WinHttp.WINHTTP_NO_PROXY_NAME,
Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS,
(int)Interop.WinHttp.WINHTTP_FLAG_ASYNC);
if (sessionHandle.IsInvalid)
{
int lastError = Marshal.GetLastWin32Error();
WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: error={0}", lastError);
if (lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER)
{
ThrowOnInvalidHandle(sessionHandle);
}
// We must be running on a platform earlier than Win8.1/Win2K12R2 which doesn't support
// WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY. So, we'll need to read the Wininet style proxy
// settings ourself using our WinInetProxyHelper object.
_proxyHelper = new WinInetProxyHelper();
sessionHandle = Interop.WinHttp.WinHttpOpen(
IntPtr.Zero,
_proxyHelper.ManualSettingsOnly ? Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY : Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY,
_proxyHelper.ManualSettingsOnly ? _proxyHelper.Proxy : Interop.WinHttp.WINHTTP_NO_PROXY_NAME,
_proxyHelper.ManualSettingsOnly ? _proxyHelper.ProxyBypass : Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS,
(int)Interop.WinHttp.WINHTTP_FLAG_ASYNC);
ThrowOnInvalidHandle(sessionHandle);
}
uint optionAssuredNonBlockingTrue = 1; // TRUE
if (!Interop.WinHttp.WinHttpSetOption(
sessionHandle,
Interop.WinHttp.WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS,
ref optionAssuredNonBlockingTrue,
(uint)Marshal.SizeOf<uint>()))
{
// This option is not available on downlevel Windows versions. While it improves
// performance, we can ignore the error that the option is not available.
int lastError = Marshal.GetLastWin32Error();
if (lastError != Interop.WinHttp.ERROR_WINHTTP_INVALID_OPTION)
{
throw WinHttpException.CreateExceptionUsingError(lastError);
}
}
SetSessionHandleOptions(sessionHandle);
_sessionHandle = sessionHandle;
}
}
}
}