5#include <QtCore/private/qsystemerror_p.h>
7#include <QtCore/qpointer.h>
11#if QT_CONFIG(cpp_winrt)
12#include <QtCore/private/qt_winrtbase_p.h>
14#include <winrt/Windows.Networking.Connectivity.h>
23 if (riid == __uuidof(T)) {
24 *ppvObject =
static_cast<T *>(from);
34 auto hr = CoCreateInstance(CLSID_NetworkListManager,
nullptr, CLSCTX_INPROC_SERVER,
35 IID_INetworkListManager, &networkListManager);
37 qCWarning(lcNetInfoNLM) <<
"Could not get a NetworkListManager instance:"
38 << QSystemError::windowsComString(hr);
42 ComPtr<IConnectionPointContainer> connectionPointContainer;
43 hr = networkListManager.As(&connectionPointContainer);
45 hr = connectionPointContainer->FindConnectionPoint(IID_INetworkListManagerEvents,
49 qCWarning(lcNetInfoNLM) <<
"Failed to get connection point for network list manager events:"
50 << QSystemError::windowsComString(hr);
59HRESULT STDMETHODCALLTYPE QNetworkListManagerEvents::QueryInterface(REFIID riid,
void **ppvObject)
64 return QueryInterfaceImpl<IUnknown>(
this, riid, ppvObject)
65 || QueryInterfaceImpl<INetworkListManagerEvents>(
this, riid, ppvObject)
70HRESULT STDMETHODCALLTYPE
71QNetworkListManagerEvents::ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
75 emit connectivityChanged(newConnectivity);
81 if (!connectionPoint) {
82 qCWarning(lcNetInfoNLM,
"Initialization failed, can't start!");
85 auto hr = connectionPoint->Advise(
this, &cookie);
87 qCWarning(lcNetInfoNLM) <<
"Failed to subscribe to network connectivity events:"
88 << QSystemError::windowsComString(hr);
93 NLM_CONNECTIVITY connectivity;
94 hr = networkListManager->GetConnectivity(&connectivity);
96 qCWarning(lcNetInfoNLM) <<
"Could not get connectivity:"
97 << QSystemError::windowsComString(hr);
99 emit connectivityChanged(connectivity);
102#if QT_CONFIG(cpp_winrt)
103 using namespace winrt::Windows::Networking::Connectivity;
104 using winrt::Windows::Foundation::IInspectable;
107 token = NetworkInformation::NetworkStatusChanged(
108 [owner = QPointer(
this)](
const IInspectable sender) {
111 std::scoped_lock locker(owner->winrtLock);
113 owner->emitWinRTUpdates();
116 }
catch (
const winrt::hresult_error &ex) {
117 qCWarning(lcNetInfoNLM) <<
"Failed to register network status changed callback:"
118 << QSystemError::windowsComString(ex.code());
130 Q_ASSERT(connectionPoint);
131 auto hr = connectionPoint->Unadvise(cookie);
133 qCWarning(lcNetInfoNLM) <<
"Failed to unsubscribe from network connectivity events:"
134 << QSystemError::windowsComString(hr);
140#if QT_CONFIG(cpp_winrt)
142 std::scoped_lock locker(winrtLock);
144 using namespace winrt::Windows::Networking::Connectivity;
146 NetworkInformation::NetworkStatusChanged(token);
154 if (!networkListManager)
156 ComPtr<IEnumNetworks> networks;
158 networkListManager->GetNetworks(NLM_ENUM_NETWORK_CONNECTED, networks.GetAddressOf());
159 if (FAILED(hr) || networks ==
nullptr)
163 ComPtr<INetwork> network;
164 hr = networks->Next(1, network.GetAddressOf(),
nullptr);
165 while (SUCCEEDED(hr) && network !=
nullptr) {
166 ComPtr<IPropertyBag> propertyBag;
167 hr = network.As(&propertyBag);
168 if (SUCCEEDED(hr) && propertyBag !=
nullptr) {
170 VariantInit(&variant);
171 const auto scopedVariantClear = qScopeGuard([&variant]() { VariantClear(&variant); });
173 const wchar_t *versions[] = { L"NA_InternetConnectivityV6", L"NA_InternetConnectivityV4" };
174 for (
const auto version : versions) {
175 hr = propertyBag->Read(version, &variant,
nullptr);
177 && (V_UINT(&variant) & NLM_INTERNET_CONNECTIVITY_WEBHIJACK)
178 == NLM_INTERNET_CONNECTIVITY_WEBHIJACK) {
184 hr = networks->Next(1, network.GetAddressOf(),
nullptr);
190#if QT_CONFIG(cpp_winrt)
192using namespace winrt::Windows::Networking::Connectivity;
196QNetworkInformation::TransportMedium getTransportMedium(
const ConnectionProfile &profile)
198 if (profile.IsWwanConnectionProfile())
199 return QNetworkInformation::TransportMedium::Cellular;
200 if (profile.IsWlanConnectionProfile())
201 return QNetworkInformation::TransportMedium::WiFi;
203 NetworkAdapter adapter(
nullptr);
205 adapter = profile.NetworkAdapter();
206 }
catch (
const winrt::hresult_error &ex) {
207 qCWarning(lcNetInfoNLM) <<
"Failed to obtain network adapter:"
208 << QSystemError::windowsComString(ex.code());
211 if (adapter ==
nullptr)
212 return QNetworkInformation::TransportMedium::Unknown;
217 auto fromIanaId = [](quint32 ianaId) -> QNetworkInformation::TransportMedium {
221 return QNetworkInformation::TransportMedium::Ethernet;
223 return QNetworkInformation::TransportMedium::WiFi;
225 return QNetworkInformation::TransportMedium::Unknown;
228 return fromIanaId(adapter.IanaInterfaceType());
231[[nodiscard]]
bool getMetered(
const ConnectionProfile &profile)
233 ConnectionCost cost(
nullptr);
235 cost = profile.GetConnectionCost();
236 }
catch (
const winrt::hresult_error &ex) {
237 qCWarning(lcNetInfoNLM) <<
"Failed to obtain connection cost:"
238 << QSystemError::windowsComString(ex.code());
243 NetworkCostType type = cost.NetworkCostType();
244 return type == NetworkCostType::Fixed || type == NetworkCostType::Variable;
248void QNetworkListManagerEvents::emitWinRTUpdates()
250 using namespace winrt::Windows::Networking::Connectivity;
251 ConnectionProfile profile =
nullptr;
253 profile = NetworkInformation::GetInternetConnectionProfile();
254 }
catch (
const winrt::hresult_error &ex) {
255 qCWarning(lcNetInfoNLM) <<
"Failed to obtain connection profile:"
256 << QSystemError::windowsComString(ex.code());
259 if (profile ==
nullptr)
261 emit transportMediumChanged(getTransportMedium(profile));
262 emit isMeteredChanged(getMetered(profile));
268#include "moc_qnetworklistmanagerevents.cpp"
bool checkBehindCaptivePortal()
virtual ~QNetworkListManagerEvents()
bool QueryInterfaceImpl(IUnknown *from, REFIID riid, void **ppvObject)