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
8 * Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
9 * add more debug output.
10 * David Welch (welch@cwcom.net)
13 /* INCLUDES *****************************************************************/
17 #include <internal/debug.h>
19 POBJECT_TYPE ExMutantObjectType
= NULL
;
21 static GENERIC_MAPPING ExpMutantMapping
= {
22 STANDARD_RIGHTS_READ
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
23 STANDARD_RIGHTS_WRITE
| SYNCHRONIZE
,
24 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| MUTANT_QUERY_STATE
,
27 static const INFORMATION_CLASS_INFO ExMutantInfoClass
[] = {
29 /* MutantBasicInformation */
30 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
33 /* FUNCTIONS *****************************************************************/
37 ExpDeleteMutant(PVOID ObjectBody
)
40 DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody
);
42 /* Make sure to release the Mutant */
43 KeReleaseMutant((PKMUTANT
)ObjectBody
,
51 ExpInitializeMutantImplementation(VOID
)
54 /* Allocate the Object Type */
55 ExMutantObjectType
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(OBJECT_TYPE
), TAG('M', 't', 'n', 't'));
57 /* Create the Object Type */
58 RtlpCreateUnicodeString(&ExMutantObjectType
->TypeName
, L
"Mutant", NonPagedPool
);
59 ExMutantObjectType
->Tag
= TAG('M', 't', 'n', 't');
60 ExMutantObjectType
->PeakObjects
= 0;
61 ExMutantObjectType
->PeakHandles
= 0;
62 ExMutantObjectType
->TotalObjects
= 0;
63 ExMutantObjectType
->TotalHandles
= 0;
64 ExMutantObjectType
->PagedPoolCharge
= 0;
65 ExMutantObjectType
->NonpagedPoolCharge
= sizeof(KMUTANT
);
66 ExMutantObjectType
->Mapping
= &ExpMutantMapping
;
67 ExMutantObjectType
->Dump
= NULL
;
68 ExMutantObjectType
->Open
= NULL
;
69 ExMutantObjectType
->Close
= NULL
;
70 ExMutantObjectType
->Delete
= ExpDeleteMutant
;
71 ExMutantObjectType
->Parse
= NULL
;
72 ExMutantObjectType
->Security
= NULL
;
73 ExMutantObjectType
->QueryName
= NULL
;
74 ExMutantObjectType
->OkayToClose
= NULL
;
75 ExMutantObjectType
->Create
= NULL
;
76 ExMutantObjectType
->DuplicationNotify
= NULL
;
77 ObpCreateTypeObject(ExMutantObjectType
);
85 NtCreateMutant(OUT PHANDLE MutantHandle
,
86 IN ACCESS_MASK DesiredAccess
,
87 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
88 IN BOOLEAN InitialOwner
)
90 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
93 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();
166 NtOpenMutant(OUT PHANDLE MutantHandle
,
167 IN ACCESS_MASK DesiredAccess
,
168 IN POBJECT_ATTRIBUTES ObjectAttributes
)
171 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
172 NTSTATUS Status
= STATUS_SUCCESS
;
176 DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle
, DesiredAccess
, ObjectAttributes
);
178 /* Check Output Safety */
179 if(PreviousMode
== UserMode
) {
183 ProbeForWrite(MutantHandle
,
188 Status
= _SEH_GetExceptionCode();
192 if(!NT_SUCCESS(Status
)) return Status
;
195 /* Open the Object */
196 Status
= ObOpenObjectByName(ObjectAttributes
,
204 /* Check for success and return handle */
205 if(NT_SUCCESS(Status
)) {
209 *MutantHandle
= hMutant
;
213 Status
= _SEH_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
= (PMUTANT_BASIC_INFORMATION
)MutantInformation
;
238 /* Check buffers and parameters */
239 DefaultQueryInfoBufferCheck(MutantInformationClass
,
242 MutantInformationLength
,
246 if(!NT_SUCCESS(Status
)) {
248 DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status
);
254 /* Open the Object */
255 Status
= ObReferenceObjectByHandle(MutantHandle
,
261 /* Check for Status */
262 if(NT_SUCCESS(Status
)) {
266 /* Fill out the Basic Information Requested */
267 DPRINT1("Returning Mutant Information\n");
268 BasicInfo
->CurrentCount
= KeReadStateMutant(Mutant
);
269 BasicInfo
->OwnedByCaller
= (Mutant
->OwnerThread
== KeGetCurrentThread());
270 BasicInfo
->AbandonedState
= Mutant
->Abandoned
;
272 /* Return the Result Length if requested */
273 if(ResultLength
) *ResultLength
= sizeof(MUTANT_BASIC_INFORMATION
);
277 Status
= _SEH_GetExceptionCode();
281 /* Release the Object */
282 ObDereferenceObject(Mutant
);
295 NtReleaseMutant(IN HANDLE MutantHandle
,
296 IN PLONG PreviousCount OPTIONAL
)
299 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
300 NTSTATUS Status
= STATUS_SUCCESS
;
304 DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
308 /* Check Output Safety */
309 if(PreviousMode
== UserMode
&& PreviousCount
) {
313 ProbeForWrite(PreviousCount
,
318 Status
= _SEH_GetExceptionCode();
322 if(!NT_SUCCESS(Status
)) return Status
;
325 /* Open the Object */
326 Status
= ObReferenceObjectByHandle(MutantHandle
,
333 /* Check for Success and release if such */
334 if(NT_SUCCESS(Status
)) {
336 /* Save the Old State */
337 DPRINT1("Releasing Mutant\n");
338 LONG Prev
= KeReleaseMutant(Mutant
, MUTANT_INCREMENT
, FALSE
, FALSE
);
339 ObDereferenceObject(Mutant
);
346 *PreviousCount
= Prev
;
350 Status
= _SEH_GetExceptionCode();