2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/sem.c
5 * PURPOSE: Semaphore Implementation
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, ExpInitializeSemaphoreImplementation()
21 /* GLOBALS ******************************************************************/
23 POBJECT_TYPE ExSemaphoreObjectType
;
25 static GENERIC_MAPPING ExSemaphoreMapping
=
27 STANDARD_RIGHTS_READ
| SEMAPHORE_QUERY_STATE
,
28 STANDARD_RIGHTS_WRITE
| SEMAPHORE_MODIFY_STATE
,
29 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| SEMAPHORE_QUERY_STATE
,
33 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass
[] =
35 /* SemaphoreBasicInformation */
36 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
42 ExpInitializeSemaphoreImplementation(VOID
)
44 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 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &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();
75 NTSTATUS Status
= STATUS_SUCCESS
;
78 /* Check Output Safety */
79 if(PreviousMode
!= KernelMode
)
83 ProbeForWriteHandle(SemaphoreHandle
);
85 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
87 Status
= _SEH_GetExceptionCode();
91 if(!NT_SUCCESS(Status
)) return Status
;
94 /* Make sure the counts make sense */
95 if (MaximumCount
<= 0 || InitialCount
< 0 || InitialCount
> MaximumCount
)
97 DPRINT("Invalid Count Data!\n");
98 return STATUS_INVALID_PARAMETER
;
101 /* Create the Semaphore Object */
102 Status
= ObCreateObject(PreviousMode
,
103 ExSemaphoreObjectType
,
112 /* Check for Success */
113 if (NT_SUCCESS(Status
))
116 KeInitializeSemaphore(Semaphore
,
120 /* Insert it into the Object Tree */
121 Status
= ObInsertObject((PVOID
)Semaphore
,
127 ObDereferenceObject(Semaphore
);
129 /* Check for success and return handle */
130 if(NT_SUCCESS(Status
))
134 *SemaphoreHandle
= hSemaphore
;
136 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
138 Status
= _SEH_GetExceptionCode();
153 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
154 IN ACCESS_MASK DesiredAccess
,
155 IN POBJECT_ATTRIBUTES ObjectAttributes
)
158 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
159 NTSTATUS Status
= STATUS_SUCCESS
;
162 /* Check Output Safety */
163 if(PreviousMode
!= KernelMode
)
167 ProbeForWriteHandle(SemaphoreHandle
);
169 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
171 Status
= _SEH_GetExceptionCode();
175 if(!NT_SUCCESS(Status
)) return Status
;
178 /* Open the Object */
179 Status
= ObOpenObjectByName(ObjectAttributes
,
180 ExSemaphoreObjectType
,
187 /* Check for success and return handle */
188 if(NT_SUCCESS(Status
))
192 *SemaphoreHandle
= hSemaphore
;
194 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
196 Status
= _SEH_GetExceptionCode();
209 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
210 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
211 OUT PVOID SemaphoreInformation
,
212 IN ULONG SemaphoreInformationLength
,
213 OUT PULONG ReturnLength OPTIONAL
)
215 PKSEMAPHORE Semaphore
;
216 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
217 NTSTATUS Status
= STATUS_SUCCESS
;
221 /* Check buffers and class validity */
222 Status
= DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
223 ExSemaphoreInfoClass
,
224 sizeof(ExSemaphoreInfoClass
) / sizeof(ExSemaphoreInfoClass
[0]),
225 SemaphoreInformation
,
226 SemaphoreInformationLength
,
229 if(!NT_SUCCESS(Status
))
231 /* Invalid buffers */
232 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
237 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
238 SEMAPHORE_QUERY_STATE
,
239 ExSemaphoreObjectType
,
244 /* Check for success */
245 if(NT_SUCCESS(Status
))
249 PSEMAPHORE_BASIC_INFORMATION BasicInfo
= (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
251 /* Return the basic information */
252 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
253 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
256 if(ReturnLength
) *ReturnLength
= sizeof(SEMAPHORE_BASIC_INFORMATION
);
259 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
261 Status
= _SEH_GetExceptionCode();
264 /* Dereference the Object */
265 ObDereferenceObject(Semaphore
);
277 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
278 IN LONG ReleaseCount
,
279 OUT PLONG PreviousCount OPTIONAL
)
281 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
282 PKSEMAPHORE Semaphore
;
283 NTSTATUS Status
= STATUS_SUCCESS
;
287 /* Check buffer validity */
288 if(PreviousCount
&& PreviousMode
!= KernelMode
)
292 ProbeForWriteLong(PreviousCount
);
294 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
296 Status
= _SEH_GetExceptionCode();
300 if(!NT_SUCCESS(Status
)) return Status
;
303 /* Make sure count makes sense */
304 if (ReleaseCount
<= 0)
306 DPRINT("Invalid Release Count\n");
307 return STATUS_INVALID_PARAMETER
;
311 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
312 SEMAPHORE_MODIFY_STATE
,
313 ExSemaphoreObjectType
,
318 /* Check for success */
319 if (NT_SUCCESS(Status
))
321 /* Release the semaphore */
324 LONG PrevCount
= KeReleaseSemaphore(Semaphore
,
328 ObDereferenceObject(Semaphore
);
330 /* Return the old count if requested */
333 *PreviousCount
= PrevCount
;
336 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
338 Status
= _SEH_GetExceptionCode();