[ros-kernel] attempt to fix Nt/ZwDuplicateObject() and ObCreateHandle() functions

Thomas Weidenmueller thomas at reactsoft.com
Fri Jul 30 15:18:56 CEST 2004


Hi,

I attempted to fix the Nt/ZwDuplicateObject() and ObCreateHandle() 
functions (the Inherit parameter is supposed to be HandleAttributes 
instead). I also added a few access checks on some places. However, I 
don't remember if the changes worked properly, I just thought I might 
submit it, in case someone finds it useful. Patch is attached.

Regards
Thomas
-------------- next part --------------
Index: include/ntos/ntdef.h
===================================================================
RCS file: /CVS/ReactOS/reactos/include/ntos/ntdef.h,v
retrieving revision 1.8
diff -u -r1.8 ntdef.h
--- include/ntos/ntdef.h	13 Jul 2004 16:57:10 -0000	1.8
+++ include/ntos/ntdef.h	23 Jul 2004 13:09:19 -0000
@@ -25,6 +25,7 @@
 
 #define DUPLICATE_CLOSE_SOURCE	(1)
 #define DUPLICATE_SAME_ACCESS	(2)
+#define DUPLICATE_SAME_ATTRIBUTES	(4)
 
 #define INVALID_HANDLE_VALUE	((HANDLE)-1)
 
Index: include/ntos/zw.h
===================================================================
RCS file: /CVS/ReactOS/reactos/include/ntos/zw.h,v
retrieving revision 1.28
diff -u -r1.28 zw.h
--- include/ntos/zw.h	17 Jul 2004 05:13:05 -0000	1.28
+++ include/ntos/zw.h	23 Jul 2004 12:59:14 -0000
@@ -5662,7 +5662,7 @@
  *	   TargetProcessHandle = The destination process owning the handle 
  *	   TargetHandle (OUT) = Caller should supply storage for the duplicated handle. 
  *	   DesiredAccess = The desired access to the handle.
- *	   InheritHandle = Indicates wheter the new handle will be inheritable or not.
+ *	   HandleAttributes = Specifies the handle attributes for the new handle.
  *	   Options = Specifies special actions upon duplicating the handle. Can be
  *			one of the values DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS.
  *			DUPLICATE_CLOSE_SOURCE specifies that the source handle should be
@@ -5681,7 +5681,7 @@
 	IN HANDLE TargetProcessHandle,
 	OUT PHANDLE TargetHandle,
 	IN ACCESS_MASK DesiredAccess,
-	IN BOOLEAN InheritHandle,
+	IN ULONG HandleAttributes,
 	IN ULONG Options
 	);
 
@@ -5693,7 +5693,7 @@
 	IN HANDLE TargetProcessHandle,
 	OUT PHANDLE TargetHandle,
 	IN ACCESS_MASK DesiredAccess,
-	IN BOOLEAN InheritHandle,
+	IN ULONG HandleAttributes,
 	IN ULONG Options
 	);
 
Index: lib/kernel32/misc/handle.c
===================================================================
RCS file: /CVS/ReactOS/reactos/lib/kernel32/misc/handle.c,v
retrieving revision 1.16
diff -u -r1.16 handle.c
--- lib/kernel32/misc/handle.c	23 Jan 2004 21:16:03 -0000	1.16
+++ lib/kernel32/misc/handle.c	23 Jul 2004 12:54:00 -0000
@@ -171,7 +171,7 @@
 			       hTargetProcessHandle,
 			       lpTargetHandle, 
 			       dwDesiredAccess, 
-			       (BOOLEAN)bInheritHandle,
+			       (bInheritHandle ? OBJ_INHERIT: 0),
 			       dwOptions);
    if (!NT_SUCCESS(errCode)) 
      {
Index: lib/kernel32/process/create.c
===================================================================
RCS file: /CVS/ReactOS/reactos/lib/kernel32/process/create.c,v
retrieving revision 1.87
diff -u -r1.87 create.c
--- lib/kernel32/process/create.c	7 Jul 2004 16:32:02 -0000	1.87
+++ lib/kernel32/process/create.c	23 Jul 2004 13:18:28 -0000
@@ -1061,7 +1061,7 @@
 			 hProcess,
 			 &Ppb->CurrentDirectoryHandle,
 			 0,
-			 TRUE,
+			 OBJ_INHERIT,
 			 DUPLICATE_SAME_ACCESS);
    }
 
@@ -1208,7 +1208,7 @@
                                      hProcess,
                                      &Ppb->hStdInput,
                                      0,
-                                     TRUE,
+                                     OBJ_INHERIT,
                                      DUPLICATE_SAME_ACCESS);
          if(!NT_SUCCESS(Status))
          {
@@ -1231,7 +1231,7 @@
                                      hProcess,
                                      &Ppb->hStdOutput,
                                      0,
-                                     TRUE,
+                                     OBJ_INHERIT,
                                      DUPLICATE_SAME_ACCESS);
          if(!NT_SUCCESS(Status))
          {
@@ -1268,7 +1268,7 @@
                                      hProcess,
                                      &Ppb->hStdError,
                                      0,
-                                     TRUE,
+                                     OBJ_INHERIT,
                                      DUPLICATE_SAME_ACCESS);
          if(!NT_SUCCESS(Status))
          {
Index: lib/kernel32/process/proc.c
===================================================================
RCS file: /CVS/ReactOS/reactos/lib/kernel32/process/proc.c,v
retrieving revision 1.63
diff -u -r1.63 proc.c
--- lib/kernel32/process/proc.c	2 Jul 2004 12:18:04 -0000	1.63
+++ lib/kernel32/process/proc.c	23 Jul 2004 13:19:16 -0000
@@ -731,7 +731,7 @@
 		       GetCurrentProcess(),
 		       &hProcessTmp,
 		       (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
-		       FALSE,
+		       0,
 		       0);
   if (!NT_SUCCESS(Status))
     {
@@ -793,7 +793,7 @@
 		       GetCurrentProcess(),
 		       &hProcessTmp,
 		       (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
-		       FALSE,
+		       0,
 		       0);
   if (!NT_SUCCESS(Status))
     {
Index: lib/ntdll/rtl/registry.c
===================================================================
RCS file: /CVS/ReactOS/reactos/lib/ntdll/rtl/registry.c,v
retrieving revision 1.28
diff -u -r1.28 registry.c
--- lib/ntdll/rtl/registry.c	20 Mar 2004 15:56:00 -0000	1.28
+++ lib/ntdll/rtl/registry.c	23 Jul 2004 13:20:30 -0000
@@ -48,7 +48,7 @@
 				 NtCurrentProcess(),
 				 KeyHandle,
 				 0,
-				 FALSE,
+				 0,
 				 DUPLICATE_SAME_ACCESS);
       return(Status);
     }
Index: ntoskrnl/cm/rtlfunc.c
===================================================================
RCS file: /CVS/ReactOS/reactos/ntoskrnl/cm/rtlfunc.c,v
retrieving revision 1.38
diff -u -r1.38 rtlfunc.c
--- ntoskrnl/cm/rtlfunc.c	3 Apr 2004 13:45:00 -0000	1.38
+++ ntoskrnl/cm/rtlfunc.c	23 Jul 2004 13:21:43 -0000
@@ -42,7 +42,7 @@
 				 NtCurrentProcess(),
 				 KeyHandle,
 				 0,
-				 FALSE,
+				 0,
 				 DUPLICATE_SAME_ACCESS);
       return(Status);
     }
Index: ntoskrnl/include/internal/ob.h
===================================================================
RCS file: /CVS/ReactOS/reactos/ntoskrnl/include/internal/ob.h,v
retrieving revision 1.20
diff -u -r1.20 ob.h
--- ntoskrnl/include/internal/ob.h	23 Jul 2004 21:43:11 -0000	1.20
+++ ntoskrnl/include/internal/ob.h	25 Jul 2004 13:45:30 -0000
@@ -94,7 +94,7 @@
 NTSTATUS ObCreateHandle(struct _EPROCESS* Process,
 			PVOID ObjectBody,
 			ACCESS_MASK GrantedAccess,
-			BOOLEAN Inherit,
+			ULONG HandleAttributes,
 			PHANDLE Handle);
 VOID ObCreateHandleTable(struct _EPROCESS* Parent,
 			 BOOLEAN Inherit,
@@ -111,26 +111,26 @@
 	       HANDLE Handle,
 	       PVOID *ObjectBody);
 
-NTSTATUS
+NTSTATUS FASTCALL
 ObpQueryHandleAttributes(HANDLE Handle,
-			 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
+                         POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
 
-NTSTATUS
+NTSTATUS FASTCALL
 ObpSetHandleAttributes(HANDLE Handle,
-		       POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
+                       POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
 
 NTSTATUS
 ObpCreateTypeObject(POBJECT_TYPE ObjectType);
 
 ULONG
 ObGetObjectHandleCount(PVOID Object);
-NTSTATUS
+NTSTATUS FASTCALL
 ObDuplicateObject(PEPROCESS SourceProcess,
 		  PEPROCESS TargetProcess,
 		  HANDLE SourceHandle,
 		  PHANDLE TargetHandle,
 		  ACCESS_MASK DesiredAccess,
-		  BOOLEAN InheritHandle,
+		  ULONG HandleAttributes,
 		  ULONG	Options);
 
 ULONG
@@ -155,5 +155,4 @@
 VOID
 ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
 
-
 #endif /* __INCLUDE_INTERNAL_OBJMGR_H */
Index: ntoskrnl/ob/handle.c
===================================================================
RCS file: /CVS/ReactOS/reactos/ntoskrnl/ob/handle.c,v
retrieving revision 1.57
diff -u -r1.57 handle.c
--- ntoskrnl/ob/handle.c	16 Jul 2004 19:54:05 -0000	1.57
+++ ntoskrnl/ob/handle.c	23 Jul 2004 13:15:58 -0000
@@ -48,20 +48,20 @@
 {
    PVOID ObjectBody;
    ACCESS_MASK GrantedAccess;
+   OBJECT_ATTRIBUTES Attributes;
 } HANDLE_REP, *PHANDLE_REP;
 
 #define HANDLE_BLOCK_ENTRIES ((PAGE_SIZE-sizeof(LIST_ENTRY))/sizeof(HANDLE_REP))
 
-#define OB_HANDLE_FLAG_MASK    0x00000007
 #define OB_HANDLE_FLAG_AUDIT   0x00000004
 #define OB_HANDLE_FLAG_PROTECT 0x00000002
 #define OB_HANDLE_FLAG_INHERIT 0x00000001
 
-#define OB_POINTER_TO_ENTRY(Pointer) \
-  (PVOID)((ULONG_PTR)(Pointer) & ~OB_HANDLE_FLAG_MASK)
+#define ObpLockProcessHandles(Process, OldIrql) \
+  KeAcquireSpinLock(&(Process)->HandleTable.ListLock, &(OldIrql))
 
-#define OB_ENTRY_TO_POINTER(Entry) \
-  (PVOID)((ULONG_PTR)(Entry) & ~OB_HANDLE_FLAG_MASK)
+#define ObpUnlockProcessHandles(Process, OldIrql) \
+  KeReleaseSpinLock(&(Process)->HandleTable.ListLock, (OldIrql))
 
 /*
  * PURPOSE: Defines a page's worth of handles
@@ -79,46 +79,40 @@
 
 /* FUNCTIONS ***************************************************************/
 
-
-static PHANDLE_REP ObpGetObjectByHandle(PHANDLE_TABLE HandleTable, HANDLE h)
-/*
- * FUNCTION: Get the data structure for a handle
- * ARGUMENTS:
- *         Process = Process to get the handle for
- *         h = Handle
- * ARGUMENTS: A pointer to the information about the handle on success,
- *            NULL on failure
- */
+PHANDLE_REP FASTCALL
+ObpGetObjectByHandle(PHANDLE_TABLE HandleTable,
+                     HANDLE Handle)
 {
-   PLIST_ENTRY current;
-   unsigned int handle = (((unsigned int)h) >> 2) - 1;
-   unsigned int count=handle/HANDLE_BLOCK_ENTRIES;
-   HANDLE_BLOCK* blk = NULL;
-   unsigned int i;
-   
-   DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable,h);
-   
-   current = HandleTable->ListHead.Flink;
-   DPRINT("current %x\n",current);
-   
-   for (i=0;i<count;i++)
-     {
-	current = current->Flink;
-	if (current == (&(HandleTable->ListHead)))
-	  {
-	     return(NULL);
-	  }
-     }
-   
-   blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
-   DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
-   return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
-}
+  PLIST_ENTRY Current;
+  ULONG i, h;
+  HANDLE_BLOCK *HandleBlock;
+  
+  DPRINT("ObpGetObjectByHandle(HandleTable 0x%x, h 0x%x)\n", HandleTable, Handle);
+  
+  Current = HandleTable->ListHead.Flink;
 
+  h = ((ULONG)Handle >> 2) - 1;
+  i = h / HANDLE_BLOCK_ENTRIES;
+  
+  while(i-- > 0)
+  {
+    Current = Current->Flink;
+    if(Current == &HandleTable->ListHead)
+    {
+      return NULL;
+    }
+  }
+  
+  HandleBlock = CONTAINING_RECORD(Current, HANDLE_BLOCK, entry);
 
-NTSTATUS
+  DPRINT("object: 0x%x\n", &(HandleBlock->handles[h % HANDLE_BLOCK_ENTRIES]));
+  
+  return &(HandleBlock->handles[h % HANDLE_BLOCK_ENTRIES]);
+}
+
+NTSTATUS FASTCALL
 ObpQueryHandleAttributes(HANDLE Handle,
-			 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
+                         POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
 {
   PEPROCESS Process;
   KIRQL oldIrql;
@@ -128,29 +122,27 @@
 
   Process = PsGetCurrentProcess();
 
-  KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
+  ObpLockProcessHandles(Process, oldIrql);
   HandleRep = ObpGetObjectByHandle(&Process->HandleTable,
-				   Handle);
+                                   Handle);
   if (HandleRep == NULL)
-    {
-      KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
-      return STATUS_INVALID_HANDLE;
-    }
+  {
+    ObpUnlockProcessHandles(Process, oldIrql);
+    return STATUS_INVALID_HANDLE;
+  }
 
-  HandleInfo->Inherit =
-    ((ULONG_PTR)HandleRep->ObjectBody & OB_HANDLE_FLAG_INHERIT);
-  HandleInfo->ProtectFromClose =
-    ((ULONG_PTR)HandleRep->ObjectBody & OB_HANDLE_FLAG_PROTECT);
+  HandleInfo->Inherit = ((HandleRep->Attributes.Attributes & OB_HANDLE_FLAG_INHERIT) != 0);
+  HandleInfo->ProtectFromClose = ((HandleRep->Attributes.Attributes & OB_HANDLE_FLAG_PROTECT) != 0);
 
-  KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+  ObpUnlockProcessHandles(Process, oldIrql);
 
   return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
+NTSTATUS FASTCALL
 ObpSetHandleAttributes(HANDLE Handle,
-		       POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
+                       POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
 {
   PEPROCESS Process;
   KIRQL oldIrql;
@@ -160,92 +152,117 @@
 
   Process = PsGetCurrentProcess();
 
-  KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
+  ObpLockProcessHandles(Process, oldIrql);
   HandleRep = ObpGetObjectByHandle(&Process->HandleTable,
-				   Handle);
+                                   Handle);
   if (HandleRep == NULL)
-    {
-      KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
-      return STATUS_INVALID_HANDLE;
-    }
+  {
+    ObpUnlockProcessHandles(Process, oldIrql);
+    return STATUS_INVALID_HANDLE;
+  }
 
   if (HandleInfo->Inherit)
-    HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody | OB_HANDLE_FLAG_INHERIT);
+    HandleRep->Attributes.Attributes |= OB_HANDLE_FLAG_INHERIT;
   else
-    HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody & ~OB_HANDLE_FLAG_INHERIT);
+    HandleRep->Attributes.Attributes &= ~OB_HANDLE_FLAG_INHERIT;
 
-  if (HandleInfo->ProtectFromClose)
-    HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody | OB_HANDLE_FLAG_PROTECT);
+  if (HandleInfo->Inherit)
+    HandleRep->Attributes.Attributes |= OB_HANDLE_FLAG_PROTECT;
   else
-    HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody & ~OB_HANDLE_FLAG_PROTECT);
-
+    HandleRep->Attributes.Attributes &= ~OB_HANDLE_FLAG_PROTECT;
+    
   /* FIXME: Do we need to set anything in the object header??? */
 
-  KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+  ObpUnlockProcessHandles(Process, oldIrql);
 
   return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
+NTSTATUS FASTCALL
 ObDuplicateObject(PEPROCESS SourceProcess,
-		  PEPROCESS TargetProcess,
-		  HANDLE SourceHandle,
-		  PHANDLE TargetHandle,
-		  ACCESS_MASK DesiredAccess,
-		  BOOLEAN InheritHandle,
-		  ULONG	Options)
+                  PEPROCESS TargetProcess,
+                  HANDLE SourceHandle,
+                  PHANDLE TargetHandle,
+                  ACCESS_MASK DesiredAccess,
+                  ULONG HandleAttributes,
+                  ULONG	Options)
 {
   KIRQL oldIrql;
   PHANDLE_REP SourceHandleRep;
   PVOID ObjectBody;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status;
 
-  KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
+  PreviousMode = ExGetPreviousMode();
+  
+  #if 0
+  if(PreviousMode != KernelMode)
+  {
+    /* FIXME - probe TargetHandle buffer */
+  }
+  #endif
+
+  ObpLockProcessHandles(SourceProcess, oldIrql);
   SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
-					 SourceHandle);
+                                         SourceHandle);
   if (SourceHandleRep == NULL)
-    {
-      KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-      return(STATUS_INVALID_HANDLE);
-    }
-  ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleRep->ObjectBody);
-  ObReferenceObjectByPointer(ObjectBody,
-			     0,
-			     NULL,
-			     UserMode);
+  {
+    ObpUnlockProcessHandles(SourceProcess, oldIrql);
+    return STATUS_INVALID_HANDLE;
+  }
+
+  ObjectBody = SourceHandleRep->ObjectBody;
+  Status = ObReferenceObjectByPointer(ObjectBody,
+                                      (PreviousMode == KernelMode ? 0 : DesiredAccess),
+			                                NULL,
+			                                PreviousMode);
+  if(!NT_SUCCESS(Status))
+  {
+    DPRINT("Failed to duplicated object due to missing access rights!\n");
+    return Status;
+  }
   
   if (Options & DUPLICATE_SAME_ACCESS)
-    {
-      DesiredAccess = SourceHandleRep->GrantedAccess;
-    }
+  {
+    DesiredAccess = SourceHandleRep->GrantedAccess;
+  }
   
-  KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-  ObCreateHandle(TargetProcess,
-		 ObjectBody,
-		 DesiredAccess,
-		 InheritHandle,
-		 TargetHandle);
+  ObpUnlockProcessHandles(SourceProcess, oldIrql);
+  
+  Status = ObCreateHandle(TargetProcess,
+                          ObjectBody,
+                          DesiredAccess,
+                          HandleAttributes,
+                          TargetHandle);
+  if(!NT_SUCCESS(Status))
+  {
+    ObDereferenceObject(ObjectBody);
+    
+    DPRINT("Failed to duplicate object, couldn't create new handle!\n");
+    return Status;
+  }
   
   if (Options & DUPLICATE_CLOSE_SOURCE)
-    {
-      ZwClose(SourceHandle);
-    }
+  {
+    ZwClose(SourceHandle);
+  }
   
   ObDereferenceObject(ObjectBody);
-  return(STATUS_SUCCESS);
+  return STATUS_SUCCESS;
 }
 
 /*
  * @implemented
  */
 NTSTATUS STDCALL 
-NtDuplicateObject (IN	HANDLE		SourceProcessHandle,
-		   IN	HANDLE		SourceHandle,
-		   IN	HANDLE		TargetProcessHandle,
-		   OUT	PHANDLE		UnsafeTargetHandle,
-		   IN	ACCESS_MASK	DesiredAccess,
-		   IN	BOOLEAN		InheritHandle,
-		   ULONG		Options)
+NtDuplicateObject(IN HANDLE SourceProcessHandle,
+                  IN HANDLE SourceHandle,
+                  IN HANDLE TargetProcessHandle,
+                  OUT PHANDLE UnsafeTargetHandle,
+                  IN ACCESS_MASK DesiredAccess,
+                  IN ULONG HandleAttributes,
+                  IN ULONG Options)
 /*
  * FUNCTION: Copies a handle from one process space to another
  * ARGUMENTS:
@@ -258,8 +275,7 @@
  *	   TargetHandle (OUT) = Caller should supply storage for the 
  *                              duplicated handle. 
  *	   DesiredAccess = The desired access to the handle.
- *	   InheritHandle = Indicates wheter the new handle will be inheritable
- *                         or not.
+ *	   HandleAttributes = Specifies the handle attributes for the new handle.
  *	   Options = Specifies special actions upon duplicating the handle. 
  *                   Can be one of the values DUPLICATE_CLOSE_SOURCE | 
  *                   DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies 
@@ -271,39 +287,142 @@
  * REMARKS: This function maps to the win32 DuplicateHandle.
  */
 {
-   PEPROCESS SourceProcess;
-   PEPROCESS TargetProcess;
-   PHANDLE_REP SourceHandleRep;
-   KIRQL oldIrql;
-   PVOID ObjectBody;
-   HANDLE TargetHandle;
-   NTSTATUS Status;
-   
-   ASSERT_IRQL(PASSIVE_LEVEL);
-   
-   Status = ObReferenceObjectByHandle(SourceProcessHandle,
-				      PROCESS_DUP_HANDLE,
-				      NULL,
-				      UserMode,
-				      (PVOID*)&SourceProcess,
-				      NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
-   Status = ObReferenceObjectByHandle(TargetProcessHandle,
-				      PROCESS_DUP_HANDLE,
-				      NULL,
-				      UserMode,
-				      (PVOID*)&TargetProcess,
-				      NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       ObDereferenceObject(SourceProcess);
-       return(Status);
-     }
+  PEPROCESS SourceProcess;
+  PEPROCESS TargetProcess;
+  KPROCESSOR_MODE PreviousMode;
+  PVOID ObjectBody;
+  HANDLE TargetHandle;
+  OBJECT_HANDLE_INFORMATION HandleInformation;
+  BOOL IsSourceProcess;
+  NTSTATUS Status;
+
+  ASSERT_IRQL(PASSIVE_LEVEL);
+
+  PreviousMode = ExGetPreviousMode();
+
+  Status = ObReferenceObjectByHandle(SourceProcessHandle,
+                                     PROCESS_DUP_HANDLE,
+                                     PsProcessType,
+                                     PreviousMode,
+                                     (PVOID*)&SourceProcess,
+                                     NULL);
+  if(!NT_SUCCESS(Status))
+  {
+    DPRINT("Failed to reference source process handle\n");
+    return Status;
+  }
 
-   /* Check for magic handle first */
+  IsSourceProcess = (PsGetCurrentProcess() == SourceProcess);
+  
+  if(!IsSourceProcess)
+  {
+    KeAttachProcess(SourceProcess);
+  }
+
+  Status = ObReferenceObjectByHandle(SourceHandle,
+                                     0,
+                                     NULL,
+                                     PreviousMode,
+                                     &ObjectBody,
+                                     &HandleInformation);
+  if(!IsSourceProcess)
+  {
+    KeDetachProcess();
+  }
+  
+  if(!NT_SUCCESS(Status))
+  {
+    DPRINT("Failed to reference the source handle!\n");
+    
+    ObDereferenceObject(SourceProcess);
+    return Status;
+  }
+  
+  if(TargetProcessHandle == NULL)
+  {
+    DPRINT("No target process handle specified, unable to duplicated the object\n");
+    
+    /* All we can do is close the handle, the caller didn't specify a target process
+       for this object so we can't copy it! */
+
+    if(Options & DUPLICATE_CLOSE_SOURCE)
+    {
+      /* we need to switch into the source process context in order to correctly
+         close the handle! */
+      if(!IsSourceProcess)
+      {
+        KeAttachProcess(SourceProcess);
+      }
+
+      ZwClose(SourceHandle);
+      
+      if(!IsSourceProcess)
+      {
+        KeDetachProcess();
+      }
+    }
+    
+    ObDereferenceObject(SourceHandle);
+    ObDereferenceObject(SourceProcess);
+    
+    return STATUS_SUCCESS;
+  }
+  
+  /*
+   * We can actually duplicate the handle, a target process is specified
+   */
+
+  Status = ObReferenceObjectByHandle(TargetProcessHandle,
+                                     PROCESS_DUP_HANDLE,
+                                     PsProcessType,
+                                     PreviousMode,
+                                     (PVOID*)&TargetProcess,
+                                     NULL);
+  if(!NT_SUCCESS(Status))
+  {
+    DPRINT("Failed to reference target process handle\n");
+    
+    /* We couldn't reference the target process, now let's just close the source
+       handle if required! */
+
+    if(Options & DUPLICATE_CLOSE_SOURCE)
+    {
+      /* we need to switch into the source process context in order to correctly
+         close the handle! */
+      if(!IsSourceProcess)
+      {
+        KeAttachProcess(SourceProcess);
+      }
+
+      ZwClose(SourceHandle);
+
+      if(!IsSourceProcess)
+      {
+        KeDetachProcess();
+      }
+    }
+
+    ObDereferenceObject(SourceHandle);
+    ObDereferenceObject(SourceProcess);
+    return Status;
+  }
+  
+  /* FIXME - Don't we have to check if the target process is about to terminate?!
+             We don't want to create a handle in a process that is terminated already. */
+
+  if(Options & DUPLICATE_SAME_ACCESS)
+  {
+    DesiredAccess = HandleInformation.GrantedAccess;
+  }
+  
+  HandleAttributes = ((Options & DUPLICATE_SAME_ATTRIBUTES) ?
+                      HandleInformation.HandleAttributes : /* copy the same attributes */
+                      HandleAttributes | HandleInformation.HandleAttributes); /* copy at least the same attributes */
+
+
+
+  #if 0
+  /* Check for magic handle first */
    if (SourceHandle == NtCurrentThread())
      {
        ObReferenceObjectByHandle(SourceHandle,
@@ -365,7 +484,7 @@
    ObDereferenceObject(TargetProcess);
    ObDereferenceObject(SourceProcess);
    ObDereferenceObject(ObjectBody);
-   
+   #endif
    Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
    if (!NT_SUCCESS(Status))
      {
@@ -398,7 +517,7 @@
 	
 	for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
 	  {
-	     ObjectBody = OB_ENTRY_TO_POINTER(current->handles[i].ObjectBody);
+	     ObjectBody = current->handles[i].ObjectBody;
 	     
 	     if (ObjectBody != NULL)
 	       {
@@ -522,7 +641,7 @@
 			current_block->handles[i].ObjectBody;
 		      new_block->handles[i].GrantedAccess = 
 			current_block->handles[i].GrantedAccess;
-		      InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block->handles[i].ObjectBody))->HandleCount));
+		      InterlockedIncrement(&(BODY_TO_HEADER(current_block->handles[i].ObjectBody)->HandleCount));
 		   }
 		}
 	     }
@@ -567,7 +686,7 @@
 	return STATUS_HANDLE_NOT_CLOSABLE;
      }
 
-   Body = OB_ENTRY_TO_POINTER(Rep->ObjectBody);
+   Body = Rep->ObjectBody;
    DPRINT("ObjectBody %x\n", Body);
    if (Body == NULL)
      {
@@ -603,7 +722,7 @@
 NTSTATUS ObCreateHandle(PEPROCESS Process,
 			PVOID ObjectBody,
 			ACCESS_MASK GrantedAccess,
-			BOOLEAN Inherit,
+			ULONG HandleAttributes,
 			PHANDLE HandleReturn)
 /*
  * FUNCTION: Add a handle referencing an object
@@ -646,9 +765,8 @@
 	     DPRINT("Considering slot %d containing %x\n",i,blk->handles[i]);
 	     if (blk->handles[i].ObjectBody == NULL)
 	       {
-		  blk->handles[i].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
-		  if (Inherit)
-		    blk->handles[i].ObjectBody = (PVOID)((ULONG_PTR)blk->handles[i].ObjectBody | OB_HANDLE_FLAG_INHERIT);
+		  blk->handles[i].ObjectBody = ObjectBody;
+		  blk->handles[i].Attributes.Attributes = HandleAttributes;
 		  blk->handles[i].GrantedAccess = GrantedAccess;
 		  KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
 		  *HandleReturn = (HANDLE)((handle + i) << 2);
@@ -674,9 +792,8 @@
    RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK));
    InsertTailList(&(Process->HandleTable.ListHead),
 		  &new_blk->entry);
-   new_blk->handles[0].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
-   if (Inherit)
-     new_blk->handles[0].ObjectBody = (PVOID)((ULONG_PTR)new_blk->handles[0].ObjectBody | OB_HANDLE_FLAG_INHERIT);
+   new_blk->handles[0].ObjectBody = ObjectBody;
+   new_blk->handles[i].Attributes.Attributes = HandleAttributes;
    new_blk->handles[0].GrantedAccess = GrantedAccess;
    KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
    *HandleReturn = (HANDLE)(handle << 2);
@@ -824,7 +941,7 @@
 			  oldIrql);
 	return(STATUS_INVALID_HANDLE);
      }
-   ObjectBody = OB_ENTRY_TO_POINTER(HandleRep->ObjectBody);
+   ObjectBody = HandleRep->ObjectBody;
    DPRINT("ObjectBody %p\n",ObjectBody);
    ObjectHeader = BODY_TO_HEADER(ObjectBody);
    DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
@@ -832,7 +949,7 @@
 			      0,
 			      NULL,
 			      UserMode);
-   Attributes = (ULONG_PTR)HandleRep->ObjectBody & OB_HANDLE_FLAG_MASK;
+   Attributes = HandleRep->Attributes.Attributes;
    GrantedAccess = HandleRep->GrantedAccess;
    KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
 		     oldIrql);
@@ -970,7 +1087,7 @@
 
       for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
 	{
-	  ObjectBody = OB_ENTRY_TO_POINTER(blk->handles[i].ObjectBody);
+	  ObjectBody = blk->handles[i].ObjectBody;
 	  if (ObjectBody != NULL)
 	    {
 	      Header = BODY_TO_HEADER(ObjectBody);


More information about the Ros-kernel mailing list