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 /* It's not, try the next one */
57 /* It is, clear the current routine */
58 if (ExCompareExchangeCallBack(&PspProcessNotifyRoutine
[i
],
62 /* Decrement the number of routines */
63 InterlockedDecrement((PLONG
)&PspProcessNotifyRoutineCount
);
65 /* Dereference the block */
66 ExDereferenceCallBackBlock(&PspProcessNotifyRoutine
[i
],
69 /* Wait for actice callbacks */
70 ExWaitForCallBacks(CallBack
);
72 /* Free the callback and exit */
73 ExFreeCallBack (CallBack
);
74 return STATUS_SUCCESS
;
77 /* Dereference the block */
78 ExDereferenceCallBackBlock(&PspProcessNotifyRoutine
[i
],
82 /* We didn't find any matching block */
83 return STATUS_PROCEDURE_NOT_FOUND
;
87 /* Allocate a callback */
88 CallBack
= ExAllocateCallBack((PVOID
)NotifyRoutine
, NULL
);
89 if (!CallBack
) return STATUS_INSUFFICIENT_RESOURCES
;
91 /* Loop all callbacks */
92 for (i
= 0; i
< PSP_MAX_CREATE_PROCESS_NOTIFY
; i
++)
94 /* Add this routine if it's an empty slot */
95 if (ExCompareExchangeCallBack(&PspProcessNotifyRoutine
[i
],
99 /* Found and inserted into an empty slot, return */
100 InterlockedIncrement((PLONG
)&PspProcessNotifyRoutineCount
);
101 return STATUS_SUCCESS
;
105 /* We didn't find a free slot, free the callback and fail */
106 ExFreeCallBack(CallBack
);
107 return STATUS_INVALID_PARAMETER
;
116 PsSetLegoNotifyRoutine(PVOID LegoNotifyRoutine
)
118 /* Set the System-Wide Lego Routine */
119 PspLegoNotifyRoutine
= LegoNotifyRoutine
;
121 /* Return the location to the Lego Data */
122 return FIELD_OFFSET(KTHREAD
, LegoData
);
130 PsRemoveLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
133 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
136 /* Loop all callbacks */
137 for (i
= 0; i
< PSP_MAX_LOAD_IMAGE_NOTIFY
; i
++)
139 /* Reference this slot */
140 CallBack
= ExReferenceCallBackBlock(&PspLoadImageNotifyRoutine
[i
]);
143 /* Check for a match */
144 if (ExGetCallBackBlockRoutine(CallBack
) == (PVOID
)NotifyRoutine
)
146 /* Try removing it if it matches */
147 if (ExCompareExchangeCallBack(&PspLoadImageNotifyRoutine
[i
],
151 /* We removed it, now dereference the block */
152 InterlockedDecrement((PLONG
)&PspLoadImageNotifyRoutineCount
);
153 ExDereferenceCallBackBlock(&PspLoadImageNotifyRoutine
[i
],
156 /* Wait for active callbacks */
157 ExWaitForCallBacks(CallBack
);
159 /* Free the callback and return */
160 ExFreeCallBack(CallBack
);
161 return STATUS_SUCCESS
;
165 /* Dereference the callback */
166 ExDereferenceCallBackBlock(&PspLoadImageNotifyRoutine
[i
], CallBack
);
170 /* Nothing found to remove */
171 return STATUS_PROCEDURE_NOT_FOUND
;
179 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
182 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
185 /* Allocate a callback */
186 CallBack
= ExAllocateCallBack((PVOID
)NotifyRoutine
, NULL
);
187 if (!CallBack
) return STATUS_INSUFFICIENT_RESOURCES
;
190 for (i
= 0; i
< PSP_MAX_LOAD_IMAGE_NOTIFY
; i
++)
192 /* Add this entry if the slot is empty */
193 if (ExCompareExchangeCallBack(&PspLoadImageNotifyRoutine
[i
],
198 InterlockedIncrement((PLONG
)&PspLoadImageNotifyRoutineCount
);
199 PsImageNotifyEnabled
= TRUE
;
200 return STATUS_SUCCESS
;
204 /* No free space found, fail */
205 ExFreeCallBack(CallBack
);
206 return STATUS_INSUFFICIENT_RESOURCES
;
214 PsRemoveCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
217 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
220 /* Loop all callbacks */
221 for (i
= 0; i
< PSP_MAX_CREATE_THREAD_NOTIFY
; i
++)
223 /* Reference this slot */
224 CallBack
= ExReferenceCallBackBlock(&PspThreadNotifyRoutine
[i
]);
227 /* Check for a match */
228 if (ExGetCallBackBlockRoutine(CallBack
) == (PVOID
)NotifyRoutine
)
230 /* Try removing it if it matches */
231 if (ExCompareExchangeCallBack(&PspThreadNotifyRoutine
[i
],
235 /* We removed it, now dereference the block */
236 InterlockedDecrement((PLONG
)&PspThreadNotifyRoutineCount
);
237 ExDereferenceCallBackBlock(&PspThreadNotifyRoutine
[i
],
240 /* Wait for active callbacks */
241 ExWaitForCallBacks(CallBack
);
243 /* Free the callback and return */
244 ExFreeCallBack(CallBack
);
245 return STATUS_SUCCESS
;
249 /* Dereference the callback */
250 ExDereferenceCallBackBlock(&PspThreadNotifyRoutine
[i
], CallBack
);
254 /* Nothing found to remove */
255 return STATUS_PROCEDURE_NOT_FOUND
;
263 PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
266 PEX_CALLBACK_ROUTINE_BLOCK CallBack
;
269 /* Allocate a callback */
270 CallBack
= ExAllocateCallBack((PVOID
)NotifyRoutine
, NULL
);
271 if (!CallBack
) return STATUS_INSUFFICIENT_RESOURCES
;
274 for (i
= 0; i
< PSP_MAX_CREATE_THREAD_NOTIFY
; i
++)
276 /* Add this entry if the slot is empty */
277 if (ExCompareExchangeCallBack(&PspThreadNotifyRoutine
[i
],
282 InterlockedIncrement((PLONG
)&PspThreadNotifyRoutineCount
);
283 return STATUS_SUCCESS
;
287 /* No free space found, fail */
288 ExFreeCallBack(CallBack
);
289 return STATUS_INSUFFICIENT_RESOURCES
;