winrt: Use winsock2 API for hostname resolution on WinRT/WinPhone

That API has been available for WinRT and Windows
Phone for some time now. By using it to get the
machine name and for hostname resolution we can get
rid of some winrt-only code and use qhostinfo_win.cpp
on WinRT and Windows phone as well.

Additionally the required capability was added to
tst_qhostinfo so that this auto test can be run without
any manual editing.

Change-Id: I63fa5521bf8cdb0c919bd5a0100ea977c865622a
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
This commit is contained in:
Oliver Wolff 2015-12-16 15:33:42 +01:00
parent 2ca20724dd
commit 190c76f685
8 changed files with 17 additions and 223 deletions

View File

@ -78,9 +78,9 @@ QMAKE_PREFIX_STATICLIB =
QMAKE_EXTENSION_STATICLIB = lib
QMAKE_LIBS += runtimeobject.lib
QMAKE_LIBS_CORE =
QMAKE_LIBS_CORE += ws2_32.lib
QMAKE_LIBS_GUI =
QMAKE_LIBS_NETWORK =
QMAKE_LIBS_NETWORK += ws2_32.lib
QMAKE_LIBS_OPENGL_ES2 = $${LIBEGL_NAME}.lib $${LIBGLESV2_NAME}.lib
QMAKE_LIBS_OPENGL_ES2_DEBUG = $${LIBEGL_NAME}d.lib $${LIBGLESV2_NAME}d.lib

View File

@ -130,14 +130,4 @@
typedef int mode_t;
#ifndef INADDR_ANY
# define INADDR_ANY (u_long)0x00000000
#endif
#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBACK 0x7f000001
#endif
#ifndef INADDR_BROADCAST
# define INADDR_BROADCAST (u_long)0xffffffff
#endif
#endif // QPLATFORMDEFS_H

View File

@ -66,18 +66,8 @@
#endif
#ifdef Q_OS_WINRT
#include <wrl.h>
#include <windows.networking.h>
#include <windows.networking.sockets.h>
#include <windows.networking.connectivity.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::Networking;
using namespace ABI::Windows::Networking::Connectivity;
using namespace ABI::Windows::Networking::Sockets;
#endif
#include <Ws2tcpip.h>
#endif // Q_OS_WINRT
#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL)
# include <envLib.h>
@ -1880,8 +1870,6 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qt_windows.h"
QT_END_INCLUDE_NAMESPACE
#ifndef Q_OS_WINRT
# ifndef QT_BOOTSTRAPPED
class QWindowsSockInit
{
@ -1912,8 +1900,6 @@ QWindowsSockInit::~QWindowsSockInit()
Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
# endif // QT_BOOTSTRAPPED
#endif // !Q_OS_WINRT
#ifdef Q_OS_WINRT
static inline HMODULE moduleHandleForFunction(LPCVOID address)
{
@ -2797,42 +2783,6 @@ QString QSysInfo::machineHostName()
struct utsname u;
if (uname(&u) == 0)
return QString::fromLocal8Bit(u.nodename);
#elif defined(Q_OS_WINRT)
ComPtr<INetworkInformationStatics> statics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
ComPtr<IVectorView<HostName *>> hostNames;
statics->GetHostNames(&hostNames);
if (!hostNames)
return QString();
unsigned int size;
hostNames->get_Size(&size);
if (size == 0)
return QString();
for (unsigned int i = 0; i < size; ++i) {
ComPtr<IHostName> hostName;
hostNames->GetAt(i, &hostName);
HostNameType type;
hostName->get_Type(&type);
if (type != HostNameType_DomainName)
continue;
HString name;
hostName->get_CanonicalName(name.GetAddressOf());
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
return QString::fromWCharArray(rawString, length);
}
ComPtr<IHostName> firstHost;
hostNames->GetAt(0, &firstHost);
HString name;
firstHost->get_CanonicalName(name.GetAddressOf());
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
return QString::fromWCharArray(rawString, length);
#else
# ifdef Q_OS_WIN
// Important: QtNetwork depends on machineHostName() initializing ws2_32.dll

View File

@ -611,7 +611,6 @@ class QDataStream;
#if defined(Q_OS_WINRT)
# define QT_NO_FILESYSTEMWATCHER
# define QT_NO_GETADDRINFO
# define QT_NO_NETWORKPROXY
# define QT_NO_PROCESS
# define QT_NO_SOCKETNOTIFIER

View File

@ -33,16 +33,16 @@ android {
}
win32: {
SOURCES += kernel/qhostinfo_win.cpp
!winrt {
SOURCES += kernel/qdnslookup_win.cpp \
kernel/qhostinfo_win.cpp \
kernel/qnetworkinterface_win.cpp
LIBS_PRIVATE += -ldnsapi -liphlpapi
DEFINES += WINVER=0x0600 _WIN32_WINNT=0x0600
} else {
SOURCES += kernel/qdnslookup_winrt.cpp \
kernel/qhostinfo_winrt.cpp \
kernel/qnetworkinterface_winrt.cpp
}
}

View File

@ -34,7 +34,6 @@
#include <winsock2.h>
#include "qhostinfo_p.h"
#include "private/qnativesocketengine_p.h"
#include <ws2tcpip.h>
#include <private/qsystemlibrary_p.h>
#include <qmutex.h>
@ -77,14 +76,18 @@ static void resolveLibrary()
{
// Attempt to resolve getaddrinfo(); without it we'll have to fall
// back to gethostbyname(), which has no IPv6 support.
#if !defined(Q_OS_WINCE)
local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getaddrinfo");
local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo");
local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo");
#else
#if defined(Q_OS_WINCE)
local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getaddrinfo");
local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "freeaddrinfo");
local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getnameinfo");
#elif defined (Q_OS_WINRT)
local_getaddrinfo = (getaddrinfoProto) &getaddrinfo;
local_freeaddrinfo = (freeaddrinfoProto) &freeaddrinfo;
local_getnameinfo = (getnameinfoProto) getnameinfo;
#else
local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getaddrinfo");
local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo");
local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo");
#endif
}

View File

@ -1,150 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qhostinfo_p.h"
#include <qfunctions_winrt.h>
#include <qurl.h>
#include <wrl.h>
#include <windows.networking.h>
#include <windows.networking.sockets.h>
#include <windows.networking.connectivity.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::Networking;
using namespace ABI::Windows::Networking::Connectivity;
using namespace ABI::Windows::Networking::Sockets;
QT_BEGIN_NAMESPACE
#define E_NO_SUCH_HOST 0x80072af9
//#define QHOSTINFO_DEBUG
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
QHostInfo results;
QHostAddress address;
if (address.setAddress(hostName)) {
// Reverse lookup
// TODO: is there a replacement for getnameinfo for winrt?
Q_UNIMPLEMENTED();
return results;
}
QByteArray aceHostname = QUrl::toAce(hostName);
results.setHostName(hostName);
if (aceHostname.isEmpty()) {
results.setError(QHostInfo::HostNotFound);
results.setErrorString(hostName.isEmpty() ? tr("No host name given") : tr("Invalid hostname"));
return results;
}
ComPtr<IHostNameFactory> hostnameFactory;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
IID_PPV_ARGS(&hostnameFactory));
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IHostName> host;
HStringReference hostNameRef((const wchar_t*)hostName.utf16());
hr = hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IDatagramSocketStatics> datagramSocketStatics;
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IAsyncOperation<IVectorView<EndpointPair *> *>> op;
hr = datagramSocketStatics->GetEndpointPairsAsync(host.Get(),
HString::MakeReference(L"0").Get(),
&op);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IVectorView<EndpointPair *>> endpointPairs;
hr = op->GetResults(&endpointPairs);
int waitCount = 0;
while (hr == E_ILLEGAL_METHOD_CALL) {
WaitForSingleObjectEx(GetCurrentThread(), 50, FALSE);
hr = op->GetResults(&endpointPairs);
if (++waitCount > 1200) // Wait for 1 minute max
return results;
}
if (hr == E_NO_SUCH_HOST || !endpointPairs) {
results.setError(QHostInfo::HostNotFound);
results.setErrorString(tr("Host %1 could not be found.").arg(hostName));
return results;
}
Q_ASSERT_SUCCEEDED(hr);
unsigned int size;
hr = endpointPairs->get_Size(&size);
Q_ASSERT_SUCCEEDED(hr);
QList<QHostAddress> addresses;
for (unsigned int i = 0; i < size; ++i) {
ComPtr<IEndpointPair> endpointpair;
hr = endpointPairs->GetAt(i, &endpointpair);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IHostName> remoteHost;
hr = endpointpair->get_RemoteHostName(&remoteHost);
Q_ASSERT_SUCCEEDED(hr);
if (!remoteHost)
continue;
HostNameType type;
hr = remoteHost->get_Type(&type);
Q_ASSERT_SUCCEEDED(hr);
if (type == HostNameType_DomainName)
continue;
HString name;
hr = remoteHost->get_CanonicalName(name.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
UINT32 length;
PCWSTR rawString = name.GetRawBuffer(&length);
QHostAddress addr;
addr.setAddress(QString::fromWCharArray(rawString, length));
if (!addresses.contains(addr))
addresses.append(addr);
}
results.setAddresses(addresses);
return results;
}
// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp
QT_END_NAMESPACE

View File

@ -14,3 +14,5 @@ wince {
# needed for getaddrinfo with official MinGW
mingw:DEFINES += _WIN32_WINNT=0x0501
winrt: WINRT_MANIFEST.capabilities += internetClientServer