2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/notify.c
5 * PURPOSE: Process Manager: Callbacks to Registered Clients (Drivers)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Thomas Weidenmueller (w3seek@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 BOOLEAN PsImageNotifyEnabled
= FALSE
;
19 ULONG PspThreadNotifyRoutineCount
, PspProcessNotifyRoutineCount
;
20 ULONG PspLoadImageNotifyRoutineCount
;
21 EX_CALLBACK PspThreadNotifyRoutine
[PSP_MAX_CREATE_THREAD_NOTIFY
];
22 EX_CALLBACK PspProcessNotifyRoutine
[PSP_MAX_CREATE_PROCESS_NOTIFY
];
23 EX_CALLBACK PspLoadImageNotifyRoutine
[PSP_MAX_LOAD_IMAGE_NOTIFY
];
24 PLEGO_NOTIFY_ROUTINE PspLegoNotifyRoutine
;
26 /* PUBLIC FUNCTIONS **********************************************************/
33 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
37 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
40 /* Check if we're removing */
43 /* Loop all the routines */
44 for (i
= 0; i
< PSP_MAX_CREATE_PROCESS_NOTIFY
; i
++)
46 /* Reference the callback block */
47 CallBack
= ExReferenceCallBackBlock(&PspProcessNotifyRoutine
[i
]);
48 if (!CallBack
) continue;
50 /* Check it this is a matching block */
51 if (ExGetCallBackBlockRoutine(CallBack
) == (PVOID
)NotifyRoutine
)
53 /* Try removing it if it matches */
54 if (ExCompareExchangeCallBack(&PspProcessNotifyRoutine
[i
],
58 /* Decrement the number of routines */
59 InterlockedDecrement((PLONG
)&PspProcessNotifyRoutineCount
);
61 /* Dereference the block */
62 ExDereferenceCallBackBlock(&PspProcessNotifyRoutine
[i
],
65 /* Wait for active callbacks */
66 ExWaitForCallBacks(CallBack
);
68 /* Free the callback and exit */
69 ExFreeCallBack(CallBack
);
70 return STATUS_SUCCESS
;
73 /* Dereference the block */
74 ExDereferenceCallBackBlock(&PspProcessNotifyRoutine
[i
],
79 /* We didn't find any matching block */
80 return STATUS_PROCEDURE_NOT_FOUND
;
84 /* Allocate a callback */
85 CallBack
= ExAllocateCallBack((PVOID
)NotifyRoutine
, NULL
);
86 if (!CallBack
) return STATUS_INSUFFICIENT_RESOURCES
;
88 /* Loop all callbacks */
89 for (i
= 0; i
< PSP_MAX_CREATE_PROCESS_NOTIFY
; i
++)
91 /* Add this routine if it's an empty slot */
92 if (ExCompareExchangeCallBack(&PspProcessNotifyRoutine
[i
],
96 /* Found and inserted into an empty slot, return */
97 InterlockedIncrement((PLONG
)&PspProcessNotifyRoutineCount
);
98 return STATUS_SUCCESS
;
102 /* We didn't find a free slot, free the callback and fail */
103 ExFreeCallBack(CallBack
);
104 return STATUS_INVALID_PARAMETER
;
113 PsSetLegoNotifyRoutine(PVOID LegoNotifyRoutine
)
115 /* Set the System-Wide Lego Routine */
116 PspLegoNotifyRoutine
= LegoNotifyRoutine
;
118 /* Return the location to the Lego Data */
119 return FIELD_OFFSET(KTHREAD
, LegoData
);
127 PsRemoveLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
130 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
133 /* Loop all callbacks */
134 for (i
= 0; i
< PSP_MAX_LOAD_IMAGE_NOTIFY
; i
++)
136 /* Reference this slot */
137 CallBack
= ExReferenceCallBackBlock(&PspLoadImageNotifyRoutine
[i
]);
140 /* Check for a match */
141 if (ExGetCallBackBlockRoutine(CallBack
) == (PVOID
)NotifyRoutine
)
143 /* Try removing it if it matches */
144 if (ExCompareExchangeCallBack(&PspLoadImageNotifyRoutine
[i
],
148 /* We removed it, now dereference the block */
149 InterlockedDecrement((PLONG
)&PspLoadImageNotifyRoutineCount
);
150 ExDereferenceCallBackBlock(&PspLoadImageNotifyRoutine
[i
],
153 /* Wait for active callbacks */
154 ExWaitForCallBacks(CallBack
);
156 /* Free the callback and return */
157 ExFreeCallBack(CallBack
);
158 return STATUS_SUCCESS
;
162 /* Dereference the callback */
163 ExDereferenceCallBackBlock(&PspLoadImageNotifyRoutine
[i
], CallBack
);
167 /* Nothing found to remove */
168 return STATUS_PROCEDURE_NOT_FOUND
;
176 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
179 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
182 /* Allocate a callback */
183 CallBack
= ExAllocateCallBack((PVOID
)NotifyRoutine
, NULL
);
184 if (!CallBack
) return STATUS_INSUFFICIENT_RESOURCES
;
187 for (i
= 0; i
< PSP_MAX_LOAD_IMAGE_NOTIFY
; i
++)
189 /* Add this entry if the slot is empty */
190 if (ExCompareExchangeCallBack(&PspLoadImageNotifyRoutine
[i
],
195 InterlockedIncrement((PLONG
)&PspLoadImageNotifyRoutineCount
);
196 PsImageNotifyEnabled
= TRUE
;
197 return STATUS_SUCCESS
;
201 /* No free space found, fail */
202 ExFreeCallBack(CallBack
);
203 return STATUS_INSUFFICIENT_RESOURCES
;
211 PsRemoveCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
214 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
217 /* Loop all callbacks */
218 for (i
= 0; i
< PSP_MAX_CREATE_THREAD_NOTIFY
; i
++)
220 /* Reference this slot */
221 CallBack
= ExReferenceCallBackBlock(&PspThreadNotifyRoutine
[i
]);
224 /* Check for a match */
225 if (ExGetCallBackBlockRoutine(CallBack
) == (PVOID
)NotifyRoutine
)
227 /* Try removing it if it matches */
228 if (ExCompareExchangeCallBack(&PspThreadNotifyRoutine
[i
],
232 /* We removed it, now dereference the block */
233 InterlockedDecrement((PLONG
)&PspThreadNotifyRoutineCount
);
234 ExDereferenceCallBackBlock(&PspThreadNotifyRoutine
[i
],
237 /* Wait for active callbacks */
238 ExWaitForCallBacks(CallBack
);
240 /* Free the callback and return */
241 ExFreeCallBack(CallBack
);
242 return STATUS_SUCCESS
;
246 /* Dereference the callback */
247 ExDereferenceCallBackBlock(&PspThreadNotifyRoutine
[i
], CallBack
);
251 /* Nothing found to remove */
252 return STATUS_PROCEDURE_NOT_FOUND
;
260 PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
263 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
266 /* Allocate a callback */
267 CallBack
= ExAllocateCallBack((PVOID
)NotifyRoutine
, NULL
);
268 if (!CallBack
) return STATUS_INSUFFICIENT_RESOURCES
;
271 for (i
= 0; i
< PSP_MAX_CREATE_THREAD_NOTIFY
; i
++)
273 /* Add this entry if the slot is empty */
274 if (ExCompareExchangeCallBack(&PspThreadNotifyRoutine
[i
],
279 InterlockedIncrement((PLONG
)&PspThreadNotifyRoutineCount
);
280 return STATUS_SUCCESS
;
284 /* No free space found, fail */
285 ExFreeCallBack(CallBack
);
286 return STATUS_INSUFFICIENT_RESOURCES
;