mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 10:45:24 +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
|
@ -15,22 +15,22 @@ ARCH := i386
|
||||||
# be optimized for.
|
# be optimized for.
|
||||||
#
|
#
|
||||||
|
|
||||||
OARCH := i486
|
OARCH := i586
|
||||||
|
|
||||||
#
|
#
|
||||||
# Whether to compile in the kernel debugger
|
# Whether to compile in the kernel debugger
|
||||||
#
|
#
|
||||||
KDBG := 0
|
KDBG := 1
|
||||||
|
|
||||||
#
|
#
|
||||||
# Whether to compile for debugging
|
# Whether to compile for debugging
|
||||||
#
|
#
|
||||||
DBG := 0
|
DBG := 1
|
||||||
|
|
||||||
#
|
#
|
||||||
# Whether to compile with optimizations
|
# Whether to compile with optimizations
|
||||||
#
|
#
|
||||||
OPTIMIZED := 0
|
OPTIMIZED := 1
|
||||||
|
|
||||||
#
|
#
|
||||||
# Whether to compile a multiprocessor or single processor version
|
# Whether to compile a multiprocessor or single processor version
|
||||||
|
|
|
@ -42,6 +42,15 @@ VOID STDCALL KeAcquireSpinLock (PKSPIN_LOCK SpinLock,
|
||||||
|
|
||||||
#ifndef __USE_W32API
|
#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);
|
VOID STDCALL KeAcquireSpinLockAtDpcLevel (IN PKSPIN_LOCK SpinLock);
|
||||||
|
|
||||||
#define KefAcquireSpinLockAtDpcLevel KeAcquireSpinLockAtDpcLevel
|
#define KefAcquireSpinLockAtDpcLevel KeAcquireSpinLockAtDpcLevel
|
||||||
|
|
|
@ -87,18 +87,42 @@ typedef struct _OBJECT_ATTRIBUTES
|
||||||
PVOID SecurityQualityOfService;
|
PVOID SecurityQualityOfService;
|
||||||
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
} 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 */
|
#endif /* __USE_W32API */
|
||||||
|
|
||||||
typedef struct _HANDLE_TABLE
|
typedef struct _HANDLE_TABLE
|
||||||
{
|
{
|
||||||
LIST_ENTRY ListHead;
|
ULONG Flags;
|
||||||
KSPIN_LOCK ListLock;
|
LONG HandleCount;
|
||||||
} HANDLE_TABLE;
|
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
|
#ifndef __USE_W32API
|
||||||
|
|
||||||
typedef struct _HANDLE_TABLE *PHANDLE_TABLE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: These will eventually become centerfold in the compliant Ob Manager
|
* 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
|
* 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/event.o \
|
||||||
ex/evtpair.o \
|
ex/evtpair.o \
|
||||||
ex/fmutex.o \
|
ex/fmutex.o \
|
||||||
|
ex/handle.o \
|
||||||
ex/hashtab.o \
|
ex/hashtab.o \
|
||||||
ex/init.o \
|
ex/init.o \
|
||||||
ex/interlck.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();
|
ExpInitializeMutantImplementation();
|
||||||
ExpInitializeSemaphoreImplementation();
|
ExpInitializeSemaphoreImplementation();
|
||||||
ExpInitializeTimerImplementation();
|
ExpInitializeTimerImplementation();
|
||||||
|
ExpInitializeHandleTables();
|
||||||
LpcpInitSystem();
|
LpcpInitSystem();
|
||||||
ExpInitializeProfileImplementation();
|
ExpInitializeProfileImplementation();
|
||||||
ExpWin32kInit();
|
ExpWin32kInit();
|
||||||
|
|
|
@ -617,7 +617,7 @@ QSI_DEF(SystemProcessInformation)
|
||||||
SpiCur->BasePriority = pr->Pcb.BasePriority;
|
SpiCur->BasePriority = pr->Pcb.BasePriority;
|
||||||
SpiCur->ProcessId = pr->UniqueProcessId;
|
SpiCur->ProcessId = pr->UniqueProcessId;
|
||||||
SpiCur->InheritedFromProcessId = pr->InheritedFromUniqueProcessId;
|
SpiCur->InheritedFromProcessId = pr->InheritedFromUniqueProcessId;
|
||||||
SpiCur->HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
|
SpiCur->HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
|
||||||
SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize;
|
SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize;
|
||||||
SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart;
|
SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart;
|
||||||
SpiCur->VmCounters.PageFaultCount = pr->LastFaultCount;
|
SpiCur->VmCounters.PageFaultCount = pr->LastFaultCount;
|
||||||
|
@ -849,7 +849,7 @@ QSI_DEF(SystemHandleInformation)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hCount = hCount + ObpGetHandleCountByHandleTable(&pr->HandleTable);
|
hCount = hCount + ObpGetHandleCountByHandleTable(pr->ObjectTable);
|
||||||
pr = PsGetNextProcess(pr);
|
pr = PsGetNextProcess(pr);
|
||||||
|
|
||||||
if ((pr == syspr) || (pr == NULL))
|
if ((pr == syspr) || (pr == NULL))
|
||||||
|
@ -885,7 +885,7 @@ QSI_DEF(SystemHandleInformation)
|
||||||
{
|
{
|
||||||
int Count = 0, HandleCount = 0;
|
int Count = 0, HandleCount = 0;
|
||||||
|
|
||||||
HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
|
HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
|
||||||
|
|
||||||
for (Count = 0; HandleCount > 0 ; HandleCount--)
|
for (Count = 0; HandleCount > 0 ; HandleCount--)
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,32 +85,55 @@ ExWorkerThreadEntryPoint(IN PVOID context)
|
||||||
static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
|
static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
|
||||||
KPRIORITY Priority)
|
KPRIORITY Priority)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
HANDLE hThread;
|
HANDLE hThread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
|
PAGED_CODE();
|
||||||
{
|
|
||||||
|
/* Loop through how many threads we need to create */
|
||||||
PsCreateSystemThread(&hThread,
|
for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
|
||||||
THREAD_ALL_ACCESS,
|
|
||||||
NULL,
|
/* Create the System Thread */
|
||||||
NULL,
|
Status = PsCreateSystemThread(&hThread,
|
||||||
NULL,
|
THREAD_ALL_ACCESS,
|
||||||
ExWorkerThreadEntryPoint,
|
NULL,
|
||||||
WorkQueue);
|
NULL,
|
||||||
ObReferenceObjectByHandle(hThread,
|
NULL,
|
||||||
THREAD_ALL_ACCESS,
|
ExWorkerThreadEntryPoint,
|
||||||
PsThreadType,
|
(PVOID)WorkQueue);
|
||||||
KernelMode,
|
if(NT_SUCCESS(Status))
|
||||||
(PVOID*)&Thread,
|
{
|
||||||
NULL);
|
/* Get the Thread */
|
||||||
KeSetPriorityThread(&Thread->Tcb,
|
Status = ObReferenceObjectByHandle(hThread,
|
||||||
Priority);
|
THREAD_SET_INFORMATION,
|
||||||
ObDereferenceObject(Thread);
|
PsThreadType,
|
||||||
ZwClose(hThread);
|
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
|
VOID INIT_FUNCTION
|
||||||
|
|
|
@ -109,6 +109,65 @@ VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
ExpInitializeExecutive(VOID);
|
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 **********************************************************/
|
/* OTHER FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
LONGLONG
|
LONGLONG
|
||||||
|
|
|
@ -228,17 +228,22 @@ enum
|
||||||
OBJTYP_MAX,
|
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 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 PDIRECTORY_OBJECT NameSpaceRoot;
|
||||||
extern POBJECT_TYPE ObSymbolicLinkType;
|
extern POBJECT_TYPE ObSymbolicLinkType;
|
||||||
|
|
||||||
|
|
||||||
POBJECT_HEADER BODY_TO_HEADER(PVOID body);
|
|
||||||
PVOID HEADER_TO_BODY(POBJECT_HEADER obj);
|
|
||||||
|
|
||||||
VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
|
VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
|
||||||
POBJECT_HEADER Header,
|
POBJECT_HEADER Header,
|
||||||
PWSTR Name);
|
PWSTR Name);
|
||||||
|
@ -260,13 +265,11 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
PVOID* ReturnedObject,
|
PVOID* ReturnedObject,
|
||||||
PUNICODE_STRING RemainingPath,
|
PUNICODE_STRING RemainingPath,
|
||||||
POBJECT_TYPE ObjectType);
|
POBJECT_TYPE ObjectType);
|
||||||
VOID ObCloseAllHandles(struct _EPROCESS* Process);
|
|
||||||
VOID ObDeleteHandleTable(struct _EPROCESS* Process);
|
VOID ObDeleteHandleTable(struct _EPROCESS* Process);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ObDeleteHandle(PEPROCESS Process,
|
ObDeleteHandle(PEPROCESS Process,
|
||||||
HANDLE Handle,
|
HANDLE Handle);
|
||||||
PVOID *ObjectBody);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ObpQueryHandleAttributes(HANDLE Handle,
|
ObpQueryHandleAttributes(HANDLE Handle,
|
||||||
|
|
|
@ -345,7 +345,7 @@ struct _EPROCESS
|
||||||
LIST_ENTRY SessionProcessLinks;
|
LIST_ENTRY SessionProcessLinks;
|
||||||
struct _EPORT *DebugPort;
|
struct _EPORT *DebugPort;
|
||||||
struct _EPORT *ExceptionPort;
|
struct _EPORT *ExceptionPort;
|
||||||
HANDLE_TABLE HandleTable;
|
PHANDLE_TABLE ObjectTable;
|
||||||
PVOID Token;
|
PVOID Token;
|
||||||
FAST_MUTEX WorkingSetLock;
|
FAST_MUTEX WorkingSetLock;
|
||||||
ULONG WorkingSetPage;
|
ULONG WorkingSetPage;
|
||||||
|
@ -454,8 +454,6 @@ VOID PsQueueThreadReap(PETHREAD Thread);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PsInitializeThread(PEPROCESS Process,
|
PsInitializeThread(PEPROCESS Process,
|
||||||
PETHREAD* ThreadPtr,
|
PETHREAD* ThreadPtr,
|
||||||
PHANDLE ThreadHandle,
|
|
||||||
ACCESS_MASK DesiredAccess,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
BOOLEAN First);
|
BOOLEAN First);
|
||||||
|
|
||||||
|
@ -641,26 +639,12 @@ typedef struct _EJOB
|
||||||
|
|
||||||
VOID INIT_FUNCTION PsInitJobManagment(VOID);
|
VOID INIT_FUNCTION PsInitJobManagment(VOID);
|
||||||
|
|
||||||
/* CID */
|
/* CLIENT ID */
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
NTSTATUS PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle);
|
NTSTATUS PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle);
|
||||||
NTSTATUS PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
|
NTSTATUS PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
|
||||||
PCID_OBJECT PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
|
PHANDLE_TABLE_ENTRY PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object);
|
||||||
VOID PsUnlockCidObject(PCID_OBJECT CidObject);
|
VOID PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry);
|
||||||
NTSTATUS PsLockProcess(PEPROCESS Process, BOOL Timeout);
|
NTSTATUS PsLockProcess(PEPROCESS Process, BOOL Timeout);
|
||||||
VOID PsUnlockProcess(PEPROCESS Process);
|
VOID PsUnlockProcess(PEPROCESS Process);
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ IopCloseFile(PVOID ObjectBody,
|
||||||
|
|
||||||
DPRINT("IopCloseFile()\n");
|
DPRINT("IopCloseFile()\n");
|
||||||
|
|
||||||
if (HandleCount > 0 || FileObject->DeviceObject == NULL)
|
if (HandleCount > 1 || FileObject->DeviceObject == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1740,10 +1740,13 @@ IopInvalidateDeviceRelations(
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
|
if(NT_SUCCESS(Status))
|
||||||
BootDrivers = NT_SUCCESS(Status) ? FALSE : TRUE;
|
{
|
||||||
|
BootDrivers = FALSE;
|
||||||
ZwClose(Handle);
|
ZwClose(Handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BootDrivers = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize services for discovered children. Only boot drivers will
|
* 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
|
* If the client has just closed its handle then tell the server what
|
||||||
* happened and disconnect this port.
|
* happened and disconnect this port.
|
||||||
*/
|
*/
|
||||||
if (HandleCount == 0 && Port->State == EPORT_CONNECTED_CLIENT &&
|
if (HandleCount == 1 && Port->State == EPORT_CONNECTED_CLIENT)
|
||||||
ObGetObjectPointerCount(Port) == 2)
|
|
||||||
{
|
{
|
||||||
DPRINT("Informing server\n");
|
DPRINT("Informing server\n");
|
||||||
Message.MessageSize = sizeof(LPC_MESSAGE);
|
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,
|
* If the server has closed all of its handles then disconnect the port,
|
||||||
* don't actually notify the client until it attempts an operation.
|
* don't actually notify the client until it attempts an operation.
|
||||||
*/
|
*/
|
||||||
if (HandleCount == 0 && Port->State == EPORT_CONNECTED_SERVER &&
|
if (HandleCount == 1 && Port->State == EPORT_CONNECTED_SERVER)
|
||||||
ObGetObjectPointerCount(Port) == 1)
|
|
||||||
{
|
{
|
||||||
DPRINT("Cleaning up server\n");
|
DPRINT("Cleaning up server\n");
|
||||||
Port->OtherPort->OtherPort = NULL;
|
Port->OtherPort->OtherPort = NULL;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,18 +25,6 @@ typedef struct _RETENTION_CHECK_PARAMS
|
||||||
|
|
||||||
/* FUNCTIONS ************************************************************/
|
/* 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
|
NTSTATUS
|
||||||
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||||
IN KPROCESSOR_MODE AccessMode,
|
IN KPROCESSOR_MODE AccessMode,
|
||||||
|
@ -734,7 +722,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
|
||||||
RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize));
|
RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize));
|
||||||
|
|
||||||
/* Initialize the object header */
|
/* Initialize the object header */
|
||||||
DPRINT("Initalizing header\n");
|
DPRINT("Initalizing header 0x%x (%wZ)\n", Header, &Type->TypeName);
|
||||||
Header->HandleCount = 0;
|
Header->HandleCount = 0;
|
||||||
Header->RefCount = 1;
|
Header->RefCount = 1;
|
||||||
Header->ObjectType = Type;
|
Header->ObjectType = Type;
|
||||||
|
@ -1111,7 +1099,7 @@ ObfReferenceObject(IN PVOID Object)
|
||||||
KEBUGCHECK(0);
|
KEBUGCHECK(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
(VOID)InterlockedIncrement(&Header->RefCount);
|
InterlockedIncrement(&Header->RefCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1137,25 +1125,23 @@ ObfDereferenceObject(IN PVOID Object)
|
||||||
POBJECT_HEADER Header;
|
POBJECT_HEADER Header;
|
||||||
LONG NewRefCount;
|
LONG NewRefCount;
|
||||||
BOOL Permanent;
|
BOOL Permanent;
|
||||||
ULONG HandleCount;
|
|
||||||
|
|
||||||
ASSERT(Object);
|
ASSERT(Object);
|
||||||
|
|
||||||
/* Extract the object header. */
|
/* Extract the object header. */
|
||||||
Header = BODY_TO_HEADER(Object);
|
Header = BODY_TO_HEADER(Object);
|
||||||
Permanent = Header->Permanent;
|
Permanent = Header->Permanent;
|
||||||
HandleCount = Header->HandleCount;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Drop our reference and get the new count so we can tell if this was the
|
Drop our reference and get the new count so we can tell if this was the
|
||||||
last reference.
|
last reference.
|
||||||
*/
|
*/
|
||||||
NewRefCount = InterlockedDecrement(&Header->RefCount);
|
NewRefCount = InterlockedDecrement(&Header->RefCount);
|
||||||
|
DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object, NewRefCount, &Header->ObjectType->TypeName);
|
||||||
ASSERT(NewRefCount >= 0);
|
ASSERT(NewRefCount >= 0);
|
||||||
|
|
||||||
/* Check whether the object can now be deleted. */
|
/* Check whether the object can now be deleted. */
|
||||||
if (NewRefCount == 0 &&
|
if (NewRefCount == 0 &&
|
||||||
HandleCount == 0 &&
|
|
||||||
!Permanent)
|
!Permanent)
|
||||||
{
|
{
|
||||||
ObpDeleteObjectDpcLevel(Header, NewRefCount);
|
ObpDeleteObjectDpcLevel(Header, NewRefCount);
|
||||||
|
|
|
@ -16,147 +16,126 @@
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
/*
|
PHANDLE_TABLE PspCidTable = NULL;
|
||||||
* FIXME - use a global handle table instead!
|
|
||||||
*/
|
|
||||||
|
|
||||||
KSPIN_LOCK CidLock;
|
|
||||||
LIST_ENTRY CidHead;
|
|
||||||
KEVENT CidReleaseEvent;
|
|
||||||
LONG CidCounter = 0;
|
|
||||||
LARGE_INTEGER ShortDelay, LongDelay;
|
|
||||||
|
|
||||||
#define TAG_CIDOBJECT TAG('C', 'I', 'D', 'O')
|
#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 *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
PsInitClientIDManagment(VOID)
|
PsInitClientIDManagment(VOID)
|
||||||
{
|
{
|
||||||
InitializeListHead(&CidHead);
|
PspCidTable = ExCreateHandleTable(NULL);
|
||||||
KeInitializeSpinLock(&CidLock);
|
ASSERT(PspCidTable);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle)
|
PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
HANDLE_TABLE_ENTRY NewEntry;
|
||||||
PCID_OBJECT cido = ExAllocatePoolWithTag(NonPagedPool,
|
LONG ExHandle;
|
||||||
sizeof(CID_OBJECT),
|
|
||||||
TAG_CIDOBJECT);
|
PAGED_CODE();
|
||||||
if(cido != NULL)
|
|
||||||
|
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;
|
DPRINT1("Can't create CID handles for %wZ objects\n", &ObjectType->TypeName);
|
||||||
ExInitializeFastMutex(&cido->Lock);
|
KEBUGCHECK(0);
|
||||||
cido->Obj.Object = Object;
|
}
|
||||||
|
|
||||||
KeAcquireSpinLock(&CidLock, &oldIrql);
|
ExHandle = ExCreateHandle(PspCidTable,
|
||||||
cido->Handle = (HANDLE)((ULONG_PTR)(++CidCounter) << 2);
|
&NewEntry);
|
||||||
InsertTailList(&CidHead, &cido->Entry);
|
if(ExHandle != EX_INVALID_HANDLE)
|
||||||
KeReleaseSpinLock(&CidLock, oldIrql);
|
{
|
||||||
|
*Handle = EX_HANDLE_TO_HANDLE(ExHandle);
|
||||||
*Handle = cido->Handle;
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
|
PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
|
||||||
{
|
{
|
||||||
PCID_OBJECT cido, Found = NULL;
|
PHANDLE_TABLE_ENTRY Entry;
|
||||||
PLIST_ENTRY Current;
|
LONG ExHandle = HANDLE_TO_EX_HANDLE(CidHandle);
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
if(CidHandle == NULL)
|
PAGED_CODE();
|
||||||
|
|
||||||
|
Entry = ExMapHandleToPointer(PspCidTable,
|
||||||
|
ExHandle);
|
||||||
|
if(Entry != NULL)
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
if((ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD)) ||
|
||||||
}
|
(ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS)))
|
||||||
|
|
||||||
KeAcquireSpinLock(&CidLock, &oldIrql);
|
|
||||||
Current = CidHead.Flink;
|
|
||||||
while(Current != &CidHead)
|
|
||||||
{
|
|
||||||
cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
|
|
||||||
if(cido->Handle == CidHandle)
|
|
||||||
{
|
{
|
||||||
RemoveEntryList(&cido->Entry);
|
ExDestroyHandleByEntry(PspCidTable,
|
||||||
cido->Handle = NULL;
|
Entry,
|
||||||
Found = cido;
|
ExHandle);
|
||||||
break;
|
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
|
PHANDLE_TABLE_ENTRY
|
||||||
PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
|
PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object)
|
||||||
{
|
{
|
||||||
PCID_OBJECT cido, Found = NULL;
|
PHANDLE_TABLE_ENTRY Entry;
|
||||||
PLIST_ENTRY Current;
|
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
if(CidHandle == NULL)
|
PAGED_CODE();
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
VOID
|
||||||
PsUnlockCidObject(PCID_OBJECT CidObject)
|
PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry)
|
||||||
{
|
{
|
||||||
ExReleaseFastMutex(&CidObject->Lock);
|
PAGED_CODE();
|
||||||
PspDereferenceCidObject(CidObject);
|
|
||||||
|
ExUnlockHandleTableEntry(PspCidTable,
|
||||||
|
CidEntry);
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -376,7 +376,10 @@ PiDeleteThread(PVOID ObjectBody)
|
||||||
Process = Thread->ThreadsProcess;
|
Process = Thread->ThreadsProcess;
|
||||||
Thread->ThreadsProcess = NULL;
|
Thread->ThreadsProcess = NULL;
|
||||||
|
|
||||||
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
if(Thread->Cid.UniqueThread != NULL)
|
||||||
|
{
|
||||||
|
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
||||||
|
}
|
||||||
|
|
||||||
if(Thread->Tcb.Win32Thread != NULL)
|
if(Thread->Tcb.Win32Thread != NULL)
|
||||||
{
|
{
|
||||||
|
@ -395,19 +398,39 @@ PiDeleteThread(PVOID ObjectBody)
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PsInitializeThread(PEPROCESS Process,
|
PsInitializeThread(PEPROCESS Process,
|
||||||
PETHREAD* ThreadPtr,
|
PETHREAD* ThreadPtr,
|
||||||
PHANDLE ThreadHandle,
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
ACCESS_MASK DesiredAccess,
|
|
||||||
POBJECT_ATTRIBUTES ThreadAttributes,
|
|
||||||
BOOLEAN First)
|
BOOLEAN First)
|
||||||
{
|
{
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
KPROCESSOR_MODE PreviousMode;
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PreviousMode = ExGetPreviousMode();
|
||||||
|
|
||||||
if (Process == NULL)
|
if (Process == NULL)
|
||||||
{
|
{
|
||||||
Process = PsInitialSystemProcess;
|
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
|
* Reference process
|
||||||
|
@ -416,35 +439,10 @@ PsInitializeThread(PEPROCESS Process,
|
||||||
PROCESS_CREATE_THREAD,
|
PROCESS_CREATE_THREAD,
|
||||||
PsProcessType,
|
PsProcessType,
|
||||||
KernelMode);
|
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 */
|
Thread->ThreadsProcess = Process;
|
||||||
Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread);
|
Thread->Cid.UniqueThread = NULL;
|
||||||
if (!NT_SUCCESS(Status))
|
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
|
||||||
{
|
|
||||||
ObDereferenceObject (Thread);
|
|
||||||
ObDereferenceObject (Process);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
Thread->ThreadsProcess = Process;
|
|
||||||
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
|
|
||||||
|
|
||||||
DPRINT("Thread = %x\n",Thread);
|
DPRINT("Thread = %x\n",Thread);
|
||||||
|
|
||||||
|
@ -477,14 +475,8 @@ PsInitializeThread(PEPROCESS Process,
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||||
|
|
||||||
*ThreadPtr = Thread;
|
*ThreadPtr = Thread;
|
||||||
|
|
||||||
Status = ObInsertObject((PVOID)Thread,
|
return STATUS_SUCCESS;
|
||||||
NULL,
|
|
||||||
DesiredAccess,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
ThreadHandle);
|
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -737,21 +729,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
|
|
||||||
Status = PsInitializeThread(Process,
|
Status = PsInitializeThread(Process,
|
||||||
&Thread,
|
&Thread,
|
||||||
&hThread,
|
|
||||||
DesiredAccess,
|
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(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);
|
Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,6 +761,8 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
InitialTeb);
|
InitialTeb);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
Thread->Tcb.Teb = TebBase;
|
Thread->Tcb.Teb = TebBase;
|
||||||
|
@ -808,20 +810,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
PsUnblockThread(Thread, NULL, 0);
|
PsUnblockThread(Thread, NULL, 0);
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,20 +876,28 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
|
||||||
|
|
||||||
Status = PsInitializeThread(NULL,
|
Status = PsInitializeThread(NULL,
|
||||||
&Thread,
|
&Thread,
|
||||||
ThreadHandle,
|
|
||||||
DesiredAccess,
|
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
FALSE);
|
FALSE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = PsCreateCidHandle(Thread,
|
||||||
|
PsThreadType,
|
||||||
|
&Thread->Cid.UniqueThread);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
Thread->StartAddress = StartRoutine;
|
Thread->StartAddress = StartRoutine;
|
||||||
Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext);
|
Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(Status);
|
ObDereferenceObject(Thread);
|
||||||
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClientId != NULL)
|
if (ClientId != NULL)
|
||||||
|
@ -890,7 +909,17 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
|
||||||
PsUnblockThread(Thread, NULL, 0);
|
PsUnblockThread(Thread, NULL, 0);
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
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;
|
NTSTATUS Status;
|
||||||
PETHREAD IdleThread;
|
PETHREAD IdleThread;
|
||||||
HANDLE IdleThreadHandle;
|
KIRQL oldIrql;
|
||||||
|
|
||||||
Status = PsCreateSystemThread(&IdleThreadHandle,
|
Status = PsInitializeThread(NULL,
|
||||||
THREAD_ALL_ACCESS,
|
&IdleThread,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
FALSE);
|
||||||
NULL,
|
if (!NT_SUCCESS(Status))
|
||||||
PsIdleThreadMain,
|
{
|
||||||
NULL);
|
DPRINT1("Couldn't create idle system thread! Status: 0x%x\n", Status);
|
||||||
if(!NT_SUCCESS(Status))
|
KEBUGCHECK(0);
|
||||||
{
|
return;
|
||||||
DPRINT("Couldn't create Idle System Thread!");
|
}
|
||||||
KEBUGCHECK(0);
|
|
||||||
return;
|
IdleThread->StartAddress = PsIdleThreadMain;
|
||||||
}
|
Status = KiArchInitThread(&IdleThread->Tcb, PsIdleThreadMain, NULL);
|
||||||
Status = ObReferenceObjectByHandle(IdleThreadHandle,
|
if (!NT_SUCCESS(Status))
|
||||||
THREAD_ALL_ACCESS,
|
{
|
||||||
PsThreadType,
|
DPRINT1("Couldn't initialize system idle thread! Status: 0x%x\n", Status);
|
||||||
KernelMode,
|
ObDereferenceObject(IdleThread);
|
||||||
(PVOID*)&IdleThread,
|
KEBUGCHECK(0);
|
||||||
NULL);
|
return;
|
||||||
if(!NT_SUCCESS(Status))
|
}
|
||||||
{
|
|
||||||
DPRINT("Couldn't get pointer to Idle System Thread!");
|
oldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||||
KEBUGCHECK(0);
|
PsUnblockThread(IdleThread, NULL, 0);
|
||||||
return;
|
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||||
}
|
|
||||||
NtClose(IdleThreadHandle);
|
|
||||||
KeGetCurrentPrcb()->IdleThread = &IdleThread->Tcb;
|
KeGetCurrentPrcb()->IdleThread = &IdleThread->Tcb;
|
||||||
KeSetPriorityThread(&IdleThread->Tcb, LOW_PRIORITY);
|
KeSetPriorityThread(&IdleThread->Tcb, LOW_PRIORITY);
|
||||||
KeSetAffinityThread(&IdleThread->Tcb, 1 << 0);
|
KeSetAffinityThread(&IdleThread->Tcb, 1 << 0);
|
||||||
|
|
|
@ -218,6 +218,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
|
||||||
|
|
||||||
PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
|
PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
|
||||||
PsTerminateWin32Process(CurrentProcess);
|
PsTerminateWin32Process(CurrentProcess);
|
||||||
|
|
||||||
PiTerminateProcess(CurrentProcess, ExitStatus);
|
PiTerminateProcess(CurrentProcess, ExitStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,19 +316,26 @@ PiTerminateProcess(PEPROCESS Process,
|
||||||
ObGetObjectHandleCount(Process));
|
ObGetObjectHandleCount(Process));
|
||||||
|
|
||||||
ObReferenceObject(Process);
|
ObReferenceObject(Process);
|
||||||
if (InterlockedExchangeUL(&Process->Pcb.State,
|
if (Process->Pcb.State == PROCESS_STATE_TERMINATED)
|
||||||
PROCESS_STATE_TERMINATED) ==
|
|
||||||
PROCESS_STATE_TERMINATED)
|
|
||||||
{
|
{
|
||||||
ObDereferenceObject(Process);
|
ObDereferenceObject(Process);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process->Pcb.State = PROCESS_STATE_TERMINATED;
|
||||||
|
|
||||||
CurrentProcess = PsGetCurrentProcess();
|
CurrentProcess = PsGetCurrentProcess();
|
||||||
if (Process != CurrentProcess)
|
if (Process != CurrentProcess)
|
||||||
{
|
{
|
||||||
KeAttachProcess(&Process->Pcb);
|
KeAttachProcess(&Process->Pcb);
|
||||||
}
|
}
|
||||||
ObCloseAllHandles(Process);
|
|
||||||
|
ObDeleteHandleTable(Process);
|
||||||
|
if(Process->UniqueProcessId != NULL)
|
||||||
|
{
|
||||||
|
PsDeleteCidHandle(Process->UniqueProcessId, PsProcessType);
|
||||||
|
}
|
||||||
|
|
||||||
if (Process != CurrentProcess)
|
if (Process != CurrentProcess)
|
||||||
{
|
{
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
|
|
|
@ -412,15 +412,6 @@ PsInitProcessManagment(VOID)
|
||||||
|
|
||||||
strcpy(PsInitialSystemProcess->ImageFileName, "System");
|
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;
|
PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
|
||||||
|
|
||||||
InsertHeadList(&PsActiveProcessHead,
|
InsertHeadList(&PsActiveProcessHead,
|
||||||
|
@ -456,7 +447,6 @@ PiDeleteProcessWorker(PVOID pContext)
|
||||||
KDB_DELETEPROCESS_HOOK(Process);
|
KDB_DELETEPROCESS_HOOK(Process);
|
||||||
|
|
||||||
ObDereferenceObject(Process->Token);
|
ObDereferenceObject(Process->Token);
|
||||||
ObDeleteHandleTable(Process);
|
|
||||||
|
|
||||||
if (CurrentProcess != Process)
|
if (CurrentProcess != Process)
|
||||||
{
|
{
|
||||||
|
@ -1458,7 +1448,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
|
||||||
|
|
||||||
case ProcessHandleCount:
|
case ProcessHandleCount:
|
||||||
{
|
{
|
||||||
ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
|
ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
|
||||||
|
|
||||||
_SEH_TRY
|
_SEH_TRY
|
||||||
{
|
{
|
||||||
|
@ -2636,30 +2626,25 @@ NTSTATUS STDCALL
|
||||||
PsLookupProcessByProcessId(IN HANDLE ProcessId,
|
PsLookupProcessByProcessId(IN HANDLE ProcessId,
|
||||||
OUT PEPROCESS *Process)
|
OUT PEPROCESS *Process)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current_entry;
|
PHANDLE_TABLE_ENTRY CidEntry;
|
||||||
PEPROCESS current;
|
PEPROCESS FoundProcess;
|
||||||
|
|
||||||
ExAcquireFastMutex(&PspActiveProcessMutex);
|
PAGED_CODE();
|
||||||
|
|
||||||
current_entry = PsActiveProcessHead.Flink;
|
ASSERT(Process);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
VOID
|
||||||
|
|
|
@ -28,11 +28,23 @@ VOID PiShutdownProcessManager(VOID)
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
PiInitProcessManager(VOID)
|
PiInitProcessManager(VOID)
|
||||||
{
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
PsInitClientIDManagment();
|
PsInitClientIDManagment();
|
||||||
PsInitJobManagment();
|
PsInitJobManagment();
|
||||||
PsInitProcessManagment();
|
PsInitProcessManagment();
|
||||||
PsInitThreadManagment();
|
PsInitThreadManagment();
|
||||||
PsInitIdleThread();
|
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();
|
PsInitialiseSuspendImplementation();
|
||||||
PsInitialiseW32Call();
|
PsInitialiseW32Call();
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,7 @@ PsIsThreadTerminating(IN PETHREAD Thread)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
STDCALL
|
||||||
PsIsSystemThread(
|
PsIsSystemThread(
|
||||||
|
@ -235,7 +235,7 @@ PsIsSystemThread(
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
STDCALL
|
STDCALL
|
||||||
PsIsThreadImpersonating(
|
PsIsThreadImpersonating(
|
||||||
|
@ -251,7 +251,7 @@ KiRequestReschedule(CCHAR Processor)
|
||||||
PKPCR Pcr;
|
PKPCR Pcr;
|
||||||
|
|
||||||
Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
|
Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
|
||||||
Pcr->PrcbData.QuantumEnd = TRUE;
|
Pcr->Prcb->QuantumEnd = TRUE;
|
||||||
KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
|
KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,7 +641,7 @@ PsEnumThreadsByProcess(PEPROCESS Process)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
PsRemoveCreateThreadNotifyRoutine (
|
PsRemoveCreateThreadNotifyRoutine (
|
||||||
|
@ -704,13 +704,10 @@ VOID INIT_FUNCTION
|
||||||
PsPrepareForApplicationProcessorInit(ULONG Id)
|
PsPrepareForApplicationProcessorInit(ULONG Id)
|
||||||
{
|
{
|
||||||
PETHREAD IdleThread;
|
PETHREAD IdleThread;
|
||||||
HANDLE IdleThreadHandle;
|
PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb;
|
||||||
PKPCR Pcr = (PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE);
|
|
||||||
|
|
||||||
PsInitializeThread(NULL,
|
PsInitializeThread(NULL,
|
||||||
&IdleThread,
|
&IdleThread,
|
||||||
&IdleThreadHandle,
|
|
||||||
THREAD_ALL_ACCESS,
|
|
||||||
NULL,
|
NULL,
|
||||||
FALSE);
|
FALSE);
|
||||||
IdleThread->Tcb.State = THREAD_STATE_RUNNING;
|
IdleThread->Tcb.State = THREAD_STATE_RUNNING;
|
||||||
|
@ -719,12 +716,11 @@ PsPrepareForApplicationProcessorInit(ULONG Id)
|
||||||
IdleThread->Tcb.UserAffinity = 1 << Id;
|
IdleThread->Tcb.UserAffinity = 1 << Id;
|
||||||
IdleThread->Tcb.Priority = LOW_PRIORITY;
|
IdleThread->Tcb.Priority = LOW_PRIORITY;
|
||||||
IdleThread->Tcb.BasePriority = LOW_PRIORITY;
|
IdleThread->Tcb.BasePriority = LOW_PRIORITY;
|
||||||
Pcr->PrcbData.IdleThread = &IdleThread->Tcb;
|
Prcb->IdleThread = &IdleThread->Tcb;
|
||||||
Pcr->PrcbData.CurrentThread = &IdleThread->Tcb;
|
Prcb->CurrentThread = &IdleThread->Tcb;
|
||||||
|
|
||||||
Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit;
|
Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit;
|
||||||
|
|
||||||
NtClose(IdleThreadHandle);
|
|
||||||
DPRINT("IdleThread for Processor %d has PID %d\n",
|
DPRINT("IdleThread for Processor %d has PID %d\n",
|
||||||
Id, IdleThread->Cid.UniqueThread);
|
Id, IdleThread->Cid.UniqueThread);
|
||||||
}
|
}
|
||||||
|
@ -738,7 +734,6 @@ PsInitThreadManagment(VOID)
|
||||||
HANDLE PiReaperThreadHandle;
|
HANDLE PiReaperThreadHandle;
|
||||||
PETHREAD FirstThread;
|
PETHREAD FirstThread;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
HANDLE FirstThreadHandle;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
for (i=0; i < MAXIMUM_PRIORITY; i++)
|
for (i=0; i < MAXIMUM_PRIORITY; i++)
|
||||||
|
@ -771,14 +766,12 @@ PsInitThreadManagment(VOID)
|
||||||
|
|
||||||
ObpCreateTypeObject(PsThreadType);
|
ObpCreateTypeObject(PsThreadType);
|
||||||
|
|
||||||
PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle,
|
PsInitializeThread(NULL, &FirstThread, NULL, TRUE);
|
||||||
THREAD_ALL_ACCESS,NULL, TRUE);
|
|
||||||
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
|
FirstThread->Tcb.State = THREAD_STATE_RUNNING;
|
||||||
FirstThread->Tcb.FreezeCount = 0;
|
FirstThread->Tcb.FreezeCount = 0;
|
||||||
FirstThread->Tcb.UserAffinity = (1 << 0); /* Set the affinity of the first thread to the boot processor */
|
FirstThread->Tcb.UserAffinity = (1 << 0); /* Set the affinity of the first thread to the boot processor */
|
||||||
FirstThread->Tcb.Affinity = (1 << 0);
|
FirstThread->Tcb.Affinity = (1 << 0);
|
||||||
KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread;
|
KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread;
|
||||||
NtClose(FirstThreadHandle);
|
|
||||||
|
|
||||||
DPRINT("FirstThread %x\n",FirstThread);
|
DPRINT("FirstThread %x\n",FirstThread);
|
||||||
|
|
||||||
|
@ -895,8 +888,8 @@ KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority)
|
||||||
{
|
{
|
||||||
for (i = 0; i < KeNumberProcessors; i++)
|
for (i = 0; i < KeNumberProcessors; i++)
|
||||||
{
|
{
|
||||||
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
||||||
if (Pcr->PrcbData.CurrentThread == Thread)
|
if (Pcr->Prcb->CurrentThread == Thread)
|
||||||
{
|
{
|
||||||
KeReleaseDispatcherDatabaseLockFromDpcLevel();
|
KeReleaseDispatcherDatabaseLockFromDpcLevel();
|
||||||
KiRequestReschedule(i);
|
KiRequestReschedule(i);
|
||||||
|
@ -959,7 +952,7 @@ KeSetAffinityThread(PKTHREAD Thread,
|
||||||
for (i = 0; i < KeNumberProcessors; i++)
|
for (i = 0; i < KeNumberProcessors; i++)
|
||||||
{
|
{
|
||||||
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
|
||||||
if (Pcr->PrcbData.CurrentThread == Thread)
|
if (Pcr->Prcb->CurrentThread == Thread)
|
||||||
{
|
{
|
||||||
if (!(Affinity & ProcessorMask))
|
if (!(Affinity & ProcessorMask))
|
||||||
{
|
{
|
||||||
|
@ -988,63 +981,95 @@ KeSetAffinityThread(PKTHREAD Thread,
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
NtOpenThread(OUT PHANDLE ThreadHandle,
|
NtOpenThread(OUT PHANDLE ThreadHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||||
IN PCLIENT_ID ClientId)
|
IN PCLIENT_ID ClientId OPTIONAL)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
|
CLIENT_ID SafeClientId;
|
||||||
|
HANDLE hThread;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
if((NULL != ThreadHandle)&&(NULL != ObjectAttributes))
|
PreviousMode = ExGetPreviousMode();
|
||||||
{
|
|
||||||
PETHREAD EThread = NULL;
|
|
||||||
|
|
||||||
if((ClientId)
|
if(PreviousMode != KernelMode)
|
||||||
&& (ClientId->UniqueThread))
|
{
|
||||||
{
|
_SEH_TRY
|
||||||
// It is an error to specify both
|
{
|
||||||
// ObjectAttributes.ObjectName
|
ProbeForWrite(ThreadHandle,
|
||||||
// and ClientId.
|
sizeof(HANDLE),
|
||||||
if((ObjectAttributes)
|
sizeof(ULONG));
|
||||||
&& (ObjectAttributes->ObjectName)
|
if(ClientId != NULL)
|
||||||
&& (0 < ObjectAttributes->ObjectName->Length))
|
{
|
||||||
{
|
ProbeForRead(ClientId,
|
||||||
return(STATUS_INVALID_PARAMETER_MIX);
|
sizeof(CLIENT_ID),
|
||||||
}
|
sizeof(ULONG));
|
||||||
// Parameters mix OK
|
SafeClientId = *ClientId;
|
||||||
Status = PsLookupThreadByThreadId(ClientId->UniqueThread,
|
ClientId = &SafeClientId;
|
||||||
& EThread);
|
}
|
||||||
}
|
}
|
||||||
else if((ObjectAttributes)
|
_SEH_HANDLE
|
||||||
&& (ObjectAttributes->ObjectName)
|
{
|
||||||
&& (0 < ObjectAttributes->ObjectName->Length))
|
Status = _SEH_GetExceptionCode();
|
||||||
{
|
}
|
||||||
// Three Ob attributes are forbidden
|
_SEH_END;
|
||||||
if(!(ObjectAttributes->Attributes &
|
|
||||||
(OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENIF)))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
|
return Status;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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
|
NTSTATUS STDCALL
|
||||||
|
@ -1074,22 +1099,26 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
|
||||||
OUT PEPROCESS *Process OPTIONAL,
|
OUT PEPROCESS *Process OPTIONAL,
|
||||||
OUT PETHREAD *Thread)
|
OUT PETHREAD *Thread)
|
||||||
{
|
{
|
||||||
PCID_OBJECT CidObject;
|
PHANDLE_TABLE_ENTRY CidEntry;
|
||||||
PETHREAD FoundThread;
|
PETHREAD FoundThread;
|
||||||
|
|
||||||
CidObject = PsLockCidHandle((HANDLE)Cid->UniqueThread, PsThreadType);
|
PAGED_CODE();
|
||||||
if(CidObject != NULL)
|
|
||||||
|
ASSERT(Thread);
|
||||||
|
ASSERT(Cid);
|
||||||
|
|
||||||
|
CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread);
|
||||||
|
if(CidEntry != NULL)
|
||||||
{
|
{
|
||||||
FoundThread = CidObject->Obj.Thread;
|
|
||||||
ObReferenceObject(FoundThread);
|
ObReferenceObject(FoundThread);
|
||||||
|
|
||||||
|
PsUnlockCidHandle(CidEntry);
|
||||||
|
|
||||||
if(Process != NULL)
|
if(Process != NULL)
|
||||||
{
|
{
|
||||||
*Process = FoundThread->ThreadsProcess;
|
*Process = FoundThread->ThreadsProcess;
|
||||||
ObReferenceObject(FoundThread->ThreadsProcess);
|
|
||||||
}
|
}
|
||||||
|
*Thread = FoundThread;
|
||||||
PsUnlockCidObject(CidObject);
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,15 +1133,21 @@ NTSTATUS STDCALL
|
||||||
PsLookupThreadByThreadId(IN HANDLE ThreadId,
|
PsLookupThreadByThreadId(IN HANDLE ThreadId,
|
||||||
OUT PETHREAD *Thread)
|
OUT PETHREAD *Thread)
|
||||||
{
|
{
|
||||||
PCID_OBJECT CidObject;
|
PHANDLE_TABLE_ENTRY CidEntry;
|
||||||
|
PETHREAD FoundThread;
|
||||||
CidObject = PsLockCidHandle(ThreadId, PsThreadType);
|
|
||||||
if(CidObject != NULL)
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(Thread);
|
||||||
|
|
||||||
|
CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread);
|
||||||
|
if(CidEntry != NULL)
|
||||||
{
|
{
|
||||||
*Thread = CidObject->Obj.Thread;
|
ObReferenceObject(FoundThread);
|
||||||
ObReferenceObject(*Thread);
|
|
||||||
|
PsUnlockCidHandle(CidEntry);
|
||||||
PsUnlockCidObject(CidObject);
|
|
||||||
|
*Thread = FoundThread;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#define HEADER_TO_BODY(ObjectHeader) \
|
#define USER_HEADER_TO_BODY(ObjectHeader) \
|
||||||
((PVOID)(((PUSER_OBJECT_HEADER)ObjectHeader) + 1))
|
((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))
|
((PUSER_OBJECT_HEADER)(((PUSER_OBJECT_HEADER)ObjectBody) - 1))
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
@ -125,7 +125,7 @@ ObmpCloseAllHandles(PUSER_HANDLE_TABLE HandleTable)
|
||||||
|
|
||||||
if (ObjectBody != NULL)
|
if (ObjectBody != NULL)
|
||||||
{
|
{
|
||||||
PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
|
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
|
||||||
ObjectHeader->HandleCount--;
|
ObjectHeader->HandleCount--;
|
||||||
|
@ -191,7 +191,7 @@ ObmpDeleteHandle(PUSER_HANDLE_TABLE HandleTable,
|
||||||
|
|
||||||
if (ObjectBody != NULL)
|
if (ObjectBody != NULL)
|
||||||
{
|
{
|
||||||
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
ObjectHeader->HandleCount--;
|
ObjectHeader->HandleCount--;
|
||||||
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
|
ObmReferenceObjectByPointer(ObjectBody, otUnknown);
|
||||||
Entry->ObjectBody = NULL;
|
Entry->ObjectBody = NULL;
|
||||||
|
@ -219,7 +219,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable,
|
||||||
if (Handle != NULL)
|
if (Handle != NULL)
|
||||||
{
|
{
|
||||||
Status = ObmCreateHandle(HandleTable,
|
Status = ObmCreateHandle(HandleTable,
|
||||||
HEADER_TO_BODY(ObjectHeader),
|
USER_HEADER_TO_BODY(ObjectHeader),
|
||||||
Handle);
|
Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable,
|
||||||
ULONG FASTCALL
|
ULONG FASTCALL
|
||||||
ObmGetReferenceCount(PVOID ObjectBody)
|
ObmGetReferenceCount(PVOID ObjectBody)
|
||||||
{
|
{
|
||||||
PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
return ObjectHeader->RefCount;
|
return ObjectHeader->RefCount;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ ObmGetReferenceCount(PVOID ObjectBody)
|
||||||
ULONG FASTCALL
|
ULONG FASTCALL
|
||||||
ObmGetHandleCount(PVOID ObjectBody)
|
ObmGetHandleCount(PVOID ObjectBody)
|
||||||
{
|
{
|
||||||
PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
return ObjectHeader->HandleCount;
|
return ObjectHeader->HandleCount;
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ ObmReferenceObject(PVOID ObjectBody)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
ObjectHeader->RefCount++;
|
ObjectHeader->RefCount++;
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ ObmDereferenceObject(PVOID ObjectBody)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
ObjectHeader->RefCount--;
|
ObjectHeader->RefCount--;
|
||||||
ObmpPerformRetentionChecks(ObjectHeader);
|
ObmpPerformRetentionChecks(ObjectHeader);
|
||||||
|
@ -303,7 +303,7 @@ ObmReferenceObjectByPointer(PVOID ObjectBody,
|
||||||
{
|
{
|
||||||
PUSER_OBJECT_HEADER ObjectHeader;
|
PUSER_OBJECT_HEADER ObjectHeader;
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
|
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
|
||||||
{
|
{
|
||||||
|
@ -331,7 +331,7 @@ ObmCreateObject(PUSER_HANDLE_TABLE HandleTable,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectBody = HEADER_TO_BODY(ObjectHeader);
|
ObjectBody = USER_HEADER_TO_BODY(ObjectHeader);
|
||||||
|
|
||||||
RtlZeroMemory(ObjectBody, ObjectSize);
|
RtlZeroMemory(ObjectBody, ObjectSize);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable,
|
||||||
|
|
||||||
if (ObjectBody != NULL)
|
if (ObjectBody != NULL)
|
||||||
{
|
{
|
||||||
BODY_TO_HEADER(ObjectBody)->HandleCount++;
|
USER_BODY_TO_HEADER(ObjectBody)->HandleCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObmpLockHandleTable(HandleTable);
|
ObmpLockHandleTable(HandleTable);
|
||||||
|
@ -456,7 +456,7 @@ ObmReferenceObjectByHandle(PUSER_HANDLE_TABLE HandleTable,
|
||||||
|
|
||||||
ObmpUnlockHandleTable(HandleTable);
|
ObmpUnlockHandleTable(HandleTable);
|
||||||
|
|
||||||
ObjectHeader = BODY_TO_HEADER(ObjectBody);
|
ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
|
||||||
|
|
||||||
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
|
if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue