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
)
53 /* Allocate the Object Type */
54 ExMutantObjectType
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(OBJECT_TYPE
), TAG('M', 't', 'n', 't'));
56 /* Create the Object Type */
57 RtlInitUnicodeString(&ExMutantObjectType
->TypeName
, L
"Mutant");
58 ExMutantObjectType
->Tag
= TAG('M', 't', 'n', 't');
59 ExMutantObjectType
->PeakObjects
= 0;
60 ExMutantObjectType
->PeakHandles
= 0;
61 ExMutantObjectType
->TotalObjects
= 0;
62 ExMutantObjectType
->TotalHandles
= 0;
63 ExMutantObjectType
->PagedPoolCharge
= 0;
64 ExMutantObjectType
->NonpagedPoolCharge
= sizeof(KMUTANT
);
65 ExMutantObjectType
->Mapping
= &ExpMutantMapping
;
66 ExMutantObjectType
->Dump
= NULL
;
67 ExMutantObjectType
->Open
= NULL
;
68 ExMutantObjectType
->Close
= NULL
;
69 ExMutantObjectType
->Delete
= ExpDeleteMutant
;
70 ExMutantObjectType
->Parse
= NULL
;
71 ExMutantObjectType
->Security
= NULL
;
72 ExMutantObjectType
->QueryName
= NULL
;
73 ExMutantObjectType
->OkayToClose
= NULL
;
74 ExMutantObjectType
->Create
= NULL
;
75 ExMutantObjectType
->DuplicationNotify
= NULL
;
76 ObpCreateTypeObject(ExMutantObjectType
);
84 NtCreateMutant(OUT PHANDLE MutantHandle
,
85 IN ACCESS_MASK DesiredAccess
,
86 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
87 IN BOOLEAN InitialOwner
)
89 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
92 NTSTATUS Status
= STATUS_SUCCESS
;
95 DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
97 /* Check Output Safety */
98 if(PreviousMode
== UserMode
) {
102 ProbeForWrite(MutantHandle
,
107 Status
= _SEH_GetExceptionCode();
111 if(!NT_SUCCESS(Status
)) return Status
;
114 /* Create the Mutant Object*/
115 Status
= ObCreateObject(PreviousMode
,
125 /* Check for success */
126 if(NT_SUCCESS(Status
)) {
128 /* Initalize the Kernel Mutant */
129 DPRINT("Initializing the Mutant\n");
130 KeInitializeMutant(Mutant
, InitialOwner
);
132 /* Insert the Object */
133 Status
= ObInsertObject((PVOID
)Mutant
,
139 ObDereferenceObject(Mutant
);
141 /* Check for success and return handle */
142 if(NT_SUCCESS(Status
)) {
146 *MutantHandle
= hMutant
;
150 Status
= _SEH_GetExceptionCode();
165 NtOpenMutant(OUT PHANDLE MutantHandle
,
166 IN ACCESS_MASK DesiredAccess
,
167 IN POBJECT_ATTRIBUTES ObjectAttributes
)
170 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
171 NTSTATUS Status
= STATUS_SUCCESS
;
174 DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
176 /* Check Output Safety */
177 if(PreviousMode
== UserMode
) {
181 ProbeForWrite(MutantHandle
,
186 Status
= _SEH_GetExceptionCode();
190 if(!NT_SUCCESS(Status
)) return Status
;
193 /* Open the Object */
194 Status
= ObOpenObjectByName(ObjectAttributes
,
202 /* Check for success and return handle */
203 if(NT_SUCCESS(Status
)) {
207 *MutantHandle
= hMutant
;
211 Status
= _SEH_GetExceptionCode();
225 NtQueryMutant(IN HANDLE MutantHandle
,
226 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
227 OUT PVOID MutantInformation
,
228 IN ULONG MutantInformationLength
,
229 OUT PULONG ResultLength OPTIONAL
)
232 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
233 NTSTATUS Status
= STATUS_SUCCESS
;
234 PMUTANT_BASIC_INFORMATION BasicInfo
= (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
238 /* Check buffers and parameters */
239 DefaultQueryInfoBufferCheck(MutantInformationClass
,
242 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
)) {
264 /* Fill out the Basic Information Requested */
265 DPRINT("Returning Mutant Information\n");
266 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
267 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
== KeGetCurrentThread());
268 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
270 /* Return the Result Length if requested */
271 if(ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
275 Status
= _SEH_GetExceptionCode();
279 /* Release the Object */
280 ObDereferenceObject(Mutant
);
293 NtReleaseMutant(IN HANDLE MutantHandle
,
294 IN PLONG PreviousCount OPTIONAL
)
297 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
298 NTSTATUS Status
= STATUS_SUCCESS
;
301 DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
305 /* Check Output Safety */
306 if(PreviousMode
== UserMode
&& PreviousCount
) {
310 ProbeForWrite(PreviousCount
,
315 Status
= _SEH_GetExceptionCode();
319 if(!NT_SUCCESS(Status
)) return Status
;
322 /* Open the Object */
323 Status
= ObReferenceObjectByHandle(MutantHandle
,
330 /* Check for Success and release if such */
331 if(NT_SUCCESS(Status
)) {
335 /* Save the Old State */
336 DPRINT("Releasing Mutant\n");
337 Prev
= KeReleaseMutant(Mutant
, MUTANT_INCREMENT
, FALSE
, FALSE
);
338 ObDereferenceObject(Mutant
);
345 *PreviousCount
= Prev
;
349 Status
= _SEH_GetExceptionCode();