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 POBJECT_TYPE ExMutantObjectType
= NULL
;
20 static GENERIC_MAPPING ExpMutantMapping
= {
21 STANDARD_RIGHTS_READ
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
22 STANDARD_RIGHTS_WRITE
| SYNCHRONIZE
,
23 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
26 static const INFORMATION_CLASS_INFO ExMutantInfoClass
[] = {
28 /* MutantBasicInformation */
29 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
32 /* FUNCTIONS *****************************************************************/
36 ExpDeleteMutant(PVOID ObjectBody
)
39 DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody
);
41 /* Make sure to release the Mutant */
42 KeReleaseMutant((PKMUTANT
)ObjectBody
,
50 ExpInitializeMutantImplementation(VOID
)
52 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
55 DPRINT("Creating Mutant Object Type\n");
57 /* Create the Event Pair Object Type */
58 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
59 RtlInitUnicodeString(&Name
, L
"Mutant");
60 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
61 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KMUTANT
);
62 ObjectTypeInitializer
.GenericMapping
= ExpMutantMapping
;
63 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
64 ObjectTypeInitializer
.DeleteProcedure
= ExpDeleteMutant
;
65 ObjectTypeInitializer
.ValidAccessMask
= MUTANT_ALL_ACCESS
;
66 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
67 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &ExMutantObjectType
);
75 NtCreateMutant(OUT PHANDLE MutantHandle
,
76 IN ACCESS_MASK DesiredAccess
,
77 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
78 IN BOOLEAN InitialOwner
)
80 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
83 NTSTATUS Status
= STATUS_SUCCESS
;
86 DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
88 /* Check Output Safety */
89 if(PreviousMode
== UserMode
) {
93 ProbeForWrite(MutantHandle
,
96 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
98 Status
= _SEH_GetExceptionCode();
102 if(!NT_SUCCESS(Status
)) return Status
;
105 /* Create the Mutant Object*/
106 Status
= ObCreateObject(PreviousMode
,
116 /* Check for success */
117 if(NT_SUCCESS(Status
)) {
119 /* Initalize the Kernel Mutant */
120 DPRINT("Initializing the Mutant\n");
121 KeInitializeMutant(Mutant
, InitialOwner
);
123 /* Insert the Object */
124 Status
= ObInsertObject((PVOID
)Mutant
,
130 ObDereferenceObject(Mutant
);
132 /* Check for success and return handle */
133 if(NT_SUCCESS(Status
)) {
137 *MutantHandle
= hMutant
;
139 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
141 Status
= _SEH_GetExceptionCode();
156 NtOpenMutant(OUT PHANDLE MutantHandle
,
157 IN ACCESS_MASK DesiredAccess
,
158 IN POBJECT_ATTRIBUTES ObjectAttributes
)
161 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
162 NTSTATUS Status
= STATUS_SUCCESS
;
165 DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
167 /* Check Output Safety */
168 if(PreviousMode
== UserMode
) {
172 ProbeForWrite(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 0%x PreviousCount 0%x)\n",
299 /* Check Output Safety */
300 if(PreviousMode
!= KernelMode
&& PreviousCount
) {
304 ProbeForWrite(PreviousCount
,
307 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
309 Status
= _SEH_GetExceptionCode();
313 if(!NT_SUCCESS(Status
)) return Status
;
316 /* Open the Object */
317 Status
= ObReferenceObjectByHandle(MutantHandle
,
324 /* Check for Success and release if such */
325 if(NT_SUCCESS(Status
)) {
329 /* release the mutant. doing so might raise an exception which we're
330 required to catch! */
333 Prev
= KeReleaseMutant(Mutant
, MUTANT_INCREMENT
, FALSE
, FALSE
);
335 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
337 Status
= _SEH_GetExceptionCode();
341 ObDereferenceObject(Mutant
);
343 if(NT_SUCCESS(Status
)) {
350 *PreviousCount
= Prev
;
352 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
) {
354 Status
= _SEH_GetExceptionCode();