ReactOS  r76032
sem.c
Go to the documentation of this file.
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 
23 
25 {
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 BOOLEAN
42 NTAPI
44 {
45  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
48  DPRINT("Creating Semaphore Object Type\n");
49 
50  /* Create the Event Pair Object Type */
51  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
52  RtlInitUnicodeString(&Name, L"Semaphore");
53  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
54  ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KSEMAPHORE);
55  ObjectTypeInitializer.GenericMapping = ExSemaphoreMapping;
56  ObjectTypeInitializer.PoolType = NonPagedPool;
57  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
58  ObjectTypeInitializer.ValidAccessMask = SEMAPHORE_ALL_ACCESS;
59  Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExSemaphoreObjectType);
60  if (!NT_SUCCESS(Status)) return FALSE;
61  return TRUE;
62 }
63 
64 /*
65  * @implemented
66  */
68 NTAPI
69 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
72  IN LONG InitialCount,
74 {
75  PKSEMAPHORE Semaphore;
76  HANDLE hSemaphore;
79  PAGED_CODE();
80 
81  /* Check if we were called from user-mode */
82  if (PreviousMode != KernelMode)
83  {
84  /* Enter SEH Block */
85  _SEH2_TRY
86  {
87  /* Check handle pointer */
88  ProbeForWriteHandle(SemaphoreHandle);
89  }
91  {
92  /* Return the exception code */
94  }
95  _SEH2_END;
96  }
97 
98  /* Make sure the counts make sense */
99  if ((MaximumCount <= 0) ||
100  (InitialCount < 0) ||
101  (InitialCount > MaximumCount))
102  {
103  DPRINT("Invalid Count Data!\n");
105  }
106 
107  /* Create the Semaphore Object */
108  Status = ObCreateObject(PreviousMode,
109  ExSemaphoreObjectType,
111  PreviousMode,
112  NULL,
113  sizeof(KSEMAPHORE),
114  0,
115  0,
116  (PVOID*)&Semaphore);
117 
118  /* Check for Success */
119  if (NT_SUCCESS(Status))
120  {
121  /* Initialize it */
122  KeInitializeSemaphore(Semaphore,
123  InitialCount,
124  MaximumCount);
125 
126  /* Insert it into the Object Tree */
127  Status = ObInsertObject((PVOID)Semaphore,
128  NULL,
129  DesiredAccess,
130  0,
131  NULL,
132  &hSemaphore);
133 
134  /* Check for success */
135  if (NT_SUCCESS(Status))
136  {
137  /* Enter SEH Block for return */
138  _SEH2_TRY
139  {
140  /* Return the handle */
141  *SemaphoreHandle = hSemaphore;
142  }
144  {
145  /* Get the exception code */
146  Status = _SEH2_GetExceptionCode();
147  }
148  _SEH2_END;
149  }
150  }
151 
152  /* Return Status */
153  return Status;
154 }
155 
156 /*
157  * @implemented
158  */
159 NTSTATUS
160 NTAPI
161 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
164 {
165  HANDLE hSemaphore;
168  PAGED_CODE();
169 
170  /* Check if we were called from user-mode */
171  if (PreviousMode != KernelMode)
172  {
173  /* Enter SEH Block */
174  _SEH2_TRY
175  {
176  /* Check handle pointer */
177  ProbeForWriteHandle(SemaphoreHandle);
178  }
180  {
181  /* Return the exception code */
183  }
184  _SEH2_END;
185  }
186 
187  /* Open the Object */
188  Status = ObOpenObjectByName(ObjectAttributes,
189  ExSemaphoreObjectType,
190  PreviousMode,
191  NULL,
192  DesiredAccess,
193  NULL,
194  &hSemaphore);
195 
196  /* Check for success */
197  if (NT_SUCCESS(Status))
198  {
199  /* Enter SEH Block for return */
200  _SEH2_TRY
201  {
202  /* Return the handle */
203  *SemaphoreHandle = hSemaphore;
204  }
206  {
207  /* Get the exception code */
208  Status = _SEH2_GetExceptionCode();
209  }
210  _SEH2_END;
211  }
212 
213  /* Return Status */
214  return Status;
215 }
216 
217 /*
218  * @implemented
219  */
220 NTSTATUS
221 NTAPI
222 NtQuerySemaphore(IN HANDLE SemaphoreHandle,
223  IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
224  OUT PVOID SemaphoreInformation,
225  IN ULONG SemaphoreInformationLength,
227 {
228  PKSEMAPHORE Semaphore;
231  PAGED_CODE();
232 
233  /* Check buffers and class validity */
234  Status = DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
236  sizeof(ExSemaphoreInfoClass) /
237  sizeof(ExSemaphoreInfoClass[0]),
238  SemaphoreInformation,
239  SemaphoreInformationLength,
240  ReturnLength,
241  NULL,
242  PreviousMode);
243  if (!NT_SUCCESS(Status))
244  {
245  /* Invalid buffers */
246  DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
247  return Status;
248  }
249 
250  /* Get the Object */
251  Status = ObReferenceObjectByHandle(SemaphoreHandle,
253  ExSemaphoreObjectType,
254  PreviousMode,
255  (PVOID*)&Semaphore,
256  NULL);
257 
258  /* Check for success */
259  if (NT_SUCCESS(Status))
260  {
261  /* Entry SEH Block */
262  _SEH2_TRY
263  {
264  PSEMAPHORE_BASIC_INFORMATION BasicInfo =
265  (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
266 
267  /* Return the basic information */
268  BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
269  BasicInfo->MaximumCount = Semaphore->Limit;
270 
271  /* Return the length */
272  if (ReturnLength) *ReturnLength = sizeof(*BasicInfo);
273  }
275  {
276  /* Get the exception code */
277  Status = _SEH2_GetExceptionCode();
278  }
279  _SEH2_END;
280 
281  /* Dereference the Object */
282  ObDereferenceObject(Semaphore);
283  }
284 
285  /* Return status */
286  return Status;
287 }
288 
289 /*
290  * @implemented
291  */
292 NTSTATUS
293 NTAPI
294 NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
295  IN LONG ReleaseCount,
296  OUT PLONG PreviousCount OPTIONAL)
297 {
299  PKSEMAPHORE Semaphore;
301  PAGED_CODE();
302 
303  /* Check if we were called from user-mode */
304  if ((PreviousCount) && (PreviousMode != KernelMode))
305  {
306  /* Entry SEH Block */
307  _SEH2_TRY
308  {
309  /* Make sure the state pointer is valid */
310  ProbeForWriteLong(PreviousCount);
311  }
313  {
314  /* Return the exception code */
316  }
317  _SEH2_END;
318  }
319 
320  /* Make sure count makes sense */
321  if (ReleaseCount <= 0)
322  {
323  DPRINT("Invalid Release Count\n");
325  }
326 
327  /* Get the Object */
328  Status = ObReferenceObjectByHandle(SemaphoreHandle,
330  ExSemaphoreObjectType,
331  PreviousMode,
332  (PVOID*)&Semaphore,
333  NULL);
334 
335  /* Check for success */
336  if (NT_SUCCESS(Status))
337  {
338  /* Enter SEH Block */
339  _SEH2_TRY
340  {
341  /* Release the semaphore */
342  LONG PrevCount = KeReleaseSemaphore(Semaphore,
344  ReleaseCount,
345  FALSE);
346 
347  /* Return the old count if requested */
348  if (PreviousCount) *PreviousCount = PrevCount;
349  }
351  {
352  /* Get the exception code */
353  Status = _SEH2_GetExceptionCode();
354  }
355  _SEH2_END;
356 
357  /* Dereference the Semaphore */
358  ObDereferenceObject(Semaphore);
359  }
360 
361  /* Return Status */
362  return Status;
363 }
364 
365 /* EOF */
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2522
DWORD *typedef PVOID
Definition: winlogon.h:52
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define IN
Definition: typedefs.h:38
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1034
#define TRUE
Definition: types.h:120
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
Definition: bidi.c:75
#define ProbeForWriteLong(Ptr)
Definition: probe.h:37
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
BOOLEAN INIT_FUNCTION NTAPI ExpInitializeSemaphoreImplementation(VOID)
Definition: sem.c:43
#define OBJ_OPENLINK
Definition: winternl.h:230
#define SEMAPHORE_MODIFY_STATE
Definition: winbase.h:159
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:2740
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:267
#define SEMAPHORE_QUERY_STATE
Definition: security.c:60
IN POBJECT_ATTRIBUTES PortAttributes IN ACCESS_MASK DesiredAccess
Definition: creport.c:28
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:388
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
LONG Limit
Definition: ketypes.h:790
#define _SEH2_END
Definition: pseh2_64.h:7
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:557
void DPRINT(...)
Definition: polytest.cpp:61
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[]
Definition: sem.c:32
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:938
unsigned char BOOLEAN
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
GENERIC_MAPPING ExSemaphoreMapping
Definition: sem.c:24
VOID NTAPI KeInitializeSemaphore(IN PKSEMAPHORE Semaphore, IN LONG Count, IN LONG Limit)
Definition: semphobj.c:22
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
NTSTATUS NTAPI NtReleaseSemaphore(IN HANDLE SemaphoreHandle, IN LONG ReleaseCount, OUT PLONG PreviousCount OPTIONAL)
Definition: sem.c:294
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
#define PAGED_CODE()
Definition: video.h:57
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI NtOpenSemaphore(OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: sem.c:161
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
enum _SEMAPHORE_INFORMATION_CLASS SEMAPHORE_INFORMATION_CLASS
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:411
static __inline NTSTATUS DefaultQueryInfoBufferCheck(ULONG Class, const INFORMATION_CLASS_INFO *ClassList, ULONG ClassListEntries, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength, PULONG_PTR ReturnLengthPtr, KPROCESSOR_MODE PreviousMode)
Definition: probe.h:59
struct _KSEMAPHORE KSEMAPHORE
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define SYNCHRONIZE
Definition: nt_native.h:61
Status
Definition: gdiplustypes.h:24
DWORD *typedef HANDLE
Definition: winlogon.h:52
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2925
LONG NTSTATUS
Definition: DriverTester.h:11
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:325
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
NTSTATUS NTAPI NtQuerySemaphore(IN HANDLE SemaphoreHandle, IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, OUT PVOID SemaphoreInformation, IN ULONG SemaphoreInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: sem.c:222
LONG NTAPI KeReadStateSemaphore(IN PKSEMAPHORE Semaphore)
Definition: semphobj.c:41
#define _SEH2_TRY
Definition: pseh2_64.h:5
unsigned int * PULONG
Definition: retypes.h:1
*Count PHARDWARE_COUNTER _In_ ULONG MaximumCount
Definition: kefuncs.h:1460
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:565
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
signed int * PLONG
Definition: retypes.h:5
struct _SEMAPHORE_BASIC_INFORMATION * PSEMAPHORE_BASIC_INFORMATION
#define SEMAPHORE_ALL_ACCESS
Definition: winbase.h:158
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
ULONG ACCESS_MASK
Definition: nt_native.h:40
NTSTATUS NTAPI NtCreateSemaphore(OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN LONG InitialCount, IN LONG MaximumCount)
Definition: sem.c:69
POBJECT_TYPE ExSemaphoreObjectType
Definition: sem.c:22
#define INIT_FUNCTION
Definition: ntoskrnl.h:11