mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 14:30:57 +00:00
- 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:
parent
a3c3364289
commit
d288e05d38
24 changed files with 1880 additions and 979 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
949
reactos/ntoskrnl/ex/handle.c
Normal file
949
reactos/ntoskrnl/ex/handle.c
Normal 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 */
|
|
@ -662,6 +662,7 @@ ExInit3 (VOID)
|
|||
ExpInitializeMutantImplementation();
|
||||
ExpInitializeSemaphoreImplementation();
|
||||
ExpInitializeTimerImplementation();
|
||||
ExpInitializeHandleTables();
|
||||
LpcpInitSystem();
|
||||
ExpInitializeProfileImplementation();
|
||||
ExpWin32kInit();
|
||||
|
|
|
@ -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--)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ IopCloseFile(PVOID ObjectBody,
|
|||
|
||||
DPRINT("IopCloseFile()\n");
|
||||
|
||||
if (HandleCount > 0 || FileObject->DeviceObject == NULL)
|
||||
if (HandleCount > 1 || FileObject->DeviceObject == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue