277
278
// It is guaranteed that after closing the handles, a callback with status WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
279
// will be issued to indicate that the callback has been cleaned up.
280
- m_resolver.reset();
281
- m_session.reset();
280
+ {
281
+ const auto requestLock = m_requestLock.lock();
282
+ m_resolver.reset();
283
+ m_session.reset();
284
+ }
285
}
286
CATCH_LOG()
287
445
try
446
{
447
WI_ASSERT(m_callbackQueue.isRunningInQueue());
448
+ const auto requestLock = m_requestLock.lock();
449
+ if (m_stopping)
450
+ {
451
+ return;
452
+ }
453
+
454
if (m_queryState == QueryState::PendingAndQueueAdditional)
455
{
456
return;
478
wil::unique_winhttp_hinternet resolver{};
479
THROW_IF_WIN32_ERROR(WinHttpCreateProxyResolver(session.get(), &resolver));
480
481
+ executionStep = "WinHttpSetOption";
482
+ DWORD_PTR context = reinterpret_cast<DWORD_PTR>(this);
483
+ THROW_IF_WIN32_BOOL_FALSE(WinHttpSetOption(resolver.get(), WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context)));
484
+
485
executionStep = "WinHttpSetStatusCallback";
486
// We need to set flag WINHTTP_CALLBACK_FLAG_HANDLES in order to get the WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
487
// status callback when a handle is closed.
496
497
WINHTTP_PROXY_SETTINGS_PARAM ProxySettingsParam{0, nullptr, nullptr};
498
499
+ // Track the request before calling WinHttp because it can complete asynchronously before returning.
500
+ m_requestFinished.ResetEvent();
501
+ m_queryState = QueryState::Pending;
502
+
503
executionStep = "WinHttpGetProxySettingsEx";
504
// Query the proxy settings
488
- const DWORD dwError = s_WinHttpGetProxySettingsEx.value()(
489
- resolver.get(), WinHttpProxySettingsTypeWsl, &ProxySettingsParam, reinterpret_cast<DWORD_PTR>(this));
505
+ const DWORD dwError = s_WinHttpGetProxySettingsEx.value()(resolver.get(), WinHttpProxySettingsTypeWsl, &ProxySettingsParam, context);
506
507
if (dwError != ERROR_IO_PENDING && dwError != ERROR_SUCCESS)
508
{
512
// Transfer ownership of HTTP handles and track request
513
m_resolver = std::move(resolver);
514
m_session = std::move(session);
499
- m_requestFinished.ResetEvent();
500
- m_queryState = QueryState::Pending;
515
}
516
catch (...)
517
{
528
m_localizedProxyChangeString{wsl::shared::Localization::MessageHttpProxyChangeDetected()}
529
{
530
THROW_IF_WIN32_BOOL_FALSE(::DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenImpersonation, &m_userToken));
517
- m_callbackQueue.submit([this] { QueryProxySettingsAsync(); });
531
THROW_IF_WIN32_ERROR(s_WinHttpRegisterProxyChangeNotification.value()(WINHTTP_PROXY_NOTIFY_CHANGE, s_OnProxyChange, this, &m_proxyRegistrationHandle));
532
+ m_callbackQueue.submit([this] { QueryProxySettingsAsync(); });
533
}
534
535
HttpProxyStateTracker::~HttpProxyStateTracker()
543
}
544
CATCH_LOG()
545
}
532
- // It is guaranteed that after closing the handles, a callback with status WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
533
- // will be issued and it will be the last callback for this request, making it safe to delete the ProxyStateTracker.
534
- m_resolver.reset();
535
- m_session.reset();
546
+
547
+ {
548
+ const auto requestLock = m_requestLock.lock();
549
+ m_stopping = true;
550
+
551
+ // It is guaranteed that after closing the handles, a callback with status WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
552
+ // will be issued and it will be the last callback for this request, making it safe to delete the ProxyStateTracker.
553
+ m_resolver.reset();
554
+ m_session.reset();
555
+ }
556
557
// Wait for all requests to complete. At this point no new requests can be started since we unregistered for proxy change
558
// notifications. Without this we risk racing proxy callbacks and them calling into a cleaned up ProxyStateTracker.