Fix RDP host resolution failure on Windows: initialize Winsock

Every RDP connect attempt on Windows failed instantly with
ERRCONNECT_DNS_NAME_NOT_FOUND, even for a literal IP address. Root cause:
Winsock requires WSAStartup() to be called once by the process before any
socket/getaddrinfo call will succeed, and nothing in OrbitHub was calling
it (Qt Network isn't used, so Qt never does it either). FreeRDP's own
reference Windows client (wf_client.c) pairs WSAStartup with
freerdp_handle_signals() in its startup init for exactly this reason.
WinPR provides a portable no-op WSAStartup shim on POSIX, so this can be
called unconditionally cross-platform alongside the existing signal-handler
fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 09:37:02 -06:00
co-authored by Claude Sonnet 5
parent 317df68d1f
commit b28adf8cbe
+28 -11
View File
@@ -33,6 +33,7 @@
#include <freerdp/scancode.h> #include <freerdp/scancode.h>
#include <freerdp/settings.h> #include <freerdp/settings.h>
#include <freerdp/utils/signal.h> #include <freerdp/utils/signal.h>
#include <winpr/winsock.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/synch.h> #include <winpr/synch.h>
#include <winpr/user.h> #include <winpr/user.h>
@@ -41,19 +42,35 @@
namespace { namespace {
#ifdef ORBITHUB_HAS_FREERDP #ifdef ORBITHUB_HAS_FREERDP
// Every reference FreeRDP client (X11, Windows, macOS, SDL, Wayland, // Mirrors wfreerdp_client_global_init() in FreeRDP's own reference Windows
// Android) calls this once at startup before connecting. On Windows it's // client (client/Windows/wf_client.c): every reference client calls
// the only place that initializes a global CRITICAL_SECTION used by // WSAStartup + freerdp_handle_signals once at startup before connecting.
// freerdp_add_signal_cleanup_handler(); skipping it leaves that lock //
// zero-initialized (invalid on Windows, tolerated on POSIX), so the first // WSAStartup: on Windows, sockets (getaddrinfo et al.) fail immediately
// freerdp_connect() crashes with a null-pointer dereference inside // with WSANOTINITIALISED until this has been called by *someone* in the
// EnterCriticalSection. Guarded so it only ever runs once. // process; OrbitHub never used Qt Network, so nothing else on Windows was
void ensureFreeRdpSignalHandlersInitialized() // calling it, and every connect failed instantly with
// ERRCONNECT_DNS_NAME_NOT_FOUND even for a literal IP address. WinPR
// provides a portable no-op WSAStartup shim on POSIX, so this is safe to
// call unconditionally cross-platform.
//
// freerdp_handle_signals: on Windows it's the only place that initializes
// a global CRITICAL_SECTION used by freerdp_add_signal_cleanup_handler();
// skipping it leaves that lock zero-initialized (invalid on Windows,
// tolerated on POSIX), so the first freerdp_connect() crashed with a
// null-pointer dereference inside EnterCriticalSection.
//
// Guarded so it only ever runs once.
void ensureFreeRdpRuntimeInitialized()
{ {
static std::once_flag onceFlag; static std::once_flag onceFlag;
std::call_once(onceFlag, []() { std::call_once(onceFlag, []() {
const int rc = freerdp_handle_signals(); WSADATA wsaData;
Q_UNUSED(rc); const int wsaRc = WSAStartup(0x101, &wsaData);
Q_UNUSED(wsaRc);
const int signalRc = freerdp_handle_signals();
Q_UNUSED(signalRc);
}); });
} }
#endif #endif
@@ -1493,7 +1510,7 @@ void RdpSessionBackend::workerMain()
m_workerRunning.store(false); m_workerRunning.store(false);
return; return;
#else #else
ensureFreeRdpSignalHandlersInitialized(); ensureFreeRdpRuntimeInitialized();
freerdp* instance = freerdp_new(); freerdp* instance = freerdp_new();
if (instance == nullptr) { if (instance == nullptr) {