- KdDebuggerNotPresent should be FALSE by default.
[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 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Thomas Weidenmueller
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/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 | SYNCHRONIZE | MUTANT_QUERY_STATE,
27 STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
28 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
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 VOID
54 INIT_FUNCTION
55 NTAPI
56 ExpInitializeMutantImplementation(VOID)
57 {
58 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
59 UNICODE_STRING Name;
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 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExMutantObjectType);
72 }
73
74 /*
75 * @implemented
76 */
77 NTSTATUS
78 NTAPI
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 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 _SEH_TRY
97 {
98 /* Check handle pointer */
99 ProbeForWriteHandle(MutantHandle);
100 }
101 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
102 {
103 Status = _SEH_GetExceptionCode();
104 }
105 _SEH_END;
106
107 /* Bail out if pointer was invalid */
108 if(!NT_SUCCESS(Status)) return Status;
109 }
110
111 /* Create the Mutant Object*/
112 Status = ObCreateObject(PreviousMode,
113 ExMutantObjectType,
114 ObjectAttributes,
115 PreviousMode,
116 NULL,
117 sizeof(KMUTANT),
118 0,
119 0,
120 (PVOID*)&Mutant);
121
122 /* Check for success */
123 if(NT_SUCCESS(Status))
124 {
125 /* Initalize the Kernel Mutant */
126 DPRINT("Initializing the Mutant\n");
127 KeInitializeMutant(Mutant, InitialOwner);
128
129 /* Insert the Object */
130 Status = ObInsertObject((PVOID)Mutant,
131 NULL,
132 DesiredAccess,
133 0,
134 NULL,
135 &hMutant);
136
137 /* Check for success */
138 if(NT_SUCCESS(Status))
139 {
140 /* Enter SEH for return */
141 _SEH_TRY
142 {
143 /* Return the handle to the caller */
144 *MutantHandle = hMutant;
145 }
146 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
147 {
148 Status = _SEH_GetExceptionCode();
149 }
150 _SEH_END;
151 }
152 }
153
154 /* Return Status */
155 return Status;
156 }
157
158 /*
159 * @implemented
160 */
161 NTSTATUS
162 NTAPI
163 NtOpenMutant(OUT PHANDLE MutantHandle,
164 IN ACCESS_MASK DesiredAccess,
165 IN POBJECT_ATTRIBUTES ObjectAttributes)
166 {
167 HANDLE hMutant;
168 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
169 NTSTATUS Status = STATUS_SUCCESS;
170 PAGED_CODE();
171 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
172 MutantHandle, DesiredAccess, ObjectAttributes);
173
174 /* Check if we were called from user-mode */
175 if(PreviousMode != KernelMode)
176 {
177 /* Enter SEH Block */
178 _SEH_TRY
179 {
180 /* Check handle pointer */
181 ProbeForWriteHandle(MutantHandle);
182 }
183 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
184 {
185 Status = _SEH_GetExceptionCode();
186 }
187 _SEH_END;
188
189 /* Bail out if pointer was invalid */
190 if(!NT_SUCCESS(Status)) return Status;
191 }
192
193 /* Open the Object */
194 Status = ObOpenObjectByName(ObjectAttributes,
195 ExMutantObjectType,
196 PreviousMode,
197 NULL,
198 DesiredAccess,
199 NULL,
200 &hMutant);
201
202 /* Check for success */
203 if(NT_SUCCESS(Status))
204 {
205 /* Enter SEH for return */
206 _SEH_TRY
207 {
208 /* Return the handle to the caller */
209 *MutantHandle = hMutant;
210 }
211 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
212 {
213 Status = _SEH_GetExceptionCode();
214 }
215 _SEH_END;
216 }
217
218 /* Return Status */
219 return Status;
220 }
221
222 /*
223 * @implemented
224 */
225 NTSTATUS
226 NTAPI
227 NtQueryMutant(IN HANDLE MutantHandle,
228 IN MUTANT_INFORMATION_CLASS MutantInformationClass,
229 OUT PVOID MutantInformation,
230 IN ULONG MutantInformationLength,
231 OUT PULONG ResultLength OPTIONAL)
232 {
233 PKMUTANT Mutant;
234 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
235 NTSTATUS Status = STATUS_SUCCESS;
236 PMUTANT_BASIC_INFORMATION BasicInfo =
237 (PMUTANT_BASIC_INFORMATION)MutantInformation;
238 PAGED_CODE();
239
240 /* Check buffers and parameters */
241 Status = DefaultQueryInfoBufferCheck(MutantInformationClass,
242 ExMutantInfoClass,
243 sizeof(ExMutantInfoClass) /
244 sizeof(ExMutantInfoClass[0]),
245 MutantInformation,
246 MutantInformationLength,
247 ResultLength,
248 PreviousMode);
249 if(!NT_SUCCESS(Status))
250 {
251 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
252 return Status;
253 }
254
255 /* Open the Object */
256 Status = ObReferenceObjectByHandle(MutantHandle,
257 MUTANT_QUERY_STATE,
258 ExMutantObjectType,
259 PreviousMode,
260 (PVOID*)&Mutant,
261 NULL);
262 /* Check for Status */
263 if(NT_SUCCESS(Status))
264 {
265 /* Enter SEH Block for return */
266 _SEH_TRY
267 {
268 /* Fill out the Basic Information Requested */
269 DPRINT("Returning Mutant Information\n");
270 BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
271 BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
272 KeGetCurrentThread());
273 BasicInfo->AbandonedState = Mutant->Abandoned;
274
275 /* Return the Result Length if requested */
276 if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
277 }
278 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
279 {
280 Status = _SEH_GetExceptionCode();
281 }
282 _SEH_END;
283
284 /* Release the Object */
285 ObDereferenceObject(Mutant);
286 }
287
288 /* Return Status */
289 return Status;
290 }
291
292 /*
293 * @implemented
294 */
295 NTSTATUS
296 NTAPI
297 NtReleaseMutant(IN HANDLE MutantHandle,
298 IN PLONG PreviousCount OPTIONAL)
299 {
300 PKMUTANT Mutant;
301 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
302 NTSTATUS Status = STATUS_SUCCESS;
303 PAGED_CODE();
304 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
305 MutantHandle,
306 PreviousCount);
307
308 /* Check if we were called from user-mode */
309 if((PreviousCount) && (PreviousMode != KernelMode))
310 {
311 /* Entry SEH Block */
312 _SEH_TRY
313 {
314 /* Make sure the state pointer is valid */
315 ProbeForWriteLong(PreviousCount);
316 }
317 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
318 {
319 Status = _SEH_GetExceptionCode();
320 }
321 _SEH_END;
322
323 /* Bail out if pointer was invalid */
324 if(!NT_SUCCESS(Status)) return Status;
325 }
326
327 /* Open the Object */
328 Status = ObReferenceObjectByHandle(MutantHandle,
329 MUTANT_QUERY_STATE,
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 _SEH_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 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
354 {
355 Status = _SEH_GetExceptionCode();
356 }
357 _SEH_END;
358
359 /* Dereference it */
360 ObDereferenceObject(Mutant);
361 }
362
363 /* Return Status */
364 return Status;
365 }
366
367 /* EOF */