diff --git a/src/ui/FortFirewallUI.pro b/src/ui/FortFirewallUI.pro index 6aa4e8c3..46620ce4 100644 --- a/src/ui/FortFirewallUI.pro +++ b/src/ui/FortFirewallUI.pro @@ -111,8 +111,6 @@ SOURCES += \ rpc/windowmanagerfake.cpp \ serviceinfo/serviceinfo.cpp \ serviceinfo/serviceinfomanager.cpp \ - serviceinfo/serviceinfomonitor.cpp \ - serviceinfo/servicelistmonitor.cpp \ stat/quotamanager.cpp \ stat/statmanager.cpp \ stat/statsql.cpp \ @@ -266,8 +264,6 @@ HEADERS += \ rpc/windowmanagerfake.h \ serviceinfo/serviceinfo.h \ serviceinfo/serviceinfomanager.h \ - serviceinfo/serviceinfomonitor.h \ - serviceinfo/servicelistmonitor.h \ stat/quotamanager.h \ stat/statmanager.h \ stat/statsql.h \ diff --git a/src/ui/fortmanager.cpp b/src/ui/fortmanager.cpp index 8a9af232..0761aa86 100644 --- a/src/ui/fortmanager.cpp +++ b/src/ui/fortmanager.cpp @@ -84,7 +84,6 @@ void FortManager::initialize() setupConfManager(); setupQuotaManager(); setupTaskManager(); - setupServiceInfoManager(); setupDriver(); loadConf(); @@ -287,13 +286,6 @@ void FortManager::setupTaskManager() IoC(), &ConfManager::updateDriverZones); } -void FortManager::setupServiceInfoManager() -{ - auto serviceInfoManager = IoC(); - - serviceInfoManager->setMonitorEnabled(IoC()->isMaster()); -} - void FortManager::setupTranslationManager() { IoC()->switchLanguageByName(IoC()->iniUser().language()); diff --git a/src/ui/fortmanager.h b/src/ui/fortmanager.h index e4349b8f..ab0a8cd3 100644 --- a/src/ui/fortmanager.h +++ b/src/ui/fortmanager.h @@ -46,7 +46,6 @@ private: void setupConfManager(); void setupQuotaManager(); void setupTaskManager(); - void setupServiceInfoManager(); void setupTranslationManager(); diff --git a/src/ui/serviceinfo/serviceinfomanager.cpp b/src/ui/serviceinfo/serviceinfomanager.cpp index c9ab4bf1..76205601 100644 --- a/src/ui/serviceinfo/serviceinfomanager.cpp +++ b/src/ui/serviceinfo/serviceinfomanager.cpp @@ -5,9 +5,6 @@ #define WIN32_LEAN_AND_MEAN #include -#include "serviceinfomonitor.h" -#include "servicelistmonitor.h" - namespace { const QLoggingCategory LC("serviceInfo.serviceInfoManager"); @@ -49,21 +46,6 @@ QVector getServiceInfoList(SC_HANDLE mngr, DWORD state = SERVICE_ST ServiceInfoManager::ServiceInfoManager(QObject *parent) : QObject(parent) { } -ServiceInfoManager::~ServiceInfoManager() -{ - clearServiceMonitors(); - stopServiceListMonitor(); -} - -void ServiceInfoManager::setMonitorEnabled(bool v) -{ - if (m_monitorEnabled != v) { - m_monitorEnabled = v; - - setupServiceMonitors(); - } -} - int ServiceInfoManager::groupIndexByName(const QString &name) const { return m_serviceGroups.value(name, -1); @@ -80,114 +62,3 @@ QVector ServiceInfoManager::loadServiceInfoList() } return list; } - -void ServiceInfoManager::setupServiceMonitors() -{ - clearServiceMonitors(); - - if (!monitorEnabled()) - return; - - const SC_HANDLE mngr = - OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); - if (!mngr) { - qCCritical(LC) << "Open manager error:" << GetLastError(); - return; - } - - if (!m_serviceGroups.isEmpty()) { - const auto services = getServiceInfoList(mngr); - for (const auto &info : services) { - startServiceMonitor(info.serviceName, info.processId, mngr); - } - } - - startServiceListMonitor(mngr); -} - -void ServiceInfoManager::clearServiceMonitors() -{ - const auto monitors = m_serviceMonitors.values(); - m_serviceMonitors.clear(); - - for (ServiceInfoMonitor *m : monitors) { - stopServiceMonitor(m); - } -} - -void ServiceInfoManager::startServiceMonitor( - const QString &name, quint32 processId, void *managerHandle) -{ - if (!m_serviceGroups.contains(name)) - return; - - auto m = new ServiceInfoMonitor(processId, name, managerHandle); - - connect(m, &ServiceInfoMonitor::stateChanged, this, &ServiceInfoManager::onServiceStateChanged, - Qt::QueuedConnection); - - m_serviceMonitors.insert(name, m); -} - -void ServiceInfoManager::stopServiceMonitor(ServiceInfoMonitor *m) -{ - m_serviceMonitors.remove(m->name()); - - m->terminate(); - m->deleteLater(); -} - -void ServiceInfoManager::startServiceListMonitor(void *managerHandle) -{ - auto m = new ServiceListMonitor(managerHandle); - - connect(m, &ServiceListMonitor::serviceCreated, this, &ServiceInfoManager::onServiceCreated, - Qt::QueuedConnection); - connect(m, &ServiceListMonitor::errorOccurred, this, - &ServiceInfoManager::stopServiceListMonitor, Qt::QueuedConnection); - - m_serviceListMonitor = m; -} - -void ServiceInfoManager::stopServiceListMonitor() -{ - auto m = m_serviceListMonitor; - if (!m) - return; - - m_serviceListMonitor = nullptr; - - m->terminate(); - m->deleteLater(); -} - -void ServiceInfoManager::onServiceStateChanged(ServiceInfo::State state, quint32 processId) -{ - const auto m = qobject_cast(sender()); - Q_ASSERT(m); - - if (state == ServiceInfo::StateDeleted) { - Q_ASSERT(processId == 0); - processId = m->processId(); - if (processId != 0) { - state = ServiceInfo::StateInactive; - } - - stopServiceMonitor(m); - } - - const int groupIndex = groupIndexByName(m->name()); - if (groupIndex == -1) - return; - - Q_ASSERT(processId != 0); - - emit serviceChanged(processId, (state == ServiceInfo::StateActive ? groupIndex : -1)); -} - -void ServiceInfoManager::onServiceCreated(const QStringList &nameList) -{ - for (const auto &name : nameList) { - startServiceMonitor(name); - } -} diff --git a/src/ui/serviceinfo/serviceinfomanager.h b/src/ui/serviceinfo/serviceinfomanager.h index 551ab262..564d76b3 100644 --- a/src/ui/serviceinfo/serviceinfomanager.h +++ b/src/ui/serviceinfo/serviceinfomanager.h @@ -8,19 +8,12 @@ #include "serviceinfo.h" -class ServiceInfoMonitor; -class ServiceListMonitor; - class ServiceInfoManager : public QObject, public IocService { Q_OBJECT public: explicit ServiceInfoManager(QObject *parent = nullptr); - ~ServiceInfoManager() override; - - bool monitorEnabled() const { return m_monitorEnabled; } - void setMonitorEnabled(bool v); int groupIndexByName(const QString &name) const; @@ -30,25 +23,7 @@ signals: void serviceChanged(quint32 processId, int groupIndex = -1); private: - void setupServiceMonitors(); - void clearServiceMonitors(); - - void startServiceMonitor( - const QString &name, quint32 processId = 0, void *managerHandle = nullptr); - void stopServiceMonitor(ServiceInfoMonitor *m); - - void startServiceListMonitor(void *managerHandle = nullptr); - void stopServiceListMonitor(); - - void onServiceStateChanged(ServiceInfo::State state, quint32 processId = 0); - void onServiceCreated(const QStringList &nameList); - -private: - bool m_monitorEnabled = false; - QHash m_serviceGroups; - QHash m_serviceMonitors; - ServiceListMonitor *m_serviceListMonitor = nullptr; }; #endif // SERVICEINFOMANAGER_H diff --git a/src/ui/serviceinfo/serviceinfomonitor.cpp b/src/ui/serviceinfo/serviceinfomonitor.cpp deleted file mode 100644 index 70206b95..00000000 --- a/src/ui/serviceinfo/serviceinfomonitor.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include "serviceinfomonitor.h" - -#include - -#define WIN32_LEAN_AND_MEAN -#include - -#define asServiceHandle(h) static_cast((h)) -#define serviceHandle() asServiceHandle(m_serviceHandle) - -namespace { - -const QLoggingCategory LC("serviceInfo.serviceInfoMonitor"); - -static void CALLBACK notifyCallback(PVOID parameter) -{ - PSERVICE_NOTIFYW notify = static_cast(parameter); - ServiceInfoMonitor *m = static_cast(notify->pContext); - - if (notify->dwNotificationStatus != ERROR_SUCCESS) { - qCDebug(LC) << "Callback error:" << m->name() << notify->dwNotificationStatus; - m->requestReopenService(); - return; - } - - if (notify->dwNotificationTriggered & SERVICE_NOTIFY_DELETE_PENDING) { - emit m->stateChanged(ServiceInfo::StateDeleted); - return; - } - - const bool running = (notify->ServiceStatus.dwCurrentState == SERVICE_RUNNING); - m->setRunning(running); - - const quint32 processId = notify->ServiceStatus.dwProcessId; - const quint32 oldProcessId = m->processId(); - m->setProcessId(processId); - - const ServiceInfo::State state = - running ? ServiceInfo::StateActive : ServiceInfo::StateInactive; - - emit m->stateChanged(state, (running ? processId : oldProcessId)); - - // NotifyServiceStatusChange() must not be called from the callback - m->requestStartNotifier(); -} - -PSERVICE_NOTIFYW getNotifyBuffer(ServiceInfoMonitor *m) -{ - auto &buffer = m->notifyBuffer(); - - PSERVICE_NOTIFYW notify = reinterpret_cast(buffer.data()); - - notify->dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; - notify->pfnNotifyCallback = notifyCallback; - notify->pContext = m; - - return notify; -} - -} - -ServiceInfoMonitor::ServiceInfoMonitor( - quint32 processId, const QString &name, void *managerHandle, QObject *parent) : - QObject(parent), - m_terminated(false), - m_isReopening(false), - m_reopenServiceRequested(false), - m_startNotifierRequested(false), - m_running(processId != 0), - m_processId(processId), - m_name(name), - m_notifyBuffer(sizeof(SERVICE_NOTIFYW)) -{ - openService(managerHandle); -} - -ServiceInfoMonitor::~ServiceInfoMonitor() -{ - terminate(); -} - -void ServiceInfoMonitor::terminate() -{ - if (m_terminated) - return; - - m_terminated = true; - - closeService(); -} - -void ServiceInfoMonitor::requestReopenService() -{ - if (m_reopenServiceRequested) - return; - - m_reopenServiceRequested = true; - - QMetaObject::invokeMethod(this, &ServiceInfoMonitor::reopenService, Qt::QueuedConnection); -} - -void ServiceInfoMonitor::requestStartNotifier() -{ - if (m_startNotifierRequested) - return; - - m_startNotifierRequested = true; - - QMetaObject::invokeMethod(this, &ServiceInfoMonitor::startNotifier, Qt::QueuedConnection); -} - -void ServiceInfoMonitor::openService(void *managerHandle) -{ - const SC_HANDLE mngr = managerHandle ? asServiceHandle(managerHandle) - : OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT); - if (mngr) { - m_serviceHandle = OpenServiceW(mngr, (LPCWSTR) name().utf16(), SERVICE_QUERY_STATUS); - - if (!managerHandle) { - CloseServiceHandle(mngr); - } - } - - if (!m_serviceHandle) { - const DWORD res = GetLastError(); - switch (res) { - case ERROR_SERVICE_MARKED_FOR_DELETE: { - emit stateChanged(ServiceInfo::StateDeleted); - } break; - default: - qCCritical(LC) << "Open service error:" << name() << res; - errorOccurred(); - } - return; - } - - startNotifier(); -} - -void ServiceInfoMonitor::closeService() -{ - if (m_serviceHandle) { - CloseServiceHandle(serviceHandle()); - m_serviceHandle = nullptr; - } -} - -void ServiceInfoMonitor::reopenService() -{ - if (m_isReopening) { - qCCritical(LC) << "Reopen service error:" << name(); - errorOccurred(); - return; - } - - m_isReopening = true; - - m_reopenServiceRequested = false; - - closeService(); - openService(); - - m_isReopening = false; -} - -void ServiceInfoMonitor::startNotifier() -{ - if (m_terminated) - return; - - m_startNotifierRequested = false; - - constexpr DWORD mask = - SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING | SERVICE_NOTIFY_DELETE_PENDING; - - PSERVICE_NOTIFYW notify = getNotifyBuffer(this); - - const DWORD res = NotifyServiceStatusChangeW(serviceHandle(), mask, notify); - - if (res != ERROR_SUCCESS) { - switch (res) { - case ERROR_SERVICE_MARKED_FOR_DELETE: { - emit stateChanged(ServiceInfo::StateDeleted); - } break; - case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: { - qCDebug(LC) << "Notifier is lagging:" << name(); - reopenService(); - } break; - default: - qCCritical(LC) << "Start notifier error:" << name() << res; - errorOccurred(); - } - } -} - -void ServiceInfoMonitor::errorOccurred() -{ - emit stateChanged(ServiceInfo::StateDeleted); -} diff --git a/src/ui/serviceinfo/serviceinfomonitor.h b/src/ui/serviceinfo/serviceinfomonitor.h deleted file mode 100644 index 99d3a16d..00000000 --- a/src/ui/serviceinfo/serviceinfomonitor.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef SERVICEINFOMONITOR_H -#define SERVICEINFOMONITOR_H - -#include - -#include "serviceinfo.h" - -class ServiceInfoMonitor : public QObject -{ - Q_OBJECT - -public: - explicit ServiceInfoMonitor(quint32 processId, const QString &name, - void *managerHandle = nullptr, QObject *parent = nullptr); - ~ServiceInfoMonitor() override; - - bool running() const { return m_running; } - void setRunning(bool v) { m_running = v; } - - quint32 processId() const { return m_processId; } - void setProcessId(quint32 v) { m_processId = v; } - - QString name() const { return m_name; } - - QVector ¬ifyBuffer() { return m_notifyBuffer; } - -signals: - void stateChanged(ServiceInfo::State state, quint32 processId = 0); - -public slots: - void terminate(); - - void requestReopenService(); - void requestStartNotifier(); - -private: - void openService(void *managerHandle = nullptr); - void closeService(); - void reopenService(); - - void startNotifier(); - - void errorOccurred(); - -private: - bool m_terminated : 1; - bool m_isReopening : 1; - bool m_reopenServiceRequested : 1; - bool m_startNotifierRequested : 1; - bool m_running : 1; - - quint32 m_processId = 0; - - const QString m_name; - - void *m_serviceHandle = nullptr; - QVector m_notifyBuffer; -}; - -#endif // SERVICEINFOMONITOR_H diff --git a/src/ui/serviceinfo/servicelistmonitor.cpp b/src/ui/serviceinfo/servicelistmonitor.cpp deleted file mode 100644 index 2a451139..00000000 --- a/src/ui/serviceinfo/servicelistmonitor.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "servicelistmonitor.h" - -#include - -#define WIN32_LEAN_AND_MEAN -#include - -#define asManagerHandle(h) static_cast((h)) -#define managerHandle() asManagerHandle(m_managerHandle) - -namespace { - -const QLoggingCategory LC("serviceInfo.serviceListMonitor"); - -static QStringList parseServiceNames(LPWSTR pszServiceNames) -{ - QStringList list; - PWSTR name = pszServiceNames; - for (;;) { - if (name[0] == '\0') - break; - Q_ASSERT(name[0] == '/'); - ++name; // Skip the leading '/' for created services - const QString nameStr = QString::fromWCharArray(name); - name += nameStr.length() + 1; - list.append(nameStr); - } - LocalFree(pszServiceNames); - return list; -} - -static void CALLBACK notifyCallback(PVOID parameter) -{ - PSERVICE_NOTIFYW notify = static_cast(parameter); - ServiceListMonitor *m = static_cast(notify->pContext); - - if (notify->dwNotificationStatus != ERROR_SUCCESS) { - qCDebug(LC) << "Callback error:" << notify->dwNotificationStatus; - m->requestReopenManager(); - return; - } - - const QStringList nameList = - notify->pszServiceNames ? parseServiceNames(notify->pszServiceNames) : QStringList(); - - if (!nameList.isEmpty()) { - emit m->serviceCreated(nameList); - } - - // NotifyServiceStatusChange() must not be called from the callback - m->requestStartNotifier(); -} - -PSERVICE_NOTIFYW getNotifyBuffer(ServiceListMonitor *m) -{ - auto &buffer = m->notifyBuffer(); - - PSERVICE_NOTIFYW notify = reinterpret_cast(buffer.data()); - - notify->dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; - notify->pfnNotifyCallback = notifyCallback; - notify->pContext = m; - - return notify; -} - -} - -ServiceListMonitor::ServiceListMonitor(void *managerHandle, QObject *parent) : - QObject(parent), - m_terminated(false), - m_isReopening(false), - m_reopenManagerRequested(false), - m_startNotifierRequested(false), - m_managerHandle(managerHandle), - m_notifyBuffer(sizeof(SERVICE_NOTIFYW)) -{ - openManager(); -} - -ServiceListMonitor::~ServiceListMonitor() -{ - terminate(); -} - -void ServiceListMonitor::terminate() -{ - if (m_terminated) - return; - - m_terminated = true; - - closeManager(); -} - -void ServiceListMonitor::requestReopenManager() -{ - if (m_reopenManagerRequested) - return; - - m_reopenManagerRequested = true; - - QMetaObject::invokeMethod(this, &ServiceListMonitor::reopenManager, Qt::QueuedConnection); -} - -void ServiceListMonitor::requestStartNotifier() -{ - if (m_startNotifierRequested) - return; - - m_startNotifierRequested = true; - - QMetaObject::invokeMethod(this, &ServiceListMonitor::startNotifier, Qt::QueuedConnection); -} - -void ServiceListMonitor::openManager() -{ - if (!m_managerHandle) { - m_managerHandle = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ENUMERATE_SERVICE); - - if (!m_managerHandle) { - qCCritical(LC) << "Open manager error:" << GetLastError(); - emit errorOccurred(); - return; - } - } - - startNotifier(); -} - -void ServiceListMonitor::closeManager() -{ - if (m_managerHandle) { - CloseServiceHandle(managerHandle()); - m_managerHandle = nullptr; - } -} - -void ServiceListMonitor::reopenManager() -{ - if (m_isReopening) { - qCCritical(LC) << "Reopen manager error"; - emit errorOccurred(); - return; - } - - m_isReopening = true; - - m_reopenManagerRequested = false; - - closeManager(); - openManager(); - - m_isReopening = false; -} - -void ServiceListMonitor::startNotifier() -{ - if (m_terminated) - return; - - m_startNotifierRequested = false; - - constexpr DWORD mask = SERVICE_NOTIFY_CREATED; - - PSERVICE_NOTIFYW notify = getNotifyBuffer(this); - - const DWORD res = NotifyServiceStatusChangeW(managerHandle(), mask, notify); - - if (res != ERROR_SUCCESS) { - switch (res) { - case ERROR_SERVICE_NOTIFY_CLIENT_LAGGING: { - qCDebug(LC) << "Notifier is lagging"; - reopenManager(); - } break; - default: - qCCritical(LC) << "Start notifier error:" << res; - emit errorOccurred(); - } - } -} diff --git a/src/ui/serviceinfo/servicelistmonitor.h b/src/ui/serviceinfo/servicelistmonitor.h deleted file mode 100644 index 4f24b685..00000000 --- a/src/ui/serviceinfo/servicelistmonitor.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef SERVICELISTMONITOR_H -#define SERVICELISTMONITOR_H - -#include - -class ServiceListMonitor : public QObject -{ - Q_OBJECT - -public: - explicit ServiceListMonitor(void *managerHandle = nullptr, QObject *parent = nullptr); - ~ServiceListMonitor() override; - - QVector ¬ifyBuffer() { return m_notifyBuffer; } - -signals: - void serviceCreated(const QStringList &nameList); - void errorOccurred(); - -public slots: - void terminate(); - - void requestReopenManager(); - void requestStartNotifier(); - -private: - void openManager(); - void closeManager(); - void reopenManager(); - - void startNotifier(); - -private: - bool m_terminated : 1; - bool m_isReopening : 1; - bool m_reopenManagerRequested : 1; - bool m_startNotifierRequested : 1; - - void *m_managerHandle = nullptr; - QVector m_notifyBuffer; -}; - -#endif // SERVICELISTMONITOR_H