1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef OHOS_HOOK_MANAGER_H__
17#define OHOS_HOOK_MANAGER_H__
18
19#ifdef __cplusplus
20#if __cplusplus
21extern "C" {
22#endif
23#endif
24
25/**
26 * @brief A Hook is a means of executing custom code (function) for existing running code.
27 *
28 * For a running process, it may consists of several stages.
29 * HookManager can help to add hooks to different stages with different priorities.
30 * The relationships for HookManager, HookStage and HookItem are shown as below:
31 *
32 * | ̄ ̄ ̄ ̄ ̄ ̄|
33 * |  HookMgr |
34 * |__________|
35 *      |
36 *      |    |▔▔▔▔▔▔▔▔▔▔▔|    |▔▔▔▔▔▔▔▔▔▔▔|
37 *      └--->| HookStage |--->| HookStage | ...
38 *           |___________|    |___________|
39 *               |
40 *               |    |▔▔▔▔▔▔▔▔▔▔|    |▔▔▔▔▔▔▔▔▔▔|
41 *               └--->| HookItem |--->| HookItem | ...
42 *                    |__________|    |__________|
43 *
44 * Usage example:
45 *
46 * For an existing module with several stages as below:
47 *      ExistingStage1(...);
48 *      ExistingStage2(...);
49 *      ExistingStage3(...);
50 * We can add hooks capability to it as below:
51 *      HookMgrExecute(hookMgr, PRE_STAGE1, ...);
52 *      ExistingStage1(...);
53 *      HookMgrExecute(hookMgr, PRE_STAGE2, ...);
54 *      ExistingStage2(...);
55 *      HookMgrExecute(hookMgr, PRE_STAGE3, ...);
56 *      ExistingStage3(...);
57 *      HookMgrExecute(hookMgr, POST_STAGE3, ...);
58 *
59 * For extending modules, we can add hooks without changing the existing module as below:
60 *      int sampleHook() {
61 *          ...
62 *      }
63 *      HookMgrAdd(hookMgr, PRE_STAGE1, priority, sampleHook);
64 */
65
66/* Forward declaration for HookManager */
67typedef struct tagHOOK_MGR HOOK_MGR;
68
69/* Forward declaration for HOOK_INFO */
70typedef struct tagHOOK_INFO HOOK_INFO;
71
72/**
73 * @brief Hook function prototype
74 *
75 * @param hookInfo hook information
76 * @param executionContext input arguments for running the hook execution context
77 * @return return 0 if succeed; other values if failed.
78 */
79typedef int (*OhosHook)(const HOOK_INFO *hookInfo, void *executionContext);
80
81struct tagHOOK_INFO {
82    int stage;          /* hook stage */
83    int prio;           /* hook priority */
84    OhosHook hook;      /* hook function */
85    void *hookCookie;   /* hook function cookie, for current hook only */
86};
87
88/**
89 * @brief Add a hook function
90 *
91 * @param hookMgr HookManager handle.
92 *                If hookMgr is NULL, it will use default HookManager
93 * @param stage hook stage
94 * @param prio hook priority
95 * @param hook hook function pointer
96 * @return return 0 if succeed; other values if failed.
97 */
98int HookMgrAdd(HOOK_MGR *hookMgr, int stage, int prio, OhosHook hook);
99
100/**
101 * @brief Add a hook function with full hook information
102 *
103 * @param hookMgr HookManager handle.
104 *                If hookMgr is NULL, it will use default HookManager
105 * @param hookInfo full hook information
106 * @return return 0 if succeed; other values if failed.
107 */
108int HookMgrAddEx(HOOK_MGR *hookMgr, const HOOK_INFO *hookInfo);
109
110/**
111 * @brief Delete hook function
112 *
113 * @param hookMgr HookManager handle.
114 *                If hookMgr is NULL, it will use default HookManager
115 * @param stage hook stage
116 * @param hook hook function pointer
117 *                If hook is NULL, it will delete all hooks in the stage
118 * @return None
119 */
120void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook);
121
122/**
123 * @brief preHook function prototype for HookMgrExecute each hook
124 *
125 * @param hookInfo HOOK_INFO for the each hook.
126 * @param executionContext input arguments for running the hook execution context.
127 * @return None
128 */
129typedef void (*OhosHookPreExecution)(const HOOK_INFO *hookInfo, void *executionContext);
130
131/**
132 * @brief postHook function prototype for HookMgrExecute each hook
133 *
134 * @param hookInfo HOOK_INFO for the each hook.
135 * @param executionContext input arguments for running the hook execution context.
136 * @param executionRetVal return value for running the hook.
137 * @return None
138 */
139typedef void (*OhosHookPostExecution)(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal);
140
141/* Executing hooks in descending priority order */
142#define HOOK_EXEC_REVERSE_ORDER     0x01
143/* Stop executing hooks when error returned for each hook */
144#define HOOK_EXEC_EXIT_WHEN_ERROR   0x02
145
146/**
147 * @brief Extra execution arguments for HookMgrExecute
148 */
149typedef struct tagHOOK_EXEC_OPTIONS {
150    /* Executing flags */
151    int flags;
152    /* preHook for before executing each hook */
153    OhosHookPreExecution preHook;
154    /* postHook for before executing each hook */
155    OhosHookPostExecution postHook;
156} HOOK_EXEC_OPTIONS;
157
158/**
159 * @brief Executing each hooks in specified stages
160 *
161 * @param hookMgr HookManager handle.
162 *                If hookMgr is NULL, it will use default HookManager
163 * @param stage hook stage
164 * @param extraArgs HOOK_EXEC_ARGS for executing each hook.
165 * @return return 0 if succeed; other values if failed.
166 */
167int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *extraArgs);
168
169/**
170 * @brief Create a HookManager handle
171 *
172 * @param name HookManager name.
173 * @return return HookManager handle; NULL if failed.
174 */
175HOOK_MGR *HookMgrCreate(const char *name);
176
177/**
178 * @brief Destroy HookManager
179 *
180 * @param hookMgr HookManager handle.
181 *                If hookMgr is NULL, it will use default HookManager
182 * @return None.
183 */
184void HookMgrDestroy(HOOK_MGR *hookMgr);
185
186/**
187 * @brief Hook traversal function prototype
188 *
189 * @param hookInfo HOOK_INFO for traversing each hook.
190 * @return None
191 */
192typedef void (*OhosHookTraversal)(const HOOK_INFO *hookInfo, void *traversalCookie);
193
194/**
195 * @brief Traversing all hooks in the HookManager
196 *
197 * @param hookMgr HookManager handle.
198 *                If hookMgr is NULL, it will use default HookManager
199 * @param traversalCookie traversal cookie.
200 * @param traversal traversal function.
201 * @return None.
202 */
203void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal);
204
205/**
206 * @brief Get number of hooks in specified stage
207 *
208 * @param hookMgr HookManager handle.
209 *                If hookMgr is NULL, it will use default HookManager
210 * @param stage hook stage.
211 * @return number of hooks, return 0 if none
212 */
213int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage);
214
215/**
216 * @brief Get number of stages in the HookManager
217 *
218 * @param hookMgr HookManager handle.
219 *                If hookMgr is NULL, it will use default HookManager
220 * @return number of stages, return 0 if none
221 */
222int HookMgrGetStagesCnt(HOOK_MGR *hookMgr);
223
224#define HOOK_OK = 0
225#define ERR_NO_HOOK_STAGE (-1000)
226#ifdef __cplusplus
227#if __cplusplus
228}
229#endif
230#endif
231#endif
232