win-capture: Fix case where hook only captures one frame
When using a chain hook method (forward or reverse), it was unwisely assumed that the previous hook in the chain would not overwrite new hooks when it's called. When the game capture hook calls the previous hook in the chain, certain other programs that hook (in this case, rivatuner on-screen display) would overwrite the hook with older data and erase the game capture hook, causing it to only capture the first frame and then never capture again. This patch ensures that the hook is always saved before calling the next hook in the chain and then restored after the call returns. It also preserves any new hooks that may be added on top of it at any point.master
parent
3fec8e236e
commit
bef1b37ae2
|
@ -213,16 +213,24 @@ void do_hook(struct func_hook *hook, bool force)
|
|||
{
|
||||
intptr_t offset;
|
||||
|
||||
/* chained hooks do not unhook */
|
||||
if (!force && hook->hooked)
|
||||
return;
|
||||
|
||||
/* if the hook is a forward overwrite hook, copy back the memory that
|
||||
* was previously encountered to preserve any new hooks on top */
|
||||
if (hook->started && !force &&
|
||||
hook->type == HOOKTYPE_FORWARD_OVERWRITE) {
|
||||
memcpy((void*)hook->func_addr, hook->rehook_data,
|
||||
patch_size(hook));
|
||||
/* copy back the memory that was previously encountered to preserve
|
||||
* the current hook and any newer hooks on top */
|
||||
if (hook->started && !force) {
|
||||
uintptr_t addr;
|
||||
size_t size;
|
||||
|
||||
if (hook->type == HOOKTYPE_REVERSE_CHAIN) {
|
||||
addr = hook->func_addr - JMP_32_SIZE;
|
||||
size = JMP_32_SIZE;
|
||||
} else {
|
||||
addr = hook->func_addr;
|
||||
size = patch_size(hook);
|
||||
}
|
||||
|
||||
memcpy((void*)addr, hook->rehook_data, size);
|
||||
hook->hooked = true;
|
||||
return;
|
||||
}
|
||||
|
@ -250,16 +258,25 @@ void do_hook(struct func_hook *hook, bool force)
|
|||
|
||||
void unhook(struct func_hook *hook)
|
||||
{
|
||||
uintptr_t addr;
|
||||
size_t size;
|
||||
|
||||
/* chain hooks do not need to unhook */
|
||||
if (!hook->hooked || hook->type != HOOKTYPE_FORWARD_OVERWRITE)
|
||||
if (!hook->hooked)
|
||||
return;
|
||||
|
||||
size = patch_size(hook);
|
||||
fix_permissions((void*)hook->func_addr, size);
|
||||
memcpy(hook->rehook_data, (void*)hook->func_addr, size);
|
||||
memcpy((void*)hook->func_addr, hook->unhook_data, size);
|
||||
if (hook->type == HOOKTYPE_REVERSE_CHAIN) {
|
||||
size = JMP_32_SIZE;
|
||||
addr = (hook->func_addr - JMP_32_SIZE);
|
||||
} else {
|
||||
size = patch_size(hook);
|
||||
addr = hook->func_addr;
|
||||
}
|
||||
|
||||
fix_permissions((void*)addr, size);
|
||||
memcpy(hook->rehook_data, (void*)addr, size);
|
||||
|
||||
if (hook->type == HOOKTYPE_FORWARD_OVERWRITE)
|
||||
memcpy((void*)hook->func_addr, hook->unhook_data, size);
|
||||
|
||||
hook->hooked = false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue