- Return correct error. Spotted by Thomas.
[reactos.git] / reactos / ntoskrnl / ps / cid.c
index 2d6da14..935ca8f 100644 (file)
@@ -1,12 +1,11 @@
 /* $Id$
  *
- * COPYRIGHT:         See COPYING in the top level directory
- * PROJECT:           ReactOS kernel
- * FILE:              ntoskrnl/ps/clientid.c
- * PURPOSE:           Client ID (CID) management
- * PROGRAMMER:        Thomas Weidenmueller <w3seek@reactos.com>
- * REVISION HISTORY:
- *              9/20/2004: Created
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ps/cid.c
+ * PURPOSE:         Client ID (CID) management
+ *
+ * PROGRAMMERS:     Thomas Weidenmueller <w3seek@reactos.com>
  */
 
 /* INCLUDES ******************************************************************/
 
 /* GLOBALS ******************************************************************/
 
-/*
- * FIXME - use a global handle table instead!
- */
-
-KSPIN_LOCK CidLock;
-LIST_ENTRY CidHead;
-KEVENT CidReleaseEvent;
-LONG CidCounter = 0;
-LARGE_INTEGER ShortDelay, LongDelay;
+PHANDLE_TABLE PspCidTable = NULL;
 
-#define TAG_CIDOBJECT TAG('C', 'I', 'D', 'O')
+#define CID_FLAG_PROCESS 0x1
+#define CID_FLAG_THREAD 0x2
+#define CID_FLAGS_MASK (CID_FLAG_PROCESS | CID_FLAG_THREAD)
 
 /* FUNCTIONS *****************************************************************/
 
 VOID INIT_FUNCTION
 PsInitClientIDManagment(VOID)
 {
-   InitializeListHead(&CidHead);
-   KeInitializeSpinLock(&CidLock);
-   KeInitializeEvent(&CidReleaseEvent, SynchronizationEvent, FALSE);
-   ShortDelay.QuadPart = -100LL;
-   LongDelay.QuadPart = -100000LL;
+  PspCidTable = ExCreateHandleTable(NULL);
+  ASSERT(PspCidTable);
 }
 
-VOID
-PspReferenceCidObject(PCID_OBJECT Object)
+NTSTATUS
+PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle)
 {
-  InterlockedIncrement(&Object->ref);
-}
+  HANDLE_TABLE_ENTRY NewEntry;
+  LONG ExHandle;
 
-VOID
-PspDereferenceCidObject(PCID_OBJECT Object)
-{
-  if(InterlockedDecrement(&Object->ref) == 0)
+  PAGED_CODE();
+
+  NewEntry.u1.Object = Object;
+  if(ObjectType == PsThreadType)
+    NewEntry.u2.GrantedAccess = CID_FLAG_THREAD;
+  else if(ObjectType == PsProcessType)
+    NewEntry.u2.GrantedAccess = CID_FLAG_PROCESS;
+  else
   {
-    ExFreePool(Object);
+    DPRINT1("Can't create CID handles for %wZ objects\n", &ObjectType->Name);
+    KEBUGCHECK(0);
   }
-}
 
-NTSTATUS
-PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle)
-{
-  KIRQL oldIrql;
-  PCID_OBJECT cido = ExAllocatePoolWithTag(NonPagedPool,
-                                           sizeof(CID_OBJECT),
-                                           TAG_CIDOBJECT);
-  if(cido != NULL)
+  ExHandle = ExCreateHandle(PspCidTable,
+                            &NewEntry);
+  if(ExHandle != EX_INVALID_HANDLE)
   {
-    cido->ref = 1;
-    ExInitializeFastMutex(&cido->Lock);
-    cido->Obj.Object = Object;
-
-    KeAcquireSpinLock(&CidLock, &oldIrql);
-    cido->Handle = (HANDLE)(++CidCounter);
-    InsertTailList(&CidHead, &cido->Entry);
-    KeReleaseSpinLock(&CidLock, oldIrql);
-
-    *Handle = cido->Handle;
+    *Handle = EX_HANDLE_TO_HANDLE(ExHandle);
     return STATUS_SUCCESS;
   }
-  
-  return STATUS_INSUFFICIENT_RESOURCES;
+
+  return STATUS_UNSUCCESSFUL;
 }
 
 NTSTATUS
 PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
 {
-  PCID_OBJECT cido, Found = NULL;
-  PLIST_ENTRY Current;
-  KIRQL oldIrql;
-  
-  if(CidHandle == NULL)
-  {
-    return STATUS_INVALID_PARAMETER;
-  }
-  
-  KeAcquireSpinLock(&CidLock, &oldIrql);
-  Current = CidHead.Flink;
-  while(Current != &CidHead)
+  PHANDLE_TABLE_ENTRY Entry;
+  LONG ExHandle = HANDLE_TO_EX_HANDLE(CidHandle);
+
+  PAGED_CODE();
+
+  KeEnterCriticalRegion();
+
+  Entry = ExMapHandleToPointer(PspCidTable,
+                               ExHandle);
+  if(Entry != NULL)
   {
-    cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
-    if(cido->Handle == CidHandle)
+    if((ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD)) ||
+       (ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS)))
+    {
+      ExDestroyHandleByEntry(PspCidTable,
+                             Entry,
+                             ExHandle);
+      KeLeaveCriticalRegion();
+      return STATUS_SUCCESS;
+    }
+    else
     {
-      RemoveEntryList(&cido->Entry);
-      cido->Handle = NULL;
-      Found = cido;
-      break;
+      ExUnlockHandleTableEntry(PspCidTable,
+                               Entry);
+      KeLeaveCriticalRegion();
+      return STATUS_OBJECT_TYPE_MISMATCH;
     }
-    Current = Current->Flink;
   }
-  KeReleaseSpinLock(&CidLock, oldIrql);
+  KeLeaveCriticalRegion();
+  return STATUS_INVALID_HANDLE;
+}
+
+PHANDLE_TABLE_ENTRY
+PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object)
+{
+  PHANDLE_TABLE_ENTRY Entry;
+
+  PAGED_CODE();
 
-  if(Found != NULL)
+  KeEnterCriticalRegion();
+
+  Entry = ExMapHandleToPointer(PspCidTable,
+                               HANDLE_TO_EX_HANDLE(CidHandle));
+  if(Entry != NULL)
   {
-    PspDereferenceCidObject(Found);
-    return STATUS_SUCCESS;
+    if((ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS)) ||
+       (ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD)))
+    {
+      *Object = Entry->u1.Object;
+      return Entry;
+    }
+    else
+    {
+      DPRINT1("CID Obj type mismatch handle 0x%x %wZ vs 0x%x\n", CidHandle,
+              &ObjectType->Name, Entry->u2.GrantedAccess);
+      ExUnlockHandleTableEntry(PspCidTable,
+                               Entry);
+    }
   }
 
-  return STATUS_UNSUCCESSFUL;
+  KeLeaveCriticalRegion();
+
+  return NULL;
 }
 
-PCID_OBJECT
-PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
+                          OUT PEPROCESS *Process OPTIONAL,
+                          OUT PETHREAD *Thread)
 {
-  PCID_OBJECT cido, Found = NULL;
-  PLIST_ENTRY Current;
-  KIRQL oldIrql;
-  
-  if(CidHandle == NULL)
-  {
-    return NULL;
-  }
-  
-  KeAcquireSpinLock(&CidLock, &oldIrql);
-  Current = CidHead.Flink;
-  while(Current != &CidHead)
+  PHANDLE_TABLE_ENTRY CidEntry;
+  PETHREAD FoundThread;
+  NTSTATUS Status = STATUS_INVALID_CID;
+
+  PAGED_CODE();
+
+  ASSERT(Thread);
+  ASSERT(Cid);
+
+  CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread);
+  if(CidEntry != NULL)
   {
-    cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
-    if(cido->Handle == CidHandle)
+    ObReferenceObject(FoundThread);
+
+    PsUnlockCidHandle(CidEntry);
+
+    if(Process != NULL)
     {
-      Found = cido;
-      PspReferenceCidObject(Found);
-      break;
+      *Process = FoundThread->ThreadsProcess;
     }
-    Current = Current->Flink;
+    *Thread = FoundThread;
+    Status = STATUS_SUCCESS;
   }
-  KeReleaseSpinLock(&CidLock, oldIrql);
-  
-  if(Found != NULL)
+
+  return Status;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsLookupThreadByThreadId(IN HANDLE ThreadId,
+                        OUT PETHREAD *Thread)
+{
+  PHANDLE_TABLE_ENTRY CidEntry;
+  PETHREAD FoundThread;
+  NTSTATUS Status = STATUS_INVALID_CID;
+
+  PAGED_CODE();
+
+  ASSERT(Thread);
+
+  CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread);
+  if(CidEntry != NULL)
   {
-    ExAcquireFastMutex(&Found->Lock);
+    ObReferenceObject(FoundThread);
+
+    PsUnlockCidHandle(CidEntry);
+
+    *Thread = FoundThread;
+    Status = STATUS_SUCCESS;
   }
 
-  return Found;
+  return Status;
 }
 
 VOID
-PsUnlockCidObject(PCID_OBJECT CidObject)
+PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry)
 {
-  ExReleaseFastMutex(&CidObject->Lock);
-  PspDereferenceCidObject(CidObject);
+  PAGED_CODE();
+
+  ExUnlockHandleTableEntry(PspCidTable,
+                           CidEntry);
+  KeLeaveCriticalRegion();
 }
 
 /* EOF */