/* $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 */