winrt: Add support for Windows Information Protection
Windows Information Protection is used for splitting corporate and personal data, requiring connections to be established in a different way instantiating ThreadNetworkContext. Usage is enabled via the QT_WINRT_USE_THREAD_NETWORK_CONTEXT environment variable. Change-Id: I3aaa097b66fc616d42cd05a1e20bbcb004f6e467 Reviewed-by: James Tong Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
parent
20017d0b1b
commit
e9fa435652
@ -1113,7 +1113,12 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
|
||||
// Tries to connect to the address. If it succeeds immediately
|
||||
// (localhost address on BSD or any UDP connect), emit
|
||||
// connected() and return.
|
||||
if (socketEngine->connectToHost(host, port)) {
|
||||
if (
|
||||
#if defined(Q_OS_WINRT) && _MSC_VER >= 1900
|
||||
!qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT") ?
|
||||
socketEngine->connectToHostByName(hostName, port) :
|
||||
#endif
|
||||
socketEngine->connectToHost(host, port)) {
|
||||
//_q_testConnection();
|
||||
fetchConnectionParameters();
|
||||
return;
|
||||
|
@ -75,6 +75,9 @@ using namespace ABI::Windows::Storage::Streams;
|
||||
using namespace ABI::Windows::Networking;
|
||||
using namespace ABI::Windows::Networking::Connectivity;
|
||||
using namespace ABI::Windows::Networking::Sockets;
|
||||
#if _MSC_VER >= 1900
|
||||
using namespace ABI::Windows::Security::EnterpriseData;
|
||||
#endif
|
||||
|
||||
typedef ITypedEventHandler<StreamSocketListener *, StreamSocketListenerConnectionReceivedEventArgs *> ClientConnectedHandler;
|
||||
typedef ITypedEventHandler<DatagramSocket *, DatagramSocketMessageReceivedEventArgs *> DatagramReceivedHandler;
|
||||
@ -84,6 +87,45 @@ typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr<IThreadNetworkContext> &context)
|
||||
{
|
||||
HRESULT hr;
|
||||
ComPtr<IProtectionPolicyManagerStatics> protectionPolicyManager;
|
||||
|
||||
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_EnterpriseData_ProtectionPolicyManager).Get(),
|
||||
&protectionPolicyManager);
|
||||
RETURN_HR_IF_FAILED("Could not access ProtectionPolicyManager statics.");
|
||||
|
||||
ComPtr<IHostNameFactory> hostNameFactory;
|
||||
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
|
||||
&hostNameFactory);
|
||||
RETURN_HR_IF_FAILED("Could not access HostName factory.");
|
||||
|
||||
ComPtr<IHostName> hostName;
|
||||
HStringReference hostRef(reinterpret_cast<LPCWSTR>(host.utf16()), host.length());
|
||||
hr = hostNameFactory->CreateHostName(hostRef.Get(), &hostName);
|
||||
RETURN_HR_IF_FAILED("Could not create hostname.");
|
||||
|
||||
ComPtr<IAsyncOperation<HSTRING>> op;
|
||||
hr = protectionPolicyManager->GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName.Get(), &op);
|
||||
RETURN_HR_IF_FAILED("Could not get identity operation.");
|
||||
|
||||
HSTRING hIdentity;
|
||||
hr = QWinRTFunctions::await(op, &hIdentity);
|
||||
RETURN_HR_IF_FAILED("Could not wait for identity operation.");
|
||||
|
||||
// Implies there is no need for a network context for this address
|
||||
if (hIdentity == nullptr)
|
||||
return S_OK;
|
||||
|
||||
hr = protectionPolicyManager->CreateCurrentThreadNetworkContext(hIdentity, &context);
|
||||
RETURN_HR_IF_FAILED("Could not create thread network context");
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#endif // _MSC_VER >= 1900
|
||||
|
||||
static inline QString qt_QStringFromHString(const HString &string)
|
||||
{
|
||||
UINT32 length;
|
||||
@ -367,9 +409,23 @@ bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 por
|
||||
bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
|
||||
{
|
||||
Q_D(QNativeSocketEngine);
|
||||
HRESULT hr;
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
ComPtr<IThreadNetworkContext> networkContext;
|
||||
if (!qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT")) {
|
||||
hr = qt_winrt_try_create_thread_network_context(name, networkContext);
|
||||
if (FAILED(hr)) {
|
||||
setError(QAbstractSocket::ConnectionRefusedError, QLatin1String("Could not create thread network context."));
|
||||
d->socketState = QAbstractSocket::ConnectedState;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif // _MSC_VER >= 1900
|
||||
|
||||
HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(name.utf16()));
|
||||
ComPtr<IHostNameFactory> hostNameFactory;
|
||||
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
|
||||
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
|
||||
&hostNameFactory);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
ComPtr<IHostName> remoteHost;
|
||||
@ -390,6 +446,16 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
|
||||
}
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
if (networkContext != nullptr) {
|
||||
ComPtr<IClosable> networkContextCloser;
|
||||
hr = networkContext.As(&networkContextCloser);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = networkContextCloser->Close();
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
#endif // _MSC_VER >= 1900
|
||||
|
||||
d->socketState = QAbstractSocket::ConnectingState;
|
||||
QEventDispatcherWinRT::runOnXamlThread([d, &hr]() {
|
||||
hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
|
||||
|
Loading…
x
Reference in New Issue
Block a user