2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/mutant.c
5 * PURPOSE: Executive Management of Mutants
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeMutantImplementation)
20 /* DATA **********************************************************************/
22 POBJECT_TYPE ExMutantObjectType
= NULL
;
24 GENERIC_MAPPING ExpMutantMapping
=
26 STANDARD_RIGHTS_READ
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
27 STANDARD_RIGHTS_WRITE
| SYNCHRONIZE
,
28 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
32 static const INFORMATION_CLASS_INFO ExMutantInfoClass
[] =
34 /* MutantBasicInformation */
35 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
38 /* FUNCTIONS *****************************************************************/
42 ExpDeleteMutant(PVOID ObjectBody
)
44 DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody
);
46 /* Make sure to release the Mutant */
47 KeReleaseMutant((PKMUTANT
)ObjectBody
,
56 ExpInitializeMutantImplementation(VOID
)
58 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
60 DPRINT("Creating Mutant Object Type\n");
62 /* Create the Event Pair Object Type */
63 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
64 RtlInitUnicodeString(&Name
, L
"Mutant");
65 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
66 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KMUTANT
);
67 ObjectTypeInitializer
.GenericMapping
= ExpMutantMapping
;
68 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
69 ObjectTypeInitializer
.DeleteProcedure
= ExpDeleteMutant
;
70 ObjectTypeInitializer
.ValidAccessMask
= MUTANT_ALL_ACCESS
;
71 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExMutantObjectType
);
79 NtCreateMutant(OUT PHANDLE MutantHandle
,
80 IN ACCESS_MASK DesiredAccess
,
81 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
82 IN BOOLEAN InitialOwner
)
84 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
89 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
90 MutantHandle
, DesiredAccess
, ObjectAttributes
);
92 /* Check if we were called from user-mode */
93 if (PreviousMode
!= KernelMode
)
98 /* Check handle pointer */
99 ProbeForWriteHandle(MutantHandle
);
101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
103 /* Return the exception code */
104 _SEH2_YIELD(return _SEH2_GetExceptionCode());
109 /* Create the Mutant Object*/
110 Status
= ObCreateObject(PreviousMode
,
120 /* Check for success */
121 if(NT_SUCCESS(Status
))
123 /* Initalize the Kernel Mutant */
124 DPRINT("Initializing the Mutant\n");
125 KeInitializeMutant(Mutant
, InitialOwner
);
127 /* Insert the Object */
128 Status
= ObInsertObject((PVOID
)Mutant
,
135 /* Check for success */
136 if (NT_SUCCESS(Status
))
138 /* Enter SEH for return */
141 /* Return the handle to the caller */
142 *MutantHandle
= hMutant
;
144 _SEH2_EXCEPT(ExSystemExceptionFilter())
146 /* Get the exception code */
147 Status
= _SEH2_GetExceptionCode();
162 NtOpenMutant(OUT PHANDLE MutantHandle
,
163 IN ACCESS_MASK DesiredAccess
,
164 IN POBJECT_ATTRIBUTES ObjectAttributes
)
167 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
170 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
171 MutantHandle
, DesiredAccess
, ObjectAttributes
);
173 /* Check if we were called from user-mode */
174 if (PreviousMode
!= KernelMode
)
176 /* Enter SEH Block */
179 /* Check handle pointer */
180 ProbeForWriteHandle(MutantHandle
);
182 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
184 /* Return the exception code */
185 _SEH2_YIELD(return _SEH2_GetExceptionCode());
190 /* Open the Object */
191 Status
= ObOpenObjectByName(ObjectAttributes
,
199 /* Check for success */
200 if(NT_SUCCESS(Status
))
202 /* Enter SEH for return */
205 /* Return the handle to the caller */
206 *MutantHandle
= hMutant
;
208 _SEH2_EXCEPT(ExSystemExceptionFilter())
210 Status
= _SEH2_GetExceptionCode();
224 NtQueryMutant(IN HANDLE MutantHandle
,
225 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
226 OUT PVOID MutantInformation
,
227 IN ULONG MutantInformationLength
,
228 OUT PULONG ResultLength OPTIONAL
)
231 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
233 PMUTANT_BASIC_INFORMATION BasicInfo
=
234 (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
237 /* Check buffers and parameters */
238 Status
= DefaultQueryInfoBufferCheck(MutantInformationClass
,
240 sizeof(ExMutantInfoClass
) /
241 sizeof(ExMutantInfoClass
[0]),
243 MutantInformationLength
,
247 if(!NT_SUCCESS(Status
))
249 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status
);
253 /* Open the Object */
254 Status
= ObReferenceObjectByHandle(MutantHandle
,
260 /* Check for Status */
261 if (NT_SUCCESS(Status
))
263 /* Enter SEH Block for return */
266 /* Fill out the Basic Information Requested */
267 DPRINT("Returning Mutant Information\n");
268 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
269 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
==
270 KeGetCurrentThread());
271 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
273 /* Return the Result Length if requested */
274 if (ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
276 _SEH2_EXCEPT(ExSystemExceptionFilter())
278 Status
= _SEH2_GetExceptionCode();
282 /* Release the Object */
283 ObDereferenceObject(Mutant
);
295 NtReleaseMutant(IN HANDLE MutantHandle
,
296 IN PLONG PreviousCount OPTIONAL
)
299 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
302 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
306 /* Check if we were called from user-mode */
307 if ((PreviousCount
) && (PreviousMode
!= KernelMode
))
309 /* Entry SEH Block */
312 /* Make sure the state pointer is valid */
313 ProbeForWriteLong(PreviousCount
);
315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
317 /* Return the exception code */
318 _SEH2_YIELD(return _SEH2_GetExceptionCode());
323 /* Open the Object */
324 Status
= ObReferenceObjectByHandle(MutantHandle
,
331 /* Check for Success and release if such */
332 if (NT_SUCCESS(Status
))
335 * Release the mutant. doing so might raise an exception which we're
340 /* Release the mutant */
341 LONG Prev
= KeReleaseMutant(Mutant
,
346 /* Return the previous count if requested */
347 if (PreviousCount
) *PreviousCount
= Prev
;
349 _SEH2_EXCEPT(ExSystemExceptionFilter())
351 /* Get the exception code */
352 Status
= _SEH2_GetExceptionCode();
357 ObDereferenceObject(Mutant
);