2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/sem.c
5 * PURPOSE: Semaphore Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeSemaphoreImplementation)
20 /* GLOBALS ******************************************************************/
22 POBJECT_TYPE ExSemaphoreObjectType
;
24 GENERIC_MAPPING ExSemaphoreMapping
=
26 STANDARD_RIGHTS_READ
| SEMAPHORE_QUERY_STATE
,
27 STANDARD_RIGHTS_WRITE
| SEMAPHORE_MODIFY_STATE
,
28 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
32 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass
[] =
34 /* SemaphoreBasicInformation */
35 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
38 /* FUNCTIONS *****************************************************************/
43 ExpInitializeSemaphoreImplementation(VOID
)
45 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
48 DPRINT("Creating Semaphore Object Type\n");
50 /* Create the Event Pair Object Type */
51 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
52 RtlInitUnicodeString(&Name
, L
"Semaphore");
53 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
54 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KSEMAPHORE
);
55 ObjectTypeInitializer
.GenericMapping
= ExSemaphoreMapping
;
56 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
57 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
58 ObjectTypeInitializer
.ValidAccessMask
= SEMAPHORE_ALL_ACCESS
;
59 Status
= ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExSemaphoreObjectType
);
60 if (!NT_SUCCESS(Status
)) return FALSE
;
69 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle
,
70 IN ACCESS_MASK DesiredAccess
,
71 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
75 PKSEMAPHORE Semaphore
;
77 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
81 /* Check if we were called from user-mode */
82 if (PreviousMode
!= KernelMode
)
87 /* Check handle pointer */
88 ProbeForWriteHandle(SemaphoreHandle
);
90 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
92 /* Return the exception code */
93 _SEH2_YIELD(return _SEH2_GetExceptionCode());
98 /* Make sure the counts make sense */
99 if ((MaximumCount
<= 0) ||
100 (InitialCount
< 0) ||
101 (InitialCount
> MaximumCount
))
103 DPRINT("Invalid Count Data!\n");
104 return STATUS_INVALID_PARAMETER
;
107 /* Create the Semaphore Object */
108 Status
= ObCreateObject(PreviousMode
,
109 ExSemaphoreObjectType
,
118 /* Check for Success */
119 if (NT_SUCCESS(Status
))
122 KeInitializeSemaphore(Semaphore
,
126 /* Insert it into the Object Tree */
127 Status
= ObInsertObject((PVOID
)Semaphore
,
134 /* Check for success */
135 if (NT_SUCCESS(Status
))
137 /* Enter SEH Block for return */
140 /* Return the handle */
141 *SemaphoreHandle
= hSemaphore
;
143 _SEH2_EXCEPT(ExSystemExceptionFilter())
145 /* Get the exception code */
146 Status
= _SEH2_GetExceptionCode();
161 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
162 IN ACCESS_MASK DesiredAccess
,
163 IN POBJECT_ATTRIBUTES ObjectAttributes
)
166 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
170 /* Check if we were called from user-mode */
171 if (PreviousMode
!= KernelMode
)
173 /* Enter SEH Block */
176 /* Check handle pointer */
177 ProbeForWriteHandle(SemaphoreHandle
);
179 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
181 /* Return the exception code */
182 _SEH2_YIELD(return _SEH2_GetExceptionCode());
187 /* Open the Object */
188 Status
= ObOpenObjectByName(ObjectAttributes
,
189 ExSemaphoreObjectType
,
196 /* Check for success */
197 if (NT_SUCCESS(Status
))
199 /* Enter SEH Block for return */
202 /* Return the handle */
203 *SemaphoreHandle
= hSemaphore
;
205 _SEH2_EXCEPT(ExSystemExceptionFilter())
207 /* Get the exception code */
208 Status
= _SEH2_GetExceptionCode();
222 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
223 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
224 OUT PVOID SemaphoreInformation
,
225 IN ULONG SemaphoreInformationLength
,
226 OUT PULONG ReturnLength OPTIONAL
)
228 PKSEMAPHORE Semaphore
;
229 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
233 /* Check buffers and class validity */
234 Status
= DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
235 ExSemaphoreInfoClass
,
236 sizeof(ExSemaphoreInfoClass
) /
237 sizeof(ExSemaphoreInfoClass
[0]),
238 SemaphoreInformation
,
239 SemaphoreInformationLength
,
243 if (!NT_SUCCESS(Status
))
245 /* Invalid buffers */
246 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
251 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
252 SEMAPHORE_QUERY_STATE
,
253 ExSemaphoreObjectType
,
258 /* Check for success */
259 if (NT_SUCCESS(Status
))
261 /* Entry SEH Block */
264 PSEMAPHORE_BASIC_INFORMATION BasicInfo
=
265 (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
267 /* Return the basic information */
268 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
269 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
271 /* Return the length */
272 if (ReturnLength
) *ReturnLength
= sizeof(*BasicInfo
);
274 _SEH2_EXCEPT(ExSystemExceptionFilter())
276 /* Get the exception code */
277 Status
= _SEH2_GetExceptionCode();
281 /* Dereference the Object */
282 ObDereferenceObject(Semaphore
);
294 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
295 IN LONG ReleaseCount
,
296 OUT PLONG PreviousCount OPTIONAL
)
298 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
299 PKSEMAPHORE Semaphore
;
303 /* Check if we were called from user-mode */
304 if ((PreviousCount
) && (PreviousMode
!= KernelMode
))
306 /* Entry SEH Block */
309 /* Make sure the state pointer is valid */
310 ProbeForWriteLong(PreviousCount
);
312 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
314 /* Return the exception code */
315 _SEH2_YIELD(return _SEH2_GetExceptionCode());
320 /* Make sure count makes sense */
321 if (ReleaseCount
<= 0)
323 DPRINT("Invalid Release Count\n");
324 return STATUS_INVALID_PARAMETER
;
328 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
329 SEMAPHORE_MODIFY_STATE
,
330 ExSemaphoreObjectType
,
335 /* Check for success */
336 if (NT_SUCCESS(Status
))
338 /* Enter SEH Block */
341 /* Release the semaphore */
342 LONG PrevCount
= KeReleaseSemaphore(Semaphore
,
347 /* Return the old count if requested */
348 if (PreviousCount
) *PreviousCount
= PrevCount
;
350 _SEH2_EXCEPT(ExSystemExceptionFilter())
352 /* Get the exception code */
353 Status
= _SEH2_GetExceptionCode();
357 /* Dereference the Semaphore */
358 ObDereferenceObject(Semaphore
);