Reverting to 13775. Sorry for the mess. This is dedicated to Jane! 19934415.
[reactos.git] / reactos / ntoskrnl / ex / sem.c
1 /* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/sem.c
6 * PURPOSE: Synchronization primitives
7 *
8 * PROGRAMMERS: 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 ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
30 };
31
32 /* FUNCTIONS *****************************************************************/
33
34 NTSTATUS STDCALL
35 ExpCreateSemaphore(PVOID ObjectBody,
36 PVOID Parent,
37 PWSTR RemainingPath,
38 POBJECT_ATTRIBUTES ObjectAttributes)
39 {
40 DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n",
41 ObjectBody, Parent, RemainingPath);
42
43 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
44 {
45 return(STATUS_UNSUCCESSFUL);
46 }
47
48 return(STATUS_SUCCESS);
49 }
50
51 VOID INIT_FUNCTION
52 ExpInitializeSemaphoreImplementation(VOID)
53 {
54 ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
55
56 RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
57
58 ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
59 ExSemaphoreObjectType->PeakObjects = 0;
60 ExSemaphoreObjectType->PeakHandles = 0;
61 ExSemaphoreObjectType->TotalObjects = 0;
62 ExSemaphoreObjectType->TotalHandles = 0;
63 ExSemaphoreObjectType->PagedPoolCharge = 0;
64 ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
65 ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
66 ExSemaphoreObjectType->Dump = NULL;
67 ExSemaphoreObjectType->Open = NULL;
68 ExSemaphoreObjectType->Close = NULL;
69 ExSemaphoreObjectType->Delete = NULL;
70 ExSemaphoreObjectType->Parse = NULL;
71 ExSemaphoreObjectType->Security = NULL;
72 ExSemaphoreObjectType->QueryName = NULL;
73 ExSemaphoreObjectType->OkayToClose = NULL;
74 ExSemaphoreObjectType->Create = ExpCreateSemaphore;
75 ExSemaphoreObjectType->DuplicationNotify = NULL;
76
77 ObpCreateTypeObject(ExSemaphoreObjectType);
78 }
79
80 /*
81 * @implemented
82 */
83 NTSTATUS STDCALL
84 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
85 IN ACCESS_MASK DesiredAccess,
86 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
87 IN LONG InitialCount,
88 IN LONG MaximumCount)
89 {
90 PKSEMAPHORE Semaphore;
91 HANDLE hSemaphore;
92 KPROCESSOR_MODE PreviousMode;
93 NTSTATUS Status = STATUS_SUCCESS;
94
95 PAGED_CODE();
96
97 PreviousMode = ExGetPreviousMode();
98
99 if(PreviousMode == UserMode)
100 {
101 _SEH_TRY
102 {
103 ProbeForWrite(SemaphoreHandle,
104 sizeof(HANDLE),
105 sizeof(ULONG));
106 }
107 _SEH_HANDLE
108 {
109 Status = _SEH_GetExceptionCode();
110 }
111 _SEH_END;
112
113 if(!NT_SUCCESS(Status))
114 {
115 return Status;
116 }
117 }
118
119 Status = ObCreateObject(PreviousMode,
120 ExSemaphoreObjectType,
121 ObjectAttributes,
122 PreviousMode,
123 NULL,
124 sizeof(KSEMAPHORE),
125 0,
126 0,
127 (PVOID*)&Semaphore);
128 if (NT_SUCCESS(Status))
129 {
130 KeInitializeSemaphore(Semaphore,
131 InitialCount,
132 MaximumCount);
133
134 Status = ObInsertObject ((PVOID)Semaphore,
135 NULL,
136 DesiredAccess,
137 0,
138 NULL,
139 &hSemaphore);
140
141 ObDereferenceObject(Semaphore);
142
143 if(NT_SUCCESS(Status))
144 {
145 _SEH_TRY
146 {
147 *SemaphoreHandle = hSemaphore;
148 }
149 _SEH_HANDLE
150 {
151 Status = _SEH_GetExceptionCode();
152 }
153 _SEH_END;
154 }
155 }
156
157 return Status;
158 }
159
160
161 /*
162 * @implemented
163 */
164 NTSTATUS STDCALL
165 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
166 IN ACCESS_MASK DesiredAccess,
167 IN POBJECT_ATTRIBUTES ObjectAttributes)
168 {
169 HANDLE hSemaphore;
170 KPROCESSOR_MODE PreviousMode;
171 NTSTATUS Status = STATUS_SUCCESS;
172
173 PAGED_CODE();
174
175 PreviousMode = ExGetPreviousMode();
176
177 if(PreviousMode == UserMode)
178 {
179 _SEH_TRY
180 {
181 ProbeForWrite(SemaphoreHandle,
182 sizeof(HANDLE),
183 sizeof(ULONG));
184 }
185 _SEH_HANDLE
186 {
187 Status = _SEH_GetExceptionCode();
188 }
189 _SEH_END;
190
191 if(!NT_SUCCESS(Status))
192 {
193 return Status;
194 }
195 }
196
197 Status = ObOpenObjectByName(ObjectAttributes,
198 ExSemaphoreObjectType,
199 NULL,
200 PreviousMode,
201 DesiredAccess,
202 NULL,
203 &hSemaphore);
204 if(NT_SUCCESS(Status))
205 {
206 _SEH_TRY
207 {
208 *SemaphoreHandle = hSemaphore;
209 }
210 _SEH_HANDLE
211 {
212 Status = _SEH_GetExceptionCode();
213 }
214 _SEH_END;
215 }
216
217 return Status;
218 }
219
220
221 /*
222 * @implemented
223 */
224 NTSTATUS STDCALL
225 NtQuerySemaphore(IN HANDLE SemaphoreHandle,
226 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
227 OUT PVOID SemaphoreInformation,
228 IN ULONG SemaphoreInformationLength,
229 OUT PULONG ReturnLength OPTIONAL)
230 {
231 PKSEMAPHORE Semaphore;
232 KPROCESSOR_MODE PreviousMode;
233 NTSTATUS Status = STATUS_SUCCESS;
234
235 PAGED_CODE();
236
237 PreviousMode = ExGetPreviousMode();
238
239 DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
240 ExSemaphoreInfoClass,
241 SemaphoreInformation,
242 SemaphoreInformationLength,
243 ReturnLength,
244 PreviousMode,
245 &Status);
246 if(!NT_SUCCESS(Status))
247 {
248 DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
249 return Status;
250 }
251
252 Status = ObReferenceObjectByHandle(SemaphoreHandle,
253 SEMAPHORE_QUERY_STATE,
254 ExSemaphoreObjectType,
255 PreviousMode,
256 (PVOID*)&Semaphore,
257 NULL);
258 if(NT_SUCCESS(Status))
259 {
260 switch(SemaphoreInformationClass)
261 {
262 case SemaphoreBasicInformation:
263 {
264 PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
265
266 _SEH_TRY
267 {
268 BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
269 BasicInfo->MaximumCount = Semaphore->Limit;
270
271 if(ReturnLength != NULL)
272 {
273 *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
274 }
275 }
276 _SEH_HANDLE
277 {
278 Status = _SEH_GetExceptionCode();
279 }
280 _SEH_END;
281 break;
282 }
283
284 default:
285 Status = STATUS_NOT_IMPLEMENTED;
286 break;
287 }
288
289 ObDereferenceObject(Semaphore);
290 }
291
292 return Status;
293 }
294
295
296 /*
297 * @implemented
298 */
299 NTSTATUS STDCALL
300 NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
301 IN LONG ReleaseCount,
302 OUT PLONG PreviousCount OPTIONAL)
303 {
304 KPROCESSOR_MODE PreviousMode;
305 PKSEMAPHORE Semaphore;
306 NTSTATUS Status = STATUS_SUCCESS;
307
308 PAGED_CODE();
309
310 PreviousMode = ExGetPreviousMode();
311
312 if(PreviousCount != NULL && PreviousMode == UserMode)
313 {
314 _SEH_TRY
315 {
316 ProbeForWrite(PreviousCount,
317 sizeof(LONG),
318 sizeof(ULONG));
319 }
320 _SEH_HANDLE
321 {
322 Status = _SEH_GetExceptionCode();
323 }
324 _SEH_END;
325
326 if(!NT_SUCCESS(Status))
327 {
328 return Status;
329 }
330 }
331
332 Status = ObReferenceObjectByHandle(SemaphoreHandle,
333 SEMAPHORE_MODIFY_STATE,
334 ExSemaphoreObjectType,
335 PreviousMode,
336 (PVOID*)&Semaphore,
337 NULL);
338 if (NT_SUCCESS(Status))
339 {
340 LONG PrevCount = KeReleaseSemaphore(Semaphore,
341 IO_NO_INCREMENT,
342 ReleaseCount,
343 FALSE);
344 ObDereferenceObject(Semaphore);
345
346 if(PreviousCount != NULL)
347 {
348 _SEH_TRY
349 {
350 *PreviousCount = PrevCount;
351 }
352 _SEH_HANDLE
353 {
354 Status = _SEH_GetExceptionCode();
355 }
356 _SEH_END;
357 }
358 }
359
360 return Status;
361 }
362
363 /* EOF */