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
| SEMAPHORE_QUERY_STATE
,
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
;
47 DPRINT("Creating Semaphore Object Type\n");
49 /* Create the Event Pair Object Type */
50 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
51 RtlInitUnicodeString(&Name
, L
"Semaphore");
52 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
53 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KSEMAPHORE
);
54 ObjectTypeInitializer
.GenericMapping
= ExSemaphoreMapping
;
55 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
56 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
57 ObjectTypeInitializer
.ValidAccessMask
= SEMAPHORE_ALL_ACCESS
;
58 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExSemaphoreObjectType
);
66 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle
,
67 IN ACCESS_MASK DesiredAccess
,
68 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
72 PKSEMAPHORE Semaphore
;
74 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
78 /* Check if we were called from user-mode */
79 if (PreviousMode
!= KernelMode
)
84 /* Check handle pointer */
85 ProbeForWriteHandle(SemaphoreHandle
);
87 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
89 /* Return the exception code */
90 _SEH2_YIELD(return _SEH2_GetExceptionCode());
95 /* Make sure the counts make sense */
96 if ((MaximumCount
<= 0) ||
98 (InitialCount
> MaximumCount
))
100 DPRINT("Invalid Count Data!\n");
101 return STATUS_INVALID_PARAMETER
;
104 /* Create the Semaphore Object */
105 Status
= ObCreateObject(PreviousMode
,
106 ExSemaphoreObjectType
,
115 /* Check for Success */
116 if (NT_SUCCESS(Status
))
119 KeInitializeSemaphore(Semaphore
,
123 /* Insert it into the Object Tree */
124 Status
= ObInsertObject((PVOID
)Semaphore
,
131 /* Check for success */
132 if (NT_SUCCESS(Status
))
134 /* Enter SEH Block for return */
137 /* Return the handle */
138 *SemaphoreHandle
= hSemaphore
;
140 _SEH2_EXCEPT(ExSystemExceptionFilter())
142 /* Get the exception code */
143 Status
= _SEH2_GetExceptionCode();
158 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
159 IN ACCESS_MASK DesiredAccess
,
160 IN POBJECT_ATTRIBUTES ObjectAttributes
)
163 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
167 /* Check if we were called from user-mode */
168 if (PreviousMode
!= KernelMode
)
170 /* Enter SEH Block */
173 /* Check handle pointer */
174 ProbeForWriteHandle(SemaphoreHandle
);
176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
178 /* Return the exception code */
179 _SEH2_YIELD(return _SEH2_GetExceptionCode());
184 /* Open the Object */
185 Status
= ObOpenObjectByName(ObjectAttributes
,
186 ExSemaphoreObjectType
,
193 /* Check for success */
194 if (NT_SUCCESS(Status
))
196 /* Enter SEH Block for return */
199 /* Return the handle */
200 *SemaphoreHandle
= hSemaphore
;
202 _SEH2_EXCEPT(ExSystemExceptionFilter())
204 /* Get the exception code */
205 Status
= _SEH2_GetExceptionCode();
219 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
220 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
221 OUT PVOID SemaphoreInformation
,
222 IN ULONG SemaphoreInformationLength
,
223 OUT PULONG ReturnLength OPTIONAL
)
225 PKSEMAPHORE Semaphore
;
226 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
230 /* Check buffers and class validity */
231 Status
= DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
232 ExSemaphoreInfoClass
,
233 sizeof(ExSemaphoreInfoClass
) /
234 sizeof(ExSemaphoreInfoClass
[0]),
235 SemaphoreInformation
,
236 SemaphoreInformationLength
,
240 if (!NT_SUCCESS(Status
))
242 /* Invalid buffers */
243 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
248 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
249 SEMAPHORE_QUERY_STATE
,
250 ExSemaphoreObjectType
,
255 /* Check for success */
256 if (NT_SUCCESS(Status
))
258 /* Entry SEH Block */
261 PSEMAPHORE_BASIC_INFORMATION BasicInfo
=
262 (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
264 /* Return the basic information */
265 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
266 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
268 /* Return the length */
269 if (ReturnLength
) *ReturnLength
= sizeof(*BasicInfo
);
271 _SEH2_EXCEPT(ExSystemExceptionFilter())
273 /* Get the exception code */
274 Status
= _SEH2_GetExceptionCode();
278 /* Dereference the Object */
279 ObDereferenceObject(Semaphore
);
291 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
292 IN LONG ReleaseCount
,
293 OUT PLONG PreviousCount OPTIONAL
)
295 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
296 PKSEMAPHORE Semaphore
;
300 /* Check if we were called from user-mode */
301 if ((PreviousCount
) && (PreviousMode
!= KernelMode
))
303 /* Entry SEH Block */
306 /* Make sure the state pointer is valid */
307 ProbeForWriteLong(PreviousCount
);
309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
311 /* Return the exception code */
312 _SEH2_YIELD(return _SEH2_GetExceptionCode());
317 /* Make sure count makes sense */
318 if (ReleaseCount
<= 0)
320 DPRINT("Invalid Release Count\n");
321 return STATUS_INVALID_PARAMETER
;
325 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
326 SEMAPHORE_MODIFY_STATE
,
327 ExSemaphoreObjectType
,
332 /* Check for success */
333 if (NT_SUCCESS(Status
))
335 /* Enter SEH Block */
338 /* Release the semaphore */
339 LONG PrevCount
= KeReleaseSemaphore(Semaphore
,
344 /* Return the old count if requested */
345 if (PreviousCount
) *PreviousCount
= PrevCount
;
347 _SEH2_EXCEPT(ExSystemExceptionFilter())
349 /* Get the exception code */
350 Status
= _SEH2_GetExceptionCode();
354 /* Dereference the Semaphore */
355 ObDereferenceObject(Semaphore
);