ReactOS  0.4.15-dev-2320-gf3e1697
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 /* GLOBALS ******************************************************************/
17 
19 
21 {
26 };
27 
28 static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
29 {
30  /* SemaphoreBasicInformation */
31  ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
32 };
33 
34 /* FUNCTIONS *****************************************************************/
35 
36 CODE_SEG("INIT")
37 BOOLEAN
38 NTAPI
40 {
41  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
44  DPRINT("Creating Semaphore Object Type\n");
45 
46  /* Create the Event Pair Object Type */
47  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
48  RtlInitUnicodeString(&Name, L"Semaphore");
49  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
50  ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KSEMAPHORE);
51  ObjectTypeInitializer.GenericMapping = ExSemaphoreMapping;
52  ObjectTypeInitializer.PoolType = NonPagedPool;
53  ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
54  ObjectTypeInitializer.ValidAccessMask = SEMAPHORE_ALL_ACCESS;
55  Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExSemaphoreObjectType);
56  if (!NT_SUCCESS(Status)) return FALSE;
57  return TRUE;
58 }
59 
60 /*
61  * @implemented
62  */
64 NTAPI
65 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
68  IN LONG InitialCount,
70 {
71  PKSEMAPHORE Semaphore;
72  HANDLE hSemaphore;
75  PAGED_CODE();
76 
77  /* Check if we were called from user-mode */
78  if (PreviousMode != KernelMode)
79  {
80  /* Enter SEH Block */
81  _SEH2_TRY
82  {
83  /* Check handle pointer */
84  ProbeForWriteHandle(SemaphoreHandle);
85  }
87  {
88  /* Return the exception code */
90  }
91  _SEH2_END;
92  }
93 
94  /* Make sure the counts make sense */
95  if ((MaximumCount <= 0) ||
96  (InitialCount < 0) ||
97  (InitialCount > MaximumCount))
98  {
99  DPRINT("Invalid Count Data!\n");
101  }
102 
103  /* Create the Semaphore Object */
107  PreviousMode,
108  NULL,
109  sizeof(KSEMAPHORE),
110  0,
111  0,
112  (PVOID*)&Semaphore);
113 
114  /* Check for Success */
115  if (NT_SUCCESS(Status))
116  {
117  /* Initialize it */
118  KeInitializeSemaphore(Semaphore,
119  InitialCount,
120  MaximumCount);
121 
122  /* Insert it into the Object Tree */
123  Status = ObInsertObject((PVOID)Semaphore,
124  NULL,
126  0,
127  NULL,
128  &hSemaphore);
129 
130  /* Check for success */
131  if (NT_SUCCESS(Status))
132  {
133  /* Enter SEH Block for return */
134  _SEH2_TRY
135  {
136  /* Return the handle */
137  *SemaphoreHandle = hSemaphore;
138  }
140  {
141  /* Get the exception code */
143  }
144  _SEH2_END;
145  }
146  }
147 
148  /* Return Status */
149  return Status;
150 }
151 
152 /*
153  * @implemented
154  */
155 NTSTATUS
156 NTAPI
157 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
160 {
161  HANDLE hSemaphore;
164  PAGED_CODE();
165 
166  /* Check if we were called from user-mode */
167  if (PreviousMode != KernelMode)
168  {
169  /* Enter SEH Block */
170  _SEH2_TRY
171  {
172  /* Check handle pointer */
173  ProbeForWriteHandle(SemaphoreHandle);
174  }
176  {
177  /* Return the exception code */
179  }
180  _SEH2_END;
181  }
182 
183  /* Open the Object */
186  PreviousMode,
187  NULL,
189  NULL,
190  &hSemaphore);
191 
192  /* Check for success */
193  if (NT_SUCCESS(Status))
194  {
195  /* Enter SEH Block for return */
196  _SEH2_TRY
197  {
198  /* Return the handle */
199  *SemaphoreHandle = hSemaphore;
200  }
202  {
203  /* Get the exception code */
205  }
206  _SEH2_END;
207  }
208 
209  /* Return Status */
210  return Status;
211 }
212 
213 /*
214  * @implemented
215  */
216 NTSTATUS
217 NTAPI
218 NtQuerySemaphore(IN HANDLE SemaphoreHandle,
219  IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
220  OUT PVOID SemaphoreInformation,
221  IN ULONG SemaphoreInformationLength,
223 {
224  PKSEMAPHORE Semaphore;
227  PAGED_CODE();
228 
229  /* Check buffers and class validity */
230  Status = DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
232  sizeof(ExSemaphoreInfoClass) /
233  sizeof(ExSemaphoreInfoClass[0]),
234  SemaphoreInformation,
235  SemaphoreInformationLength,
236  ReturnLength,
237  NULL,
238  PreviousMode);
239  if (!NT_SUCCESS(Status))
240  {
241  /* Invalid buffers */
242  DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
243  return Status;
244  }
245 
246  /* Get the Object */
247  Status = ObReferenceObjectByHandle(SemaphoreHandle,
250  PreviousMode,
251  (PVOID*)&Semaphore,
252  NULL);
253 
254  /* Check for success */
255  if (NT_SUCCESS(Status))
256  {
257  /* Entry SEH Block */
258  _SEH2_TRY
259  {
260  PSEMAPHORE_BASIC_INFORMATION BasicInfo =
261  (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
262 
263  /* Return the basic information */
264  BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
265  BasicInfo->MaximumCount = Semaphore->Limit;
266 
267  /* Return the length */
268  if (ReturnLength) *ReturnLength = sizeof(*BasicInfo);
269  }
271  {
272  /* Get the exception code */
274  }
275  _SEH2_END;
276 
277  /* Dereference the Object */
278  ObDereferenceObject(Semaphore);
279  }
280 
281  /* Return status */
282  return Status;
283 }
284 
285 /*
286  * @implemented
287  */
288 NTSTATUS
289 NTAPI
290 NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
291  IN LONG ReleaseCount,
292  OUT PLONG PreviousCount OPTIONAL)
293 {
295  PKSEMAPHORE Semaphore;
297  PAGED_CODE();
298 
299  /* Check if we were called from user-mode */
300  if ((PreviousCount) && (PreviousMode != KernelMode))
301  {
302  /* Entry SEH Block */
303  _SEH2_TRY
304  {
305  /* Make sure the state pointer is valid */
306  ProbeForWriteLong(PreviousCount);
307  }
309  {
310  /* Return the exception code */
312  }
313  _SEH2_END;
314  }
315 
316  /* Make sure count makes sense */
317  if (ReleaseCount <= 0)
318  {
319  DPRINT("Invalid Release Count\n");
321  }
322 
323  /* Get the Object */
324  Status = ObReferenceObjectByHandle(SemaphoreHandle,
327  PreviousMode,
328  (PVOID*)&Semaphore,
329  NULL);
330 
331  /* Check for success */
332  if (NT_SUCCESS(Status))
333  {
334  /* Enter SEH Block */
335  _SEH2_TRY
336  {
337  /* Release the semaphore */
338  LONG PrevCount = KeReleaseSemaphore(Semaphore,
340  ReleaseCount,
341  FALSE);
342 
343  /* Return the old count if requested */
344  if (PreviousCount) *PreviousCount = PrevCount;
345  }
347  {
348  /* Get the exception code */
350  }
351  _SEH2_END;
352 
353  /* Dereference the Semaphore */
354  ObDereferenceObject(Semaphore);
355  }
356 
357  /* Return Status */
358  return Status;
359 }
360 
361 /* EOF */
#define OBJ_OPENLINK
Definition: winternl.h:230
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:2529
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:39
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1048
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define ProbeForWriteLong(Ptr)
Definition: probe.h:37
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
#define SEMAPHORE_MODIFY_STATE
Definition: winbase.h:161
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
#define SEMAPHORE_QUERY_STATE
Definition: security.c:57
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67
_SEH2_TRY
Definition: create.c:4226
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:496
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
struct NameRec_ * Name
Definition: cdprocs.h:459
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[]
Definition: sem.c:28
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:952
Status
Definition: gdiplustypes.h:24
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
GENERIC_MAPPING ExSemaphoreMapping
Definition: sem.c:20
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:32
NTSTATUS NTAPI NtReleaseSemaphore(IN HANDLE SemaphoreHandle, IN LONG ReleaseCount, OUT PLONG PreviousCount OPTIONAL)
Definition: sem.c:290
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI NtOpenSemaphore(OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: sem.c:157
static const WCHAR L[]
Definition: oid.c:1250
enum _SEMAPHORE_INFORMATION_CLASS SEMAPHORE_INFORMATION_CLASS
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
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
BOOLEAN NTAPI ExpInitializeSemaphoreImplementation(VOID)
Definition: sem.c:39
#define SYNCHRONIZE
Definition: nt_native.h:61
_SEH2_END
Definition: create.c:4400
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:2932
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:351
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:218
LONG NTAPI KeReadStateSemaphore(IN PKSEMAPHORE Semaphore)
Definition: semphobj.c:41
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
*Count PHARDWARE_COUNTER _In_ ULONG MaximumCount
Definition: kefuncs.h:1380
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define DPRINT
Definition: sndvol32.h:71
signed int * PLONG
Definition: retypes.h:5
struct _SEMAPHORE_BASIC_INFORMATION * PSEMAPHORE_BASIC_INFORMATION
#define SEMAPHORE_ALL_ACCESS
Definition: winbase.h:160
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
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:65
POBJECT_TYPE ExSemaphoreObjectType
Definition: sem.c:18
#define PAGED_CODE()
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68