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/settings.h>
#include <freerdp/utils/signal.h>
#include <winpr/winsock.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/user.h>
@@ -41,19 +42,35 @@
namespace {
#ifdef ORBITHUB_HAS_FREERDP
// Every reference FreeRDP client (X11, Windows, macOS, SDL, Wayland,
// Android) calls this once at startup before connecting. 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() crashes with a null-pointer dereference inside
// EnterCriticalSection. Guarded so it only ever runs once.
void ensureFreeRdpSignalHandlersInitialized()
// Mirrors wfreerdp_client_global_init() in FreeRDP's own reference Windows
// client (client/Windows/wf_client.c): every reference client calls
// WSAStartup + freerdp_handle_signals once at startup before connecting.
//
// WSAStartup: on Windows, sockets (getaddrinfo et al.) fail immediately
// with WSANOTINITIALISED until this has been called by *someone* in the
// process; OrbitHub never used Qt Network, so nothing else on Windows was
// 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;
std::call_once(onceFlag, []() {
const int rc = freerdp_handle_signals();
Q_UNUSED(rc);
WSADATA wsaData;
const int wsaRc = WSAStartup(0x101, &wsaData);
Q_UNUSED(wsaRc);
const int signalRc = freerdp_handle_signals();
Q_UNUSED(signalRc);
});
}
#endif
@@ -1493,7 +1510,7 @@ void RdpSessionBackend::workerMain()
m_workerRunning.store(false);
return;
#else
ensureFreeRdpSignalHandlersInitialized();
ensureFreeRdpRuntimeInitialized();
freerdp* instance = freerdp_new();
if (instance == nullptr) {