Standardize comment headers. Patch by Trevor McCort
[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 RtlCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant");
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 PreviousMode = ExGetPreviousMode();
108
109 if(PreviousMode == UserMode)
110 {
111 _SEH_TRY
112 {
113 ProbeForWrite(MutantHandle,
114 sizeof(HANDLE),
115 sizeof(ULONG));
116 }
117 _SEH_HANDLE
118 {
119 Status = _SEH_GetExceptionCode();
120 }
121 _SEH_END;
122
123 if(!NT_SUCCESS(Status))
124 {
125 return Status;
126 }
127 }
128
129 Status = ObCreateObject(PreviousMode,
130 ExMutantObjectType,
131 ObjectAttributes,
132 PreviousMode,
133 NULL,
134 sizeof(KMUTANT),
135 0,
136 0,
137 (PVOID*)&Mutant);
138 if(NT_SUCCESS(Status))
139 {
140 KeInitializeMutant(Mutant,
141 InitialOwner);
142
143 Status = ObInsertObject((PVOID)Mutant,
144 NULL,
145 DesiredAccess,
146 0,
147 NULL,
148 &hMutant);
149 ObDereferenceObject(Mutant);
150
151 if(NT_SUCCESS(Status))
152 {
153 _SEH_TRY
154 {
155 *MutantHandle = hMutant;
156 }
157 _SEH_HANDLE
158 {
159 Status = _SEH_GetExceptionCode();
160 }
161 _SEH_END;
162 }
163 }
164
165 return Status;
166 }
167
168
169 /*
170 * @implemented
171 */
172 NTSTATUS STDCALL
173 NtOpenMutant(OUT PHANDLE MutantHandle,
174 IN ACCESS_MASK DesiredAccess,
175 IN POBJECT_ATTRIBUTES ObjectAttributes)
176 {
177 HANDLE hMutant;
178 KPROCESSOR_MODE PreviousMode;
179 NTSTATUS Status = STATUS_SUCCESS;
180
181 DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
182
183 PreviousMode = ExGetPreviousMode();
184
185 if(PreviousMode == UserMode)
186 {
187 _SEH_TRY
188 {
189 ProbeForWrite(MutantHandle,
190 sizeof(HANDLE),
191 sizeof(ULONG));
192 }
193 _SEH_HANDLE
194 {
195 Status = _SEH_GetExceptionCode();
196 }
197 _SEH_END;
198
199 if(!NT_SUCCESS(Status))
200 {
201 return Status;
202 }
203 }
204
205 Status = ObOpenObjectByName(ObjectAttributes,
206 ExMutantObjectType,
207 NULL,
208 PreviousMode,
209 DesiredAccess,
210 NULL,
211 &hMutant);
212
213 if(NT_SUCCESS(Status))
214 {
215 _SEH_TRY
216 {
217 *MutantHandle = hMutant;
218 }
219 _SEH_HANDLE
220 {
221 Status = _SEH_GetExceptionCode();
222 }
223 _SEH_END;
224 }
225
226 return Status;
227 }
228
229
230 /*
231 * @implemented
232 */
233 NTSTATUS STDCALL
234 NtQueryMutant(IN HANDLE MutantHandle,
235 IN MUTANT_INFORMATION_CLASS MutantInformationClass,
236 OUT PVOID MutantInformation,
237 IN ULONG MutantInformationLength,
238 OUT PULONG ResultLength OPTIONAL)
239 {
240 PKMUTANT Mutant;
241 KPROCESSOR_MODE PreviousMode;
242 NTSTATUS Status = STATUS_SUCCESS;
243
244 PreviousMode = ExGetPreviousMode();
245
246 DefaultQueryInfoBufferCheck(MutantInformationClass,
247 ExMutantInfoClass,
248 MutantInformation,
249 MutantInformationLength,
250 ResultLength,
251 PreviousMode,
252 &Status);
253 if(!NT_SUCCESS(Status))
254 {
255 DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
256 return Status;
257 }
258
259 Status = ObReferenceObjectByHandle(MutantHandle,
260 MUTANT_QUERY_STATE,
261 ExMutantObjectType,
262 PreviousMode,
263 (PVOID*)&Mutant,
264 NULL);
265 if(NT_SUCCESS(Status))
266 {
267 switch(MutantInformationClass)
268 {
269 case MutantBasicInformation:
270 {
271 PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
272
273 _SEH_TRY
274 {
275 BasicInfo->Count = KeReadStateMutant(Mutant);
276 BasicInfo->Owned = (Mutant->OwnerThread != NULL);
277 BasicInfo->Abandoned = Mutant->Abandoned;
278
279 if(ResultLength != NULL)
280 {
281 *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
282 }
283 }
284 _SEH_HANDLE
285 {
286 Status = _SEH_GetExceptionCode();
287 }
288 _SEH_END;
289 break;
290 }
291
292 default:
293 Status = STATUS_NOT_IMPLEMENTED;
294 break;
295 }
296
297 ObDereferenceObject(Mutant);
298 }
299
300 return Status;
301 }
302
303
304 /*
305 * @implemented
306 */
307 NTSTATUS STDCALL
308 NtReleaseMutant(IN HANDLE MutantHandle,
309 IN PLONG PreviousCount OPTIONAL)
310 {
311 PKMUTANT Mutant;
312 KPROCESSOR_MODE PreviousMode;
313 NTSTATUS Status = STATUS_SUCCESS;
314
315 DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
316 MutantHandle, PreviousCount);
317
318 PreviousMode = ExGetPreviousMode();
319
320 if(PreviousCount != NULL && PreviousMode == UserMode)
321 {
322 _SEH_TRY
323 {
324 ProbeForWrite(PreviousCount,
325 sizeof(LONG),
326 sizeof(ULONG));
327 }
328 _SEH_HANDLE
329 {
330 Status = _SEH_GetExceptionCode();
331 }
332 _SEH_END;
333
334 if(!NT_SUCCESS(Status))
335 {
336 return Status;
337 }
338 }
339
340 Status = ObReferenceObjectByHandle(MutantHandle,
341 MUTANT_QUERY_STATE,
342 ExMutantObjectType,
343 PreviousMode,
344 (PVOID*)&Mutant,
345 NULL);
346 if(NT_SUCCESS(Status))
347 {
348 LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
349 ObDereferenceObject(Mutant);
350
351 if(PreviousCount != NULL)
352 {
353 _SEH_TRY
354 {
355 *PreviousCount = Prev;
356 }
357 _SEH_HANDLE
358 {
359 Status = _SEH_GetExceptionCode();
360 }
361 _SEH_END;
362 }
363 }
364
365 return Status;
366 }
367
368 /* EOF */