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
)
38 /* Create the Semaphore Object */
39 ExSemaphoreObjectType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
40 RtlInitUnicodeString(&ExSemaphoreObjectType
->TypeName
, L
"Semaphore");
41 ExSemaphoreObjectType
->Tag
= TAG('S', 'E', 'M', 'T');
42 ExSemaphoreObjectType
->PeakObjects
= 0;
43 ExSemaphoreObjectType
->PeakHandles
= 0;
44 ExSemaphoreObjectType
->TotalObjects
= 0;
45 ExSemaphoreObjectType
->TotalHandles
= 0;
46 ExSemaphoreObjectType
->PagedPoolCharge
= 0;
47 ExSemaphoreObjectType
->NonpagedPoolCharge
= sizeof(KSEMAPHORE
);
48 ExSemaphoreObjectType
->Mapping
= &ExSemaphoreMapping
;
49 ExSemaphoreObjectType
->Dump
= NULL
;
50 ExSemaphoreObjectType
->Open
= NULL
;
51 ExSemaphoreObjectType
->Close
= NULL
;
52 ExSemaphoreObjectType
->Delete
= NULL
;
53 ExSemaphoreObjectType
->Parse
= NULL
;
54 ExSemaphoreObjectType
->Security
= NULL
;
55 ExSemaphoreObjectType
->QueryName
= NULL
;
56 ExSemaphoreObjectType
->OkayToClose
= NULL
;
57 ExSemaphoreObjectType
->Create
= NULL
;
58 ExSemaphoreObjectType
->DuplicationNotify
= NULL
;
59 ObpCreateTypeObject(ExSemaphoreObjectType
);
67 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle
,
68 IN ACCESS_MASK DesiredAccess
,
69 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
73 PKSEMAPHORE Semaphore
;
75 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
76 NTSTATUS Status
= STATUS_SUCCESS
;
80 /* Check Output Safety */
81 if(PreviousMode
!= KernelMode
) {
85 ProbeForWrite(SemaphoreHandle
,
90 Status
= _SEH_GetExceptionCode();
94 if(!NT_SUCCESS(Status
)) return Status
;
97 /* Make sure the counts make sense */
98 if (!MaximumCount
|| InitialCount
< 0 || 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
,
130 ObDereferenceObject(Semaphore
);
132 /* Check for success and return handle */
133 if(NT_SUCCESS(Status
)) {
137 *SemaphoreHandle
= hSemaphore
;
141 Status
= _SEH_GetExceptionCode();
156 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle
,
157 IN ACCESS_MASK DesiredAccess
,
158 IN POBJECT_ATTRIBUTES ObjectAttributes
)
161 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
162 NTSTATUS Status
= STATUS_SUCCESS
;
166 /* Check Output Safety */
167 if(PreviousMode
== UserMode
) {
171 ProbeForWrite(SemaphoreHandle
,
176 Status
= _SEH_GetExceptionCode();
180 if(!NT_SUCCESS(Status
)) return Status
;
183 /* Open the Object */
184 Status
= ObOpenObjectByName(ObjectAttributes
,
185 ExSemaphoreObjectType
,
192 /* Check for success and return handle */
193 if(NT_SUCCESS(Status
)) {
197 *SemaphoreHandle
= hSemaphore
;
201 Status
= _SEH_GetExceptionCode();
215 NtQuerySemaphore(IN HANDLE SemaphoreHandle
,
216 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
217 OUT PVOID SemaphoreInformation
,
218 IN ULONG SemaphoreInformationLength
,
219 OUT PULONG ReturnLength OPTIONAL
)
221 PKSEMAPHORE Semaphore
;
222 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
223 NTSTATUS Status
= STATUS_SUCCESS
;
227 /* Check buffers and class validity */
228 DefaultQueryInfoBufferCheck(SemaphoreInformationClass
,
229 ExSemaphoreInfoClass
,
230 SemaphoreInformation
,
231 SemaphoreInformationLength
,
235 if(!NT_SUCCESS(Status
)) {
237 /* Invalid buffers */
238 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
243 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
244 SEMAPHORE_QUERY_STATE
,
245 ExSemaphoreObjectType
,
250 /* Check for success */
251 if(NT_SUCCESS(Status
)) {
255 PSEMAPHORE_BASIC_INFORMATION BasicInfo
= (PSEMAPHORE_BASIC_INFORMATION
)SemaphoreInformation
;
257 /* Return the basic information */
258 BasicInfo
->CurrentCount
= KeReadStateSemaphore(Semaphore
);
259 BasicInfo
->MaximumCount
= Semaphore
->Limit
;
262 if(ReturnLength
) *ReturnLength
= sizeof(SEMAPHORE_BASIC_INFORMATION
);
266 Status
= _SEH_GetExceptionCode();
270 /* Dereference the Object */
271 ObDereferenceObject(Semaphore
);
283 NtReleaseSemaphore(IN HANDLE SemaphoreHandle
,
284 IN LONG ReleaseCount
,
285 OUT PLONG PreviousCount OPTIONAL
)
287 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
288 PKSEMAPHORE Semaphore
;
289 NTSTATUS Status
= STATUS_SUCCESS
;
293 /* Check buffer validity */
294 if(PreviousCount
!= NULL
&& PreviousMode
== UserMode
) {
298 ProbeForWrite(PreviousCount
,
303 Status
= _SEH_GetExceptionCode();
307 if(!NT_SUCCESS(Status
)) return Status
;
310 /* Make sure count makes sense */
313 DPRINT("Invalid Release Count\n");
314 return STATUS_INVALID_PARAMETER
;
318 Status
= ObReferenceObjectByHandle(SemaphoreHandle
,
319 SEMAPHORE_MODIFY_STATE
,
320 ExSemaphoreObjectType
,
325 /* Check for success */
326 if (NT_SUCCESS(Status
)) {
328 /* Release the semaphore */
329 LONG PrevCount
= KeReleaseSemaphore(Semaphore
,
333 ObDereferenceObject(Semaphore
);
340 *PreviousCount
= PrevCount
;
344 Status
= _SEH_GetExceptionCode();