-/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/sem.c
- * PURPOSE: Synchronization primitives
- *
- * PROGRAMMERS: David Welch (welch@mcmail.com)
+ * PURPOSE: Semaphore Implementation
+ *
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
POBJECT_TYPE ExSemaphoreObjectType;
-static 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};
-
-static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
+static GENERIC_MAPPING ExSemaphoreMapping =
{
- ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
+ STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
+ STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
+ STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
+ SEMAPHORE_ALL_ACCESS
};
-/* FUNCTIONS *****************************************************************/
-
-NTSTATUS STDCALL
-ExpCreateSemaphore(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
+static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
{
- DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
-
- if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
-
- return(STATUS_SUCCESS);
-}
+ /* SemaphoreBasicInformation */
+ ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+};
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+STDCALL
ExpInitializeSemaphoreImplementation(VOID)
{
- 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 = ExpCreateSemaphore;
- 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
+STDCALL
NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
- IN LONG InitialCount,
- IN LONG MaximumCount)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN LONG InitialCount,
+ IN LONG MaximumCount)
{
- PKSEMAPHORE Semaphore;
- HANDLE hSemaphore;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode == UserMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(SemaphoreHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
+ PKSEMAPHORE Semaphore;
+ HANDLE hSemaphore;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ /* Check Output Safety */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(SemaphoreHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status)) return Status;
+ }
- Status = ObCreateObject(PreviousMode,
- ExSemaphoreObjectType,
- ObjectAttributes,
- PreviousMode,
- NULL,
- sizeof(KSEMAPHORE),
- 0,
- 0,
- (PVOID*)&Semaphore);
- if (NT_SUCCESS(Status))
- {
- KeInitializeSemaphore(Semaphore,
- InitialCount,
- MaximumCount);
-
- Status = ObInsertObject ((PVOID)Semaphore,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &hSemaphore);
-
- ObDereferenceObject(Semaphore);
-
- if(NT_SUCCESS(Status))
- {
- _SEH_TRY
- {
- *SemaphoreHandle = hSemaphore;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
- }
+ /* Make sure the counts make sense */
+ if (MaximumCount <= 0 || InitialCount < 0 || InitialCount > MaximumCount)
+ {
+ DPRINT("Invalid Count Data!\n");
+ return STATUS_INVALID_PARAMETER;
+ }
- return Status;
-}
+ /* Create the Semaphore Object */
+ Status = ObCreateObject(PreviousMode,
+ ExSemaphoreObjectType,
+ ObjectAttributes,
+ PreviousMode,
+ NULL,
+ sizeof(KSEMAPHORE),
+ 0,
+ 0,
+ (PVOID*)&Semaphore);
+
+ /* Check for Success */
+ if (NT_SUCCESS(Status))
+ {
+ /* Initialize it */
+ KeInitializeSemaphore(Semaphore,
+ InitialCount,
+ MaximumCount);
+
+ /* Insert it into the Object Tree */
+ Status = ObInsertObject((PVOID)Semaphore,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &hSemaphore);
+ ObDereferenceObject(Semaphore);
+
+ /* Check for success and return handle */
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *SemaphoreHandle = hSemaphore;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ }
+ /* Return Status */
+ return Status;
+}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- HANDLE hSemaphore;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode == UserMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(SemaphoreHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- Status = ObOpenObjectByName(ObjectAttributes,
- ExSemaphoreObjectType,
- NULL,
- PreviousMode,
- DesiredAccess,
- NULL,
- &hSemaphore);
- if(NT_SUCCESS(Status))
- {
- _SEH_TRY
- {
- *SemaphoreHandle = hSemaphore;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
-
- return Status;
-}
+ HANDLE hSemaphore;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+ /* Check Output Safety */
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(SemaphoreHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Open the Object */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExSemaphoreObjectType,
+ NULL,
+ PreviousMode,
+ DesiredAccess,
+ NULL,
+ &hSemaphore);
+
+ /* Check for success and return handle */
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *SemaphoreHandle = hSemaphore;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+ }
+
+ /* Return Status */
+ return Status;
+}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
- IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
- OUT PVOID SemaphoreInformation,
- IN ULONG SemaphoreInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
+ IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
+ OUT PVOID SemaphoreInformation,
+ IN ULONG SemaphoreInformationLength,
+ OUT PULONG ReturnLength OPTIONAL)
{
- PKSEMAPHORE Semaphore;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
- ExSemaphoreInfoClass,
- SemaphoreInformation,
- SemaphoreInformationLength,
- ReturnLength,
- PreviousMode,
- &Status);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
- return Status;
- }
+ PKSEMAPHORE Semaphore;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ /* Check buffers and class validity */
+ 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;
+ }
- Status = ObReferenceObjectByHandle(SemaphoreHandle,
- SEMAPHORE_QUERY_STATE,
- ExSemaphoreObjectType,
- PreviousMode,
- (PVOID*)&Semaphore,
- NULL);
- if(NT_SUCCESS(Status))
- {
- switch(SemaphoreInformationClass)
- {
- case SemaphoreBasicInformation:
- {
- PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
-
- _SEH_TRY
- {
- BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
- BasicInfo->MaximumCount = Semaphore->Limit;
-
- if(ReturnLength != NULL)
- {
- *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
+ /* Get the Object */
+ Status = ObReferenceObjectByHandle(SemaphoreHandle,
+ SEMAPHORE_QUERY_STATE,
+ ExSemaphoreObjectType,
+ PreviousMode,
+ (PVOID*)&Semaphore,
+ NULL);
+
+ /* Check for success */
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
+
+ /* Return the basic information */
+ BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
+ BasicInfo->MaximumCount = Semaphore->Limit;
- default:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
- }
+ /* Return length */
+ if(ReturnLength) *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
- ObDereferenceObject(Semaphore);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
+
+ /* Dereference the Object */
+ ObDereferenceObject(Semaphore);
}
+ /* Return status */
return Status;
}
-
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
- IN LONG ReleaseCount,
- OUT PLONG PreviousCount OPTIONAL)
+ IN LONG ReleaseCount,
+ OUT PLONG PreviousCount OPTIONAL)
{
- KPROCESSOR_MODE PreviousMode;
- PKSEMAPHORE Semaphore;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousCount != NULL && PreviousMode == UserMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(PreviousCount,
- sizeof(LONG),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- Status = ObReferenceObjectByHandle(SemaphoreHandle,
- SEMAPHORE_MODIFY_STATE,
- ExSemaphoreObjectType,
- PreviousMode,
- (PVOID*)&Semaphore,
- NULL);
- if (NT_SUCCESS(Status))
- {
- LONG PrevCount = KeReleaseSemaphore(Semaphore,
- IO_NO_INCREMENT,
- ReleaseCount,
- FALSE);
- ObDereferenceObject(Semaphore);
-
- if(PreviousCount != NULL)
- {
- _SEH_TRY
- {
- *PreviousCount = PrevCount;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
- }
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PKSEMAPHORE Semaphore;
+ NTSTATUS Status = STATUS_SUCCESS;
- return Status;
+ PAGED_CODE();
+
+ /* Check buffer validity */
+ if(PreviousCount && PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteLong(PreviousCount);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Make sure count makes sense */
+ if (ReleaseCount <= 0)
+ {
+ DPRINT("Invalid Release Count\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Get the Object */
+ Status = ObReferenceObjectByHandle(SemaphoreHandle,
+ SEMAPHORE_MODIFY_STATE,
+ ExSemaphoreObjectType,
+ PreviousMode,
+ (PVOID*)&Semaphore,
+ NULL);
+
+ /* Check for success */
+ if (NT_SUCCESS(Status))
+ {
+ /* Release the semaphore */
+ _SEH_TRY
+ {
+ 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 */
+ return Status;
}
/* EOF */