diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c642e22..1eda15f72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Update Xbox toolchain to include `UseDebugLibraries` fix for Debug builds. ([#1302](https://github.com/getsentry/sentry-native/pull/1302)) - Fix GDK version selection for Xbox by propagating `XdkEditionTarget` to MSBuild. ([#1312](https://github.com/getsentry/sentry-native/pull/1312)) +- Fix WinHTTP initialization timing to prevent error 12007 on Xbox platform. ([#1321](https://github.com/getsentry/sentry-native/pull/1321)) **Meta**: diff --git a/CMakeLists.txt b/CMakeLists.txt index 98f30edff..fd6d56afd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,7 +489,7 @@ elseif(LINUX) set(_SENTRY_PLATFORM_LIBS "dl" "rt") elseif(WIN32) if (XBOX) - set(_SENTRY_PLATFORM_LIBS "version") + set(_SENTRY_PLATFORM_LIBS "version" "xgameruntime") else() set(_SENTRY_PLATFORM_LIBS "dbghelp" "shlwapi" "version") endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a34a54004..46742197c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -112,6 +112,11 @@ elseif(SENTRY_TRANSPORT_WINHTTP) sentry_target_sources_cwd(sentry transports/sentry_transport_winhttp.c ) + if (XBOX) + sentry_target_sources_cwd(sentry + transports/sentry_transport_xnetworking.cpp + ) + endif() elseif(SENTRY_TRANSPORT_NONE) sentry_target_sources_cwd(sentry transports/sentry_transport_none.c diff --git a/src/transports/sentry_transport_winhttp.c b/src/transports/sentry_transport_winhttp.c index d9c7b60b1..659c182b8 100644 --- a/src/transports/sentry_transport_winhttp.c +++ b/src/transports/sentry_transport_winhttp.c @@ -13,6 +13,10 @@ #include #include +#ifdef SENTRY_PLATFORM_XBOX +HRESULT sentry__transport_ensure_network_initialized(); +#endif // SENTRY_PLATFORM_XBOX + typedef struct { sentry_dsn_t *dsn; wchar_t *user_agent; @@ -40,6 +44,31 @@ sentry__winhttp_bgworker_state_new(void) return state; } +static void +sentry__winhttp_session_start(void *_state) +{ + winhttp_bgworker_state_t *state = _state; + if (state->proxy) { + state->session + = WinHttpOpen(state->user_agent, WINHTTP_ACCESS_TYPE_NAMED_PROXY, + state->proxy, WINHTTP_NO_PROXY_BYPASS, 0); + } else { +#if _WIN32_WINNT >= 0x0603 + state->session = WinHttpOpen(state->user_agent, + WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, 0); +#endif + // On windows 8.0 or lower, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY does + // not work on error we fallback to + // WINHTTP_ACCESS_TYPE_DEFAULT_PROXY + if (!state->session) { + state->session = WinHttpOpen(state->user_agent, + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, 0); + } + } +} + static void sentry__winhttp_bgworker_state_free(void *_state) { @@ -118,28 +147,14 @@ sentry__winhttp_transport_start( } } - if (state->proxy) { - state->session - = WinHttpOpen(state->user_agent, WINHTTP_ACCESS_TYPE_NAMED_PROXY, - state->proxy, WINHTTP_NO_PROXY_BYPASS, 0); - } else { -#if _WIN32_WINNT >= 0x0603 - state->session = WinHttpOpen(state->user_agent, - WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY, WINHTTP_NO_PROXY_NAME, - WINHTTP_NO_PROXY_BYPASS, 0); -#endif - // On windows 8.0 or lower, WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY does - // not work on error we fallback to WINHTTP_ACCESS_TYPE_DEFAULT_PROXY - if (!state->session) { - state->session = WinHttpOpen(state->user_agent, - WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, - WINHTTP_NO_PROXY_BYPASS, 0); - } - } +#ifndef SENTRY_PLATFORM_XBOX + sentry__winhttp_session_start(state); + if (!state->session) { SENTRY_WARN("`WinHttpOpen` failed"); return 1; } +#endif // !SENTRY_PLATFORM_XBOX return sentry__bgworker_start(bgworker); } @@ -187,6 +202,20 @@ sentry__winhttp_send_task(void *_envelope, void *_state) sentry_envelope_t *envelope = (sentry_envelope_t *)_envelope; winhttp_bgworker_state_t *state = (winhttp_bgworker_state_t *)_state; +#ifdef SENTRY_PLATFORM_XBOX + if (!state->session) { + SENTRY_DEBUG( + "ensuring xbox network is initialized for WinHttp transport"); + sentry__transport_ensure_network_initialized(); + sentry__winhttp_session_start(state); + + if (!state->session) { + SENTRY_WARN("`WinHttpOpen` failed"); + return; + } + } +#endif // SENTRY_PLATFORM_XBOX + uint64_t started = sentry__monotonic_time(); char *user_agent = sentry__string_from_wstr(state->user_agent); diff --git a/src/transports/sentry_transport_xnetworking.cpp b/src/transports/sentry_transport_xnetworking.cpp new file mode 100644 index 000000000..4af10ecd8 --- /dev/null +++ b/src/transports/sentry_transport_xnetworking.cpp @@ -0,0 +1,64 @@ +#include "sentry_boot.h" + +#include + +static void +sentry__transport_network_connectivity_hint_changed_callback(_In_ void *context, + _In_ const XNetworkingConnectivityHint *connectivity_hint) +{ + HANDLE network_initialized_event = static_cast(context); + if (connectivity_hint->networkInitialized) { + (void)SetEvent(network_initialized_event); + } +} + +extern "C" { + +HRESULT +sentry__transport_ensure_network_initialized() +{ + HRESULT hr = S_OK; + XNetworkingConnectivityHint connectivity_hint; + XTaskQueueHandle queue; + + hr = XTaskQueueCreate(XTaskQueueDispatchMode::Immediate, + XTaskQueueDispatchMode::Immediate, &queue); + if (SUCCEEDED(hr)) { + // Use the new XNetworking APIs to check if the network is initialized. + hr = XNetworkingGetConnectivityHint(&connectivity_hint); + if (SUCCEEDED(hr)) { + if (!connectivity_hint.networkInitialized) { + // The network isn't initialized. Wait until the network becomes + // initialized. + HANDLE network_initialized_event + = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (network_initialized_event != nullptr) { + XTaskQueueRegistrationToken token; + hr = XNetworkingRegisterConnectivityHintChanged(queue, + network_initialized_event, + sentry__transport_network_connectivity_hint_changed_callback, + &token); + if (SUCCEEDED(hr)) { + DWORD result = WaitForSingleObjectEx( + network_initialized_event, INFINITE, FALSE); + if (result != WAIT_OBJECT_0) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + XNetworkingUnregisterConnectivityHintChanged( + token, true); + } + + CloseHandle(network_initialized_event); + } else { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + } + + XTaskQueueCloseHandle(queue); + } + + return hr; +} +}