[NTOS:MM] Fix ViewSize parameter passed to MiInsertVadEx() from MiCreatePebOrTeb()
[reactos.git] / ntoskrnl / ex / mutant.c
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 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeMutantImplementation)
18 #endif
19
20 /* DATA **********************************************************************/
21
22 POBJECT_TYPE ExMutantObjectType = NULL;
23
24 GENERIC_MAPPING ExpMutantMapping =
25 {
26 STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE,
27 STANDARD_RIGHTS_WRITE,
28 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
29 MUTANT_ALL_ACCESS
30 };
31
32 static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
33 {
34 /* MutantBasicInformation */
35 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
36 };
37
38 /* FUNCTIONS *****************************************************************/
39
40 VOID
41 NTAPI
42 ExpDeleteMutant(PVOID ObjectBody)
43 {
44 DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
45
46 /* Make sure to release the Mutant */
47 KeReleaseMutant((PKMUTANT)ObjectBody,
48 MUTANT_INCREMENT,
49 TRUE,
50 FALSE);
51 }
52
53 BOOLEAN
54 INIT_FUNCTION
55 NTAPI
56 ExpInitializeMutantImplementation(VOID)
57 {
58 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
59 UNICODE_STRING Name;
60 NTSTATUS Status;
61 DPRINT("Creating Mutant Object Type\n");
62
63 /* Create the Event Pair Object Type */
64 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
65 RtlInitUnicodeString(&Name, L"Mutant");
66 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
67 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT);
68 ObjectTypeInitializer.GenericMapping = ExpMutantMapping;
69 ObjectTypeInitializer.PoolType = NonPagedPool;
70 ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant;
71 ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS;
72 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
73 Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExMutantObjectType);
74 if (!NT_SUCCESS(Status)) return FALSE;
75 return TRUE;
76 }
77
78 /*
79 * @implemented
80 */
81 NTSTATUS
82 NTAPI
83 NtCreateMutant(OUT PHANDLE MutantHandle,
84 IN ACCESS_MASK DesiredAccess,
85 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
86 IN BOOLEAN InitialOwner)
87 {
88 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
89 HANDLE hMutant;
90 PKMUTANT Mutant;
91 NTSTATUS Status;
92 PAGED_CODE();
93 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
94 MutantHandle, DesiredAccess, ObjectAttributes);
95
96 /* Check if we were called from user-mode */
97 if (PreviousMode != KernelMode)
98 {
99 /* Enter SEH Block */
100 _SEH2_TRY
101 {
102 /* Check handle pointer */
103 ProbeForWriteHandle(MutantHandle);
104 }
105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
106 {
107 /* Return the exception code */
108 _SEH2_YIELD(return _SEH2_GetExceptionCode());
109 }
110 _SEH2_END;
111 }
112
113 /* Create the Mutant Object*/
114 Status = ObCreateObject(PreviousMode,
115 ExMutantObjectType,
116 ObjectAttributes,
117 PreviousMode,
118 NULL,
119 sizeof(KMUTANT),
120 0,
121 0,
122 (PVOID*)&Mutant);
123
124 /* Check for success */
125 if(NT_SUCCESS(Status))
126 {
127 /* Initialize the Kernel Mutant */
128 DPRINT("Initializing the Mutant\n");
129 KeInitializeMutant(Mutant, InitialOwner);
130
131 /* Insert the Object */
132 Status = ObInsertObject((PVOID)Mutant,
133 NULL,
134 DesiredAccess,
135 0,
136 NULL,
137 &hMutant);
138
139 /* Check for success */
140 if (NT_SUCCESS(Status))
141 {
142 /* Enter SEH for return */
143 _SEH2_TRY
144 {
145 /* Return the handle to the caller */
146 *MutantHandle = hMutant;
147 }
148 _SEH2_EXCEPT(ExSystemExceptionFilter())
149 {
150 /* Get the exception code */
151 Status = _SEH2_GetExceptionCode();
152 }
153 _SEH2_END;
154 }
155 }
156
157 /* Return Status */
158 return Status;
159 }
160
161 /*
162 * @implemented
163 */
164 NTSTATUS
165 NTAPI
166 NtOpenMutant(OUT PHANDLE MutantHandle,
167 IN ACCESS_MASK DesiredAccess,
168 IN POBJECT_ATTRIBUTES ObjectAttributes)
169 {
170 HANDLE hMutant;
171 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
172 NTSTATUS Status;
173 PAGED_CODE();
174 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
175 MutantHandle, DesiredAccess, ObjectAttributes);
176
177 /* Check if we were called from user-mode */
178 if (PreviousMode != KernelMode)
179 {
180 /* Enter SEH Block */
181 _SEH2_TRY
182 {
183 /* Check handle pointer */
184 ProbeForWriteHandle(MutantHandle);
185 }
186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
187 {
188 /* Return the exception code */
189 _SEH2_YIELD(return _SEH2_GetExceptionCode());
190 }
191 _SEH2_END;
192 }
193
194 /* Open the Object */
195 Status = ObOpenObjectByName(ObjectAttributes,
196 ExMutantObjectType,
197 PreviousMode,
198 NULL,
199 DesiredAccess,
200 NULL,
201 &hMutant);
202
203 /* Check for success */
204 if(NT_SUCCESS(Status))
205 {
206 /* Enter SEH for return */
207 _SEH2_TRY
208 {
209 /* Return the handle to the caller */
210 *MutantHandle = hMutant;
211 }
212 _SEH2_EXCEPT(ExSystemExceptionFilter())
213 {
214 Status = _SEH2_GetExceptionCode();
215 }
216 _SEH2_END;
217 }
218
219 /* Return Status */
220 return Status;
221 }
222
223 /*
224 * @implemented
225 */
226 NTSTATUS
227 NTAPI
228 NtQueryMutant(IN HANDLE MutantHandle,
229 IN MUTANT_INFORMATION_CLASS MutantInformationClass,
230 OUT PVOID MutantInformation,
231 IN ULONG MutantInformationLength,
232 OUT PULONG ResultLength OPTIONAL)
233 {
234 PKMUTANT Mutant;
235 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
236 NTSTATUS Status;
237 PMUTANT_BASIC_INFORMATION BasicInfo =
238 (PMUTANT_BASIC_INFORMATION)MutantInformation;
239 PAGED_CODE();
240
241 /* Check buffers and parameters */
242 Status = DefaultQueryInfoBufferCheck(MutantInformationClass,
243 ExMutantInfoClass,
244 sizeof(ExMutantInfoClass) /
245 sizeof(ExMutantInfoClass[0]),
246 MutantInformation,
247 MutantInformationLength,
248 ResultLength,
249 NULL,
250 PreviousMode);
251 if(!NT_SUCCESS(Status))
252 {
253 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
254 return Status;
255 }
256
257 /* Open the Object */
258 Status = ObReferenceObjectByHandle(MutantHandle,
259 MUTANT_QUERY_STATE,
260 ExMutantObjectType,
261 PreviousMode,
262 (PVOID*)&Mutant,
263 NULL);
264 /* Check for Status */
265 if (NT_SUCCESS(Status))
266 {
267 /* Enter SEH Block for return */
268 _SEH2_TRY
269 {
270 /* Fill out the Basic Information Requested */
271 DPRINT("Returning Mutant Information\n");
272 BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
273 BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
274 KeGetCurrentThread());
275 BasicInfo->AbandonedState = Mutant->Abandoned;
276
277 /* Return the Result Length if requested */
278 if (ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
279 }
280 _SEH2_EXCEPT(ExSystemExceptionFilter())
281 {
282 Status = _SEH2_GetExceptionCode();
283 }
284 _SEH2_END;
285
286 /* Release the Object */
287 ObDereferenceObject(Mutant);
288 }
289
290 /* Return Status */
291 return Status;
292 }
293
294 /*
295 * @implemented
296 */
297 NTSTATUS
298 NTAPI
299 NtReleaseMutant(IN HANDLE MutantHandle,
300 IN PLONG PreviousCount OPTIONAL)
301 {
302 PKMUTANT Mutant;
303 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
304 NTSTATUS Status;
305 PAGED_CODE();
306 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
307 MutantHandle,
308 PreviousCount);
309
310 /* Check if we were called from user-mode */
311 if ((PreviousCount) && (PreviousMode != KernelMode))
312 {
313 /* Entry SEH Block */
314 _SEH2_TRY
315 {
316 /* Make sure the state pointer is valid */
317 ProbeForWriteLong(PreviousCount);
318 }
319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
320 {
321 /* Return the exception code */
322 _SEH2_YIELD(return _SEH2_GetExceptionCode());
323 }
324 _SEH2_END;
325 }
326
327 /* Open the Object */
328 Status = ObReferenceObjectByHandle(MutantHandle,
329 0, /* No access rights required */
330 ExMutantObjectType,
331 PreviousMode,
332 (PVOID*)&Mutant,
333 NULL);
334
335 /* Check for Success and release if such */
336 if (NT_SUCCESS(Status))
337 {
338 /*
339 * Release the mutant. doing so might raise an exception which we're
340 * required to catch!
341 */
342 _SEH2_TRY
343 {
344 /* Release the mutant */
345 LONG Prev = KeReleaseMutant(Mutant,
346 MUTANT_INCREMENT,
347 FALSE,
348 FALSE);
349
350 /* Return the previous count if requested */
351 if (PreviousCount) *PreviousCount = Prev;
352 }
353 _SEH2_EXCEPT(ExSystemExceptionFilter())
354 {
355 /* Get the exception code */
356 Status = _SEH2_GetExceptionCode();
357 }
358 _SEH2_END;
359
360 /* Dereference it */
361 ObDereferenceObject(Mutant);
362 }
363
364 /* Return Status */
365 return Status;
366 }
367
368 /* EOF */