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