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 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
73 Status
= ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExMutantObjectType
);
74 if (!NT_SUCCESS(Status
)) return FALSE
;
83 NtCreateMutant(OUT PHANDLE MutantHandle
,
84 IN ACCESS_MASK DesiredAccess
,
85 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
86 IN BOOLEAN InitialOwner
)
88 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
93 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
94 MutantHandle
, DesiredAccess
, ObjectAttributes
);
96 /* Check if we were called from user-mode */
97 if (PreviousMode
!= KernelMode
)
102 /* Check handle pointer */
103 ProbeForWriteHandle(MutantHandle
);
105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
107 /* Return the exception code */
108 _SEH2_YIELD(return _SEH2_GetExceptionCode());
113 /* Create the Mutant Object*/
114 Status
= ObCreateObject(PreviousMode
,
124 /* Check for success */
125 if(NT_SUCCESS(Status
))
127 /* Initialize the Kernel Mutant */
128 DPRINT("Initializing the Mutant\n");
129 KeInitializeMutant(Mutant
, InitialOwner
);
131 /* Insert the Object */
132 Status
= ObInsertObject((PVOID
)Mutant
,
139 /* Check for success */
140 if (NT_SUCCESS(Status
))
142 /* Enter SEH for return */
145 /* Return the handle to the caller */
146 *MutantHandle
= hMutant
;
148 _SEH2_EXCEPT(ExSystemExceptionFilter())
150 /* Get the exception code */
151 Status
= _SEH2_GetExceptionCode();
166 NtOpenMutant(OUT PHANDLE MutantHandle
,
167 IN ACCESS_MASK DesiredAccess
,
168 IN POBJECT_ATTRIBUTES ObjectAttributes
)
171 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
174 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
175 MutantHandle
, DesiredAccess
, ObjectAttributes
);
177 /* Check if we were called from user-mode */
178 if (PreviousMode
!= KernelMode
)
180 /* Enter SEH Block */
183 /* Check handle pointer */
184 ProbeForWriteHandle(MutantHandle
);
186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
188 /* Return the exception code */
189 _SEH2_YIELD(return _SEH2_GetExceptionCode());
194 /* Open the Object */
195 Status
= ObOpenObjectByName(ObjectAttributes
,
203 /* Check for success */
204 if(NT_SUCCESS(Status
))
206 /* Enter SEH for return */
209 /* Return the handle to the caller */
210 *MutantHandle
= hMutant
;
212 _SEH2_EXCEPT(ExSystemExceptionFilter())
214 Status
= _SEH2_GetExceptionCode();
228 NtQueryMutant(IN HANDLE MutantHandle
,
229 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
230 OUT PVOID MutantInformation
,
231 IN ULONG MutantInformationLength
,
232 OUT PULONG ResultLength OPTIONAL
)
235 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
237 PMUTANT_BASIC_INFORMATION BasicInfo
=
238 (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
241 /* Check buffers and parameters */
242 Status
= DefaultQueryInfoBufferCheck(MutantInformationClass
,
244 sizeof(ExMutantInfoClass
) /
245 sizeof(ExMutantInfoClass
[0]),
247 MutantInformationLength
,
251 if(!NT_SUCCESS(Status
))
253 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status
);
257 /* Open the Object */
258 Status
= ObReferenceObjectByHandle(MutantHandle
,
264 /* Check for Status */
265 if (NT_SUCCESS(Status
))
267 /* Enter SEH Block for return */
270 /* Fill out the Basic Information Requested */
271 DPRINT("Returning Mutant Information\n");
272 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
273 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
==
274 KeGetCurrentThread());
275 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
277 /* Return the Result Length if requested */
278 if (ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
280 _SEH2_EXCEPT(ExSystemExceptionFilter())
282 Status
= _SEH2_GetExceptionCode();
286 /* Release the Object */
287 ObDereferenceObject(Mutant
);
299 NtReleaseMutant(IN HANDLE MutantHandle
,
300 IN PLONG PreviousCount OPTIONAL
)
303 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
306 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
310 /* Check if we were called from user-mode */
311 if ((PreviousCount
) && (PreviousMode
!= KernelMode
))
313 /* Entry SEH Block */
316 /* Make sure the state pointer is valid */
317 ProbeForWriteLong(PreviousCount
);
319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
321 /* Return the exception code */
322 _SEH2_YIELD(return _SEH2_GetExceptionCode());
327 /* Open the Object */
328 Status
= ObReferenceObjectByHandle(MutantHandle
,
329 0, /* No access rights required */
335 /* Check for Success and release if such */
336 if (NT_SUCCESS(Status
))
339 * Release the mutant. doing so might raise an exception which we're
344 /* Release the mutant */
345 LONG Prev
= KeReleaseMutant(Mutant
,
350 /* Return the previous count if requested */
351 if (PreviousCount
) *PreviousCount
= Prev
;
353 _SEH2_EXCEPT(ExSystemExceptionFilter())
355 /* Get the exception code */
356 Status
= _SEH2_GetExceptionCode();
361 ObDereferenceObject(Mutant
);