summaryrefslogtreecommitdiffhomepage
path: root/proto-ft/mutex.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2016-04-06 15:56:01 +0200
committerStanislaw Halik <sthalik@misaki.pl>2016-04-06 15:56:01 +0200
commit5ac80f5ed0dfff50af05d064401c37f88a28f894 (patch)
tree6a69aaf5fff871b2531ca2dcf70ac4a0bd53b33a /proto-ft/mutex.cpp
parentba64bc2432e1c903bfd99477d31736db227171b7 (diff)
proto/ft: don't make games think opentrack is running after it quits
Some background: Our dll's for freetrack and npclient protocols don't support indication whether opentrack is running or not. Worse yet, they're whitelisted on Arma's anticheat system so we can't modify them at arbitrary times. It's possible to run multiple opentrack instances at a time and we can't have multiple instances stepping upon each other's toes. It's kind of pointless to run multiple sessions but hey. Implementation: Guard with a mutex against multiple instances. Only the first instance (that uses the freetrack protocol at all) gets to control whether the dll's are accessible. Remove the registry keys after either freetrack protocol exits or software exits, but only if we're the first opentrack instance running freetrack protocol at all. Issue: #332
Diffstat (limited to 'proto-ft/mutex.cpp')
-rwxr-xr-xproto-ft/mutex.cpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/proto-ft/mutex.cpp b/proto-ft/mutex.cpp
new file mode 100755
index 00000000..0d50c9bd
--- /dev/null
+++ b/proto-ft/mutex.cpp
@@ -0,0 +1,64 @@
+#include "ftnoir_protocol_ft.h"
+#include <windows.h>
+
+class check_for_first_run : public runonce
+{
+ bool checked_for_first_run;
+ bool is_first_instance;
+
+public:
+ bool is_first_run() override
+ {
+ return checked_for_first_run && is_first_instance;
+ }
+
+ void try_runonce() override
+ {
+ constexpr const char* name = "opentrack-freetrack-runonce";
+
+ if (checked_for_first_run)
+ return;
+
+ // just leak it, no issue
+ HANDLE h = CreateMutexA(nullptr, false, name);
+
+ switch (WaitForSingleObject(h, 0))
+ {
+ case WAIT_OBJECT_0:
+ is_first_instance = true;
+ checked_for_first_run = true;
+ break;
+ case WAIT_TIMEOUT:
+ checked_for_first_run = true;
+ break;
+ default:
+ checked_for_first_run = false;
+ break;
+ }
+
+ if (checked_for_first_run && !is_first_instance)
+ CloseHandle(h);
+
+ qDebug() << "ft runonce:" << "first-run" << is_first_instance << "checked" << checked_for_first_run;
+ }
+
+ void try_exit() override
+ {
+ if (is_first_instance)
+ {
+ qDebug() << "ft runonce: removing registry keys";
+ FTNoIR_Protocol::set_protocols(false, false);
+ }
+ }
+
+public:
+ check_for_first_run() : checked_for_first_run(false), is_first_instance(false)
+ {
+ }
+ ~check_for_first_run()
+ {
+ try_exit();
+ }
+};
+
+std::unique_ptr<runonce> FTNoIR_Protocol::runonce_check = std::unique_ptr<runonce>(static_cast<runonce*>(new check_for_first_run()));