2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/sem.c
5 * PURPOSE: Synchronization primitives
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
8 * David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 POBJECT_TYPE ExSemaphoreObjectType
;
21 static GENERIC_MAPPING ExSemaphoreMapping
= {
22 STANDARD_RIGHTS_READ
| SEMAPHORE_QUERY_STATE
,
23 STANDARD_RIGHTS_WRITE
| SEMAPHORE_MODIFY_STATE
,
24 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| SEMAPHORE_QUERY_STATE
,
25 SEMAPHORE_ALL_ACCESS
};
27 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass
[] = {
29 /* SemaphoreBasicInformation */
30 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
35 ExpInitializeSemaphoreImplementation(VOID
)
37 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
40 DPRINT1("Creating Semaphore Object Type\n");
42 /* Create the Event Pair Object Type */
43 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
44 RtlInitUnicodeString(&Name
, L
"Semaphore");
45 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
46 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KSEMAPHORE
);
47 ObjectTypeInitializer
.GenericMapping
= ExSemaphoreMapping
;
48 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
49 ObjectTypeInitializer
.ValidAccessMask
= SEMAPHORE_ALL_ACCESS
;
50 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
51 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &ExSemaphoreObjectType
);
59 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle
,
60 IN ACCESS_MASK DesiredAccess
,
61 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
65 PKSEMAPHORE Semaphore
;
67 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
68 NTSTATUS Status
= STATUS_SUCCESS
;
72 /* Check Output Safety */
73 if(PreviousMode
!= KernelMode
) {
77 ProbeForWrite(SemaphoreHandle
,
80 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
82 Status
= _SEH_GetExceptionCode();
86 if(!NT_SUCCESS(Status
)) return Status
;
89 /* Make sure the counts make sense */
90 if (!MaximumCount
|| InitialCount
< 0 || InitialCount
> MaximumCount
) {
92 DPRINT("Invalid Count Data!\n");
93 return STATUS_INVALID_PARAMETER
;
96 /* Create the Semaphore Object */
97 Status
= ObCreateObject(PreviousMode
,
98 ExSemaphoreObjectType
,
107 /* Check for Success */
108 if (NT_SUCCESS(Status
)) {
111 KeInitializeSemaphore(Semaphore
,
115 /* Insert it into the Object Tree */
116 Status
= ObInsertObject((PVOID
)Semaphore
,
122 ObDereferenceObject(Semaphore
);
124 /* Check for success and return handle */
125 if(NT_SUCCESS(Status
)) {
129 *SemaphoreHandle
= hSemaphore
;
131 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
133 Status
= _SEH_GetExceptionCode();
148 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
149 IN ACCESS_MASK DesiredAccess
,
150 IN POBJECT_ATTRIBUTES ObjectAttributes
)
153 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
154 NTSTATUS Status
= STATUS_SUCCESS
;
158 /* Check Output Safety */
159 if(PreviousMode
== UserMode
) {
163 ProbeForWrite(SemaphoreHandle
,
166 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
168 Status
= _SEH_GetExceptionCode();
172 if(!NT_SUCCESS(Status
)) return Status
;
175 /* Open the Object */
176 Status
= ObOpenObjectByName(ObjectAttributes
,
177 ExSemaphoreObjectType
,
184 /* Check for success and return handle */
185 if(NT_SUCCESS(Status
)) {
189 *SemaphoreHandle
= hSemaphore
;
191 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
193 Status
= _SEH_GetExceptionCode();
207 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
208 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
209 OUT PVOID SemaphoreInformation
,
210 IN ULONG SemaphoreInformationLength
,
211 OUT PULONG ReturnLength OPTIONAL
)
213 PKSEMAPHORE Semaphore
;
214 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
215 NTSTATUS Status
= STATUS_SUCCESS
;
219 /* Check buffers and class validity */
220 DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
221 ExSemaphoreInfoClass
,
222 SemaphoreInformation
,
223 SemaphoreInformationLength
,
227 if(!NT_SUCCESS(Status
)) {
229 /* Invalid buffers */
230 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
235 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
236 SEMAPHORE_QUERY_STATE
,
237 ExSemaphoreObjectType
,
242 /* Check for success */
243 if(NT_SUCCESS(Status
)) {
247 PSEMAPHORE_BASIC_INFORMATION BasicInfo
= (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
249 /* Return the basic information */
250 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
251 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
254 if(ReturnLength
) *ReturnLength
= sizeof(SEMAPHORE_BASIC_INFORMATION
);
256 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
258 Status
= _SEH_GetExceptionCode();
262 /* Dereference the Object */
263 ObDereferenceObject(Semaphore
);
275 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
276 IN LONG ReleaseCount
,
277 OUT PLONG PreviousCount OPTIONAL
)
279 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
280 PKSEMAPHORE Semaphore
;
281 NTSTATUS Status
= STATUS_SUCCESS
;
285 /* Check buffer validity */
286 if(PreviousCount
!= NULL
&& PreviousMode
== UserMode
) {
290 ProbeForWrite(PreviousCount
,
293 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
295 Status
= _SEH_GetExceptionCode();
299 if(!NT_SUCCESS(Status
)) return Status
;
302 /* Make sure count makes sense */
305 DPRINT("Invalid Release Count\n");
306 return STATUS_INVALID_PARAMETER
;
310 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
311 SEMAPHORE_MODIFY_STATE
,
312 ExSemaphoreObjectType
,
317 /* Check for success */
318 if (NT_SUCCESS(Status
)) {
320 /* Release the semaphore */
321 LONG PrevCount
= KeReleaseSemaphore(Semaphore
,
325 ObDereferenceObject(Semaphore
);
332 *PreviousCount
= PrevCount
;
334 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
336 Status
= _SEH_GetExceptionCode();