forked from nyaoouo/FFxivPythonTrigger2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path__init__.py
More file actions
115 lines (97 loc) · 3.73 KB
/
Copy path__init__.py
File metadata and controls
115 lines (97 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from ctypes import *
from typing import Annotated, List
from inspect import stack
from . import EasyHook
RAISE_ERROR = False
class Hook(object):
"""
a hook class to do local hooks
```restype```, ```argtypes``` and ```hook_function``` need to be overridden
"""
restype: Annotated[any, "the return type of hook function"] = c_void_p
argtypes: Annotated[List[any], "the argument types of hook function"] = []
original: Annotated[callable, "the original function"]
is_enabled: Annotated[bool, "is the hook enabled"]
is_installed: Annotated[bool, "is the hook installed"]
IS_WIN_FUNC = False
def hook_function(self, *args):
"""
the hooked function
"""
return self.original(*args)
def __init__(self, func_address: int):
"""
create a hook,remember to install and enable it afterwards and uninstall it after use
:param func_address: address of the function need to be hooked
"""
self.address = func_address
self.is_enabled = False
self.is_installed = False
self.hook_info = c_void_p()
self._hook_function = c_void_p()
self.original = lambda x: x
self.ACL_entries = (c_ulong * 1)(1)
caller = stack()[1]
self.create_at = f"{caller.filename}:{caller.lineno}"
def install(self) -> None:
"""
install the hook
"""
if self.address in hook_manager:
raise Exception(f"a hook is already installed at [{hex(self.address)}] from [{hook_manager[self.address].create_at}]")
if self.is_installed:
if RAISE_ERROR:
raise Exception("Hook is installed")
else:
return
self.hook_info = EasyHook.HOOK_TRACE_INFO()
interface = (WINFUNCTYPE if self.IS_WIN_FUNC else CFUNCTYPE)(self.restype, *self.argtypes)
def _hook_function(*args):
return self.hook_function(*args)
self._hook_function = interface(_hook_function)
if EasyHook.lh_install_hook(self.address, self._hook_function, None, byref(self.hook_info)):
raise EasyHook.LocalHookError()
self.is_installed = True
hook_manager[self.address] = self
original_func_p = c_void_p()
if EasyHook.lh_get_bypass_address(byref(self.hook_info), byref(original_func_p)):
raise EasyHook.LocalHookError()
self.original = interface(original_func_p.value)
def uninstall(self) -> None:
"""
uninstall the hook
"""
if not self.is_installed:
if RAISE_ERROR:
raise Exception("Hook is not installed")
else:
return
EasyHook.lh_uninstall_hook(byref(self.hook_info))
EasyHook.lh_wait_for_pending_removals()
self.is_installed = False
del hook_manager[self.address]
def enable(self) -> None:
"""
enable the hook
"""
if not self.is_installed:
if RAISE_ERROR:
raise Exception("Hook is not installed")
else:
return
if EasyHook.lh_set_exclusive_acl(addressof(self.ACL_entries), 1, byref(self.hook_info)):
raise EasyHook.LocalHookError()
self.is_enabled = True
def disable(self) -> None:
"""
disable the hook
"""
if not self.is_installed:
if RAISE_ERROR:
raise Exception("Hook is not installed")
else:
return
if EasyHook.lh_set_inclusive_acl(addressof(self.ACL_entries), 1, byref(self.hook_info)):
raise EasyHook.LocalHookError()
self.is_enabled = False
hook_manager: Annotated[dict[int, Hook], "manage those installed hooks"] = dict()