#include #include "radhook/radhook.h" static int fnA() { return 1; } static int detourA() { return 100; } static int fnB() { return 2; } static int detourB() { return 200; } static int fnC() { return 3; } static int detourC() { return 300; } int main() { RadHookHandle hA = nullptr; RadHookHandle hB = nullptr; assert(RadHookCreate((void*)fnA, (void*)detourA, &hA) == RadHookResult::Success); assert(RadHookCreate((void*)fnB, (void*)detourB, &hB) == RadHookResult::Success); // start both from a known, disabled state assert(RadHookDisable(hA) == RadHookResult::Success); assert(RadHookDisable(hB) == RadHookResult::Success); assert(fnA() == 1); assert(fnB() == 2); // queueing must not apply immediately assert(RadHookQueueEnable(hA) == RadHookResult::Success); assert(RadHookQueueEnable(hB) == RadHookResult::Success); assert(!RadHookIsEnabled(hA)); assert(!RadHookIsEnabled(hB)); assert(fnA() == 1); assert(fnB() == 2); // apply enables both together assert(RadHookApplyQueued() == RadHookResult::Success); assert(RadHookIsEnabled(hA)); assert(RadHookIsEnabled(hB)); assert(fnA() == 100); assert(fnB() == 200); // last queued action before apply wins assert(RadHookQueueDisable(hA) == RadHookResult::Success); assert(RadHookQueueEnable(hA) == RadHookResult::Success); assert(RadHookApplyQueued() == RadHookResult::Success); assert(RadHookIsEnabled(hA)); // an apply with nothing queued is a no-op assert(RadHookApplyQueued() == RadHookResult::Success); // queueing a redundant transition (already enabled) still applies cleanly assert(RadHookQueueEnable(hA) == RadHookResult::Success); assert(RadHookApplyQueued() == RadHookResult::Success); assert(RadHookIsEnabled(hA)); // invalid handles assert(RadHookQueueEnable(nullptr) == RadHookResult::InvalidHandle); assert(RadHookQueueDisable(nullptr) == RadHookResult::InvalidHandle); // a destroyed hook can no longer be queued RadHookHandle hC = nullptr; assert(RadHookCreate((void*)fnC, (void*)detourC, &hC) == RadHookResult::Success); RadHookDestroy(hC); assert(RadHookQueueEnable(hC) == RadHookResult::InvalidHandle); RadHookDestroy(hA); RadHookDestroy(hB); return 0; }