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

cmhook.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/config/cmhook.c
00005  * PURPOSE:         Configuration Manager - Registry Notifications/Callbacks
00006  * PROGRAMMERS:     Thomas Weidenmueller (w3seek@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "ntoskrnl.h"
00012 #define NDEBUG
00013 #include "debug.h"
00014 
00015 /* GLOBALS *******************************************************************/
00016 
00017 ULONG CmpCallBackCount = 0;
00018 EX_CALLBACK CmpCallBackVector[100];
00019 
00020 LIST_ENTRY CmiCallbackHead;
00021 FAST_MUTEX CmiCallbackLock;
00022 
00023 typedef struct _REGISTRY_CALLBACK
00024 {
00025     LIST_ENTRY ListEntry;
00026     EX_RUNDOWN_REF RundownRef;
00027     PEX_CALLBACK_FUNCTION Function;
00028     PVOID Context;
00029     LARGE_INTEGER Cookie;
00030     BOOLEAN PendingDelete;
00031 } REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
00032 
00033 /* PRIVATE FUNCTIONS *********************************************************/
00034 
00035 VOID
00036 NTAPI
00037 INIT_FUNCTION
00038 CmpInitCallback(VOID)
00039 {
00040     ULONG i;
00041     PAGED_CODE();
00042 
00043     /* Reset counter */
00044     CmpCallBackCount = 0;
00045 
00046     /* Loop all the callbacks */
00047     for (i = 0; i < CMP_MAX_CALLBACKS; i++)
00048     {
00049         /* Initialize this one */
00050         ExInitializeCallBack(&CmpCallBackVector[i]);
00051     }
00052 
00053     /* ROS: Initialize old-style callbacks for now */
00054     InitializeListHead(&CmiCallbackHead);
00055     ExInitializeFastMutex(&CmiCallbackLock);
00056 }
00057 
00058 NTSTATUS
00059 CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
00060                            IN PVOID Argument2)
00061 {
00062     PLIST_ENTRY CurrentEntry;
00063     NTSTATUS Status = STATUS_SUCCESS;
00064     PREGISTRY_CALLBACK CurrentCallback;
00065     PAGED_CODE();
00066 
00067     ExAcquireFastMutex(&CmiCallbackLock);
00068 
00069     for (CurrentEntry = CmiCallbackHead.Flink;
00070          CurrentEntry != &CmiCallbackHead;
00071          CurrentEntry = CurrentEntry->Flink)
00072     {
00073         CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
00074         if (!CurrentCallback->PendingDelete &&
00075             ExAcquireRundownProtection(&CurrentCallback->RundownRef))
00076         {
00077             /* don't hold locks during the callbacks! */
00078             ExReleaseFastMutex(&CmiCallbackLock);
00079 
00080             Status = CurrentCallback->Function(CurrentCallback->Context,
00081                                          (PVOID)Argument1,
00082                                          Argument2);
00083 
00084             ExAcquireFastMutex(&CmiCallbackLock);
00085 
00086             /* don't release the rundown protection before holding the callback lock
00087             so the pointer to the next callback isn't cleared in case this callback
00088             get's deleted */
00089             ExReleaseRundownProtection(&CurrentCallback->RundownRef);
00090             if(!NT_SUCCESS(Status))
00091             {
00092                 /* one callback returned failure, don't call any more callbacks */
00093                 break;
00094             }
00095         }
00096     }
00097 
00098     ExReleaseFastMutex(&CmiCallbackLock);
00099 
00100     return Status;
00101 }
00102 
00103 /* PUBLIC FUNCTIONS **********************************************************/
00104 
00105 /*
00106  * @implemented
00107  */
00108 NTSTATUS
00109 NTAPI
00110 CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
00111                    IN PVOID Context,
00112                    IN OUT PLARGE_INTEGER Cookie)
00113 {
00114     PREGISTRY_CALLBACK Callback;
00115     PAGED_CODE();
00116     ASSERT(Function && Cookie);
00117 
00118     Callback = ExAllocatePoolWithTag(PagedPool,
00119                                    sizeof(REGISTRY_CALLBACK),
00120                                    'bcMC');
00121     if (Callback != NULL)
00122     {
00123         /* initialize the callback */
00124         ExInitializeRundownProtection(&Callback->RundownRef);
00125         Callback->Function = Function;
00126         Callback->Context = Context;
00127         Callback->PendingDelete = FALSE;
00128 
00129         /* add it to the callback list and receive a cookie for the callback */
00130         ExAcquireFastMutex(&CmiCallbackLock);
00131 
00132         /* FIXME - to receive a unique cookie we'll just return the pointer to the
00133            callback object */
00134         Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
00135         InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
00136 
00137         ExReleaseFastMutex(&CmiCallbackLock);
00138 
00139         *Cookie = Callback->Cookie;
00140         return STATUS_SUCCESS;
00141     }
00142 
00143     return STATUS_INSUFFICIENT_RESOURCES;
00144 }
00145 
00146 /*
00147  * @implemented
00148  */
00149 NTSTATUS
00150 NTAPI
00151 CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
00152 {
00153     PLIST_ENTRY CurrentEntry;
00154     PREGISTRY_CALLBACK CurrentCallback;
00155     PAGED_CODE();
00156 
00157     ExAcquireFastMutex(&CmiCallbackLock);
00158 
00159     for (CurrentEntry = CmiCallbackHead.Flink;
00160          CurrentEntry != &CmiCallbackHead;
00161          CurrentEntry = CurrentEntry->Flink)
00162     {
00163         CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
00164         if (CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
00165         {
00166             if (!CurrentCallback->PendingDelete)
00167             {
00168                 /* found the callback, don't unlink it from the list yet so we don't screw
00169                 the calling loop */
00170                 CurrentCallback->PendingDelete = TRUE;
00171                 ExReleaseFastMutex(&CmiCallbackLock);
00172 
00173                 /* if the callback is currently executing, wait until it finished */
00174                 ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
00175 
00176                 /* time to unlink it. It's now safe because every attempt to acquire a
00177                 runtime protection on this callback will fail */
00178                 ExAcquireFastMutex(&CmiCallbackLock);
00179                 RemoveEntryList(&CurrentCallback->ListEntry);
00180                 ExReleaseFastMutex(&CmiCallbackLock);
00181 
00182                 /* free the callback */
00183                 ExFreePool(CurrentCallback);
00184                 return STATUS_SUCCESS;
00185             }
00186             else
00187             {
00188                 /* pending delete, pretend like it already is deleted */
00189                 ExReleaseFastMutex(&CmiCallbackLock);
00190                 return STATUS_UNSUCCESSFUL;
00191             }
00192         }
00193     }
00194 
00195     ExReleaseFastMutex(&CmiCallbackLock);
00196 
00197     return STATUS_UNSUCCESSFUL;
00198 }

Generated on Sun May 27 2012 04:37:07 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.