Merge 13159:13510 from trunk
[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 PreviousMode = ExGetPreviousMode();
96
97 if(PreviousMode == UserMode)
98 {
99 _SEH_TRY
100 {
101 ProbeForWrite(SemaphoreHandle,
102 sizeof(HANDLE),
103 sizeof(ULONG));
104 }
105 _SEH_HANDLE
106 {
107 Status = _SEH_GetExceptionCode();
108 }
109 _SEH_END;
110
111 if(!NT_SUCCESS(Status))
112 {
113 return Status;
114 }
115 }
116
117 Status = ObCreateObject(PreviousMode,
118 ExSemaphoreObjectType,
119 ObjectAttributes,
120 PreviousMode,
121 NULL,
122 sizeof(KSEMAPHORE),
123 0,
124 0,
125 (PVOID*)&Semaphore);
126 if (NT_SUCCESS(Status))
127 {
128 KeInitializeSemaphore(Semaphore,
129 InitialCount,
130 MaximumCount);
131
132 Status = ObInsertObject ((PVOID)Semaphore,
133 NULL,
134 DesiredAccess,
135 0,
136 NULL,
137 &hSemaphore);
138
139 ObDereferenceObject(Semaphore);
140
141 if(NT_SUCCESS(Status))
142 {
143 _SEH_TRY
144 {
145 *SemaphoreHandle = hSemaphore;
146 }
147 _SEH_HANDLE
148 {
149 Status = _SEH_GetExceptionCode();
150 }
151 _SEH_END;
152 }
153 }
154
155 return Status;
156 }
157
158
159 /*
160 * @implemented
161 */
162 NTSTATUS STDCALL
163 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
164 IN ACCESS_MASK DesiredAccess,
165 IN POBJECT_ATTRIBUTES ObjectAttributes)
166 {
167 HANDLE hSemaphore;
168 KPROCESSOR_MODE PreviousMode;
169 NTSTATUS Status = STATUS_SUCCESS;
170
171 PreviousMode = ExGetPreviousMode();
172
173 if(PreviousMode == UserMode)
174 {
175 _SEH_TRY
176 {
177 ProbeForWrite(SemaphoreHandle,
178 sizeof(HANDLE),
179 sizeof(ULONG));
180 }
181 _SEH_HANDLE
182 {
183 Status = _SEH_GetExceptionCode();
184 }
185 _SEH_END;
186
187 if(!NT_SUCCESS(Status))
188 {
189 return Status;
190 }
191 }
192
193 Status = ObOpenObjectByName(ObjectAttributes,
194 ExSemaphoreObjectType,
195 NULL,
196 PreviousMode,
197 DesiredAccess,
198 NULL,
199 &hSemaphore);
200 if(NT_SUCCESS(Status))
201 {
202 _SEH_TRY
203 {
204 *SemaphoreHandle = hSemaphore;
205 }
206 _SEH_HANDLE
207 {
208 Status = _SEH_GetExceptionCode();
209 }
210 _SEH_END;
211 }
212
213 return Status;
214 }
215
216
217 /*
218 * @implemented
219 */
220 NTSTATUS STDCALL
221 NtQuerySemaphore(IN HANDLE SemaphoreHandle,
222 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
223 OUT PVOID SemaphoreInformation,
224 IN ULONG SemaphoreInformationLength,
225 OUT PULONG ReturnLength OPTIONAL)
226 {
227 PKSEMAPHORE Semaphore;
228 KPROCESSOR_MODE PreviousMode;
229 NTSTATUS Status = STATUS_SUCCESS;
230
231 PreviousMode = ExGetPreviousMode();
232
233 DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
234 ExSemaphoreInfoClass,
235 SemaphoreInformation,
236 SemaphoreInformationLength,
237 ReturnLength,
238 PreviousMode,
239 &Status);
240 if(!NT_SUCCESS(Status))
241 {
242 DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
243 return Status;
244 }
245
246 Status = ObReferenceObjectByHandle(SemaphoreHandle,
247 SEMAPHORE_QUERY_STATE,
248 ExSemaphoreObjectType,
249 PreviousMode,
250 (PVOID*)&Semaphore,
251 NULL);
252 if(NT_SUCCESS(Status))
253 {
254 switch(SemaphoreInformationClass)
255 {
256 case SemaphoreBasicInformation:
257 {
258 PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
259
260 _SEH_TRY
261 {
262 BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
263 BasicInfo->MaximumCount = Semaphore->Limit;
264
265 if(ReturnLength != NULL)
266 {
267 *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
268 }
269 }
270 _SEH_HANDLE
271 {
272 Status = _SEH_GetExceptionCode();
273 }
274 _SEH_END;
275 break;
276 }
277
278 default:
279 Status = STATUS_NOT_IMPLEMENTED;
280 break;
281 }
282
283 ObDereferenceObject(Semaphore);
284 }
285
286 return Status;
287 }
288
289
290 /*
291 * @implemented
292 */
293 NTSTATUS STDCALL
294 NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
295 IN LONG ReleaseCount,
296 OUT PLONG PreviousCount OPTIONAL)
297 {
298 KPROCESSOR_MODE PreviousMode;
299 PKSEMAPHORE Semaphore;
300 NTSTATUS Status = STATUS_SUCCESS;
301
302 PreviousMode = ExGetPreviousMode();
303
304 if(PreviousCount != NULL && PreviousMode == UserMode)
305 {
306 _SEH_TRY
307 {
308 ProbeForWrite(PreviousCount,
309 sizeof(LONG),
310 sizeof(ULONG));
311 }
312 _SEH_HANDLE
313 {
314 Status = _SEH_GetExceptionCode();
315 }
316 _SEH_END;
317
318 if(!NT_SUCCESS(Status))
319 {
320 return Status;
321 }
322 }
323
324 Status = ObReferenceObjectByHandle(SemaphoreHandle,
325 SEMAPHORE_MODIFY_STATE,
326 ExSemaphoreObjectType,
327 PreviousMode,
328 (PVOID*)&Semaphore,
329 NULL);
330 if (NT_SUCCESS(Status))
331 {
332 LONG PrevCount = KeReleaseSemaphore(Semaphore,
333 IO_NO_INCREMENT,
334 ReleaseCount,
335 FALSE);
336 ObDereferenceObject(Semaphore);
337
338 if(PreviousCount != NULL)
339 {
340 _SEH_TRY
341 {
342 *PreviousCount = PrevCount;
343 }
344 _SEH_HANDLE
345 {
346 Status = _SEH_GetExceptionCode();
347 }
348 _SEH_END;
349 }
350 }
351
352 return Status;
353 }
354
355 /* EOF */