diff --git a/reactos/ntoskrnl/ex/callback.c b/reactos/ntoskrnl/ex/callback.c index c0c7adca428..35b9a44590b 100644 --- a/reactos/ntoskrnl/ex/callback.c +++ b/reactos/ntoskrnl/ex/callback.c @@ -1,9 +1,10 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ex/callback.c * PURPOSE: Executive callbacks - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * PROGRAMMERS: Filip Navara + * Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ @@ -63,433 +64,441 @@ KEVENT ExpCallbackEvent; /* FUNCTIONS *****************************************************************/ -/* - * ExpInitializeCallbacks +/*++ + * @name ExpInitializeCallbacks * - * FUNCTION: * Creates the Callback Object as a valid Object Type in the Kernel. + * Internal function, subject to further review * - * ARGUMENTS: - * None + * @return TRUE if the Callback Object Type was successfully created. * - * RETURNS: - * TRUE if the Callback Object Type was successfully created. - */ + * @remarks None + * + *--*/ VOID INIT_FUNCTION -STDCALL +NTAPI ExpInitializeCallbacks(VOID) { - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status; - UNICODE_STRING DirName = RTL_CONSTANT_STRING(L"\\Callback"); - UNICODE_STRING CallbackName; - UNICODE_STRING Name; - OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; - HANDLE DirectoryHandle; - ULONG i; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + UNICODE_STRING DirName = RTL_CONSTANT_STRING(L"\\Callback"); + UNICODE_STRING CallbackName; + UNICODE_STRING Name; + OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; + HANDLE DirectoryHandle; + ULONG i; - /* Initialize the Callback Object type */ - RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); - RtlInitUnicodeString(&Name, L"Callback"); - ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); - ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CALLBACK_OBJECT); - ObjectTypeInitializer.GenericMapping = ExpCallbackMapping; - ObjectTypeInitializer.PoolType = NonPagedPool; + /* Initialize the Callback Object type */ + RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); + RtlInitUnicodeString(&Name, L"Callback"); + ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); + ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CALLBACK_OBJECT); + ObjectTypeInitializer.GenericMapping = ExpCallbackMapping; + ObjectTypeInitializer.PoolType = NonPagedPool; - Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExCallbackObjectType); + Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExCallbackObjectType); - /* Fail if it wasn't created successfully */ - if (!NT_SUCCESS(Status)) - { - return; - } + /* Fail if it wasn't created successfully */ + if (!NT_SUCCESS(Status)) + { + return; + } - /* Initialize the Object */ - InitializeObjectAttributes( - &ObjectAttributes, - &DirName, - OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, - NULL, - NULL - ); + /* Initialize the Object */ + InitializeObjectAttributes( + &ObjectAttributes, + &DirName, + OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, + NULL, + NULL + ); - /* Create the Object Directory */ - Status = NtCreateDirectoryObject( - &DirectoryHandle, - DIRECTORY_ALL_ACCESS, - &ObjectAttributes + /* Create the Object Directory */ + Status = NtCreateDirectoryObject( + &DirectoryHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes + ); + + /* Fail if couldn't create */ + if (!NT_SUCCESS(Status)) + { + return; + } + + /* Close Handle... */ + NtClose(DirectoryHandle); + + /* Initialize Event used when unregistering */ + KeInitializeEvent(&ExpCallbackEvent, NotificationEvent, 0); + + /* Default NT Kernel Callbacks. */ + for (i=0; ExpInitializeCallback[i].CallbackObject; i++) + { + /* Create the name from the structure */ + RtlInitUnicodeString(&CallbackName, ExpInitializeCallback[i].Name); + + /* Initialize the Object Attributes Structure */ + InitializeObjectAttributes( + &ObjectAttributes, + &CallbackName, + OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, + NULL, + NULL ); - /* Fail if couldn't create */ - if (!NT_SUCCESS(Status)) - { - return; - } + /* Create the Callback Object */ + Status = ExCreateCallback( + (PCALLBACK_OBJECT*)&(ExpInitializeCallback[i].CallbackObject), + &ObjectAttributes, + TRUE, + TRUE + ); - /* Close Handle... */ - NtClose(DirectoryHandle); - - /* Initialize Event used when unregistering */ - KeInitializeEvent(&ExpCallbackEvent, NotificationEvent, 0); - - /* Default NT Kernel Callbacks. */ - for (i=0; ExpInitializeCallback[i].CallbackObject; i++) - { - /* Create the name from the structure */ - RtlInitUnicodeString(&CallbackName, ExpInitializeCallback[i].Name); - - /* Initialize the Object Attributes Structure */ - InitializeObjectAttributes( - &ObjectAttributes, - &CallbackName, - OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, - NULL, - NULL - ); - - /* Create the Callback Object */ - Status = ExCreateCallback( - (PCALLBACK_OBJECT*)&(ExpInitializeCallback[i].CallbackObject), - &ObjectAttributes, - TRUE, - TRUE - ); - - /* Make sure Global Callbacks have been created */ - if (!NT_SUCCESS(Status)) - { - return; - } - } - /* Everything successful */ + /* Make sure Global Callbacks have been created */ + if (!NT_SUCCESS(Status)) + { + return; + } + } + /* Everything successful */ } -/* - * ExCreateCallback +/*++ + * @name ExCreateCallback + * @implemented * - * FUNCTION: * Opens or creates a Callback Object. Creates only if Create is true. - * Allows multiple Callback Functions to be registred only if AllowMultipleCallbacks - * is true. + * Allows multiple Callback Functions to be registred only if + * AllowMultipleCallbacks is true. + * See: http://www.osronline.com/ddkx/kmarch/k102_967m.htm + * http://www.osronline.com/article.cfm?id=24 * - * ARGUMENTS: - * CallbackObject = Pointer that will receive the Callback Object. - * CallbackName = Name of Callback - * Create = Determines if the object will be created if it doesn't exit - * AllowMultipleCallbacks = Determines if more then one registered callback function - * can be attached to this Callback Object. + * @param CallbackObject + * Pointer that will receive the Callback Object. * - * RETURNS: - * STATUS_SUCESS if not failed. + * @param CallbackName + * Name of Callback * - * @implemented - */ + * @param Create + * Determines if the object will be created if it doesn't exit + * + * @param AllowMultipleCallbacks + * Determines if more then one registered callback function + * can be attached to this Callback Object. + * + * @return STATUS_SUCESS if not failed. + * + * @remarks Must be called at IRQL = PASSIVE_LEVEL + * + *--*/ NTSTATUS -STDCALL -ExCreateCallback( - OUT PCALLBACK_OBJECT *CallbackObject, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN BOOLEAN Create, - IN BOOLEAN AllowMultipleCallbacks -) +NTAPI +ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN Create, + IN BOOLEAN AllowMultipleCallbacks) { - PCALLBACK_OBJECT Callback; - NTSTATUS Status; - HANDLE Handle; + PCALLBACK_OBJECT Callback; + NTSTATUS Status; + HANDLE Handle; - PAGED_CODE(); + PAGED_CODE(); - /* Open a handle to the callback if it exists */ - if (ObjectAttributes->ObjectName) - { - Status = ObOpenObjectByName(ObjectAttributes, - ExCallbackObjectType, - KernelMode, - NULL, - 0, - NULL, - &Handle); - } - else - { - Status = STATUS_UNSUCCESSFUL; - } + /* Open a handle to the callback if it exists */ + if (ObjectAttributes->ObjectName) + { + Status = ObOpenObjectByName(ObjectAttributes, + ExCallbackObjectType, + KernelMode, + NULL, + 0, + NULL, + &Handle); + } + else + { + Status = STATUS_UNSUCCESSFUL; + } - /* We weren't able to open it...should we create it? */ - if(!NT_SUCCESS(Status) && Create ) - { - Status = ObCreateObject(KernelMode, - ExCallbackObjectType, - ObjectAttributes, - KernelMode, - NULL, - sizeof(CALLBACK_OBJECT), - 0, - 0, - (PVOID *)&Callback ); + /* We weren't able to open it...should we create it? */ + if(!NT_SUCCESS(Status) && Create ) + { + Status = ObCreateObject(KernelMode, + ExCallbackObjectType, + ObjectAttributes, + KernelMode, + NULL, + sizeof(CALLBACK_OBJECT), + 0, + 0, + (PVOID *)&Callback ); - /* We Created it...let's initialize the structure now */ - if(NT_SUCCESS(Status)) - { - KeInitializeSpinLock (&Callback->Lock); /* SpinLock */ - InitializeListHead(&Callback->RegisteredCallbacks); /* Callback Entries */ - Callback->AllowMultipleCallbacks = AllowMultipleCallbacks; /* Multiple Callbacks */ - Status = ObInsertObject ( /* Create the object */ - Callback, - NULL, - FILE_READ_DATA, - 0, - NULL, - &Handle ); - } - } - if(NT_SUCCESS(Status)) - { + /* We Created it...let's initialize the structure now */ + if(NT_SUCCESS(Status)) + { + KeInitializeSpinLock(&Callback->Lock); /* SpinLock */ + InitializeListHead(&Callback->RegisteredCallbacks); /* Callback Entries */ + Callback->AllowMultipleCallbacks = AllowMultipleCallbacks; /* Multiple Callbacks */ + /* Create the object */ + Status = ObInsertObject(Callback, + NULL, + FILE_READ_DATA, + 0, + NULL, + &Handle ); + } + } - /* Get a pointer to the new object from the handle we just got */ - Status = ObReferenceObjectByHandle ( - Handle, - 0, - ExCallbackObjectType, - KernelMode, - (PVOID)&Callback, - NULL - ); - /* Close the Handle, since we now have the pointer */ - ZwClose(Handle); - } + if(NT_SUCCESS(Status)) + { + /* Get a pointer to the new object from the handle we just got */ + Status = ObReferenceObjectByHandle(Handle, + 0, + ExCallbackObjectType, + KernelMode, + (PVOID)&Callback, + NULL); + /* Close the Handle, since we now have the pointer */ + ZwClose(Handle); + } - /* Everything went fine, so return a pointer to the Object */ - if (NT_SUCCESS(Status)) - { - *CallbackObject = (PCALLBACK_OBJECT)Callback; - } - return Status; + /* Everything went fine, so return a pointer to the Object */ + if (NT_SUCCESS(Status)) + { + *CallbackObject = (PCALLBACK_OBJECT)Callback; + } + return Status; } -/* - * ExNotifyCallback - * - * FUNCTION: - * Calls a function pointer (a registered callback) - * - * ARGUMENTS: - * CallbackObject - Which callback to call - * Argument1 - Pointer/data to send to callback function - * Argument2 - Pointer/data to send to callback function - * - * RETURNS: - * Nothing - * +/*++ + * @name ExNotifyCallback * @implemented - */ + * + * Calls a function pointer (a registered callback) + * 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 + * + * @param CallbackObject + * Which callback to call + * + * @param Argument1 + * Pointer/data to send to callback function + * + * @param Argument2 + * Pointer/data to send to callback function + * + * @return None + * + * @remarks None + * + *--*/ VOID -STDCALL -ExNotifyCallback( - IN PCALLBACK_OBJECT OpaqueCallbackObject, - IN PVOID Argument1, - IN PVOID Argument2 -) +NTAPI +ExNotifyCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject, + IN PVOID Argument1, + IN PVOID Argument2) { - PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject; - PLIST_ENTRY RegisteredCallbacks; - PCALLBACK_REGISTRATION CallbackRegistration; - KIRQL OldIrql; + PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject; + PLIST_ENTRY RegisteredCallbacks; + PCALLBACK_REGISTRATION CallbackRegistration; + KIRQL OldIrql; - /* Acquire the Lock */ - OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); + /* Acquire the Lock */ + OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); - /* Enumerate through all the registered functions */ - for (RegisteredCallbacks = CallbackObject->RegisteredCallbacks.Flink; + /* Enumerate through all the registered functions */ + for (RegisteredCallbacks = CallbackObject->RegisteredCallbacks.Flink; RegisteredCallbacks != &CallbackObject->RegisteredCallbacks; RegisteredCallbacks = RegisteredCallbacks->Flink) - { + { + /* Get a pointer to a Callback Registration from the List Entries */ + CallbackRegistration = CONTAINING_RECORD(RegisteredCallbacks, + CALLBACK_REGISTRATION, + RegisteredCallbacks); - /* Get a pointer to a Callback Registration from the List Entries */ - CallbackRegistration = CONTAINING_RECORD ( RegisteredCallbacks, - CALLBACK_REGISTRATION, - RegisteredCallbacks); + /* Don't bother doing Callback Notification if it's pending to be deleted */ + if (!CallbackRegistration->PendingDeletion) + { + /* Mark the Callback in use, so it won't get deleted while we are calling it */ + CallbackRegistration->InUse += 1; - /* Don't bother doing Callback Notification if it's pending to be deleted */ - if (!CallbackRegistration->PendingDeletion) - { + /* Release the Spinlock before making the call */ + KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); - /* Mark the Callback in use, so it won't get deleted while we are calling it */ - CallbackRegistration->InUse += 1; + /* Call the Registered Function */ + CallbackRegistration->CallbackFunction( + CallbackRegistration->CallbackContext, + Argument1, + Argument2 + ); - /* Release the Spinlock before making the call */ - KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); + /* Get SpinLock back */ + OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); - /* Call the Registered Function */ - CallbackRegistration->CallbackFunction ( - CallbackRegistration->CallbackContext, - Argument1, - Argument2 - ); + /* We are not in use anymore */ + CallbackRegistration->InUse -= 1; - /* Get SpinLock back */ - OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); - - /* We are not in use anymore */ - CallbackRegistration->InUse -= 1; - - /* If another instance of this function isn't running and deletion is pending, signal the event */ - if (CallbackRegistration->PendingDeletion && CallbackRegistration->InUse == 0) - { - KeSetEvent(&ExpCallbackEvent, 0, FALSE); - } - } - } - /* Unsynchronize and release the Callback Object */ - KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); + /* If another instance of this function isn't running and deletion is pending, signal the event */ + if (CallbackRegistration->PendingDeletion && CallbackRegistration->InUse == 0) + { + KeSetEvent(&ExpCallbackEvent, 0, FALSE); + } + } + } + /* Unsynchronize and release the Callback Object */ + KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); } -/* - * ExRegisterCallback - * - * FUNCTION: - * Allows a function to associate a callback pointer (Function) - * to a created Callback object - * - * ARGUMENTS: - * CallbackObject = The Object Created with ExCreateCallBack - * CallBackFunction = Pointer to the function to be called back - * CallBackContext = Block of memory that can contain user-data - * which will be passed on to the callback - * - * RETURNS: - * A handle to a Callback Registration Structure (MSDN Documentation) - * +/*++ + * @name ExRegisterCallback * @implemented - */ + * + * Allows a function to associate a callback pointer (Function) to + * a created Callback object + * See: DDK, OSR, links in ExNotifyCallback + * + * @param CallbackObject + * The Object Created with ExCreateCallBack + * + * @param CallBackFunction + * Pointer to the function to be called back + * + * @param CallBackContext + * Block of memory that can contain user-data which will be + * passed on to the callback + * + * @return A handle to a Callback Registration Structure (MSDN Documentation) + * + * @remarks None + * + *--*/ PVOID -STDCALL -ExRegisterCallback( - IN PCALLBACK_OBJECT OpaqueCallbackObject, - IN PCALLBACK_FUNCTION CallbackFunction, - IN PVOID CallbackContext -) +NTAPI +ExRegisterCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject, + IN PCALLBACK_FUNCTION CallbackFunction, + IN PVOID CallbackContext) { - PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject; - PCALLBACK_REGISTRATION CallbackRegistration = NULL; - KIRQL OldIrql; + PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject; + PCALLBACK_REGISTRATION CallbackRegistration = NULL; + KIRQL OldIrql; - PAGED_CODE(); + PAGED_CODE(); - /* Create reference to Callback Object */ - ObReferenceObject (CallbackObject); + /* Create reference to Callback Object */ + ObReferenceObject (CallbackObject); - /* Allocate memory for the structure */ - CallbackRegistration = ExAllocatePoolWithTag( - NonPagedPool, - sizeof(CallbackRegistration), - CALLBACK_TAG - ); - /* Fail if memory allocation failed */ - if(!CallbackRegistration) - { - ObDereferenceObject (CallbackObject); - return NULL; - } + /* Allocate memory for the structure */ + CallbackRegistration = ExAllocatePoolWithTag( + NonPagedPool, + sizeof(CallbackRegistration), + CALLBACK_TAG + ); + /* Fail if memory allocation failed */ + if(!CallbackRegistration) + { + ObDereferenceObject (CallbackObject); + return NULL; + } - /* Create Callback Registration */ - CallbackRegistration->CallbackObject = CallbackObject; /* When unregistering, drivers send a handle to the Registration, not the object... */ - CallbackRegistration->CallbackFunction = CallbackFunction; /* NotifyCallback uses Objects, so this needs to be here in order to call the registered functions */ - CallbackRegistration->CallbackContext = CallbackContext; /* The documented NotifyCallback returns the Context, so we must save this somewhere */ + /* Create Callback Registration */ + CallbackRegistration->CallbackObject = CallbackObject; /* When unregistering, drivers send a handle to the Registration, not the object... */ + CallbackRegistration->CallbackFunction = CallbackFunction; /* NotifyCallback uses Objects, so this needs to be here in order to call the registered functions */ + CallbackRegistration->CallbackContext = CallbackContext; /* The documented NotifyCallback returns the Context, so we must save this somewhere */ - /* Acquire SpinLock */ - OldIrql = KfAcquireSpinLock (&CallbackObject->Lock); + /* Acquire SpinLock */ + OldIrql = KfAcquireSpinLock (&CallbackObject->Lock); - /* Add Callback if 1) No Callbacks registered or 2) Multiple Callbacks allowed */ - if(CallbackObject->AllowMultipleCallbacks || IsListEmpty(&CallbackObject->RegisteredCallbacks)) - { - InsertTailList(&CallbackObject->RegisteredCallbacks,&CallbackRegistration->RegisteredCallbacks); - } - else - { - ExFreePool(CallbackRegistration); - CallbackRegistration = NULL; - } + /* Add Callback if 1) No Callbacks registered or 2) Multiple Callbacks allowed */ + if(CallbackObject->AllowMultipleCallbacks || IsListEmpty(&CallbackObject->RegisteredCallbacks)) + { + InsertTailList(&CallbackObject->RegisteredCallbacks,&CallbackRegistration->RegisteredCallbacks); + } + else + { + ExFreePool(CallbackRegistration); + CallbackRegistration = NULL; + } - /* Release SpinLock */ - KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); + /* Release SpinLock */ + KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); - /* Return handle to Registration Object */ - return (PVOID) CallbackRegistration; + /* Return handle to Registration Object */ + return (PVOID)CallbackRegistration; } -/* - * ExUnregisterCallback - * - * FUNCTION: - * Deregisters a CallBack - * - * ARGUMENTS: - * CallbackRegistration = Callback Registration Handle - * - * RETURNS: - * Nothing - * +/*++ + * @name ExUnregisterCallback * @implemented - */ -VOID STDCALL -ExUnregisterCallback( - IN PVOID CallbackRegistrationHandle -) + * + * Deregisters a CallBack + * See: DDK, OSR, links in ExNotifyCallback + * + * @param CallbackRegistration + * Callback Registration Handle + * + * @return None + * + * @remarks None + * + *--*/ +VOID +NTAPI +ExUnregisterCallback(IN PVOID CallbackRegistrationHandle) { - PCALLBACK_REGISTRATION CallbackRegistration; - PCALLBACK_OBJECT CallbackObject; - KIRQL OldIrql; + PCALLBACK_REGISTRATION CallbackRegistration; + PCALLBACK_OBJECT CallbackObject; + KIRQL OldIrql; - PAGED_CODE(); + PAGED_CODE(); - /* Convert Handle to valid Structure Pointer */ - CallbackRegistration = (PCALLBACK_REGISTRATION) CallbackRegistrationHandle; + /* Convert Handle to valid Structure Pointer */ + CallbackRegistration = (PCALLBACK_REGISTRATION) CallbackRegistrationHandle; - /* Get the Callback Object */ - CallbackObject = CallbackRegistration->CallbackObject; + /* Get the Callback Object */ + CallbackObject = CallbackRegistration->CallbackObject; - /* Lock the Object */ - OldIrql = KfAcquireSpinLock (&CallbackObject->Lock); + /* Lock the Object */ + OldIrql = KfAcquireSpinLock (&CallbackObject->Lock); - /* We can't Delete the Callback if it's in use, because this would create a call towards a null pointer => crash */ - while (CallbackRegistration->InUse) - { + /* We can't Delete the Callback if it's in use, because this would create a call towards a null pointer => crash */ + while (CallbackRegistration->InUse) + { + /* Similarly, we also don't want to wait ages for all pending callbacks to be called */ + CallbackRegistration->PendingDeletion = TRUE; - /* Similarly, we also don't want to wait ages for all pending callbacks to be called */ - CallbackRegistration->PendingDeletion = TRUE; + /* We are going to wait for the event, so the Lock isn't necessary */ + KfReleaseSpinLock (&CallbackObject->Lock, OldIrql); - /* We are going to wait for the event, so the Lock isn't necessary */ - KfReleaseSpinLock (&CallbackObject->Lock, OldIrql); + /* Make sure the event is cleared */ + KeClearEvent (&ExpCallbackEvent); - /* Make sure the event is cleared */ - KeClearEvent (&ExpCallbackEvent); + /* Wait for the Event */ + KeWaitForSingleObject ( + &ExpCallbackEvent, + Executive, + KernelMode, + FALSE, + NULL + ); - /* Wait for the Event */ - KeWaitForSingleObject ( - &ExpCallbackEvent, - Executive, - KernelMode, - FALSE, - NULL - ); + /* We need the Lock again */ + OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); + } - /* We need the Lock again */ - OldIrql = KfAcquireSpinLock(&CallbackObject->Lock); - } + /* Remove the Callback */ + RemoveEntryList(&CallbackRegistration->RegisteredCallbacks); - /* Remove the Callback */ - RemoveEntryList(&CallbackRegistration->RegisteredCallbacks); + /* It's now safe to release the lock */ + KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); - /* It's now safe to release the lock */ - KfReleaseSpinLock(&CallbackObject->Lock, OldIrql); + /* Delete this registration */ + ExFreePool(CallbackRegistration); - /* Delete this registration */ - ExFreePool(CallbackRegistration); - - /* Remove the reference */ - ObDereferenceObject(CallbackObject); + /* Remove the reference */ + ObDereferenceObject(CallbackObject); } /* EOF */