6#include <QtCore/private/qsystemerror_p.h>
8#include <QtCore/qpointer.h>
12#if QT_CONFIG(cpp_winrt)
13#include <QtCore/private/qt_winrtbase_p.h>
15#include <winrt/Windows.Networking.Connectivity.h>
24 if (riid == __uuidof(T)) {
25 *ppvObject =
static_cast<T *>(from);
35 auto hr = CoCreateInstance(CLSID_NetworkListManager,
nullptr, CLSCTX_INPROC_SERVER,
36 IID_INetworkListManager, &networkListManager);
38 qCWarning(lcNetInfoNLM) <<
"Could not get a NetworkListManager instance:"
39 << QSystemError::windowsComString(hr);
43 ComPtr<IConnectionPointContainer> connectionPointContainer;
44 hr = networkListManager.As(&connectionPointContainer);
46 hr = connectionPointContainer->FindConnectionPoint(IID_INetworkListManagerEvents,
50 qCWarning(lcNetInfoNLM) <<
"Failed to get connection point for network list manager events:"
51 << QSystemError::windowsComString(hr);
60HRESULT STDMETHODCALLTYPE QNetworkListManagerEvents::QueryInterface(REFIID riid,
void **ppvObject)
65 return QueryInterfaceImpl<IUnknown>(
this, riid, ppvObject)
66 || QueryInterfaceImpl<INetworkListManagerEvents>(
this, riid, ppvObject)
71HRESULT STDMETHODCALLTYPE
72QNetworkListManagerEvents::ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
76 emit connectivityChanged(newConnectivity);
82 if (!connectionPoint) {
83 qCWarning(lcNetInfoNLM,
"Initialization failed, can't start!");
86 auto hr = connectionPoint->Advise(
this, &cookie);
88 qCWarning(lcNetInfoNLM) <<
"Failed to subscribe to network connectivity events:"
89 << QSystemError::windowsComString(hr);
94 NLM_CONNECTIVITY connectivity;
95 hr = networkListManager->GetConnectivity(&connectivity);
97 qCWarning(lcNetInfoNLM) <<
"Could not get connectivity:"
98 << QSystemError::windowsComString(hr);
100 emit connectivityChanged(connectivity);
103#if QT_CONFIG(cpp_winrt)
104 using namespace winrt::Windows::Networking::Connectivity;
105 using winrt::Windows::Foundation::IInspectable;
108 token = NetworkInformation::NetworkStatusChanged(
109 [owner = QPointer(
this)](
const IInspectable sender) {
112 std::scoped_lock locker(owner->winrtLock);
114 owner->emitWinRTUpdates();
117 }
catch (
const winrt::hresult_error &ex) {
118 qCWarning(lcNetInfoNLM) <<
"Failed to register network status changed callback:"
119 << QSystemError::windowsComString(ex.code());
131 Q_ASSERT(connectionPoint);
132 auto hr = connectionPoint->Unadvise(cookie);
134 qCWarning(lcNetInfoNLM) <<
"Failed to unsubscribe from network connectivity events:"
135 << QSystemError::windowsComString(hr);
141#if QT_CONFIG(cpp_winrt)
143 std::scoped_lock locker(winrtLock);
145 using namespace winrt::Windows::Networking::Connectivity;
147 NetworkInformation::NetworkStatusChanged(token);
155 if (!networkListManager)
157 ComPtr<IEnumNetworks> networks;
159 networkListManager->GetNetworks(NLM_ENUM_NETWORK_CONNECTED, networks.GetAddressOf());
160 if (FAILED(hr) || networks ==
nullptr)
164 ComPtr<INetwork> network;
165 hr = networks->Next(1, network.GetAddressOf(),
nullptr);
166 while (SUCCEEDED(hr) && network !=
nullptr) {
167 ComPtr<IPropertyBag> propertyBag;
168 hr = network.As(&propertyBag);
169 if (SUCCEEDED(hr) && propertyBag !=
nullptr) {
171 VariantInit(&variant);
172 const auto scopedVariantClear = qScopeGuard([&variant]() { VariantClear(&variant); });
174 const wchar_t *versions[] = { L"NA_InternetConnectivityV6", L"NA_InternetConnectivityV4" };
175 for (
const auto version : versions) {
176 hr = propertyBag->Read(version, &variant,
nullptr);
178 && (V_UINT(&variant) & NLM_INTERNET_CONNECTIVITY_WEBHIJACK)
179 == NLM_INTERNET_CONNECTIVITY_WEBHIJACK) {
185 hr = networks->Next(1, network.GetAddressOf(),
nullptr);
191#if QT_CONFIG(cpp_winrt)
193using namespace winrt::Windows::Networking::Connectivity;
197QNetworkInformation::TransportMedium getTransportMedium(
const ConnectionProfile &profile)
199 if (profile.IsWwanConnectionProfile())
200 return QNetworkInformation::TransportMedium::Cellular;
201 if (profile.IsWlanConnectionProfile())
202 return QNetworkInformation::TransportMedium::WiFi;
204 NetworkAdapter adapter(
nullptr);
206 adapter = profile.NetworkAdapter();
207 }
catch (
const winrt::hresult_error &ex) {
208 qCWarning(lcNetInfoNLM) <<
"Failed to obtain network adapter:"
209 << QSystemError::windowsComString(ex.code());
212 if (adapter ==
nullptr)
213 return QNetworkInformation::TransportMedium::Unknown;
218 auto fromIanaId = [](quint32 ianaId) -> QNetworkInformation::TransportMedium {
222 return QNetworkInformation::TransportMedium::Ethernet;
224 return QNetworkInformation::TransportMedium::WiFi;
226 return QNetworkInformation::TransportMedium::Unknown;
229 return fromIanaId(adapter.IanaInterfaceType());
232[[nodiscard]]
bool getMetered(
const ConnectionProfile &profile)
234 ConnectionCost cost(
nullptr);
236 cost = profile.GetConnectionCost();
237 }
catch (
const winrt::hresult_error &ex) {
238 qCWarning(lcNetInfoNLM) <<
"Failed to obtain connection cost:"
239 << QSystemError::windowsComString(ex.code());
244 NetworkCostType type = cost.NetworkCostType();
245 return type == NetworkCostType::Fixed || type == NetworkCostType::Variable;
249void QNetworkListManagerEvents::emitWinRTUpdates()
251 using namespace winrt::Windows::Networking::Connectivity;
252 ConnectionProfile profile =
nullptr;
254 profile = NetworkInformation::GetInternetConnectionProfile();
255 }
catch (
const winrt::hresult_error &ex) {
256 qCWarning(lcNetInfoNLM) <<
"Failed to obtain connection profile:"
257 << QSystemError::windowsComString(ex.code());
260 if (profile ==
nullptr)
262 emit transportMediumChanged(getTransportMedium(profile));
263 emit isMeteredChanged(getMetered(profile));
269#include "moc_qnetworklistmanagerevents.cpp"
bool checkBehindCaptivePortal()
virtual ~QNetworkListManagerEvents()
bool QueryInterfaceImpl(IUnknown *from, REFIID riid, void **ppvObject)