ReactOS  0.4.15-dev-1386-g5cb9f87
mutant.c
Go to the documentation of this file.
1 /*
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
6  * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7  * Thomas Weidenmueller
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* DATA **********************************************************************/
17 
19 
21 {
26 };
27 
28 static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
29 {
30  /* MutantBasicInformation */
31  ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
32 };
33 
34 /* FUNCTIONS *****************************************************************/
35 
36 VOID
37 NTAPI
39 {
40  DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
41 
42  /* Make sure to release the Mutant */
43  KeReleaseMutant((PKMUTANT)ObjectBody,
45  TRUE,
46  FALSE);
47 }
48 
49 CODE_SEG("INIT")
50 BOOLEAN
51 NTAPI
53 {
54  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
57  DPRINT("Creating Mutant Object Type\n");
58 
59  /* Create the Event Pair Object Type */
60  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
61  RtlInitUnicodeString(&Name, L"Mutant");
62  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
63  ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT);
64  ObjectTypeInitializer.GenericMapping = ExpMutantMapping;
65  ObjectTypeInitializer.PoolType = NonPagedPool;
66  ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant;
67  ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS;
68  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
69  Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExMutantObjectType);
70  if (!NT_SUCCESS(Status)) return FALSE;
71  return TRUE;
72 }
73 
74 /*
75  * @implemented
76  */
78 NTAPI
79 NtCreateMutant(OUT PHANDLE MutantHandle,
83 {
85  HANDLE hMutant;
86  PKMUTANT Mutant;
88  PAGED_CODE();
89  DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
90  MutantHandle, DesiredAccess, ObjectAttributes);
91 
92  /* Check if we were called from user-mode */
93  if (PreviousMode != KernelMode)
94  {
95  /* Enter SEH Block */
96  _SEH2_TRY
97  {
98  /* Check handle pointer */
99  ProbeForWriteHandle(MutantHandle);
100  }
102  {
103  /* Return the exception code */
105  }
106  _SEH2_END;
107  }
108 
109  /* Create the Mutant Object*/
113  PreviousMode,
114  NULL,
115  sizeof(KMUTANT),
116  0,
117  0,
118  (PVOID*)&Mutant);
119 
120  /* Check for success */
121  if(NT_SUCCESS(Status))
122  {
123  /* Initialize the Kernel Mutant */
124  DPRINT("Initializing the Mutant\n");
126 
127  /* Insert the Object */
128  Status = ObInsertObject((PVOID)Mutant,
129  NULL,
131  0,
132  NULL,
133  &hMutant);
134 
135  /* Check for success */
136  if (NT_SUCCESS(Status))
137  {
138  /* Enter SEH for return */
139  _SEH2_TRY
140  {
141  /* Return the handle to the caller */
142  *MutantHandle = hMutant;
143  }
145  {
146  /* Get the exception code */
148  }
149  _SEH2_END;
150  }
151  }
152 
153  /* Return Status */
154  return Status;
155 }
156 
157 /*
158  * @implemented
159  */
160 NTSTATUS
161 NTAPI
162 NtOpenMutant(OUT PHANDLE MutantHandle,
165 {
166  HANDLE hMutant;
169  PAGED_CODE();
170  DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
171  MutantHandle, DesiredAccess, ObjectAttributes);
172 
173  /* Check if we were called from user-mode */
174  if (PreviousMode != KernelMode)
175  {
176  /* Enter SEH Block */
177  _SEH2_TRY
178  {
179  /* Check handle pointer */
180  ProbeForWriteHandle(MutantHandle);
181  }
183  {
184  /* Return the exception code */
186  }
187  _SEH2_END;
188  }
189 
190  /* Open the Object */
193  PreviousMode,
194  NULL,
196  NULL,
197  &hMutant);
198 
199  /* Check for success */
200  if(NT_SUCCESS(Status))
201  {
202  /* Enter SEH for return */
203  _SEH2_TRY
204  {
205  /* Return the handle to the caller */
206  *MutantHandle = hMutant;
207  }
209  {
211  }
212  _SEH2_END;
213  }
214 
215  /* Return Status */
216  return Status;
217 }
218 
219 /*
220  * @implemented
221  */
222 NTSTATUS
223 NTAPI
224 NtQueryMutant(IN HANDLE MutantHandle,
225  IN MUTANT_INFORMATION_CLASS MutantInformationClass,
226  OUT PVOID MutantInformation,
227  IN ULONG MutantInformationLength,
229 {
230  PKMUTANT Mutant;
233  PMUTANT_BASIC_INFORMATION BasicInfo =
234  (PMUTANT_BASIC_INFORMATION)MutantInformation;
235  PAGED_CODE();
236 
237  /* Check buffers and parameters */
238  Status = DefaultQueryInfoBufferCheck(MutantInformationClass,
240  sizeof(ExMutantInfoClass) /
241  sizeof(ExMutantInfoClass[0]),
242  MutantInformation,
243  MutantInformationLength,
244  ResultLength,
245  NULL,
246  PreviousMode);
247  if(!NT_SUCCESS(Status))
248  {
249  DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
250  return Status;
251  }
252 
253  /* Open the Object */
254  Status = ObReferenceObjectByHandle(MutantHandle,
257  PreviousMode,
258  (PVOID*)&Mutant,
259  NULL);
260  /* Check for Status */
261  if (NT_SUCCESS(Status))
262  {
263  /* Enter SEH Block for return */
264  _SEH2_TRY
265  {
266  /* Fill out the Basic Information Requested */
267  DPRINT("Returning Mutant Information\n");
268  BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
269  BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
271  BasicInfo->AbandonedState = Mutant->Abandoned;
272 
273  /* Return the Result Length if requested */
275  }
277  {
279  }
280  _SEH2_END;
281 
282  /* Release the Object */
283  ObDereferenceObject(Mutant);
284  }
285 
286  /* Return Status */
287  return Status;
288 }
289 
290 /*
291  * @implemented
292  */
293 NTSTATUS
294 NTAPI
295 NtReleaseMutant(IN HANDLE MutantHandle,
296  IN PLONG PreviousCount OPTIONAL)
297 {
298  PKMUTANT Mutant;
301  PAGED_CODE();
302  DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
303  MutantHandle,
304  PreviousCount);
305 
306  /* Check if we were called from user-mode */
307  if ((PreviousCount) && (PreviousMode != KernelMode))
308  {
309  /* Entry SEH Block */
310  _SEH2_TRY
311  {
312  /* Make sure the state pointer is valid */
313  ProbeForWriteLong(PreviousCount);
314  }
316  {
317  /* Return the exception code */
319  }
320  _SEH2_END;
321  }
322 
323  /* Open the Object */
324  Status = ObReferenceObjectByHandle(MutantHandle,
325  0, /* No access rights required */
327  PreviousMode,
328  (PVOID*)&Mutant,
329  NULL);
330 
331  /* Check for Success and release if such */
332  if (NT_SUCCESS(Status))
333  {
334  /*
335  * Release the mutant. doing so might raise an exception which we're
336  * required to catch!
337  */
338  _SEH2_TRY
339  {
340  /* Release the mutant */
341  LONG Prev = KeReleaseMutant(Mutant,
343  FALSE,
344  FALSE);
345 
346  /* Return the previous count if requested */
347  if (PreviousCount) *PreviousCount = Prev;
348  }
350  {
351  /* Get the exception code */
353  }
354  _SEH2_END;
355 
356  /* Dereference it */
357  ObDereferenceObject(Mutant);
358  }
359 
360  /* Return Status */
361  return Status;
362 }
363 
364 /* EOF */
#define OBJ_OPENLINK
Definition: winternl.h:230
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2529
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
struct _KMUTANT KMUTANT
#define IN
Definition: typedefs.h:39
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1048
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
NTSTATUS NTAPI NtQueryMutant(IN HANDLE MutantHandle, IN MUTANT_INFORMATION_CLASS MutantInformationClass, OUT PVOID MutantInformation, IN ULONG MutantInformationLength, OUT PULONG ResultLength OPTIONAL)
Definition: mutant.c:224
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define ProbeForWriteLong(Ptr)
Definition: probe.h:37
#define TRUE
Definition: types.h:120
VOID NTAPI KeInitializeMutant(IN PKMUTANT Mutant, IN BOOLEAN InitialOwner)
Definition: mutex.c:22
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI ExpInitializeMutantImplementation(VOID)
Definition: mutant.c:52
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
struct _MUTANT_BASIC_INFORMATION MUTANT_BASIC_INFORMATION
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
#define MUTANT_ALL_ACCESS
Definition: extypes.h:110
VOID NTAPI ExpDeleteMutant(PVOID ObjectBody)
Definition: mutant.c:38
struct NameRec_ * Name
Definition: cdprocs.h:459
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
POBJECT_TYPE ExMutantObjectType
Definition: mutant.c:18
void DPRINT(...)
Definition: polytest.cpp:61
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:952
Status
Definition: gdiplustypes.h:24
enum _MUTANT_INFORMATION_CLASS MUTANT_INFORMATION_CLASS
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define MUTANT_INCREMENT
Definition: extypes.h:84
NTSTATUS NTAPI NtCreateMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner)
Definition: mutant.c:79
LONG NTAPI KeReleaseMutant(IN PKMUTANT Mutant, IN KPRIORITY Increment, IN BOOLEAN Abandon, IN BOOLEAN Wait)
Definition: mutex.c:98
GENERIC_MAPPING ExpMutantMapping
Definition: mutant.c:20
static const INFORMATION_CLASS_INFO ExMutantInfoClass[]
Definition: mutant.c:28
static const WCHAR L[]
Definition: oid.c:1250
struct _MUTANT_BASIC_INFORMATION * PMUTANT_BASIC_INFORMATION
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
static __inline NTSTATUS DefaultQueryInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength, PULONG_PTR ReturnLengthPtr, KPROCESSOR_MODE PreviousMode)
Definition: probe.h:59
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define SYNCHRONIZE
Definition: nt_native.h:61
LONG NTAPI KeReadStateMutant(IN PKMUTANT Mutant)
Definition: mutex.c:87
_SEH2_END
Definition: create.c:4400
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2932
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:351
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
NTSTATUS NTAPI NtOpenMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: mutant.c:162
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define KeGetCurrentThread
Definition: hal.h:44
#define MUTANT_QUERY_STATE
Definition: extypes.h:109
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
signed int * PLONG
Definition: retypes.h:5
NTSTATUS NTAPI NtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL)
Definition: mutant.c:295
_In_ BOOLEAN InitialOwner
Definition: kefuncs.h:577
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define PAGED_CODE()
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68