Added ObGetObjectHandleCount().
[reactos.git] / reactos / ntoskrnl / ob / object.c
index 02f60cd..7e78bfe 100644 (file)
-/*\r
- * COPYRIGHT:     See COPYING in the top level directory\r
- * PROJECT:       ReactOS kernel\r
- * FILE:          ntoskrnl/ob/object.c\r
- * PURPOSE:       Implements generic object managment functions\r
- * PROGRAMMER:    David Welch (welch@mcmail.com)\r
- * UPDATE HISTORY:\r
- *               10/06/98: Created\r
- */\r
-\r
-/* INCLUDES *****************************************************************/\r
-\r
-#include <ddk/ntddk.h>\r
-#include <internal/ob.h>\r
-#include <wstring.h>\r
-#include <string.h>\r
-\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-/* FUNCTIONS ************************************************************/\r
-\r
-NTSTATUS STDCALL NtSetInformationObject(IN HANDLE ObjectHandle,\r
-                                       IN CINT ObjectInformationClass,\r
-                                       IN PVOID ObjectInformation,\r
-                                       IN ULONG Length)\r
-{\r
-   return(ZwSetInformationObject(ObjectHandle,\r
-                                ObjectInformationClass,\r
-                                ObjectInformation,\r
-                                Length));\r
-}\r
-\r
-NTSTATUS STDCALL ZwSetInformationObject(IN HANDLE ObjectHandle,\r
-                                       IN CINT ObjectInformationClass,\r
-                                       IN PVOID ObjectInformation,\r
-                                       IN ULONG Length)\r
-{\r
-   UNIMPLEMENTED;\r
-}\r
-\r
-NTSTATUS STDCALL NtQueryObject(IN HANDLE ObjectHandle,\r
-                              IN CINT ObjectInformationClass,\r
-                              OUT PVOID ObjectInformation,\r
-                              IN ULONG Length,\r
-                              OUT PULONG ResultLength)\r
-{\r
-   return(ZwQueryObject(ObjectHandle,\r
-                       ObjectInformationClass,\r
-                       ObjectInformation,\r
-                       Length,\r
-                       ResultLength));\r
-}\r
-\r
-NTSTATUS STDCALL ZwQueryObject(IN HANDLE ObjectHandle,\r
-                              IN CINT ObjectInformationClass,\r
-                              OUT PVOID ObjectInformation,\r
-                              IN ULONG Length,\r
-                              OUT PULONG ResultLength)\r
-{\r
-   UNIMPLEMENTED\r
-}\r
-\r
-NTSTATUS NtMakeTemporaryObject(HANDLE Handle)\r
-{\r
-   return(ZwMakeTemporaryObject(Handle));\r
-}\r
-\r
-NTSTATUS ZwMakeTemporaryObject(HANDLE Handle)\r
-{\r
-   PVOID Object;\r
-   NTSTATUS Status;  \r
-   POBJECT_HEADER ObjectHeader;\r
-   \r
-   Status = ObReferenceObjectByHandle(Handle,\r
-                                     0,\r
-                                     NULL,\r
-                                     KernelMode,\r
-                                     &Object,\r
-                                     NULL);\r
-   if (Status != STATUS_SUCCESS)\r
-     {\r
-       return(Status);\r
-     }\r
-\r
-   ObjectHeader = BODY_TO_HEADER(Object);\r
-   ObjectHeader->Permanent = FALSE;\r
-   \r
-   ObDereferenceObject(Object);\r
-   \r
-   return(STATUS_SUCCESS);\r
-}\r
-\r
-PVOID ObGenericCreateObject(PHANDLE Handle,\r
-                           ACCESS_MASK DesiredAccess,\r
-                           POBJECT_ATTRIBUTES ObjectAttributes,\r
-                           POBJECT_TYPE Type)\r
-{\r
-   POBJECT_HEADER hdr = NULL;\r
-   PWSTR path;\r
-   PWSTR name;\r
-   PWSTR Ignored;\r
-   PULONG addr;\r
-   PWSTR Buffer;\r
-   \r
-   DPRINT("ObGenericCreateObject(Handle %x, DesiredAccess %x,"\r
-         "ObjectAttributes %x, Type %x)\n",Handle,DesiredAccess,\r
-         ObjectAttributes,Type);\r
-   \r
-   /*\r
-    * Allocate the object body and header\r
-    */\r
-   hdr=(POBJECT_HEADER)ExAllocatePool(NonPagedPool,OBJECT_ALLOC_SIZE(Type));\r
-   DPRINT("OBJECT_ALLOC_SIZE(Type) %d\n",OBJECT_ALLOC_SIZE(Type));\r
-   if (hdr==NULL)\r
-     {\r
-       return(NULL);\r
-     }\r
-   DPRINT("hdr %x\n",hdr);\r
-\r
-\r
-   /*\r
-    * If unnamed then initalize\r
-    */\r
-   if (ObjectAttributes==NULL || ObjectAttributes->ObjectName==NULL)\r
-     {\r
-       ObInitializeObjectHeader(Type,NULL,hdr);\r
-       if (Handle != NULL)\r
-         {\r
-            *Handle = ObInsertHandle(KeGetCurrentProcess(),\r
-                                     HEADER_TO_BODY(hdr),\r
-                                     DesiredAccess,\r
-                                     FALSE);\r
-         }\r
-       return(HEADER_TO_BODY(hdr));\r
-     }\r
-\r
-   \r
-   /*\r
-    * Copy the object name into a buffer\r
-    */\r
-//   DbgPrint("ObjectAttributes->ObjectName %x\n",ObjectAttributes->ObjectName);\r
-//   DbgPrint("ObjectAttributes->ObjectName->Length %d\n",\r
-//         ObjectAttributes->ObjectName->Length);\r
-//   DbgPrint("ObjectAttributes->ObjectName->MaximumLength %d\n",\r
-//         ObjectAttributes->ObjectName->MaximumLength);\r
-   Buffer = ExAllocatePool(NonPagedPool,\r
-                          ((ObjectAttributes->ObjectName->Length+1)*2));   \r
-   if (Buffer==NULL)\r
-     {\r
-       return(NULL);   \r
-     }\r
-   memcpy(Buffer, ObjectAttributes->ObjectName->Buffer,\r
-         (ObjectAttributes->ObjectName->Length+1)*2);\r
-   \r
-   /*\r
-    * Seperate the name into a path and name \r
-    */\r
-   name = wcsrchr(Buffer,'\\');\r
-   if (name==NULL)\r
-     {\r
-       name=Buffer;\r
-       path=NULL;\r
-     }\r
-   else\r
-     {\r
-       path=Buffer;\r
-       *name=0;\r
-       name=name+1;\r
-     }\r
-   DPRINT("name %w path %w\n",name,path);\r
-   \r
-   ObLookupObject(ObjectAttributes->RootDirectory,\r
-                 path,\r
-                 &hdr->Parent,\r
-                 &Ignored, \r
-                 0L);\r
-\r
-   /*\r
-    * Initialize the object header\r
-    */\r
-   ObInitializeObjectHeader(Type,name,hdr);\r
-\r
-\r
-   ObCreateEntry(hdr->Parent,hdr);\r
-\r
-   DPRINT("Handle %x\n",Handle);\r
-   if (Handle != NULL)\r
-     {\r
-       *Handle = ObInsertHandle(KeGetCurrentProcess(),\r
-                                HEADER_TO_BODY(hdr),\r
-                                DesiredAccess,\r
-                                FALSE);\r
-     }\r
-   \r
-   return(HEADER_TO_BODY(hdr));\r
-}\r
-\r
-VOID ObInitializeObjectHeader(POBJECT_TYPE Type, PWSTR name,\r
-                             POBJECT_HEADER ObjectHeader)\r
-/*\r
- * FUNCTION: Creates a new object\r
- * ARGUMENT:\r
- *        id = Identifier for the type of object\r
- *        obj = Pointer to the header of the object\r
- */\r
-{\r
-   PWSTR temp_name;\r
-   extern unsigned long long ticks;\r
-   \r
-   DPRINT("ObInitializeObjectHeader(id %x name %w obj %x)\n",Type,\r
-         name,ObjectHeader);\r
-\r
-   ObjectHeader->HandleCount = 0;\r
-   ObjectHeader->RefCount = 0;\r
-   ObjectHeader->ObjectType = Type;\r
-   ObjectHeader->Permanent = FALSE;\r
-   if (name==NULL)\r
-     {\r
-       ObjectHeader->Name.Length=0;\r
-       ObjectHeader->Name.Buffer=NULL;\r
-     }\r
-   else\r
-     {\r
-        RtlInitUnicodeString(&(ObjectHeader->Name),name);\r
-     }\r
-}\r
-\r
-\r
-NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody,\r
-                                   ACCESS_MASK DesiredAccess,\r
-                                   POBJECT_TYPE ObjectType,\r
-                                   KPROCESSOR_MODE AccessMode)\r
-/*\r
- * FUNCTION: Increments the pointer reference count for a given object\r
- * ARGUMENTS:\r
- *         ObjectBody = Object's body\r
- *         DesiredAccess = Desired access to the object\r
- *         ObjectType = Points to the object type structure\r
- *         AccessMode = Type of access check to perform\r
- * RETURNS: Status\r
- */\r
-{\r
-   POBJECT_HEADER Object;\r
-\r
-   DPRINT("ObReferenceObjectByPointer(%x)\n",ObjectBody);\r
-   \r
-   Object = BODY_TO_HEADER(ObjectBody);\r
-   Object->RefCount++;\r
-   return(STATUS_SUCCESS);\r
-}\r
-\r
-NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)\r
-{\r
-   if (Header->RefCount == 0 && Header->HandleCount == 0 &&\r
-       !Header->Permanent)\r
-     {\r
-       ObRemoveEntry(Header);\r
-       ExFreePool(Header);\r
-     }\r
-   return(STATUS_SUCCESS);\r
-}\r
-\r
-VOID ObDereferenceObject(PVOID ObjectBody)\r
-/*\r
- * FUNCTION: Decrements a given object's reference count and performs\r
- * retention checks\r
- * ARGUMENTS:\r
- *        ObjectBody = Body of the object\r
- */\r
-{\r
-   POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);\r
-   Header->RefCount--;\r
-   ObPerformRetentionChecks(Header);\r
-}\r
-\r
-\r
-NTSTATUS NtClose(HANDLE Handle)\r
-{\r
-   return(ZwClose(Handle));\r
-}\r
-\r
-NTSTATUS ZwClose(HANDLE Handle)\r
-/*\r
- * FUNCTION: Closes a handle reference to an object\r
- * ARGUMENTS:\r
- *         Handle = handle to close\r
- * RETURNS: Status\r
- */\r
-{\r
-   PVOID ObjectBody;\r
-   POBJECT_HEADER Header;\r
-   PHANDLE_REP HandleRep;\r
-   \r
-   assert_irql(PASSIVE_LEVEL);\r
-   \r
-   HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle);\r
-   if (HandleRep == NULL)\r
-     {\r
-       return(STATUS_INVALID_HANDLE);\r
-     }   \r
-   ObjectBody = HandleRep->ObjectBody;\r
-   \r
-   HandleRep->ObjectBody = NULL;\r
-   \r
-   Header = BODY_TO_HEADER(ObjectBody);\r
-   \r
-   Header->HandleCount--;\r
-   ObPerformRetentionChecks(Header);\r
-   \r
-   return(STATUS_SUCCESS);\r
-}\r
-\r
-NTSTATUS ObReferenceObjectByHandle(HANDLE Handle,\r
-                                  ACCESS_MASK DesiredAccess,\r
-                                  POBJECT_TYPE ObjectType,\r
-                                  KPROCESSOR_MODE AccessMode,\r
-                                  PVOID* Object,\r
-                                  POBJECT_HANDLE_INFORMATION \r
-                                          HandleInformationPtr\r
-                                  )\r
-/*\r
- * FUNCTION: Increments the reference count for an object and returns a \r
- * pointer to its body\r
- * ARGUMENTS:\r
- *         Handle = Handle for the object\r
- *         DesiredAccess = Desired access to the object\r
- *         ObjectType\r
- *         AccessMode \r
- *         Object (OUT) = Points to the object body on return\r
- *         HandleInformation (OUT) = Contains information about the handle \r
- *                                   on return\r
- * RETURNS: Status\r
- */\r
-{\r
-   PHANDLE_REP HandleRep;\r
-   POBJECT_HEADER ObjectHeader;\r
-   \r
-   ASSERT_IRQL(PASSIVE_LEVEL);\r
-   \r
-   DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "\r
-         "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,\r
-         ObjectType,AccessMode,Object);\r
-   \r
-   if (Handle == NtCurrentProcess())\r
-     {\r
-       *Object = PsGetCurrentProcess();\r
-       return(STATUS_SUCCESS);\r
-     }\r
-   if (Handle == NtCurrentThread())\r
-     {\r
-       *Object = PsGetCurrentThread();\r
-       return(STATUS_SUCCESS);\r
-     }\r
-   \r
-   HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle);\r
-   if (HandleRep == NULL || HandleRep->ObjectBody == NULL)\r
-     {\r
-       return(STATUS_INVALID_HANDLE);\r
-     }\r
-   \r
-   ObjectHeader = BODY_TO_HEADER(HandleRep->ObjectBody);\r
-   \r
-   if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)\r
-     {\r
-       return(STATUS_UNSUCCESSFUL);\r
-     }   \r
-   \r
-   if (!(HandleRep->GrantedAccess & DesiredAccess))\r
-     {\r
-       return(STATUS_ACCESS_DENIED);\r
-     }\r
-   \r
-   ObjectHeader->RefCount++;\r
-   \r
-   *Object = HandleRep->ObjectBody;\r
-   \r
-   return(STATUS_SUCCESS);\r
-}\r
+/* $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
+ * FILE:          ntoskrnl/ob/object.c
+ * PURPOSE:       Implements generic object managment functions
+ * PROGRAMMER:    David Welch (welch@cwcom.net)
+ * UPDATE HISTORY:
+ *               10/06/98: Created
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <roscfg.h>
+#include <internal/ob.h>
+#include <internal/ps.h>
+#include <internal/id.h>
+#include <internal/ke.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS ************************************************************/
+
+PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
+{
+   return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
+}
+
+POBJECT_HEADER BODY_TO_HEADER(PVOID body)
+{
+   PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
+   return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
+}
+
+
+/**********************************************************************
+ * NAME                                                        PRIVATE
+ *     ObInitializeObject
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ */
+VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
+                       PHANDLE Handle,
+                       ACCESS_MASK DesiredAccess,
+                       POBJECT_TYPE Type,
+                       POBJECT_ATTRIBUTES ObjectAttributes)
+{
+   ObjectHeader->HandleCount = 0;
+   ObjectHeader->RefCount = 1;
+   ObjectHeader->ObjectType = Type;
+   if (ObjectAttributes != NULL &&
+       ObjectAttributes->Attributes & OBJ_PERMANENT)
+     {
+       ObjectHeader->Permanent = TRUE;
+     }
+   else
+     {
+       ObjectHeader->Permanent = FALSE;
+     }
+   RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
+   if (Handle != NULL)
+     {
+       ObCreateHandle(PsGetCurrentProcess(),
+                      HEADER_TO_BODY(ObjectHeader),
+                      DesiredAccess,
+                      FALSE,
+                      Handle);
+     }
+}
+
+
+/**********************************************************************
+ * NAME                                                        PRIVATE
+ *     ObFindObject@16
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *     ObjectAttributes
+ *
+ *     ReturnedObject
+ *
+ *     RemainigPath
+ *             Pointer to a unicode string that will contain the
+ *             remaining path if the function returns successfully.
+ *             The caller must free the buffer after use by calling
+ *             RtlFreeUnicodeString ().
+ *
+ *     ObjectType
+ *             Optional pointer to an object type. This is used to
+ *             descide if a symbolic link object will be parsed or not.
+ *
+ * RETURN VALUE
+ */
+NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
+                     PVOID* ReturnedObject,
+                     PUNICODE_STRING RemainingPath,
+                     POBJECT_TYPE ObjectType)
+{
+   PVOID NextObject;
+   PVOID CurrentObject;
+   PVOID RootObject;
+   POBJECT_HEADER CurrentHeader;
+   NTSTATUS Status;
+   PWSTR Path;
+   PWSTR current;
+   UNICODE_STRING PathString;
+   
+   DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
+         "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
+   DPRINT("ObjectAttributes->ObjectName %wZ\n",
+         ObjectAttributes->ObjectName);
+
+   RtlInitUnicodeString (RemainingPath, NULL);
+
+   if (ObjectAttributes->RootDirectory == NULL)
+     {
+       ObReferenceObjectByPointer(NameSpaceRoot,
+                                  DIRECTORY_TRAVERSE,
+                                  NULL,
+                                  UserMode);
+       CurrentObject = NameSpaceRoot;
+     }
+   else
+     {
+       Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
+                                          DIRECTORY_TRAVERSE,
+                                          NULL,
+                                          UserMode,
+                                          &CurrentObject,
+                                          NULL);
+       if (!NT_SUCCESS(Status))
+         {
+            return(Status);
+         }
+     }
+   
+   Path = ObjectAttributes->ObjectName->Buffer;
+   
+   if (Path[0] == 0)
+     {
+       *ReturnedObject = CurrentObject;
+       return(STATUS_SUCCESS);
+     }
+   
+   if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
+     {
+       ObDereferenceObject(CurrentObject);
+       return(STATUS_UNSUCCESSFUL);
+     }
+   
+   if (Path)
+     {
+       RtlCreateUnicodeString (&PathString, Path);
+       current = PathString.Buffer;
+     }
+   else
+     {
+       RtlInitUnicodeString (&PathString, NULL);
+       current = NULL;
+     }
+
+   RootObject = CurrentObject;
+
+   while (TRUE)
+     {
+       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");
+            break;
+         }
+       Status = CurrentHeader->ObjectType->Parse(CurrentObject,
+                                                 &NextObject,
+                                                 &PathString,
+                                                 &current,
+                                                 ObjectType,
+                                                 ObjectAttributes->Attributes);
+       if (Status == STATUS_REPARSE)
+         {
+            /* reparse the object path */
+            NextObject = RootObject;
+            current = PathString.Buffer;
+            
+            ObReferenceObjectByPointer(NextObject,
+                                       DIRECTORY_TRAVERSE,
+                                       NULL,
+                                       UserMode);
+         }
+
+       if (NextObject == NULL)
+         {
+            break;
+         }
+       ObDereferenceObject(CurrentObject);
+       CurrentObject = NextObject;
+     }
+   
+   if (current)
+      RtlCreateUnicodeString (RemainingPath, current);
+   RtlFreeUnicodeString (&PathString);
+   *ReturnedObject = CurrentObject;
+   
+   return(STATUS_SUCCESS);
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     ObCreateObject@36
+ *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *
+ * RETURN VALUE
+ */
+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;
+  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(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:
+ *         ObjectBody = Object's body
+ *         DesiredAccess = Desired access to the object
+ *         ObjectType = Points to the object type structure
+ *         AccessMode = Type of access check to perform
+ * RETURNS: Status
+ */
+{
+   POBJECT_HEADER Header;
+
+//   DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
+//       Object,ObjectType);
+   
+   Header = BODY_TO_HEADER(Object);
+   
+   if (ObjectType != NULL && Header->ObjectType != ObjectType)
+     {
+       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 (Header->ObjectType == PsProcessType)
+     {
+       DPRINT("Ref p 0x%x 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++;
+   
+   return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS STDCALL
+ObOpenObjectByPointer(IN POBJECT Object,
+                     IN ULONG HandleAttributes,
+                     IN PACCESS_STATE PassedAccessState,
+                     IN ACCESS_MASK DesiredAccess,
+                     IN POBJECT_TYPE ObjectType,
+                     IN KPROCESSOR_MODE AccessMode,
+                     OUT PHANDLE Handle)
+{
+   NTSTATUS Status;
+   
+   DPRINT("ObOpenObjectByPointer()\n");
+   
+   Status = ObReferenceObjectByPointer(Object,
+                                      0,
+                                      ObjectType,
+                                      AccessMode);
+   if (!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   
+   Status = ObCreateHandle(PsGetCurrentProcess(),
+                          Object,
+                          DesiredAccess,
+                          FALSE,
+                          Handle);
+   
+   ObDereferenceObject(Object);
+   
+   return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+ObpPerformRetentionChecks(POBJECT_HEADER Header)
+{
+//  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);
+}
+
+
+/**********************************************************************
+ * 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;
+
+  assert(Object);
+
+  Header = BODY_TO_HEADER(Object);
+
+  Header->RefCount++;
+
+  ObpPerformRetentionChecks(Header);
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     ObfDereferenceObject@4
+ *
+ * DESCRIPTION
+ *     Decrements a given object's reference count and performs
+ *     retention checks.
+ *
+ * ARGUMENTS
+ *     ObjectBody = Body of the object.
+ *
+ * RETURN VALUE
+ *     None.
+ */
+VOID FASTCALL
+ObfDereferenceObject(IN PVOID Object)
+{
+  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);
+}
+
+
+/**********************************************************************
+ * 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;
+
+  assert(Object);
+  Header = BODY_TO_HEADER(Object);
+
+  return(Header->RefCount);
+}
+
+
+/**********************************************************************
+ * 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;
+
+  assert(Object);
+  Header = BODY_TO_HEADER(Object);
+
+  return(Header->HandleCount);
+}
+
+/* EOF */