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
,
246 if(!NT_SUCCESS(Status
))
248 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status
);
252 /* Open the Object */
253 Status
= ObReferenceObjectByHandle(MutantHandle
,
259 /* Check for Status */
260 if (NT_SUCCESS(Status
))
262 /* Enter SEH Block for return */
265 /* Fill out the Basic Information Requested */
266 DPRINT("Returning Mutant Information\n");
267 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
268 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
==
269 KeGetCurrentThread());
270 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
272 /* Return the Result Length if requested */
273 if (ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
275 _SEH2_EXCEPT(ExSystemExceptionFilter())
277 Status
= _SEH2_GetExceptionCode();
281 /* Release the Object */
282 ObDereferenceObject(Mutant
);
294 NtReleaseMutant(IN HANDLE MutantHandle
,
295 IN PLONG PreviousCount OPTIONAL
)
298 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
301 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
305 /* Check if we were called from user-mode */
306 if ((PreviousCount
) && (PreviousMode
!= KernelMode
))
308 /* Entry SEH Block */
311 /* Make sure the state pointer is valid */
312 ProbeForWriteLong(PreviousCount
);
314 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
316 /* Return the exception code */
317 _SEH2_YIELD(return _SEH2_GetExceptionCode());
322 /* Open the Object */
323 Status
= ObReferenceObjectByHandle(MutantHandle
,
330 /* Check for Success and release if such */
331 if (NT_SUCCESS(Status
))
334 * Release the mutant. doing so might raise an exception which we're
339 /* Release the mutant */
340 LONG Prev
= KeReleaseMutant(Mutant
,
345 /* Return the previous count if requested */
346 if (PreviousCount
) *PreviousCount
= Prev
;
348 _SEH2_EXCEPT(ExSystemExceptionFilter())
350 /* Get the exception code */
351 Status
= _SEH2_GetExceptionCode();
356 ObDereferenceObject(Mutant
);