Thomas Weidenmueller <w3seek@reactos.com>
[reactos.git] / reactos / ntoskrnl / ob / object.c
index eeef81f..d9e1580 100644 (file)
@@ -1,14 +1,12 @@
 /* $Id$
  * 
- * COPYRIGHT:     See COPYING in the top level directory
- * PROJECT:       ReactOS kernel
- * FILE:          ntoskrnl/ob/object.c
- * PURPOSE:       Implements generic object managment functions
- * PROGRAMMERS    David Welch (welch@cwcom.net), Skywing (skywing@valhallalegends.com)
- * UPDATE HISTORY:
- *               10/06/98: Created
- *               09/13/03: Fixed various ObXxx routines to not call retention
- *                         checks directly at a raised IRQL.
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ob/object.c
+ * PURPOSE:         Implements generic object managment functions
+ * 
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ *                  Skywing (skywing@valhallalegends.com)
  */
 
 /* INCLUDES *****************************************************************/
@@ -49,24 +47,16 @@ ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
 {
   OBJECT_ATTRIBUTES AttributesCopy;
   NTSTATUS Status = STATUS_SUCCESS;
-  
+
   /* at least one output parameter must be != NULL! */
-  ASSERT((ULONG_PTR)CapturedObjectAttributes ^ (ULONG_PTR)ObjectName != 0);
-  
+  ASSERT(CapturedObjectAttributes != NULL || ObjectName != NULL);
+
   if(ObjectAttributes == NULL)
   {
-failbasiccleanup:
-    if(ObjectName != NULL)
-    {
-      RtlInitUnicodeString(ObjectName, NULL);
-    }
-    if(CapturedObjectAttributes != NULL)
-    {
-      RtlZeroMemory(CapturedObjectAttributes, sizeof(CAPTURED_OBJECT_ATTRIBUTES));
-    }
-    return Status; /* STATUS_SUCCESS */
+    /* we're going to return STATUS_SUCCESS! */
+    goto failbasiccleanup;
   }
-  
+
   if(AccessMode != KernelMode)
   {
     _SEH_TRY
@@ -82,27 +72,37 @@ failbasiccleanup:
       Status = _SEH_GetExceptionCode();
     }
     _SEH_END;
-    
+
     if(!NT_SUCCESS(Status))
     {
-      return Status;
+      DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
+      goto failbasiccleanup;
     }
   }
-  else if(AccessMode == KernelMode && !CaptureIfKernel)
+  else if(!CaptureIfKernel)
   {
-    if(ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))
+    if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
     {
-      /* we don't have to capture any memory, the caller considers the passed data
-         as valid */
       if(ObjectName != NULL)
       {
-        *ObjectName = *ObjectAttributes->ObjectName;
+        /* we don't have to capture any memory, the caller considers the passed data
+           as valid */
+        if(ObjectAttributes->ObjectName != NULL)
+        {
+          *ObjectName = *ObjectAttributes->ObjectName;
+        }
+        else
+        {
+          ObjectName->Length = ObjectName->MaximumLength = 0;
+          ObjectName->Buffer = NULL;
+        }
       }
       if(CapturedObjectAttributes != NULL)
       {
         CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory;
         CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes;
         CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
+        CapturedObjectAttributes->SecurityQualityOfService = ObjectAttributes->SecurityQualityOfService;
       }
 
       return STATUS_SUCCESS;
@@ -117,7 +117,7 @@ failbasiccleanup:
   {
     AttributesCopy = *ObjectAttributes;
   }
-  
+
   /* if Length isn't as expected, bail with an invalid parameter status code so
      the caller knows he passed garbage... */
   if(AttributesCopy.Length != sizeof(OBJECT_ATTRIBUTES))
@@ -125,7 +125,7 @@ failbasiccleanup:
     Status = STATUS_INVALID_PARAMETER;
     goto failbasiccleanup;
   }
-  
+
   if(CapturedObjectAttributes != NULL)
   {
     CapturedObjectAttributes->RootDirectory = AttributesCopy.RootDirectory;
@@ -148,14 +148,61 @@ failbasiccleanup:
     {
       CapturedObjectAttributes->SecurityDescriptor = NULL;
     }
+
+    if(AttributesCopy.SecurityQualityOfService != NULL)
+    {
+      SECURITY_QUALITY_OF_SERVICE SafeQoS;
+
+      _SEH_TRY
+      {
+        ProbeForRead(AttributesCopy.SecurityQualityOfService,
+                     sizeof(SECURITY_QUALITY_OF_SERVICE),
+                     sizeof(ULONG));
+        SafeQoS = *(PSECURITY_QUALITY_OF_SERVICE)AttributesCopy.SecurityQualityOfService;
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+
+      if(!NT_SUCCESS(Status))
+      {
+        DPRINT1("Unable to capture QoS!!!\n");
+        goto failcleanupsdescriptor;
+      }
+
+      if(SafeQoS.Length != sizeof(SECURITY_QUALITY_OF_SERVICE))
+      {
+        DPRINT1("Unable to capture QoS, wrong size!!!\n");
+        Status = STATUS_INVALID_PARAMETER;
+        goto failcleanupsdescriptor;
+      }
+
+      CapturedObjectAttributes->SecurityQualityOfService = ExAllocatePool(PoolType,
+                                                                          sizeof(SECURITY_QUALITY_OF_SERVICE));
+      if(CapturedObjectAttributes->SecurityQualityOfService != NULL)
+      {
+        *CapturedObjectAttributes->SecurityQualityOfService = SafeQoS;
+      }
+      else
+      {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto failcleanupsdescriptor;
+      }
+    }
+    else
+    {
+      CapturedObjectAttributes->SecurityQualityOfService = NULL;
+    }
   }
-  
+
   if(ObjectName != NULL)
   {
     if(AttributesCopy.ObjectName != NULL)
     {
       UNICODE_STRING OriginalCopy;
-      
+
       if(AccessMode != KernelMode)
       {
         _SEH_TRY
@@ -169,7 +216,7 @@ failbasiccleanup:
           {
             ProbeForRead(OriginalCopy.Buffer,
                          OriginalCopy.Length,
-                         sizeof(ULONG));
+                         sizeof(WCHAR));
           }
         }
         _SEH_HANDLE
@@ -177,7 +224,7 @@ failbasiccleanup:
           Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
-        
+
         if(NT_SUCCESS(Status))
         {
           if(OriginalCopy.Length > 0)
@@ -199,6 +246,11 @@ failbasiccleanup:
                 Status = _SEH_GetExceptionCode();
               }
               _SEH_END;
+
+              if(!NT_SUCCESS(Status))
+              {
+                DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n");
+              }
             }
             else
             {
@@ -211,29 +263,15 @@ failbasiccleanup:
             Status = STATUS_OBJECT_NAME_INVALID;
           }
         }
-
-        /* handle failure */
-        if(!NT_SUCCESS(Status))
+        else
         {
-failallocatedcleanup:
-          if(ObjectName->Buffer)
-          {
-            ExFreePool(ObjectName->Buffer);
-          }
-          if(CapturedObjectAttributes != NULL)
-          {
-            /* cleanup allocated resources */
-            SeReleaseSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor,
-                                        AccessMode,
-                                        TRUE);
-          }
-          goto failbasiccleanup;
+          DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n");
         }
       }
       else /* AccessMode == KernelMode */
       {
         OriginalCopy = *AttributesCopy.ObjectName;
-        
+
         if(OriginalCopy.Length > 0)
         {
           ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
@@ -254,22 +292,47 @@ failallocatedcleanup:
           /* if the caller specified a root directory, there must be an object name! */
           Status = STATUS_OBJECT_NAME_INVALID;
         }
-        
-        if(!NT_SUCCESS(Status))
-        {
-          goto failallocatedcleanup;
-        }
       }
     }
     else
     {
-      RtlInitUnicodeString(ObjectName, NULL);
+      ObjectName->Length = ObjectName->MaximumLength = 0;
+      ObjectName->Buffer = NULL;
     }
   }
-  
+
+  if(!NT_SUCCESS(Status))
+  {
+    if(ObjectName->Buffer)
+    {
+      ExFreePool(ObjectName->Buffer);
+    }
+
+failcleanupsdescriptor:
+    if(CapturedObjectAttributes != NULL)
+    {
+      /* cleanup allocated resources */
+      SeReleaseSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor,
+                                  AccessMode,
+                                  TRUE);
+    }
+
+failbasiccleanup:
+    if(ObjectName != NULL)
+    {
+      ObjectName->Length = ObjectName->MaximumLength = 0;
+      ObjectName->Buffer = NULL;
+    }
+    if(CapturedObjectAttributes != NULL)
+    {
+      RtlZeroMemory(CapturedObjectAttributes, sizeof(CAPTURED_OBJECT_ATTRIBUTES));
+    }
+  }
+
   return Status;
 }
 
+
 VOID
 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes  OPTIONAL,
                            IN PUNICODE_STRING ObjectName  OPTIONAL,
@@ -278,14 +341,20 @@ ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttribut
 {
   /* WARNING - You need to pass the same parameters to this function as you passed
                to ObpCaptureObjectAttributes() to avoid memory leaks */
-  if(AccessMode != KernelMode ||
-     (AccessMode == KernelMode && CaptureIfKernel))
+  if(AccessMode != KernelMode || CaptureIfKernel)
   {
-    if(CapturedObjectAttributes != NULL &&
-       CapturedObjectAttributes->SecurityDescriptor != NULL)
+    if(CapturedObjectAttributes != NULL)
     {
-      ExFreePool(CapturedObjectAttributes->SecurityDescriptor);
-      CapturedObjectAttributes->SecurityDescriptor = NULL;
+      if(CapturedObjectAttributes->SecurityDescriptor != NULL)
+      {
+        ExFreePool(CapturedObjectAttributes->SecurityDescriptor);
+        CapturedObjectAttributes->SecurityDescriptor = NULL;
+      }
+      if(CapturedObjectAttributes->SecurityQualityOfService != NULL)
+      {
+        ExFreePool(CapturedObjectAttributes->SecurityQualityOfService);
+        CapturedObjectAttributes->SecurityQualityOfService = NULL;
+      }
     }
     if(ObjectName != NULL &&
        ObjectName->Length > 0)
@@ -334,6 +403,8 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
   UNICODE_STRING PathString;
   ULONG Attributes;
   PUNICODE_STRING ObjectName;
+  
+  PAGED_CODE();
 
   DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
         "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
@@ -441,7 +512,7 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
     }
 
   if (current)
-     RtlCreateUnicodeString (RemainingPath, current);
+     RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
   RtlFreeUnicodeString (&PathString);
   *ReturnedObject = CurrentObject;
 
@@ -471,6 +542,8 @@ ObQueryNameString (IN PVOID Object,
   POBJECT_HEADER ObjectHeader;
   ULONG LocalReturnLength;
   NTSTATUS Status;
+  
+  PAGED_CODE();
 
   *ReturnLength = 0;
 
@@ -599,9 +672,9 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
   PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
   SECURITY_SUBJECT_CONTEXT SubjectContext;
 
-  ASSERT_IRQL(APC_LEVEL);
+  PAGED_CODE();
   
-  if(AccessMode == UserMode)
+  if(ObjectAttributesAccessMode == UserMode && ObjectAttributes != NULL)
   {
     Status = STATUS_SUCCESS;
     _SEH_TRY
@@ -802,6 +875,8 @@ ObReferenceObjectByPointer(IN PVOID Object,
                           IN KPROCESSOR_MODE AccessMode)
 {
    POBJECT_HEADER Header;
+   
+   /* NOTE: should be possible to reference an object above APC_LEVEL! */
 
    DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
          Object,ObjectType);
@@ -864,6 +939,8 @@ ObOpenObjectByPointer(IN POBJECT Object,
 {
    NTSTATUS Status;
    
+   PAGED_CODE();
+   
    DPRINT("ObOpenObjectByPointer()\n");
    
    Status = ObReferenceObjectByPointer(Object,
@@ -1105,6 +1182,8 @@ ULONG STDCALL
 ObGetObjectPointerCount(PVOID Object)
 {
   POBJECT_HEADER Header;
+  
+  PAGED_CODE();
 
   ASSERT(Object);
   Header = BODY_TO_HEADER(Object);
@@ -1130,6 +1209,8 @@ ULONG
 ObGetObjectHandleCount(PVOID Object)
 {
   POBJECT_HEADER Header;
+  
+  PAGED_CODE();
 
   ASSERT(Object);
   Header = BODY_TO_HEADER(Object);