- fixed handle table structures

- 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
This commit is contained in:
Thomas Bluemel 2005-03-13 14:21:47 +00:00
parent a3c3364289
commit d288e05d38
24 changed files with 1880 additions and 979 deletions

View file

@ -15,22 +15,22 @@ ARCH := i386
# 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

View file

@ -42,6 +42,15 @@ VOID STDCALL KeAcquireSpinLock (PKSPIN_LOCK SpinLock,
#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

View file

@ -87,18 +87,42 @@ typedef struct _OBJECT_ATTRIBUTES
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

View file

@ -239,6 +239,7 @@ OBJECTS_EX = \
ex/event.o \
ex/evtpair.o \
ex/fmutex.o \
ex/handle.o \
ex/hashtab.o \
ex/init.o \
ex/interlck.o \

View file

@ -0,0 +1,949 @@
/* $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 */

View file

@ -662,6 +662,7 @@ ExInit3 (VOID)
ExpInitializeMutantImplementation();
ExpInitializeSemaphoreImplementation();
ExpInitializeTimerImplementation();
ExpInitializeHandleTables();
LpcpInitSystem();
ExpInitializeProfileImplementation();
ExpWin32kInit();

View file

@ -617,7 +617,7 @@ QSI_DEF(SystemProcessInformation)
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;
@ -849,7 +849,7 @@ QSI_DEF(SystemHandleInformation)
do
{
hCount = hCount + ObpGetHandleCountByHandleTable(&pr->HandleTable);
hCount = hCount + ObpGetHandleCountByHandleTable(pr->ObjectTable);
pr = PsGetNextProcess(pr);
if ((pr == syspr) || (pr == NULL))
@ -885,7 +885,7 @@ QSI_DEF(SystemHandleInformation)
{
int Count = 0, HandleCount = 0;
HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
for (Count = 0; HandleCount > 0 ; HandleCount--)
{

View file

@ -85,32 +85,55 @@ ExWorkerThreadEntryPoint(IN PVOID context)
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

View file

@ -109,6 +109,65 @@ VOID
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

View file

@ -228,17 +228,22 @@ enum
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);
@ -260,13 +265,11 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
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,

View file

@ -345,7 +345,7 @@ struct _EPROCESS
LIST_ENTRY SessionProcessLinks;
struct _EPORT *DebugPort;
struct _EPORT *ExceptionPort;
HANDLE_TABLE HandleTable;
PHANDLE_TABLE ObjectTable;
PVOID Token;
FAST_MUTEX WorkingSetLock;
ULONG WorkingSetPage;
@ -454,8 +454,6 @@ VOID PsQueueThreadReap(PETHREAD Thread);
NTSTATUS
PsInitializeThread(PEPROCESS Process,
PETHREAD* ThreadPtr,
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
BOOLEAN First);
@ -641,26 +639,12 @@ typedef struct _EJOB
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);

View file

@ -52,7 +52,7 @@ IopCloseFile(PVOID ObjectBody,
DPRINT("IopCloseFile()\n");
if (HandleCount > 0 || FileObject->DeviceObject == NULL)
if (HandleCount > 1 || FileObject->DeviceObject == NULL)
{
return;
}

View file

@ -1740,10 +1740,13 @@ IopInvalidateDeviceRelations(
&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

View file

@ -41,8 +41,7 @@ NiClosePort (PVOID ObjectBody, ULONG HandleCount)
* 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);
@ -64,8 +63,7 @@ NiClosePort (PVOID ObjectBody, ULONG HandleCount)
* 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;

File diff suppressed because it is too large Load diff

View file

@ -25,18 +25,6 @@ typedef struct _RETENTION_CHECK_PARAMS
/* 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,
@ -734,7 +722,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
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;
@ -1111,7 +1099,7 @@ ObfReferenceObject(IN PVOID Object)
KEBUGCHECK(0);
}
(VOID)InterlockedIncrement(&Header->RefCount);
InterlockedIncrement(&Header->RefCount);
}
@ -1137,25 +1125,23 @@ ObfDereferenceObject(IN PVOID Object)
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);

View file

@ -16,147 +16,126 @@
/* 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)
PAGED_CODE();
Entry = ExMapHandleToPointer(PspCidTable,
ExHandle);
if(Entry != NULL)
{
return STATUS_INVALID_PARAMETER;
}
KeAcquireSpinLock(&CidLock, &oldIrql);
Current = CidHead.Flink;
while(Current != &CidHead)
{
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;
}
KeAcquireSpinLock(&CidLock, &oldIrql);
Current = CidHead.Flink;
while(Current != &CidHead)
{
cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
if(cido->Handle == CidHandle)
{
Found = cido;
PspReferenceCidObject(Found);
break;
}
Current = Current->Flink;
}
KeReleaseSpinLock(&CidLock, oldIrql);
if(Found != NULL)
{
ExAcquireFastMutex(&Found->Lock);
}
PAGED_CODE();
return Found;
KeEnterCriticalRegion();
Entry = ExMapHandleToPointer(PspCidTable,
HANDLE_TO_EX_HANDLE(CidHandle));
if(Entry != NULL)
{
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->TypeName, Entry->u2.GrantedAccess);
ExUnlockHandleTableEntry(PspCidTable,
Entry);
KEBUGCHECK(0);
}
}
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 */

View file

@ -376,7 +376,10 @@ PiDeleteThread(PVOID ObjectBody)
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)
{
@ -395,19 +398,39 @@ PiDeleteThread(PVOID ObjectBody)
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;
}
/*
* Create and initialize thread
*/
Status = ObCreateObject(PreviousMode,
PsThreadType,
ObjectAttributes,
KernelMode,
NULL,
sizeof(ETHREAD),
0,
0,
(PVOID*)&Thread);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/*
* Reference process
@ -416,35 +439,10 @@ PsInitializeThread(PEPROCESS Process,
PROCESS_CREATE_THREAD,
PsProcessType,
KernelMode);
/*
* Create and initialize thread
*/
Status = ObCreateObject(UserMode,
PsThreadType,
ThreadAttributes,
KernelMode,
NULL,
sizeof(ETHREAD),
0,
0,
(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;
Thread->ThreadsProcess = Process;
Thread->Cid.UniqueThread = NULL;
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
DPRINT("Thread = %x\n",Thread);
@ -477,14 +475,8 @@ PsInitializeThread(PEPROCESS Process,
KeReleaseDispatcherDatabaseLock(oldIrql);
*ThreadPtr = Thread;
Status = ObInsertObject((PVOID)Thread,
NULL,
DesiredAccess,
0,
NULL,
ThreadHandle);
return(Status);
return STATUS_SUCCESS;
}
@ -737,21 +729,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
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);
}
@ -761,6 +761,8 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
InitialTeb);
if (!NT_SUCCESS(Status))
{
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
ObDereferenceObject(Thread);
return(Status);
}
Thread->Tcb.Teb = TebBase;
@ -808,20 +810,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
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_END;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
return Status;
}
@ -865,20 +876,28 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
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)
@ -890,7 +909,17 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
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;
}

View file

@ -52,34 +52,33 @@ PsInitIdleThread(VOID)
{
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);

View file

@ -218,6 +218,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
PsTerminateWin32Process(CurrentProcess);
PiTerminateProcess(CurrentProcess, ExitStatus);
}
@ -315,19 +316,26 @@ PiTerminateProcess(PEPROCESS Process,
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();

View file

@ -412,15 +412,6 @@ PsInitProcessManagment(VOID)
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,
@ -456,7 +447,6 @@ PiDeleteProcessWorker(PVOID pContext)
KDB_DELETEPROCESS_HOOK(Process);
ObDereferenceObject(Process->Token);
ObDeleteHandleTable(Process);
if (CurrentProcess != Process)
{
@ -1458,7 +1448,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
case ProcessHandleCount:
{
ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
_SEH_TRY
{
@ -2636,30 +2626,25 @@ NTSTATUS STDCALL
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);
return(STATUS_INVALID_PARAMETER);
PsUnlockCidHandle(CidEntry);
*Process = FoundProcess;
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
VOID

View file

@ -28,11 +28,23 @@ VOID PiShutdownProcessManager(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();
}

View file

@ -222,7 +222,7 @@ PsIsThreadTerminating(IN PETHREAD Thread)
/*
* @unimplemented
*/
*/
BOOLEAN
STDCALL
PsIsSystemThread(
@ -235,7 +235,7 @@ PsIsSystemThread(
/*
* @implemented
*/
*/
BOOLEAN
STDCALL
PsIsThreadImpersonating(
@ -251,7 +251,7 @@ KiRequestReschedule(CCHAR Processor)
PKPCR Pcr;
Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
Pcr->PrcbData.QuantumEnd = TRUE;
Pcr->Prcb->QuantumEnd = TRUE;
KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
}
@ -641,7 +641,7 @@ PsEnumThreadsByProcess(PEPROCESS Process)
/*
* @unimplemented
*/
*/
NTSTATUS
STDCALL
PsRemoveCreateThreadNotifyRoutine (
@ -704,13 +704,10 @@ VOID INIT_FUNCTION
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;
@ -719,12 +716,11 @@ PsPrepareForApplicationProcessorInit(ULONG Id)
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);
}
@ -738,7 +734,6 @@ PsInitThreadManagment(VOID)
HANDLE PiReaperThreadHandle;
PETHREAD FirstThread;
ULONG i;
HANDLE FirstThreadHandle;
NTSTATUS Status;
for (i=0; i < MAXIMUM_PRIORITY; i++)
@ -771,14 +766,12 @@ PsInitThreadManagment(VOID)
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);
@ -895,8 +888,8 @@ KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority)
{
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);
@ -959,7 +952,7 @@ KeSetAffinityThread(PKTHREAD Thread,
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))
{
@ -988,63 +981,95 @@ KeSetAffinityThread(PKTHREAD Thread,
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))
{
PETHREAD EThread = NULL;
PreviousMode = ExGetPreviousMode();
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(PreviousMode != KernelMode)
{
_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(!NT_SUCCESS(Status))
{
return 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;
}
NTSTATUS STDCALL
@ -1074,22 +1099,26 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
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;
}
@ -1104,15 +1133,21 @@ NTSTATUS STDCALL
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;
}

View file

@ -34,10 +34,10 @@
#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 *****************************************************************/
@ -125,7 +125,7 @@ ObmpCloseAllHandles(PUSER_HANDLE_TABLE HandleTable)
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--;
@ -191,7 +191,7 @@ ObmpDeleteHandle(PUSER_HANDLE_TABLE HandleTable,
if (ObjectBody != NULL)
{
ObjectHeader = BODY_TO_HEADER(ObjectBody);
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObjectHeader->HandleCount--;
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
Entry->ObjectBody = NULL;
@ -219,7 +219,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable,
if (Handle != NULL)
{
Status = ObmCreateHandle(HandleTable,
HEADER_TO_BODY(ObjectHeader),
USER_HEADER_TO_BODY(ObjectHeader),
Handle);
}
@ -230,7 +230,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable,
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;
}
@ -238,7 +238,7 @@ ObmGetReferenceCount(PVOID ObjectBody)
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;
}
@ -260,7 +260,7 @@ ObmReferenceObject(PVOID ObjectBody)
return;
}
ObjectHeader = BODY_TO_HEADER(ObjectBody);
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObjectHeader->RefCount++;
@ -284,7 +284,7 @@ ObmDereferenceObject(PVOID ObjectBody)
return;
}
ObjectHeader = BODY_TO_HEADER(ObjectBody);
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
ObjectHeader->RefCount--;
ObmpPerformRetentionChecks(ObjectHeader);
@ -303,7 +303,7 @@ ObmReferenceObjectByPointer(PVOID ObjectBody,
{
PUSER_OBJECT_HEADER ObjectHeader;
ObjectHeader = BODY_TO_HEADER(ObjectBody);
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
{
@ -331,7 +331,7 @@ ObmCreateObject(PUSER_HANDLE_TABLE HandleTable,
return NULL;
}
ObjectBody = HEADER_TO_BODY(ObjectHeader);
ObjectBody = USER_HEADER_TO_BODY(ObjectHeader);
RtlZeroMemory(ObjectBody, ObjectSize);
@ -369,7 +369,7 @@ ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable,
if (ObjectBody != NULL)
{
BODY_TO_HEADER(ObjectBody)->HandleCount++;
USER_BODY_TO_HEADER(ObjectBody)->HandleCount++;
}
ObmpLockHandleTable(HandleTable);
@ -456,7 +456,7 @@ ObmReferenceObjectByHandle(PUSER_HANDLE_TABLE HandleTable,
ObmpUnlockHandleTable(HandleTable);
ObjectHeader = BODY_TO_HEADER(ObjectBody);
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
{