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
| MUTANT_QUERY_STATE
,
27 STANDARD_RIGHTS_WRITE
,
28 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
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
;
61 DPRINT("Creating Mutant Object Type\n");
63 /* Create the Event Pair Object Type */
64 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
65 RtlInitUnicodeString(&Name
, L
"Mutant");
66 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
67 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KMUTANT
);
68 ObjectTypeInitializer
.GenericMapping
= ExpMutantMapping
;
69 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
70 ObjectTypeInitializer
.DeleteProcedure
= ExpDeleteMutant
;
71 ObjectTypeInitializer
.ValidAccessMask
= MUTANT_ALL_ACCESS
;
72 Status
= ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExMutantObjectType
);
73 if (!NT_SUCCESS(Status
)) return FALSE
;
82 NtCreateMutant(OUT PHANDLE MutantHandle
,
83 IN ACCESS_MASK DesiredAccess
,
84 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
85 IN BOOLEAN InitialOwner
)
87 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
92 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
93 MutantHandle
, DesiredAccess
, ObjectAttributes
);
95 /* Check if we were called from user-mode */
96 if (PreviousMode
!= KernelMode
)
101 /* Check handle pointer */
102 ProbeForWriteHandle(MutantHandle
);
104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
106 /* Return the exception code */
107 _SEH2_YIELD(return _SEH2_GetExceptionCode());
112 /* Create the Mutant Object*/
113 Status
= ObCreateObject(PreviousMode
,
123 /* Check for success */
124 if(NT_SUCCESS(Status
))
126 /* Initialize the Kernel Mutant */
127 DPRINT("Initializing the Mutant\n");
128 KeInitializeMutant(Mutant
, InitialOwner
);
130 /* Insert the Object */
131 Status
= ObInsertObject((PVOID
)Mutant
,
138 /* Check for success */
139 if (NT_SUCCESS(Status
))
141 /* Enter SEH for return */
144 /* Return the handle to the caller */
145 *MutantHandle
= hMutant
;
147 _SEH2_EXCEPT(ExSystemExceptionFilter())
149 /* Get the exception code */
150 Status
= _SEH2_GetExceptionCode();
165 NtOpenMutant(OUT PHANDLE MutantHandle
,
166 IN ACCESS_MASK DesiredAccess
,
167 IN POBJECT_ATTRIBUTES ObjectAttributes
)
170 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
173 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
174 MutantHandle
, DesiredAccess
, ObjectAttributes
);
176 /* Check if we were called from user-mode */
177 if (PreviousMode
!= KernelMode
)
179 /* Enter SEH Block */
182 /* Check handle pointer */
183 ProbeForWriteHandle(MutantHandle
);
185 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
187 /* Return the exception code */
188 _SEH2_YIELD(return _SEH2_GetExceptionCode());
193 /* Open the Object */
194 Status
= ObOpenObjectByName(ObjectAttributes
,
202 /* Check for success */
203 if(NT_SUCCESS(Status
))
205 /* Enter SEH for return */
208 /* Return the handle to the caller */
209 *MutantHandle
= hMutant
;
211 _SEH2_EXCEPT(ExSystemExceptionFilter())
213 Status
= _SEH2_GetExceptionCode();
227 NtQueryMutant(IN HANDLE MutantHandle
,
228 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
229 OUT PVOID MutantInformation
,
230 IN ULONG MutantInformationLength
,
231 OUT PULONG ResultLength OPTIONAL
)
234 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
236 PMUTANT_BASIC_INFORMATION BasicInfo
=
237 (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
240 /* Check buffers and parameters */
241 Status
= DefaultQueryInfoBufferCheck(MutantInformationClass
,
243 sizeof(ExMutantInfoClass
) /
244 sizeof(ExMutantInfoClass
[0]),
246 MutantInformationLength
,
250 if(!NT_SUCCESS(Status
))
252 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status
);
256 /* Open the Object */
257 Status
= ObReferenceObjectByHandle(MutantHandle
,
263 /* Check for Status */
264 if (NT_SUCCESS(Status
))
266 /* Enter SEH Block for return */
269 /* Fill out the Basic Information Requested */
270 DPRINT("Returning Mutant Information\n");
271 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
272 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
==
273 KeGetCurrentThread());
274 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
276 /* Return the Result Length if requested */
277 if (ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
279 _SEH2_EXCEPT(ExSystemExceptionFilter())
281 Status
= _SEH2_GetExceptionCode();
285 /* Release the Object */
286 ObDereferenceObject(Mutant
);
298 NtReleaseMutant(IN HANDLE MutantHandle
,
299 IN PLONG PreviousCount OPTIONAL
)
302 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
305 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
309 /* Check if we were called from user-mode */
310 if ((PreviousCount
) && (PreviousMode
!= KernelMode
))
312 /* Entry SEH Block */
315 /* Make sure the state pointer is valid */
316 ProbeForWriteLong(PreviousCount
);
318 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
320 /* Return the exception code */
321 _SEH2_YIELD(return _SEH2_GetExceptionCode());
326 /* Open the Object */
327 Status
= ObReferenceObjectByHandle(MutantHandle
,
334 /* Check for Success and release if such */
335 if (NT_SUCCESS(Status
))
338 * Release the mutant. doing so might raise an exception which we're
343 /* Release the mutant */
344 LONG Prev
= KeReleaseMutant(Mutant
,
349 /* Return the previous count if requested */
350 if (PreviousCount
) *PreviousCount
= Prev
;
352 _SEH2_EXCEPT(ExSystemExceptionFilter())
354 /* Get the exception code */
355 Status
= _SEH2_GetExceptionCode();
360 ObDereferenceObject(Mutant
);