ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

callback.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ex/callback.c
00005  * PURPOSE:         Executive callbacks
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* TYPES *********************************************************************/
00016 
00017 /* Mapping for Callback Object */
00018 GENERIC_MAPPING ExpCallbackMapping =
00019 {
00020     CALLBACK_READ,
00021     CALLBACK_WRITE,
00022     CALLBACK_EXECUTE,
00023     CALLBACK_ALL_ACCESS
00024 };
00025 
00026 /* Kernel Default Callbacks */
00027 PCALLBACK_OBJECT SetSystemTimeCallback;
00028 PCALLBACK_OBJECT SetSystemStateCallback;
00029 PCALLBACK_OBJECT PowerStateCallback;
00030 SYSTEM_CALLBACKS ExpInitializeCallback[] =
00031 {
00032    {&SetSystemTimeCallback, L"\\Callback\\SetSystemTime"},
00033    {&SetSystemStateCallback, L"\\Callback\\SetSystemState"},
00034    {&PowerStateCallback, L"\\Callback\\PowerState"},
00035    {NULL, NULL}
00036 };
00037 
00038 POBJECT_TYPE ExCallbackObjectType;
00039 KEVENT ExpCallbackEvent;
00040 EX_PUSH_LOCK ExpCallBackFlush;
00041 
00042 /* PRIVATE FUNCTIONS *********************************************************/
00043 
00044 VOID
00045 NTAPI
00046 ExInitializeCallBack(IN OUT PEX_CALLBACK Callback)
00047 {
00048     /* Initialize the fast reference */
00049     ExInitializeFastReference(&Callback->RoutineBlock, NULL);
00050 }
00051 
00052 PEX_CALLBACK_ROUTINE_BLOCK
00053 NTAPI
00054 ExAllocateCallBack(IN PEX_CALLBACK_FUNCTION Function,
00055                    IN PVOID Context)
00056 {
00057     PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
00058 
00059     /* Allocate a callback */
00060     CallbackBlock = ExAllocatePoolWithTag(PagedPool,
00061                                           sizeof(EX_CALLBACK_ROUTINE_BLOCK),
00062                                           'CbRb');
00063     if (CallbackBlock)
00064     {
00065         /* Initialize it */
00066         CallbackBlock->Function = Function;
00067         CallbackBlock->Context = Context;
00068         ExInitializeRundownProtection(&CallbackBlock->RundownProtect);
00069     }
00070 
00071     /* Return it */
00072     return CallbackBlock;
00073 }
00074 
00075 VOID
00076 NTAPI
00077 ExFreeCallBack(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
00078 {
00079     /* Just free it from memory */
00080     ExFreePoolWithTag(CallbackBlock, CALLBACK_TAG);
00081 }
00082 
00083 VOID
00084 NTAPI
00085 ExWaitForCallBacks(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
00086 {
00087     /* Wait on the rundown */
00088     ExWaitForRundownProtectionRelease(&CallbackBlock->RundownProtect);
00089 }
00090 
00091 PEX_CALLBACK_FUNCTION
00092 NTAPI
00093 ExGetCallBackBlockRoutine(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
00094 {
00095     /* Return the function */
00096     return CallbackBlock->Function;
00097 }
00098 
00099 PVOID
00100 NTAPI
00101 ExGetCallBackBlockContext(IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
00102 {
00103     /* Return the context */
00104     return CallbackBlock->Context;
00105 }
00106 
00107 VOID
00108 NTAPI
00109 ExDereferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack,
00110                            IN PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock)
00111 {
00112     /* Release a fast reference */
00113     if (!ExReleaseFastReference(&CallBack->RoutineBlock, CallbackBlock))
00114     {
00115         /* Take slow path */
00116         ExReleaseRundownProtection(&CallbackBlock->RundownProtect);
00117     }
00118 }
00119 
00120 PEX_CALLBACK_ROUTINE_BLOCK
00121 NTAPI
00122 ExReferenceCallBackBlock(IN OUT PEX_CALLBACK CallBack)
00123 {
00124     EX_FAST_REF OldValue;
00125     ULONG_PTR Count;
00126     PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
00127     
00128     /* Acquire a reference */
00129     OldValue = ExAcquireFastReference(&CallBack->RoutineBlock);
00130     Count = ExGetCountFastReference(OldValue);
00131 
00132     /* Fail if there isn't any object */
00133     if (!ExGetObjectFastReference(OldValue)) return NULL;
00134 
00135     /* Check if we don't have a reference */
00136     if (!Count)
00137     {
00138         /* FIXME: Race */
00139         DPRINT1("Unhandled callback race condition\n");
00140         ASSERT(FALSE);
00141         return NULL;
00142     }
00143     
00144     /* Get the callback block */
00145     CallbackBlock = ExGetObjectFastReference(OldValue);
00146     
00147     /* Check if this is the last reference */
00148     if (Count == 1)
00149     {
00150         /* Acquire rundown protection */
00151         if (ExfAcquireRundownProtectionEx(&CallbackBlock->RundownProtect,
00152                                           MAX_FAST_REFS))
00153         {
00154             /* Insert references */
00155             if (!ExInsertFastReference(&CallBack->RoutineBlock, CallbackBlock))
00156             {
00157                 /* Backdown the rundown acquire */
00158                 ExfReleaseRundownProtectionEx(&CallbackBlock->RundownProtect,
00159                                               MAX_FAST_REFS);
00160             }
00161         }
00162     }
00163 
00164     /* Return the callback block */
00165     return CallbackBlock;
00166 }
00167 
00168 BOOLEAN
00169 NTAPI
00170 ExCompareExchangeCallBack(IN OUT PEX_CALLBACK CallBack,
00171                           IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
00172                           IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock)
00173 {
00174     EX_FAST_REF OldValue;
00175     PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock;
00176     ULONG Count;
00177 
00178     /* Check that we have a new block */
00179     if (NewBlock)
00180     {
00181         /* Acquire rundown */
00182         if (!ExfAcquireRundownProtectionEx(&NewBlock->RundownProtect,
00183                                            MAX_FAST_REFS + 1))
00184         {
00185             /* This should never happen */
00186             ASSERTMSG("Callback block is already undergoing rundown", FALSE);
00187             return FALSE;
00188         }
00189     }
00190 
00191     /* Do the swap */
00192     OldValue = ExCompareSwapFastReference(&CallBack->RoutineBlock,
00193                                           NewBlock,
00194                                           OldBlock);
00195 
00196     /* Get the routine block */
00197     CallbackBlock = ExGetObjectFastReference(OldValue);
00198     Count = ExGetCountFastReference(OldValue);
00199 
00200     /* Make sure the swap worked */
00201     if (CallbackBlock == OldBlock)
00202     {
00203         /* Make sure we replaced a valid pointer */
00204         if (CallbackBlock)
00205         {
00206             /* Acquire the flush lock and immediately release it */
00207             KeEnterCriticalRegion();
00208             ExWaitOnPushLock(&ExpCallBackFlush);
00209 
00210             /* Release rundown protection */
00211             KeLeaveCriticalRegion();
00212             ExfReleaseRundownProtectionEx(&CallbackBlock->RundownProtect,
00213                                           Count + 1);
00214         }
00215 
00216         /* Compare worked */
00217         return TRUE;
00218     }
00219     else
00220     {
00221         /* It failed, check if we had a block */
00222         if (NewBlock)
00223         {
00224             /* We did, remove the refernces that we had added */
00225             ExfReleaseRundownProtectionEx(&NewBlock->RundownProtect,
00226                                           MAX_FAST_REFS + 1);
00227         }
00228 
00229         /* Return failure */
00230         return FALSE;
00231     }
00232 }
00233 
00234 VOID
00235 NTAPI
00236 ExpDeleteCallback(IN PVOID Object)
00237 {
00238     /* Sanity check */
00239     ASSERT(IsListEmpty(&((PCALLBACK_OBJECT)Object)->RegisteredCallbacks));
00240 }
00241 
00242 /*++
00243  * @name ExpInitializeCallbacks
00244  *
00245  * Creates the Callback Object as a valid Object Type in the Kernel.
00246  * Internal function, subject to further review
00247  *
00248  * @return TRUE if the Callback Object Type was successfully created.
00249  *
00250  * @remarks None
00251  *
00252  *--*/
00253 BOOLEAN
00254 INIT_FUNCTION
00255 NTAPI
00256 ExpInitializeCallbacks(VOID)
00257 {
00258     OBJECT_ATTRIBUTES ObjectAttributes;
00259     NTSTATUS Status;
00260     UNICODE_STRING DirName = RTL_CONSTANT_STRING(L"\\Callback");
00261     UNICODE_STRING CallbackName;
00262     UNICODE_STRING Name;
00263     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
00264     HANDLE DirectoryHandle;
00265     ULONG i;
00266 
00267     /* Setup lightweight callback lock */
00268     ExpCallBackFlush.Value = 0;
00269 
00270     /* Initialize the Callback Object type  */
00271     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
00272     RtlInitUnicodeString(&Name, L"Callback");
00273     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
00274     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
00275     ObjectTypeInitializer.GenericMapping = ExpCallbackMapping;
00276     ObjectTypeInitializer.PoolType = NonPagedPool;
00277     ObjectTypeInitializer.DeleteProcedure = ExpDeleteCallback;
00278     ObjectTypeInitializer.ValidAccessMask = CALLBACK_ALL_ACCESS;
00279     Status = ObCreateObjectType(&Name,
00280                                 &ObjectTypeInitializer,
00281                                 NULL,
00282                                 &ExCallbackObjectType);
00283     if (!NT_SUCCESS(Status)) return FALSE;
00284 
00285     /* Initialize the Object */
00286     InitializeObjectAttributes(&ObjectAttributes,
00287                                &DirName,
00288                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
00289                                NULL,
00290                                SePublicDefaultSd);
00291 
00292     /* Create the Object Directory */
00293     Status = NtCreateDirectoryObject(&DirectoryHandle,
00294                                      DIRECTORY_ALL_ACCESS,
00295                                      &ObjectAttributes);
00296     if (!NT_SUCCESS(Status)) return FALSE;
00297 
00298     /* Close Handle... */
00299     NtClose(DirectoryHandle);
00300 
00301     /* Initialize Event used when unregistering */
00302     KeInitializeEvent(&ExpCallbackEvent, NotificationEvent, 0);
00303 
00304     /* Default NT Kernel Callbacks. */
00305     for (i = 0; ExpInitializeCallback[i].CallbackObject; i++)
00306     {
00307         /* Create the name from the structure */
00308         RtlInitUnicodeString(&CallbackName, ExpInitializeCallback[i].Name);
00309 
00310         /* Initialize the Object Attributes Structure */
00311         InitializeObjectAttributes(&ObjectAttributes,
00312                                    &CallbackName,
00313                                    OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
00314                                    NULL,
00315                                    NULL);
00316 
00317         /* Create the Callback Object */
00318         Status = ExCreateCallback(ExpInitializeCallback[i].CallbackObject,
00319                                   &ObjectAttributes,
00320                                   TRUE,
00321                                   TRUE);
00322         if (!NT_SUCCESS(Status)) return FALSE;
00323     }
00324 
00325     /* Everything successful */
00326     return TRUE;
00327 }
00328 
00329 /* PUBLIC FUNCTIONS **********************************************************/
00330 
00331 /*++
00332  * @name ExCreateCallback
00333  * @implemented
00334  *
00335  * Opens or creates a Callback Object. Creates only if Create is true.
00336  * Allows multiple Callback Functions to be registred only if
00337  * AllowMultipleCallbacks is true.
00338  * See: http://www.osronline.com/ddkx/kmarch/k102_967m.htm
00339  *      http://www.osronline.com/article.cfm?id=24
00340  *
00341  * @param CallbackObject
00342  *        Pointer that will receive the Callback Object.
00343  *
00344  * @param CallbackName
00345  *        Name of Callback
00346  *
00347  * @param Create
00348  *        Determines if the object will be created if it doesn't exit
00349  *
00350  * @param AllowMultipleCallbacks
00351  *        Determines if more then one registered callback function
00352  *        can be attached to this Callback Object.
00353  *
00354  * @return STATUS_SUCESS if not failed.
00355  *
00356  * @remarks Must be called at IRQL = PASSIVE_LEVEL
00357  *
00358  *--*/
00359 NTSTATUS
00360 NTAPI
00361 ExCreateCallback(OUT PCALLBACK_OBJECT *CallbackObject,
00362                  IN POBJECT_ATTRIBUTES ObjectAttributes,
00363                  IN BOOLEAN Create,
00364                  IN BOOLEAN AllowMultipleCallbacks)
00365 {
00366     PCALLBACK_OBJECT Callback = NULL;
00367     NTSTATUS Status;
00368     HANDLE Handle = NULL;
00369     PAGED_CODE();
00370 
00371     /* Open a handle to the callback if it exists */
00372     if (ObjectAttributes->ObjectName)
00373     {
00374         /* Open the handle */
00375         Status = ObOpenObjectByName(ObjectAttributes,
00376                                     ExCallbackObjectType,
00377                                     KernelMode,
00378                                     NULL,
00379                                     0,
00380                                     NULL,
00381                                     &Handle);
00382     }
00383     else
00384     {
00385         /* Otherwise, fail */
00386         Status = STATUS_UNSUCCESSFUL;
00387     }
00388 
00389     /* We weren't able to open it...should we create it? */
00390     if (!(NT_SUCCESS(Status)) && (Create))
00391     {
00392         /* Create the object */
00393         Status = ObCreateObject(KernelMode,
00394                                 ExCallbackObjectType,
00395                                 ObjectAttributes,
00396                                 KernelMode,
00397                                 NULL,
00398                                 sizeof(CALLBACK_OBJECT),
00399                                 0,
00400                                 0,
00401                                 (PVOID *)&Callback);
00402         if (NT_SUCCESS(Status))
00403         {
00404             /* Set it up */
00405             Callback->Signature = 'llaC';
00406             KeInitializeSpinLock(&Callback->Lock);
00407             InitializeListHead(&Callback->RegisteredCallbacks);
00408             Callback->AllowMultipleCallbacks = AllowMultipleCallbacks;
00409 
00410             /* Insert the object into the object namespace */
00411             Status = ObInsertObject(Callback,
00412                                     NULL,
00413                                     FILE_READ_DATA,
00414                                     0,
00415                                     NULL,
00416                                     &Handle);
00417         }
00418     }
00419 
00420     /* Check if we have success until here */
00421     if (NT_SUCCESS(Status))
00422     {
00423         /* Get a pointer to the new object from the handle we just got */
00424         Status = ObReferenceObjectByHandle(Handle,
00425                                            0,
00426                                            ExCallbackObjectType,
00427                                            KernelMode,
00428                                            (PVOID)&Callback,
00429                                            NULL);
00430 
00431         /* Close the Handle, since we now have the pointer */
00432         ZwClose(Handle);
00433     }
00434 
00435     /* Everything went fine, so return a pointer to the Object */
00436     if (NT_SUCCESS(Status)) *CallbackObject = Callback;
00437     return Status;
00438 }
00439 
00440 /*++
00441  * @name ExNotifyCallback
00442  * @implemented
00443  *
00444  * Calls a function pointer (a registered callback)
00445  * See: http://www.osronline.com/ddkx/kmarch/k102_2f5e.htm
00446  *      http://vmsone.com/~decuslib/vmssig/vmslt99b/nt/wdm-callback.txt
00447  *
00448  * @param CallbackObject
00449  *        Which callback to call
00450  *
00451  * @param Argument1
00452  *        Pointer/data to send to callback function
00453  *
00454  * @param Argument2
00455  *        Pointer/data to send to callback function
00456  *
00457  * @return None
00458  *
00459  * @remarks None
00460  *
00461  *--*/
00462 VOID
00463 NTAPI
00464 ExNotifyCallback(IN PCALLBACK_OBJECT CallbackObject,
00465                  IN PVOID Argument1,
00466                  IN PVOID Argument2)
00467 {
00468     PLIST_ENTRY RegisteredCallbacks;
00469     PCALLBACK_REGISTRATION CallbackRegistration;
00470     KIRQL OldIrql;
00471 
00472     /* Check if we don't have an object or registrations */
00473     if (!(CallbackObject) ||
00474         (IsListEmpty(&CallbackObject->RegisteredCallbacks)))
00475     {
00476         /* Don't notify */
00477         return;
00478     }
00479 
00480     /* Acquire the Lock */
00481     KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
00482 
00483     /* Enumerate through all the registered functions */
00484     for (RegisteredCallbacks = CallbackObject->RegisteredCallbacks.Flink;
00485          RegisteredCallbacks != &CallbackObject->RegisteredCallbacks;
00486          RegisteredCallbacks = RegisteredCallbacks->Flink)
00487     {
00488         /* Get a pointer to a Callback Registration from the List Entries */
00489         CallbackRegistration = CONTAINING_RECORD(RegisteredCallbacks,
00490                                                  CALLBACK_REGISTRATION,
00491                                                  Link);
00492 
00493         /* Don't bother doing notification if it's pending to be deleted */
00494         if (!CallbackRegistration->UnregisterWaiting)
00495         {
00496             /* Mark the Callback in use, so it won't get deleted */
00497             CallbackRegistration->Busy += 1;
00498 
00499             /* Release the Spinlock before making the call */
00500             KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
00501 
00502             /* Call the Registered Function */
00503             CallbackRegistration->CallbackFunction(CallbackRegistration->
00504                                                    CallbackContext,
00505                                                    Argument1,
00506                                                    Argument2);
00507 
00508             /* Get SpinLock back */
00509             KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
00510 
00511             /* We are not in use anymore */
00512             CallbackRegistration->Busy -= 1;
00513 
00514             /* Check if removal is pending and we're not active */
00515             if ((CallbackRegistration->UnregisterWaiting) &&
00516                 !(CallbackRegistration->Busy))
00517             {
00518                 /* Signal the callback event */
00519                 KeSetEvent(&ExpCallbackEvent, 0, FALSE);
00520             }
00521         }
00522     }
00523 
00524     /* Release the Callback Object */
00525     KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
00526 }
00527 
00528 /*++
00529  * @name ExRegisterCallback
00530  * @implemented
00531  *
00532  * Allows a function to associate a callback pointer (Function) to
00533  * a created Callback object
00534  * See: DDK, OSR, links in ExNotifyCallback
00535  *
00536  * @param CallbackObject
00537  *        The Object Created with ExCreateCallBack
00538  *
00539  * @param CallBackFunction
00540  *        Pointer to the function to be called back
00541  *
00542  * @param CallBackContext
00543  *        Block of memory that can contain user-data which will be
00544  *        passed on to the callback
00545  *
00546  * @return A handle to a Callback Registration Structure (MSDN Documentation)
00547  *
00548  * @remarks None
00549  *
00550  *--*/
00551 PVOID
00552 NTAPI
00553 ExRegisterCallback(IN PCALLBACK_OBJECT CallbackObject,
00554                    IN PCALLBACK_FUNCTION CallbackFunction,
00555                    IN PVOID CallbackContext)
00556 {
00557     PCALLBACK_REGISTRATION CallbackRegistration = NULL;
00558     KIRQL OldIrql;
00559 
00560     /* Sanity checks */
00561     ASSERT(CallbackFunction);
00562     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00563 
00564     /* Create reference to Callback Object */
00565     ObReferenceObject(CallbackObject);
00566 
00567     /* Allocate memory for the structure */
00568     CallbackRegistration = ExAllocatePoolWithTag(NonPagedPool,
00569                                                  sizeof(CALLBACK_REGISTRATION),
00570                                                  CALLBACK_TAG);
00571     if (!CallbackRegistration)
00572     {
00573         /* Dereference and fail */
00574         ObDereferenceObject (CallbackObject);
00575         return NULL;
00576     }
00577 
00578     /* Create Callback Registration */
00579     CallbackRegistration->CallbackObject = CallbackObject;
00580     CallbackRegistration->CallbackFunction = CallbackFunction;
00581     CallbackRegistration->CallbackContext = CallbackContext;
00582     CallbackRegistration->Busy = 0;
00583     CallbackRegistration->UnregisterWaiting = FALSE;
00584 
00585     /* Acquire SpinLock */
00586     KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
00587 
00588     /* Check if 1) No Callbacks registered or 2) Multiple Callbacks allowed */
00589     if ((CallbackObject->AllowMultipleCallbacks) ||
00590         (IsListEmpty(&CallbackObject->RegisteredCallbacks)))
00591     {
00592         /* Register the callback */
00593         InsertTailList(&CallbackObject->RegisteredCallbacks,
00594                        &CallbackRegistration->Link);
00595 
00596         /* Release SpinLock */
00597         KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
00598     }
00599     else
00600     {
00601         /* Release SpinLock */
00602         KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
00603 
00604         /* Free the registration */
00605         ExFreePoolWithTag(CallbackRegistration, CALLBACK_TAG);
00606         CallbackRegistration = NULL;
00607 
00608         /* Dereference the object */
00609         ObDereferenceObject(CallbackObject);
00610     }
00611 
00612     /* Return handle to Registration Object */
00613     return (PVOID)CallbackRegistration;
00614 }
00615 
00616 /*++
00617  * @name ExUnregisterCallback
00618  * @implemented
00619  *
00620  * Deregisters a CallBack
00621  * See: DDK, OSR, links in ExNotifyCallback
00622  *
00623  * @param CallbackRegistration
00624  *        Callback Registration Handle
00625  *
00626  * @return None
00627  *
00628  * @remarks None
00629  *
00630  *--*/
00631 VOID
00632 NTAPI
00633 ExUnregisterCallback(IN PVOID CallbackRegistrationHandle)
00634 {
00635     PCALLBACK_REGISTRATION CallbackRegistration;
00636     PCALLBACK_OBJECT CallbackObject;
00637     KIRQL OldIrql;
00638     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00639 
00640     /* Convert Handle to valid Structure Pointer */
00641     CallbackRegistration = (PCALLBACK_REGISTRATION)CallbackRegistrationHandle;
00642 
00643     /* Get the Callback Object */
00644     CallbackObject = CallbackRegistration->CallbackObject;
00645 
00646     /* Lock the Object */
00647     KeAcquireSpinLock (&CallbackObject->Lock, &OldIrql);
00648 
00649     /* We can't Delete the Callback if it's in use */
00650     while (CallbackRegistration->Busy)
00651     {
00652         /* Let everyone else know we're unregistering */
00653         CallbackRegistration->UnregisterWaiting = TRUE;
00654 
00655         /* We are going to wait for the event, so the Lock isn't necessary */
00656         KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
00657 
00658         /* Make sure the event is cleared */
00659         KeClearEvent(&ExpCallbackEvent);
00660 
00661         /* Wait for the Event */
00662         KeWaitForSingleObject(&ExpCallbackEvent,
00663                               Executive,
00664                               KernelMode,
00665                               FALSE,
00666                               NULL);
00667 
00668         /* We need the Lock again */
00669         KeAcquireSpinLock(&CallbackObject->Lock, &OldIrql);
00670     }
00671 
00672     /* Remove the Callback */
00673     RemoveEntryList(&CallbackRegistration->Link);
00674 
00675     /* It's now safe to release the lock */
00676     KeReleaseSpinLock(&CallbackObject->Lock, OldIrql);
00677 
00678     /* Delete this registration */
00679     ExFreePoolWithTag(CallbackRegistration, CALLBACK_TAG);
00680 
00681     /* Remove the reference */
00682     ObDereferenceObject(CallbackObject);
00683 }
00684 
00685 /* EOF */

Generated on Fri May 25 2012 04:15:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.