Skip to content

Commit

Permalink
Refactored watchdog service (#168)
Browse files Browse the repository at this point in the history
* Bumped to C++23

* Moved stuff to neflib

* Update App.cpp

* Update appveyor.yml

* Vcpkg adjustments

* Update appveyor.yml

* Update App.cpp

* Fixes

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Added app icon to watchdog

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update App.cpp

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Update vcpkg-configuration.json

* Updated dependencies
  • Loading branch information
nefarius authored Sep 2, 2024
1 parent 69bb4a4 commit a6a5ad5
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 508 deletions.
6 changes: 5 additions & 1 deletion HidHide.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=DEVCLASS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=eventlog/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=HIDCLASS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ITERS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=POCO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=STDEXT/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=uninitialize/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xbox/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xbox/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=XBOXCOMPOSITE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=XNACOMPOSITE/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
159 changes: 68 additions & 91 deletions Watchdog/App.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#include "App.hpp"
#include "Util.h"
#include <initguid.h>
#include <devguid.h>

#include <variant>
#include <expected>
#include <format>

#include <nefarius/neflib/MiscWinApi.hpp>
#include <nefarius/neflib/ClassFilter.hpp>

#pragma warning(disable: 26800)
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
Expand All @@ -27,67 +33,6 @@ class WatchdogTask : public Poco::Task
{
bool _isInteractive;

static DWORD CheckServiceStatus(const std::wstring& serviceName, unsigned long& serviceState)
{
SC_HANDLE sch = nullptr;
SC_HANDLE svc = nullptr;
DWORD error = ERROR_SUCCESS;

__try
{
sch = OpenSCManager(
nullptr,
nullptr,
SC_MANAGER_ALL_ACCESS
);
if (sch == nullptr)
{
error = GetLastError();
__leave;
}

svc = OpenService(
sch,
serviceName.c_str(),
SC_MANAGER_ALL_ACCESS
);
if (svc == nullptr)
{
error = GetLastError();
__leave;
}

SERVICE_STATUS_PROCESS stat;
DWORD needed = 0;
BOOL ret = QueryServiceStatusEx(
svc,
SC_STATUS_PROCESS_INFO,
(BYTE*)&stat,
sizeof stat,
&needed
);
if (ret == 0)
{
error = GetLastError();
__leave;
}

serviceState = stat.dwCurrentState;

error = ERROR_SUCCESS;
__leave;
}
__finally
{
if (svc)
CloseServiceHandle(svc);
if (sch)
CloseServiceHandle(sch);
}

return error;
}

public:
explicit WatchdogTask(const std::string& name, const bool isInteractive)
: Task(name)
Expand All @@ -105,71 +50,95 @@ class WatchdogTask : public Poco::Task

do
{
const auto serviceName = L"HidHide";
unsigned long winError = 0, serviceStatus = 0;
const std::wstring serviceName = L"HidHide";

const auto serviceStatus = nefarius::winapi::services::GetServiceStatus(serviceName);

// check if driver service is healthy
if ((winError = CheckServiceStatus(serviceName, serviceStatus)) != ERROR_SUCCESS)
if (!serviceStatus)
{
spdlog::error("Failed to query service status, error {}", winError);
logger->error("Failed to query service status, error {}", serviceStatus.error().getErrorMessageA());
continue;
}

// expecting service to be running as an indicator that driver is loaded
if (serviceStatus != SERVICE_RUNNING)
if (serviceStatus.value().dwCurrentState != SERVICE_RUNNING)
{
spdlog::error("Driver service not detected running, removing filter entries");
logger->error("Driver service not detected running, removing filter entries");

//
// Prevents bricked HID devices
//

RemoveDeviceClassFilter(&GUID_DEVCLASS_HIDCLASS,
serviceName, util::DeviceClassFilterPosition::Upper);
RemoveDeviceClassFilter(&GUID_DEVCLASS_XNACOMPOSITE,
serviceName, util::DeviceClassFilterPosition::Upper);
RemoveDeviceClassFilter(&GUID_DEVCLASS_XBOXCOMPOSITE,
serviceName, util::DeviceClassFilterPosition::Upper);
auto removeResult = RemoveDeviceClassFilter(&GUID_DEVCLASS_HIDCLASS,
serviceName,
nefarius::devcon::DeviceClassFilterPosition::Upper);

if (!removeResult)
{
logger->error("Removal from GUID_DEVCLASS_HIDCLASS failed with {}",
removeResult.error().getErrorMessageA());
}

removeResult = RemoveDeviceClassFilter(&GUID_DEVCLASS_XNACOMPOSITE,
serviceName,
nefarius::devcon::DeviceClassFilterPosition::Upper);

if (!removeResult)
{
logger->error("Removal from GUID_DEVCLASS_XNACOMPOSITE failed with {}",
removeResult.error().getErrorMessageA());
}

removeResult = RemoveDeviceClassFilter(&GUID_DEVCLASS_XBOXCOMPOSITE,
serviceName,
nefarius::devcon::DeviceClassFilterPosition::Upper);

if (!removeResult)
{
logger->error("Removal from GUID_DEVCLASS_XBOXCOMPOSITE failed with {}",
removeResult.error().getErrorMessageA());
}

continue;
}

// filter value or entry not present
if (bool found = false; !HasDeviceClassFilter(&GUID_DEVCLASS_HIDCLASS, serviceName,
util::DeviceClassFilterPosition::Upper, found) || !found)
if (!HasDeviceClassFilter(&GUID_DEVCLASS_HIDCLASS, serviceName,
nefarius::devcon::DeviceClassFilterPosition::Upper).value_or(false))
{
spdlog::warn("Filter missing for HIDClass, adding");
logger->warn("Filter missing for HIDClass, adding");

if (!AddDeviceClassFilter(&GUID_DEVCLASS_HIDCLASS, serviceName,
util::DeviceClassFilterPosition::Upper))
nefarius::devcon::DeviceClassFilterPosition::Upper))
{
spdlog::error("Failed to add upper filters entry for HIDClass");
logger->error("Failed to add upper filters entry for HIDClass");
}
}

// filter value or entry not present
if (bool found = false; !HasDeviceClassFilter(&GUID_DEVCLASS_XNACOMPOSITE, serviceName,
util::DeviceClassFilterPosition::Upper, found) || !found)
if (!HasDeviceClassFilter(&GUID_DEVCLASS_XNACOMPOSITE, serviceName,
nefarius::devcon::DeviceClassFilterPosition::Upper).value_or(false))
{
spdlog::warn("Filter missing for XnaComposite, adding");
logger->warn("Filter missing for XnaComposite, adding");

if (!AddDeviceClassFilter(&GUID_DEVCLASS_XNACOMPOSITE, serviceName,
util::DeviceClassFilterPosition::Upper))
nefarius::devcon::DeviceClassFilterPosition::Upper))
{
spdlog::error("Failed to add upper filters entry for XnaComposite");
logger->error("Failed to add upper filters entry for XnaComposite");
}
}

// filter value or entry not present
if (bool found = false; !HasDeviceClassFilter(&GUID_DEVCLASS_XBOXCOMPOSITE, serviceName,
util::DeviceClassFilterPosition::Upper, found) || !found)
if (!HasDeviceClassFilter(&GUID_DEVCLASS_XBOXCOMPOSITE, serviceName,
nefarius::devcon::DeviceClassFilterPosition::Upper).value_or(false))
{
spdlog::warn("Filter missing for XboxComposite, adding");
logger->warn("Filter missing for XboxComposite, adding");

if (!AddDeviceClassFilter(&GUID_DEVCLASS_XBOXCOMPOSITE, serviceName,
util::DeviceClassFilterPosition::Upper))
nefarius::devcon::DeviceClassFilterPosition::Upper))
{
spdlog::error("Failed to add upper filters entry for XboxComposite");
logger->error("Failed to add upper filters entry for XboxComposite");
}
}
}
Expand Down Expand Up @@ -211,22 +180,30 @@ int App::main(const std::vector<std::string>& args)

console->info("Application started");

const bool isAdmin = util::IsAdmin();
#if !defined(_DEBUG)
const auto isAdmin = nefarius::winapi::security::IsAppRunningAsAdminMode();

if (isAdmin)
if (isAdmin.value_or(false))
#endif
{
Poco::TaskManager tm;
tm.start(new WatchdogTask("HidHideWatchdog", this->isInteractive()));
waitForTerminationRequest();
tm.cancelAll();
tm.joinAll();
}
#if !defined(_DEBUG)
else
{
errLogger->error("App need administrative permissions to run");
}
#endif

console->info("Exiting application");

#if !defined(_DEBUG)
return isAdmin ? EXIT_OK : EXIT_TEMPFAIL;
#else
return EXIT_OK;
#endif
}
Binary file added Watchdog/AppIcon.rc
Binary file not shown.
Loading

0 comments on commit a6a5ad5

Please sign in to comment.