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();
87 NTSTATUS Status
= STATUS_SUCCESS
;
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(ExSystemExceptionFilter())
103 Status
= _SEH2_GetExceptionCode();
107 /* Bail out if pointer was invalid */
108 if(!NT_SUCCESS(Status
)) return Status
;
111 /* Create the Mutant Object*/
112 Status
= ObCreateObject(PreviousMode
,
122 /* Check for success */
123 if(NT_SUCCESS(Status
))
125 /* Initalize the Kernel Mutant */
126 DPRINT("Initializing the Mutant\n");
127 KeInitializeMutant(Mutant
, InitialOwner
);
129 /* Insert the Object */
130 Status
= ObInsertObject((PVOID
)Mutant
,
137 /* Check for success */
138 if(NT_SUCCESS(Status
))
140 /* Enter SEH for return */
143 /* Return the handle to the caller */
144 *MutantHandle
= hMutant
;
146 _SEH2_EXCEPT(ExSystemExceptionFilter())
148 Status
= _SEH2_GetExceptionCode();
163 NtOpenMutant(OUT PHANDLE MutantHandle
,
164 IN ACCESS_MASK DesiredAccess
,
165 IN POBJECT_ATTRIBUTES ObjectAttributes
)
168 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
169 NTSTATUS Status
= STATUS_SUCCESS
;
171 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
172 MutantHandle
, DesiredAccess
, ObjectAttributes
);
174 /* Check if we were called from user-mode */
175 if(PreviousMode
!= KernelMode
)
177 /* Enter SEH Block */
180 /* Check handle pointer */
181 ProbeForWriteHandle(MutantHandle
);
183 _SEH2_EXCEPT(ExSystemExceptionFilter())
185 Status
= _SEH2_GetExceptionCode();
189 /* Bail out if pointer was invalid */
190 if(!NT_SUCCESS(Status
)) return Status
;
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();
235 NTSTATUS Status
= STATUS_SUCCESS
;
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();
303 NTSTATUS Status
= STATUS_SUCCESS
;
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(ExSystemExceptionFilter())
320 Status
= _SEH2_GetExceptionCode();
324 /* Bail out if pointer was invalid */
325 if(!NT_SUCCESS(Status
)) return Status
;
328 /* Open the Object */
329 Status
= ObReferenceObjectByHandle(MutantHandle
,
336 /* Check for Success and release if such */
337 if(NT_SUCCESS(Status
))
340 * Release the mutant. doing so might raise an exception which we're
345 /* Release the mutant */
346 LONG Prev
= KeReleaseMutant(Mutant
,
351 /* Return the previous count if requested */
352 if(PreviousCount
) *PreviousCount
= Prev
;
354 _SEH2_EXCEPT(ExSystemExceptionFilter())
356 Status
= _SEH2_GetExceptionCode();
361 ObDereferenceObject(Mutant
);