From 1655cb5a690895631238b5b7a9a1f0c8ad32fbc4 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 19 Jun 2012 17:38:40 +0100 Subject: Fix non inheritable socket creation on old windows versions The documentation is misleading, as using the new API actually causes WSASocket to fail. New behaviour: On windows vista or earlier: skip the new API, use old one On windows 7: try the new API first, if it fails try the old one On windows 8: try the new API only The windows 7 behaviour is because we don't know if the service pack has been installed or not. (And IT departments may have specifically installed/blocked the hotfix) Task-number: QTBUG-26224 Change-Id: I6da47959919caee0cd2697f1ae1fca46aa33c1ff Reviewed-by: Thiago Macieira Reviewed-by: Mikhail Vorozhtsov --- src/network/socket/qnativesocketengine_win.cpp | 37 +++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'src/network/socket/qnativesocketengine_win.cpp') diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 60c4c73950..8b354a8c50 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -307,10 +307,11 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return -1; } */ + QSysInfo::WinVersion osver = QSysInfo::windowsVersion(); //Windows XP and 2003 support IPv6 but not dual stack sockets int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol - || (socketProtocol == QAbstractSocket::AnyIPProtocol && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0)) ? AF_INET6 : AF_INET; + || (socketProtocol == QAbstractSocket::AnyIPProtocol && osver >= QSysInfo::WV_6_0)) ? AF_INET6 : AF_INET; int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM; // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking @@ -318,12 +319,29 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc // WSA_FLAG_NO_HANDLE_INHERIT is atomic (like linux O_CLOEXEC), but requires windows 7 SP 1 or later // SetHandleInformation is supported since W2K but isn't atomic - // According to the MS docs, we can use the new flag and call GetHandleInformation to see if it was successful #ifndef WSA_FLAG_NO_HANDLE_INHERIT #define WSA_FLAG_NO_HANDLE_INHERIT 0x80 #endif - SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); + SOCKET socket = INVALID_SOCKET; + // Windows 7 or later, try the new API + if (osver >= QSysInfo::WV_6_1) + socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); + // previous call fails if the windows 7 service pack 1 or hot fix isn't installed. + + // Try the old API if the new one failed on Windows 7, or always on earlier versions + if (socket == INVALID_SOCKET && osver <= QSysInfo::WV_6_1) { + socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED); +#ifdef HANDLE_FLAG_INHERIT + if (socket != INVALID_SOCKET) { + // make non inheritable the old way + BOOL handleFlags = SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0); +#ifdef QNATIVESOCKETENGINE_DEBUG + qDebug() << "QNativeSocketEnginePrivate::createNewSocket - set inheritable" << handleFlags; +#endif + } +#endif + } if (socket == INVALID_SOCKET) { int err = WSAGetLastError(); @@ -349,19 +367,6 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc return false; } -#ifdef HANDLE_FLAG_INHERIT - // check if the WSASocket was successful or not at creating a non inheritable socket - DWORD handleFlags = 0xFF; - if (GetHandleInformation((HANDLE)socket, &handleFlags) && (handleFlags & HANDLE_FLAG_INHERIT)) { - // make non inheritable the old way - if (SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) - handleFlags = 0; - } -#ifdef QNATIVESOCKETENGINE_DEBUG - qDebug() << "QNativeSocketEnginePrivate::createNewSocket - set inheritable" << handleFlags; -#endif -#endif - #if !defined(Q_OS_WINCE) if (socketType == QAbstractSocket::UdpSocket) { // enable new behavior using -- cgit v1.2.3