diff --git a/GlosSITarget/HidHide.cpp b/GlosSITarget/HidHide.cpp index 1791e07..bf63a2f 100644 --- a/GlosSITarget/HidHide.cpp +++ b/GlosSITarget/HidHide.cpp @@ -43,7 +43,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_XUSB, 0xEC87F1E3, 0xC13B, 0x4100, 0xB5, 0xF7, 0x8B // {00000000-0000-0000-FFFF-FFFFFFFFFFFF} the system container id DEFINE_GUID(GUID_CONTAINER_ID_SYSTEM, 0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); -HidHide::HidHide() = default; +HidHide::HidHide(){}; void HidHide::openCtrlDevice() { @@ -68,6 +68,8 @@ void HidHide::closeCtrlDevice() void HidHide::hideDevices(const std::filesystem::path& steam_path) { + UnPatchValveHooks(); + openCtrlDevice(); auto active = getActive(); if (active) { @@ -109,14 +111,18 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path) if (std::ranges::none_of(blacklisted_devices_, [&dev](const auto& blackdev) { return blackdev == dev.device_instance_path || blackdev == dev.base_container_device_instance_path; })) { - if (!dev.device_instance_path.empty()) { - blacklisted_devices_.push_back(dev.device_instance_path); - } - if (!dev.device_instance_path.empty()) { - blacklisted_devices_.push_back(dev.base_container_device_instance_path); + // Valve emulated gamepad PID/VID; mirrord by ViGEm + if (!(dev.vendor_id == 0x28de && dev.product_id == 0x11FF)) { + if (!dev.device_instance_path.empty()) { + blacklisted_devices_.push_back(dev.device_instance_path); + } + if (!dev.device_instance_path.empty()) { + blacklisted_devices_.push_back(dev.base_container_device_instance_path); + } } } } + // TODO: remove all vigem controllers added by GlosSI setBlacklistDevices(blacklisted_devices_); setActive(true); closeCtrlDevice(); @@ -132,6 +138,110 @@ void HidHide::disableHidHide() spdlog::info("Un-hid Gaming Devices"); } +void HidHide::UnPatchValveHooks() +{ + spdlog::debug("Unpatching Valve HID hooks..."); + // need to load addresses that way.. Otherwise we land before some jumps... + auto setupapidll = GetModuleHandle(L"setupapi.dll"); + if (setupapidll) { + BYTE* addr = reinterpret_cast(GetProcAddress(setupapidll, "SetupDiEnumDeviceInfo")); + if (addr) { + UnPatchHook(addr, SETUP_DI_ENUM_DEV_INFO_ORIG_BYTES); + spdlog::trace("Unpatched SetupDiEnumDeviceInfo"); + } + else { + spdlog::error("failed to unpatch SetupDiEnumDeviceInfo"); + } + } + auto hiddll = GetModuleHandle(L"hid.dll"); + if (hiddll) { + BYTE* addr = reinterpret_cast(GetProcAddress(hiddll, "HidD_GetPreparsedData")); + if (addr) { + UnPatchHook(addr, HID_GETPREPARSED_ORIG_BYTES); + spdlog::trace("Unpatched HidD_GetPreparsedData"); + } + else { + spdlog::error("failed to unpatch HidD_GetPreparsedData"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidP_GetCaps")); + if (addr) { + UnPatchHook(addr, HID_GETCAPS_ORIG_BYTES); + spdlog::trace("Unpatched HidP_GetCaps"); + } + else { + spdlog::error("failed to unpatch HidP_GetCaps"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidD_GetAttributes")); + if (addr) { + UnPatchHook(addr, HID_GETATTRS_ORIG_BYTES); + spdlog::trace("Unpatched HidD_GetAttributes"); + } + else { + spdlog::error("failed to unpatch HidD_GetAttributes"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidD_GetProductString")); + if (addr) { + UnPatchHook(addr, HID_GETPRODSTR_ORIG_BYTES); + spdlog::trace("Unpatched HidD_GetProductString"); + } + else { + spdlog::error("failed to unpatch HidD_GetProductString"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidP_GetUsages")); + if (addr) { + UnPatchHook(addr, HID_GETUSAGE_ORIG_BYTES); + spdlog::trace("Unpatched HidP_GetUsages"); + } + else { + spdlog::error("failed to unpatch HidP_GetUsages"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidP_GetData")); + if (addr) { + UnPatchHook(addr, HID_GETDATA_ORIG_BYTES); + spdlog::trace("Unpatched HidP_GetData"); + } + else { + spdlog::error("failed to unpatch HidP_GetData"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidP_GetValueCaps")); + if (addr) { + UnPatchHook(addr, HID_GETVALUECAPS_ORIG_BYTES); + spdlog::trace("Unpatched HidP_GetValueCaps"); + } + else { + spdlog::error("failed to unpatch HidP_GetValueCaps"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidP_GetUsageValue")); + if (addr) { + UnPatchHook(addr, HID_GETUSAGE_VAL_ORIG_BYTES); + spdlog::trace("Unpatched HidP_GetUsageValue"); + } + else { + spdlog::error("failed to unpatch HidP_GetUsageValue"); + } + addr = reinterpret_cast(GetProcAddress(hiddll, "HidP_GetButtonCaps")); + if (addr) { + UnPatchHook(addr, HID_GETBTNCAPS_VAL_ORIG_BYTES); + spdlog::trace("Unpatched HidP_GetButtonCaps"); + } + else { + spdlog::error("failed to unpatch HidP_GetButtonCaps"); + } + } +} + +void HidHide::UnPatchHook(BYTE* address, const std::string& bytes) +{ + DWORD dw_old_protect, dw_bkup; + const auto len = bytes.size(); + VirtualProtect(address, len, PAGE_EXECUTE_READWRITE, &dw_old_protect); //Change permissions of memory.. + for (DWORD i = 0; i < len; i++) //unpatch Valve's hook + { + *(address + i) = bytes[i]; + } + VirtualProtect(address, len, dw_old_protect, &dw_bkup); //Revert permission change... +} + void HidHide::enableOverlayElement() { Overlay::AddOverlayElem([this]() { @@ -329,6 +439,7 @@ std::vector HidHide::GetHidDeviceList() } auto device_instance_paths = BufferToStringVec(buffer); + device_instance_paths.erase( std::ranges::remove_if( device_instance_paths, @@ -419,6 +530,8 @@ HidHide::SmallHidInfo HidHide::GetDeviceInfo(const DeviceInstancePath& instance_ } res.base_container_device_instance_path = BaseContainerDeviceInstancePath(instance_path); res.gaming_device = IsGamingDevice(attributes, capabilities); + res.vendor_id = attributes.VendorID; + res.product_id = attributes.ProductID; return res; } diff --git a/GlosSITarget/HidHide.h b/GlosSITarget/HidHide.h index ee90d5a..6b6209c 100644 --- a/GlosSITarget/HidHide.h +++ b/GlosSITarget/HidHide.h @@ -50,6 +50,8 @@ class HidHide { DeviceInstancePath device_instance_path; DeviceInstancePath base_container_device_instance_path; std::filesystem::path symlink; + USHORT vendor_id; + USHORT product_id; bool gaming_device = false; }; @@ -66,6 +68,31 @@ class HidHide { private: HANDLE hidhide_handle = nullptr; + // Valve Hooks `SetupDiEnumDeviceInfo` and hides Gaming devices like this. + // To be able to query them, unpatch the hook with the original bytes... + static inline const std::string SETUP_DI_ENUM_DEV_INFO_ORIG_BYTES = "\x48\x89\x5C\x24\x08"; + // Valve also Hooks `HidD_GetPreparsedData` ..unhook that as well... + static inline const std::string HID_GETPREPARSED_ORIG_BYTES = "\x48\x89\x5C\x24\x18"; + // ..aand `HidP_GetCaps` + static inline const std::string HID_GETCAPS_ORIG_BYTES = "\x4C\x8B\xD1\x48\x85\xC9"; + // ...aaand `HidD_GetAttributes` + static inline const std::string HID_GETATTRS_ORIG_BYTES = "\x40\x53\x48\x83\xEC"; + // ...aaaaand `HidD_GetProductString` + static inline const std::string HID_GETPRODSTR_ORIG_BYTES = "\x48\x83\xEC\x48\x48"; + // ...aaaaand `HidP_GetUsages` + static inline const std::string HID_GETUSAGE_ORIG_BYTES = "\x4C\x89\x4C\x24\x20"; + // ...aaaaand `HidP_GetData` + static inline const std::string HID_GETDATA_ORIG_BYTES = "\x4C\x89\x44\x24\x18"; + // ...aaaaand `HidP_GetValueCaps` + static inline const std::string HID_GETVALUECAPS_ORIG_BYTES = "\x48\x83\xEC\x48\x49"; + // ...aaaaand `HidP_GetUsageValue` + static inline const std::string HID_GETUSAGE_VAL_ORIG_BYTES = "\x40\x53\x55\x56\x48"; + // ...aaaaand `HidP_GetButtonCaps` + static inline const std::string HID_GETBTNCAPS_VAL_ORIG_BYTES = "\x48\x83\xEC\x48\x49"; + + static void UnPatchValveHooks(); + static void UnPatchHook(BYTE* address, const std::string& bytes); + void enableOverlayElement(); sf::Clock overlay_elem_clock_;