diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 3a4ef4b400..b926583c46 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -342,19 +342,21 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QNativeSocketEngine); HRESULT hr; - hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() { - HRESULT hr; + // runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result. + // hr is set inside the lambda though. If an error occurred hr will point that out. + bool specificErrorSet = false; + QEventDispatcherWinRT::runOnXamlThread([address, d, &hr, port, &specificErrorSet, this]() { ComPtr hostAddress; if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { ComPtr hostNameFactory; hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), &hostNameFactory); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); const QString addressString = address.toString(); HStringReference addressRef(reinterpret_cast(addressString.utf16())); hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); } QString portQString = port ? QString::number(port) : QString(); @@ -365,13 +367,13 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) if (!d->tcpListener) { hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), &d->tcpListener); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); } hr = d->tcpListener->add_ConnectionReceived( Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); } else if (d->socketType == QAbstractSocket::UdpSocket) { hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); @@ -379,15 +381,40 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) if (hr == E_ACCESSDENIED) { qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", qPrintable(address.toString()), port, socketDescription(this).constData()); - return hr; + d->setError(QAbstractSocket::SocketAccessError, + QNativeSocketEnginePrivate::AccessErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + specificErrorSet = true; + return S_OK; } - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); hr = QWinRTFunctions::await(op); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); + if (hr == 0x80072741) { // The requested address is not valid in its context + d->setError(QAbstractSocket::SocketAddressNotAvailableError, + QNativeSocketEnginePrivate::AddressNotAvailableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + specificErrorSet = true; + return S_OK; + // Only one usage of each socket address (protocol/network address/port) is normally permitted + } else if (hr == 0x80072740) { + d->setError(QAbstractSocket::AddressInUseError, + QNativeSocketEnginePrivate::AddressInuseErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + specificErrorSet = true; + return S_OK; + } + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); return S_OK; }); - Q_ASSERT_SUCCEEDED(hr); + if (FAILED(hr)) { + if (!specificErrorSet) { + d->setError(QAbstractSocket::UnknownSocketError, + QNativeSocketEnginePrivate::UnknownSocketErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + } + return false; + } d->socketState = QAbstractSocket::BoundState; return d->fetchConnectionParameters();