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();
75 NTSTATUS Status
= STATUS_SUCCESS
;
78 /* Check if we were called from user-mode */
79 if(PreviousMode
!= KernelMode
)
84 /* Check handle pointer */
85 ProbeForWriteHandle(SemaphoreHandle
);
87 _SEH2_EXCEPT(ExSystemExceptionFilter())
89 Status
= _SEH2_GetExceptionCode();
93 /* Bail out if pointer was invalid */
94 if(!NT_SUCCESS(Status
)) return Status
;
97 /* Make sure the counts make sense */
98 if ((MaximumCount
<= 0) ||
100 (InitialCount
> MaximumCount
))
102 DPRINT("Invalid Count Data!\n");
103 return STATUS_INVALID_PARAMETER
;
106 /* Create the Semaphore Object */
107 Status
= ObCreateObject(PreviousMode
,
108 ExSemaphoreObjectType
,
117 /* Check for Success */
118 if (NT_SUCCESS(Status
))
121 KeInitializeSemaphore(Semaphore
,
125 /* Insert it into the Object Tree */
126 Status
= ObInsertObject((PVOID
)Semaphore
,
133 /* Check for success */
134 if(NT_SUCCESS(Status
))
136 /* Enter SEH Block for return */
139 /* Return the handle */
140 *SemaphoreHandle
= hSemaphore
;
142 _SEH2_EXCEPT(ExSystemExceptionFilter())
144 Status
= _SEH2_GetExceptionCode();
159 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
160 IN ACCESS_MASK DesiredAccess
,
161 IN POBJECT_ATTRIBUTES ObjectAttributes
)
164 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
165 NTSTATUS Status
= STATUS_SUCCESS
;
168 /* Check if we were called from user-mode */
169 if(PreviousMode
!= KernelMode
)
171 /* Enter SEH Block */
174 /* Check handle pointer */
175 ProbeForWriteHandle(SemaphoreHandle
);
177 _SEH2_EXCEPT(ExSystemExceptionFilter())
179 Status
= _SEH2_GetExceptionCode();
183 /* Bail out if pointer was invalid */
184 if(!NT_SUCCESS(Status
)) return Status
;
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 Status
= _SEH2_GetExceptionCode();
221 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
222 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
223 OUT PVOID SemaphoreInformation
,
224 IN ULONG SemaphoreInformationLength
,
225 OUT PULONG ReturnLength OPTIONAL
)
227 PKSEMAPHORE Semaphore
;
228 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
229 NTSTATUS Status
= STATUS_SUCCESS
;
232 /* Check buffers and class validity */
233 Status
= DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
234 ExSemaphoreInfoClass
,
235 sizeof(ExSemaphoreInfoClass
) /
236 sizeof(ExSemaphoreInfoClass
[0]),
237 SemaphoreInformation
,
238 SemaphoreInformationLength
,
242 if(!NT_SUCCESS(Status
))
244 /* Invalid buffers */
245 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
250 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
251 SEMAPHORE_QUERY_STATE
,
252 ExSemaphoreObjectType
,
257 /* Check for success */
258 if(NT_SUCCESS(Status
))
260 /* Entry SEH Block */
263 PSEMAPHORE_BASIC_INFORMATION BasicInfo
=
264 (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
266 /* Return the basic information */
267 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
268 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
270 /* Return the length */
271 if(ReturnLength
) *ReturnLength
= sizeof(*BasicInfo
);
273 _SEH2_EXCEPT(ExSystemExceptionFilter())
275 Status
= _SEH2_GetExceptionCode();
279 /* Dereference the Object */
280 ObDereferenceObject(Semaphore
);
292 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
293 IN LONG ReleaseCount
,
294 OUT PLONG PreviousCount OPTIONAL
)
296 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
297 PKSEMAPHORE Semaphore
;
298 NTSTATUS Status
= STATUS_SUCCESS
;
301 /* Check if we were called from user-mode */
302 if((PreviousCount
) && (PreviousMode
!= KernelMode
))
304 /* Entry SEH Block */
307 /* Make sure the state pointer is valid */
308 ProbeForWriteLong(PreviousCount
);
310 _SEH2_EXCEPT(ExSystemExceptionFilter())
312 Status
= _SEH2_GetExceptionCode();
316 /* Bail out if pointer was invalid */
317 if(!NT_SUCCESS(Status
)) return Status
;
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 Status
= _SEH2_GetExceptionCode();
356 ObDereferenceObject(Semaphore
);