- Fix some small formatting issues.
[reactos.git] / reactos / ntoskrnl / ex / mutant.c
index 0852e00..a74e762 100644 (file)
@@ -1,11 +1,10 @@
-/* $Id:$
- * 
+/*
  * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * PROJECT:         ReactOS Kernel
  * FILE:            ntoskrnl/ex/mutant.c
- * PURPOSE:         Synchronization primitives
- * 
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Executive Management of Mutants
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  Thomas Weidenmueller
  */
 
 /* INCLUDES *****************************************************************/
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ExpInitializeMutantImplementation)
+#endif
+
+/* DATA **********************************************************************/
+
 POBJECT_TYPE ExMutantObjectType = NULL;
 
-static GENERIC_MAPPING ExpMutantMapping = {
-       STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
-       STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
-       STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
-       MUTANT_ALL_ACCESS};
+GENERIC_MAPPING ExpMutantMapping =
+{
+    STANDARD_RIGHTS_READ    | SYNCHRONIZE | MUTANT_QUERY_STATE,
+    STANDARD_RIGHTS_WRITE   | SYNCHRONIZE,
+    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
+    MUTANT_ALL_ACCESS
+};
 
 static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
 {
-  ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
+     /* MutantBasicInformation */
+    ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
 };
 
 /* FUNCTIONS *****************************************************************/
 
-
-NTSTATUS STDCALL
-ExpCreateMutant(PVOID ObjectBody,
-               PVOID Parent,
-               PWSTR RemainingPath,
-               POBJECT_ATTRIBUTES ObjectAttributes)
-{
-  DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
-        ObjectBody, Parent, RemainingPath);
-
-  if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
-    {
-      return(STATUS_UNSUCCESSFUL);
-    }
-
-  return(STATUS_SUCCESS);
-}
-
-
-VOID STDCALL
+VOID
+NTAPI
 ExpDeleteMutant(PVOID ObjectBody)
 {
-  DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
+    DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
 
-  KeReleaseMutant((PKMUTANT)ObjectBody,
-                 MUTANT_INCREMENT,
-                 TRUE,
-                 FALSE);
+    /* Make sure to release the Mutant */
+    KeReleaseMutant((PKMUTANT)ObjectBody,
+                    MUTANT_INCREMENT,
+                    TRUE,
+                    FALSE);
 }
 
-
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
 ExpInitializeMutantImplementation(VOID)
 {
-  ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
-  RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
-
-  ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
-  ExMutantObjectType->PeakObjects = 0;
-  ExMutantObjectType->PeakHandles = 0;
-  ExMutantObjectType->TotalObjects = 0;
-  ExMutantObjectType->TotalHandles = 0;
-  ExMutantObjectType->PagedPoolCharge = 0;
-  ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
-  ExMutantObjectType->Mapping = &ExpMutantMapping;
-  ExMutantObjectType->Dump = NULL;
-  ExMutantObjectType->Open = NULL;
-  ExMutantObjectType->Close = NULL;
-  ExMutantObjectType->Delete = ExpDeleteMutant;
-  ExMutantObjectType->Parse = NULL;
-  ExMutantObjectType->Security = NULL;
-  ExMutantObjectType->QueryName = NULL;
-  ExMutantObjectType->OkayToClose = NULL;
-  ExMutantObjectType->Create = ExpCreateMutant;
-  ExMutantObjectType->DuplicationNotify = NULL;
-
-  ObpCreateTypeObject(ExMutantObjectType);
+    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+    UNICODE_STRING Name;
+    DPRINT("Creating Mutant Object Type\n");
+
+    /* Create the Event Pair Object Type */
+    RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+    RtlInitUnicodeString(&Name, L"Mutant");
+    ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+    ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT);
+    ObjectTypeInitializer.GenericMapping = ExpMutantMapping;
+    ObjectTypeInitializer.PoolType = NonPagedPool;
+    ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant;
+    ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS;
+    ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExMutantObjectType);
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtCreateMutant(OUT PHANDLE MutantHandle,
-              IN ACCESS_MASK DesiredAccess,
-              IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-              IN BOOLEAN InitialOwner)
+               IN ACCESS_MASK DesiredAccess,
+               IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+               IN BOOLEAN InitialOwner)
 {
-  KPROCESSOR_MODE PreviousMode;
-  HANDLE hMutant;
-  PKMUTEX Mutant;
-  NTSTATUS Status = STATUS_SUCCESS;
-  
-   PreviousMode = ExGetPreviousMode();
-
-   if(PreviousMode == UserMode)
-   {
-     _SEH_TRY
-     {
-       ProbeForWrite(MutantHandle,
-                     sizeof(HANDLE),
-                     sizeof(ULONG));
-     }
-     _SEH_HANDLE
-     {
-       Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
-     
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
-
-  Status = ObCreateObject(PreviousMode,
-                         ExMutantObjectType,
-                         ObjectAttributes,
-                         PreviousMode,
-                         NULL,
-                         sizeof(KMUTANT),
-                         0,
-                         0,
-                         (PVOID*)&Mutant);
-  if(NT_SUCCESS(Status))
-  {
-    KeInitializeMutant(Mutant,
-                      InitialOwner);
-
-    Status = ObInsertObject((PVOID)Mutant,
-                           NULL,
-                           DesiredAccess,
-                           0,
-                           NULL,
-                           &hMutant);
-    ObDereferenceObject(Mutant);
-    
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    HANDLE hMutant;
+    PKMUTANT Mutant;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PAGED_CODE();
+    DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
+            MutantHandle, DesiredAccess, ObjectAttributes);
+
+    /* Check if we were called from user-mode */
+    if(PreviousMode != KernelMode)
+    {
+        /* Enter SEH Block */
+        _SEH_TRY
+        {
+            /* Check handle pointer */
+            ProbeForWriteHandle(MutantHandle);
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Bail out if pointer was invalid */
+        if(!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Create the Mutant Object*/
+    Status = ObCreateObject(PreviousMode,
+                            ExMutantObjectType,
+                            ObjectAttributes,
+                            PreviousMode,
+                            NULL,
+                            sizeof(KMUTANT),
+                            0,
+                            0,
+                            (PVOID*)&Mutant);
+
+    /* Check for success */
     if(NT_SUCCESS(Status))
     {
-      _SEH_TRY
-      {
-        *MutantHandle = hMutant;
-      }
-      _SEH_HANDLE
-      {
-        Status = _SEH_GetExceptionCode();
-      }
-      _SEH_END;
+        /* Initalize the Kernel Mutant */
+        DPRINT("Initializing the Mutant\n");
+        KeInitializeMutant(Mutant, InitialOwner);
+
+        /* Insert the Object */
+        Status = ObInsertObject((PVOID)Mutant,
+                                NULL,
+                                DesiredAccess,
+                                0,
+                                NULL,
+                                &hMutant);
+        ObDereferenceObject(Mutant);
+
+        /* Check for success */
+        if(NT_SUCCESS(Status))
+        {
+            /* Enter SEH for return */
+            _SEH_TRY
+            {
+                /* Return the handle to the caller */
+                *MutantHandle = hMutant;
+            }
+            _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
+        }
     }
-  }
 
-  return Status;
+    /* Return Status */
+    return Status;
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtOpenMutant(OUT PHANDLE MutantHandle,
-            IN ACCESS_MASK DesiredAccess,
-            IN POBJECT_ATTRIBUTES ObjectAttributes)
+             IN ACCESS_MASK DesiredAccess,
+             IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-  HANDLE hMutant;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status = STATUS_SUCCESS;
-
-  DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
-
-  PreviousMode = ExGetPreviousMode();
-
-  if(PreviousMode == UserMode)
-  {
-    _SEH_TRY
+    HANDLE hMutant;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    PAGED_CODE();
+    DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
+            MutantHandle, DesiredAccess, ObjectAttributes);
+
+    /* Check if we were called from user-mode */
+    if(PreviousMode != KernelMode)
     {
-      ProbeForWrite(MutantHandle,
-                    sizeof(HANDLE),
-                    sizeof(ULONG));
+        /* Enter SEH Block */
+        _SEH_TRY
+        {
+            /* Check handle pointer */
+            ProbeForWriteHandle(MutantHandle);
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Bail out if pointer was invalid */
+        if(!NT_SUCCESS(Status)) return Status;
     }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
 
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-  }
-
-  Status = ObOpenObjectByName(ObjectAttributes,
-                             ExMutantObjectType,
-                             NULL,
-                             PreviousMode,
-                             DesiredAccess,
-                             NULL,
-                             &hMutant);
-
-  if(NT_SUCCESS(Status))
-  {
-    _SEH_TRY
-    {
-      *MutantHandle = hMutant;
-    }
-    _SEH_HANDLE
+    /* Open the Object */
+    Status = ObOpenObjectByName(ObjectAttributes,
+                                ExMutantObjectType,
+                                NULL,
+                                PreviousMode,
+                                DesiredAccess,
+                                NULL,
+                                &hMutant);
+
+    /* Check for success */
+    if(NT_SUCCESS(Status))
     {
-      Status = _SEH_GetExceptionCode();
+        /* Enter SEH for return */
+        _SEH_TRY
+        {
+            /* Return the handle to the caller */
+            *MutantHandle = hMutant;
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
     }
-    _SEH_END;
-  }
 
-  return Status;
+    /* Return Status */
+    return Status;
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtQueryMutant(IN HANDLE MutantHandle,
-             IN MUTANT_INFORMATION_CLASS MutantInformationClass,
-             OUT PVOID MutantInformation,
-             IN ULONG MutantInformationLength,
-             OUT PULONG ResultLength  OPTIONAL)
+              IN MUTANT_INFORMATION_CLASS MutantInformationClass,
+              OUT PVOID MutantInformation,
+              IN ULONG MutantInformationLength,
+              OUT PULONG ResultLength  OPTIONAL)
 {
-   PKMUTANT Mutant;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   PreviousMode = ExGetPreviousMode();
-
-   DefaultQueryInfoBufferCheck(MutantInformationClass,
-                               ExMutantInfoClass,
-                               MutantInformation,
-                               MutantInformationLength,
-                               ResultLength,
-                               PreviousMode,
-                               &Status);
-   if(!NT_SUCCESS(Status))
-   {
-     DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
-     return Status;
-   }
-
-   Status = ObReferenceObjectByHandle(MutantHandle,
-                                     MUTANT_QUERY_STATE,
-                                     ExMutantObjectType,
-                                     PreviousMode,
-                                     (PVOID*)&Mutant,
-                                     NULL);
-   if(NT_SUCCESS(Status))
-   {
-     switch(MutantInformationClass)
-     {
-       case MutantBasicInformation:
-       {
-         PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
+    PKMUTANT Mutant;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    PMUTANT_BASIC_INFORMATION BasicInfo =
+        (PMUTANT_BASIC_INFORMATION)MutantInformation;
+    PAGED_CODE();
+
+    /* Check buffers and parameters */
+    Status = DefaultQueryInfoBufferCheck(MutantInformationClass,
+                                         ExMutantInfoClass,
+                                         sizeof(ExMutantInfoClass) /
+                                         sizeof(ExMutantInfoClass[0]),
+                                         MutantInformation,
+                                         MutantInformationLength,
+                                         ResultLength,
+                                         PreviousMode);
+    if(!NT_SUCCESS(Status))
+    {
+        DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
+        return Status;
+    }
 
+    /* Open the Object */
+    Status = ObReferenceObjectByHandle(MutantHandle,
+                                       MUTANT_QUERY_STATE,
+                                       ExMutantObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Mutant,
+                                       NULL);
+    /* Check for Status */
+    if(NT_SUCCESS(Status))
+    {
+        /* Enter SEH Block for return */
          _SEH_TRY
          {
-           BasicInfo->Count = KeReadStateMutant(Mutant);
-           BasicInfo->Owned = (Mutant->OwnerThread != NULL);
-           BasicInfo->Abandoned = Mutant->Abandoned;
-
-           if(ResultLength != NULL)
-           {
-             *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
-           }
-         }
-         _SEH_HANDLE
-         {
-           Status = _SEH_GetExceptionCode();
-         }
-         _SEH_END;
-         break;
-       }
-
-       default:
-         Status = STATUS_NOT_IMPLEMENTED;
-         break;
-     }
-
-     ObDereferenceObject(Mutant);
-   }
+            /* Fill out the Basic Information Requested */
+            DPRINT("Returning Mutant Information\n");
+            BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
+            BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
+                                        KeGetCurrentThread());
+            BasicInfo->AbandonedState = Mutant->Abandoned;
+
+            /* Return the Result Length if requested */
+           if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Release the Object */
+        ObDereferenceObject(Mutant);
+    }
 
-   return Status;
+    /* Return Status */
+    return Status;
 }
 
-
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtReleaseMutant(IN HANDLE MutantHandle,
-               IN PLONG PreviousCount  OPTIONAL)
+                IN PLONG PreviousCount OPTIONAL)
 {
-   PKMUTANT Mutant;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
-         MutantHandle, PreviousCount);
-
-   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(MutantHandle,
-                                     MUTANT_QUERY_STATE,
-                                     ExMutantObjectType,
-                                     PreviousMode,
-                                     (PVOID*)&Mutant,
-                                     NULL);
-   if(NT_SUCCESS(Status))
-   {
-     LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
-     ObDereferenceObject(Mutant);
-
-     if(PreviousCount != NULL)
-     {
-       _SEH_TRY
-       {
-         *PreviousCount = Prev;
-       }
-       _SEH_HANDLE
-       {
-         Status = _SEH_GetExceptionCode();
-       }
-       _SEH_END;
-     }
-   }
-
-   return Status;
+    PKMUTANT Mutant;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    PAGED_CODE();
+    DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
+            MutantHandle,
+            PreviousCount);
+
+     /* 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;
+    }
+
+    /* Open the Object */
+    Status = ObReferenceObjectByHandle(MutantHandle,
+                                       MUTANT_QUERY_STATE,
+                                       ExMutantObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Mutant,
+                                       NULL);
+
+    /* Check for Success and release if such */
+    if(NT_SUCCESS(Status))
+    {
+        /*
+         * Release the mutant. doing so might raise an exception which we're
+         * required to catch!
+         */
+        _SEH_TRY
+        {
+            /* Release the mutant */
+            LONG Prev = KeReleaseMutant(Mutant,
+                                        MUTANT_INCREMENT,
+                                        FALSE,
+                                        FALSE);
+
+            /* Return the previous count if requested */
+            if(PreviousCount) *PreviousCount = Prev;
+        }
+        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        /* Dereference it */
+        ObDereferenceObject(Mutant);
+    }
+
+    /* Return Status */
+    return Status;
 }
 
 /* EOF */