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