mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 11:33:35 +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
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue