- implement generic executive handle tables (since there don't exist documents that describe the parameters of most of these functions (which are kernel internal only), i made them up as required)
- adjusted OB's handle manager to use ex handle tables
- adjusted the client id manager to use ex handle tables
svn path=/trunk/; revision=14007
# be optimized for.
#
-OARCH := i486
+OARCH := i586
#
# Whether to compile in the kernel debugger
#
-KDBG := 0
+KDBG := 1
#
# Whether to compile for debugging
#
-DBG := 0
+DBG := 1
#
# Whether to compile with optimizations
#
-OPTIMIZED := 0
+OPTIMIZED := 1
#
# Whether to compile a multiprocessor or single processor version
#ifndef __USE_W32API
+static __inline
+VOID
+KeMemoryBarrier(
+ VOID)
+{
+ volatile LONG Barrier;
+ __asm__ __volatile__ ("xchg %%eax, %0" : : "m" (Barrier) : "%eax");
+}
+
VOID STDCALL KeAcquireSpinLockAtDpcLevel (IN PKSPIN_LOCK SpinLock);
#define KefAcquireSpinLockAtDpcLevel KeAcquireSpinLockAtDpcLevel
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
+typedef struct _HANDLE_TABLE_ENTRY_INFO {
+ ULONG AuditMask;
+} HANDLE_TABLE_ENTRY_INFO, *PHANDLE_TABLE_ENTRY_INFO;
+
+typedef struct _HANDLE_TABLE_ENTRY {
+ union {
+ PVOID Object;
+ ULONG_PTR ObAttributes;
+ PHANDLE_TABLE_ENTRY_INFO InfoTable;
+ ULONG_PTR Value;
+ } u1;
+ union {
+ ULONG GrantedAccess;
+ USHORT GrantedAccessIndex;
+ LONG NextFreeTableEntry;
+ } u2;
+} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
+
#endif /* __USE_W32API */
typedef struct _HANDLE_TABLE
{
- LIST_ENTRY ListHead;
- KSPIN_LOCK ListLock;
-} HANDLE_TABLE;
+ ULONG Flags;
+ LONG HandleCount;
+ PHANDLE_TABLE_ENTRY **Table;
+ PEPROCESS QuotaProcess;
+ HANDLE UniqueProcessId;
+ LONG FirstFreeTableEntry;
+ LONG NextIndexNeedingPool;
+ ERESOURCE HandleTableLock;
+ LIST_ENTRY HandleTableList;
+ KEVENT HandleContentionEvent;
+} HANDLE_TABLE, *PHANDLE_TABLE;
#ifndef __USE_W32API
-typedef struct _HANDLE_TABLE *PHANDLE_TABLE;
-
/*
* FIXME: These will eventually become centerfold in the compliant Ob Manager
* For now, they are only here so Device Map is properly defined before the header
ex/event.o \
ex/evtpair.o \
ex/fmutex.o \
+ ex/handle.o \
ex/hashtab.o \
ex/init.o \
ex/interlck.o \
--- /dev/null
+/* $Id:$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ex/handle.c
+ * PURPOSE: Generic Executive Handle Tables
+ *
+ * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
+ *
+ * TODO:
+ *
+ * - the last entry of a subhandle list should be reserved for auditing
+ *
+ * ExSweepHandleTable (???)
+ * ExReferenceHandleDebugInfo
+ * ExSnapShotHandleTables
+ * ExpMoveFreeHandles (???)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ntoskrnl.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+static LIST_ENTRY ExpHandleTableHead;
+static FAST_MUTEX ExpHandleTableListLock;
+static LARGE_INTEGER ExpHandleShortWait;
+
+#define ExAcquireHandleTableListLock() \
+ ExAcquireFastMutexUnsafe(&ExpHandleTableListLock)
+
+#define ExReleaseHandleTableListLock() \
+ ExReleaseFastMutexUnsafe(&ExpHandleTableListLock)
+
+#define ExAcquireHandleTableLockExclusive(HandleTable) \
+ ExAcquireResourceExclusiveLite(&(HandleTable)->HandleTableLock, TRUE)
+
+#define ExAcquireHandleTableLockShared(HandleTable) \
+ ExAcquireResourceSharedLite(&(HandleTable)->HandleTableLock, TRUE)
+
+#define ExReleaseHandleTableLock(HandleTable) \
+ ExReleaseResourceLite(&(HandleTable)->HandleTableLock)
+
+/*
+ 5 bits: reserved
+ 8 bits: top level index
+ 10 bits: middle level index
+ 9 bits: sub handle index
+*/
+#define N_TLI_BITS 8 /* top level index */
+#define N_MLI_BITS 10 /* middle level index */
+#define N_EI_BITS 9 /* sub handle index */
+#define TLI_OFFSET (N_MLI_BITS + N_EI_BITS)
+#define MLI_OFFSET N_EI_BITS
+#define EI_OFFSET 0
+
+#define N_TOPLEVEL_POINTERS (1 << N_TLI_BITS)
+#define N_MIDDLELEVEL_POINTERS (1 << N_MLI_BITS)
+#define N_SUBHANDLE_ENTRIES (1 << N_EI_BITS)
+#define EX_MAX_HANDLES (N_TOPLEVEL_POINTERS * N_MIDDLELEVEL_POINTERS * N_SUBHANDLE_ENTRIES)
+
+#define VALID_HANDLE_MASK (((N_TOPLEVEL_POINTERS - 1) << TLI_OFFSET) | \
+ ((N_MIDDLELEVEL_POINTERS - 1) << MLI_OFFSET) | ((N_SUBHANDLE_ENTRIES - 1) << EI_OFFSET))
+#define TLI_FROM_HANDLE(index) (ULONG)(((index) >> TLI_OFFSET) & (N_TOPLEVEL_POINTERS - 1))
+#define MLI_FROM_HANDLE(index) (ULONG)(((index) >> MLI_OFFSET) & (N_MIDDLELEVEL_POINTERS - 1))
+#define ELI_FROM_HANDLE(index) (ULONG)(((index) >> EI_OFFSET) & (N_SUBHANDLE_ENTRIES - 1))
+
+#define N_MAX_HANDLE (N_TOPLEVEL_POINTERS * N_MIDDLELEVEL_POINTERS * N_SUBHANDLE_ENTRIES)
+
+#define BUILD_HANDLE(tli, mli, eli) ((((tli) & (N_TOPLEVEL_POINTERS - 1)) << TLI_OFFSET) | \
+ (((mli) & (N_MIDDLELEVEL_POINTERS - 1)) << MLI_OFFSET) | (((eli) & (N_SUBHANDLE_ENTRIES - 1)) << EI_OFFSET))
+
+#define IS_INVALID_EX_HANDLE(index) \
+ (((index) & ~VALID_HANDLE_MASK) != 0)
+#define IS_VALID_EX_HANDLE(index) \
+ (((index) & ~VALID_HANDLE_MASK) == 0)
+
+/******************************************************************************/
+
+VOID
+ExpInitializeHandleTables(VOID)
+{
+ ExpHandleShortWait.QuadPart = -50000;
+ InitializeListHead(&ExpHandleTableHead);
+ ExInitializeFastMutex(&ExpHandleTableListLock);
+}
+
+PHANDLE_TABLE
+ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL)
+{
+ PHANDLE_TABLE HandleTable;
+
+ PAGED_CODE();
+
+ if(QuotaProcess != NULL)
+ {
+ /* FIXME - Charge process quota before allocating the handle table! */
+ }
+
+ /* allocate enough memory for the handle table and the lowest level */
+ HandleTable = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(HANDLE_TABLE) + (N_TOPLEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY*)),
+ TAG('E', 'x', 'H', 't'));
+ if(HandleTable != NULL)
+ {
+ /* initialize the handle table */
+ HandleTable->Flags = 0;
+ HandleTable->HandleCount = 0;
+ HandleTable->Table = (PHANDLE_TABLE_ENTRY**)(HandleTable + 1);
+ HandleTable->QuotaProcess = QuotaProcess;
+ HandleTable->FirstFreeTableEntry = -1; /* no entries freed so far */
+ HandleTable->NextIndexNeedingPool = 0; /* no entries freed so far, so we have to allocate already for the first handle */
+ HandleTable->UniqueProcessId = (QuotaProcess ? QuotaProcess->UniqueProcessId : PsGetCurrentProcessId());
+
+ ExInitializeResource(&HandleTable->HandleTableLock);
+
+ KeInitializeEvent(&HandleTable->HandleContentionEvent,
+ NotificationEvent,
+ FALSE);
+
+ RtlZeroMemory(HandleTable->Table, N_TOPLEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY*));
+
+ /* during bootup KeGetCurrentThread() might be NULL, needs to be fixed... */
+ if(KeGetCurrentThread() != NULL)
+ {
+ /* insert it into the global handle table list */
+ KeEnterCriticalRegion();
+
+ ExAcquireHandleTableListLock();
+ InsertTailList(&ExpHandleTableHead,
+ &HandleTable->HandleTableList);
+ ExReleaseHandleTableListLock();
+
+ KeLeaveCriticalRegion();
+ }
+ else
+ {
+ InsertTailList(&ExpHandleTableHead,
+ &HandleTable->HandleTableList);
+ }
+ }
+ else
+ {
+ /* FIXME - return the quota to the process */
+ }
+
+ return HandleTable;
+}
+
+static BOOLEAN
+ExLockHandleTableEntryNoDestructionCheck(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry)
+{
+ ULONG_PTR Current, New;
+
+ PAGED_CODE();
+
+ DPRINT("Entering handle table entry 0x%x lock...\n", Entry);
+
+ ASSERT(HandleTable);
+ ASSERT(Entry);
+
+ for(;;)
+ {
+ Current = (volatile ULONG_PTR)Entry->u1.Object;
+
+ if(!Current)
+ {
+ DPRINT("Attempted to lock empty handle table entry 0x%x or handle table shut down\n", Entry);
+ break;
+ }
+
+ if(!(Current & EX_HANDLE_ENTRY_LOCKED))
+ {
+ New = Current | EX_HANDLE_ENTRY_LOCKED;
+ if(InterlockedCompareExchangePointer(&Entry->u1.Object,
+ (PVOID)New,
+ (PVOID)Current) == (PVOID)Current)
+ {
+ DPRINT("SUCCESS handle table 0x%x entry 0x%x lock\n", HandleTable, Entry);
+ /* we acquired the lock */
+ return TRUE;
+ }
+ }
+
+ /* wait about 5ms at maximum so we don't wait forever in unfortunate
+ co-incidences where releasing the lock in another thread happens right
+ before we're waiting on the contention event to get pulsed, which might
+ never happen again... */
+ KeWaitForSingleObject(&HandleTable->HandleContentionEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ &ExpHandleShortWait);
+ }
+
+ return FALSE;
+}
+
+VOID
+ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
+ IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback OPTIONAL,
+ IN PVOID Context OPTIONAL)
+{
+ PHANDLE_TABLE_ENTRY **tlp, **lasttlp, *mlp, *lastmlp;
+ PEPROCESS QuotaProcess;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+
+ KeEnterCriticalRegion();
+
+ /* ensure there's no other operations going by acquiring an exclusive lock */
+ ExAcquireHandleTableLockExclusive(HandleTable);
+
+ ASSERT(!(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING));
+
+ HandleTable->Flags |= EX_HANDLE_TABLE_CLOSING;
+
+ KePulseEvent(&HandleTable->HandleContentionEvent,
+ EVENT_INCREMENT,
+ FALSE);
+
+ /* remove the handle table from the global handle table list */
+ ExAcquireHandleTableListLock();
+ RemoveEntryList(&HandleTable->HandleTableList);
+ ExReleaseHandleTableListLock();
+
+ /* call the callback function to cleanup the objects associated with the
+ handle table */
+ if(DestroyHandleCallback != NULL)
+ {
+ for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
+ tlp != lasttlp;
+ tlp++)
+ {
+ if((*tlp) != NULL)
+ {
+ for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
+ mlp != lastmlp;
+ mlp++)
+ {
+ if((*mlp) != NULL)
+ {
+ PHANDLE_TABLE_ENTRY curee, laste;
+
+ for(curee = *mlp, laste = *mlp + N_SUBHANDLE_ENTRIES;
+ curee != laste;
+ curee++)
+ {
+ if(curee->u1.Object != NULL && ExLockHandleTableEntryNoDestructionCheck(HandleTable, curee))
+ {
+ DestroyHandleCallback(HandleTable, curee->u1.Object, curee->u2.GrantedAccess, Context);
+ ExUnlockHandleTableEntry(HandleTable, curee);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ QuotaProcess = HandleTable->QuotaProcess;
+
+ /* free the tables */
+ for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
+ tlp != lasttlp;
+ tlp++)
+ {
+ if((*tlp) != NULL)
+ {
+ for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
+ mlp != lastmlp;
+ mlp++)
+ {
+ if((*mlp) != NULL)
+ {
+ ExFreePool(*mlp);
+
+ if(QuotaProcess != NULL)
+ {
+ /* FIXME - return the quota to the process */
+ }
+ }
+ }
+
+ ExFreePool(*tlp);
+
+ if(QuotaProcess != NULL)
+ {
+ /* FIXME - return the quota to the process */
+ }
+ }
+ }
+
+ ExReleaseHandleTableLock(HandleTable);
+
+ KeLeaveCriticalRegion();
+
+ /* free the handle table */
+ ExDeleteResource(&HandleTable->HandleTableLock);
+ ExFreePool(HandleTable);
+
+ if(QuotaProcess != NULL)
+ {
+ /* FIXME - return the quota to the process */
+ }
+}
+
+PHANDLE_TABLE
+ExDupHandleTable(IN PEPROCESS QuotaProcess OPTIONAL,
+ IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL,
+ IN PVOID Context OPTIONAL,
+ IN PHANDLE_TABLE SourceHandleTable)
+{
+ PHANDLE_TABLE HandleTable;
+
+ PAGED_CODE();
+
+ ASSERT(SourceHandleTable);
+
+ HandleTable = ExCreateHandleTable(QuotaProcess);
+ if(HandleTable != NULL)
+ {
+ PHANDLE_TABLE_ENTRY **tlp, **srctlp, **etlp, *mlp, *srcmlp, *emlp, stbl, srcstbl, estbl;
+ LONG tli, mli, eli;
+
+ tli = mli = eli = 0;
+
+ /* make sure the other handle table isn't being changed during the duplication */
+ ExAcquireHandleTableLockShared(SourceHandleTable);
+
+ /* allocate enough tables */
+ etlp = SourceHandleTable->Table + N_TOPLEVEL_POINTERS;
+ for(srctlp = SourceHandleTable->Table, tlp = HandleTable->Table;
+ srctlp != etlp;
+ srctlp++, tlp++)
+ {
+ if(*srctlp != NULL)
+ {
+ /* allocate middle level entry tables */
+ if(QuotaProcess != NULL)
+ {
+ /* FIXME - Charge process quota before allocating the handle table! */
+ }
+
+ *tlp = ExAllocatePoolWithTag(PagedPool,
+ N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY),
+ TAG('E', 'x', 'H', 't'));
+ if(*tlp != NULL)
+ {
+ RtlZeroMemory(*tlp, N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY));
+
+ KeMemoryBarrier();
+
+ emlp = *srctlp + N_MIDDLELEVEL_POINTERS;
+ for(srcmlp = *srctlp, mlp = *tlp;
+ srcmlp != emlp;
+ srcmlp++, mlp++)
+ {
+ if(*srcmlp != NULL)
+ {
+ /* allocate subhandle tables */
+ if(QuotaProcess != NULL)
+ {
+ /* FIXME - Charge process quota before allocating the handle table! */
+ }
+
+ *mlp = ExAllocatePoolWithTag(PagedPool,
+ N_SUBHANDLE_ENTRIES * sizeof(HANDLE_TABLE_ENTRY),
+ TAG('E', 'x', 'H', 't'));
+ if(*mlp != NULL)
+ {
+ RtlZeroMemory(*mlp, N_SUBHANDLE_ENTRIES * sizeof(HANDLE_TABLE_ENTRY));
+ }
+ else
+ {
+ goto freehandletable;
+ }
+ }
+ else
+ {
+ *mlp = NULL;
+ }
+ }
+ }
+ else
+ {
+freehandletable:
+ DPRINT1("Failed to duplicate handle table 0x%x\n", SourceHandleTable);
+
+ ExReleaseHandleTableLock(SourceHandleTable);
+
+ ExDestroyHandleTable(HandleTable,
+ NULL,
+ NULL);
+ /* allocate an empty handle table */
+ return ExCreateHandleTable(QuotaProcess);
+ }
+ }
+ }
+
+ /* duplicate the handles */
+ HandleTable->HandleCount = SourceHandleTable->HandleCount;
+ HandleTable->FirstFreeTableEntry = SourceHandleTable->FirstFreeTableEntry;
+ HandleTable->NextIndexNeedingPool = SourceHandleTable->NextIndexNeedingPool;
+
+ /* make sure all tables are zeroed */
+ KeMemoryBarrier();
+
+ etlp = SourceHandleTable->Table + N_TOPLEVEL_POINTERS;
+ for(srctlp = SourceHandleTable->Table, tlp = HandleTable->Table;
+ srctlp != etlp;
+ srctlp++, tlp++, tli++)
+ {
+ if(*srctlp != NULL)
+ {
+ ASSERT(*tlp != NULL);
+
+ emlp = *srctlp + N_MIDDLELEVEL_POINTERS;
+ for(srcmlp = *srctlp, mlp = *tlp;
+ srcmlp != emlp;
+ srcmlp++, mlp++, mli++)
+ {
+ if(*srcmlp != NULL)
+ {
+ ASSERT(*mlp != NULL);
+
+ /* walk all handle entries and duplicate them if wanted */
+ estbl = *srcmlp + N_SUBHANDLE_ENTRIES;
+ for(srcstbl = *srcmlp, stbl = *mlp;
+ srcstbl != estbl;
+ srcstbl++, stbl++, eli++)
+ {
+ /* try to duplicate the source handle */
+ if(srcstbl->u1.Object != NULL &&
+ ExLockHandleTableEntry(SourceHandleTable,
+ srcstbl))
+ {
+ /* ask the caller if this handle should be duplicated */
+ if(DuplicateHandleCallback != NULL &&
+ !DuplicateHandleCallback(HandleTable,
+ srcstbl,
+ Context))
+ {
+ /* free the entry and chain it into the free list */
+ HandleTable->HandleCount--;
+ stbl->u1.Object = NULL;
+ stbl->u2.NextFreeTableEntry = HandleTable->FirstFreeTableEntry;
+ HandleTable->FirstFreeTableEntry = BUILD_HANDLE(tli, mli, eli);
+ }
+ else
+ {
+ /* duplicate the handle and unlock it */
+ stbl->u2.GrantedAccess = srcstbl->u2.GrantedAccess;
+ stbl->u1.ObAttributes = srcstbl->u1.ObAttributes & ~EX_HANDLE_ENTRY_LOCKED;
+ }
+ ExUnlockHandleTableEntry(SourceHandleTable,
+ srcstbl);
+ }
+ else
+ {
+ /* this is a free handle table entry, copy over the entire
+ structure as-is */
+ *stbl = *srcstbl;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* release the source handle table */
+ ExReleaseHandleTableLock(SourceHandleTable);
+ }
+
+ return HandleTable;
+}
+
+static PHANDLE_TABLE_ENTRY
+ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ OUT PLONG Handle)
+{
+ PHANDLE_TABLE_ENTRY Entry = NULL;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+ ASSERT(Handle);
+ ASSERT(KeGetCurrentThread() != NULL);
+
+ DPRINT("HT[0x%x]: HandleCount: %d\n", HandleTable, HandleTable->HandleCount);
+
+ if(HandleTable->HandleCount < EX_MAX_HANDLES)
+ {
+ ULONG tli, mli, eli;
+
+ if(HandleTable->FirstFreeTableEntry != -1)
+ {
+ /* there's a free handle entry we can just grab and use */
+ tli = TLI_FROM_HANDLE(HandleTable->FirstFreeTableEntry);
+ mli = MLI_FROM_HANDLE(HandleTable->FirstFreeTableEntry);
+ eli = ELI_FROM_HANDLE(HandleTable->FirstFreeTableEntry);
+
+ /* the pointer should be valid in any way!!! */
+ ASSERT(HandleTable->Table[tli]);
+ ASSERT(HandleTable->Table[tli][mli]);
+
+ Entry = &HandleTable->Table[tli][mli][eli];
+
+ *Handle = HandleTable->FirstFreeTableEntry;
+
+ /* save the index to the next free handle (if available) */
+ HandleTable->FirstFreeTableEntry = Entry->u2.NextFreeTableEntry;
+ Entry->u2.NextFreeTableEntry = 0;
+ Entry->u1.Object = NULL;
+
+ HandleTable->HandleCount++;
+ }
+ else
+ {
+ /* we need to allocate a new subhandle table first */
+ PHANDLE_TABLE_ENTRY cure, laste, ntbl, *nmtbl;
+ ULONG i;
+ BOOLEAN AllocatedMtbl;
+
+ ASSERT(HandleTable->NextIndexNeedingPool <= N_MAX_HANDLE);
+
+ /* the index of the next table to be allocated was saved in
+ NextIndexNeedingPool the last time a handle entry was allocated and
+ the subhandle entry list was full. the subhandle entry index of
+ NextIndexNeedingPool should be 0 here! */
+ tli = TLI_FROM_HANDLE(HandleTable->NextIndexNeedingPool);
+ mli = MLI_FROM_HANDLE(HandleTable->NextIndexNeedingPool);
+ DPRINT("HandleTable->NextIndexNeedingPool: 0x%x\n", HandleTable->NextIndexNeedingPool);
+ DPRINT("tli: 0x%x mli: 0x%x eli: 0x%x\n", tli, mli, ELI_FROM_HANDLE(HandleTable->NextIndexNeedingPool));
+
+ ASSERT(ELI_FROM_HANDLE(HandleTable->NextIndexNeedingPool) == 0);
+
+ DPRINT("HandleTable->Table[%d] == 0x%x\n", tli, HandleTable->Table[tli]);
+
+ /* allocate a middle level entry list if required */
+ nmtbl = HandleTable->Table[tli];
+ if(nmtbl == NULL)
+ {
+ if(HandleTable->QuotaProcess != NULL)
+ {
+ /* FIXME - Charge process quota before allocating the handle table! */
+ }
+
+ nmtbl = ExAllocatePoolWithTag(PagedPool,
+ N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY),
+ TAG('E', 'x', 'H', 't'));
+ if(nmtbl == NULL)
+ {
+ if(HandleTable->QuotaProcess != NULL)
+ {
+ /* FIXME - return the quota to the process */
+ }
+
+ return NULL;
+ }
+
+ /* clear the middle level entry list */
+ RtlZeroMemory(nmtbl, N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY));
+
+ /* make sure the table was zeroed before we set one item */
+ KeMemoryBarrier();
+
+ /* note, don't set the the pointer in the top level list yet because we
+ might screw up lookups if allocating a subhandle entry table failed
+ and this newly allocated table might get freed again */
+ AllocatedMtbl = TRUE;
+ }
+ else
+ {
+ AllocatedMtbl = FALSE;
+
+ /* allocate a subhandle entry table in any case! */
+ ASSERT(nmtbl[mli] == NULL);
+ }
+
+ DPRINT("HandleTable->Table[%d][%d] == 0x%x\n", tli, mli, nmtbl[mli]);
+
+ if(HandleTable->QuotaProcess != NULL)
+ {
+ /* FIXME - Charge process quota before allocating the handle table! */
+ }
+
+ ntbl = ExAllocatePoolWithTag(PagedPool,
+ N_SUBHANDLE_ENTRIES * sizeof(HANDLE_TABLE_ENTRY),
+ TAG('E', 'x', 'H', 't'));
+ if(ntbl == NULL)
+ {
+ if(HandleTable->QuotaProcess != NULL)
+ {
+ /* FIXME - Return process quota charged */
+ }
+
+ /* free the middle level entry list, if allocated, because it's empty and
+ unused */
+ if(AllocatedMtbl)
+ {
+ ExFreePool(nmtbl);
+
+ if(HandleTable->QuotaProcess != NULL)
+ {
+ /* FIXME - Return process quota charged */
+ }
+ }
+
+ return NULL;
+ }
+
+ /* let's just use the very first entry */
+ Entry = ntbl;
+ Entry->u1.ObAttributes = EX_HANDLE_ENTRY_LOCKED;
+ Entry->u2.NextFreeTableEntry = 0;
+
+ *Handle = HandleTable->NextIndexNeedingPool;
+
+ HandleTable->HandleCount++;
+
+ /* set the FirstFreeTableEntry member to the second entry and chain the
+ free entries */
+ HandleTable->FirstFreeTableEntry = HandleTable->NextIndexNeedingPool + 1;
+ for(cure = Entry + 1, laste = Entry + N_SUBHANDLE_ENTRIES, i = HandleTable->FirstFreeTableEntry + 1;
+ cure != laste;
+ cure++, i++)
+ {
+ cure->u1.Object = NULL;
+ cure->u2.NextFreeTableEntry = i;
+ }
+ /* truncate the free entry list */
+ (cure - 1)->u2.NextFreeTableEntry = -1;
+
+ /* save the pointers to the allocated list(s) */
+ InterlockedExchangePointer(&nmtbl[mli], ntbl);
+ if(AllocatedMtbl)
+ {
+ InterlockedExchangePointer(&HandleTable->Table[tli], nmtbl);
+ }
+
+ /* increment the NextIndexNeedingPool to the next index where we need to
+ allocate new memory */
+ HandleTable->NextIndexNeedingPool += N_SUBHANDLE_ENTRIES;
+ }
+ }
+ else
+ {
+ DPRINT1("Can't allocate any more handles in handle table 0x%x!\n", HandleTable);
+ }
+
+ return Entry;
+}
+
+static VOID
+ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry,
+ IN LONG Handle)
+{
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+ ASSERT(Entry);
+ ASSERT(IS_VALID_EX_HANDLE(Handle));
+
+ DPRINT("ExpFreeHandleTableEntry HT:0x%x Entry:0x%x\n", HandleTable, Entry);
+
+ /* automatically unlock the entry if currently locked. We however don't notify
+ anyone who waited on the handle because we're holding an exclusive lock after
+ all and these locks will fail then */
+ InterlockedExchangePointer(&Entry->u1.Object, NULL);
+ Entry->u2.NextFreeTableEntry = HandleTable->FirstFreeTableEntry;
+ HandleTable->FirstFreeTableEntry = Handle;
+
+ HandleTable->HandleCount--;
+}
+
+static PHANDLE_TABLE_ENTRY
+ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle)
+{
+ PHANDLE_TABLE_ENTRY Entry = NULL;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+
+ if(IS_VALID_EX_HANDLE(Handle))
+ {
+ ULONG tli, mli, eli;
+ PHANDLE_TABLE_ENTRY *mlp;
+
+ tli = TLI_FROM_HANDLE(Handle);
+ mli = MLI_FROM_HANDLE(Handle);
+ eli = ELI_FROM_HANDLE(Handle);
+
+ mlp = HandleTable->Table[tli];
+ if(Handle < HandleTable->NextIndexNeedingPool &&
+ mlp != NULL && mlp[mli] != NULL && mlp[mli][eli].u1.Object != NULL)
+ {
+ Entry = &mlp[mli][eli];
+ DPRINT("handle lookup 0x%x -> entry 0x%x [HT:0x%x] ptr: 0x%x\n", Handle, Entry, HandleTable, mlp[mli][eli].u1.Object);
+ }
+ }
+ else
+ {
+ DPRINT("Looking up invalid handle 0x%x\n", Handle);
+ }
+
+ return Entry;
+}
+
+BOOLEAN
+ExLockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry)
+{
+ ULONG_PTR Current, New;
+
+ PAGED_CODE();
+
+ DPRINT("Entering handle table entry 0x%x lock...\n", Entry);
+
+ ASSERT(HandleTable);
+ ASSERT(Entry);
+
+ for(;;)
+ {
+ Current = (volatile ULONG_PTR)Entry->u1.Object;
+
+ if(!Current || (HandleTable->Flags & EX_HANDLE_TABLE_CLOSING))
+ {
+ DPRINT("Attempted to lock empty handle table entry 0x%x or handle table shut down\n", Entry);
+ break;
+ }
+
+ if(!(Current & EX_HANDLE_ENTRY_LOCKED))
+ {
+ New = Current | EX_HANDLE_ENTRY_LOCKED;
+ if(InterlockedCompareExchangePointer(&Entry->u1.Object,
+ (PVOID)New,
+ (PVOID)Current) == (PVOID)Current)
+ {
+ DPRINT("SUCCESS handle table 0x%x entry 0x%x lock\n", HandleTable, Entry);
+ /* we acquired the lock */
+ return TRUE;
+ }
+ }
+
+ /* wait about 5ms at maximum so we don't wait forever in unfortunate
+ co-incidences where releasing the lock in another thread happens right
+ before we're waiting on the contention event to get pulsed, which might
+ never happen again... */
+ KeWaitForSingleObject(&HandleTable->HandleContentionEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ &ExpHandleShortWait);
+ }
+
+ return FALSE;
+}
+
+VOID
+ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry)
+{
+ ULONG_PTR Current, New;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+ ASSERT(Entry);
+
+ DPRINT("ExUnlockHandleTableEntry HT:0x%x Entry:0x%x\n", HandleTable, Entry);
+
+ Current = (volatile ULONG_PTR)Entry->u1.Object;
+
+ ASSERT(Current & EX_HANDLE_ENTRY_LOCKED);
+
+ New = Current & ~EX_HANDLE_ENTRY_LOCKED;
+
+ InterlockedExchangePointer(&Entry->u1.Object,
+ (PVOID)New);
+
+ /* we unlocked the entry, pulse the contention event so threads who're waiting
+ on the release can continue */
+ KePulseEvent(&HandleTable->HandleContentionEvent,
+ EVENT_INCREMENT,
+ FALSE);
+}
+
+LONG
+ExCreateHandle(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry)
+{
+ PHANDLE_TABLE_ENTRY NewHandleTableEntry;
+ LONG Handle = EX_INVALID_HANDLE;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+ ASSERT(Entry);
+
+ /* The highest bit in Entry->u1.Object has to be 1 so we make sure it's a
+ pointer to kmode memory. It will cleared though because it also indicates
+ the lock */
+ ASSERT((ULONG_PTR)Entry->u1.Object & EX_HANDLE_ENTRY_LOCKED);
+
+ KeEnterCriticalRegion();
+ ExAcquireHandleTableLockExclusive(HandleTable);
+
+ NewHandleTableEntry = ExpAllocateHandleTableEntry(HandleTable,
+ &Handle);
+ if(NewHandleTableEntry != NULL)
+ {
+ *NewHandleTableEntry = *Entry;
+
+ ExUnlockHandleTableEntry(HandleTable,
+ NewHandleTableEntry);
+ }
+
+ ExReleaseHandleTableLock(HandleTable);
+ KeLeaveCriticalRegion();
+
+ return Handle;
+}
+
+BOOLEAN
+ExDestroyHandle(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle)
+{
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+ BOOLEAN Ret = FALSE;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+
+ KeEnterCriticalRegion();
+ ExAcquireHandleTableLockExclusive(HandleTable);
+
+ HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
+ Handle);
+
+ if(HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
+ {
+ /* free and automatically unlock the handle. However we don't need to pulse
+ the contention event since other locks on this entry will fail */
+ ExpFreeHandleTableEntry(HandleTable,
+ HandleTableEntry,
+ Handle);
+ Ret = TRUE;
+ }
+
+ ExReleaseHandleTableLock(HandleTable);
+ KeLeaveCriticalRegion();
+
+ return Ret;
+}
+
+VOID
+ExDestroyHandleByEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry,
+ IN LONG Handle)
+{
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+ ASSERT(Entry);
+
+ /* This routine requires the entry to be locked */
+ ASSERT((ULONG_PTR)Entry->u1.Object & EX_HANDLE_ENTRY_LOCKED);
+
+ DPRINT("DestroyHandleByEntry HT:0x%x Entry:0x%x\n", HandleTable, Entry);
+
+ KeEnterCriticalRegion();
+ ExAcquireHandleTableLockExclusive(HandleTable);
+
+ /* free and automatically unlock the handle. However we don't need to pulse
+ the contention event since other locks on this entry will fail */
+ ExpFreeHandleTableEntry(HandleTable,
+ Entry,
+ Handle);
+
+ ExReleaseHandleTableLock(HandleTable);
+ KeLeaveCriticalRegion();
+}
+
+PHANDLE_TABLE_ENTRY
+ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle)
+{
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+
+ HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
+ Handle);
+ if (HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
+ {
+ DPRINT("ExMapHandleToPointer HT:0x%x Entry:0x%x locked\n", HandleTable, HandleTableEntry);
+ return HandleTableEntry;
+ }
+
+ return NULL;
+}
+
+BOOLEAN
+ExChangeHandle(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle,
+ IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
+ IN PVOID Context)
+{
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+ BOOLEAN Ret = FALSE;
+
+ PAGED_CODE();
+
+ ASSERT(HandleTable);
+ ASSERT(ChangeHandleCallback);
+
+ KeEnterCriticalRegion();
+
+ HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
+ Handle);
+
+ if(HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
+ {
+ Ret = ChangeHandleCallback(HandleTable,
+ HandleTableEntry,
+ NULL);
+
+ ExUnlockHandleTableEntry(HandleTable,
+ HandleTableEntry);
+ }
+
+ KeLeaveCriticalRegion();
+
+ return Ret;
+}
+
+/* EOF */
ExpInitializeMutantImplementation();
ExpInitializeSemaphoreImplementation();
ExpInitializeTimerImplementation();
+ ExpInitializeHandleTables();
LpcpInitSystem();
ExpInitializeProfileImplementation();
ExpWin32kInit();
SpiCur->BasePriority = pr->Pcb.BasePriority;
SpiCur->ProcessId = pr->UniqueProcessId;
SpiCur->InheritedFromProcessId = pr->InheritedFromUniqueProcessId;
- SpiCur->HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
+ SpiCur->HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize;
SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart;
SpiCur->VmCounters.PageFaultCount = pr->LastFaultCount;
do
{
- hCount = hCount + ObpGetHandleCountByHandleTable(&pr->HandleTable);
+ hCount = hCount + ObpGetHandleCountByHandleTable(pr->ObjectTable);
pr = PsGetNextProcess(pr);
if ((pr == syspr) || (pr == NULL))
{
int Count = 0, HandleCount = 0;
- HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
+ HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
for (Count = 0; HandleCount > 0 ; HandleCount--)
{
static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
KPRIORITY Priority)
{
- ULONG i;
- PETHREAD Thread;
- HANDLE hThread;
-
-
- for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
- {
-
- PsCreateSystemThread(&hThread,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- NULL,
- ExWorkerThreadEntryPoint,
- WorkQueue);
- ObReferenceObjectByHandle(hThread,
- THREAD_ALL_ACCESS,
- PsThreadType,
- KernelMode,
- (PVOID*)&Thread,
- NULL);
- KeSetPriorityThread(&Thread->Tcb,
- Priority);
- ObDereferenceObject(Thread);
- ZwClose(hThread);
- }
+ ULONG i;
+ PETHREAD Thread;
+ HANDLE hThread;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ /* Loop through how many threads we need to create */
+ for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
+
+ /* Create the System Thread */
+ Status = PsCreateSystemThread(&hThread,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ NULL,
+ ExWorkerThreadEntryPoint,
+ (PVOID)WorkQueue);
+ if(NT_SUCCESS(Status))
+ {
+ /* Get the Thread */
+ Status = ObReferenceObjectByHandle(hThread,
+ THREAD_SET_INFORMATION,
+ PsThreadType,
+ KernelMode,
+ (PVOID*)&Thread,
+ NULL);
+
+ if(NT_SUCCESS(Status))
+ {
+ /* Set the Priority */
+ KeSetPriorityThread(&Thread->Tcb, Priority);
+
+ /* Dereference and close handle */
+ ObDereferenceObject(Thread);
+ ZwClose(hThread);
+ }
+ else
+ {
+ DPRINT1("Unable to reference worker thread handle 0x%x, Status: 0x%x!\n", hThread, Status);
+ KEBUGCHECK(0);
+ }
+ }
+ else
+ {
+ DPRINT1("Unable to create worker thread, Status: 0x%x!\n", Status);
+ KEBUGCHECK(0);
+ }
+ }
}
VOID INIT_FUNCTION
STDCALL
ExpInitializeExecutive(VOID);
+/* HANDLE TABLE FUNCTIONS ***************************************************/
+
+#define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
+#define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
+#define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
+#define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
+
+#define EX_HANDLE_TABLE_CLOSING 0x1
+
+#define EX_INVALID_HANDLE (~0)
+
+#define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \
+ EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \
+ EX_HANDLE_ENTRY_INHERITABLE | \
+ EX_HANDLE_ENTRY_AUDITONCLOSE)
+
+typedef VOID (STDCALL PEX_DESTROY_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PVOID Object, ULONG GrantedAccess, PVOID Context);
+typedef BOOLEAN (STDCALL PEX_DUPLICATE_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry, PVOID Context);
+typedef BOOLEAN (STDCALL PEX_CHANGE_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry, PVOID Context);
+
+VOID
+ExpInitializeHandleTables(VOID);
+PHANDLE_TABLE
+ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL);
+VOID
+ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
+ IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback OPTIONAL,
+ IN PVOID Context OPTIONAL);
+PHANDLE_TABLE
+ExDupHandleTable(IN PEPROCESS QuotaProcess OPTIONAL,
+ IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL,
+ IN PVOID Context OPTIONAL,
+ IN PHANDLE_TABLE SourceHandleTable);
+BOOLEAN
+ExLockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry);
+VOID
+ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry);
+LONG
+ExCreateHandle(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry);
+BOOLEAN
+ExDestroyHandle(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle);
+VOID
+ExDestroyHandleByEntry(IN PHANDLE_TABLE HandleTable,
+ IN PHANDLE_TABLE_ENTRY Entry,
+ IN LONG Handle);
+PHANDLE_TABLE_ENTRY
+ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle);
+
+BOOLEAN
+ExChangeHandle(IN PHANDLE_TABLE HandleTable,
+ IN LONG Handle,
+ IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
+ IN PVOID Context);
+
/* OTHER FUNCTIONS **********************************************************/
LONGLONG
OBJTYP_MAX,
};
+#define HEADER_TO_BODY(objhdr) \
+ (PVOID)((ULONG_PTR)objhdr + sizeof(OBJECT_HEADER) - sizeof(COMMON_BODY_HEADER))
+
+#define BODY_TO_HEADER(objbdy) \
+ CONTAINING_RECORD(&(((PCOMMON_BODY_HEADER)objbdy)->Type), OBJECT_HEADER, Type)
#define OBJECT_ALLOC_SIZE(ObjectSize) ((ObjectSize)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER))
+#define HANDLE_TO_EX_HANDLE(handle) \
+ (LONG)(((LONG)(handle) >> 2) - 1)
+#define EX_HANDLE_TO_HANDLE(exhandle) \
+ (HANDLE)(((exhandle) + 1) << 2)
extern PDIRECTORY_OBJECT NameSpaceRoot;
extern POBJECT_TYPE ObSymbolicLinkType;
-
-POBJECT_HEADER BODY_TO_HEADER(PVOID body);
-PVOID HEADER_TO_BODY(POBJECT_HEADER obj);
-
VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
POBJECT_HEADER Header,
PWSTR Name);
PVOID* ReturnedObject,
PUNICODE_STRING RemainingPath,
POBJECT_TYPE ObjectType);
-VOID ObCloseAllHandles(struct _EPROCESS* Process);
VOID ObDeleteHandleTable(struct _EPROCESS* Process);
NTSTATUS
ObDeleteHandle(PEPROCESS Process,
- HANDLE Handle,
- PVOID *ObjectBody);
+ HANDLE Handle);
NTSTATUS
ObpQueryHandleAttributes(HANDLE Handle,
LIST_ENTRY SessionProcessLinks;
struct _EPORT *DebugPort;
struct _EPORT *ExceptionPort;
- HANDLE_TABLE HandleTable;
+ PHANDLE_TABLE ObjectTable;
PVOID Token;
FAST_MUTEX WorkingSetLock;
ULONG WorkingSetPage;
NTSTATUS
PsInitializeThread(PEPROCESS Process,
PETHREAD* ThreadPtr,
- PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
BOOLEAN First);
VOID INIT_FUNCTION PsInitJobManagment(VOID);
-/* CID */
-
-typedef struct _CID_OBJECT
-{
- LONG ref;
- HANDLE Handle;
- LIST_ENTRY Entry;
- FAST_MUTEX Lock;
- union
- {
- struct _EPROCESS *Process;
- struct _ETHREAD *Thread;
- PVOID Object;
- } Obj;
-} CID_OBJECT, *PCID_OBJECT;
+/* CLIENT ID */
NTSTATUS PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle);
NTSTATUS PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
-PCID_OBJECT PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
-VOID PsUnlockCidObject(PCID_OBJECT CidObject);
+PHANDLE_TABLE_ENTRY PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object);
+VOID PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry);
NTSTATUS PsLockProcess(PEPROCESS Process, BOOL Timeout);
VOID PsUnlockProcess(PEPROCESS Process);
DPRINT("IopCloseFile()\n");
- if (HandleCount > 0 || FileObject->DeviceObject == NULL)
+ if (HandleCount > 1 || FileObject->DeviceObject == NULL)
{
return;
}
&IoStatusBlock,
0,
0);
-
- BootDrivers = NT_SUCCESS(Status) ? FALSE : TRUE;
-
- ZwClose(Handle);
+ if(NT_SUCCESS(Status))
+ {
+ BootDrivers = FALSE;
+ ZwClose(Handle);
+ }
+ else
+ BootDrivers = TRUE;
/*
* Initialize services for discovered children. Only boot drivers will
* If the client has just closed its handle then tell the server what
* happened and disconnect this port.
*/
- if (HandleCount == 0 && Port->State == EPORT_CONNECTED_CLIENT &&
- ObGetObjectPointerCount(Port) == 2)
+ if (HandleCount == 1 && Port->State == EPORT_CONNECTED_CLIENT)
{
DPRINT("Informing server\n");
Message.MessageSize = sizeof(LPC_MESSAGE);
* If the server has closed all of its handles then disconnect the port,
* don't actually notify the client until it attempts an operation.
*/
- if (HandleCount == 0 && Port->State == EPORT_CONNECTED_SERVER &&
- ObGetObjectPointerCount(Port) == 1)
+ if (HandleCount == 1 && Port->State == EPORT_CONNECTED_SERVER)
{
DPRINT("Cleaning up server\n");
Port->OtherPort->OtherPort = NULL;
#define NDEBUG
#include <internal/debug.h>
-/* TYPES *******************************************************************/
-
-/*
- * PURPOSE: Defines a handle
- */
-typedef struct _HANDLE_ENTRY
-{
- PVOID ObjectBody;
- ACCESS_MASK GrantedAccess;
-} HANDLE_ENTRY, *PHANDLE_ENTRY;
-
-#define HANDLE_BLOCK_ENTRIES \
- (((4 * PAGE_SIZE) - \
- (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(HANDLE_ENTRY))
-
-#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 OB_ENTRY_TO_POINTER(Entry) \
- (PVOID)((ULONG_PTR)(Entry) & ~OB_HANDLE_FLAG_MASK)
-
-/*
- * PURPOSE: Defines a 4 page's worth of handles
- */
-typedef struct
-{
- LIST_ENTRY entry;
- ULONG allocation_hint;
- ULONG allocation_count;
- HANDLE_ENTRY handles[HANDLE_BLOCK_ENTRIES];
-} HANDLE_BLOCK, *PHANDLE_BLOCK;
-
-
-/* GLOBALS *******************************************************************/
-
-#define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L')
+#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
+ ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
+ EX_HANDLE_ENTRY_AUDITONCLOSE)))
+#define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \
+ ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
+ EX_HANDLE_ENTRY_AUDITONCLOSE)))
/* FUNCTIONS ***************************************************************/
-/*
- * 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
- */
-static PHANDLE_ENTRY
-ObpGetObjectByHandle(PHANDLE_TABLE HandleTable,
- HANDLE h,
- HANDLE_BLOCK **Block)
+VOID
+ObpDecrementHandleCount(PVOID ObjectBody)
{
- 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);
- if (Block)
- *Block = blk;
- DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
- return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
+ POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
+
+ if ((ObjectHeader->ObjectType != NULL) &&
+ (ObjectHeader->ObjectType->Close != NULL))
+ {
+ /* the handle count should be decremented but we pass the previous value
+ to the callback */
+ ObjectHeader->ObjectType->Close(ObjectBody, NewHandleCount + 1);
+ }
+
+ if(NewHandleCount == 0)
+ {
+ ObDereferenceObject(ObjectBody);
+ }
}
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
{
PEPROCESS Process;
- KIRQL oldIrql;
- PHANDLE_ENTRY HandleEntry;
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+ LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
+
+ PAGED_CODE();
DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
+ KeEnterCriticalRegion();
+
Process = PsGetCurrentProcess();
- KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL)
+ HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+ ExHandle);
+ if (HandleTableEntry == NULL)
{
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+ KeLeaveCriticalRegion();
return STATUS_INVALID_HANDLE;
}
- HandleInfo->Inherit =
- ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_INHERIT);
- HandleInfo->ProtectFromClose =
- ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT);
+ HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+ HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleTableEntry);
+
+ KeLeaveCriticalRegion();
return STATUS_SUCCESS;
}
ObpSetHandleAttributes(HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
{
- PHANDLE_ENTRY HandleEntry;
PEPROCESS Process;
- KIRQL oldIrql;
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+ LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
+
+ PAGED_CODE();
- DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
+ DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle);
Process = PsGetCurrentProcess();
+
+ KeEnterCriticalRegion();
- KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL)
+ HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+ ExHandle);
+ if (HandleTableEntry == NULL)
{
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+ KeLeaveCriticalRegion();
return STATUS_INVALID_HANDLE;
}
if (HandleInfo->Inherit)
- HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_INHERIT);
+ HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
else
- HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody & ~OB_HANDLE_FLAG_INHERIT);
+ HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
if (HandleInfo->ProtectFromClose)
- HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_PROTECT);
+ HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
else
- HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody & ~OB_HANDLE_FLAG_PROTECT);
+ HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
/* FIXME: Do we need to set anything in the object header??? */
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleTableEntry);
+
+ KeLeaveCriticalRegion();
return STATUS_SUCCESS;
}
BOOLEAN InheritHandle,
ULONG Options)
{
- KIRQL oldIrql;
- PHANDLE_ENTRY SourceHandleEntry;
+ PHANDLE_TABLE_ENTRY SourceHandleEntry;
+ HANDLE_TABLE_ENTRY NewHandleEntry;
PVOID ObjectBody;
-
- KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
- SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable,
- SourceHandle,
- NULL);
+ POBJECT_HEADER ObjectHeader;
+ LONG ExTargetHandle;
+ LONG ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle);
+
+ PAGED_CODE();
+
+ KeEnterCriticalRegion();
+
+ SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
+ ExSourceHandle);
if (SourceHandleEntry == NULL)
{
- KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
return STATUS_INVALID_HANDLE;
}
- ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody);
- ObReferenceObjectByPointer(ObjectBody,
- 0,
- NULL,
- UserMode);
+ ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
+ ObjectBody = HEADER_TO_BODY(ObjectHeader);
+
+ NewHandleEntry.u1.Object = SourceHandleEntry->u1.Object;
+ if(InheritHandle)
+ NewHandleEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+ else
+ NewHandleEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+ NewHandleEntry.u2.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
+ SourceHandleEntry->u2.GrantedAccess :
+ DesiredAccess);
+
+ /* reference the object so it doesn't get deleted after releasing the lock
+ and before creating a new handle for it */
+ ObReferenceObject(ObjectBody);
- if (Options & DUPLICATE_SAME_ACCESS)
+ /* increment the handle count of the object, it should always be >= 2 because
+ we're holding a handle lock to this object! if the new handle count was
+ 1 here, we're in big trouble... it would've been safe to increment and
+ check the handle count without using interlocked functions because the
+ entry is locked, which means the handle count can't change. */
+ InterlockedIncrement(&ObjectHeader->HandleCount);
+ ASSERT(ObjectHeader->HandleCount >= 2);
+
+ ExUnlockHandleTableEntry(SourceProcess->ObjectTable,
+ SourceHandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ /* attempt to create the new handle */
+ ExTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
+ &NewHandleEntry);
+ if (ExTargetHandle != EX_INVALID_HANDLE)
+ {
+ if (Options & DUPLICATE_CLOSE_SOURCE)
{
- DesiredAccess = SourceHandleEntry->GrantedAccess;
+ ObDeleteHandle(SourceProcess,
+ SourceHandle);
}
+
+ ObDereferenceObject(ObjectBody);
- KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
- ObCreateHandle(TargetProcess,
- ObjectBody,
- DesiredAccess,
- InheritHandle,
- TargetHandle);
-
- if (Options & DUPLICATE_CLOSE_SOURCE)
+ *TargetHandle = EX_HANDLE_TO_HANDLE(ExTargetHandle);
+
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* decrement the handle count we previously incremented, but don't call the
+ closing procedure because we're not closing a handle! */
+ if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0)
{
- ZwClose(SourceHandle);
+ ObDereferenceObject(ObjectBody);
}
-
- ObDereferenceObject(ObjectBody);
-
- return STATUS_SUCCESS;
+
+ ObDereferenceObject(ObjectBody);
+ return STATUS_UNSUCCESSFUL;
+ }
}
/*
NtDuplicateObject (IN HANDLE SourceProcessHandle,
IN HANDLE SourceHandle,
IN HANDLE TargetProcessHandle,
- OUT PHANDLE UnsafeTargetHandle,
+ OUT PHANDLE TargetHandle,
IN ACCESS_MASK DesiredAccess,
IN BOOLEAN InheritHandle,
ULONG Options)
{
PEPROCESS SourceProcess;
PEPROCESS TargetProcess;
- PHANDLE_ENTRY SourceHandleEntry;
- KIRQL oldIrql;
- PVOID ObjectBody;
- HANDLE TargetHandle;
- NTSTATUS Status;
+ HANDLE hTarget;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(TargetHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
Status = ObReferenceObjectByHandle(SourceProcessHandle,
PROCESS_DUP_HANDLE,
NULL,
- UserMode,
+ PreviousMode,
(PVOID*)&SourceProcess,
NULL);
if (!NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle(TargetProcessHandle,
PROCESS_DUP_HANDLE,
NULL,
- UserMode,
+ PreviousMode,
(PVOID*)&TargetProcess,
NULL);
if (!NT_SUCCESS(Status))
/* Check for magic handle first */
if (SourceHandle == NtCurrentThread())
{
- ObReferenceObjectByHandle(SourceHandle,
- PROCESS_DUP_HANDLE,
- NULL,
- UserMode,
- &ObjectBody,
- NULL);
-
- ObCreateHandle(TargetProcess,
- ObjectBody,
- THREAD_ALL_ACCESS,
- InheritHandle,
- &TargetHandle);
+ PVOID ObjectBody;
+
+ Status = ObReferenceObjectByHandle(SourceHandle,
+ PROCESS_DUP_HANDLE,
+ NULL,
+ PreviousMode,
+ &ObjectBody,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ Status = ObCreateHandle(TargetProcess,
+ ObjectBody,
+ THREAD_ALL_ACCESS,
+ InheritHandle,
+ &hTarget);
+
+ ObDereferenceObject(ObjectBody);
+
+ if (Options & DUPLICATE_CLOSE_SOURCE)
+ {
+ ObDeleteHandle(SourceProcess,
+ SourceHandle);
+ }
+ }
}
else
{
- KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
- SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable,
- SourceHandle,
- NULL);
- if (SourceHandleEntry == NULL)
- {
- KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
- ObDereferenceObject(SourceProcess);
- ObDereferenceObject(TargetProcess);
- return(STATUS_INVALID_HANDLE);
- }
- ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody);
- ObReferenceObjectByPointer(ObjectBody,
- 0,
- NULL,
- UserMode);
-
- if (Options & DUPLICATE_SAME_ACCESS)
- {
- DesiredAccess = SourceHandleEntry->GrantedAccess;
- }
-
- KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-
- ObCreateHandle(TargetProcess,
- ObjectBody,
- DesiredAccess,
- InheritHandle,
- &TargetHandle);
- }
-
- if (Options & DUPLICATE_CLOSE_SOURCE)
- {
- ZwClose(SourceHandle);
+ Status = ObDuplicateObject(SourceProcess,
+ TargetProcess,
+ SourceHandle,
+ &hTarget,
+ DesiredAccess,
+ InheritHandle,
+ Options);
}
-
+
ObDereferenceObject(TargetProcess);
ObDereferenceObject(SourceProcess);
- ObDereferenceObject(ObjectBody);
-
- Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
- if (!NT_SUCCESS(Status))
+
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
{
- return(Status);
+ *TargetHandle = hTarget;
}
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
- return(STATUS_SUCCESS);
+ return Status;
}
-VOID ObCloseAllHandles(PEPROCESS Process)
+static VOID STDCALL
+DeleteHandleCallback(PHANDLE_TABLE HandleTable,
+ PVOID Object,
+ ULONG GrantedAccess,
+ PVOID Context)
{
- KIRQL oldIrql;
- PHANDLE_TABLE HandleTable;
- PLIST_ENTRY current_entry;
- PHANDLE_BLOCK current;
- ULONG i;
- PVOID ObjectBody;
-
- DPRINT("ObCloseAllHandles(Process %x)\n", Process);
-
- HandleTable = &Process->HandleTable;
-
- KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-
- current_entry = HandleTable->ListHead.Flink;
-
- while (current_entry != &HandleTable->ListHead)
- {
- current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
-
- for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
- {
- ObjectBody = OB_ENTRY_TO_POINTER(current->handles[i].ObjectBody);
-
- if (ObjectBody != NULL)
- {
- POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-
-#if 0
- if (Header->ObjectType == PsProcessType ||
- Header->ObjectType == PsThreadType)
- {
- DPRINT("Deleting handle to %x\n", ObjectBody);
- }
-#endif
-
- ObReferenceObjectByPointer(ObjectBody,
- 0,
- NULL,
- UserMode);
- InterlockedDecrement(&Header->HandleCount);
- current->handles[i].ObjectBody = NULL;
-
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- if ((Header->ObjectType != NULL) &&
- (Header->ObjectType->Close != NULL))
- {
- Header->ObjectType->Close(ObjectBody,
- Header->HandleCount);
- }
-
- ObDereferenceObject(ObjectBody);
- KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
- current_entry = &HandleTable->ListHead;
- break;
- }
- }
-
- current_entry = current_entry->Flink;
- }
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- DPRINT("ObCloseAllHandles() finished\n");
- DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType);
+ POBJECT_HEADER ObjectHeader;
+ PVOID ObjectBody;
+
+ PAGED_CODE();
+
+ ObjectHeader = EX_OBJ_TO_HDR(Object);
+ ObjectBody = HEADER_TO_BODY(ObjectHeader);
+
+ ObpDecrementHandleCount(ObjectBody);
}
VOID ObDeleteHandleTable(PEPROCESS Process)
* FUNCTION: Deletes the handle table associated with a process
*/
{
- PLIST_ENTRY current = NULL;
- PHANDLE_TABLE HandleTable = NULL;
-
- ObCloseAllHandles(Process);
-
- HandleTable = &Process->HandleTable;
- current = RemoveHeadList(&HandleTable->ListHead);
-
- while (current != &HandleTable->ListHead)
- {
- HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current,
- HANDLE_BLOCK,
- entry);
- DPRINT("Freeing %x\n", HandleBlock);
- ExFreePool(HandleBlock);
-
- current = RemoveHeadList(&HandleTable->ListHead);
- }
+ PAGED_CODE();
+
+ ExDestroyHandleTable(Process->ObjectTable,
+ DeleteHandleCallback,
+ Process);
}
+static BOOLEAN STDCALL
+DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
+ PHANDLE_TABLE_ENTRY HandleTableEntry,
+ PVOID Context)
+{
+ POBJECT_HEADER ObjectHeader;
+ BOOLEAN Ret = FALSE;
+
+ PAGED_CODE();
+
+ Ret = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+ if(Ret)
+ {
+ ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
+ if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+ {
+ ObReferenceObjectByPointer(HEADER_TO_BODY(ObjectHeader),
+ 0,
+ NULL,
+ UserMode);
+ }
+ }
+
+ return Ret;
+}
VOID ObCreateHandleTable(PEPROCESS Parent,
BOOLEAN Inherit,
* Process = Process whose handle table is to be created
*/
{
- PHANDLE_TABLE ParentHandleTable, HandleTable;
- KIRQL oldIrql;
- PLIST_ENTRY parent_current;
- ULONG i;
- PHANDLE_BLOCK current_block, new_block;
-
+ PAGED_CODE();
+
DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
Parent,Inherit,Process);
-
- InitializeListHead(&(Process->HandleTable.ListHead));
- KeInitializeSpinLock(&(Process->HandleTable.ListLock));
-
- if (Parent != NULL)
- {
- ParentHandleTable = &Parent->HandleTable;
- HandleTable = &Process->HandleTable;
-
- KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
- KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock);
-
- parent_current = ParentHandleTable->ListHead.Flink;
-
- while (parent_current != &ParentHandleTable->ListHead)
- {
- current_block = CONTAINING_RECORD(parent_current,
- HANDLE_BLOCK,
- entry);
- new_block = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(HANDLE_BLOCK),
- TAG_HANDLE_TABLE);
- if (new_block == NULL)
- {
- break;
- }
- RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK));
-
- for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
- {
- if (current_block->handles[i].ObjectBody)
- {
- if ((ULONG_PTR)current_block->handles[i].ObjectBody & OB_HANDLE_FLAG_INHERIT)
- {
- new_block->handles[i].ObjectBody =
- 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));
- }
- }
- }
- InsertTailList(&Process->HandleTable.ListHead, &new_block->entry);
- parent_current = parent_current->Flink;
- }
- KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock);
- KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
- }
+ if(Parent != NULL)
+ {
+ Process->ObjectTable = ExDupHandleTable(Process,
+ DuplicateHandleCallback,
+ NULL,
+ Parent->ObjectTable);
+ }
+ else
+ {
+ Process->ObjectTable = ExCreateHandleTable(Process);
+ }
}
NTSTATUS
ObDeleteHandle(PEPROCESS Process,
- HANDLE Handle,
- PVOID *ObjectBody)
+ HANDLE Handle)
{
- PHANDLE_ENTRY HandleEntry;
+ PHANDLE_TABLE_ENTRY HandleEntry;
PVOID Body;
- KIRQL oldIrql;
- PHANDLE_TABLE HandleTable;
- POBJECT_HEADER Header;
- HANDLE_BLOCK *Block;
+ POBJECT_HEADER ObjectHeader;
+ LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
PAGED_CODE();
DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
-
- HandleTable = &Process->HandleTable;
-
- KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-
- HandleEntry = ObpGetObjectByHandle(HandleTable, Handle, &Block);
- if (HandleEntry == NULL)
- {
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- *ObjectBody = NULL;
- return STATUS_INVALID_HANDLE;
- }
-
- if ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT)
- {
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- *ObjectBody = NULL;
- return STATUS_HANDLE_NOT_CLOSABLE;
- }
-
- Body = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody);
- DPRINT("ObjectBody %x\n", Body);
- if (Body == NULL)
+
+ KeEnterCriticalRegion();
+
+ HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+ ExHandle);
+ if(HandleEntry != NULL)
+ {
+ if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
{
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- *ObjectBody = NULL;
- return STATUS_UNSUCCESSFUL;
- }
-
- Header = BODY_TO_HEADER(Body);
- ObReferenceObjectByPointer(Body,
- 0,
- NULL,
- UserMode);
- InterlockedDecrement(&Header->HandleCount);
- HandleEntry->ObjectBody = NULL;
-
- Block->allocation_count--;
- Block->allocation_hint = (ULONG_PTR)Handle % HANDLE_BLOCK_ENTRIES;
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
+ KeLeaveCriticalRegion();
- if ((Header->ObjectType != NULL) &&
- (Header->ObjectType->Close != NULL))
- {
- Header->ObjectType->Close(Body, Header->HandleCount);
+ return STATUS_HANDLE_NOT_CLOSABLE;
}
- *ObjectBody = Body;
-
- DPRINT("Finished ObDeleteHandle()\n");
-
- return STATUS_SUCCESS;
+ ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+ Body = HEADER_TO_BODY(ObjectHeader);
+
+ ObpDecrementHandleCount(Body);
+
+ /* destroy and unlock the handle entry */
+ ExDestroyHandleByEntry(Process->ObjectTable,
+ HandleEntry,
+ ExHandle);
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_HANDLE;
}
* NOTE: The handle is valid only in the context of the current process
*/
{
- LIST_ENTRY* current;
- unsigned int handle=1;
- unsigned int Loop, Index, MaxIndex;
- HANDLE_BLOCK* new_blk = NULL;
- PHANDLE_TABLE HandleTable;
- KIRQL oldlvl;
+ HANDLE_TABLE_ENTRY NewEntry;
+ POBJECT_HEADER ObjectHeader;
+ LONG ExHandle;
PAGED_CODE();
DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
ASSERT(Process);
+ ASSERT(ObjectBody);
- if (ObjectBody != NULL)
- {
- InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
- }
- HandleTable = &Process->HandleTable;
- KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl);
- current = HandleTable->ListHead.Flink;
- /*
- * Scan through the currently allocated handle blocks looking for a free
- * slot
- */
- while (current != (&HandleTable->ListHead))
- {
- HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
-
- DPRINT("Current %x\n",current);
+ ObjectHeader = BODY_TO_HEADER(ObjectBody);
- if (blk->allocation_count == HANDLE_BLOCK_ENTRIES)
- {
- handle = handle + HANDLE_BLOCK_ENTRIES;
- current = current->Flink;
- continue;
- }
+ ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
- Index = blk->allocation_hint;
- MaxIndex = HANDLE_BLOCK_ENTRIES;
- for (Loop = 0; Loop < 2; Loop++)
- {
- for (Index = 0; Index < MaxIndex; Index++)
- {
- DPRINT("Considering slot %d containing %x\n", Index, blk->handles[Index]);
- if (blk->handles[Index].ObjectBody == NULL)
- {
- blk->handles[Index].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
- if (Inherit)
- blk->handles[Index].ObjectBody = (PVOID)((ULONG_PTR)blk->handles[Index].ObjectBody | OB_HANDLE_FLAG_INHERIT);
- blk->handles[Index].GrantedAccess = GrantedAccess;
- blk->allocation_hint = Index + 1;
- blk->allocation_count++;
- KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
- *HandleReturn = (HANDLE)((handle + Index) << 2);
- return(STATUS_SUCCESS);
- }
- }
- Index = 0;
- MaxIndex = blk->allocation_hint;
- }
-
- handle = handle + HANDLE_BLOCK_ENTRIES;
- current = current->Flink;
+ NewEntry.u1.Object = ObjectHeader;
+ if(Inherit)
+ NewEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+ else
+ NewEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+ NewEntry.u2.GrantedAccess = GrantedAccess;
+
+ ExHandle = ExCreateHandle(Process->ObjectTable,
+ &NewEntry);
+ DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader, *HandleReturn, Process->ObjectTable);
+ if(ExHandle != EX_INVALID_HANDLE)
+ {
+ if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+ {
+ ObReferenceObjectByPointer(ObjectBody,
+ 0,
+ NULL,
+ UserMode);
}
+
+ *HandleReturn = EX_HANDLE_TO_HANDLE(ExHandle);
- /*
- * Add a new handle block to the end of the list
- */
- new_blk =
- (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK),
- TAG_HANDLE_TABLE);
- if (!new_blk)
- {
- *HandleReturn = (PHANDLE)NULL;
- return(STATUS_INSUFFICIENT_RESOURCES);
- }
- 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].GrantedAccess = GrantedAccess;
- new_blk->allocation_hint = 1;
- new_blk->allocation_count++;
- KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
- *HandleReturn = (HANDLE)(handle << 2);
- return(STATUS_SUCCESS);
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_UNSUCCESSFUL;
}
ObQueryObjectAuditingByHandle(IN HANDLE Handle,
OUT PBOOLEAN GenerateOnClose)
{
+ PHANDLE_TABLE_ENTRY HandleEntry;
PEPROCESS Process;
- KIRQL oldIrql;
- PHANDLE_ENTRY HandleEntry;
+ LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
PAGED_CODE();
DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
Process = PsGetCurrentProcess();
-
- KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL)
- {
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
- return STATUS_INVALID_HANDLE;
- }
-
- *GenerateOnClose = (BOOLEAN)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_AUDIT);
-
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
-
- return STATUS_SUCCESS;
+
+ KeEnterCriticalRegion();
+
+ HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+ ExHandle);
+ if(HandleEntry != NULL)
+ {
+ *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
+
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_SUCCESS;
+ }
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_INVALID_HANDLE;
}
PVOID* Object,
POBJECT_HANDLE_INFORMATION HandleInformation)
{
- PHANDLE_ENTRY HandleEntry;
+ PHANDLE_TABLE_ENTRY HandleEntry;
POBJECT_HEADER ObjectHeader;
- KIRQL oldIrql;
PVOID ObjectBody;
ACCESS_MASK GrantedAccess;
+ PGENERIC_MAPPING GenericMapping;
ULONG Attributes;
NTSTATUS Status;
+ LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
PAGED_CODE();
if (Handle == NtCurrentProcess() &&
(ObjectType == PsProcessType || ObjectType == NULL))
{
- DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
-
Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
PROCESS_ALL_ACCESS,
PsProcessType,
if (HandleInformation != NULL)
{
- HandleInformation->HandleAttributes = 0; /* FIXME? */
+ HandleInformation->HandleAttributes = 0;
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
}
if (HandleInformation != NULL)
{
- HandleInformation->HandleAttributes = 0; /* FIXME? */
+ HandleInformation->HandleAttributes = 0;
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
}
return(STATUS_OBJECT_TYPE_MISMATCH);
}
- KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
- &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL || HandleEntry->ObjectBody == 0)
+ KeEnterCriticalRegion();
+
+ HandleEntry = ExMapHandleToPointer(PsGetCurrentProcess()->ObjectTable,
+ ExHandle);
+ if (HandleEntry == NULL)
{
- KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
- oldIrql);
- return(STATUS_INVALID_HANDLE);
+ KeLeaveCriticalRegion();
+ DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle);
+ return(STATUS_INVALID_HANDLE);
}
- ObjectBody = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody);
- DPRINT("ObjectBody %p\n",ObjectBody);
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
- DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
+
+ ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+ ObjectBody = HEADER_TO_BODY(ObjectHeader);
+
+ DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, PsGetCurrentProcess()->ObjectTable);
+
ObReferenceObjectByPointer(ObjectBody,
0,
NULL,
UserMode);
- Attributes = (ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_MASK;
- GrantedAccess = HandleEntry->GrantedAccess;
- KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
- oldIrql);
-
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
- DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
+ Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
+ EX_HANDLE_ENTRY_INHERITABLE |
+ EX_HANDLE_ENTRY_AUDITONCLOSE);
+ GrantedAccess = HandleEntry->u2.GrantedAccess;
+ GenericMapping = ObjectHeader->ObjectType->Mapping;
if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
{
- CHECKPOINT;
- return(STATUS_OBJECT_TYPE_MISMATCH);
+ DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->TypeName, ObjectHeader->ObjectType ? &ObjectHeader->ObjectType->TypeName : NULL, Handle);
+
+ ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ return(STATUS_OBJECT_TYPE_MISMATCH);
}
+
+ ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
+ HandleEntry);
- if (ObjectHeader->ObjectType == PsProcessType)
- {
- DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
- }
+ KeLeaveCriticalRegion();
- if (DesiredAccess && AccessMode == UserMode)
+ if (DesiredAccess && AccessMode != KernelMode)
{
- RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping);
+ RtlMapGenericMask(&DesiredAccess, GenericMapping);
if (!(GrantedAccess & DesiredAccess) &&
!((~GrantedAccess) & DesiredAccess))
*Object = ObjectBody;
- CHECKPOINT;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtClose(IN HANDLE Handle)
{
- PVOID ObjectBody;
- POBJECT_HEADER Header;
NTSTATUS Status;
PAGED_CODE();
- DPRINT("NtClose(Handle %x)\n",Handle);
-
Status = ObDeleteHandle(PsGetCurrentProcess(),
- Handle,
- &ObjectBody);
+ Handle);
if (!NT_SUCCESS(Status))
{
if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort)
return Status;
}
- Header = BODY_TO_HEADER(ObjectBody);
-
- DPRINT("Dereferencing %x\n", ObjectBody);
- ObDereferenceObject(ObjectBody);
-
return(STATUS_SUCCESS);
}
ULONG
ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
{
- PHANDLE_BLOCK blk;
- POBJECT_HEADER Header;
- PVOID ObjectBody;
- KIRQL OldIrql;
- PLIST_ENTRY current;
- ULONG i;
- ULONG Count=0;
-
- KeAcquireSpinLock(&HandleTable->ListLock, &OldIrql);
-
- current = HandleTable->ListHead.Flink;
- while (current != &HandleTable->ListHead)
- {
- blk = CONTAINING_RECORD(current, HANDLE_BLOCK, entry);
-
- for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
- {
- ObjectBody = OB_ENTRY_TO_POINTER(blk->handles[i].ObjectBody);
- if (ObjectBody != NULL)
- {
- Header = BODY_TO_HEADER(ObjectBody);
-
- /* Make sure this is real. Okay! For real!*/
- if ((Header->ObjectType != NULL) &&
- (Header->ObjectType->Close != NULL))
- Count++;
- }
- }
-
- current = current->Flink;
- }
-
- KeReleaseSpinLock(&HandleTable->ListLock,
- OldIrql);
-
- return Count;
+ return HandleTable->HandleCount;
}
/*
int Count)
{
ULONG P;
- KIRQL oldIrql;
+// KIRQL oldIrql;
// pshi->HandleValue;
P = (ULONG) Process->UniqueProcessId;
pshi->UniqueProcessId = (USHORT) P;
- KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
+// KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
// pshi->GrantedAccess;
// pshi->Object;
// pshi->ObjectTypeIndex;
// pshi->HandleAttributes;
- KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
+// KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
return;
}
/* FUNCTIONS ************************************************************/
-PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
-{
- return(((char*)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));
-}
-
NTSTATUS
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN KPROCESSOR_MODE AccessMode,
RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize));
/* Initialize the object header */
- DPRINT("Initalizing header\n");
+ DPRINT("Initalizing header 0x%x (%wZ)\n", Header, &Type->TypeName);
Header->HandleCount = 0;
Header->RefCount = 1;
Header->ObjectType = Type;
KEBUGCHECK(0);
}
- (VOID)InterlockedIncrement(&Header->RefCount);
+ InterlockedIncrement(&Header->RefCount);
}
POBJECT_HEADER Header;
LONG NewRefCount;
BOOL Permanent;
- ULONG HandleCount;
ASSERT(Object);
/* Extract the object header. */
Header = BODY_TO_HEADER(Object);
Permanent = Header->Permanent;
- HandleCount = Header->HandleCount;
/*
Drop our reference and get the new count so we can tell if this was the
last reference.
*/
NewRefCount = InterlockedDecrement(&Header->RefCount);
+ DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object, NewRefCount, &Header->ObjectType->TypeName);
ASSERT(NewRefCount >= 0);
/* Check whether the object can now be deleted. */
if (NewRefCount == 0 &&
- HandleCount == 0 &&
!Permanent)
{
ObpDeleteObjectDpcLevel(Header, NewRefCount);
/* 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;
-}
-
-VOID
-PspReferenceCidObject(PCID_OBJECT Object)
-{
- InterlockedIncrement(&Object->ref);
-}
-
-VOID
-PspDereferenceCidObject(PCID_OBJECT Object)
-{
- if(InterlockedDecrement(&Object->ref) == 0)
- {
- ExFreePool(Object);
- }
+ PspCidTable = ExCreateHandleTable(NULL);
+ ASSERT(PspCidTable);
}
NTSTATUS
PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle)
{
- KIRQL oldIrql;
- PCID_OBJECT cido = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(CID_OBJECT),
- TAG_CIDOBJECT);
- if(cido != NULL)
+ HANDLE_TABLE_ENTRY NewEntry;
+ LONG ExHandle;
+
+ 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
{
- cido->ref = 1;
- ExInitializeFastMutex(&cido->Lock);
- cido->Obj.Object = Object;
-
- KeAcquireSpinLock(&CidLock, &oldIrql);
- cido->Handle = (HANDLE)((ULONG_PTR)(++CidCounter) << 2);
- InsertTailList(&CidHead, &cido->Entry);
- KeReleaseSpinLock(&CidLock, oldIrql);
-
- *Handle = cido->Handle;
+ DPRINT1("Can't create CID handles for %wZ objects\n", &ObjectType->TypeName);
+ KEBUGCHECK(0);
+ }
+
+ ExHandle = ExCreateHandle(PspCidTable,
+ &NewEntry);
+ if(ExHandle != EX_INVALID_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;
+ PHANDLE_TABLE_ENTRY Entry;
+ LONG ExHandle = HANDLE_TO_EX_HANDLE(CidHandle);
- if(CidHandle == NULL)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- KeAcquireSpinLock(&CidLock, &oldIrql);
- Current = CidHead.Flink;
- while(Current != &CidHead)
+ PAGED_CODE();
+
+ 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)))
{
- RemoveEntryList(&cido->Entry);
- cido->Handle = NULL;
- Found = cido;
- break;
+ ExDestroyHandleByEntry(PspCidTable,
+ Entry,
+ ExHandle);
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ ExUnlockHandleTableEntry(PspCidTable,
+ Entry);
+ return STATUS_OBJECT_TYPE_MISMATCH;
}
- Current = Current->Flink;
- }
- KeReleaseSpinLock(&CidLock, oldIrql);
-
- if(Found != NULL)
- {
- PspDereferenceCidObject(Found);
- return STATUS_SUCCESS;
}
- return STATUS_UNSUCCESSFUL;
+ return STATUS_INVALID_HANDLE;
}
-PCID_OBJECT
-PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
+PHANDLE_TABLE_ENTRY
+PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object)
{
- PCID_OBJECT cido, Found = NULL;
- PLIST_ENTRY Current;
- KIRQL oldIrql;
+ PHANDLE_TABLE_ENTRY Entry;
- if(CidHandle == NULL)
- {
- return NULL;
- }
+ PAGED_CODE();
+
+ KeEnterCriticalRegion();
- KeAcquireSpinLock(&CidLock, &oldIrql);
- Current = CidHead.Flink;
- while(Current != &CidHead)
+ Entry = ExMapHandleToPointer(PspCidTable,
+ HANDLE_TO_EX_HANDLE(CidHandle));
+ if(Entry != NULL)
{
- cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
- if(cido->Handle == CidHandle)
+ 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
{
- Found = cido;
- PspReferenceCidObject(Found);
- break;
+ DPRINT1("CID Obj type mismatch handle 0x%x %wZ vs 0x%x\n", CidHandle,
+ &ObjectType->TypeName, Entry->u2.GrantedAccess);
+ ExUnlockHandleTableEntry(PspCidTable,
+ Entry);
+ KEBUGCHECK(0);
}
- Current = Current->Flink;
}
- KeReleaseSpinLock(&CidLock, oldIrql);
- if(Found != NULL)
- {
- ExAcquireFastMutex(&Found->Lock);
- }
-
- return Found;
+ KeLeaveCriticalRegion();
+
+ return NULL;
}
VOID
-PsUnlockCidObject(PCID_OBJECT CidObject)
+PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry)
{
- ExReleaseFastMutex(&CidObject->Lock);
- PspDereferenceCidObject(CidObject);
+ PAGED_CODE();
+
+ ExUnlockHandleTableEntry(PspCidTable,
+ CidEntry);
+ KeLeaveCriticalRegion();
}
/* EOF */
Process = Thread->ThreadsProcess;
Thread->ThreadsProcess = NULL;
- PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+ if(Thread->Cid.UniqueThread != NULL)
+ {
+ PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+ }
if(Thread->Tcb.Win32Thread != NULL)
{
NTSTATUS
PsInitializeThread(PEPROCESS Process,
PETHREAD* ThreadPtr,
- PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ThreadAttributes,
+ POBJECT_ATTRIBUTES ObjectAttributes,
BOOLEAN First)
{
PETHREAD Thread;
NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
KIRQL oldIrql;
-
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
if (Process == NULL)
{
Process = PsInitialSystemProcess;
}
-
- /*
- * Reference process
- */
- ObReferenceObjectByPointer(Process,
- PROCESS_CREATE_THREAD,
- PsProcessType,
- KernelMode);
/*
* Create and initialize thread
*/
- Status = ObCreateObject(UserMode,
+ Status = ObCreateObject(PreviousMode,
PsThreadType,
- ThreadAttributes,
+ ObjectAttributes,
KernelMode,
NULL,
sizeof(ETHREAD),
(PVOID*)&Thread);
if (!NT_SUCCESS(Status))
{
- ObDereferenceObject (Process);
return(Status);
}
- /* create a client id handle */
- Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject (Thread);
- ObDereferenceObject (Process);
- return Status;
- }
- Thread->ThreadsProcess = Process;
- Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
+ /*
+ * Reference process
+ */
+ ObReferenceObjectByPointer(Process,
+ PROCESS_CREATE_THREAD,
+ PsProcessType,
+ KernelMode);
+
+ Thread->ThreadsProcess = Process;
+ Thread->Cid.UniqueThread = NULL;
+ Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
DPRINT("Thread = %x\n",Thread);
KeReleaseDispatcherDatabaseLock(oldIrql);
*ThreadPtr = Thread;
-
- Status = ObInsertObject((PVOID)Thread,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- ThreadHandle);
- return(Status);
+
+ return STATUS_SUCCESS;
}
Status = PsInitializeThread(Process,
&Thread,
- &hThread,
- DesiredAccess,
ObjectAttributes,
FALSE);
ObDereferenceObject(Process);
-
+
if (!NT_SUCCESS(Status))
{
return(Status);
}
+
+ /* create a client id handle */
+ Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Thread);
+ return Status;
+ }
Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
if (!NT_SUCCESS(Status))
{
+ PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+ ObDereferenceObject(Thread);
return(Status);
}
InitialTeb);
if (!NT_SUCCESS(Status))
{
+ PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+ ObDereferenceObject(Thread);
return(Status);
}
Thread->Tcb.Teb = TebBase;
PsUnblockThread(Thread, NULL, 0);
KeReleaseDispatcherDatabaseLock(oldIrql);
- _SEH_TRY
+ Status = ObInsertObject((PVOID)Thread,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &hThread);
+ if(NT_SUCCESS(Status))
{
- if(ClientId != NULL)
+ _SEH_TRY
{
- *ClientId = Thread->Cid;
+ if(ClientId != NULL)
+ {
+ *ClientId = Thread->Cid;
+ }
+ *ThreadHandle = hThread;
}
- *ThreadHandle = hThread;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- _SEH_END;
-
+
return Status;
}
Status = PsInitializeThread(NULL,
&Thread,
- ThreadHandle,
- DesiredAccess,
ObjectAttributes,
FALSE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
+
+ Status = PsCreateCidHandle(Thread,
+ PsThreadType,
+ &Thread->Cid.UniqueThread);
+ if(!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Thread);
+ return Status;
+ }
Thread->StartAddress = StartRoutine;
Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ ObDereferenceObject(Thread);
+ return(Status);
}
if (ClientId != NULL)
PsUnblockThread(Thread, NULL, 0);
KeReleaseDispatcherDatabaseLock(oldIrql);
- return(STATUS_SUCCESS);
+ Status = ObInsertObject((PVOID)Thread,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ ThreadHandle);
+
+ /* don't dereference the thread, the initial reference serves as the keep-alive
+ reference which will be removed by the thread reaper */
+
+ return Status;
}
{
NTSTATUS Status;
PETHREAD IdleThread;
- HANDLE IdleThreadHandle;
+ KIRQL oldIrql;
- Status = PsCreateSystemThread(&IdleThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- NULL,
- PsIdleThreadMain,
- NULL);
- if(!NT_SUCCESS(Status))
- {
- DPRINT("Couldn't create Idle System Thread!");
- KEBUGCHECK(0);
- return;
- }
- Status = ObReferenceObjectByHandle(IdleThreadHandle,
- THREAD_ALL_ACCESS,
- PsThreadType,
- KernelMode,
- (PVOID*)&IdleThread,
- NULL);
- if(!NT_SUCCESS(Status))
- {
- DPRINT("Couldn't get pointer to Idle System Thread!");
- KEBUGCHECK(0);
- return;
- }
- NtClose(IdleThreadHandle);
+ Status = PsInitializeThread(NULL,
+ &IdleThread,
+ NULL,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Couldn't create idle system thread! Status: 0x%x\n", Status);
+ KEBUGCHECK(0);
+ return;
+ }
+
+ IdleThread->StartAddress = PsIdleThreadMain;
+ Status = KiArchInitThread(&IdleThread->Tcb, PsIdleThreadMain, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Couldn't initialize system idle thread! Status: 0x%x\n", Status);
+ ObDereferenceObject(IdleThread);
+ KEBUGCHECK(0);
+ return;
+ }
+
+ oldIrql = KeAcquireDispatcherDatabaseLock ();
+ PsUnblockThread(IdleThread, NULL, 0);
+ KeReleaseDispatcherDatabaseLock(oldIrql);
+
KeGetCurrentPrcb()->IdleThread = &IdleThread->Tcb;
KeSetPriorityThread(&IdleThread->Tcb, LOW_PRIORITY);
KeSetAffinityThread(&IdleThread->Tcb, 1 << 0);
PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
PsTerminateWin32Process(CurrentProcess);
+
PiTerminateProcess(CurrentProcess, ExitStatus);
}
ObGetObjectHandleCount(Process));
ObReferenceObject(Process);
- if (InterlockedExchangeUL(&Process->Pcb.State,
- PROCESS_STATE_TERMINATED) ==
- PROCESS_STATE_TERMINATED)
+ if (Process->Pcb.State == PROCESS_STATE_TERMINATED)
{
ObDereferenceObject(Process);
return(STATUS_SUCCESS);
}
+
+ Process->Pcb.State = PROCESS_STATE_TERMINATED;
+
CurrentProcess = PsGetCurrentProcess();
if (Process != CurrentProcess)
{
KeAttachProcess(&Process->Pcb);
}
- ObCloseAllHandles(Process);
+
+ ObDeleteHandleTable(Process);
+ if(Process->UniqueProcessId != NULL)
+ {
+ PsDeleteCidHandle(Process->UniqueProcessId, PsProcessType);
+ }
+
if (Process != CurrentProcess)
{
KeDetachProcess();
strcpy(PsInitialSystemProcess->ImageFileName, "System");
- Status = PsCreateCidHandle(PsInitialSystemProcess,
- PsProcessType,
- &PsInitialSystemProcess->UniqueProcessId);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
- return;
- }
-
PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
InsertHeadList(&PsActiveProcessHead,
KDB_DELETEPROCESS_HOOK(Process);
ObDereferenceObject(Process->Token);
- ObDeleteHandleTable(Process);
if (CurrentProcess != Process)
{
case ProcessHandleCount:
{
- ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
+ ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
_SEH_TRY
{
PsLookupProcessByProcessId(IN HANDLE ProcessId,
OUT PEPROCESS *Process)
{
- PLIST_ENTRY current_entry;
- PEPROCESS current;
+ PHANDLE_TABLE_ENTRY CidEntry;
+ PEPROCESS FoundProcess;
- ExAcquireFastMutex(&PspActiveProcessMutex);
+ PAGED_CODE();
- current_entry = PsActiveProcessHead.Flink;
- while (current_entry != &PsActiveProcessHead)
- {
- current = CONTAINING_RECORD(current_entry,
- EPROCESS,
- ProcessListEntry);
- if (current->UniqueProcessId == ProcessId)
- {
- *Process = current;
- ObReferenceObject(current);
- ExReleaseFastMutex(&PspActiveProcessMutex);
- return(STATUS_SUCCESS);
- }
- current_entry = current_entry->Flink;
- }
+ ASSERT(Process);
- ExReleaseFastMutex(&PspActiveProcessMutex);
+ CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
+ if(CidEntry != NULL)
+ {
+ ObReferenceObject(FoundProcess);
+
+ PsUnlockCidHandle(CidEntry);
+
+ *Process = FoundProcess;
+ return STATUS_SUCCESS;
+ }
- return(STATUS_INVALID_PARAMETER);
+ return STATUS_INVALID_PARAMETER;
}
VOID
VOID INIT_FUNCTION
PiInitProcessManager(VOID)
{
+ NTSTATUS Status;
+
PsInitClientIDManagment();
PsInitJobManagment();
PsInitProcessManagment();
PsInitThreadManagment();
PsInitIdleThread();
+
+ Status = PsCreateCidHandle(PsInitialSystemProcess,
+ PsProcessType,
+ &PsInitialSystemProcess->UniqueProcessId);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
+ KEBUGCHECK(0);
+ }
+
PsInitialiseSuspendImplementation();
PsInitialiseW32Call();
}
/*
* @unimplemented
- */
+ */
BOOLEAN
STDCALL
PsIsSystemThread(
/*
* @implemented
- */
+ */
BOOLEAN
STDCALL
PsIsThreadImpersonating(
PKPCR Pcr;
Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
- Pcr->PrcbData.QuantumEnd = TRUE;
+ Pcr->Prcb->QuantumEnd = TRUE;
KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
}
/*
* @unimplemented
- */
+ */
NTSTATUS
STDCALL
PsRemoveCreateThreadNotifyRoutine (
PsPrepareForApplicationProcessorInit(ULONG Id)
{
PETHREAD IdleThread;
- HANDLE IdleThreadHandle;
- PKPCR Pcr = (PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE);
+ PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb;
PsInitializeThread(NULL,
&IdleThread,
- &IdleThreadHandle,
- THREAD_ALL_ACCESS,
NULL,
FALSE);
IdleThread->Tcb.State = THREAD_STATE_RUNNING;
IdleThread->Tcb.UserAffinity = 1 << Id;
IdleThread->Tcb.Priority = LOW_PRIORITY;
IdleThread->Tcb.BasePriority = LOW_PRIORITY;
- Pcr->PrcbData.IdleThread = &IdleThread->Tcb;
- Pcr->PrcbData.CurrentThread = &IdleThread->Tcb;
+ Prcb->IdleThread = &IdleThread->Tcb;
+ Prcb->CurrentThread = &IdleThread->Tcb;
Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit;
- NtClose(IdleThreadHandle);
DPRINT("IdleThread for Processor %d has PID %d\n",
Id, IdleThread->Cid.UniqueThread);
}
HANDLE PiReaperThreadHandle;
PETHREAD FirstThread;
ULONG i;
- HANDLE FirstThreadHandle;
NTSTATUS Status;
for (i=0; i < MAXIMUM_PRIORITY; i++)
ObpCreateTypeObject(PsThreadType);
- PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle,
- THREAD_ALL_ACCESS,NULL, TRUE);
+ PsInitializeThread(NULL, &FirstThread, NULL, TRUE);
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
FirstThread->Tcb.FreezeCount = 0;
FirstThread->Tcb.UserAffinity = (1 << 0); /* Set the affinity of the first thread to the boot processor */
FirstThread->Tcb.Affinity = (1 << 0);
KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread;
- NtClose(FirstThreadHandle);
DPRINT("FirstThread %x\n",FirstThread);
{
for (i = 0; i < KeNumberProcessors; i++)
{
- Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
- if (Pcr->PrcbData.CurrentThread == Thread)
+ Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
+ if (Pcr->Prcb->CurrentThread == Thread)
{
KeReleaseDispatcherDatabaseLockFromDpcLevel();
KiRequestReschedule(i);
for (i = 0; i < KeNumberProcessors; i++)
{
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
- if (Pcr->PrcbData.CurrentThread == Thread)
+ if (Pcr->Prcb->CurrentThread == Thread)
{
if (!(Affinity & ProcessorMask))
{
NTSTATUS STDCALL
NtOpenThread(OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN PCLIENT_ID ClientId)
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN PCLIENT_ID ClientId OPTIONAL)
{
- NTSTATUS Status = STATUS_INVALID_PARAMETER;
-
+ KPROCESSOR_MODE PreviousMode;
+ CLIENT_ID SafeClientId;
+ HANDLE hThread;
+ NTSTATUS Status = STATUS_SUCCESS;
+
PAGED_CODE();
- if((NULL != ThreadHandle)&&(NULL != ObjectAttributes))
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
{
- PETHREAD EThread = NULL;
+ _SEH_TRY
+ {
+ ProbeForWrite(ThreadHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ if(ClientId != NULL)
+ {
+ ProbeForRead(ClientId,
+ sizeof(CLIENT_ID),
+ sizeof(ULONG));
+ SafeClientId = *ClientId;
+ ClientId = &SafeClientId;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- if((ClientId)
- && (ClientId->UniqueThread))
- {
- // It is an error to specify both
- // ObjectAttributes.ObjectName
- // and ClientId.
- if((ObjectAttributes)
- && (ObjectAttributes->ObjectName)
- && (0 < ObjectAttributes->ObjectName->Length))
- {
- return(STATUS_INVALID_PARAMETER_MIX);
- }
- // Parameters mix OK
- Status = PsLookupThreadByThreadId(ClientId->UniqueThread,
- & EThread);
- }
- else if((ObjectAttributes)
- && (ObjectAttributes->ObjectName)
- && (0 < ObjectAttributes->ObjectName->Length))
- {
- // Three Ob attributes are forbidden
- if(!(ObjectAttributes->Attributes &
- (OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENIF)))
- {
- Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
- ObjectAttributes->Attributes,
- NULL,
- DesiredAccess,
- PsThreadType,
- UserMode,
- NULL,
- (PVOID*) & EThread);
- }
- }
- // EThread may be OK...
- if(STATUS_SUCCESS == Status)
- {
- Status = ObCreateHandle(PsGetCurrentProcess(),
- EThread,
- DesiredAccess,
- FALSE,
- ThreadHandle);
- ObDereferenceObject(EThread);
- }
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ if(!((ObjectAttributes == NULL) ^ (ClientId == NULL)))
+ {
+ DPRINT("NtOpenThread should be called with either ObjectAttributes or ClientId!\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if(ClientId != NULL)
+ {
+ PETHREAD Thread;
+
+ Status = PsLookupThreadByThreadId(ClientId->UniqueThread,
+ &Thread);
+ if(NT_SUCCESS(Status))
+ {
+ Status = ObInsertObject(Thread,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &hThread);
+
+ ObDereferenceObject(Thread);
+ }
+ }
+ else
+ {
+ Status = ObOpenObjectByName(ObjectAttributes,
+ PsThreadType,
+ NULL,
+ PreviousMode,
+ DesiredAccess,
+ NULL,
+ &hThread);
+ }
+
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *ThreadHandle = hThread;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- return(Status);
+
+ return Status;
}
NTSTATUS STDCALL
OUT PEPROCESS *Process OPTIONAL,
OUT PETHREAD *Thread)
{
- PCID_OBJECT CidObject;
+ PHANDLE_TABLE_ENTRY CidEntry;
PETHREAD FoundThread;
- CidObject = PsLockCidHandle((HANDLE)Cid->UniqueThread, PsThreadType);
- if(CidObject != NULL)
+ PAGED_CODE();
+
+ ASSERT(Thread);
+ ASSERT(Cid);
+
+ CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread);
+ if(CidEntry != NULL)
{
- FoundThread = CidObject->Obj.Thread;
ObReferenceObject(FoundThread);
-
+
+ PsUnlockCidHandle(CidEntry);
+
if(Process != NULL)
{
*Process = FoundThread->ThreadsProcess;
- ObReferenceObject(FoundThread->ThreadsProcess);
}
-
- PsUnlockCidObject(CidObject);
+ *Thread = FoundThread;
return STATUS_SUCCESS;
}
PsLookupThreadByThreadId(IN HANDLE ThreadId,
OUT PETHREAD *Thread)
{
- PCID_OBJECT CidObject;
-
- CidObject = PsLockCidHandle(ThreadId, PsThreadType);
- if(CidObject != NULL)
+ PHANDLE_TABLE_ENTRY CidEntry;
+ PETHREAD FoundThread;
+
+ PAGED_CODE();
+
+ ASSERT(Thread);
+
+ CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread);
+ if(CidEntry != NULL)
{
- *Thread = CidObject->Obj.Thread;
- ObReferenceObject(*Thread);
-
- PsUnlockCidObject(CidObject);
+ ObReferenceObject(FoundThread);
+
+ PsUnlockCidHandle(CidEntry);
+
+ *Thread = FoundThread;
return STATUS_SUCCESS;
}
#define NDEBUG
#include <debug.h>
-#define HEADER_TO_BODY(ObjectHeader) \
+#define USER_HEADER_TO_BODY(ObjectHeader) \
((PVOID)(((PUSER_OBJECT_HEADER)ObjectHeader) + 1))
-#define BODY_TO_HEADER(ObjectBody) \
+#define USER_BODY_TO_HEADER(ObjectBody) \
((PUSER_OBJECT_HEADER)(((PUSER_OBJECT_HEADER)ObjectBody) - 1))
/* FUNCTIONS *****************************************************************/
if (ObjectBody != NULL)
{
- PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
ObjectHeader->HandleCount--;
if (ObjectBody != NULL)
{
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObjectHeader->HandleCount--;
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
Entry->ObjectBody = NULL;
if (Handle != NULL)
{
Status = ObmCreateHandle(HandleTable,
- HEADER_TO_BODY(ObjectHeader),
+ USER_HEADER_TO_BODY(ObjectHeader),
Handle);
}
ULONG FASTCALL
ObmGetReferenceCount(PVOID ObjectBody)
{
- PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
return ObjectHeader->RefCount;
}
ULONG FASTCALL
ObmGetHandleCount(PVOID ObjectBody)
{
- PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
return ObjectHeader->HandleCount;
}
return;
}
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObjectHeader->RefCount++;
return;
}
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObjectHeader->RefCount--;
ObmpPerformRetentionChecks(ObjectHeader);
{
PUSER_OBJECT_HEADER ObjectHeader;
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
{
return NULL;
}
- ObjectBody = HEADER_TO_BODY(ObjectHeader);
+ ObjectBody = USER_HEADER_TO_BODY(ObjectHeader);
RtlZeroMemory(ObjectBody, ObjectSize);
if (ObjectBody != NULL)
{
- BODY_TO_HEADER(ObjectBody)->HandleCount++;
+ USER_BODY_TO_HEADER(ObjectBody)->HandleCount++;
}
ObmpLockHandleTable(HandleTable);
ObmpUnlockHandleTable(HandleTable);
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
{