./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
1 / 1
100.0%
Branches:
-
-%
Functions:
1 / 1
100.0%

src/internal/xinput_route_probe.hpp
Line Branch Exec Source
1 #ifndef DETOURMODKIT_INTERNAL_XINPUT_ROUTE_PROBE_HPP
2 #define DETOURMODKIT_INTERNAL_XINPUT_ROUTE_PROBE_HPP
3
4 #include <cstdint>
5
6 namespace DetourModKit::detail
7 {
8 /** @brief The required export whose scoped call supplies a receipt. */
9 enum class XInputRouteMember : std::uint8_t
10 {
11 Primary,
12 Ex
13 };
14
15 /** @brief Exact identity of one export invocation under an interception snapshot. */
16 struct XInputRouteProbeIdentity
17 {
18 std::uint64_t owner{0};
19 std::uint64_t hook_epoch{0};
20 XInputRouteMember member{XInputRouteMember::Primary};
21 std::uint32_t user_index{0};
22 std::uintptr_t state_address{0};
23 };
24
25 /**
26 * @brief Reserves receipt TLS and opens probe admission. Call under the interception control lock.
27 * @return false when TLS reservation fails. Existing leases retain their index across a reopen.
28 */
29 [[nodiscard]] bool reserve_xinput_route_probe() noexcept;
30
31 /** @brief Closes probe admission for XInput teardown. */
32 void close_xinput_route_probes() noexcept;
33
34 /** @brief Returns the number of leases across upstream calls and final snapshot publication. */
35 [[nodiscard]] std::uint64_t xinput_route_probe_inflight() noexcept;
36
37 /**
38 * @brief Returns receipt TLS after closed admission and zero probe leases.
39 * @details Call under the interception control lock after every callback that reads receipt TLS drains.
40 * @return false while admission is open or any lease remains. A refused release retains the index.
41 */
42 [[nodiscard]] bool release_xinput_route_probe_if_idle() noexcept;
43
44 /**
45 * @brief Records this thread's exact scoped export invocation without an application lock or C++ allocation.
46 * @details A receipt proves this invocation only. The identity must match its private token and native thread.
47 */
48 void xinput_route_probe_record(const XInputRouteProbeIdentity &identity) noexcept;
49
50 /**
51 * @brief Owns permanent receipt storage and a counted upstream-call lease.
52 * @details Construct before the export call and retain through final snapshot publication. Nested probes restore
53 * prior numeric TLS tokens in reverse order. Keep the object on its construction thread.
54 */
55 class XInputRouteProbe
56 {
57 public:
58 /** @brief Opens one probe. Refuse the export call when admitted() is false. */
59 explicit XInputRouteProbe(const XInputRouteProbeIdentity &identity) noexcept;
60 /** @brief Restores an unfinished token, clears its receipt slot, and releases the complete-call lease. */
61 ~XInputRouteProbe() noexcept;
62
63 XInputRouteProbe(const XInputRouteProbe &) = delete;
64 XInputRouteProbe &operator=(const XInputRouteProbe &) = delete;
65 XInputRouteProbe(XInputRouteProbe &&) = delete;
66 XInputRouteProbe &operator=(XInputRouteProbe &&) = delete;
67
68 /** @brief Reports whether the lease and its TLS token were acquired. */
69 5179 [[nodiscard]] bool admitted() const noexcept { return m_admitted; }
70
71 /**
72 * @brief Restores prior TLS and returns whether this exact invocation supplied a receipt.
73 * @details The lease stays counted until destruction. A repeated call returns the cached verdict.
74 * @return false after an entry failure, unmatched receipt, token mismatch, or failed TLS restore.
75 */
76 [[nodiscard]] bool finish() noexcept;
77
78 private:
79 std::uintptr_t m_token{0};
80 std::uintptr_t m_previous_token{0};
81 std::uint32_t m_index{0};
82 std::uint32_t m_slot{0};
83 bool m_admitted{false};
84 bool m_finished{false};
85 bool m_receipt{false};
86 };
87
88 #if defined(DMK_ENABLE_TEST_SEAMS)
89 /** @brief Forces TLS reservation, probe entry, or token restore failures for deterministic proofs. */
90 void set_xinput_route_probe_failures_for_test(bool reservation, bool entry, bool restore) noexcept;
91 /** @brief Returns the private receipt TLS index, or TLS_OUT_OF_INDEXES. */
92 [[nodiscard]] std::uint32_t xinput_route_probe_tls_index_for_test() noexcept;
93 /** @brief Returns this thread's numeric receipt token, or zero without an index. */
94 [[nodiscard]] std::uintptr_t xinput_route_probe_token_for_test() noexcept;
95 /** @brief Replaces this thread's token to verify nonce and unrelated-call refusal. */
96 [[nodiscard]] bool set_xinput_route_probe_token_for_test(std::uintptr_t token) noexcept;
97 #endif
98 } // namespace DetourModKit::detail
99
100 #endif // DETOURMODKIT_INTERNAL_XINPUT_ROUTE_PROBE_HPP
101