UI: StartupUtil: Add service (un)install functions.

This commit is contained in:
Nodir Temirkhodjaev 2021-03-29 12:33:17 +03:00
parent e7d04f1224
commit 44498bd145
7 changed files with 94 additions and 38 deletions

View File

@ -118,13 +118,14 @@ void OptionsPage::retranslateComboStartMode()
const QStringList list = { tr("Disabled"), tr("For current user"), tr("For all users"),
tr("For all users in background") };
const int currentIndex = m_comboStartMode->currentIndex();
const int currentIndex = m_comboStartMode->currentIndex() >= 0
? m_comboStartMode->currentIndex()
: StartupUtil::getStartupMode();
m_comboStartMode->clear();
m_comboStartMode->addItems(list);
m_comboStartMode->setCurrentIndex(
currentIndex < 0 ? StartupUtil::getStartupMode() : currentIndex);
m_comboStartMode->setCurrentIndex(currentIndex);
// Disable some items if user is not an administrator
if (OsUtil::isUserAdmin())

View File

@ -31,6 +31,7 @@ FortSettings::FortSettings(QObject *parent) :
QObject(parent),
m_iniExists(false),
m_noCache(false),
m_isService(false),
m_bulkUpdating(false),
m_bulkIniChanged(false)
{
@ -99,6 +100,10 @@ void FortSettings::processArguments(const QStringList &args, EnvManager *envMana
const QCommandLineOption langOption(QStringList() << "lang", "Default language.", "lang", "en");
parser.addOption(langOption);
const QCommandLineOption serviceOption(
QStringList() << "service", "Is running as a service?", "service");
parser.addOption(serviceOption);
const QCommandLineOption controlOption(QStringList() << "c"
<< "control",
"Control running instance by executing the command.", "control");
@ -119,6 +124,11 @@ void FortSettings::processArguments(const QStringList &args, EnvManager *envMana
m_defaultLanguage = parser.value(langOption);
}
// Is service
if (parser.isSet(serviceOption)) {
m_isService = true;
}
// Profile Path
if (parser.isSet(profileOption)) {
m_profilePath = parser.value(profileOption);

View File

@ -18,6 +18,7 @@ public:
explicit FortSettings(QObject *parent = nullptr);
bool noCache() const { return m_noCache; }
bool isService() const { return m_isService; }
bool debug() const { return iniBool("base/debug"); }
void setDebug(bool on) { setIniValue("base/debug", on); }
@ -276,6 +277,7 @@ private:
private:
bool m_iniExists : 1;
bool m_noCache : 1;
bool m_isService : 1;
bool m_bulkUpdating : 1;
bool m_bulkIniChanged : 1;

View File

@ -1,27 +1,3 @@
#include "servicemanager.h"
#define WIN32_LEAN_AND_MEAN
#include <qt_windows.h>
namespace {
const char *const serviceName = "FortFirewallSvc";
}
ServiceManager::ServiceManager(QObject *parent) : QObject(parent) { }
bool ServiceManager::isServiceInstalled()
{
bool res = false;
const SC_HANDLE scHandle = OpenSCManagerA(nullptr, nullptr, SC_MANAGER_CONNECT);
if (scHandle) {
const SC_HANDLE serviceHandle = OpenServiceA(scHandle, serviceName, SERVICE_INTERROGATE);
if (serviceHandle) {
res = true;
CloseServiceHandle(serviceHandle);
}
CloseServiceHandle(scHandle);
}
return res;
}
#include <fort_version.h>

View File

@ -3,14 +3,9 @@
#include <QObject>
class ServiceManager : public QObject
class ServiceManager
{
Q_OBJECT
public:
explicit ServiceManager(QObject *parent = nullptr);
static bool isServiceInstalled();
};
#endif // SERVICEMANAGER_H

View File

@ -2,6 +2,10 @@
#include <QCoreApplication>
#include <QSettings>
#include <QThread>
#define WIN32_LEAN_AND_MEAN
#include <qt_windows.h>
#include <fort_version.h>
@ -9,11 +13,19 @@
namespace {
const char *const serviceName = "FortFirewallSvc";
const char *const regCurUserRun =
R"(HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run)";
const char *const regAllUsersRun =
R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run)";
QString appFilePath()
{
const auto filePath = QCoreApplication::applicationFilePath().replace('/', '\\');
return QString("\"%1\"").arg(filePath);
}
bool isAutorunForUser(const char *key)
{
const QSettings reg(key, QSettings::Registry64Format);
@ -33,7 +45,7 @@ bool isAutorunForAllUsers()
void setAutorunForUser(const char *key)
{
QSettings reg(key, QSettings::Registry64Format);
reg.setValue(APP_NAME, QString("\"%1\"").arg(QCoreApplication::applicationFilePath()));
reg.setValue(APP_NAME, appFilePath());
}
void setAutorunForCurrentUser()
@ -64,9 +76,65 @@ void removeAutorunForAllUsers()
}
bool StartupUtil::isServiceInstalled()
{
bool res = false;
const SC_HANDLE mngr = OpenSCManagerA(nullptr, nullptr, SC_MANAGER_CONNECT);
if (mngr) {
const SC_HANDLE svc = OpenServiceA(mngr, serviceName, SERVICE_INTERROGATE);
if (svc) {
res = true;
CloseServiceHandle(svc);
}
CloseServiceHandle(mngr);
}
return res;
}
bool StartupUtil::installService()
{
bool res = false;
const SC_HANDLE mngr = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (mngr) {
const auto command = appFilePath() + " --service";
const SC_HANDLE svc = CreateServiceA(mngr, serviceName, APP_NAME, SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
command.toLatin1(), 0, 0, 0, 0, 0);
if (svc) {
res = true;
CloseServiceHandle(svc);
}
CloseServiceHandle(mngr);
}
return res;
}
bool StartupUtil::uninstallService()
{
bool res = false;
const SC_HANDLE mngr = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (mngr) {
const SC_HANDLE svc = OpenServiceA(mngr, serviceName, SERVICE_ALL_ACCESS | DELETE);
if (svc) {
int n = 2; /* count of attempts to stop the service */
do {
SERVICE_STATUS status;
if (QueryServiceStatus(svc, &status) && status.dwCurrentState == SERVICE_STOPPED)
break;
ControlService(svc, SERVICE_CONTROL_STOP, &status);
QThread::msleep(1000);
} while (--n > 0);
res = DeleteService(svc);
CloseServiceHandle(svc);
}
CloseServiceHandle(mngr);
}
return res;
}
StartupUtil::StartupMode StartupUtil::getStartupMode()
{
return ServiceManager::isServiceInstalled()
return isServiceInstalled()
? (isAutorunForAllUsers() ? StartupAllUsers : StartupAllUsersBackground)
: (isAutorunForCurrentUser() ? StartupCurrentUser : StartupDisabled);
}
@ -75,7 +143,7 @@ void StartupUtil::setStartupMode(StartupMode mode)
{
removeAutorunForCurrentUser();
removeAutorunForAllUsers();
// TODO: ServiceManager::uninstallService();
uninstallService();
switch (mode) {
case StartupDisabled:
@ -87,7 +155,7 @@ void StartupUtil::setStartupMode(StartupMode mode)
setAutorunForAllUsers();
Q_FALLTHROUGH();
case StartupAllUsersBackground:
// TODO: ServiceManager::installService();
installService();
break;
}
}

View File

@ -13,6 +13,10 @@ public:
StartupAllUsersBackground
};
static bool isServiceInstalled();
static bool installService();
static bool uninstallService();
static StartupMode getStartupMode();
static void setStartupMode(StartupMode mode);
};