Added ObGetObjectHandleCount().
[reactos.git] / reactos / ntoskrnl / ob / object.c
index d9a4fe7..7e78bfe 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: object.c,v 1.32 2001/02/02 20:46:36 ekohl Exp $
+/* $Id: object.c,v 1.46 2002/03/05 00:19:28 ekohl Exp $
  * 
  * COPYRIGHT:     See COPYING in the top level directory
  * PROJECT:       ReactOS kernel
@@ -12,6 +12,7 @@
 /* INCLUDES *****************************************************************/
 
 #include <ddk/ntddk.h>
+#include <roscfg.h>
 #include <internal/ob.h>
 #include <internal/ps.h>
 #include <internal/id.h>
@@ -113,8 +114,8 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
    
    DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
          "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
-   DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
-         ObjectAttributes->ObjectName->Buffer);
+   DPRINT("ObjectAttributes->ObjectName %wZ\n",
+         ObjectAttributes->ObjectName);
 
    RtlInitUnicodeString (RemainingPath, NULL);
 
@@ -171,6 +172,10 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
      {
        DPRINT("current %S\n",current);
        CurrentHeader = BODY_TO_HEADER(CurrentObject);
+
+       DPRINT("Current ObjectType %wZ\n",
+              &CurrentHeader->ObjectType->TypeName);
+
        if (CurrentHeader->ObjectType->Parse == NULL)
          {
             DPRINT("Current object can't parse\n");
@@ -180,7 +185,8 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
                                                  &NextObject,
                                                  &PathString,
                                                  &current,
-                                                 ObjectType);
+                                                 ObjectType,
+                                                 ObjectAttributes->Attributes);
        if (Status == STATUS_REPARSE)
          {
             /* reparse the object path */
@@ -220,75 +226,113 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
  *
  * RETURN VALUE
  */
-PVOID STDCALL ObCreateObject(PHANDLE Handle,
-                            ACCESS_MASK DesiredAccess,
-                            POBJECT_ATTRIBUTES ObjectAttributes,
-                            POBJECT_TYPE Type)
+NTSTATUS STDCALL
+ObCreateObject(OUT PHANDLE Handle,
+              IN ACCESS_MASK DesiredAccess,
+              IN POBJECT_ATTRIBUTES ObjectAttributes,
+              IN POBJECT_TYPE Type,
+              OUT PVOID *Object)
 {
-   PVOID Parent = NULL;
-   UNICODE_STRING RemainingPath;
-   POBJECT_HEADER Header;
-   NTSTATUS Status;
-   
-   assert_irql(APC_LEVEL);
-   
-   DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
-   if (ObjectAttributes != NULL &&
-       ObjectAttributes->ObjectName != NULL)
-     {
-       DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
-              ObjectAttributes->ObjectName->Buffer);
-     }
-   
-   if (ObjectAttributes != NULL &&
-       ObjectAttributes->ObjectName != NULL)
-     {
-       ObFindObject(ObjectAttributes,
-                    &Parent,
-                    &RemainingPath,
-                    NULL);
-     }
-   else
-     {
-       RtlInitUnicodeString (&RemainingPath, NULL);
-     }
-
-   RtlMapGenericMask(&DesiredAccess,
-                    Type->Mapping);
-
-   Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,
-                                          OBJECT_ALLOC_SIZE(Type));
-   ObInitializeObject(Header,
-                     Handle,
-                     DesiredAccess,
-                     Type,
-                     ObjectAttributes);
-   if (Header->ObjectType != NULL &&
-       Header->ObjectType->Create != NULL)
-     {
-       DPRINT("Calling %x\n", Header->ObjectType);
-       DPRINT("Calling %x\n", Header->ObjectType->Create);
-       Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
-                                           Parent,
-                                           RemainingPath.Buffer,
-                                           ObjectAttributes);
-       if (!NT_SUCCESS(Status))
-         {
-           ObDereferenceObject( Parent );
-           RtlFreeUnicodeString( &Header->Name );
-           RtlFreeUnicodeString( &RemainingPath );
-           ExFreePool( Header );
-           return(NULL);
-         }
-     }
-   RtlFreeUnicodeString( &RemainingPath );
-   return(HEADER_TO_BODY(Header));
+  PVOID Parent = NULL;
+  UNICODE_STRING RemainingPath;
+  POBJECT_HEADER Header;
+  POBJECT_HEADER ParentHeader = NULL;
+  NTSTATUS Status;
+  BOOLEAN ObjectAttached = FALSE;
+
+  assert_irql(APC_LEVEL);
+
+  DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
+        Handle, ObjectAttributes, Type);
+  if (ObjectAttributes != NULL &&
+      ObjectAttributes->ObjectName != NULL)
+    {
+      DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
+            ObjectAttributes->ObjectName->Buffer);
+    }
+
+  if (ObjectAttributes != NULL &&
+      ObjectAttributes->ObjectName != NULL)
+    {
+      Status = ObFindObject(ObjectAttributes,
+                           &Parent,
+                           &RemainingPath,
+                           NULL);
+      if (!NT_SUCCESS(Status))
+       {
+         DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
+         return(Status);
+       }
+    }
+  else
+    {
+      RtlInitUnicodeString(&RemainingPath, NULL);
+    }
+
+  RtlMapGenericMask(&DesiredAccess,
+                   Type->Mapping);
+
+  Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
+                                                OBJECT_ALLOC_SIZE(Type),
+                                                Type->Tag);
+  ObInitializeObject(Header,
+                    Handle,
+                    DesiredAccess,
+                    Type,
+                    ObjectAttributes);
+
+  if (Parent != NULL)
+    {
+      ParentHeader = BODY_TO_HEADER(Parent);
+    }
+
+  if (ParentHeader != NULL &&
+      ParentHeader->ObjectType == ObDirectoryType &&
+      RemainingPath.Buffer != NULL)
+    {
+      ObpAddEntryDirectory(Parent,
+                          Header,
+                          RemainingPath.Buffer+1);
+      ObjectAttached = TRUE;
+    }
+
+  if ((Header->ObjectType != NULL) &&
+      (Header->ObjectType->Create != NULL))
+    {
+      DPRINT("Calling %x\n", Header->ObjectType->Create);
+      Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
+                                         Parent,
+                                         RemainingPath.Buffer,
+                                         ObjectAttributes);
+      if (!NT_SUCCESS(Status))
+       {
+         if (ObjectAttached == TRUE)
+           {
+             ObpRemoveEntryDirectory(Header);
+           }
+         if (Parent)
+           {
+             ObDereferenceObject(Parent);
+           }
+         RtlFreeUnicodeString(&Header->Name);
+         RtlFreeUnicodeString(&RemainingPath);
+         ExFreePool(Header);
+         return(Status);
+       }
+    }
+  RtlFreeUnicodeString( &RemainingPath );
+
+  *Object = HEADER_TO_BODY(Header);
+
+  return(STATUS_SUCCESS);
 }
 
-NTSTATUS STDCALL ObReferenceObjectByPointer(PVOID ObjectBody,
-                                   ACCESS_MASK DesiredAccess,
-                                   POBJECT_TYPE ObjectType,
-                                   KPROCESSOR_MODE AccessMode)
+
+NTSTATUS STDCALL
+ObReferenceObjectByPointer(IN PVOID Object,
+                          IN ACCESS_MASK DesiredAccess,
+                          IN POBJECT_TYPE ObjectType,
+                          IN KPROCESSOR_MODE AccessMode)
 /*
  * FUNCTION: Increments the pointer reference count for a given object
  * ARGUMENTS:
@@ -299,41 +343,42 @@ NTSTATUS STDCALL ObReferenceObjectByPointer(PVOID ObjectBody,
  * RETURNS: Status
  */
 {
-   POBJECT_HEADER ObjectHeader;
+   POBJECT_HEADER Header;
 
-//   DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
-//       ObjectBody,ObjectType);
+//   DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
+//       Object,ObjectType);
    
-   ObjectHeader = BODY_TO_HEADER(ObjectBody);
+   Header = BODY_TO_HEADER(Object);
    
-   if (ObjectType != NULL && ObjectHeader->ObjectType != ObjectType)
+   if (ObjectType != NULL && Header->ObjectType != ObjectType)
      {
-       DPRINT("Failed %x (type was %x %S) should %x\n",
-               ObjectHeader,
-               ObjectHeader->ObjectType,
-               ObjectHeader->ObjectType->TypeName.Buffer,
-               ObjectType);
-       KeBugCheck(0);
+       DPRINT("Failed %x (type was %x %S) should be %x %S\n",
+               Header,
+               Header->ObjectType,
+               Header->ObjectType->TypeName.Buffer,
+               ObjectType,
+    ObjectType->TypeName.Buffer);
        return(STATUS_UNSUCCESSFUL);
      }
-   if (ObjectHeader->ObjectType == PsProcessType)
+   if (Header->ObjectType == PsProcessType)
      {
        DPRINT("Ref p 0x%x refcount %d type %x ",
-               ObjectBody, ObjectHeader->RefCount, PsProcessType);
-       DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
+               ObjectHeader->RefCount, PsProcessType);
+       DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
      }
-   if (ObjectHeader->ObjectType == PsThreadType)
+   if (Header->ObjectType == PsThreadType)
      {
        DPRINT("Deref t 0x%x with refcount %d type %x ",
-               ObjectBody, ObjectHeader->RefCount, PsThreadType);
-       DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
+               ObjectHeader->RefCount, PsThreadType);
+       DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
      }
    
-   ObjectHeader->RefCount++;
+   Header->RefCount++;
    
    return(STATUS_SUCCESS);
 }
 
+
 NTSTATUS STDCALL
 ObOpenObjectByPointer(IN POBJECT Object,
                      IN ULONG HandleAttributes,
@@ -343,138 +388,190 @@ ObOpenObjectByPointer(IN POBJECT Object,
                      IN KPROCESSOR_MODE AccessMode,
                      OUT PHANDLE Handle)
 {
-   UNIMPLEMENTED;
-   return STATUS_NOT_IMPLEMENTED;
-}
-
-
-NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
-{
-//   DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
-//        Header,Header->RefCount,Header->HandleCount);
+   NTSTATUS Status;
    
-   if (Header->RefCount < 0)
-     {
-       DbgPrint("Object %x/%x has invalid reference count (%d)\n",
-                Header, HEADER_TO_BODY(Header), Header->RefCount);
-       KeBugCheck(0);
-     }
-   if (Header->HandleCount < 0)
-     {
-       DbgPrint("Object %x/%x has invalid handle count (%d)\n",
-                Header, HEADER_TO_BODY(Header), Header->HandleCount);
-       KeBugCheck(0);
-     }
+   DPRINT("ObOpenObjectByPointer()\n");
    
-   if (Header->RefCount == 0 && Header->HandleCount == 0 &&
-       !Header->Permanent)
+   Status = ObReferenceObjectByPointer(Object,
+                                      0,
+                                      ObjectType,
+                                      AccessMode);
+   if (!NT_SUCCESS(Status))
      {
-       if (Header->ObjectType != NULL &&
-           Header->ObjectType->Delete != NULL)
-         {
-            Header->ObjectType->Delete(HEADER_TO_BODY(Header));
-         }
-       if (Header->Name.Buffer != NULL)
-         {
-            ObRemoveEntry(Header);
-            RtlFreeUnicodeString( &Header->Name );
-         }
-       DPRINT("ObPerformRetentionChecks() = Freeing object\n");
-       ExFreePool(Header);
+       return Status;
      }
-   return(STATUS_SUCCESS);
+   
+   Status = ObCreateHandle(PsGetCurrentProcess(),
+                          Object,
+                          DesiredAccess,
+                          FALSE,
+                          Handle);
+   
+   ObDereferenceObject(Object);
+   
+   return STATUS_SUCCESS;
 }
 
-ULONG ObGetReferenceCount(PVOID ObjectBody)
+
+static NTSTATUS
+ObpPerformRetentionChecks(POBJECT_HEADER Header)
 {
-   POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-   
-   return(Header->RefCount);
+//  DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
+//       Header,Header->RefCount,Header->HandleCount);
+  
+  if (Header->RefCount < 0)
+    {
+      CPRINT("Object %x/%x has invalid reference count (%d)\n",
+            Header, HEADER_TO_BODY(Header), Header->RefCount);
+      KeBugCheck(0);
+    }
+  if (Header->HandleCount < 0)
+    {
+      CPRINT("Object %x/%x has invalid handle count (%d)\n",
+            Header, HEADER_TO_BODY(Header), Header->HandleCount);
+      KeBugCheck(0);
+    }
+  
+  if (Header->RefCount == 0 &&
+      Header->HandleCount == 0 &&
+      Header->Permanent == FALSE)
+    {
+      if (Header->ObjectType != NULL &&
+         Header->ObjectType->Delete != NULL)
+       {
+         Header->ObjectType->Delete(HEADER_TO_BODY(Header));
+       }
+      if (Header->Name.Buffer != NULL)
+       {
+         ObpRemoveEntryDirectory(Header);
+         RtlFreeUnicodeString(&Header->Name);
+       }
+      DPRINT("ObPerformRetentionChecks() = Freeing object\n");
+      ExFreePool(Header);
+    }
+  return(STATUS_SUCCESS);
 }
 
-ULONG ObGetHandleCount(PVOID ObjectBody)
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     ObfReferenceObject@4
+ *
+ * DESCRIPTION
+ *     Increments a given object's reference count and performs
+ *     retention checks.
+ *
+ * ARGUMENTS
+ *  ObjectBody = Body of the object.
+ *
+ * RETURN VALUE
+ *     None.
+ */
+VOID FASTCALL
+ObfReferenceObject(IN PVOID Object)
 {
-   POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-   
-   return(Header->HandleCount);
+  POBJECT_HEADER Header;
+
+  assert(Object);
+
+  Header = BODY_TO_HEADER(Object);
+
+  Header->RefCount++;
+
+  ObpPerformRetentionChecks(Header);
 }
 
 
 /**********************************************************************
  * NAME                                                        EXPORTED
- *     @ObfReferenceObject@0
+ *     ObfDereferenceObject@4
  *
  * DESCRIPTION
- *     Increments a given object's reference count and performs
+ *     Decrements a given object's reference count and performs
  *     retention checks.
  *
  * ARGUMENTS
- *        ObjectBody
- *             Body of the object.
+ *     ObjectBody = Body of the object.
  *
  * RETURN VALUE
- *     The current value of the reference counter.
+ *     None.
  */
-ULONG FASTCALL ObfReferenceObject(PVOID ObjectBody)
+VOID FASTCALL
+ObfDereferenceObject(IN PVOID Object)
 {
-   POBJECT_HEADER      Header = BODY_TO_HEADER(ObjectBody);
-   ULONG               ReferenceCount;
-   
-   ReferenceCount = Header->RefCount++;
-   
-   ObPerformRetentionChecks (Header);
-   
-   return(ReferenceCount);
+  POBJECT_HEADER Header;
+  extern POBJECT_TYPE PsProcessType;
+
+  assert(Object);
+
+  Header = BODY_TO_HEADER(Object);
+
+  if (Header->ObjectType == PsProcessType)
+    {
+      DPRINT("Deref p 0x%x with refcount %d type %x ",
+            Object, Header->RefCount, PsProcessType);
+      DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
+    }
+  if (Header->ObjectType == PsThreadType)
+    {
+      DPRINT("Deref t 0x%x with refcount %d type %x ",
+            Object, Header->RefCount, PsThreadType);
+      DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
+    }
+  
+  Header->RefCount--;
+  
+  ObpPerformRetentionChecks(Header);
 }
 
 
-VOID FASTCALL ObfDereferenceObject (PVOID ObjectBody)
-/*
- * FUNCTION: Decrements a given object's reference count and performs
- * retention checks
- * ARGUMENTS:
- *        ObjectBody = Body of the object
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     ObGetObjectPointerCount@4
+ *
+ * DESCRIPTION
+ *     Retrieves the pointer(reference) count of the given object.
+ *
+ * ARGUMENTS
+ *     ObjectBody = Body of the object.
+ *
+ * RETURN VALUE
+ *     Reference count.
  */
+ULONG STDCALL
+ObGetObjectPointerCount(PVOID Object)
 {
-   POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-   extern POBJECT_TYPE PsProcessType;
-   
-//   DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
-//       Header->RefCount);
+  POBJECT_HEADER Header;
 
-   if (Header->ObjectType == PsProcessType)
-     {
-       DPRINT("Deref p 0x%x with refcount %d type %x ",
-               ObjectBody, Header->RefCount, PsProcessType);
-       DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
-     }
-   if (Header->ObjectType == PsThreadType)
-     {
-       DPRINT("Deref t 0x%x with refcount %d type %x ",
-               ObjectBody, Header->RefCount, PsThreadType);
-       DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
-     }
-   
-   Header->RefCount--;
-   
-   ObPerformRetentionChecks(Header);
+  assert(Object);
+  Header = BODY_TO_HEADER(Object);
+
+  return(Header->RefCount);
 }
 
 
-VOID STDCALL ObDereferenceObject (PVOID ObjectBody)
+/**********************************************************************
+ * NAME                                                        INTERNAL
+ *     ObGetObjectHandleCount@4
+ *
+ * DESCRIPTION
+ *     Retrieves the handle count of the given object.
+ *
+ * ARGUMENTS
+ *     ObjectBody = Body of the object.
+ *
+ * RETURN VALUE
+ *     Reference count.
+ */
+ULONG
+ObGetObjectHandleCount(PVOID Object)
 {
-   POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-   extern POBJECT_TYPE PsProcessType;
-   
-   if (Header->ObjectType == PsProcessType)
-     {
-       DPRINT("Deref p 0x%x with refcount %d type %x ",
-               ObjectBody, Header->RefCount, PsProcessType);
-       DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
-     }
-   
-   ObfDereferenceObject (ObjectBody);
-}
+  POBJECT_HEADER Header;
+
+  assert(Object);
+  Header = BODY_TO_HEADER(Object);
 
+  return(Header->HandleCount);
+}
 
 /* EOF */