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 #ifndef MUTANT_INCREMENT
19 #define MUTANT_INCREMENT 1
22 POBJECT_TYPE ExMutantObjectType
= NULL
;
24 static GENERIC_MAPPING ExpMutantMapping
= {
25 STANDARD_RIGHTS_READ
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
26 STANDARD_RIGHTS_WRITE
| SYNCHRONIZE
,
27 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
30 static const INFORMATION_CLASS_INFO ExMutantInfoClass
[] = {
32 /* MutantBasicInformation */
33 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
36 /* FUNCTIONS *****************************************************************/
40 ExpDeleteMutant(PVOID ObjectBody
)
43 DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody
);
45 /* Make sure to release the Mutant */
46 KeReleaseMutant((PKMUTANT
)ObjectBody
,
55 ExpInitializeMutantImplementation(VOID
)
57 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 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &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
;
90 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
92 /* Check Output Safety */
93 if(PreviousMode
!= KernelMode
) {
97 ProbeForWriteHandle(MutantHandle
);
98 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
100 Status
= _SEH_GetExceptionCode();
104 if(!NT_SUCCESS(Status
)) return Status
;
107 /* Create the Mutant Object*/
108 Status
= ObCreateObject(PreviousMode
,
118 /* Check for success */
119 if(NT_SUCCESS(Status
)) {
121 /* Initalize the Kernel Mutant */
122 DPRINT("Initializing the Mutant\n");
123 KeInitializeMutant(Mutant
, InitialOwner
);
125 /* Insert the Object */
126 Status
= ObInsertObject((PVOID
)Mutant
,
132 ObDereferenceObject(Mutant
);
134 /* Check for success and return handle */
135 if(NT_SUCCESS(Status
)) {
139 *MutantHandle
= hMutant
;
141 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
143 Status
= _SEH_GetExceptionCode();
158 NtOpenMutant(OUT PHANDLE MutantHandle
,
159 IN ACCESS_MASK DesiredAccess
,
160 IN POBJECT_ATTRIBUTES ObjectAttributes
)
163 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
164 NTSTATUS Status
= STATUS_SUCCESS
;
167 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
169 /* Check Output Safety */
170 if(PreviousMode
!= KernelMode
) {
174 ProbeForWriteHandle(MutantHandle
);
175 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
177 Status
= _SEH_GetExceptionCode();
181 if(!NT_SUCCESS(Status
)) return Status
;
184 /* Open the Object */
185 Status
= ObOpenObjectByName(ObjectAttributes
,
193 /* Check for success and return handle */
194 if(NT_SUCCESS(Status
)) {
198 *MutantHandle
= hMutant
;
200 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
202 Status
= _SEH_GetExceptionCode();
216 NtQueryMutant(IN HANDLE MutantHandle
,
217 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
218 OUT PVOID MutantInformation
,
219 IN ULONG MutantInformationLength
,
220 OUT PULONG ResultLength OPTIONAL
)
223 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
224 NTSTATUS Status
= STATUS_SUCCESS
;
225 PMUTANT_BASIC_INFORMATION BasicInfo
= (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
229 /* Check buffers and parameters */
230 DefaultQueryInfoBufferCheck(MutantInformationClass
,
233 MutantInformationLength
,
237 if(!NT_SUCCESS(Status
)) {
239 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status
);
243 /* Open the Object */
244 Status
= ObReferenceObjectByHandle(MutantHandle
,
250 /* Check for Status */
251 if(NT_SUCCESS(Status
)) {
255 /* Fill out the Basic Information Requested */
256 DPRINT("Returning Mutant Information\n");
257 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
258 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
== KeGetCurrentThread());
259 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
261 /* Return the Result Length if requested */
262 if(ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
264 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
266 Status
= _SEH_GetExceptionCode();
270 /* Release the Object */
271 ObDereferenceObject(Mutant
);
284 NtReleaseMutant(IN HANDLE MutantHandle
,
285 IN PLONG PreviousCount OPTIONAL
)
288 KPROCESSOR_MODE PreviousMode
;
289 NTSTATUS Status
= STATUS_SUCCESS
;
293 PreviousMode
= ExGetPreviousMode();
295 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
299 /* Check Output Safety */
300 if(PreviousMode
!= KernelMode
&& PreviousCount
) {
304 ProbeForWriteLong(PreviousCount
);
305 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
307 Status
= _SEH_GetExceptionCode();
311 if(!NT_SUCCESS(Status
)) return Status
;
314 /* Open the Object */
315 Status
= ObReferenceObjectByHandle(MutantHandle
,
322 /* Check for Success and release if such */
323 if(NT_SUCCESS(Status
)) {
327 /* release the mutant. doing so might raise an exception which we're
328 required to catch! */
331 Prev
= KeReleaseMutant(Mutant
, MUTANT_INCREMENT
, FALSE
, FALSE
);
333 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
335 Status
= _SEH_GetExceptionCode();
339 ObDereferenceObject(Mutant
);
341 if(NT_SUCCESS(Status
)) {
348 *PreviousCount
= Prev
;
350 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
352 Status
= _SEH_GetExceptionCode();