- Fix some small formatting issues.
[reactos.git] / reactos / ntoskrnl / ex / sem.c
index 5a27391..11dcc29 100644 (file)
@@ -1,11 +1,10 @@
-/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * 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)
+ *                  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 = {
-       STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
-       STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
-       STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
-       SEMAPHORE_ALL_ACCESS};
+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[] =
 {
-  ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
+     /* SemaphoreBasicInformation */
+    ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
 };
 
 /* FUNCTIONS *****************************************************************/
 
-NTSTATUS STDCALL
-ExpCreateSemaphore(PVOID ObjectBody,
-                  PVOID Parent,
-                  PWSTR RemainingPath,
-                  POBJECT_ATTRIBUTES ObjectAttributes)
-{
-  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);
-}
-
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
 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
+NTAPI
 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;
-   
-   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 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;
+
+        /* Bail out if pointer was invalid */
+        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 */
+        if(NT_SUCCESS(Status))
+        {
+            /* Enter SEH Block for return */
+            _SEH_TRY
+            {
+                /* Return the handle */
+                *SemaphoreHandle = hSemaphore;
+            }
+            _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
+        }
+    }
 
+    /* Return Status */
+    return Status;
+}
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 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;
-
-   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 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;
+
+        /* Bail out if pointer was invalid */
+        if(!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Open the Object */
+    Status = ObOpenObjectByName(ObjectAttributes,
+                                ExSemaphoreObjectType,
+                                NULL,
+                                PreviousMode,
+                                DesiredAccess,
+                                NULL,
+                                &hSemaphore);
+
+    /* Check for success */
+    if(NT_SUCCESS(Status))
+    {
+        /* Enter SEH Block for return */
+        _SEH_TRY
+        {
+            /* Return the handle */
+            *SemaphoreHandle = hSemaphore;
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+    }
+
+    /* Return Status */
+    return Status;
+}
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 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;
-
-   PreviousMode = ExGetPreviousMode();
-
-   DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
-                               ExSemaphoreInfoClass,
-                               SemaphoreInformation,
-                               SemaphoreInformationLength,
-                               ReturnLength,
-                               PreviousMode,
-                               &Status);
-   if(!NT_SUCCESS(Status))
-   {
-     DPRINT1("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;
-       }
+    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;
+    }
 
-       default:
-         Status = STATUS_NOT_IMPLEMENTED;
-         break;
-     }
+    /* Get the Object */
+    Status = ObReferenceObjectByHandle(SemaphoreHandle,
+                                       SEMAPHORE_QUERY_STATE,
+                                       ExSemaphoreObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Semaphore,
+                                       NULL);
 
-     ObDereferenceObject(Semaphore);
+    /* Check for success */
+    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 the length */
+            if(ReturnLength) *ReturnLength = sizeof(*BasicInfo);
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Dereference the Object */
+        ObDereferenceObject(Semaphore);
    }
 
+   /* Return status */
    return Status;
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 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;
-   
-   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;
+    PAGED_CODE();
 
-   return Status;
+    /* 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;
+
+        /* Bail out if pointer was invalid */
+        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))
+    {
+        /* 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 */
+    return Status;
 }
 
 /* EOF */