Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensem.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel 00004 * FILE: ntoskrnl/ex/sem.c 00005 * PURPOSE: Semaphore Implementation 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 * Thomas Weidenmueller 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 #if defined (ALLOC_PRAGMA) 00017 #pragma alloc_text(INIT, ExpInitializeSemaphoreImplementation) 00018 #endif 00019 00020 /* GLOBALS ******************************************************************/ 00021 00022 POBJECT_TYPE _ExSemaphoreObjectType; 00023 00024 GENERIC_MAPPING ExSemaphoreMapping = 00025 { 00026 STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE, 00027 STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE, 00028 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE, 00029 SEMAPHORE_ALL_ACCESS 00030 }; 00031 00032 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = 00033 { 00034 /* SemaphoreBasicInformation */ 00035 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY), 00036 }; 00037 00038 /* FUNCTIONS *****************************************************************/ 00039 00040 VOID 00041 INIT_FUNCTION 00042 NTAPI 00043 ExpInitializeSemaphoreImplementation(VOID) 00044 { 00045 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 00046 UNICODE_STRING Name; 00047 DPRINT("Creating Semaphore Object Type\n"); 00048 00049 /* Create the Event Pair Object Type */ 00050 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 00051 RtlInitUnicodeString(&Name, L"Semaphore"); 00052 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 00053 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KSEMAPHORE); 00054 ObjectTypeInitializer.GenericMapping = ExSemaphoreMapping; 00055 ObjectTypeInitializer.PoolType = NonPagedPool; 00056 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 00057 ObjectTypeInitializer.ValidAccessMask = SEMAPHORE_ALL_ACCESS; 00058 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExSemaphoreObjectType); 00059 } 00060 00061 /* 00062 * @implemented 00063 */ 00064 NTSTATUS 00065 NTAPI 00066 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle, 00067 IN ACCESS_MASK DesiredAccess, 00068 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 00069 IN LONG InitialCount, 00070 IN LONG MaximumCount) 00071 { 00072 PKSEMAPHORE Semaphore; 00073 HANDLE hSemaphore; 00074 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00075 NTSTATUS Status; 00076 PAGED_CODE(); 00077 00078 /* Check if we were called from user-mode */ 00079 if (PreviousMode != KernelMode) 00080 { 00081 /* Enter SEH Block */ 00082 _SEH2_TRY 00083 { 00084 /* Check handle pointer */ 00085 ProbeForWriteHandle(SemaphoreHandle); 00086 } 00087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00088 { 00089 /* Return the exception code */ 00090 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00091 } 00092 _SEH2_END; 00093 } 00094 00095 /* Make sure the counts make sense */ 00096 if ((MaximumCount <= 0) || 00097 (InitialCount < 0) || 00098 (InitialCount > MaximumCount)) 00099 { 00100 DPRINT("Invalid Count Data!\n"); 00101 return STATUS_INVALID_PARAMETER; 00102 } 00103 00104 /* Create the Semaphore Object */ 00105 Status = ObCreateObject(PreviousMode, 00106 ExSemaphoreObjectType, 00107 ObjectAttributes, 00108 PreviousMode, 00109 NULL, 00110 sizeof(KSEMAPHORE), 00111 0, 00112 0, 00113 (PVOID*)&Semaphore); 00114 00115 /* Check for Success */ 00116 if (NT_SUCCESS(Status)) 00117 { 00118 /* Initialize it */ 00119 KeInitializeSemaphore(Semaphore, 00120 InitialCount, 00121 MaximumCount); 00122 00123 /* Insert it into the Object Tree */ 00124 Status = ObInsertObject((PVOID)Semaphore, 00125 NULL, 00126 DesiredAccess, 00127 0, 00128 NULL, 00129 &hSemaphore); 00130 00131 /* Check for success */ 00132 if (NT_SUCCESS(Status)) 00133 { 00134 /* Enter SEH Block for return */ 00135 _SEH2_TRY 00136 { 00137 /* Return the handle */ 00138 *SemaphoreHandle = hSemaphore; 00139 } 00140 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00141 { 00142 /* Get the exception code */ 00143 Status = _SEH2_GetExceptionCode(); 00144 } 00145 _SEH2_END; 00146 } 00147 } 00148 00149 /* Return Status */ 00150 return Status; 00151 } 00152 00153 /* 00154 * @implemented 00155 */ 00156 NTSTATUS 00157 NTAPI 00158 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle, 00159 IN ACCESS_MASK DesiredAccess, 00160 IN POBJECT_ATTRIBUTES ObjectAttributes) 00161 { 00162 HANDLE hSemaphore; 00163 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00164 NTSTATUS Status; 00165 PAGED_CODE(); 00166 00167 /* Check if we were called from user-mode */ 00168 if (PreviousMode != KernelMode) 00169 { 00170 /* Enter SEH Block */ 00171 _SEH2_TRY 00172 { 00173 /* Check handle pointer */ 00174 ProbeForWriteHandle(SemaphoreHandle); 00175 } 00176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00177 { 00178 /* Return the exception code */ 00179 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00180 } 00181 _SEH2_END; 00182 } 00183 00184 /* Open the Object */ 00185 Status = ObOpenObjectByName(ObjectAttributes, 00186 ExSemaphoreObjectType, 00187 PreviousMode, 00188 NULL, 00189 DesiredAccess, 00190 NULL, 00191 &hSemaphore); 00192 00193 /* Check for success */ 00194 if (NT_SUCCESS(Status)) 00195 { 00196 /* Enter SEH Block for return */ 00197 _SEH2_TRY 00198 { 00199 /* Return the handle */ 00200 *SemaphoreHandle = hSemaphore; 00201 } 00202 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00203 { 00204 /* Get the exception code */ 00205 Status = _SEH2_GetExceptionCode(); 00206 } 00207 _SEH2_END; 00208 } 00209 00210 /* Return Status */ 00211 return Status; 00212 } 00213 00214 /* 00215 * @implemented 00216 */ 00217 NTSTATUS 00218 NTAPI 00219 NtQuerySemaphore(IN HANDLE SemaphoreHandle, 00220 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, 00221 OUT PVOID SemaphoreInformation, 00222 IN ULONG SemaphoreInformationLength, 00223 OUT PULONG ReturnLength OPTIONAL) 00224 { 00225 PKSEMAPHORE Semaphore; 00226 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00227 NTSTATUS Status; 00228 PAGED_CODE(); 00229 00230 /* Check buffers and class validity */ 00231 Status = DefaultQueryInfoBufferCheck(SemaphoreInformationClass, 00232 ExSemaphoreInfoClass, 00233 sizeof(ExSemaphoreInfoClass) / 00234 sizeof(ExSemaphoreInfoClass[0]), 00235 SemaphoreInformation, 00236 SemaphoreInformationLength, 00237 ReturnLength, 00238 NULL, 00239 PreviousMode); 00240 if (!NT_SUCCESS(Status)) 00241 { 00242 /* Invalid buffers */ 00243 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status); 00244 return Status; 00245 } 00246 00247 /* Get the Object */ 00248 Status = ObReferenceObjectByHandle(SemaphoreHandle, 00249 SEMAPHORE_QUERY_STATE, 00250 ExSemaphoreObjectType, 00251 PreviousMode, 00252 (PVOID*)&Semaphore, 00253 NULL); 00254 00255 /* Check for success */ 00256 if (NT_SUCCESS(Status)) 00257 { 00258 /* Entry SEH Block */ 00259 _SEH2_TRY 00260 { 00261 PSEMAPHORE_BASIC_INFORMATION BasicInfo = 00262 (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation; 00263 00264 /* Return the basic information */ 00265 BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore); 00266 BasicInfo->MaximumCount = Semaphore->Limit; 00267 00268 /* Return the length */ 00269 if (ReturnLength) *ReturnLength = sizeof(*BasicInfo); 00270 } 00271 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00272 { 00273 /* Get the exception code */ 00274 Status = _SEH2_GetExceptionCode(); 00275 } 00276 _SEH2_END; 00277 00278 /* Dereference the Object */ 00279 ObDereferenceObject(Semaphore); 00280 } 00281 00282 /* Return status */ 00283 return Status; 00284 } 00285 00286 /* 00287 * @implemented 00288 */ 00289 NTSTATUS 00290 NTAPI 00291 NtReleaseSemaphore(IN HANDLE SemaphoreHandle, 00292 IN LONG ReleaseCount, 00293 OUT PLONG PreviousCount OPTIONAL) 00294 { 00295 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00296 PKSEMAPHORE Semaphore; 00297 NTSTATUS Status; 00298 PAGED_CODE(); 00299 00300 /* Check if we were called from user-mode */ 00301 if ((PreviousCount) && (PreviousMode != KernelMode)) 00302 { 00303 /* Entry SEH Block */ 00304 _SEH2_TRY 00305 { 00306 /* Make sure the state pointer is valid */ 00307 ProbeForWriteLong(PreviousCount); 00308 } 00309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00310 { 00311 /* Return the exception code */ 00312 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00313 } 00314 _SEH2_END; 00315 } 00316 00317 /* Make sure count makes sense */ 00318 if (ReleaseCount <= 0) 00319 { 00320 DPRINT("Invalid Release Count\n"); 00321 return STATUS_INVALID_PARAMETER; 00322 } 00323 00324 /* Get the Object */ 00325 Status = ObReferenceObjectByHandle(SemaphoreHandle, 00326 SEMAPHORE_MODIFY_STATE, 00327 ExSemaphoreObjectType, 00328 PreviousMode, 00329 (PVOID*)&Semaphore, 00330 NULL); 00331 00332 /* Check for success */ 00333 if (NT_SUCCESS(Status)) 00334 { 00335 /* Enter SEH Block */ 00336 _SEH2_TRY 00337 { 00338 /* Release the semaphore */ 00339 LONG PrevCount = KeReleaseSemaphore(Semaphore, 00340 IO_NO_INCREMENT, 00341 ReleaseCount, 00342 FALSE); 00343 00344 /* Return the old count if requested */ 00345 if (PreviousCount) *PreviousCount = PrevCount; 00346 } 00347 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00348 { 00349 /* Get the exception code */ 00350 Status = _SEH2_GetExceptionCode(); 00351 } 00352 _SEH2_END; 00353 00354 /* Dereference the Semaphore */ 00355 ObDereferenceObject(Semaphore); 00356 } 00357 00358 /* Return Status */ 00359 return Status; 00360 } 00361 00362 /* EOF */ Generated on Fri May 25 2012 04:35:32 for ReactOS by
1.7.6.1
|