Test commit. Not official branch release -- it will follow shortly in 15 minutes...
[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:
8 * Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
9 * add more debug output.
10 * David Welch (welch@cwcom.net)
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #include <ntoskrnl.h>
16 #define NDEBUG
17 #include <internal/debug.h>
18
19 POBJECT_TYPE ExMutantObjectType = NULL;
20
21 static GENERIC_MAPPING ExpMutantMapping = {
22 STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
23 STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
24 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
25 MUTANT_ALL_ACCESS};
26
27 static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = {
28
29 /* MutantBasicInformation */
30 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
31 };
32
33 /* FUNCTIONS *****************************************************************/
34
35 VOID
36 STDCALL
37 ExpDeleteMutant(PVOID ObjectBody)
38 {
39
40 DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
41
42 /* Make sure to release the Mutant */
43 KeReleaseMutant((PKMUTANT)ObjectBody,
44 MUTANT_INCREMENT,
45 TRUE,
46 FALSE);
47 }
48
49 VOID
50 INIT_FUNCTION
51 ExpInitializeMutantImplementation(VOID)
52 {
53
54 /* Allocate the Object Type */
55 ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't'));
56
57 /* Create the Object Type */
58 RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
59 ExMutantObjectType->Tag = TAG('M', 't', 'n', 't');
60 ExMutantObjectType->PeakObjects = 0;
61 ExMutantObjectType->PeakHandles = 0;
62 ExMutantObjectType->TotalObjects = 0;
63 ExMutantObjectType->TotalHandles = 0;
64 ExMutantObjectType->PagedPoolCharge = 0;
65 ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
66 ExMutantObjectType->Mapping = &ExpMutantMapping;
67 ExMutantObjectType->Dump = NULL;
68 ExMutantObjectType->Open = NULL;
69 ExMutantObjectType->Close = NULL;
70 ExMutantObjectType->Delete = ExpDeleteMutant;
71 ExMutantObjectType->Parse = NULL;
72 ExMutantObjectType->Security = NULL;
73 ExMutantObjectType->QueryName = NULL;
74 ExMutantObjectType->OkayToClose = NULL;
75 ExMutantObjectType->Create = NULL;
76 ExMutantObjectType->DuplicationNotify = NULL;
77 ObpCreateTypeObject(ExMutantObjectType);
78 }
79
80 /*
81 * @implemented
82 */
83 NTSTATUS
84 STDCALL
85 NtCreateMutant(OUT PHANDLE MutantHandle,
86 IN ACCESS_MASK DesiredAccess,
87 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
88 IN BOOLEAN InitialOwner)
89 {
90 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
91 HANDLE hMutant;
92 PKMUTANT Mutant;
93 NTSTATUS Status = STATUS_SUCCESS;
94
95 DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
96
97 /* Check Output Safety */
98 if(PreviousMode == UserMode) {
99
100 _SEH_TRY {
101
102 ProbeForWrite(MutantHandle,
103 sizeof(HANDLE),
104 sizeof(ULONG));
105 } _SEH_HANDLE {
106
107 Status = _SEH_GetExceptionCode();
108
109 } _SEH_END;
110
111 if(!NT_SUCCESS(Status)) return Status;
112 }
113
114 /* Create the Mutant Object*/
115 Status = ObCreateObject(PreviousMode,
116 ExMutantObjectType,
117 ObjectAttributes,
118 PreviousMode,
119 NULL,
120 sizeof(KMUTANT),
121 0,
122 0,
123 (PVOID*)&Mutant);
124
125 /* Check for success */
126 if(NT_SUCCESS(Status)) {
127
128 /* Initalize the Kernel Mutant */
129 DPRINT("Initializing the Mutant\n");
130 KeInitializeMutant(Mutant, InitialOwner);
131
132 /* Insert the Object */
133 Status = ObInsertObject((PVOID)Mutant,
134 NULL,
135 DesiredAccess,
136 0,
137 NULL,
138 &hMutant);
139 ObDereferenceObject(Mutant);
140
141 /* Check for success and return handle */
142 if(NT_SUCCESS(Status)) {
143
144 _SEH_TRY {
145
146 *MutantHandle = hMutant;
147
148 } _SEH_HANDLE {
149
150 Status = _SEH_GetExceptionCode();
151
152 } _SEH_END;
153 }
154 }
155
156 /* Return Status */
157 return Status;
158 }
159
160
161 /*
162 * @implemented
163 */
164 NTSTATUS
165 STDCALL
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 = STATUS_SUCCESS;
173
174 PAGED_CODE();
175
176 DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
177
178 /* Check Output Safety */
179 if(PreviousMode == UserMode) {
180
181 _SEH_TRY {
182
183 ProbeForWrite(MutantHandle,
184 sizeof(HANDLE),
185 sizeof(ULONG));
186 } _SEH_HANDLE {
187
188 Status = _SEH_GetExceptionCode();
189
190 } _SEH_END;
191
192 if(!NT_SUCCESS(Status)) return Status;
193 }
194
195 /* Open the Object */
196 Status = ObOpenObjectByName(ObjectAttributes,
197 ExMutantObjectType,
198 NULL,
199 PreviousMode,
200 DesiredAccess,
201 NULL,
202 &hMutant);
203
204 /* Check for success and return handle */
205 if(NT_SUCCESS(Status)) {
206
207 _SEH_TRY {
208
209 *MutantHandle = hMutant;
210
211 } _SEH_HANDLE {
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 STDCALL
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 = (PMUTANT_BASIC_INFORMATION)MutantInformation;
237
238 /* Check buffers and parameters */
239 DefaultQueryInfoBufferCheck(MutantInformationClass,
240 ExMutantInfoClass,
241 MutantInformation,
242 MutantInformationLength,
243 ResultLength,
244 PreviousMode,
245 &Status);
246 if(!NT_SUCCESS(Status)) {
247
248 DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
249 return Status;
250 }
251
252 PAGED_CODE();
253
254 /* Open the Object */
255 Status = ObReferenceObjectByHandle(MutantHandle,
256 MUTANT_QUERY_STATE,
257 ExMutantObjectType,
258 PreviousMode,
259 (PVOID*)&Mutant,
260 NULL);
261 /* Check for Status */
262 if(NT_SUCCESS(Status)) {
263
264 _SEH_TRY {
265
266 /* Fill out the Basic Information Requested */
267 DPRINT1("Returning Mutant Information\n");
268 BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
269 BasicInfo->OwnedByCaller = (Mutant->OwnerThread == KeGetCurrentThread());
270 BasicInfo->AbandonedState = Mutant->Abandoned;
271
272 /* Return the Result Length if requested */
273 if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
274
275 } _SEH_HANDLE {
276
277 Status = _SEH_GetExceptionCode();
278
279 } _SEH_END;
280
281 /* Release the Object */
282 ObDereferenceObject(Mutant);
283 }
284
285 /* Return Status */
286 return Status;
287 }
288
289
290 /*
291 * @implemented
292 */
293 NTSTATUS
294 STDCALL
295 NtReleaseMutant(IN HANDLE MutantHandle,
296 IN PLONG PreviousCount OPTIONAL)
297 {
298 PKMUTANT Mutant;
299 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
300 NTSTATUS Status = STATUS_SUCCESS;
301
302 PAGED_CODE();
303
304 DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
305 MutantHandle,
306 PreviousCount);
307
308 /* Check Output Safety */
309 if(PreviousMode == UserMode && PreviousCount) {
310
311 _SEH_TRY {
312
313 ProbeForWrite(PreviousCount,
314 sizeof(LONG),
315 sizeof(ULONG));
316 } _SEH_HANDLE {
317
318 Status = _SEH_GetExceptionCode();
319
320 } _SEH_END;
321
322 if(!NT_SUCCESS(Status)) return Status;
323 }
324
325 /* Open the Object */
326 Status = ObReferenceObjectByHandle(MutantHandle,
327 MUTANT_QUERY_STATE,
328 ExMutantObjectType,
329 PreviousMode,
330 (PVOID*)&Mutant,
331 NULL);
332
333 /* Check for Success and release if such */
334 if(NT_SUCCESS(Status)) {
335
336 /* Save the Old State */
337 DPRINT1("Releasing Mutant\n");
338 LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE);
339 ObDereferenceObject(Mutant);
340
341 /* Return it */
342 if(PreviousCount) {
343
344 _SEH_TRY {
345
346 *PreviousCount = Prev;
347
348 } _SEH_HANDLE {
349
350 Status = _SEH_GetExceptionCode();
351
352 } _SEH_END;
353 }
354 }
355
356 /* Return Status */
357 return Status;
358 }
359
360 /* EOF */