Skip to content

Commit

Permalink
[feature] Support for suspending (pausing) the game process; support …
Browse files Browse the repository at this point in the history
…applying firewall rules to both inbound and outbound at the same time
  • Loading branch information
SkyD666 committed Sep 20, 2024
1 parent 6976bb0 commit c9bfb78
Show file tree
Hide file tree
Showing 20 changed files with 754 additions and 92 deletions.
3 changes: 2 additions & 1 deletion EliteSpeedrunTool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ set(PROJECT_SOURCES
AcknowledgementDialog.h AcknowledgementDialog.cpp AcknowledgementDialog.ui
LogUtil.h LogUtil.cpp
LanguageUtil.h LanguageUtil.cpp
memoryutil/MemoryUtil.h memoryutil/MemoryUtil.cpp
HttpServerUtil.h HttpServerUtil.cpp
DisplayInfoSubFunction.h DisplayInfoSubFunction.cpp
DiscordUtil.h DiscordUtil.cpp
TimeUtil.h TimeUtil.cpp
SuspendUtil.h SuspendUtil.cpp
NumberUtil.h NumberUtil.cpp
resource.qrc
)

Expand Down
100 changes: 74 additions & 26 deletions EliteSpeedrunTool/FirewallUtil.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#include "FirewallUtil.h"
#include "GlobalData.h"
#include "NumberUtil.h"

bool FirewallUtil::inited = false;
bool FirewallUtil::isEnabled = false;
HRESULT FirewallUtil::hrComInit = S_OK;
INetFwPolicy2* FirewallUtil::pNetFwPolicy2 = nullptr;
long FirewallUtil::CurrentProfilesBitMask = 0;
INetFwRules* FirewallUtil::pFwRules = nullptr;
BSTR FirewallUtil::bstrRuleName;
BSTR FirewallUtil::bstrRuleInName;
BSTR FirewallUtil::bstrRuleOutName;
BSTR FirewallUtil::bstrRuleLPorts;
BSTR FirewallUtil::bstrRuleGroup;

Expand Down Expand Up @@ -95,7 +97,7 @@ HRESULT WFCOMInitialize(INetFwPolicy2** ppNetFwPolicy2)
return hr;
}

INetFwRule* FirewallUtil::getNetFwRule()
INetFwRule* FirewallUtil::getNetFwRule(NET_FW_RULE_DIRECTION direction)
{
if (!inited)
return nullptr;
Expand All @@ -104,7 +106,7 @@ INetFwRule* FirewallUtil::getNetFwRule()

INetFwRule* pFwRule = NULL;

hr = pFwRules->Item(bstrRuleName, (INetFwRule**)&pFwRule);
hr = pFwRules->Item(direction == NET_FW_RULE_DIR_IN ? bstrRuleInName : bstrRuleOutName, (INetFwRule**)&pFwRule);
if (SUCCEEDED(hr)) {
qInfo("Found NetFwRule by pFwRules->Item()");
HRESULT h, h2;
Expand All @@ -117,7 +119,7 @@ INetFwRule* FirewallUtil::getNetFwRule()
.toStdWString()
.c_str()));
}
h2 = pFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION>(globalData->firewallDirection()));
h2 = pFwRule->put_Direction(direction);
if (!SUCCEEDED(h)) {
qCritical("put_ApplicationName failed! (%ld)", h);
} else if (!SUCCEEDED(h2)) {
Expand All @@ -140,18 +142,18 @@ INetFwRule* FirewallUtil::getNetFwRule()
}

// Populate the Firewall Rule object
pFwRule->put_Name(bstrRuleName);
pFwRule->put_Name(direction == NET_FW_RULE_DIR_IN ? bstrRuleInName : bstrRuleOutName);
if (!globalData->firewallAppPath().isEmpty()) {
pFwRule->put_ApplicationName(SysAllocString(
QString(globalData->firewallAppPath())
.replace("/", "\\")
.toStdWString()
.c_str()));
}
pFwRule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
// pFwRule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
// pFwRule->put_LocalPorts(bstrRuleLPorts);
pFwRule->put_Grouping(bstrRuleGroup);
pFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION>(globalData->firewallDirection()));
pFwRule->put_Direction(direction);
// pFwRule->put_Profiles(CurrentProfilesBitMask);
pFwRule->put_Action(NET_FW_ACTION_BLOCK);
pFwRule->put_Enabled(VARIANT_TRUE);
Expand All @@ -173,11 +175,19 @@ INetFwRule* FirewallUtil::getNetFwRule()
return nullptr;
}

bool FirewallUtil::setNetFwRuleEnabled(bool enabled)
QList<INetFwRule*> FirewallUtil::getNetFwRule()
{
int dir = globalData->firewallDirection();
if (dir == 0) {
return { getNetFwRule(NET_FW_RULE_DIR_IN), getNetFwRule(NET_FW_RULE_DIR_OUT) };
} else {
return { getNetFwRule(static_cast<NET_FW_RULE_DIRECTION_>(dir)) };
}
}

bool FirewallUtil::setNetFwRuleEnabled(bool enabled, NET_FW_RULE_DIRECTION direction)
{
if (enabled == isEnabled)
return true;
INetFwRule* fwRule = getNetFwRule();
INetFwRule* fwRule = getNetFwRule(direction);
if (!fwRule) {
qCritical("getNetFwRule() return null!");
qCritical("Firewall operate failed!");
Expand All @@ -189,7 +199,6 @@ bool FirewallUtil::setNetFwRuleEnabled(bool enabled)
qCritical("Firewall operate failed!");
return false;
}
isEnabled = enabled;

if (enabled) {
qInfo("Firewall successfully enabled!");
Expand All @@ -199,14 +208,36 @@ bool FirewallUtil::setNetFwRuleEnabled(bool enabled)
return true;
}

bool FirewallUtil::setNetFwRuleEnabled(bool enabled)
{
int dir = globalData->firewallDirection();
if (dir == 0) {
bool in = setNetFwRuleEnabled(enabled, NET_FW_RULE_DIR_IN);
bool out = setNetFwRuleEnabled(enabled, NET_FW_RULE_DIR_OUT);
if (in && out) {
isEnabled = enabled;
} else {
setNetFwRuleEnabled(!enabled, NET_FW_RULE_DIR_IN);
setNetFwRuleEnabled(!enabled, NET_FW_RULE_DIR_OUT);
isEnabled = !enabled;
}
return in && out;
} else {
bool result = setNetFwRuleEnabled(enabled, static_cast<NET_FW_RULE_DIRECTION_>(dir));
isEnabled = result ? enabled : !enabled;
return result;
}
}

void FirewallUtil::init()
{
if (inited)
return;

qInfo("Initializing the firewall...");
hrComInit = S_OK;
bstrRuleName = SysAllocString(L"AutoFirewall");
bstrRuleInName = SysAllocString(L"AutoFirewallIn");
bstrRuleOutName = SysAllocString(L"AutoFirewallOut");
// bstrRuleLPorts = SysAllocString(L"80");
bstrRuleGroup = SysAllocString(L"AutoFirewall");

Expand Down Expand Up @@ -250,13 +281,27 @@ void FirewallUtil::init()
return;
}

auto fwRule = getNetFwRule();
if (fwRule) {
VARIANT_BOOL enabled;
fwRule->get_Enabled(&enabled);
isEnabled = (enabled == VARIANT_TRUE);
QList<INetFwRule*> fwRules = getNetFwRule();
int allEnabled = 0;
for (auto rule : fwRules) {
if (rule) {
VARIANT_BOOL enabled;
rule->get_Enabled(&enabled);
allEnabled = (allEnabled << 1) | (enabled == VARIANT_TRUE);
} else {
qInfo("auto fwRule = getNetFwRule(); fwRule is null");
}
}
if (allEnabled == 0) {
isEnabled = false;
} else {
qInfo("auto fwRule = getNetFwRule(); fwRule is null");
if (fwRules.size() == NumberUtil::bitCount(allEnabled)) {
isEnabled = true;
} else {
qCritical("Not all firewall rules have same enabled");
setNetFwRuleEnabled(false);
isEnabled = false;
}
}

inited = true;
Expand All @@ -270,15 +315,18 @@ void FirewallUtil::release()
return;

// Free BSTR's
SysFreeString(bstrRuleName);
SysFreeString(bstrRuleInName);
SysFreeString(bstrRuleOutName);
SysFreeString(bstrRuleLPorts);

INetFwRule* fwRule = getNetFwRule();
if (fwRule != NULL) {
BSTR name = nullptr;
fwRule->get_Name(&name);
pFwRules->Remove(name);
fwRule->Release();
QList<INetFwRule*> fwRules = getNetFwRule();
for (auto rule : fwRules) {
if (rule) {
BSTR name = nullptr;
rule->get_Name(&name);
pFwRules->Remove(name);
rule->Release();
}
}

// Release the INetFwRules object
Expand Down
11 changes: 9 additions & 2 deletions EliteSpeedrunTool/FirewallUtil.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <QList>
#include <netfw.h>
#include <windows.h>

Expand All @@ -9,7 +10,7 @@ class FirewallUtil {

static bool firewallIsEnabled(long& enabledTypes);

static INetFwRule* getNetFwRule();
static QList<INetFwRule*> getNetFwRule();

static bool setNetFwRuleEnabled(bool enabled);

Expand All @@ -19,6 +20,11 @@ class FirewallUtil {

static bool getIsEnabled();

private:
static INetFwRule* getNetFwRule(NET_FW_RULE_DIRECTION direction);

static bool setNetFwRuleEnabled(bool enabled, NET_FW_RULE_DIRECTION direction);

private:
static bool inited;

Expand All @@ -32,7 +38,8 @@ class FirewallUtil {

static INetFwRules* pFwRules;

static BSTR bstrRuleName;
static BSTR bstrRuleInName;
static BSTR bstrRuleOutName;

static BSTR bstrRuleLPorts;

Expand Down
36 changes: 36 additions & 0 deletions EliteSpeedrunTool/GlobalData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ void GlobalData::readSettings()
setDiscordShowRichPresence(settings.value("DiscordShowRichPresence", mDiscordShowRichPresence).toBool());
settings.endGroup();

settings.beginGroup("SuspendProcess");
setSuspendAndResumeHotkey(settings.value("SuspendAndResumeHotkey", mSuspendAndResumeHotkey).toString());
setSuspendAndResumeDuration(settings.value("SuspendAndResumeDuration", mSuspendAndResumeDuration).toInt());
settings.endGroup();

settings.beginGroup("CloseGame");
setCloseGameImmediatelyHotkey(settings.value("CloseGameImmediatelyHotkey", mCloseGameImmediatelyHotkey).toString());
settings.endGroup();
Expand Down Expand Up @@ -259,6 +264,11 @@ void GlobalData::writeSettings()
settings.setValue("DiscordShowRichPresence", mDiscordShowRichPresence);
settings.endGroup();

settings.beginGroup("SuspendProcess");
settings.setValue("SuspendAndResumeHotkey", mSuspendAndResumeHotkey);
settings.setValue("SuspendAndResumeDuration", mSuspendAndResumeDuration);
settings.endGroup();

settings.beginGroup("CloseGame");
settings.setValue("CloseGameImmediatelyHotkey", mCloseGameImmediatelyHotkey);
settings.endGroup();
Expand Down Expand Up @@ -789,3 +799,29 @@ void GlobalData::setDisplayInfoToolWindow(bool newDisplayInfoToolWindow)
mDisplayInfoToolWindow = newDisplayInfoToolWindow;
emit displayInfoToolWindowChanged();
}

QString GlobalData::suspendAndResumeHotkey() const
{
return mSuspendAndResumeHotkey;
}

void GlobalData::setSuspendAndResumeHotkey(const QString& newSuspendAndResumeHotkey)
{
if (mSuspendAndResumeHotkey == newSuspendAndResumeHotkey)
return;
mSuspendAndResumeHotkey = newSuspendAndResumeHotkey;
emit suspendAndResumeHotkeyChanged();
}

int GlobalData::suspendAndResumeDuration() const
{
return mSuspendAndResumeDuration;
}

void GlobalData::setSuspendAndResumeDuration(int newSuspendAndResumeDuration)
{
if (mSuspendAndResumeDuration == newSuspendAndResumeDuration)
return;
mSuspendAndResumeDuration = newSuspendAndResumeDuration;
emit suspendAndResumeDurationChanged();
}
18 changes: 17 additions & 1 deletion EliteSpeedrunTool/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ class GlobalData : public QObject {
bool displayInfoToolWindow() const;
void setDisplayInfoToolWindow(bool newDisplayInfoToolWindow);

QString suspendAndResumeHotkey() const;
void setSuspendAndResumeHotkey(const QString& newSuspendAndResumeHotkey);

int suspendAndResumeDuration() const;
void setSuspendAndResumeDuration(int newSuspendAndResumeDuration);

signals:
void minimizeToTrayChanged();
void styleNameChanged();
Expand Down Expand Up @@ -218,6 +224,10 @@ class GlobalData : public QObject {

void displayInfoToolWindowChanged();

void suspendAndResumeHotkeyChanged();

void suspendAndResumeDurationChanged();

private:
bool mMinimizeToTray = false;
QString mStyleName = "windowsvista";
Expand Down Expand Up @@ -282,7 +292,11 @@ class GlobalData : public QObject {
// 社交
bool mDiscordShowRichPresence = false;

// 卡前置
// 卡单
QString mSuspendAndResumeHotkey = "Ctrl+Alt+`";
int mSuspendAndResumeDuration = 9000;

// 结束游戏
QString mCloseGameImmediatelyHotkey = "Ctrl+`";

// 开发者选项
Expand Down Expand Up @@ -326,4 +340,6 @@ class GlobalData : public QObject {
Q_PROPERTY(MissionDataNameUtil::MissionDataName missionDataName READ missionDataName WRITE setMissionDataName NOTIFY missionDataNameChanged FINAL)
Q_PROPERTY(bool debugMode READ debugMode WRITE setDebugMode NOTIFY debugModeChanged FINAL)
Q_PROPERTY(bool displayInfoToolWindow READ displayInfoToolWindow WRITE setDisplayInfoToolWindow NOTIFY displayInfoToolWindowChanged FINAL)
Q_PROPERTY(QString suspendAndResumeHotkey READ suspendAndResumeHotkey WRITE setSuspendAndResumeHotkey NOTIFY suspendAndResumeHotkeyChanged FINAL)
Q_PROPERTY(int suspendAndResumeDuration READ suspendAndResumeDuration WRITE setSuspendAndResumeDuration NOTIFY suspendAndResumeDurationChanged FINAL)
};
Loading

0 comments on commit c9bfb78

Please sign in to comment.