Fix duplicated startup version string
[reactos.git] / reactos / ntoskrnl / ex / sem.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/sem.c
5 * PURPOSE: Semaphore Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Thomas Weidenmueller
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeSemaphoreImplementation)
18 #endif
19
20 /* GLOBALS ******************************************************************/
21
22 POBJECT_TYPE _ExSemaphoreObjectType;
23
24 GENERIC_MAPPING ExSemaphoreMapping =
25 {
26 STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
27 STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
28 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
29 SEMAPHORE_ALL_ACCESS
30 };
31
32 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
33 {
34 /* SemaphoreBasicInformation */
35 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
36 };
37
38 /* FUNCTIONS *****************************************************************/
39
40 VOID
41 INIT_FUNCTION
42 NTAPI
43 ExpInitializeSemaphoreImplementation(VOID)
44 {
45 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
46 UNICODE_STRING Name;
47 DPRINT("Creating Semaphore Object Type\n");
48
49 /* Create the Event Pair Object Type */
50 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
51 RtlInitUnicodeString(&Name, L"Semaphore");
52 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
53 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KSEMAPHORE);
54 ObjectTypeInitializer.GenericMapping = ExSemaphoreMapping;
55 ObjectTypeInitializer.PoolType = NonPagedPool;
56 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
57 ObjectTypeInitializer.ValidAccessMask = SEMAPHORE_ALL_ACCESS;
58 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExSemaphoreObjectType);
59 }
60
61 /*
62 * @implemented
63 */
64 NTSTATUS
65 NTAPI
66 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
67 IN ACCESS_MASK DesiredAccess,
68 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
69 IN LONG InitialCount,
70 IN LONG MaximumCount)
71 {
72 PKSEMAPHORE Semaphore;
73 HANDLE hSemaphore;
74 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
75 NTSTATUS Status;
76 PAGED_CODE();
77
78 /* Check if we were called from user-mode */
79 if (PreviousMode != KernelMode)
80 {
81 /* Enter SEH Block */
82 _SEH2_TRY
83 {
84 /* Check handle pointer */
85 ProbeForWriteHandle(SemaphoreHandle);
86 }
87 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
88 {
89 /* Return the exception code */
90 _SEH2_YIELD(return _SEH2_GetExceptionCode());
91 }
92 _SEH2_END;
93 }
94
95 /* Make sure the counts make sense */
96 if ((MaximumCount <= 0) ||
97 (InitialCount < 0) ||
98 (InitialCount > MaximumCount))
99 {
100 DPRINT("Invalid Count Data!\n");
101 return STATUS_INVALID_PARAMETER;
102 }
103
104 /* Create the Semaphore Object */
105 Status = ObCreateObject(PreviousMode,
106 ExSemaphoreObjectType,
107 ObjectAttributes,
108 PreviousMode,
109 NULL,
110 sizeof(KSEMAPHORE),
111 0,
112 0,
113 (PVOID*)&Semaphore);
114
115 /* Check for Success */
116 if (NT_SUCCESS(Status))
117 {
118 /* Initialize it */
119 KeInitializeSemaphore(Semaphore,
120 InitialCount,
121 MaximumCount);
122
123 /* Insert it into the Object Tree */
124 Status = ObInsertObject((PVOID)Semaphore,
125 NULL,
126 DesiredAccess,
127 0,
128 NULL,
129 &hSemaphore);
130
131 /* Check for success */
132 if (NT_SUCCESS(Status))
133 {
134 /* Enter SEH Block for return */
135 _SEH2_TRY
136 {
137 /* Return the handle */
138 *SemaphoreHandle = hSemaphore;
139 }
140 _SEH2_EXCEPT(ExSystemExceptionFilter())
141 {
142 /* Get the exception code */
143 Status = _SEH2_GetExceptionCode();
144 }
145 _SEH2_END;
146 }
147 }
148
149 /* Return Status */
150 return Status;
151 }
152
153 /*
154 * @implemented
155 */
156 NTSTATUS
157 NTAPI
158 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
159 IN ACCESS_MASK DesiredAccess,
160 IN POBJECT_ATTRIBUTES ObjectAttributes)
161 {
162 HANDLE hSemaphore;
163 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
164 NTSTATUS Status;
165 PAGED_CODE();
166
167 /* Check if we were called from user-mode */
168 if (PreviousMode != KernelMode)
169 {
170 /* Enter SEH Block */
171 _SEH2_TRY
172 {
173 /* Check handle pointer */
174 ProbeForWriteHandle(SemaphoreHandle);
175 }
176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
177 {
178 /* Return the exception code */
179 _SEH2_YIELD(return _SEH2_GetExceptionCode());
180 }
181 _SEH2_END;
182 }
183
184 /* Open the Object */
185 Status = ObOpenObjectByName(ObjectAttributes,
186 ExSemaphoreObjectType,
187 PreviousMode,
188 NULL,
189 DesiredAccess,
190 NULL,
191 &hSemaphore);
192
193 /* Check for success */
194 if (NT_SUCCESS(Status))
195 {
196 /* Enter SEH Block for return */
197 _SEH2_TRY
198 {
199 /* Return the handle */
200 *SemaphoreHandle = hSemaphore;
201 }
202 _SEH2_EXCEPT(ExSystemExceptionFilter())
203 {
204 /* Get the exception code */
205 Status = _SEH2_GetExceptionCode();
206 }
207 _SEH2_END;
208 }
209
210 /* Return Status */
211 return Status;
212 }
213
214 /*
215 * @implemented
216 */
217 NTSTATUS
218 NTAPI
219 NtQuerySemaphore(IN HANDLE SemaphoreHandle,
220 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
221 OUT PVOID SemaphoreInformation,
222 IN ULONG SemaphoreInformationLength,
223 OUT PULONG ReturnLength OPTIONAL)
224 {
225 PKSEMAPHORE Semaphore;
226 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
227 NTSTATUS Status;
228 PAGED_CODE();
229
230 /* Check buffers and class validity */
231 Status = DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
232 ExSemaphoreInfoClass,
233 sizeof(ExSemaphoreInfoClass) /
234 sizeof(ExSemaphoreInfoClass[0]),
235 SemaphoreInformation,
236 SemaphoreInformationLength,
237 ReturnLength,
238 NULL,
239 PreviousMode);
240 if (!NT_SUCCESS(Status))
241 {
242 /* Invalid buffers */
243 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
244 return Status;
245 }
246
247 /* Get the Object */
248 Status = ObReferenceObjectByHandle(SemaphoreHandle,
249 SEMAPHORE_QUERY_STATE,
250 ExSemaphoreObjectType,
251 PreviousMode,
252 (PVOID*)&Semaphore,
253 NULL);
254
255 /* Check for success */
256 if (NT_SUCCESS(Status))
257 {
258 /* Entry SEH Block */
259 _SEH2_TRY
260 {
261 PSEMAPHORE_BASIC_INFORMATION BasicInfo =
262 (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
263
264 /* Return the basic information */
265 BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
266 BasicInfo->MaximumCount = Semaphore->Limit;
267
268 /* Return the length */
269 if (ReturnLength) *ReturnLength = sizeof(*BasicInfo);
270 }
271 _SEH2_EXCEPT(ExSystemExceptionFilter())
272 {
273 /* Get the exception code */
274 Status = _SEH2_GetExceptionCode();
275 }
276 _SEH2_END;
277
278 /* Dereference the Object */
279 ObDereferenceObject(Semaphore);
280 }
281
282 /* Return status */
283 return Status;
284 }
285
286 /*
287 * @implemented
288 */
289 NTSTATUS
290 NTAPI
291 NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
292 IN LONG ReleaseCount,
293 OUT PLONG PreviousCount OPTIONAL)
294 {
295 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
296 PKSEMAPHORE Semaphore;
297 NTSTATUS Status;
298 PAGED_CODE();
299
300 /* Check if we were called from user-mode */
301 if ((PreviousCount) && (PreviousMode != KernelMode))
302 {
303 /* Entry SEH Block */
304 _SEH2_TRY
305 {
306 /* Make sure the state pointer is valid */
307 ProbeForWriteLong(PreviousCount);
308 }
309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
310 {
311 /* Return the exception code */
312 _SEH2_YIELD(return _SEH2_GetExceptionCode());
313 }
314 _SEH2_END;
315 }
316
317 /* Make sure count makes sense */
318 if (ReleaseCount <= 0)
319 {
320 DPRINT("Invalid Release Count\n");
321 return STATUS_INVALID_PARAMETER;
322 }
323
324 /* Get the Object */
325 Status = ObReferenceObjectByHandle(SemaphoreHandle,
326 SEMAPHORE_MODIFY_STATE,
327 ExSemaphoreObjectType,
328 PreviousMode,
329 (PVOID*)&Semaphore,
330 NULL);
331
332 /* Check for success */
333 if (NT_SUCCESS(Status))
334 {
335 /* Enter SEH Block */
336 _SEH2_TRY
337 {
338 /* Release the semaphore */
339 LONG PrevCount = KeReleaseSemaphore(Semaphore,
340 IO_NO_INCREMENT,
341 ReleaseCount,
342 FALSE);
343
344 /* Return the old count if requested */
345 if (PreviousCount) *PreviousCount = PrevCount;
346 }
347 _SEH2_EXCEPT(ExSystemExceptionFilter())
348 {
349 /* Get the exception code */
350 Status = _SEH2_GetExceptionCode();
351 }
352 _SEH2_END;
353
354 /* Dereference the Semaphore */
355 ObDereferenceObject(Semaphore);
356 }
357
358 /* Return Status */
359 return Status;
360 }
361
362 /* EOF */