- Large cleanup of exported callback implementation. It was my first code to ReactOS and quite messy.

- Make code use standard NT structures.
- Fix object type initialization.
- Fix calls to ExCreatecallback during system initalization which were randomly overwriting memory.
- Fix ExREgisterCallback which was allocating only a pointer inside of the entire structure, also over-writing system memory.

svn path=/trunk/; revision=25482
This commit is contained in:
Alex Ionescu 2007-01-16 04:16:31 +00:00
parent 532a28a03c
commit b51d473275
3 changed files with 181 additions and 174 deletions

View file

@ -488,11 +488,25 @@ typedef __ALIGNED(16) struct _EX_PUSH_LOCK_WAIT_BLOCK
// //
typedef struct _CALLBACK_OBJECT typedef struct _CALLBACK_OBJECT
{ {
ULONG Name; ULONG Signature;
KSPIN_LOCK Lock; KSPIN_LOCK Lock;
LIST_ENTRY RegisteredCallbacks; LIST_ENTRY RegisteredCallbacks;
ULONG AllowMultipleCallbacks; BOOLEAN AllowMultipleCallbacks;
} CALLBACK_OBJECT , *PCALLBACK_OBJECT; UCHAR reserved[3];
} CALLBACK_OBJECT, *PCALLBACK_OBJECT;
//
// Callback Handle
//
typedef struct _CALLBACK_REGISTRATION
{
LIST_ENTRY Link;
PCALLBACK_OBJECT CallbackObject;
PCALLBACK_FUNCTION CallbackFunction;
PVOID CallbackContext;
ULONG Busy;
BOOLEAN UnregisterWaiting;
} CALLBACK_REGISTRATION, *PCALLBACK_REGISTRATION;
// //
// Internal Callback Object // Internal Callback Object

View file

@ -3,22 +3,16 @@
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ex/callback.c * FILE: ntoskrnl/ex/callback.c
* PURPOSE: Executive callbacks * PURPOSE: Executive callbacks
* PROGRAMMERS: Filip Navara * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Alex Ionescu (alex@relsoft.net)
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES ******************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#if defined (ALLOC_PRAGMA) /* TYPES *********************************************************************/
#pragma alloc_text(INIT, ExpInitializeCallbacks)
#endif
/* TYPES ********************************************************************/
/* Mapping for Callback Object */ /* Mapping for Callback Object */
GENERIC_MAPPING ExpCallbackMapping = GENERIC_MAPPING ExpCallbackMapping =
@ -29,28 +23,10 @@ GENERIC_MAPPING ExpCallbackMapping =
CALLBACK_ALL_ACCESS CALLBACK_ALL_ACCESS
}; };
/* Structure used to hold Callbacks */
typedef struct _CALLBACK_REGISTRATION
{
LIST_ENTRY RegisteredCallbacks;
PCALLBACK_OBJECT CallbackObject;
PCALLBACK_FUNCTION CallbackFunction;
PVOID CallbackContext;
ULONG InUse;
BOOLEAN PendingDeletion;
} CALLBACK_REGISTRATION, *PCALLBACK_REGISTRATION;
typedef struct
{
PCALLBACK_OBJECT *CallbackObject;
PWSTR Name;
} SYSTEM_CALLBACKS;
/* Kernel Default Callbacks */ /* Kernel Default Callbacks */
PCALLBACK_OBJECT SetSystemTimeCallback; PCALLBACK_OBJECT SetSystemTimeCallback;
PCALLBACK_OBJECT SetSystemStateCallback; PCALLBACK_OBJECT SetSystemStateCallback;
PCALLBACK_OBJECT PowerStateCallback; PCALLBACK_OBJECT PowerStateCallback;
SYSTEM_CALLBACKS ExpInitializeCallback[] = SYSTEM_CALLBACKS ExpInitializeCallback[] =
{ {
{&SetSystemTimeCallback, L"\\Callback\\SetSystemTime"}, {&SetSystemTimeCallback, L"\\Callback\\SetSystemTime"},
@ -62,7 +38,15 @@ SYSTEM_CALLBACKS ExpInitializeCallback[] =
POBJECT_TYPE ExCallbackObjectType; POBJECT_TYPE ExCallbackObjectType;
KEVENT ExpCallbackEvent; KEVENT ExpCallbackEvent;
/* FUNCTIONS *****************************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
ExpDeleteCallback(IN PVOID Object)
{
/* Sanity check */
ASSERT(IsListEmpty(&((PCALLBACK_OBJECT)Object)->RegisteredCallbacks));
}
/*++ /*++
* @name ExpInitializeCallbacks * @name ExpInitializeCallbacks
@ -75,7 +59,7 @@ KEVENT ExpCallbackEvent;
* @remarks None * @remarks None
* *
*--*/ *--*/
VOID BOOLEAN
INIT_FUNCTION INIT_FUNCTION
NTAPI NTAPI
ExpInitializeCallbacks(VOID) ExpInitializeCallbacks(VOID)
@ -93,39 +77,29 @@ ExpInitializeCallbacks(VOID)
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Callback"); RtlInitUnicodeString(&Name, L"Callback");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CALLBACK_OBJECT); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
ObjectTypeInitializer.GenericMapping = ExpCallbackMapping; ObjectTypeInitializer.GenericMapping = ExpCallbackMapping;
ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.DeleteProcedure = ExpDeleteCallback;
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExCallbackObjectType); ObjectTypeInitializer.ValidAccessMask = CALLBACK_ALL_ACCESS;
Status = ObCreateObjectType(&Name,
/* Fail if it wasn't created successfully */ &ObjectTypeInitializer,
if (!NT_SUCCESS(Status)) NULL,
{ &ExCallbackObjectType);
return; if (!NT_SUCCESS(Status)) return FALSE;
}
/* Initialize the Object */ /* Initialize the Object */
InitializeObjectAttributes( InitializeObjectAttributes(&ObjectAttributes,
&ObjectAttributes,
&DirName, &DirName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL, NULL,
NULL SePublicDefaultSd);
);
/* Create the Object Directory */ /* Create the Object Directory */
Status = NtCreateDirectoryObject( Status = NtCreateDirectoryObject(&DirectoryHandle,
&DirectoryHandle,
DIRECTORY_ALL_ACCESS, DIRECTORY_ALL_ACCESS,
&ObjectAttributes &ObjectAttributes);
); if (!NT_SUCCESS(Status)) return FALSE;
/* Fail if couldn't create */
if (!NT_SUCCESS(Status))
{
return;
}
/* Close Handle... */ /* Close Handle... */
NtClose(DirectoryHandle); NtClose(DirectoryHandle);
@ -134,37 +108,32 @@ ExpInitializeCallbacks(VOID)
KeInitializeEvent(&ExpCallbackEvent, NotificationEvent, 0); KeInitializeEvent(&ExpCallbackEvent, NotificationEvent, 0);
/* Default NT Kernel Callbacks. */ /* Default NT Kernel Callbacks. */
for (i=0; ExpInitializeCallback[i].CallbackObject; i++) for (i = 0; ExpInitializeCallback[i].CallbackObject; i++)
{ {
/* Create the name from the structure */ /* Create the name from the structure */
RtlInitUnicodeString(&CallbackName, ExpInitializeCallback[i].Name); RtlInitUnicodeString(&CallbackName, ExpInitializeCallback[i].Name);
/* Initialize the Object Attributes Structure */ /* Initialize the Object Attributes Structure */
InitializeObjectAttributes( InitializeObjectAttributes(&ObjectAttributes,
&ObjectAttributes,
&CallbackName, &CallbackName,
OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
NULL, NULL,
NULL NULL);
);
/* Create the Callback Object */ /* Create the Callback Object */
Status = ExCreateCallback( Status = ExCreateCallback(ExpInitializeCallback[i].CallbackObject,
(PCALLBACK_OBJECT*)&(ExpInitializeCallback[i].CallbackObject),
&ObjectAttributes, &ObjectAttributes,
TRUE, TRUE,
TRUE TRUE);
); if (!NT_SUCCESS(Status)) return FALSE;
}
/* Make sure Global Callbacks have been created */
if (!NT_SUCCESS(Status))
{
return;
}
}
/* Everything successful */ /* Everything successful */
return TRUE;
} }
/* PUBLIC FUNCTIONS **********************************************************/
/*++ /*++
* @name ExCreateCallback * @name ExCreateCallback
* @implemented * @implemented
@ -200,15 +169,15 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
IN BOOLEAN Create, IN BOOLEAN Create,
IN BOOLEAN AllowMultipleCallbacks) IN BOOLEAN AllowMultipleCallbacks)
{ {
PCALLBACK_OBJECT Callback; PCALLBACK_OBJECT Callback = NULL;
NTSTATUS Status; NTSTATUS Status;
HANDLE Handle; HANDLE Handle = NULL;
PAGED_CODE(); PAGED_CODE();
/* Open a handle to the callback if it exists */ /* Open a handle to the callback if it exists */
if (ObjectAttributes->ObjectName) if (ObjectAttributes->ObjectName)
{ {
/* Open the handle */
Status = ObOpenObjectByName(ObjectAttributes, Status = ObOpenObjectByName(ObjectAttributes,
ExCallbackObjectType, ExCallbackObjectType,
KernelMode, KernelMode,
@ -219,12 +188,14 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
} }
else else
{ {
/* Otherwise, fail */
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
} }
/* We weren't able to open it...should we create it? */ /* We weren't able to open it...should we create it? */
if(!NT_SUCCESS(Status) && Create ) if (!(NT_SUCCESS(Status)) && (Create))
{ {
/* Create the object */
Status = ObCreateObject(KernelMode, Status = ObCreateObject(KernelMode,
ExCallbackObjectType, ExCallbackObjectType,
ObjectAttributes, ObjectAttributes,
@ -233,25 +204,27 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
sizeof(CALLBACK_OBJECT), sizeof(CALLBACK_OBJECT),
0, 0,
0, 0,
(PVOID *)&Callback ); (PVOID *)&Callback);
if (NT_SUCCESS(Status))
/* We Created it...let's initialize the structure now */
if(NT_SUCCESS(Status))
{ {
KeInitializeSpinLock(&Callback->Lock); /* SpinLock */ /* Set it up */
InitializeListHead(&Callback->RegisteredCallbacks); /* Callback Entries */ Callback->Signature = TAG('C', 'a', 'l', 'l');
Callback->AllowMultipleCallbacks = AllowMultipleCallbacks; /* Multiple Callbacks */ KeInitializeSpinLock(&Callback->Lock);
/* Create the object */ InitializeListHead(&Callback->RegisteredCallbacks);
Callback->AllowMultipleCallbacks = AllowMultipleCallbacks;
/* Insert the object into the object namespace */
Status = ObInsertObject(Callback, Status = ObInsertObject(Callback,
NULL, NULL,
FILE_READ_DATA, FILE_READ_DATA,
0, 0,
NULL, NULL,
&Handle ); &Handle);
} }
} }
if(NT_SUCCESS(Status)) /* Check if we have success until here */
if (NT_SUCCESS(Status))
{ {
/* Get a pointer to the new object from the handle we just got */ /* Get a pointer to the new object from the handle we just got */
Status = ObReferenceObjectByHandle(Handle, Status = ObReferenceObjectByHandle(Handle,
@ -260,15 +233,13 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
KernelMode, KernelMode,
(PVOID)&Callback, (PVOID)&Callback,
NULL); NULL);
/* Close the Handle, since we now have the pointer */ /* Close the Handle, since we now have the pointer */
ZwClose(Handle); ZwClose(Handle);
} }
/* Everything went fine, so return a pointer to the Object */ /* Everything went fine, so return a pointer to the Object */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status)) *CallbackObject = Callback;
{
*CallbackObject = (PCALLBACK_OBJECT)Callback;
}
return Status; return Status;
} }
@ -278,7 +249,6 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
* *
* Calls a function pointer (a registered callback) * Calls a function pointer (a registered callback)
* See: http://www.osronline.com/ddkx/kmarch/k102_2f5e.htm * See: http://www.osronline.com/ddkx/kmarch/k102_2f5e.htm
* http://msdn.microsoft.com/library/en-us/Kernel_d/hh/Kernel_d/Synchro_e954f515-e536-4e12-8419-e7e54c4a963b.xml.asp?frame=true
* http://vmsone.com/~decuslib/vmssig/vmslt99b/nt/wdm-callback.txt * http://vmsone.com/~decuslib/vmssig/vmslt99b/nt/wdm-callback.txt
* *
* @param CallbackObject * @param CallbackObject
@ -297,17 +267,24 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
*--*/ *--*/
VOID VOID
NTAPI NTAPI
ExNotifyCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject, ExNotifyCallback(IN PCALLBACK_OBJECT CallbackObject,
IN PVOID Argument1, IN PVOID Argument1,
IN PVOID Argument2) IN PVOID Argument2)
{ {
PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject;
PLIST_ENTRY RegisteredCallbacks; PLIST_ENTRY RegisteredCallbacks;
PCALLBACK_REGISTRATION CallbackRegistration; PCALLBACK_REGISTRATION CallbackRegistration;
KIRQL OldIrql; KIRQL OldIrql;
/* Check if we don't have an object or registrations */
if (!(CallbackObject) ||
(IsListEmpty(&CallbackObject->RegisteredCallbacks)))
{
/* Don't notify */
return;
}
/* Acquire the Lock */ /* Acquire the Lock */
OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
/* Enumerate through all the registered functions */ /* Enumerate through all the registered functions */
for (RegisteredCallbacks = CallbackObject->RegisteredCallbacks.Flink; for (RegisteredCallbacks = CallbackObject->RegisteredCallbacks.Flink;
@ -317,39 +294,41 @@ ExNotifyCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject,
/* Get a pointer to a Callback Registration from the List Entries */ /* Get a pointer to a Callback Registration from the List Entries */
CallbackRegistration = CONTAINING_RECORD(RegisteredCallbacks, CallbackRegistration = CONTAINING_RECORD(RegisteredCallbacks,
CALLBACK_REGISTRATION, CALLBACK_REGISTRATION,
RegisteredCallbacks); Link);
/* Don't bother doing Callback Notification if it's pending to be deleted */ /* Don't bother doing notification if it's pending to be deleted */
if (!CallbackRegistration->PendingDeletion) if (!CallbackRegistration->UnregisterWaiting)
{ {
/* Mark the Callback in use, so it won't get deleted while we are calling it */ /* Mark the Callback in use, so it won't get deleted */
CallbackRegistration->InUse += 1; CallbackRegistration->Busy += 1;
/* Release the Spinlock before making the call */ /* Release the Spinlock before making the call */
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
/* Call the Registered Function */ /* Call the Registered Function */
CallbackRegistration->CallbackFunction( CallbackRegistration->CallbackFunction(CallbackRegistration->
CallbackRegistration->CallbackContext, CallbackContext,
Argument1, Argument1,
Argument2 Argument2);
);
/* Get SpinLock back */ /* Get SpinLock back */
OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
/* We are not in use anymore */ /* We are not in use anymore */
CallbackRegistration->InUse -= 1; CallbackRegistration->Busy -= 1;
/* If another instance of this function isn't running and deletion is pending, signal the event */ /* Check if removal is pending and we're not active */
if (CallbackRegistration->PendingDeletion && CallbackRegistration->InUse == 0) if ((CallbackRegistration->UnregisterWaiting) &&
!(CallbackRegistration->Busy))
{ {
/* Signal the callback event */
KeSetEvent(&ExpCallbackEvent, 0, FALSE); KeSetEvent(&ExpCallbackEvent, 0, FALSE);
} }
} }
} }
/* Unsynchronize and release the Callback Object */
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); /* Release the Callback Object */
KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
} }
/*++ /*++
@ -377,53 +356,64 @@ ExNotifyCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject,
*--*/ *--*/
PVOID PVOID
NTAPI NTAPI
ExRegisterCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject, ExRegisterCallback(IN PCALLBACK_OBJECT CallbackObject,
IN PCALLBACK_FUNCTION CallbackFunction, IN PCALLBACK_FUNCTION CallbackFunction,
IN PVOID CallbackContext) IN PVOID CallbackContext)
{ {
PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject;
PCALLBACK_REGISTRATION CallbackRegistration = NULL; PCALLBACK_REGISTRATION CallbackRegistration = NULL;
KIRQL OldIrql; KIRQL OldIrql;
PAGED_CODE(); /* Sanity checks */
ASSERT(CallbackFunction);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Create reference to Callback Object */ /* Create reference to Callback Object */
ObReferenceObject (CallbackObject); ObReferenceObject(CallbackObject);
/* Allocate memory for the structure */ /* Allocate memory for the structure */
CallbackRegistration = ExAllocatePoolWithTag( CallbackRegistration = ExAllocatePoolWithTag(NonPagedPool,
NonPagedPool, sizeof(CALLBACK_REGISTRATION),
sizeof(CallbackRegistration), CALLBACK_TAG);
CALLBACK_TAG if (!CallbackRegistration)
);
/* Fail if memory allocation failed */
if(!CallbackRegistration)
{ {
/* Dereference and fail */
ObDereferenceObject (CallbackObject); ObDereferenceObject (CallbackObject);
return NULL; return NULL;
} }
/* Create Callback Registration */ /* Create Callback Registration */
CallbackRegistration->CallbackObject = CallbackObject; /* When unregistering, drivers send a handle to the Registration, not the object... */ CallbackRegistration->CallbackObject = CallbackObject;
CallbackRegistration->CallbackFunction = CallbackFunction; /* NotifyCallback uses Objects, so this needs to be here in order to call the registered functions */ CallbackRegistration->CallbackFunction = CallbackFunction;
CallbackRegistration->CallbackContext = CallbackContext; /* The documented NotifyCallback returns the Context, so we must save this somewhere */ CallbackRegistration->CallbackContext = CallbackContext;
CallbackRegistration->Busy = 0;
CallbackRegistration->UnregisterWaiting = FALSE;
/* Acquire SpinLock */ /* Acquire SpinLock */
OldIrql = KfAcquireSpinLock (&CallbackObject->Lock); KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
/* Add Callback if 1) No Callbacks registered or 2) Multiple Callbacks allowed */ /* Check if 1) No Callbacks registered or 2) Multiple Callbacks allowed */
if(CallbackObject->AllowMultipleCallbacks || IsListEmpty(&CallbackObject->RegisteredCallbacks)) if ((CallbackObject->AllowMultipleCallbacks) ||
(IsListEmpty(&CallbackObject->RegisteredCallbacks)))
{ {
InsertTailList(&CallbackObject->RegisteredCallbacks,&CallbackRegistration->RegisteredCallbacks); /* Register the callback */
InsertTailList(&CallbackObject->RegisteredCallbacks,
&CallbackRegistration->Link);
/* Release SpinLock */
KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
} }
else else
{ {
/* Release SpinLock */
KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
/* Free the registration */
ExFreePool(CallbackRegistration); ExFreePool(CallbackRegistration);
CallbackRegistration = NULL; CallbackRegistration = NULL;
}
/* Release SpinLock */ /* Dereference the object */
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); ObDereferenceObject(CallbackObject);
}
/* Return handle to Registration Object */ /* Return handle to Registration Object */
return (PVOID)CallbackRegistration; return (PVOID)CallbackRegistration;
@ -451,48 +441,45 @@ ExUnregisterCallback(IN PVOID CallbackRegistrationHandle)
PCALLBACK_REGISTRATION CallbackRegistration; PCALLBACK_REGISTRATION CallbackRegistration;
PCALLBACK_OBJECT CallbackObject; PCALLBACK_OBJECT CallbackObject;
KIRQL OldIrql; KIRQL OldIrql;
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
PAGED_CODE();
/* Convert Handle to valid Structure Pointer */ /* Convert Handle to valid Structure Pointer */
CallbackRegistration = (PCALLBACK_REGISTRATION) CallbackRegistrationHandle; CallbackRegistration = (PCALLBACK_REGISTRATION)CallbackRegistrationHandle;
/* Get the Callback Object */ /* Get the Callback Object */
CallbackObject = CallbackRegistration->CallbackObject; CallbackObject = CallbackRegistration->CallbackObject;
/* Lock the Object */ /* Lock the Object */
OldIrql = KfAcquireSpinLock (&CallbackObject->Lock); KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
/* We can't Delete the Callback if it's in use, because this would create a call towards a null pointer => crash */ /* We can't Delete the Callback if it's in use */
while (CallbackRegistration->InUse) while (CallbackRegistration->Busy)
{ {
/* Similarly, we also don't want to wait ages for all pending callbacks to be called */ /* Let everyone else know we're unregistering */
CallbackRegistration->PendingDeletion = TRUE; CallbackRegistration->UnregisterWaiting = TRUE;
/* We are going to wait for the event, so the Lock isn't necessary */ /* We are going to wait for the event, so the Lock isn't necessary */
KfReleaseSpinLock (&CallbackObject->Lock, OldIrql); KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
/* Make sure the event is cleared */ /* Make sure the event is cleared */
KeClearEvent (&ExpCallbackEvent); KeClearEvent(&ExpCallbackEvent);
/* Wait for the Event */ /* Wait for the Event */
KeWaitForSingleObject ( KeWaitForSingleObject(&ExpCallbackEvent,
&ExpCallbackEvent,
Executive, Executive,
KernelMode, KernelMode,
FALSE, FALSE,
NULL NULL);
);
/* We need the Lock again */ /* We need the Lock again */
OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
} }
/* Remove the Callback */ /* Remove the Callback */
RemoveEntryList(&CallbackRegistration->RegisteredCallbacks); RemoveEntryList(&CallbackRegistration->Link);
/* It's now safe to release the lock */ /* It's now safe to release the lock */
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
/* Delete this registration */ /* Delete this registration */
ExFreePool(CallbackRegistration); ExFreePool(CallbackRegistration);

View file

@ -34,6 +34,12 @@ typedef struct _ETIMER
LIST_ENTRY WakeTimerListEntry; LIST_ENTRY WakeTimerListEntry;
} ETIMER, *PETIMER; } ETIMER, *PETIMER;
typedef struct
{
PCALLBACK_OBJECT *CallbackObject;
PWSTR Name;
} SYSTEM_CALLBACKS;
#define MAX_FAST_REFS 7 #define MAX_FAST_REFS 7
#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \ #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
@ -107,7 +113,7 @@ ExInitializeSystemLookasideList(
IN PLIST_ENTRY ListHead IN PLIST_ENTRY ListHead
); );
VOID BOOLEAN
NTAPI NTAPI
ExpInitializeCallbacks(VOID); ExpInitializeCallbacks(VOID);