mirror of
https://github.com/tnodir/fort
synced 2024-11-15 05:46:03 +00:00
Move "Windows Explorer integration" from Installer to UI.
This commit is contained in:
parent
a70a4d195f
commit
e5b9388bdc
@ -49,7 +49,6 @@ Name: pt; MessagesFile: "compiler:Languages\Portuguese.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; Flags: unchecked
|
||||
Name: "explorer"; Description: "File Explorer integration"; Flags: unchecked
|
||||
Name: "portable"; Description: "Portable"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
@ -57,16 +56,6 @@ Source: "build\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createa
|
||||
Source: "{#APP_EXE_NAME}.example.ini"; DestDir: "{app}"
|
||||
Source: "README.portable"; DestDir: "{app}"; Tasks: portable
|
||||
|
||||
[Registry]
|
||||
; Explorer's Context Menu
|
||||
#define REG_SHELL "SystemFileAssociations\.exe\Shell"
|
||||
#define REG_SHELL_MENU REG_SHELL + "\Fort Firewall"
|
||||
Root: HKCR; Subkey: "{#REG_SHELL}"; Flags: uninsdeletekeyifempty; Tasks: explorer
|
||||
Root: HKCR; Subkey: "{#REG_SHELL_MENU}"; Flags: deletekey uninsdeletekey
|
||||
Root: HKCR; Subkey: "{#REG_SHELL_MENU}"; ValueType: string; ValueName: "icon"; ValueData: "{#APP_EXE}"; Tasks: explorer
|
||||
Root: HKCR; Subkey: "{#REG_SHELL_MENU}"; ValueType: string; ValueName: "MUIVerb"; ValueData: "Fort Firewall ..."; Tasks: explorer
|
||||
Root: HKCR; Subkey: "{#REG_SHELL_MENU}\command"; ValueType: string; ValueData: """{#APP_EXE}"" -w -c prog add ""%1"""; Tasks: explorer
|
||||
|
||||
[Icons]
|
||||
; Start menu shortcut
|
||||
Name: "{group}\{#APP_NAME}"; Filename: "{#APP_EXE}"; WorkingDir: "{app}"; Parameters: "--lang {code:LanguageName}"
|
||||
|
@ -129,6 +129,7 @@ SOURCES += \
|
||||
util/net/netutil.cpp \
|
||||
util/osutil.cpp \
|
||||
util/processinfo.cpp \
|
||||
util/regkey.cpp \
|
||||
util/serviceworker.cpp \
|
||||
util/startuputil.cpp \
|
||||
util/stringutil.cpp \
|
||||
@ -265,6 +266,7 @@ HEADERS += \
|
||||
util/net/netutil.h \
|
||||
util/osutil.h \
|
||||
util/processinfo.h \
|
||||
util/regkey.h \
|
||||
util/serviceworker.h \
|
||||
util/startuputil.h \
|
||||
util/stringutil.h \
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "../optionscontroller.h"
|
||||
|
||||
OptionsPage::OptionsPage(OptionsController *ctrl, QWidget *parent) :
|
||||
BasePage(ctrl, parent), m_iniEdited(false), m_currentStartMode(0)
|
||||
BasePage(ctrl, parent), m_iniEdited(false), m_currentStartMode(0), m_explorerIntegrated(false)
|
||||
{
|
||||
setupUi();
|
||||
}
|
||||
@ -50,6 +50,7 @@ void OptionsPage::onEditResetted()
|
||||
void OptionsPage::onSaved()
|
||||
{
|
||||
saveStartMode();
|
||||
saveExplorerIntegration();
|
||||
|
||||
if (iniEdited()) {
|
||||
saveIni();
|
||||
@ -72,6 +73,14 @@ void OptionsPage::saveStartMode()
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsPage::saveExplorerIntegration()
|
||||
{
|
||||
if (m_explorerIntegrated != m_cbExplorerMenu->isChecked()) {
|
||||
m_explorerIntegrated = m_cbExplorerMenu->isChecked();
|
||||
StartupUtil::integrateExplorer(m_explorerIntegrated);
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsPage::saveIni()
|
||||
{
|
||||
settings()->setHotKeyEnabled(m_cbHotKeys->isChecked());
|
||||
@ -110,6 +119,8 @@ void OptionsPage::onRetranslateUi()
|
||||
m_cbStopTraffic->setText(tr("Stop Traffic"));
|
||||
m_cbStopInetTraffic->setText(tr("Stop Internet Traffic"));
|
||||
m_cbAllowAllNew->setText(tr("Auto-Allow New Programs"));
|
||||
|
||||
m_cbExplorerMenu->setText(tr("Windows Explorer integration"));
|
||||
m_cbHotKeys->setText(tr("Hot Keys"));
|
||||
|
||||
m_cbPassword->setText(tr("Password:"));
|
||||
@ -290,6 +301,11 @@ void OptionsPage::setupTrafficBox()
|
||||
|
||||
void OptionsPage::setupGlobalBox()
|
||||
{
|
||||
m_explorerIntegrated = StartupUtil::isExplorerIntegrated();
|
||||
m_cbExplorerMenu = ControlUtil::createCheckBox(
|
||||
m_explorerIntegrated, [&](int) { ctrl()->setOthersEdited(true); });
|
||||
m_cbExplorerMenu->setEnabled(OsUtil::isUserAdmin());
|
||||
|
||||
m_cbHotKeys = ControlUtil::createCheckBox(
|
||||
settings()->hotKeyEnabled(), [&](bool) { setIniEdited(true); });
|
||||
|
||||
@ -300,6 +316,7 @@ void OptionsPage::setupGlobalBox()
|
||||
auto langLayout = setupLangLayout();
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addWidget(m_cbExplorerMenu);
|
||||
layout->addWidget(m_cbHotKeys);
|
||||
layout->addLayout(passwordLayout);
|
||||
layout->addWidget(m_btPasswordLock, 0, Qt::AlignCenter);
|
||||
|
@ -21,6 +21,7 @@ protected slots:
|
||||
|
||||
private:
|
||||
void saveStartMode();
|
||||
void saveExplorerIntegration();
|
||||
void saveIni();
|
||||
|
||||
void retranslateComboStartMode();
|
||||
@ -47,6 +48,7 @@ private:
|
||||
private:
|
||||
uint m_iniEdited : 1;
|
||||
uint m_currentStartMode : 4;
|
||||
uint m_explorerIntegrated : 1;
|
||||
|
||||
QGroupBox *m_gbStartup = nullptr;
|
||||
QGroupBox *m_gbTraffic = nullptr;
|
||||
@ -62,6 +64,7 @@ private:
|
||||
QCheckBox *m_cbStopTraffic = nullptr;
|
||||
QCheckBox *m_cbStopInetTraffic = nullptr;
|
||||
QCheckBox *m_cbAllowAllNew = nullptr;
|
||||
QCheckBox *m_cbExplorerMenu = nullptr;
|
||||
QCheckBox *m_cbHotKeys = nullptr;
|
||||
QCheckBox *m_cbPassword = nullptr;
|
||||
QLineEdit *m_editPassword = nullptr;
|
||||
|
@ -30,10 +30,11 @@ static void setupAppStyle()
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Uninstall: Unregister booted provider, startup entries and exit
|
||||
// Uninstall
|
||||
if (argc > 1 && !strcmp(argv[1], "-u")) {
|
||||
StartupUtil::setStartupMode(StartupUtil::StartupDisabled);
|
||||
DriverCommon::provUnregister();
|
||||
StartupUtil::setStartupMode(StartupUtil::StartupDisabled); // Remove auto-run and service
|
||||
StartupUtil::integrateExplorer(false); // Remove Windows Explorer integration
|
||||
DriverCommon::provUnregister(); // Unregister booted provider
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
103
src/ui/util/regkey.cpp
Normal file
103
src/ui/util/regkey.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "regkey.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <qt_windows.h>
|
||||
|
||||
#define PREDEFINED_BASE_HANDLE quint32(HKEY_CLASSES_ROOT)
|
||||
|
||||
RegKey::RegKey(quint32 parentHandle, const QString &subKey, quint32 flags)
|
||||
{
|
||||
LPCWSTR subKeyStr = (LPCWSTR) subKey.utf16();
|
||||
const REGSAM samDesired = ((flags & ReadOnly) != 0 ? KEY_READ : KEY_ALL_ACCESS)
|
||||
| ((flags & Native64Key) != 0 ? KEY_WOW64_64KEY : 0)
|
||||
| ((flags & Native32Key) != 0 ? KEY_WOW64_32KEY : 0);
|
||||
|
||||
if ((flags & Create) != 0) {
|
||||
DWORD disposition;
|
||||
RegCreateKeyEx((HKEY) parentHandle, subKeyStr, 0, nullptr, 0, samDesired, nullptr,
|
||||
(PHKEY) &m_handle, &disposition);
|
||||
} else {
|
||||
RegOpenKeyEx((HKEY) parentHandle, subKeyStr, 0, samDesired, (PHKEY) &m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
RegKey::RegKey(Root root, const QString &subKey, quint32 flags) :
|
||||
RegKey(PREDEFINED_BASE_HANDLE + root, subKey, flags)
|
||||
{
|
||||
}
|
||||
|
||||
RegKey::RegKey(const RegKey &parent, const QString &subKey, quint32 flags) :
|
||||
RegKey(parent.handle(), subKey, flags)
|
||||
{
|
||||
}
|
||||
|
||||
RegKey::~RegKey()
|
||||
{
|
||||
if (!isNull() && handle() < PREDEFINED_BASE_HANDLE) {
|
||||
RegCloseKey((HKEY) handle());
|
||||
}
|
||||
}
|
||||
|
||||
bool RegKey::removeKey(const QString &subKey)
|
||||
{
|
||||
return !RegDeleteKey((HKEY) handle(), (LPCWSTR) subKey.utf16());
|
||||
}
|
||||
|
||||
bool RegKey::clearTree(const QString &subKey)
|
||||
{
|
||||
return !RegDeleteTree((HKEY) handle(), subKey.isEmpty() ? nullptr : (LPCWSTR) subKey.utf16());
|
||||
}
|
||||
|
||||
bool RegKey::removeRecursively(const QString &subKey)
|
||||
{
|
||||
return clearTree(subKey) && removeKey(subKey);
|
||||
}
|
||||
|
||||
bool RegKey::removeValue(const QString &name)
|
||||
{
|
||||
return !RegDeleteValue((HKEY) handle(), (LPCWSTR) name.utf16());
|
||||
}
|
||||
|
||||
bool RegKey::setValue(const QString &name, const QVariant &value)
|
||||
{
|
||||
QString text;
|
||||
union {
|
||||
qint64 i64;
|
||||
qint32 i32;
|
||||
} num;
|
||||
const unsigned char *data = nullptr;
|
||||
DWORD size = 0, type = REG_SZ;
|
||||
|
||||
switch (value.userType()) {
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
case QMetaType::Nullptr:
|
||||
break;
|
||||
case QMetaType::Bool:
|
||||
case QMetaType::Int:
|
||||
case QMetaType::UInt:
|
||||
num.i32 = value.toInt();
|
||||
data = (const unsigned char *) &num.i32;
|
||||
size = sizeof(qint32);
|
||||
type = REG_DWORD;
|
||||
break;
|
||||
case QMetaType::LongLong:
|
||||
case QMetaType::ULongLong:
|
||||
num.i64 = value.toLongLong();
|
||||
data = (const unsigned char *) &num.i64;
|
||||
size = sizeof(qint64);
|
||||
type = REG_QWORD;
|
||||
break;
|
||||
default:
|
||||
text = value.toString();
|
||||
data = (const unsigned char *) text.utf16();
|
||||
size = sizeof(wchar_t) * (text.size() + 1); /* + terminating null character */
|
||||
}
|
||||
|
||||
return !RegSetValueEx((HKEY) handle(), (LPCWSTR) name.utf16(), 0, type, data, size);
|
||||
}
|
||||
|
||||
bool RegKey::contains(const QString &name) const
|
||||
{
|
||||
return !RegQueryValueEx((HKEY) handle(), (LPCWSTR) name.utf16(), 0, nullptr, nullptr, nullptr);
|
||||
}
|
52
src/ui/util/regkey.h
Normal file
52
src/ui/util/regkey.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef REGKEY_H
|
||||
#define REGKEY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
#include "../util/classhelpers.h"
|
||||
|
||||
class RegKey
|
||||
{
|
||||
public:
|
||||
enum Root : qint8 { HKCR = 0, HKCU, HKLM, HKU };
|
||||
|
||||
enum OpenFlag : qint8 {
|
||||
ReadOnly = 0x01,
|
||||
ReadWrite = 0x02,
|
||||
Create = 0x04,
|
||||
Native64Key = 0x10,
|
||||
Native32Key = 0x20,
|
||||
DefaultReadOnly = (ReadOnly | Native64Key),
|
||||
DefaultReadWrite = (ReadWrite | Native64Key),
|
||||
DefaultCreate = (ReadWrite | Create | Native64Key)
|
||||
};
|
||||
|
||||
protected:
|
||||
explicit RegKey(quint32 parentHandle, const QString &subKey, quint32 flags);
|
||||
|
||||
public:
|
||||
explicit RegKey(Root root, const QString &subKey = QString(), quint32 flags = DefaultReadOnly);
|
||||
explicit RegKey(const RegKey &parent, const QString &subKey = QString(),
|
||||
quint32 flags = DefaultReadOnly);
|
||||
~RegKey();
|
||||
CLASS_DELETE_COPY_MOVE(RegKey)
|
||||
|
||||
bool isNull() const { return m_handle == 0; }
|
||||
|
||||
bool removeKey(const QString &subKey);
|
||||
bool clearTree(const QString &subKey = QString());
|
||||
bool removeRecursively(const QString &subKey);
|
||||
bool removeValue(const QString &name);
|
||||
bool setValue(const QString &name, const QVariant &value);
|
||||
bool setDefaultValue(const QVariant &value) { return setValue(QString(), value); }
|
||||
bool contains(const QString &name) const;
|
||||
|
||||
protected:
|
||||
quint32 handle() const { return m_handle; }
|
||||
|
||||
private:
|
||||
quint32 m_handle = 0;
|
||||
};
|
||||
|
||||
#endif // REGKEY_H
|
@ -10,13 +10,18 @@
|
||||
#include <fort_version.h>
|
||||
|
||||
#include "fileutil.h"
|
||||
#include "regkey.h"
|
||||
|
||||
namespace {
|
||||
|
||||
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)";
|
||||
constexpr RegKey::Root regCurUserRoot = RegKey::HKCU;
|
||||
const char *const regCurUserRun = R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Run)";
|
||||
|
||||
constexpr RegKey::Root regAllUsersRoot = RegKey::HKLM;
|
||||
const char *const regAllUsersRun = R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Run)";
|
||||
|
||||
constexpr RegKey::Root regShellRoot = RegKey::HKLM;
|
||||
const char *const regShellMenu = R"(SOFTWARE\Classes\SystemFileAssociations\.exe\Shell)";
|
||||
|
||||
QString startupShortcutPath()
|
||||
{
|
||||
@ -26,56 +31,56 @@ QString startupShortcutPath()
|
||||
|
||||
QString wrappedAppFilePath()
|
||||
{
|
||||
const auto filePath = QCoreApplication::applicationFilePath().replace('/', '\\');
|
||||
const auto filePath = FileUtil::toNativeSeparators(QCoreApplication::applicationFilePath());
|
||||
return QString("\"%1\"").arg(filePath);
|
||||
}
|
||||
|
||||
bool isAutorunForUser(const char *key)
|
||||
bool isAutorunForUser(RegKey::Root root, const char *key)
|
||||
{
|
||||
const QSettings reg(key, QSettings::Registry64Format);
|
||||
return !reg.value(APP_NAME).isNull();
|
||||
const RegKey reg(root, key, RegKey::DefaultReadOnly);
|
||||
return reg.contains(APP_NAME);
|
||||
}
|
||||
|
||||
bool isAutorunForCurrentUser()
|
||||
{
|
||||
return isAutorunForUser(regCurUserRun);
|
||||
return isAutorunForUser(regCurUserRoot, regCurUserRun);
|
||||
}
|
||||
|
||||
bool isAutorunForAllUsers()
|
||||
{
|
||||
return isAutorunForUser(regAllUsersRun);
|
||||
return isAutorunForUser(regAllUsersRoot, regAllUsersRun);
|
||||
}
|
||||
|
||||
void setAutorunForUser(const char *key, const QString &command)
|
||||
void setAutorunForUser(RegKey::Root root, const char *key, const QString &command)
|
||||
{
|
||||
QSettings reg(key, QSettings::Registry64Format);
|
||||
RegKey reg(root, key, RegKey::DefaultReadWrite);
|
||||
reg.setValue(APP_NAME, command);
|
||||
}
|
||||
|
||||
void setAutorunForCurrentUser(const QString &command)
|
||||
{
|
||||
setAutorunForUser(regCurUserRun, command);
|
||||
setAutorunForUser(regCurUserRoot, regCurUserRun, command);
|
||||
}
|
||||
|
||||
void setAutorunForAllUsers(const QString &command)
|
||||
{
|
||||
setAutorunForUser(regAllUsersRun, command);
|
||||
setAutorunForUser(regAllUsersRoot, regAllUsersRun, command);
|
||||
}
|
||||
|
||||
void removeAutorunForUser(const char *key)
|
||||
void removeAutorunForUser(RegKey::Root root, const char *key)
|
||||
{
|
||||
QSettings reg(key, QSettings::Registry64Format);
|
||||
reg.remove(APP_NAME);
|
||||
RegKey reg(root, key, RegKey::DefaultReadWrite);
|
||||
reg.removeValue(APP_NAME);
|
||||
}
|
||||
|
||||
void removeAutorunForCurrentUser()
|
||||
{
|
||||
removeAutorunForUser(regCurUserRun);
|
||||
removeAutorunForUser(regCurUserRoot, regCurUserRun);
|
||||
}
|
||||
|
||||
void removeAutorunForAllUsers()
|
||||
{
|
||||
removeAutorunForUser(regAllUsersRun);
|
||||
removeAutorunForUser(regAllUsersRoot, regAllUsersRun);
|
||||
}
|
||||
|
||||
bool installService(
|
||||
@ -194,3 +199,27 @@ bool StartupUtil::isServiceMode(int mode)
|
||||
{
|
||||
return mode == StartupAllUsers || mode == StartupAllUsersBackground;
|
||||
}
|
||||
|
||||
bool StartupUtil::isExplorerIntegrated()
|
||||
{
|
||||
const RegKey regShell(regShellRoot, regShellMenu, RegKey::DefaultReadOnly);
|
||||
const RegKey reg(regShell, APP_NAME, RegKey::DefaultReadOnly);
|
||||
return !reg.isNull();
|
||||
}
|
||||
|
||||
void StartupUtil::integrateExplorer(bool integrate)
|
||||
{
|
||||
RegKey regShell(regShellRoot, regShellMenu, RegKey::DefaultReadWrite);
|
||||
if (integrate) {
|
||||
const QString wrappedPath = wrappedAppFilePath();
|
||||
|
||||
RegKey reg(regShell, APP_NAME, RegKey::DefaultCreate);
|
||||
reg.setValue("icon", wrappedPath);
|
||||
reg.setValue("MUIVerb", APP_NAME + QLatin1String(" ..."));
|
||||
|
||||
RegKey regCommand(reg, "command", RegKey::DefaultCreate);
|
||||
regCommand.setDefaultValue(wrappedPath + " -w -c prog add \"%1\"");
|
||||
} else {
|
||||
regShell.removeRecursively(APP_NAME);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ public:
|
||||
static void setStartupMode(int mode, const QString &defaultLanguage = QString());
|
||||
|
||||
static bool isServiceMode(int mode);
|
||||
|
||||
static bool isExplorerIntegrated();
|
||||
static void integrateExplorer(bool integrate);
|
||||
};
|
||||
|
||||
#endif // STARTUPUTIL_H
|
||||
|
Loading…
Reference in New Issue
Block a user