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