mirror of
https://github.com/reactos/reactos.git
synced 2025-01-13 01:22:03 +00:00
- 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:
parent
532a28a03c
commit
b51d473275
3 changed files with 181 additions and 174 deletions
|
@ -488,11 +488,25 @@ typedef __ALIGNED(16) struct _EX_PUSH_LOCK_WAIT_BLOCK
|
|||
//
|
||||
typedef struct _CALLBACK_OBJECT
|
||||
{
|
||||
ULONG Name;
|
||||
ULONG Signature;
|
||||
KSPIN_LOCK Lock;
|
||||
LIST_ENTRY RegisteredCallbacks;
|
||||
ULONG AllowMultipleCallbacks;
|
||||
} CALLBACK_OBJECT , *PCALLBACK_OBJECT;
|
||||
BOOLEAN AllowMultipleCallbacks;
|
||||
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
|
||||
|
|
|
@ -3,54 +3,30 @@
|
|||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ex/callback.c
|
||||
* PURPOSE: Executive callbacks
|
||||
* PROGRAMMERS: Filip Navara
|
||||
* Alex Ionescu (alex@relsoft.net)
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#if defined (ALLOC_PRAGMA)
|
||||
#pragma alloc_text(INIT, ExpInitializeCallbacks)
|
||||
#endif
|
||||
|
||||
|
||||
/* TYPES ********************************************************************/
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
/* Mapping for Callback Object */
|
||||
GENERIC_MAPPING ExpCallbackMapping =
|
||||
{
|
||||
CALLBACK_READ,
|
||||
CALLBACK_WRITE,
|
||||
CALLBACK_EXECUTE,
|
||||
CALLBACK_ALL_ACCESS
|
||||
CALLBACK_READ,
|
||||
CALLBACK_WRITE,
|
||||
CALLBACK_EXECUTE,
|
||||
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 */
|
||||
PCALLBACK_OBJECT SetSystemTimeCallback;
|
||||
PCALLBACK_OBJECT SetSystemStateCallback;
|
||||
PCALLBACK_OBJECT PowerStateCallback;
|
||||
|
||||
SYSTEM_CALLBACKS ExpInitializeCallback[] =
|
||||
{
|
||||
{&SetSystemTimeCallback, L"\\Callback\\SetSystemTime"},
|
||||
|
@ -62,7 +38,15 @@ SYSTEM_CALLBACKS ExpInitializeCallback[] =
|
|||
POBJECT_TYPE ExCallbackObjectType;
|
||||
KEVENT ExpCallbackEvent;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExpDeleteCallback(IN PVOID Object)
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT(IsListEmpty(&((PCALLBACK_OBJECT)Object)->RegisteredCallbacks));
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name ExpInitializeCallbacks
|
||||
|
@ -75,7 +59,7 @@ KEVENT ExpCallbackEvent;
|
|||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
BOOLEAN
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
ExpInitializeCallbacks(VOID)
|
||||
|
@ -89,43 +73,33 @@ ExpInitializeCallbacks(VOID)
|
|||
HANDLE DirectoryHandle;
|
||||
ULONG i;
|
||||
|
||||
/* Initialize the Callback Object type */
|
||||
/* Initialize the Callback Object type */
|
||||
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
||||
RtlInitUnicodeString(&Name, L"Callback");
|
||||
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
||||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CALLBACK_OBJECT);
|
||||
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
|
||||
ObjectTypeInitializer.GenericMapping = ExpCallbackMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
|
||||
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExCallbackObjectType);
|
||||
|
||||
/* Fail if it wasn't created successfully */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpDeleteCallback;
|
||||
ObjectTypeInitializer.ValidAccessMask = CALLBACK_ALL_ACCESS;
|
||||
Status = ObCreateObjectType(&Name,
|
||||
&ObjectTypeInitializer,
|
||||
NULL,
|
||||
&ExCallbackObjectType);
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Initialize the Object */
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&DirName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DirName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
|
||||
NULL,
|
||||
SePublicDefaultSd);
|
||||
|
||||
/* Create the Object Directory */
|
||||
Status = NtCreateDirectoryObject(
|
||||
&DirectoryHandle,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
&ObjectAttributes
|
||||
);
|
||||
|
||||
/* Fail if couldn't create */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Status = NtCreateDirectoryObject(&DirectoryHandle,
|
||||
DIRECTORY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
|
||||
/* Close Handle... */
|
||||
NtClose(DirectoryHandle);
|
||||
|
@ -134,37 +108,32 @@ ExpInitializeCallbacks(VOID)
|
|||
KeInitializeEvent(&ExpCallbackEvent, NotificationEvent, 0);
|
||||
|
||||
/* Default NT Kernel Callbacks. */
|
||||
for (i=0; ExpInitializeCallback[i].CallbackObject; i++)
|
||||
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
|
||||
);
|
||||
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;
|
||||
}
|
||||
Status = ExCreateCallback(ExpInitializeCallback[i].CallbackObject,
|
||||
&ObjectAttributes,
|
||||
TRUE,
|
||||
TRUE);
|
||||
if (!NT_SUCCESS(Status)) return FALSE;
|
||||
}
|
||||
|
||||
/* Everything successful */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*++
|
||||
* @name ExCreateCallback
|
||||
* @implemented
|
||||
|
@ -200,15 +169,15 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
|
|||
IN BOOLEAN Create,
|
||||
IN BOOLEAN AllowMultipleCallbacks)
|
||||
{
|
||||
PCALLBACK_OBJECT Callback;
|
||||
NTSTATUS Status;
|
||||
HANDLE Handle;
|
||||
|
||||
PCALLBACK_OBJECT Callback = NULL;
|
||||
NTSTATUS Status;
|
||||
HANDLE Handle = NULL;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Open a handle to the callback if it exists */
|
||||
if (ObjectAttributes->ObjectName)
|
||||
{
|
||||
/* Open the handle */
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
ExCallbackObjectType,
|
||||
KernelMode,
|
||||
|
@ -219,12 +188,14 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, fail */
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
ExCallbackObjectType,
|
||||
ObjectAttributes,
|
||||
|
@ -233,25 +204,27 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
|
|||
sizeof(CALLBACK_OBJECT),
|
||||
0,
|
||||
0,
|
||||
(PVOID *)&Callback );
|
||||
|
||||
/* We Created it...let's initialize the structure now */
|
||||
if(NT_SUCCESS(Status))
|
||||
(PVOID *)&Callback);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
KeInitializeSpinLock(&Callback->Lock); /* SpinLock */
|
||||
InitializeListHead(&Callback->RegisteredCallbacks); /* Callback Entries */
|
||||
Callback->AllowMultipleCallbacks = AllowMultipleCallbacks; /* Multiple Callbacks */
|
||||
/* Create the object */
|
||||
/* Set it up */
|
||||
Callback->Signature = TAG('C', 'a', 'l', 'l');
|
||||
KeInitializeSpinLock(&Callback->Lock);
|
||||
InitializeListHead(&Callback->RegisteredCallbacks);
|
||||
Callback->AllowMultipleCallbacks = AllowMultipleCallbacks;
|
||||
|
||||
/* Insert the object into the object namespace */
|
||||
Status = ObInsertObject(Callback,
|
||||
NULL,
|
||||
FILE_READ_DATA,
|
||||
0,
|
||||
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 */
|
||||
Status = ObReferenceObjectByHandle(Handle,
|
||||
|
@ -260,15 +233,13 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
|
|||
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;
|
||||
}
|
||||
if (NT_SUCCESS(Status)) *CallbackObject = Callback;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -278,7 +249,6 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
|
|||
*
|
||||
* 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
|
||||
|
@ -297,17 +267,24 @@ ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
|
|||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
ExNotifyCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject,
|
||||
ExNotifyCallback(IN PCALLBACK_OBJECT CallbackObject,
|
||||
IN PVOID Argument1,
|
||||
IN PVOID Argument2)
|
||||
{
|
||||
PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject;
|
||||
PLIST_ENTRY RegisteredCallbacks;
|
||||
PCALLBACK_REGISTRATION CallbackRegistration;
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY RegisteredCallbacks;
|
||||
PCALLBACK_REGISTRATION CallbackRegistration;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Check if we don't have an object or registrations */
|
||||
if (!(CallbackObject) ||
|
||||
(IsListEmpty(&CallbackObject->RegisteredCallbacks)))
|
||||
{
|
||||
/* Don't notify */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Acquire the Lock */
|
||||
OldIrql = KfAcquireSpinLock(&CallbackObject->Lock);
|
||||
KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
|
||||
|
||||
/* Enumerate through all the registered functions */
|
||||
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 */
|
||||
CallbackRegistration = CONTAINING_RECORD(RegisteredCallbacks,
|
||||
CALLBACK_REGISTRATION,
|
||||
RegisteredCallbacks);
|
||||
Link);
|
||||
|
||||
/* Don't bother doing Callback Notification if it's pending to be deleted */
|
||||
if (!CallbackRegistration->PendingDeletion)
|
||||
/* Don't bother doing notification if it's pending to be deleted */
|
||||
if (!CallbackRegistration->UnregisterWaiting)
|
||||
{
|
||||
/* Mark the Callback in use, so it won't get deleted while we are calling it */
|
||||
CallbackRegistration->InUse += 1;
|
||||
/* Mark the Callback in use, so it won't get deleted */
|
||||
CallbackRegistration->Busy += 1;
|
||||
|
||||
/* Release the Spinlock before making the call */
|
||||
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql);
|
||||
KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
|
||||
|
||||
/* Call the Registered Function */
|
||||
CallbackRegistration->CallbackFunction(
|
||||
CallbackRegistration->CallbackContext,
|
||||
Argument1,
|
||||
Argument2
|
||||
);
|
||||
CallbackRegistration->CallbackFunction(CallbackRegistration->
|
||||
CallbackContext,
|
||||
Argument1,
|
||||
Argument2);
|
||||
|
||||
/* Get SpinLock back */
|
||||
OldIrql = KfAcquireSpinLock(&CallbackObject->Lock);
|
||||
KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
|
||||
|
||||
/* 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 */
|
||||
if (CallbackRegistration->PendingDeletion && CallbackRegistration->InUse == 0)
|
||||
/* Check if removal is pending and we're not active */
|
||||
if ((CallbackRegistration->UnregisterWaiting) &&
|
||||
!(CallbackRegistration->Busy))
|
||||
{
|
||||
/* Signal the callback event */
|
||||
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
|
||||
NTAPI
|
||||
ExRegisterCallback(IN PCALLBACK_OBJECT OpaqueCallbackObject,
|
||||
ExRegisterCallback(IN PCALLBACK_OBJECT CallbackObject,
|
||||
IN PCALLBACK_FUNCTION CallbackFunction,
|
||||
IN PVOID CallbackContext)
|
||||
{
|
||||
PCALLBACK_OBJECT CallbackObject = (PCALLBACK_OBJECT)OpaqueCallbackObject;
|
||||
PCALLBACK_REGISTRATION CallbackRegistration = NULL;
|
||||
KIRQL OldIrql;
|
||||
PCALLBACK_REGISTRATION CallbackRegistration = NULL;
|
||||
KIRQL OldIrql;
|
||||
|
||||
PAGED_CODE();
|
||||
/* Sanity checks */
|
||||
ASSERT(CallbackFunction);
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
/* Create reference to Callback Object */
|
||||
ObReferenceObject (CallbackObject);
|
||||
ObReferenceObject(CallbackObject);
|
||||
|
||||
/* Allocate memory for the structure */
|
||||
CallbackRegistration = ExAllocatePoolWithTag(
|
||||
NonPagedPool,
|
||||
sizeof(CallbackRegistration),
|
||||
CALLBACK_TAG
|
||||
);
|
||||
/* Fail if memory allocation failed */
|
||||
if(!CallbackRegistration)
|
||||
CallbackRegistration = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(CALLBACK_REGISTRATION),
|
||||
CALLBACK_TAG);
|
||||
if (!CallbackRegistration)
|
||||
{
|
||||
/* Dereference and fail */
|
||||
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 */
|
||||
CallbackRegistration->CallbackObject = CallbackObject;
|
||||
CallbackRegistration->CallbackFunction = CallbackFunction;
|
||||
CallbackRegistration->CallbackContext = CallbackContext;
|
||||
CallbackRegistration->Busy = 0;
|
||||
CallbackRegistration->UnregisterWaiting = FALSE;
|
||||
|
||||
/* Acquire SpinLock */
|
||||
OldIrql = KfAcquireSpinLock (&CallbackObject->Lock);
|
||||
KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
|
||||
|
||||
/* Add Callback if 1) No Callbacks registered or 2) Multiple Callbacks allowed */
|
||||
if(CallbackObject->AllowMultipleCallbacks || IsListEmpty(&CallbackObject->RegisteredCallbacks))
|
||||
/* Check if 1) No Callbacks registered or 2) Multiple Callbacks allowed */
|
||||
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
|
||||
{
|
||||
/* Release SpinLock */
|
||||
KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
|
||||
|
||||
/* Free the registration */
|
||||
ExFreePool(CallbackRegistration);
|
||||
CallbackRegistration = NULL;
|
||||
}
|
||||
|
||||
/* Release SpinLock */
|
||||
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql);
|
||||
/* Dereference the object */
|
||||
ObDereferenceObject(CallbackObject);
|
||||
}
|
||||
|
||||
/* Return handle to Registration Object */
|
||||
return (PVOID)CallbackRegistration;
|
||||
|
@ -448,51 +438,48 @@ VOID
|
|||
NTAPI
|
||||
ExUnregisterCallback(IN PVOID CallbackRegistrationHandle)
|
||||
{
|
||||
PCALLBACK_REGISTRATION CallbackRegistration;
|
||||
PCALLBACK_OBJECT CallbackObject;
|
||||
KIRQL OldIrql;
|
||||
|
||||
PAGED_CODE();
|
||||
PCALLBACK_REGISTRATION CallbackRegistration;
|
||||
PCALLBACK_OBJECT CallbackObject;
|
||||
KIRQL OldIrql;
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
/* Convert Handle to valid Structure Pointer */
|
||||
CallbackRegistration = (PCALLBACK_REGISTRATION) CallbackRegistrationHandle;
|
||||
CallbackRegistration = (PCALLBACK_REGISTRATION)CallbackRegistrationHandle;
|
||||
|
||||
/* Get the Callback Object */
|
||||
CallbackObject = CallbackRegistration->CallbackObject;
|
||||
|
||||
/* 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 */
|
||||
while (CallbackRegistration->InUse)
|
||||
/* We can't Delete the Callback if it's in use */
|
||||
while (CallbackRegistration->Busy)
|
||||
{
|
||||
/* Similarly, we also don't want to wait ages for all pending callbacks to be called */
|
||||
CallbackRegistration->PendingDeletion = TRUE;
|
||||
/* Let everyone else know we're unregistering */
|
||||
CallbackRegistration->UnregisterWaiting = TRUE;
|
||||
|
||||
/* 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 */
|
||||
KeClearEvent (&ExpCallbackEvent);
|
||||
KeClearEvent(&ExpCallbackEvent);
|
||||
|
||||
/* Wait for the Event */
|
||||
KeWaitForSingleObject (
|
||||
&ExpCallbackEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
KeWaitForSingleObject(&ExpCallbackEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
/* We need the Lock again */
|
||||
OldIrql = KfAcquireSpinLock(&CallbackObject->Lock);
|
||||
KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
|
||||
}
|
||||
|
||||
/* Remove the Callback */
|
||||
RemoveEntryList(&CallbackRegistration->RegisteredCallbacks);
|
||||
RemoveEntryList(&CallbackRegistration->Link);
|
||||
|
||||
/* It's now safe to release the lock */
|
||||
KfReleaseSpinLock(&CallbackObject->Lock, OldIrql);
|
||||
KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
|
||||
|
||||
/* Delete this registration */
|
||||
ExFreePool(CallbackRegistration);
|
||||
|
|
|
@ -34,6 +34,12 @@ typedef struct _ETIMER
|
|||
LIST_ENTRY WakeTimerListEntry;
|
||||
} ETIMER, *PETIMER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PCALLBACK_OBJECT *CallbackObject;
|
||||
PWSTR Name;
|
||||
} SYSTEM_CALLBACKS;
|
||||
|
||||
#define MAX_FAST_REFS 7
|
||||
|
||||
#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
|
||||
|
@ -107,7 +113,7 @@ ExInitializeSystemLookasideList(
|
|||
IN PLIST_ENTRY ListHead
|
||||
);
|
||||
|
||||
VOID
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
ExpInitializeCallbacks(VOID);
|
||||
|
||||
|
|
Loading…
Reference in a new issue