/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/sem.c
- * PURPOSE: Synchronization primitives
- *
- * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
- * David Welch (welch@mcmail.com)
+ * PURPOSE: Semaphore Implementation
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * Thomas Weidenmueller
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <internal/debug.h>
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ExpInitializeSemaphoreImplementation()
+#endif
+
/* GLOBALS ******************************************************************/
POBJECT_TYPE ExSemaphoreObjectType;
-static GENERIC_MAPPING ExSemaphoreMapping = {
+GENERIC_MAPPING ExSemaphoreMapping =
+{
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
- SEMAPHORE_ALL_ACCESS};
+ SEMAPHORE_ALL_ACCESS
+};
-static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
-
+static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
+{
/* SemaphoreBasicInformation */
- ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+ ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
};
-VOID
+/* FUNCTIONS *****************************************************************/
+
+VOID
INIT_FUNCTION
+NTAPI
ExpInitializeSemaphoreImplementation(VOID)
{
-
- /* Create the Semaphore Object */
- ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
- RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
- ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
- ExSemaphoreObjectType->PeakObjects = 0;
- ExSemaphoreObjectType->PeakHandles = 0;
- ExSemaphoreObjectType->TotalObjects = 0;
- ExSemaphoreObjectType->TotalHandles = 0;
- ExSemaphoreObjectType->PagedPoolCharge = 0;
- ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
- ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
- ExSemaphoreObjectType->Dump = NULL;
- ExSemaphoreObjectType->Open = NULL;
- ExSemaphoreObjectType->Close = NULL;
- ExSemaphoreObjectType->Delete = NULL;
- ExSemaphoreObjectType->Parse = NULL;
- ExSemaphoreObjectType->Security = NULL;
- ExSemaphoreObjectType->QueryName = NULL;
- ExSemaphoreObjectType->OkayToClose = NULL;
- ExSemaphoreObjectType->Create = NULL;
- ExSemaphoreObjectType->DuplicationNotify = NULL;
- ObpCreateTypeObject(ExSemaphoreObjectType);
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
+ DPRINT("Creating Semaphore Object Type\n");
+
+ /* Create the Event Pair Object Type */
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Semaphore");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KSEMAPHORE);
+ ObjectTypeInitializer.GenericMapping = ExSemaphoreMapping;
+ ObjectTypeInitializer.PoolType = NonPagedPool;
+ ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
+ ObjectTypeInitializer.ValidAccessMask = SEMAPHORE_ALL_ACCESS;
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExSemaphoreObjectType);
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS
+NTAPI
NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN LONG InitialCount,
IN LONG MaximumCount)
{
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
-
PAGED_CODE();
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(SemaphoreHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
+ /* Check if we were called from user-mode */
+ if(PreviousMode != KernelMode)
+ {
+ /* Enter SEH Block */
+ _SEH_TRY
+ {
+ /* Check handle pointer */
+ ProbeForWriteHandle(SemaphoreHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
-
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
if(!NT_SUCCESS(Status)) return Status;
}
-
+
/* Make sure the counts make sense */
- if (!MaximumCount || !InitialCount || InitialCount > MaximumCount) {
-
+ if ((MaximumCount <= 0) ||
+ (InitialCount < 0) ||
+ (InitialCount > MaximumCount))
+ {
DPRINT("Invalid Count Data!\n");
return STATUS_INVALID_PARAMETER;
}
0,
0,
(PVOID*)&Semaphore);
-
+
/* Check for Success */
- if (NT_SUCCESS(Status)) {
-
+ if (NT_SUCCESS(Status))
+ {
/* Initialize it */
KeInitializeSemaphore(Semaphore,
InitialCount,
MaximumCount);
-
+
/* Insert it into the Object Tree */
Status = ObInsertObject((PVOID)Semaphore,
NULL,
&hSemaphore);
ObDereferenceObject(Semaphore);
- /* Check for success and return handle */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
+ /* Check for success */
+ if(NT_SUCCESS(Status))
+ {
+ /* Enter SEH Block for return */
+ _SEH_TRY
+ {
+ /* Return the handle */
*SemaphoreHandle = hSemaphore;
-
- } _SEH_HANDLE {
-
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ }
+ _SEH_END;
}
}
return Status;
}
-
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS
+NTAPI
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
-
PAGED_CODE();
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(SemaphoreHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
+ /* Check if we were called from user-mode */
+ if(PreviousMode != KernelMode)
+ {
+ /* Enter SEH Block */
+ _SEH_TRY
+ {
+ /* Check handle pointer */
+ ProbeForWriteHandle(SemaphoreHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
-
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
if(!NT_SUCCESS(Status)) return Status;
}
-
+
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExSemaphoreObjectType,
DesiredAccess,
NULL,
&hSemaphore);
-
- /* Check for success and return handle */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
+
+ /* Check for success */
+ if(NT_SUCCESS(Status))
+ {
+ /* Enter SEH Block for return */
+ _SEH_TRY
+ {
+ /* Return the handle */
*SemaphoreHandle = hSemaphore;
-
- } _SEH_HANDLE {
-
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ }
+ _SEH_END;
}
/* Return Status */
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
OUT PVOID SemaphoreInformation,
{
PKSEMAPHORE Semaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
NTSTATUS Status = STATUS_SUCCESS;
-
PAGED_CODE();
-
+
/* Check buffers and class validity */
- DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
- ExSemaphoreInfoClass,
- SemaphoreInformation,
- SemaphoreInformationLength,
- ReturnLength,
- PreviousMode,
- &Status);
- if(!NT_SUCCESS(Status)) {
-
+ Status = DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
+ ExSemaphoreInfoClass,
+ sizeof(ExSemaphoreInfoClass) /
+ sizeof(ExSemaphoreInfoClass[0]),
+ SemaphoreInformation,
+ SemaphoreInformationLength,
+ ReturnLength,
+ PreviousMode);
+ if(!NT_SUCCESS(Status))
+ {
/* Invalid buffers */
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status;
}
-
+
/* Get the Object */
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_QUERY_STATE,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
-
+
/* Check for success */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
- /* Return the basic information */
+ if(NT_SUCCESS(Status))
+ {
+ /* Entry SEH Block */
+ _SEH_TRY
+ {
+ PSEMAPHORE_BASIC_INFORMATION BasicInfo =
+ (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
+
+ /* Return the basic information */
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
BasicInfo->MaximumCount = Semaphore->Limit;
- /* Return length */
- if(ReturnLength) *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
-
- } _SEH_HANDLE {
-
+ /* Return the length */
+ if(ReturnLength) *ReturnLength = sizeof(*BasicInfo);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
-
+ }
+ _SEH_END;
+
/* Dereference the Object */
ObDereferenceObject(Semaphore);
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS
+NTAPI
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
IN LONG ReleaseCount,
- OUT PLONG PreviousCount OPTIONAL)
+ OUT PLONG PreviousCount OPTIONAL)
{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PKSEMAPHORE Semaphore;
- NTSTATUS Status = STATUS_SUCCESS;
-
+ NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
- /* Check buffer validity */
- if(PreviousCount != NULL && PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(PreviousCount,
- sizeof(LONG),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
+ /* Check if we were called from user-mode */
+ if((PreviousCount) && (PreviousMode != KernelMode))
+ {
+ /* Entry SEH Block */
+ _SEH_TRY
+ {
+ /* Make sure the state pointer is valid */
+ ProbeForWriteLong(PreviousCount);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ }
+ _SEH_END;
+ /* Bail out if pointer was invalid */
if(!NT_SUCCESS(Status)) return Status;
}
-
+
/* Make sure count makes sense */
- if (!ReleaseCount) {
-
+ if (ReleaseCount <= 0)
+ {
DPRINT("Invalid Release Count\n");
return STATUS_INVALID_PARAMETER;
}
-
+
/* Get the Object */
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_MODIFY_STATE,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
-
+
/* Check for success */
- if (NT_SUCCESS(Status)) {
-
- /* Release the semaphore */
- LONG PrevCount = KeReleaseSemaphore(Semaphore,
- IO_NO_INCREMENT,
- ReleaseCount,
- FALSE);
- ObDereferenceObject(Semaphore);
-
- /* Return it */
- if(PreviousCount) {
-
- _SEH_TRY {
-
- *PreviousCount = PrevCount;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ if (NT_SUCCESS(Status))
+ {
+ /* Enter SEH Block */
+ _SEH_TRY
+ {
+ /* Release the semaphore */
+ LONG PrevCount = KeReleaseSemaphore(Semaphore,
+ IO_NO_INCREMENT,
+ ReleaseCount,
+ FALSE);
+ ObDereferenceObject(Semaphore);
+
+ /* Return the old count if requested */
+ if(PreviousCount) *PreviousCount = PrevCount;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
}
/* Return Status */