blob: 0446223d4cddc4304c774f40160e47ee854e8b41 [file] [log] [blame]
/*
* Copyright (C) 2019-2020 by Savoir-faire Linux
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "connectivitymonitor.h"
#include <QDebug>
#ifdef Q_OS_WIN
#include <atlbase.h>
#include <netlistmgr.h>
class NetworkEventHandler : public INetworkListManagerEvents
{
public:
NetworkEventHandler()
: m_lRefCnt(1){};
virtual ~NetworkEventHandler(){};
HRESULT STDMETHODCALLTYPE
QueryInterface(REFIID riid, void **ppvObject)
{
HRESULT hr = S_OK;
if (IsEqualIID(riid, IID_IUnknown)) {
*ppvObject = (IUnknown *) this;
} else if (IsEqualIID(riid, IID_INetworkListManagerEvents)) {
*ppvObject = (INetworkListManagerEvents *) this;
} else {
hr = E_NOINTERFACE;
}
return hr;
};
ULONG STDMETHODCALLTYPE
AddRef()
{
return (ULONG) InterlockedIncrement(&m_lRefCnt);
};
ULONG STDMETHODCALLTYPE
Release()
{
LONG res = InterlockedDecrement(&m_lRefCnt);
if (res == 0) {
delete this;
}
return (ULONG) res;
};
virtual HRESULT STDMETHODCALLTYPE
ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
{
qDebug() << "connectivity changed: " << newConnectivity;
if (connectivityChangedCb_) {
connectivityChangedCb_();
}
return S_OK;
};
void
setOnConnectivityChangedCallBack(std::function<void()> &&cb)
{
connectivityChangedCb_ = cb;
};
private:
LONG m_lRefCnt;
std::function<void()> connectivityChangedCb_;
};
ConnectivityMonitor::ConnectivityMonitor(QObject *parent)
: QObject(parent)
{
CoInitialize(NULL);
IUnknown *pUnknown = NULL;
HRESULT hr = CoCreateInstance(CLSID_NetworkListManager,
NULL,
CLSCTX_ALL,
IID_IUnknown,
(void **) &pUnknown);
if (FAILED(hr)) {
return;
}
pNetworkListManager_ = NULL;
hr = pUnknown->QueryInterface(IID_INetworkListManager, (void **) &pNetworkListManager_);
if (FAILED(hr)) {
destroy();
pUnknown->Release();
return;
}
pCPContainer_ = NULL;
hr = pNetworkListManager_->QueryInterface(IID_IConnectionPointContainer,
(void **) &pCPContainer_);
if (FAILED(hr)) {
destroy();
pUnknown->Release();
return;
}
pConnectPoint_ = NULL;
hr = pCPContainer_->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint_);
if (SUCCEEDED(hr)) {
cookie_ = NULL;
netEventHandler_ = new NetworkEventHandler;
netEventHandler_->setOnConnectivityChangedCallBack([this] { emit connectivityChanged(); });
hr = pConnectPoint_->Advise((IUnknown *) netEventHandler_, &cookie_);
} else {
destroy();
}
pUnknown->Release();
}
bool
ConnectivityMonitor::isOnline()
{
if (!pNetworkListManager_) {
return false;
}
VARIANT_BOOL IsConnect = VARIANT_FALSE;
HRESULT hr = pNetworkListManager_->get_IsConnectedToInternet(&IsConnect);
if (SUCCEEDED(hr)) {
return IsConnect == VARIANT_TRUE;
}
return false;
}
void
ConnectivityMonitor::destroy()
{
if (pConnectPoint_) {
pConnectPoint_->Unadvise(cookie_);
pConnectPoint_->Release();
}
if (pCPContainer_) {
pCPContainer_->Release();
}
if (pNetworkListManager_) {
pNetworkListManager_->Release();
pNetworkListManager_ = NULL;
}
}
ConnectivityMonitor::~ConnectivityMonitor()
{
destroy();
CoUninitialize();
}
#endif // Q_OS_WIN