diff --git a/deploy/deployment.json b/deploy/deployment.json index af1d09b8..0894c9d3 100644 --- a/deploy/deployment.json +++ b/deploy/deployment.json @@ -17,6 +17,11 @@ "${ROOT}/src/ui/i18n | *.qm |" ] }, + "${TARGET}/driver": { + "fort": [ + "${ROOT}/src/driver/scripts | *.bat *.lnk |" + ] + }, "${TARGET}/imports": { "common": [ "${QTPATH}/qml/QtQuick.2 | *.dll *.qmltypes qmldir | *d.dll" diff --git a/deploy/setup-deployment.bat b/deploy/setup-deployment.bat index 96495e4d..c2444e1e 100644 --- a/deploy/setup-deployment.bat +++ b/deploy/setup-deployment.bat @@ -6,7 +6,7 @@ md %TARGET_PATH% cd %TARGET_PATH% del /Q /F qt*.* FortFirewall.exe -rd /Q /S i18n imports plugins scripts +rd /Q /S driver\scripts i18n imports plugins scripts cd .. powershell.exe -executionpolicy remotesigned -file setup-deployment.ps1 %TARGET_PATH% %* diff --git a/src/driver/scripts/execute-cmd.bat b/src/driver/scripts/execute-cmd.bat new file mode 100644 index 00000000..8e7e3441 --- /dev/null +++ b/src/driver/scripts/execute-cmd.bat @@ -0,0 +1,11 @@ +@rem Execute the command + +@cd %~dp0 +@echo off + +set "SystemPath=%SystemRoot%\System32" +if defined PROGRAMFILES(X86) ( + if exist %SystemRoot%\Sysnative\* set "SystemPath=%SystemRoot%\Sysnative" +) + +%SystemPath%\cmd.exe /C start /W %1 diff --git a/src/driver/scripts/install.bat b/src/driver/scripts/install.bat new file mode 100644 index 00000000..df46ad04 --- /dev/null +++ b/src/driver/scripts/install.bat @@ -0,0 +1,53 @@ +@rem Install driver + +@set DISPNAME=Fort Firewall + +@set ARCH=32 +@if defined PROGRAMFILES(X86) @set ARCH=64 + +@set BASENAME=fortfw +@set FILENAME=%BASENAME%%ARCH%.sys +@set SRCPATH=%~dp0..\%FILENAME% +@set DSTPATH=%SystemRoot%\System32\drivers\%BASENAME%.sys + + +@rem Copy driver to system storage +@if exist "%DSTPATH%" ( + @echo Error: Driver already installed. Uninstall it first + @set RCODE=1 + @goto EXIT +) + +copy "%SRCPATH%" "%DSTPATH%" +@if ERRORLEVEL 1 ( + @echo Error: Cannot copy driver to system + @set RCODE=%ERRORLEVEL% + @goto EXIT +) + + +@rem Create service +sc create %BASENAME% binPath= "%DSTPATH%" type= kernel start= auto depend= BFE DisplayName= "%DISPNAME%" +@if ERRORLEVEL 1 ( + @echo Error: Cannot create a service + @set RCODE=%ERRORLEVEL% + @goto EXIT +) + +sc start %BASENAME% +@if ERRORLEVEL 1 ( + @echo Error: Cannot start the service + @set RCODE=%ERRORLEVEL% + @goto EXIT +) + + +@set RCODE=0 +@goto EXIT + +:EXIT +@echo End execution... Error Code = %RCODE% +@if %RCODE% neq 0 ( + @pause +) +@exit /b %RCODE% diff --git a/src/driver/scripts/reinstall.bat b/src/driver/scripts/reinstall.bat new file mode 100644 index 00000000..b98ae5cc --- /dev/null +++ b/src/driver/scripts/reinstall.bat @@ -0,0 +1,8 @@ +@rem Re-install driver + +@cd %~dp0 +@echo off + +%COMSPEC% /C uninstall.bat + +install.bat diff --git a/src/driver/scripts/reinstall.lnk b/src/driver/scripts/reinstall.lnk new file mode 100644 index 00000000..0980f99a Binary files /dev/null and b/src/driver/scripts/reinstall.lnk differ diff --git a/src/driver/scripts/uninstall.bat b/src/driver/scripts/uninstall.bat new file mode 100644 index 00000000..62579516 --- /dev/null +++ b/src/driver/scripts/uninstall.bat @@ -0,0 +1,33 @@ +@rem Uninstall driver + +@set DISPNAME=Fort Firewall + +@set BASENAME=fortfw +@set DSTPATH=%SystemRoot%\System32\drivers\%BASENAME%.sys + + +@rem Close the "Services" list window +taskkill /F /IM mmc.exe + +@rem Stop the service +net stop %BASENAME% + +@rem Remove the service +sc delete %BASENAME% +@if ERRORLEVEL 1 ( + @echo Error: Cannot delete the service + @set RCODE=%ERRORLEVEL% + @rem @goto EXIT +) + + +@rem Remove driver from system storage +Del "%DSTPATH%" + + +@set RCODE=0 +@goto EXIT + +:EXIT +@echo End execution... Error Code = %RCODE% +@exit /b %RCODE% diff --git a/src/driver/scripts/uninstall.lnk b/src/driver/scripts/uninstall.lnk new file mode 100644 index 00000000..7023d176 Binary files /dev/null and b/src/driver/scripts/uninstall.lnk differ diff --git a/src/ui/driver/drivermanager.cpp b/src/ui/driver/drivermanager.cpp index d183b785..51cf02b5 100644 --- a/src/ui/driver/drivermanager.cpp +++ b/src/ui/driver/drivermanager.cpp @@ -50,17 +50,23 @@ bool DriverManager::isDeviceOpened() const bool DriverManager::openDevice() { - if (!m_device->open(FortCommon::deviceName())) { + const bool res = m_device->open(FortCommon::deviceName()); + if (!res) { setErrorMessage(OsUtil::lastErrorMessage()); - return false; } - return true; + emit isDeviceOpenedChanged(); + + return res; } bool DriverManager::closeDevice() { - return m_device->close(); + const bool res = m_device->close(); + + emit isDeviceOpenedChanged(); + + return res; } bool DriverManager::validate() @@ -121,12 +127,22 @@ bool DriverManager::writeData(quint32 code, QByteArray &buf, int size) } void DriverManager::reinstallDriver() +{ + executeCommand("reinstall.lnk"); +} + +void DriverManager::uninstallDriver() +{ + executeCommand("uninstall.lnk"); +} + +void DriverManager::executeCommand(const QString &fileName) { const QString binPath = FileUtil::toNativeSeparators( FileUtil::appBinLocation()); const QString cmdPath = qEnvironmentVariable("COMSPEC"); - const QString scriptPath = binPath + "\\driver\\scripts\\reinstall-lnk.bat"; + const QString scriptPath = binPath + "\\driver\\scripts\\execute-cmd.bat"; - QProcess::execute(cmdPath, QStringList() << "/C" << scriptPath); + QProcess::execute(cmdPath, QStringList() << "/C" << scriptPath << fileName); } diff --git a/src/ui/driver/drivermanager.h b/src/ui/driver/drivermanager.h index ee759f21..17088d56 100644 --- a/src/ui/driver/drivermanager.h +++ b/src/ui/driver/drivermanager.h @@ -11,6 +11,7 @@ class DriverManager : public QObject { Q_OBJECT Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged) + Q_PROPERTY(bool isDeviceOpened READ isDeviceOpened NOTIFY isDeviceOpenedChanged) public: explicit DriverManager(QObject *parent = nullptr); @@ -23,9 +24,11 @@ public: bool isDeviceOpened() const; static void reinstallDriver(); + static void uninstallDriver(); signals: void errorMessageChanged(); + void isDeviceOpenedChanged(); public slots: bool openDevice(); @@ -44,6 +47,8 @@ private: bool writeData(quint32 code, QByteArray &buf, int size); + static void executeCommand(const QString &fileName); + private: Device *m_device; DriverWorker *m_driverWorker; diff --git a/src/ui/fort_images.qrc b/src/ui/fort_images.qrc index 1b83e636..5e261092 100644 --- a/src/ui/fort_images.qrc +++ b/src/ui/fort_images.qrc @@ -21,6 +21,9 @@ images/link.png images/page_copy.png images/page_paste.png + images/plugin.png + images/plugin_disabled.png + images/plugin_error.png images/resultset_next.png images/resultset_previous.png images/run.png diff --git a/src/ui/fort_qml.qrc b/src/ui/fort_qml.qrc index a2a6f68c..b9fd7b6f 100644 --- a/src/ui/fort_qml.qrc +++ b/src/ui/fort_qml.qrc @@ -2,6 +2,7 @@ qml/controls/ButtonMenu.qml qml/controls/ButtonPopup.qml + qml/controls/DelayButtonControl.qml qml/controls/HSeparator.qml qml/controls/LabelColorRow.qml qml/controls/LabelSpinRow.qml diff --git a/src/ui/fortmanager.cpp b/src/ui/fortmanager.cpp index 09b208e2..87e9909c 100644 --- a/src/ui/fortmanager.cpp +++ b/src/ui/fortmanager.cpp @@ -62,6 +62,7 @@ FortManager::FortManager(FortSettings *fortSettings, { setupLogger(); setupDatabaseManager(); + setupLogManager(); setupDriver(); @@ -80,6 +81,7 @@ FortManager::~FortManager() removeHotKeys(); closeDriver(); + closeLogManager(); } void FortManager::registerQmlTypes() @@ -119,28 +121,35 @@ void FortManager::registerQmlTypes() qmlRegisterType("com.fortfirewall", 1, 0, "StringUtil"); } +void FortManager::installDriver() +{ + closeDriver(); + + m_driverManager->reinstallDriver(); + + if (setupDriver()) { + updateDriverConf(m_firewallConf); + } +} + +void FortManager::removeDriver() +{ + closeDriver(); + + m_driverManager->uninstallDriver(); +} + bool FortManager::setupDriver() { bool opened = m_driverManager->openDevice(); - // Try to (re)install the driver in portable mode - if (m_fortSettings->isPortable() - && !(opened && m_driverManager->validate())) { - if (opened) { - m_driverManager->closeDevice(); - } + if (!m_driverManager->validate()) { + m_driverManager->closeDevice(); - m_driverManager->reinstallDriver(); - - opened = m_driverManager->openDevice(); + opened = false; } - if (!opened) { - showErrorBox("Setup Driver: " + m_driverManager->errorMessage()); - return false; - } - - return true; + return opened; } void FortManager::closeDriver() @@ -148,6 +157,15 @@ void FortManager::closeDriver() updateLogManager(false); m_driverManager->closeDevice(); +} + +void FortManager::setupLogManager() +{ + m_logManager->initialize(); +} + +void FortManager::closeLogManager() +{ m_logManager->close(); } @@ -169,11 +187,6 @@ void FortManager::setupLogger() updateLogger(); } -void FortManager::setupLogManager() -{ - m_logManager->initialize(); -} - void FortManager::setupTranslationManager() { TranslationManager::instance()->switchLanguageByName( @@ -201,6 +214,7 @@ bool FortManager::setupEngine() QQmlContext *context = m_engine->rootContext(); context->setContextProperty("fortManager", this); + context->setContextProperty("driverManager", m_driverManager); context->setContextProperty("translationManager", TranslationManager::instance()); m_engine->load(QUrl("qrc:/qml/main.qml")); @@ -486,8 +500,6 @@ bool FortManager::updateDriverConf(FirewallConf *conf, bool onlyFlags) if (res) { updateDatabaseManager(conf); - } else { - showErrorBox("Update Driver Conf: " + m_driverManager->errorMessage()); } updateLogManager(true); diff --git a/src/ui/fortmanager.h b/src/ui/fortmanager.h index 00b160e1..adf95b2a 100644 --- a/src/ui/fortmanager.h +++ b/src/ui/fortmanager.h @@ -47,6 +47,9 @@ signals: void firewallConfToEditChanged(); public slots: + void installDriver(); + void removeDriver(); + void launch(); void showTrayIcon(); @@ -90,10 +93,12 @@ private: bool setupDriver(); void closeDriver(); + void setupLogManager(); + void closeLogManager(); + void setupDatabaseManager(); void setupLogger(); - void setupLogManager(); void setupTranslationManager(); diff --git a/src/ui/i18n/i18n_ru.qm b/src/ui/i18n/i18n_ru.qm index 18d2c8be..cadb9c5e 100644 Binary files a/src/ui/i18n/i18n_ru.qm and b/src/ui/i18n/i18n_ru.qm differ diff --git a/src/ui/i18n/i18n_ru.ts b/src/ui/i18n/i18n_ru.ts index 9dc6fb3b..0971555e 100644 --- a/src/ui/i18n/i18n_ru.ts +++ b/src/ui/i18n/i18n_ru.ts @@ -50,42 +50,42 @@ FortManager - + Password input Ввод пароля - + Please enter the password Наберите пароль пожалуйста - + Options Опции - + Traffic Graph График трафика - + Filter Enabled Фильтр включен - + Stop Traffic Остановить трафик - + Stop Internet Traffic Остановить Интернет трафик - + Quit Выйти @@ -371,7 +371,7 @@ Статистика - + Password: Пароль: @@ -396,55 +396,72 @@ Выйти - + Start with Windows Запускать вместе с Windows - + Stop traffic when Fort Firewall is not running Остановить трафик, когда Fort Firewall не запущен - + Filter Enabled Фильтр включен - + Filter Local Addresses Фильтр локальных адресов - + Stop Traffic Остановить трафик - + Stop Internet Traffic Остановить Интернет трафик - + Hot Keys Горячие клавиши - + + Installed Установлен - + + Not Installed Не установлен - + Language: Язык: + + + Driver: + Драйвер: + + + + Install + Установить + + + + Remove + Удалить + Logs diff --git a/src/ui/images/plugin.png b/src/ui/images/plugin.png new file mode 100644 index 00000000..6187b15a Binary files /dev/null and b/src/ui/images/plugin.png differ diff --git a/src/ui/images/plugin_disabled.png b/src/ui/images/plugin_disabled.png new file mode 100644 index 00000000..f4f6be59 Binary files /dev/null and b/src/ui/images/plugin_disabled.png differ diff --git a/src/ui/images/plugin_error.png b/src/ui/images/plugin_error.png new file mode 100644 index 00000000..cff65d7f Binary files /dev/null and b/src/ui/images/plugin_error.png differ diff --git a/src/ui/main.cpp b/src/ui/main.cpp index 39be0d67..71534d48 100644 --- a/src/ui/main.cpp +++ b/src/ui/main.cpp @@ -11,8 +11,7 @@ #include "util/osutil.h" #define FORT_ERROR_INSTANCE 1 -#define FORT_ERROR_DEVICE 2 -#define FORT_ERROR_CONTROL 3 +#define FORT_ERROR_CONTROL 2 int main(int argc, char *argv[]) { @@ -52,14 +51,6 @@ int main(int argc, char *argv[]) } FortManager fortManager(&fortSettings); - - // Error: Cannot open the driver device - if (!fortManager.driverManager()->isDeviceOpened()) { - QMessageBox::critical(nullptr, QString(), - "Cannot open the driver device!"); - return FORT_ERROR_DEVICE; - } - fortManager.launch(); // Process control requests from clients diff --git a/src/ui/qml/controls/DelayButtonControl.qml b/src/ui/qml/controls/DelayButtonControl.qml new file mode 100644 index 00000000..9a6c34da --- /dev/null +++ b/src/ui/qml/controls/DelayButtonControl.qml @@ -0,0 +1,22 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +DelayButton { + + signal delayClicked() + + property bool isActivated: false + + onPressed: { + isActivated = false; + } + onActivated: { + isActivated = true; + } + onReleased: { + if (isActivated) { + delayClicked(); + checked = false; + } + } +} diff --git a/src/ui/qml/pages/OptionsPage.qml b/src/ui/qml/pages/OptionsPage.qml index f7571f9e..9c3d695b 100644 --- a/src/ui/qml/pages/OptionsPage.qml +++ b/src/ui/qml/pages/OptionsPage.qml @@ -36,144 +36,197 @@ BasePage { Frame { anchors.fill: parent - ColumnLayout { + RowLayout { anchors.fill: parent - spacing: 10 - CheckBox { - id: cbStart - text: translationManager.trTrigger - && qsTranslate("qml", "Start with Windows") - checked: fortSettings.startWithWindows - onToggled: setIniEdited() - } - - CheckBox { - text: translationManager.trTrigger - && qsTranslate("qml", "Stop traffic when Fort Firewall is not running") - checked: firewallConf.provBoot - onToggled: { - firewallConf.provBoot = checked; - - setConfFlagsEdited(); - } - } - - Row { - spacing: 20 + ColumnLayout { + Layout.alignment: Qt.AlignTop + spacing: 10 CheckBox { - id: cbFilterEnabled - width: Math.max(implicitWidth, cbStopTraffic.implicitWidth) + id: cbStart text: translationManager.trTrigger - && qsTranslate("qml", "Filter Enabled") - checked: firewallConf.filterEnabled + && qsTranslate("qml", "Start with Windows") + checked: fortSettings.startWithWindows + onToggled: setIniEdited() + } + + CheckBox { + text: translationManager.trTrigger + && qsTranslate("qml", "Stop traffic when Fort Firewall is not running") + checked: firewallConf.provBoot onToggled: { - firewallConf.filterEnabled = checked; + firewallConf.provBoot = checked; setConfFlagsEdited(); } } - CheckBox { - text: translationManager.trTrigger - && qsTranslate("qml", "Filter Local Addresses") - checked: firewallConf.filterLocals - onToggled: { - firewallConf.filterLocals = checked; + Row { + spacing: 20 - setConfFlagsEdited(); + CheckBox { + id: cbFilterEnabled + width: Math.max(implicitWidth, cbStopTraffic.implicitWidth) + text: translationManager.trTrigger + && qsTranslate("qml", "Filter Enabled") + checked: firewallConf.filterEnabled + onToggled: { + firewallConf.filterEnabled = checked; + + setConfFlagsEdited(); + } + } + + CheckBox { + text: translationManager.trTrigger + && qsTranslate("qml", "Filter Local Addresses") + checked: firewallConf.filterLocals + onToggled: { + firewallConf.filterLocals = checked; + + setConfFlagsEdited(); + } } } - } - Row { - spacing: 20 + Row { + spacing: 20 - CheckBox { - id: cbStopTraffic - width: cbFilterEnabled.width - text: translationManager.trTrigger - && qsTranslate("qml", "Stop Traffic") - checked: firewallConf.stopTraffic - onToggled: { - firewallConf.stopTraffic = checked; + CheckBox { + id: cbStopTraffic + width: cbFilterEnabled.width + text: translationManager.trTrigger + && qsTranslate("qml", "Stop Traffic") + checked: firewallConf.stopTraffic + onToggled: { + firewallConf.stopTraffic = checked; - setConfFlagsEdited(); + setConfFlagsEdited(); + } + } + + CheckBox { + text: translationManager.trTrigger + && qsTranslate("qml", "Stop Internet Traffic") + checked: firewallConf.stopInetTraffic + onToggled: { + firewallConf.stopInetTraffic = checked; + + setConfFlagsEdited(); + } } } CheckBox { + id: cbHotKeys text: translationManager.trTrigger - && qsTranslate("qml", "Stop Internet Traffic") - checked: firewallConf.stopInetTraffic - onToggled: { - firewallConf.stopInetTraffic = checked; + && qsTranslate("qml", "Hot Keys") + checked: fortSettings.hotKeyEnabled + onToggled: setIniEdited() + } - setConfFlagsEdited(); + Row { + spacing: 4 + + CheckBox { + id: cbPassword + text: translationManager.trTrigger + && qsTranslate("qml", "Password:") + checked: firewallConf.hasPassword + onToggled: { + if (!checked) { + firewallConf.passwordHash = + editPassword.text = ""; + } else { + editPassword.forceActiveFocus(); + } + + setConfEdited(); + } + } + TextFieldFrame { + id: editPassword + width: 180 + echoMode: TextInput.Password + passwordMaskDelay: 300 + readOnly: firewallConf.hasPassword || !cbPassword.checked + placeholderText: translationManager.trTrigger + && (firewallConf.hasPassword + ? qsTranslate("qml", "Installed") + : qsTranslate("qml", "Not Installed")) + } + } + + Row { + spacing: 4 + + Label { + anchors.verticalCenter: parent.verticalCenter + text: translationManager.trTrigger + && qsTranslate("qml", "Language:") + } + ComboBox { + width: Math.max(implicitWidth, 180) + flat: true + currentIndex: translationManager.language + model: translationManager.naturalLabels + onActivated: fortManager.setLanguage(index) } } } - CheckBox { - id: cbHotKeys - text: translationManager.trTrigger - && qsTranslate("qml", "Hot Keys") - checked: fortSettings.hotKeyEnabled - onToggled: setIniEdited() - } + ColumnLayout { + Layout.alignment: Qt.AlignTop + spacing: 10 - Row { - spacing: 4 + Frame { + Layout.alignment: Qt.AlignHCenter - CheckBox { - id: cbPassword - text: translationManager.trTrigger - && qsTranslate("qml", "Password:") - checked: firewallConf.hasPassword - onToggled: { - if (!checked) { - firewallConf.passwordHash = - editPassword.text = ""; - } else { - editPassword.forceActiveFocus(); + ColumnLayout { + spacing: 10 + + Row { + Layout.alignment: Qt.AlignHCenter + spacing: 5 + Image { + source: driverManager.isDeviceOpened + ? (!driverManager.errorMessage + ? "qrc:/images/plugin.png" + : "qrc:/images/plugin_error.png") + : "qrc:/images/plugin_disabled.png" + } + Label { + text: translationManager.trTrigger + && qsTranslate("qml", "Driver:") + } + Label { + width: Math.min(implicitWidth, 300) + wrapMode: Text.Wrap + text: translationManager.trTrigger + && (driverManager.isDeviceOpened + ? (driverManager.errorMessage + || qsTranslate("qml", "Installed")) + : qsTranslate("qml", "Not Installed")) + } } - setConfEdited(); + Row { + Layout.alignment: Qt.AlignHCenter + spacing: 10 + DelayButtonControl { + text: translationManager.trTrigger + && qsTranslate("qml", "Install") + onDelayClicked: fortManager.installDriver() + } + DelayButtonControl { + text: translationManager.trTrigger + && qsTranslate("qml", "Remove") + onDelayClicked: fortManager.removeDriver() + } + } } } - TextFieldFrame { - id: editPassword - width: 180 - echoMode: TextInput.Password - passwordMaskDelay: 300 - readOnly: firewallConf.hasPassword || !cbPassword.checked - placeholderText: translationManager.trTrigger - && (firewallConf.hasPassword - ? qsTranslate("qml", "Installed") - : qsTranslate("qml", "Not Installed")) - } - } - - Row { - spacing: 4 - - Label { - anchors.verticalCenter: parent.verticalCenter - text: translationManager.trTrigger - && qsTranslate("qml", "Language:") - } - ComboBox { - width: Math.max(implicitWidth, 180) - flat: true - currentIndex: translationManager.language - model: translationManager.naturalLabels - onActivated: fortManager.setLanguage(index) - } - } - - Item { - Layout.fillHeight: true } } }