diff options
Diffstat (limited to 'src/network/kernel')
-rw-r--r-- | src/network/kernel/kernel.pri | 14 | ||||
-rw-r--r-- | src/network/kernel/qauthenticator.cpp | 21 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup.cpp | 19 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup.h | 6 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup_p.h | 1 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup_winrt.cpp | 144 | ||||
-rw-r--r-- | src/network/kernel/qhostaddress.cpp | 6 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo_winrt.cpp | 194 | ||||
-rw-r--r-- | src/network/kernel/qnetworkinterface_winrt.cpp | 198 |
9 files changed, 588 insertions, 15 deletions
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 97f52fdb6e..9b584be206 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -33,9 +33,17 @@ android { } win32: { - HEADERS += kernel/qnetworkinterface_win_p.h - SOURCES += kernel/qdnslookup_win.cpp kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp - LIBS_PRIVATE += -ldnsapi + !winrt { + HEADERS += kernel/qnetworkinterface_win_p.h + SOURCES += kernel/qdnslookup_win.cpp \ + kernel/qhostinfo_win.cpp \ + kernel/qnetworkinterface_win.cpp + LIBS_PRIVATE += -ldnsapi + } else { + SOURCES += kernel/qdnslookup_winrt.cpp \ + kernel/qhostinfo_winrt.cpp \ + kernel/qnetworkinterface_winrt.cpp + } } integrity:SOURCES += kernel/qdnslookup_unix.cpp kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 8c16486878..edbbbf5a75 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -55,9 +55,11 @@ #include <qmutex.h> #include <private/qmutexpool_p.h> #include <rpc.h> +#ifndef Q_OS_WINRT #define SECURITY_WIN32 1 #include <security.h> #endif +#endif //#define NTLMV1_CLIENT @@ -69,7 +71,7 @@ QT_BEGIN_NAMESPACE static QByteArray qNtlmPhase1(); static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data); -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) static QByteArray qNtlmPhase1_SSPI(QAuthenticatorPrivate *ctx); static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& phase2data); #endif @@ -328,7 +330,7 @@ bool QAuthenticator::isNull() const return !d; } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) class QNtlmWindowsHandles { public: @@ -340,7 +342,7 @@ public: QAuthenticatorPrivate::QAuthenticatorPrivate() : method(None) - #ifdef Q_OS_WIN + #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) , ntlmWindowsHandles(0) #endif , hasFailed(false) @@ -354,7 +356,7 @@ QAuthenticatorPrivate::QAuthenticatorPrivate() QAuthenticatorPrivate::~QAuthenticatorPrivate() { -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) if (ntlmWindowsHandles) delete ntlmWindowsHandles; #endif @@ -485,7 +487,7 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet case QAuthenticatorPrivate::Ntlm: methodString = "NTLM "; if (challenge.isEmpty()) { -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) QByteArray phase1Token; if (user.isEmpty()) // Only pull from system if no user was specified in authenticator phase1Token = qNtlmPhase1_SSPI(this); @@ -502,7 +504,7 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet phase = Phase2; } } else { -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) QByteArray phase3Token; if (ntlmWindowsHandles) phase3Token = qNtlmPhase3_SSPI(this, QByteArray::fromBase64(challenge)); @@ -1475,7 +1477,7 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas return rc; } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) // See http://davenport.sourceforge.net/ntlm.html // and libcurl http_ntlm.c @@ -1513,7 +1515,6 @@ static bool q_NTLM_SSPI_library_load() return true; } -#ifdef Q_OS_WIN // Phase 1: static QByteArray qNtlmPhase1_SSPI(QAuthenticatorPrivate *ctx) { @@ -1631,8 +1632,6 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& return result; } -#endif // Q_OS_WIN - -#endif +#endif // Q_OS_WIN && !Q_OS_WINRT QT_END_NAMESPACE diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index 53675d083b..e776a8eb76 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -363,6 +363,25 @@ void QDnsLookup::setType(Type type) } /*! + \property QDnsLookup::nameserver + \brief the nameserver to use for DNS lookup. +*/ + +QHostAddress QDnsLookup::nameserver() const +{ + return d_func()->nameserver; +} + +void QDnsLookup::setNameserver(const QHostAddress &nameserver) +{ + Q_D(QDnsLookup); + if (nameserver != d->nameserver) { + d->nameserver = nameserver; + emit nameserverChanged(nameserver); + } +} + +/*! Returns the list of canonical name records associated with this lookup. */ diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index 1df21d866e..ffbef61f92 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -180,6 +180,7 @@ class Q_NETWORK_EXPORT QDnsLookup : public QObject Q_PROPERTY(QString errorString READ errorString NOTIFY finished) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(Type type READ type WRITE setType NOTIFY typeChanged) + Q_PROPERTY(QHostAddress nameserver READ nameserver WRITE setNameserver NOTIFY nameserverChanged) public: enum Error @@ -209,6 +210,7 @@ public: explicit QDnsLookup(QObject *parent = 0); QDnsLookup(Type type, const QString &name, QObject *parent = 0); + QDnsLookup(Type type, const QString &name, const QHostAddress &nameserver, QObject *parent = 0); ~QDnsLookup(); Error error() const; @@ -221,6 +223,9 @@ public: Type type() const; void setType(QDnsLookup::Type); + QHostAddress nameserver() const; + void setNameserver(const QHostAddress &nameserver); + QList<QDnsDomainNameRecord> canonicalNameRecords() const; QList<QDnsHostAddressRecord> hostAddressRecords() const; QList<QDnsMailExchangeRecord> mailExchangeRecords() const; @@ -238,6 +243,7 @@ Q_SIGNALS: void finished(); void nameChanged(const QString &name); void typeChanged(Type type); + void nameserverChanged(const QHostAddress &nameserver); private: Q_DECLARE_PRIVATE(QDnsLookup) diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h index 692b9088fe..4bd3bd7603 100644 --- a/src/network/kernel/qdnslookup_p.h +++ b/src/network/kernel/qdnslookup_p.h @@ -100,6 +100,7 @@ public: bool isFinished; QString name; QDnsLookup::Type type; + QHostAddress nameserver; QDnsLookupReply reply; QDnsLookupRunnable *runnable; diff --git a/src/network/kernel/qdnslookup_winrt.cpp b/src/network/kernel/qdnslookup_winrt.cpp new file mode 100644 index 0000000000..a5d16e4b63 --- /dev/null +++ b/src/network/kernel/qdnslookup_winrt.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdnslookup_p.h" + +#include <qurl.h> + +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.foundation.collections.h> +#include <windows.networking.h> +#include <windows.networking.sockets.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 + +void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) +{ + // TODO: is there any way to do "proper" dns lookup? + if (requestType != QDnsLookup::A && requestType != QDnsLookup::AAAA + && requestType != QDnsLookup::ANY) { + reply->error = QDnsLookup::InvalidRequestError; + reply->errorString = QLatin1String("WinRT only supports IPv4 and IPv6 requests"); + return; + } + + QString aceHostname = QUrl::fromAce(requestName); + if (aceHostname.isEmpty()) { + reply->error = QDnsLookup::InvalidRequestError; + reply->errorString = requestName.isEmpty() ? tr("No hostname given") : tr("Invalid hostname"); + return; + } + + IHostNameFactory *hostnameFactory; + + HStringReference classId(RuntimeClass_Windows_Networking_HostName); + if (FAILED(GetActivationFactory(classId.Get(), &hostnameFactory))) { + reply->error = QDnsLookup::ResolverError; + reply->errorString = QLatin1String("Could not obtain hostname factory"); + return; + } + IHostName *host; + HStringReference hostNameRef((const wchar_t*)aceHostname.utf16()); + hostnameFactory->CreateHostName(hostNameRef.Get(), &host); + hostnameFactory->Release(); + + IDatagramSocketStatics *datagramSocketStatics; + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics); + + IAsyncOperation<IVectorView<EndpointPair*> *> *op; + HSTRING proto; + WindowsCreateString(L"0", 1, &proto); + datagramSocketStatics->GetEndpointPairsAsync(host, proto, &op); + datagramSocketStatics->Release(); + host->Release(); + + IVectorView<EndpointPair*> *endpointPairs = 0; + HRESULT 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; + } + op->Release(); + + if (!endpointPairs) + return; + + unsigned int size; + endpointPairs->get_Size(&size); + for (unsigned int i = 0; i < size; ++i) { + IEndpointPair *endpointpair; + endpointPairs->GetAt(i, &endpointpair); + IHostName *remoteHost; + endpointpair->get_RemoteHostName(&remoteHost); + endpointpair->Release(); + HostNameType type; + remoteHost->get_Type(&type); + if (type == HostNameType_Bluetooth || type == HostNameType_DomainName + || (requestType != QDnsLookup::ANY + && ((type == HostNameType_Ipv4 && requestType == QDnsLookup::AAAA) + || (type == HostNameType_Ipv6 && requestType == QDnsLookup::A)))) + continue; + + HSTRING name; + remoteHost->get_CanonicalName(&name); + remoteHost->Release(); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(name, &length); + QDnsHostAddressRecord record; + record.d->name = aceHostname; + record.d->value = QHostAddress(QString::fromWCharArray(rawString, length)); + reply->hostAddressRecords.append(record); + } +} + +QT_END_NAMESPACE diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 18fd6dee58..0ab72191dc 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE // sockaddr_in6 size changed between old and new SDK // Only the new version is the correct one, so always // use this structure. -#if defined(Q_OS_WINCE) +#if defined(Q_OS_WINCE) || defined(Q_OS_WINRT) # if !defined(u_char) # define u_char unsigned char # endif @@ -448,10 +448,12 @@ QHostAddress::QHostAddress(const QString &address) QHostAddress::QHostAddress(const struct sockaddr *sockaddr) : d(new QHostAddressPrivate) { +#ifndef Q_OS_WINRT if (sockaddr->sa_family == AF_INET) setAddress(htonl(((sockaddr_in *)sockaddr)->sin_addr.s_addr)); else if (sockaddr->sa_family == AF_INET6) setAddress(((qt_sockaddr_in6 *)sockaddr)->sin6_addr.qt_s6_addr); +#endif } /*! @@ -604,11 +606,13 @@ bool QHostAddress::setAddress(const QString &address) */ void QHostAddress::setAddress(const struct sockaddr *sockaddr) { +#ifndef Q_OS_WINRT clear(); if (sockaddr->sa_family == AF_INET) setAddress(htonl(((sockaddr_in *)sockaddr)->sin_addr.s_addr)); else if (sockaddr->sa_family == AF_INET6) setAddress(((qt_sockaddr_in6 *)sockaddr)->sin6_addr.qt_s6_addr); +#endif } /*! diff --git a/src/network/kernel/qhostinfo_winrt.cpp b/src/network/kernel/qhostinfo_winrt.cpp new file mode 100644 index 0000000000..928c9e4628 --- /dev/null +++ b/src/network/kernel/qhostinfo_winrt.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhostinfo_p.h" + +#include <qurl.h> + +#include <ppltasks.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 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; + } + + IHostNameFactory *hostnameFactory; + + HStringReference classId(RuntimeClass_Windows_Networking_HostName); + if (FAILED(GetActivationFactory(classId.Get(), &hostnameFactory))) + Q_ASSERT(false, "Could not obtain hostname factory."); + + IHostName *host; + HStringReference hostNameRef((const wchar_t*)hostName.utf16()); + hostnameFactory->CreateHostName(hostNameRef.Get(), &host); + hostnameFactory->Release(); + + IDatagramSocketStatics *datagramSocketStatics; + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics); + + IAsyncOperation<IVectorView<EndpointPair*> *> *op; + HSTRING proto; + WindowsCreateString(L"0", 1, &proto); + datagramSocketStatics->GetEndpointPairsAsync(host, proto, &op); + datagramSocketStatics->Release(); + host->Release(); + + IVectorView<EndpointPair*> *endpointPairs = 0; + HRESULT 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; + } + op->Release(); + + if (!endpointPairs) + return results; + + unsigned int size; + endpointPairs->get_Size(&size); + QList<QHostAddress> addresses; + for (unsigned int i = 0; i < size; ++i) { + IEndpointPair *endpointpair; + endpointPairs->GetAt(i, &endpointpair); + IHostName *remoteHost; + endpointpair->get_RemoteHostName(&remoteHost); + endpointpair->Release(); + if (!remoteHost) + continue; + HostNameType type; + remoteHost->get_Type(&type); + if (type == HostNameType_DomainName) + continue; + + HSTRING name; + remoteHost->get_CanonicalName(&name); + remoteHost->Release(); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(name, &length); + QHostAddress addr; + addr.setAddress(QString::fromWCharArray(rawString, length)); + if (!addresses.contains(addr)) + addresses.append(addr); + } + results.setAddresses(addresses); + + return results; +} + +QString QHostInfo::localHostName() +{ + INetworkInformationStatics *statics; + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics); + + IVectorView<HostName*> *hostNames = 0; + statics->GetHostNames(&hostNames); + statics->Release(); + if (!hostNames) + return QString(); + + unsigned int size; + hostNames->get_Size(&size); + if (size == 0) + return QString(); + + for (unsigned int i = 0; i < size; ++i) { + IHostName *hostName; + hostNames->GetAt(i, &hostName); + HostNameType type; + hostName->get_Type(&type); + if (type != HostNameType_DomainName) + continue; + + HSTRING name; + hostName->get_CanonicalName(&name); + hostName->Release(); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(name, &length); + return QString::fromWCharArray(rawString, length); + } + IHostName *firstHost; + hostNames->GetAt(0, &firstHost); + hostNames->Release(); + + HSTRING name; + firstHost->get_CanonicalName(&name); + firstHost->Release(); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(name, &length); + return QString::fromWCharArray(rawString, length); +} + +// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp + +QT_END_NAMESPACE diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp new file mode 100644 index 0000000000..6a814c85d4 --- /dev/null +++ b/src/network/kernel/qnetworkinterface_winrt.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnetworkinterface.h" +#include "qnetworkinterface_p.h" + +#ifndef QT_NO_NETWORKINTERFACE + +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.foundation.collections.h> +#include <windows.networking.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; + +#include <qhostinfo.h> + +QT_BEGIN_NAMESPACE + +struct HostNameInfo { + GUID adapterId; + unsigned char prefixLength; + QString address; +}; + +static QList<QNetworkInterfacePrivate *> interfaceListing() +{ + QList<QNetworkInterfacePrivate *> interfaces; + + QList<HostNameInfo> hostList; + + INetworkInformationStatics *hostNameStatics; + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &hostNameStatics); + + IVectorView<HostName*> *hostNames = 0; + hostNameStatics->GetHostNames(&hostNames); + hostNameStatics->Release(); + if (!hostNames) + return interfaces; + + unsigned int hostNameCount; + hostNames->get_Size(&hostNameCount); + for (unsigned i = 0; i < hostNameCount; ++i) { + HostNameInfo hostInfo; + IHostName *hostName; + hostNames->GetAt(i, &hostName); + + HostNameType type; + hostName->get_Type(&type); + if (type == HostNameType_DomainName) + continue; + + IIPInformation *ipInformation; + hostName->get_IPInformation(&ipInformation); + INetworkAdapter *currentAdapter; + ipInformation->get_NetworkAdapter(¤tAdapter); + + currentAdapter->get_NetworkAdapterId(&hostInfo.adapterId); + currentAdapter->Release(); + + IReference<unsigned char> *prefixLengthReference; + ipInformation->get_PrefixLength(&prefixLengthReference); + ipInformation->Release(); + + prefixLengthReference->get_Value(&hostInfo.prefixLength); + prefixLengthReference->Release(); + + // invalid prefixes + if ((type == HostNameType_Ipv4 && hostInfo.prefixLength > 32) + || (type == HostNameType_Ipv6 && hostInfo.prefixLength > 128)) + continue; + + HSTRING name; + hostName->get_CanonicalName(&name); + hostName->Release(); + UINT32 length; + PCWSTR rawString = WindowsGetStringRawBuffer(name, &length); + hostInfo.address = QString::fromWCharArray(rawString, length); + + hostList << hostInfo; + } + hostNames->Release(); + + INetworkInformationStatics *networkInfoStatics; + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &networkInfoStatics); + IVectorView<ConnectionProfile *> *connectionProfiles = 0; + networkInfoStatics->GetConnectionProfiles(&connectionProfiles); + networkInfoStatics->Release(); + if (!connectionProfiles) + return interfaces; + + unsigned int size; + connectionProfiles->get_Size(&size); + for (unsigned int i = 0; i < size; ++i) { + QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate; + interfaces << iface; + + IConnectionProfile *profile; + connectionProfiles->GetAt(i, &profile); + + NetworkConnectivityLevel connectivityLevel; + profile->GetNetworkConnectivityLevel(&connectivityLevel); + if (connectivityLevel != NetworkConnectivityLevel_None) + iface->flags = QNetworkInterface::IsUp | QNetworkInterface::IsRunning; + + INetworkAdapter *adapter; + profile->get_NetworkAdapter(&adapter); + profile->Release(); + UINT32 type; + adapter->get_IanaInterfaceType(&type); + if (type == 23) + iface->flags |= QNetworkInterface::IsPointToPoint; + GUID id; + adapter->get_NetworkAdapterId(&id); + adapter->Release(); + OLECHAR adapterName[39]={0}; + StringFromGUID2(id, adapterName, 39); + iface->name = QString::fromWCharArray(adapterName); + + // According to http://stackoverflow.com/questions/12936193/how-unique-is-the-ethernet-network-adapter-id-in-winrt-it-is-derived-from-the-m + // obtaining the MAC address using WinRT API is impossible + // iface->hardwareAddress = ? + + for (int i = 0; i < hostList.length(); ++i) { + const HostNameInfo hostInfo = hostList.at(i); + if (id != hostInfo.adapterId) + continue; + + QNetworkAddressEntry entry; + entry.setIp(QHostAddress(hostInfo.address)); + entry.setPrefixLength(hostInfo.prefixLength); + iface->addressEntries << entry; + + hostList.takeAt(i); + --i; + } + } + connectionProfiles->Release(); + return interfaces; +} + +QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan() +{ + return interfaceListing(); +} + +QString QHostInfo::localDomainName() +{ + return QString(); +} + +QT_END_NAMESPACE + +#endif // QT_NO_NETWORKINTERFACE |