Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmhook.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
1.7.6.1
|