f6a2d4b36c703f98e3f7ba7465feb9be063f01c8
[reactos.git] / reactos / ntoskrnl / ex / mutant.c
1 /* $Id:$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/mutant.c
6 * PURPOSE: Synchronization primitives
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 POBJECT_TYPE ExMutantObjectType = NULL;
18
19 static GENERIC_MAPPING ExpMutantMapping = {
20 STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
21 STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
22 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
23 MUTANT_ALL_ACCESS};
24
25 static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
26 {
27 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
28 };
29
30 /* FUNCTIONS *****************************************************************/
31
32
33 NTSTATUS STDCALL
34 ExpCreateMutant(PVOID ObjectBody,
35 PVOID Parent,
36 PWSTR RemainingPath,
37 POBJECT_ATTRIBUTES ObjectAttributes)
38 {
39 DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
40 ObjectBody, Parent, RemainingPath);
41
42 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
43 {
44 return(STATUS_UNSUCCESSFUL);
45 }
46
47 return(STATUS_SUCCESS);
48 }
49
50
51 VOID STDCALL
52 ExpDeleteMutant(PVOID ObjectBody)
53 {
54 DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
55
56 KeReleaseMutant((PKMUTANT)ObjectBody,
57 MUTANT_INCREMENT,
58 TRUE,
59 FALSE);
60 }
61
62
63 VOID INIT_FUNCTION
64 ExpInitializeMutantImplementation(VOID)
65 {
66 ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
67
68 RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
69
70 ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
71 ExMutantObjectType->PeakObjects = 0;
72 ExMutantObjectType->PeakHandles = 0;
73 ExMutantObjectType->TotalObjects = 0;
74 ExMutantObjectType->TotalHandles = 0;
75 ExMutantObjectType->PagedPoolCharge = 0;
76 ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
77 ExMutantObjectType->Mapping = &ExpMutantMapping;
78 ExMutantObjectType->Dump = NULL;
79 ExMutantObjectType->Open = NULL;
80 ExMutantObjectType->Close = NULL;
81 ExMutantObjectType->Delete = ExpDeleteMutant;
82 ExMutantObjectType->Parse = NULL;
83 ExMutantObjectType->Security = NULL;
84 ExMutantObjectType->QueryName = NULL;
85 ExMutantObjectType->OkayToClose = NULL;
86 ExMutantObjectType->Create = ExpCreateMutant;
87 ExMutantObjectType->DuplicationNotify = NULL;
88
89 ObpCreateTypeObject(ExMutantObjectType);
90 }
91
92
93 /*
94 * @implemented
95 */
96 NTSTATUS STDCALL
97 NtCreateMutant(OUT PHANDLE MutantHandle,
98 IN ACCESS_MASK DesiredAccess,
99 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
100 IN BOOLEAN InitialOwner)
101 {
102 KPROCESSOR_MODE PreviousMode;
103 HANDLE hMutant;
104 PKMUTEX Mutant;
105 NTSTATUS Status = STATUS_SUCCESS;
106
107 PAGED_CODE();
108
109 PreviousMode = ExGetPreviousMode();
110
111 if(PreviousMode == UserMode)
112 {
113 _SEH_TRY
114 {
115 ProbeForWrite(MutantHandle,
116 sizeof(HANDLE),
117 sizeof(ULONG));
118 }
119 _SEH_HANDLE
120 {
121 Status = _SEH_GetExceptionCode();
122 }
123 _SEH_END;
124
125 if(!NT_SUCCESS(Status))
126 {
127 return Status;
128 }
129 }
130
131 Status = ObCreateObject(PreviousMode,
132 ExMutantObjectType,
133 ObjectAttributes,
134 PreviousMode,
135 NULL,
136 sizeof(KMUTANT),
137 0,
138 0,
139 (PVOID*)&Mutant);
140 if(NT_SUCCESS(Status))
141 {
142 KeInitializeMutant(Mutant,
143 InitialOwner);
144
145 Status = ObInsertObject((PVOID)Mutant,
146 NULL,
147 DesiredAccess,
148 0,
149 NULL,
150 &hMutant);
151 ObDereferenceObject(Mutant);
152
153 if(NT_SUCCESS(Status))
154 {
155 _SEH_TRY
156 {
157 *MutantHandle = hMutant;
158 }
159 _SEH_HANDLE
160 {
161 Status = _SEH_GetExceptionCode();
162 }
163 _SEH_END;
164 }
165 }
166
167 return Status;
168 }
169
170
171 /*
172 * @implemented
173 */
174 NTSTATUS STDCALL
175 NtOpenMutant(OUT PHANDLE MutantHandle,
176 IN ACCESS_MASK DesiredAccess,
177 IN POBJECT_ATTRIBUTES ObjectAttributes)
178 {
179 HANDLE hMutant;
180 KPROCESSOR_MODE PreviousMode;
181 NTSTATUS Status = STATUS_SUCCESS;
182
183 PAGED_CODE();
184
185 DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
186
187 PreviousMode = ExGetPreviousMode();
188
189 if(PreviousMode == UserMode)
190 {
191 _SEH_TRY
192 {
193 ProbeForWrite(MutantHandle,
194 sizeof(HANDLE),
195 sizeof(ULONG));
196 }
197 _SEH_HANDLE
198 {
199 Status = _SEH_GetExceptionCode();
200 }
201 _SEH_END;
202
203 if(!NT_SUCCESS(Status))
204 {
205 return Status;
206 }
207 }
208
209 Status = ObOpenObjectByName(ObjectAttributes,
210 ExMutantObjectType,
211 NULL,
212 PreviousMode,
213 DesiredAccess,
214 NULL,
215 &hMutant);
216
217 if(NT_SUCCESS(Status))
218 {
219 _SEH_TRY
220 {
221 *MutantHandle = hMutant;
222 }
223 _SEH_HANDLE
224 {
225 Status = _SEH_GetExceptionCode();
226 }
227 _SEH_END;
228 }
229
230 return Status;
231 }
232
233
234 /*
235 * @implemented
236 */
237 NTSTATUS STDCALL
238 NtQueryMutant(IN HANDLE MutantHandle,
239 IN MUTANT_INFORMATION_CLASS MutantInformationClass,
240 OUT PVOID MutantInformation,
241 IN ULONG MutantInformationLength,
242 OUT PULONG ResultLength OPTIONAL)
243 {
244 PKMUTANT Mutant;
245 KPROCESSOR_MODE PreviousMode;
246 NTSTATUS Status = STATUS_SUCCESS;
247
248 PAGED_CODE();
249
250 PreviousMode = ExGetPreviousMode();
251
252 DefaultQueryInfoBufferCheck(MutantInformationClass,
253 ExMutantInfoClass,
254 MutantInformation,
255 MutantInformationLength,
256 ResultLength,
257 PreviousMode,
258 &Status);
259 if(!NT_SUCCESS(Status))
260 {
261 DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
262 return Status;
263 }
264
265 Status = ObReferenceObjectByHandle(MutantHandle,
266 MUTANT_QUERY_STATE,
267 ExMutantObjectType,
268 PreviousMode,
269 (PVOID*)&Mutant,
270 NULL);
271 if(NT_SUCCESS(Status))
272 {
273 switch(MutantInformationClass)
274 {
275 case MutantBasicInformation:
276 {
277 PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
278
279 _SEH_TRY
280 {
281 BasicInfo->Count = KeReadStateMutant(Mutant);
282 BasicInfo->Owned = (Mutant->OwnerThread != NULL);
283 BasicInfo->Abandoned = Mutant->Abandoned;
284
285 if(ResultLength != NULL)
286 {
287 *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
288 }
289 }
290 _SEH_HANDLE
291 {
292 Status = _SEH_GetExceptionCode();
293 }
294 _SEH_END;
295 break;
296 }
297
298 default:
299 Status = STATUS_NOT_IMPLEMENTED;
300 break;
301 }
302
303 ObDereferenceObject(Mutant);
304 }
305
306 return Status;
307 }
308
309
310 /*
311 * @implemented
312 */
313 NTSTATUS STDCALL
314 NtReleaseMutant(IN HANDLE MutantHandle,
315 IN PLONG PreviousCount OPTIONAL)
316 {
317 PKMUTANT Mutant;
318 KPROCESSOR_MODE PreviousMode;
319 NTSTATUS Status = STATUS_SUCCESS;
320
321 PAGED_CODE();
322
323 DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
324 MutantHandle, PreviousCount);
325
326 PreviousMode = ExGetPreviousMode();
327
328 if(PreviousCount != NULL && PreviousMode == UserMode)
329 {
330 _SEH_TRY
331 {
332 ProbeForWrite(PreviousCount,
333 sizeof(LONG),
334 sizeof(ULONG));
335 }
336 _SEH_HANDLE
337 {
338 Status = _SEH_GetExceptionCode();
339 }
340 _SEH_END;
341
342 if(!NT_SUCCESS(Status))
343 {
344 return Status;
345 }
346 }
347
348 Status = ObReferenceObjectByHandle(MutantHandle,
349 MUTANT_QUERY_STATE,
350 ExMutantObjectType,
351 PreviousMode,
352 (PVOID*)&Mutant,
353 NULL);
354 if(NT_SUCCESS(Status))
355 {
356 LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
357 ObDereferenceObject(Mutant);
358
359 if(PreviousCount != NULL)
360 {
361 _SEH_TRY
362 {
363 *PreviousCount = Prev;
364 }
365 _SEH_HANDLE
366 {
367 Status = _SEH_GetExceptionCode();
368 }
369 _SEH_END;
370 }
371 }
372
373 return Status;
374 }
375
376 /* EOF */