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
7 * PROGRAMMERS: Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
8 * add more debug output.
9 * David Welch (welch@cwcom.net)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 #if defined (ALLOC_PRAGMA)
19 #pragma alloc_text(INIT, ExpInitializeMutantImplementation)
22 #ifndef MUTANT_INCREMENT
23 #define MUTANT_INCREMENT 1
26 POBJECT_TYPE ExMutantObjectType
= NULL
;
28 static GENERIC_MAPPING ExpMutantMapping
= {
29 STANDARD_RIGHTS_READ
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
30 STANDARD_RIGHTS_WRITE
| SYNCHRONIZE
,
31 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
34 static const INFORMATION_CLASS_INFO ExMutantInfoClass
[] = {
36 /* MutantBasicInformation */
37 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
40 /* FUNCTIONS *****************************************************************/
44 ExpDeleteMutant(PVOID ObjectBody
)
47 DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody
);
49 /* Make sure to release the Mutant */
50 KeReleaseMutant((PKMUTANT
)ObjectBody
,
59 ExpInitializeMutantImplementation(VOID
)
61 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
64 DPRINT("Creating Mutant Object Type\n");
66 /* Create the Event Pair Object Type */
67 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
68 RtlInitUnicodeString(&Name
, L
"Mutant");
69 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
70 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KMUTANT
);
71 ObjectTypeInitializer
.GenericMapping
= ExpMutantMapping
;
72 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
73 ObjectTypeInitializer
.DeleteProcedure
= ExpDeleteMutant
;
74 ObjectTypeInitializer
.ValidAccessMask
= MUTANT_ALL_ACCESS
;
75 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &ExMutantObjectType
);
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();
91 NTSTATUS Status
= STATUS_SUCCESS
;
94 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
96 /* Check Output Safety */
97 if(PreviousMode
!= KernelMode
) {
101 ProbeForWriteHandle(MutantHandle
);
102 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
104 Status
= _SEH_GetExceptionCode();
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
,
136 ObDereferenceObject(Mutant
);
138 /* Check for success and return handle */
139 if(NT_SUCCESS(Status
)) {
143 *MutantHandle
= hMutant
;
145 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
147 Status
= _SEH_GetExceptionCode();
162 NtOpenMutant(OUT PHANDLE MutantHandle
,
163 IN ACCESS_MASK DesiredAccess
,
164 IN POBJECT_ATTRIBUTES ObjectAttributes
)
167 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
168 NTSTATUS Status
= STATUS_SUCCESS
;
171 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
173 /* Check Output Safety */
174 if(PreviousMode
!= KernelMode
) {
178 ProbeForWriteHandle(MutantHandle
);
179 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
181 Status
= _SEH_GetExceptionCode();
185 if(!NT_SUCCESS(Status
)) return Status
;
188 /* Open the Object */
189 Status
= ObOpenObjectByName(ObjectAttributes
,
197 /* Check for success and return handle */
198 if(NT_SUCCESS(Status
)) {
202 *MutantHandle
= hMutant
;
204 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
206 Status
= _SEH_GetExceptionCode();
220 NtQueryMutant(IN HANDLE MutantHandle
,
221 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
222 OUT PVOID MutantInformation
,
223 IN ULONG MutantInformationLength
,
224 OUT PULONG ResultLength OPTIONAL
)
227 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
228 NTSTATUS Status
= STATUS_SUCCESS
;
229 PMUTANT_BASIC_INFORMATION BasicInfo
= (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
233 /* Check buffers and parameters */
234 Status
= DefaultQueryInfoBufferCheck(MutantInformationClass
,
236 sizeof(ExMutantInfoClass
) / sizeof(ExMutantInfoClass
[0]),
238 MutantInformationLength
,
241 if(!NT_SUCCESS(Status
)) {
243 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status
);
247 /* Open the Object */
248 Status
= ObReferenceObjectByHandle(MutantHandle
,
254 /* Check for Status */
255 if(NT_SUCCESS(Status
)) {
259 /* Fill out the Basic Information Requested */
260 DPRINT("Returning Mutant Information\n");
261 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
262 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
== KeGetCurrentThread());
263 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
265 /* Return the Result Length if requested */
266 if(ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
268 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
270 Status
= _SEH_GetExceptionCode();
274 /* Release the Object */
275 ObDereferenceObject(Mutant
);
288 NtReleaseMutant(IN HANDLE MutantHandle
,
289 IN PLONG PreviousCount OPTIONAL
)
292 KPROCESSOR_MODE PreviousMode
;
293 NTSTATUS Status
= STATUS_SUCCESS
;
297 PreviousMode
= ExGetPreviousMode();
299 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
303 /* Check Output Safety */
304 if(PreviousMode
!= KernelMode
&& PreviousCount
) {
308 ProbeForWriteLong(PreviousCount
);
309 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
311 Status
= _SEH_GetExceptionCode();
315 if(!NT_SUCCESS(Status
)) return Status
;
318 /* Open the Object */
319 Status
= ObReferenceObjectByHandle(MutantHandle
,
326 /* Check for Success and release if such */
327 if(NT_SUCCESS(Status
)) {
329 /* release the mutant. doing so might raise an exception which we're
330 required to catch! */
333 LONG Prev
= KeReleaseMutant(Mutant
, MUTANT_INCREMENT
, FALSE
, FALSE
);
337 *PreviousCount
= Prev
;
340 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
342 Status
= _SEH_GetExceptionCode();
346 ObDereferenceObject(Mutant
);