From d288e05d38673d8020ff94c88010c1be345b097c Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sun, 13 Mar 2005 14:21:47 +0000 Subject: [PATCH] - 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 --- reactos/config | 8 +- reactos/include/ddk/kefuncs.h | 9 + reactos/include/ntos/obtypes.h | 34 +- reactos/ntoskrnl/Makefile | 1 + reactos/ntoskrnl/ex/handle.c | 949 +++++++++++++++++++++++++ reactos/ntoskrnl/ex/init.c | 1 + reactos/ntoskrnl/ex/sysinfo.c | 6 +- reactos/ntoskrnl/ex/work.c | 75 +- reactos/ntoskrnl/include/internal/ex.h | 59 ++ reactos/ntoskrnl/include/internal/ob.h | 17 +- reactos/ntoskrnl/include/internal/ps.h | 24 +- reactos/ntoskrnl/io/iomgr.c | 2 +- reactos/ntoskrnl/io/pnpmgr.c | 11 +- reactos/ntoskrnl/lpc/close.c | 6 +- reactos/ntoskrnl/ob/handle.c | 944 ++++++++++-------------- reactos/ntoskrnl/ob/object.c | 20 +- reactos/ntoskrnl/ps/cid.c | 187 +++-- reactos/ntoskrnl/ps/create.c | 145 ++-- reactos/ntoskrnl/ps/idle.c | 53 +- reactos/ntoskrnl/ps/kill.c | 16 +- reactos/ntoskrnl/ps/process.c | 47 +- reactos/ntoskrnl/ps/psmgr.c | 12 + reactos/ntoskrnl/ps/thread.c | 207 +++--- reactos/subsys/win32k/misc/object.c | 26 +- 24 files changed, 1880 insertions(+), 979 deletions(-) create mode 100644 reactos/ntoskrnl/ex/handle.c diff --git a/reactos/config b/reactos/config index 34aa938c0b5..e5de9d37f8e 100644 --- a/reactos/config +++ b/reactos/config @@ -15,22 +15,22 @@ ARCH := i386 # be optimized for. # -OARCH := i486 +OARCH := i586 # # Whether to compile in the kernel debugger # -KDBG := 0 +KDBG := 1 # # Whether to compile for debugging # -DBG := 0 +DBG := 1 # # Whether to compile with optimizations # -OPTIMIZED := 0 +OPTIMIZED := 1 # # Whether to compile a multiprocessor or single processor version diff --git a/reactos/include/ddk/kefuncs.h b/reactos/include/ddk/kefuncs.h index 115851a2885..2559e460276 100644 --- a/reactos/include/ddk/kefuncs.h +++ b/reactos/include/ddk/kefuncs.h @@ -42,6 +42,15 @@ VOID STDCALL KeAcquireSpinLock (PKSPIN_LOCK SpinLock, #ifndef __USE_W32API +static __inline +VOID +KeMemoryBarrier( + VOID) +{ + volatile LONG Barrier; + __asm__ __volatile__ ("xchg %%eax, %0" : : "m" (Barrier) : "%eax"); +} + VOID STDCALL KeAcquireSpinLockAtDpcLevel (IN PKSPIN_LOCK SpinLock); #define KefAcquireSpinLockAtDpcLevel KeAcquireSpinLockAtDpcLevel diff --git a/reactos/include/ntos/obtypes.h b/reactos/include/ntos/obtypes.h index 9094b0688e6..86577d074ad 100755 --- a/reactos/include/ntos/obtypes.h +++ b/reactos/include/ntos/obtypes.h @@ -87,18 +87,42 @@ typedef struct _OBJECT_ATTRIBUTES PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; +typedef struct _HANDLE_TABLE_ENTRY_INFO { + ULONG AuditMask; +} HANDLE_TABLE_ENTRY_INFO, *PHANDLE_TABLE_ENTRY_INFO; + +typedef struct _HANDLE_TABLE_ENTRY { + union { + PVOID Object; + ULONG_PTR ObAttributes; + PHANDLE_TABLE_ENTRY_INFO InfoTable; + ULONG_PTR Value; + } u1; + union { + ULONG GrantedAccess; + USHORT GrantedAccessIndex; + LONG NextFreeTableEntry; + } u2; +} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; + #endif /* __USE_W32API */ typedef struct _HANDLE_TABLE { - LIST_ENTRY ListHead; - KSPIN_LOCK ListLock; -} HANDLE_TABLE; + ULONG Flags; + LONG HandleCount; + PHANDLE_TABLE_ENTRY **Table; + PEPROCESS QuotaProcess; + HANDLE UniqueProcessId; + LONG FirstFreeTableEntry; + LONG NextIndexNeedingPool; + ERESOURCE HandleTableLock; + LIST_ENTRY HandleTableList; + KEVENT HandleContentionEvent; +} HANDLE_TABLE, *PHANDLE_TABLE; #ifndef __USE_W32API -typedef struct _HANDLE_TABLE *PHANDLE_TABLE; - /* * FIXME: These will eventually become centerfold in the compliant Ob Manager * For now, they are only here so Device Map is properly defined before the header diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index d908dfdca40..18b781efbad 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -239,6 +239,7 @@ OBJECTS_EX = \ ex/event.o \ ex/evtpair.o \ ex/fmutex.o \ + ex/handle.o \ ex/hashtab.o \ ex/init.o \ ex/interlck.o \ diff --git a/reactos/ntoskrnl/ex/handle.c b/reactos/ntoskrnl/ex/handle.c new file mode 100644 index 00000000000..a0c5c79240e --- /dev/null +++ b/reactos/ntoskrnl/ex/handle.c @@ -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 + * + * TODO: + * + * - the last entry of a subhandle list should be reserved for auditing + * + * ExSweepHandleTable (???) + * ExReferenceHandleDebugInfo + * ExSnapShotHandleTables + * ExpMoveFreeHandles (???) + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +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 */ diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index f422db98257..bb094d85acb 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -662,6 +662,7 @@ ExInit3 (VOID) ExpInitializeMutantImplementation(); ExpInitializeSemaphoreImplementation(); ExpInitializeTimerImplementation(); + ExpInitializeHandleTables(); LpcpInitSystem(); ExpInitializeProfileImplementation(); ExpWin32kInit(); diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index f76e9695ae2..084744df023 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -617,7 +617,7 @@ QSI_DEF(SystemProcessInformation) SpiCur->BasePriority = pr->Pcb.BasePriority; SpiCur->ProcessId = pr->UniqueProcessId; SpiCur->InheritedFromProcessId = pr->InheritedFromUniqueProcessId; - SpiCur->HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable); + SpiCur->HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable); SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize; SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart; SpiCur->VmCounters.PageFaultCount = pr->LastFaultCount; @@ -849,7 +849,7 @@ QSI_DEF(SystemHandleInformation) do { - hCount = hCount + ObpGetHandleCountByHandleTable(&pr->HandleTable); + hCount = hCount + ObpGetHandleCountByHandleTable(pr->ObjectTable); pr = PsGetNextProcess(pr); if ((pr == syspr) || (pr == NULL)) @@ -885,7 +885,7 @@ QSI_DEF(SystemHandleInformation) { int Count = 0, HandleCount = 0; - HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable); + HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable); for (Count = 0; HandleCount > 0 ; HandleCount--) { diff --git a/reactos/ntoskrnl/ex/work.c b/reactos/ntoskrnl/ex/work.c index 8d7bac152fa..ff1f747785c 100644 --- a/reactos/ntoskrnl/ex/work.c +++ b/reactos/ntoskrnl/ex/work.c @@ -85,32 +85,55 @@ ExWorkerThreadEntryPoint(IN PVOID context) static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue, KPRIORITY Priority) { - ULONG i; - PETHREAD Thread; - HANDLE hThread; - - - for (i=0; iTcb, - Priority); - ObDereferenceObject(Thread); - ZwClose(hThread); - } + ULONG i; + PETHREAD Thread; + HANDLE hThread; + NTSTATUS Status; + + PAGED_CODE(); + + /* Loop through how many threads we need to create */ + for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) { + + /* Create the System Thread */ + Status = PsCreateSystemThread(&hThread, + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + ExWorkerThreadEntryPoint, + (PVOID)WorkQueue); + if(NT_SUCCESS(Status)) + { + /* Get the Thread */ + Status = ObReferenceObjectByHandle(hThread, + THREAD_SET_INFORMATION, + PsThreadType, + KernelMode, + (PVOID*)&Thread, + NULL); + + if(NT_SUCCESS(Status)) + { + /* Set the Priority */ + KeSetPriorityThread(&Thread->Tcb, Priority); + + /* Dereference and close handle */ + ObDereferenceObject(Thread); + ZwClose(hThread); + } + else + { + DPRINT1("Unable to reference worker thread handle 0x%x, Status: 0x%x!\n", hThread, Status); + KEBUGCHECK(0); + } + } + else + { + DPRINT1("Unable to create worker thread, Status: 0x%x!\n", Status); + KEBUGCHECK(0); + } + } } VOID INIT_FUNCTION diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index 8ae57b1528a..9aa28fdecbf 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -109,6 +109,65 @@ VOID STDCALL ExpInitializeExecutive(VOID); +/* HANDLE TABLE FUNCTIONS ***************************************************/ + +#define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1)) +#define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0) +#define EX_HANDLE_ENTRY_INHERITABLE (1 << 1) +#define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2) + +#define EX_HANDLE_TABLE_CLOSING 0x1 + +#define EX_INVALID_HANDLE (~0) + +#define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED | \ + EX_HANDLE_ENTRY_PROTECTFROMCLOSE | \ + EX_HANDLE_ENTRY_INHERITABLE | \ + EX_HANDLE_ENTRY_AUDITONCLOSE) + +typedef VOID (STDCALL PEX_DESTROY_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PVOID Object, ULONG GrantedAccess, PVOID Context); +typedef BOOLEAN (STDCALL PEX_DUPLICATE_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry, PVOID Context); +typedef BOOLEAN (STDCALL PEX_CHANGE_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry, PVOID Context); + +VOID +ExpInitializeHandleTables(VOID); +PHANDLE_TABLE +ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL); +VOID +ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable, + IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback OPTIONAL, + IN PVOID Context OPTIONAL); +PHANDLE_TABLE +ExDupHandleTable(IN PEPROCESS QuotaProcess OPTIONAL, + IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback OPTIONAL, + IN PVOID Context OPTIONAL, + IN PHANDLE_TABLE SourceHandleTable); +BOOLEAN +ExLockHandleTableEntry(IN PHANDLE_TABLE HandleTable, + IN PHANDLE_TABLE_ENTRY Entry); +VOID +ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, + IN PHANDLE_TABLE_ENTRY Entry); +LONG +ExCreateHandle(IN PHANDLE_TABLE HandleTable, + IN PHANDLE_TABLE_ENTRY Entry); +BOOLEAN +ExDestroyHandle(IN PHANDLE_TABLE HandleTable, + IN LONG Handle); +VOID +ExDestroyHandleByEntry(IN PHANDLE_TABLE HandleTable, + IN PHANDLE_TABLE_ENTRY Entry, + IN LONG Handle); +PHANDLE_TABLE_ENTRY +ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable, + IN LONG Handle); + +BOOLEAN +ExChangeHandle(IN PHANDLE_TABLE HandleTable, + IN LONG Handle, + IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback, + IN PVOID Context); + /* OTHER FUNCTIONS **********************************************************/ LONGLONG diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index b477878972e..11f4f9f05ca 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -228,17 +228,22 @@ enum OBJTYP_MAX, }; +#define HEADER_TO_BODY(objhdr) \ + (PVOID)((ULONG_PTR)objhdr + sizeof(OBJECT_HEADER) - sizeof(COMMON_BODY_HEADER)) + +#define BODY_TO_HEADER(objbdy) \ + CONTAINING_RECORD(&(((PCOMMON_BODY_HEADER)objbdy)->Type), OBJECT_HEADER, Type) #define OBJECT_ALLOC_SIZE(ObjectSize) ((ObjectSize)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)) +#define HANDLE_TO_EX_HANDLE(handle) \ + (LONG)(((LONG)(handle) >> 2) - 1) +#define EX_HANDLE_TO_HANDLE(exhandle) \ + (HANDLE)(((exhandle) + 1) << 2) extern PDIRECTORY_OBJECT NameSpaceRoot; extern POBJECT_TYPE ObSymbolicLinkType; - -POBJECT_HEADER BODY_TO_HEADER(PVOID body); -PVOID HEADER_TO_BODY(POBJECT_HEADER obj); - VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, POBJECT_HEADER Header, PWSTR Name); @@ -260,13 +265,11 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, PVOID* ReturnedObject, PUNICODE_STRING RemainingPath, POBJECT_TYPE ObjectType); -VOID ObCloseAllHandles(struct _EPROCESS* Process); VOID ObDeleteHandleTable(struct _EPROCESS* Process); NTSTATUS ObDeleteHandle(PEPROCESS Process, - HANDLE Handle, - PVOID *ObjectBody); + HANDLE Handle); NTSTATUS ObpQueryHandleAttributes(HANDLE Handle, diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 02378c7e831..a4d8a2f79fb 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -345,7 +345,7 @@ struct _EPROCESS LIST_ENTRY SessionProcessLinks; struct _EPORT *DebugPort; struct _EPORT *ExceptionPort; - HANDLE_TABLE HandleTable; + PHANDLE_TABLE ObjectTable; PVOID Token; FAST_MUTEX WorkingSetLock; ULONG WorkingSetPage; @@ -454,8 +454,6 @@ VOID PsQueueThreadReap(PETHREAD Thread); NTSTATUS PsInitializeThread(PEPROCESS Process, PETHREAD* ThreadPtr, - PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, BOOLEAN First); @@ -641,26 +639,12 @@ typedef struct _EJOB VOID INIT_FUNCTION PsInitJobManagment(VOID); -/* CID */ - -typedef struct _CID_OBJECT -{ - LONG ref; - HANDLE Handle; - LIST_ENTRY Entry; - FAST_MUTEX Lock; - union - { - struct _EPROCESS *Process; - struct _ETHREAD *Thread; - PVOID Object; - } Obj; -} CID_OBJECT, *PCID_OBJECT; +/* CLIENT ID */ NTSTATUS PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle); NTSTATUS PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType); -PCID_OBJECT PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType); -VOID PsUnlockCidObject(PCID_OBJECT CidObject); +PHANDLE_TABLE_ENTRY PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object); +VOID PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry); NTSTATUS PsLockProcess(PEPROCESS Process, BOOL Timeout); VOID PsUnlockProcess(PEPROCESS Process); diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 64ae143bb53..336aefef91e 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -52,7 +52,7 @@ IopCloseFile(PVOID ObjectBody, DPRINT("IopCloseFile()\n"); - if (HandleCount > 0 || FileObject->DeviceObject == NULL) + if (HandleCount > 1 || FileObject->DeviceObject == NULL) { return; } diff --git a/reactos/ntoskrnl/io/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr.c index 6709dbf328a..a1b27b48603 100644 --- a/reactos/ntoskrnl/io/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr.c @@ -1740,10 +1740,13 @@ IopInvalidateDeviceRelations( &IoStatusBlock, 0, 0); - - BootDrivers = NT_SUCCESS(Status) ? FALSE : TRUE; - - ZwClose(Handle); + if(NT_SUCCESS(Status)) + { + BootDrivers = FALSE; + ZwClose(Handle); + } + else + BootDrivers = TRUE; /* * Initialize services for discovered children. Only boot drivers will diff --git a/reactos/ntoskrnl/lpc/close.c b/reactos/ntoskrnl/lpc/close.c index 4f61c713263..c73a8dfe367 100644 --- a/reactos/ntoskrnl/lpc/close.c +++ b/reactos/ntoskrnl/lpc/close.c @@ -41,8 +41,7 @@ NiClosePort (PVOID ObjectBody, ULONG HandleCount) * If the client has just closed its handle then tell the server what * happened and disconnect this port. */ - if (HandleCount == 0 && Port->State == EPORT_CONNECTED_CLIENT && - ObGetObjectPointerCount(Port) == 2) + if (HandleCount == 1 && Port->State == EPORT_CONNECTED_CLIENT) { DPRINT("Informing server\n"); Message.MessageSize = sizeof(LPC_MESSAGE); @@ -64,8 +63,7 @@ NiClosePort (PVOID ObjectBody, ULONG HandleCount) * If the server has closed all of its handles then disconnect the port, * don't actually notify the client until it attempts an operation. */ - if (HandleCount == 0 && Port->State == EPORT_CONNECTED_SERVER && - ObGetObjectPointerCount(Port) == 1) + if (HandleCount == 1 && Port->State == EPORT_CONNECTED_SERVER) { DPRINT("Cleaning up server\n"); Port->OtherPort->OtherPort = NULL; diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c index dcc90efd882..1eafa22bd85 100644 --- a/reactos/ntoskrnl/ob/handle.c +++ b/reactos/ntoskrnl/ob/handle.c @@ -33,89 +33,34 @@ #define NDEBUG #include -/* TYPES *******************************************************************/ - -/* - * PURPOSE: Defines a handle - */ -typedef struct _HANDLE_ENTRY -{ - PVOID ObjectBody; - ACCESS_MASK GrantedAccess; -} HANDLE_ENTRY, *PHANDLE_ENTRY; - -#define HANDLE_BLOCK_ENTRIES \ - (((4 * PAGE_SIZE) - \ - (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(HANDLE_ENTRY)) - -#define OB_HANDLE_FLAG_MASK 0x00000007 -#define OB_HANDLE_FLAG_AUDIT 0x00000004 -#define OB_HANDLE_FLAG_PROTECT 0x00000002 -#define OB_HANDLE_FLAG_INHERIT 0x00000001 - -#define OB_POINTER_TO_ENTRY(Pointer) \ - (PVOID)((ULONG_PTR)(Pointer) & ~OB_HANDLE_FLAG_MASK) - -#define OB_ENTRY_TO_POINTER(Entry) \ - (PVOID)((ULONG_PTR)(Entry) & ~OB_HANDLE_FLAG_MASK) - -/* - * PURPOSE: Defines a 4 page's worth of handles - */ -typedef struct -{ - LIST_ENTRY entry; - ULONG allocation_hint; - ULONG allocation_count; - HANDLE_ENTRY handles[HANDLE_BLOCK_ENTRIES]; -} HANDLE_BLOCK, *PHANDLE_BLOCK; - - -/* GLOBALS *******************************************************************/ - -#define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L') +#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \ + ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \ + EX_HANDLE_ENTRY_AUDITONCLOSE))) +#define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \ + ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \ + EX_HANDLE_ENTRY_AUDITONCLOSE))) /* FUNCTIONS ***************************************************************/ -/* - * FUNCTION: Get the data structure for a handle - * ARGUMENTS: - * Process = Process to get the handle for - * h = Handle - * ARGUMENTS: A pointer to the information about the handle on success, - * NULL on failure - */ -static PHANDLE_ENTRY -ObpGetObjectByHandle(PHANDLE_TABLE HandleTable, - HANDLE h, - HANDLE_BLOCK **Block) +VOID +ObpDecrementHandleCount(PVOID ObjectBody) { - PLIST_ENTRY current; - unsigned int handle = (((unsigned int)h) >> 2) - 1; - unsigned int count = handle / HANDLE_BLOCK_ENTRIES; - HANDLE_BLOCK* blk = NULL; - unsigned int i; - - DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable,h); - - current = HandleTable->ListHead.Flink; - DPRINT("current %x\n",current); - - for (i = 0; i < count; i++) - { - current = current->Flink; - if (current == (&(HandleTable->ListHead))) - { - return(NULL); - } - } - - blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry); - if (Block) - *Block = blk; - DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES])); - return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES])); + POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount); + + if ((ObjectHeader->ObjectType != NULL) && + (ObjectHeader->ObjectType->Close != NULL)) + { + /* the handle count should be decremented but we pass the previous value + to the callback */ + ObjectHeader->ObjectType->Close(ObjectBody, NewHandleCount + 1); + } + + if(NewHandleCount == 0) + { + ObDereferenceObject(ObjectBody); + } } @@ -124,29 +69,32 @@ ObpQueryHandleAttributes(HANDLE Handle, POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo) { PEPROCESS Process; - KIRQL oldIrql; - PHANDLE_ENTRY HandleEntry; + PHANDLE_TABLE_ENTRY HandleTableEntry; + LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); + + PAGED_CODE(); DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle); + KeEnterCriticalRegion(); + Process = PsGetCurrentProcess(); - KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql); - HandleEntry = ObpGetObjectByHandle(&Process->HandleTable, - Handle, - NULL); - if (HandleEntry == NULL) + HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable, + ExHandle); + if (HandleTableEntry == NULL) { - KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql); + KeLeaveCriticalRegion(); return STATUS_INVALID_HANDLE; } - HandleInfo->Inherit = - ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_INHERIT); - HandleInfo->ProtectFromClose = - ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT); + HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0; + HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0; - KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql); + ExUnlockHandleTableEntry(Process->ObjectTable, + HandleTableEntry); + + KeLeaveCriticalRegion(); return STATUS_SUCCESS; } @@ -156,37 +104,42 @@ NTSTATUS ObpSetHandleAttributes(HANDLE Handle, POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo) { - PHANDLE_ENTRY HandleEntry; PEPROCESS Process; - KIRQL oldIrql; + PHANDLE_TABLE_ENTRY HandleTableEntry; + LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); + + PAGED_CODE(); - DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle); + DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle); Process = PsGetCurrentProcess(); + + KeEnterCriticalRegion(); - KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql); - HandleEntry = ObpGetObjectByHandle(&Process->HandleTable, - Handle, - NULL); - if (HandleEntry == NULL) + HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable, + ExHandle); + if (HandleTableEntry == NULL) { - KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql); + KeLeaveCriticalRegion(); return STATUS_INVALID_HANDLE; } if (HandleInfo->Inherit) - HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_INHERIT); + HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE; else - HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody & ~OB_HANDLE_FLAG_INHERIT); + HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE; if (HandleInfo->ProtectFromClose) - HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_PROTECT); + HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE; else - HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody & ~OB_HANDLE_FLAG_PROTECT); + HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE; /* FIXME: Do we need to set anything in the object header??? */ - KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql); + ExUnlockHandleTableEntry(Process->ObjectTable, + HandleTableEntry); + + KeLeaveCriticalRegion(); return STATUS_SUCCESS; } @@ -201,46 +154,82 @@ ObDuplicateObject(PEPROCESS SourceProcess, BOOLEAN InheritHandle, ULONG Options) { - KIRQL oldIrql; - PHANDLE_ENTRY SourceHandleEntry; + PHANDLE_TABLE_ENTRY SourceHandleEntry; + HANDLE_TABLE_ENTRY NewHandleEntry; PVOID ObjectBody; - - KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql); - SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable, - SourceHandle, - NULL); + POBJECT_HEADER ObjectHeader; + LONG ExTargetHandle; + LONG ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle); + + PAGED_CODE(); + + KeEnterCriticalRegion(); + + SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable, + ExSourceHandle); if (SourceHandleEntry == NULL) { - KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); return STATUS_INVALID_HANDLE; } - ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody); - ObReferenceObjectByPointer(ObjectBody, - 0, - NULL, - UserMode); + ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry); + ObjectBody = HEADER_TO_BODY(ObjectHeader); + + NewHandleEntry.u1.Object = SourceHandleEntry->u1.Object; + if(InheritHandle) + NewHandleEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE; + else + NewHandleEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE; + NewHandleEntry.u2.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ? + SourceHandleEntry->u2.GrantedAccess : + DesiredAccess); - if (Options & DUPLICATE_SAME_ACCESS) - { - DesiredAccess = SourceHandleEntry->GrantedAccess; - } - - KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); - ObCreateHandle(TargetProcess, - ObjectBody, - DesiredAccess, - InheritHandle, - TargetHandle); + /* reference the object so it doesn't get deleted after releasing the lock + and before creating a new handle for it */ + ObReferenceObject(ObjectBody); - if (Options & DUPLICATE_CLOSE_SOURCE) + /* increment the handle count of the object, it should always be >= 2 because + we're holding a handle lock to this object! if the new handle count was + 1 here, we're in big trouble... it would've been safe to increment and + check the handle count without using interlocked functions because the + entry is locked, which means the handle count can't change. */ + InterlockedIncrement(&ObjectHeader->HandleCount); + ASSERT(ObjectHeader->HandleCount >= 2); + + ExUnlockHandleTableEntry(SourceProcess->ObjectTable, + SourceHandleEntry); + + KeLeaveCriticalRegion(); + + /* attempt to create the new handle */ + ExTargetHandle = ExCreateHandle(TargetProcess->ObjectTable, + &NewHandleEntry); + if (ExTargetHandle != EX_INVALID_HANDLE) + { + if (Options & DUPLICATE_CLOSE_SOURCE) { - ZwClose(SourceHandle); + ObDeleteHandle(SourceProcess, + SourceHandle); } + + ObDereferenceObject(ObjectBody); - ObDereferenceObject(ObjectBody); - - return STATUS_SUCCESS; + *TargetHandle = EX_HANDLE_TO_HANDLE(ExTargetHandle); + + return STATUS_SUCCESS; + } + else + { + /* decrement the handle count we previously incremented, but don't call the + closing procedure because we're not closing a handle! */ + if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0) + { + ObDereferenceObject(ObjectBody); + } + + ObDereferenceObject(ObjectBody); + return STATUS_UNSUCCESSFUL; + } } /* @@ -250,7 +239,7 @@ NTSTATUS STDCALL NtDuplicateObject (IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle, - OUT PHANDLE UnsafeTargetHandle, + OUT PHANDLE TargetHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN InheritHandle, ULONG Options) @@ -281,18 +270,38 @@ NtDuplicateObject (IN HANDLE SourceProcessHandle, { PEPROCESS SourceProcess; PEPROCESS TargetProcess; - PHANDLE_ENTRY SourceHandleEntry; - KIRQL oldIrql; - PVOID ObjectBody; - HANDLE TargetHandle; - NTSTATUS Status; + HANDLE hTarget; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(TargetHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + Status = ObReferenceObjectByHandle(SourceProcessHandle, PROCESS_DUP_HANDLE, NULL, - UserMode, + PreviousMode, (PVOID*)&SourceProcess, NULL); if (!NT_SUCCESS(Status)) @@ -303,7 +312,7 @@ NtDuplicateObject (IN HANDLE SourceProcessHandle, Status = ObReferenceObjectByHandle(TargetProcessHandle, PROCESS_DUP_HANDLE, NULL, - UserMode, + PreviousMode, (PVOID*)&TargetProcess, NULL); if (!NT_SUCCESS(Status)) @@ -315,134 +324,76 @@ NtDuplicateObject (IN HANDLE SourceProcessHandle, /* Check for magic handle first */ if (SourceHandle == NtCurrentThread()) { - ObReferenceObjectByHandle(SourceHandle, - PROCESS_DUP_HANDLE, - NULL, - UserMode, - &ObjectBody, - NULL); + PVOID ObjectBody; + + Status = ObReferenceObjectByHandle(SourceHandle, + PROCESS_DUP_HANDLE, + NULL, + PreviousMode, + &ObjectBody, + NULL); + if(NT_SUCCESS(Status)) + { + Status = ObCreateHandle(TargetProcess, + ObjectBody, + THREAD_ALL_ACCESS, + InheritHandle, + &hTarget); - ObCreateHandle(TargetProcess, - ObjectBody, - THREAD_ALL_ACCESS, - InheritHandle, - &TargetHandle); + ObDereferenceObject(ObjectBody); + + if (Options & DUPLICATE_CLOSE_SOURCE) + { + ObDeleteHandle(SourceProcess, + SourceHandle); + } + } } else { - KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql); - SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable, - SourceHandle, - NULL); - if (SourceHandleEntry == NULL) - { - KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); - ObDereferenceObject(SourceProcess); - ObDereferenceObject(TargetProcess); - return(STATUS_INVALID_HANDLE); - } - ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody); - ObReferenceObjectByPointer(ObjectBody, - 0, - NULL, - UserMode); - - if (Options & DUPLICATE_SAME_ACCESS) - { - DesiredAccess = SourceHandleEntry->GrantedAccess; - } - - KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); - - ObCreateHandle(TargetProcess, - ObjectBody, - DesiredAccess, - InheritHandle, - &TargetHandle); + Status = ObDuplicateObject(SourceProcess, + TargetProcess, + SourceHandle, + &hTarget, + DesiredAccess, + InheritHandle, + Options); } - - if (Options & DUPLICATE_CLOSE_SOURCE) - { - ZwClose(SourceHandle); - } - + ObDereferenceObject(TargetProcess); ObDereferenceObject(SourceProcess); - ObDereferenceObject(ObjectBody); - - Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - return(STATUS_SUCCESS); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *TargetHandle = hTarget; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; } -VOID ObCloseAllHandles(PEPROCESS Process) +static VOID STDCALL +DeleteHandleCallback(PHANDLE_TABLE HandleTable, + PVOID Object, + ULONG GrantedAccess, + PVOID Context) { - KIRQL oldIrql; - PHANDLE_TABLE HandleTable; - PLIST_ENTRY current_entry; - PHANDLE_BLOCK current; - ULONG i; - PVOID ObjectBody; - - DPRINT("ObCloseAllHandles(Process %x)\n", Process); - - HandleTable = &Process->HandleTable; - - KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql); - - current_entry = HandleTable->ListHead.Flink; - - while (current_entry != &HandleTable->ListHead) - { - current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry); - - for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) - { - ObjectBody = OB_ENTRY_TO_POINTER(current->handles[i].ObjectBody); - - if (ObjectBody != NULL) - { - POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody); - -#if 0 - if (Header->ObjectType == PsProcessType || - Header->ObjectType == PsThreadType) - { - DPRINT("Deleting handle to %x\n", ObjectBody); - } -#endif - - ObReferenceObjectByPointer(ObjectBody, - 0, - NULL, - UserMode); - InterlockedDecrement(&Header->HandleCount); - current->handles[i].ObjectBody = NULL; - - KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); - if ((Header->ObjectType != NULL) && - (Header->ObjectType->Close != NULL)) - { - Header->ObjectType->Close(ObjectBody, - Header->HandleCount); - } - - ObDereferenceObject(ObjectBody); - KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql); - current_entry = &HandleTable->ListHead; - break; - } - } - - current_entry = current_entry->Flink; - } - KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); - DPRINT("ObCloseAllHandles() finished\n"); - DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType); + POBJECT_HEADER ObjectHeader; + PVOID ObjectBody; + + PAGED_CODE(); + + ObjectHeader = EX_OBJ_TO_HDR(Object); + ObjectBody = HEADER_TO_BODY(ObjectHeader); + + ObpDecrementHandleCount(ObjectBody); } VOID ObDeleteHandleTable(PEPROCESS Process) @@ -450,26 +401,38 @@ VOID ObDeleteHandleTable(PEPROCESS Process) * FUNCTION: Deletes the handle table associated with a process */ { - PLIST_ENTRY current = NULL; - PHANDLE_TABLE HandleTable = NULL; - - ObCloseAllHandles(Process); - - HandleTable = &Process->HandleTable; - current = RemoveHeadList(&HandleTable->ListHead); - - while (current != &HandleTable->ListHead) - { - HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current, - HANDLE_BLOCK, - entry); - DPRINT("Freeing %x\n", HandleBlock); - ExFreePool(HandleBlock); - - current = RemoveHeadList(&HandleTable->ListHead); - } + PAGED_CODE(); + + ExDestroyHandleTable(Process->ObjectTable, + DeleteHandleCallback, + Process); } +static BOOLEAN STDCALL +DuplicateHandleCallback(PHANDLE_TABLE HandleTable, + PHANDLE_TABLE_ENTRY HandleTableEntry, + PVOID Context) +{ + POBJECT_HEADER ObjectHeader; + BOOLEAN Ret = FALSE; + + PAGED_CODE(); + + Ret = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0; + if(Ret) + { + ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry); + if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1) + { + ObReferenceObjectByPointer(HEADER_TO_BODY(ObjectHeader), + 0, + NULL, + UserMode); + } + } + + return Ret; +} VOID ObCreateHandleTable(PEPROCESS Parent, BOOLEAN Inherit, @@ -482,133 +445,69 @@ VOID ObCreateHandleTable(PEPROCESS Parent, * Process = Process whose handle table is to be created */ { - PHANDLE_TABLE ParentHandleTable, HandleTable; - KIRQL oldIrql; - PLIST_ENTRY parent_current; - ULONG i; - PHANDLE_BLOCK current_block, new_block; - + PAGED_CODE(); + DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n", Parent,Inherit,Process); - - InitializeListHead(&(Process->HandleTable.ListHead)); - KeInitializeSpinLock(&(Process->HandleTable.ListLock)); - - if (Parent != NULL) - { - ParentHandleTable = &Parent->HandleTable; - HandleTable = &Process->HandleTable; - - KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql); - KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock); - - parent_current = ParentHandleTable->ListHead.Flink; - - while (parent_current != &ParentHandleTable->ListHead) - { - current_block = CONTAINING_RECORD(parent_current, - HANDLE_BLOCK, - entry); - new_block = ExAllocatePoolWithTag(NonPagedPool, - sizeof(HANDLE_BLOCK), - TAG_HANDLE_TABLE); - if (new_block == NULL) - { - break; - } - RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK)); - - for (i=0; ihandles[i].ObjectBody) - { - if ((ULONG_PTR)current_block->handles[i].ObjectBody & OB_HANDLE_FLAG_INHERIT) - { - new_block->handles[i].ObjectBody = - current_block->handles[i].ObjectBody; - new_block->handles[i].GrantedAccess = - current_block->handles[i].GrantedAccess; - InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block->handles[i].ObjectBody))->HandleCount)); - } - } - } - InsertTailList(&Process->HandleTable.ListHead, &new_block->entry); - parent_current = parent_current->Flink; - } - KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock); - KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql); - } + if(Parent != NULL) + { + Process->ObjectTable = ExDupHandleTable(Process, + DuplicateHandleCallback, + NULL, + Parent->ObjectTable); + } + else + { + Process->ObjectTable = ExCreateHandleTable(Process); + } } NTSTATUS ObDeleteHandle(PEPROCESS Process, - HANDLE Handle, - PVOID *ObjectBody) + HANDLE Handle) { - PHANDLE_ENTRY HandleEntry; + PHANDLE_TABLE_ENTRY HandleEntry; PVOID Body; - KIRQL oldIrql; - PHANDLE_TABLE HandleTable; - POBJECT_HEADER Header; - HANDLE_BLOCK *Block; + POBJECT_HEADER ObjectHeader; + LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); PAGED_CODE(); DPRINT("ObDeleteHandle(Handle %x)\n",Handle); - - HandleTable = &Process->HandleTable; - - KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql); - - HandleEntry = ObpGetObjectByHandle(HandleTable, Handle, &Block); - if (HandleEntry == NULL) + + KeEnterCriticalRegion(); + + HandleEntry = ExMapHandleToPointer(Process->ObjectTable, + ExHandle); + if(HandleEntry != NULL) + { + if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) { - KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); - *ObjectBody = NULL; - return STATUS_INVALID_HANDLE; + ExUnlockHandleTableEntry(Process->ObjectTable, + HandleEntry); + + KeLeaveCriticalRegion(); + + return STATUS_HANDLE_NOT_CLOSABLE; } - if ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT) - { - KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); - *ObjectBody = NULL; - return STATUS_HANDLE_NOT_CLOSABLE; - } + ObjectHeader = EX_HTE_TO_HDR(HandleEntry); + Body = HEADER_TO_BODY(ObjectHeader); + + ObpDecrementHandleCount(Body); + + /* destroy and unlock the handle entry */ + ExDestroyHandleByEntry(Process->ObjectTable, + HandleEntry, + ExHandle); + + KeLeaveCriticalRegion(); + + return STATUS_SUCCESS; + } - Body = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody); - DPRINT("ObjectBody %x\n", Body); - if (Body == NULL) - { - KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); - *ObjectBody = NULL; - return STATUS_UNSUCCESSFUL; - } - - Header = BODY_TO_HEADER(Body); - ObReferenceObjectByPointer(Body, - 0, - NULL, - UserMode); - InterlockedDecrement(&Header->HandleCount); - HandleEntry->ObjectBody = NULL; - - Block->allocation_count--; - Block->allocation_hint = (ULONG_PTR)Handle % HANDLE_BLOCK_ENTRIES; - - KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); - - if ((Header->ObjectType != NULL) && - (Header->ObjectType->Close != NULL)) - { - Header->ObjectType->Close(Body, Header->HandleCount); - } - - *ObjectBody = Body; - - DPRINT("Finished ObDeleteHandle()\n"); - - return STATUS_SUCCESS; + return STATUS_INVALID_HANDLE; } @@ -626,94 +525,47 @@ ObCreateHandle(PEPROCESS Process, * NOTE: The handle is valid only in the context of the current process */ { - LIST_ENTRY* current; - unsigned int handle=1; - unsigned int Loop, Index, MaxIndex; - HANDLE_BLOCK* new_blk = NULL; - PHANDLE_TABLE HandleTable; - KIRQL oldlvl; + HANDLE_TABLE_ENTRY NewEntry; + POBJECT_HEADER ObjectHeader; + LONG ExHandle; PAGED_CODE(); DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody); ASSERT(Process); + ASSERT(ObjectBody); - if (ObjectBody != NULL) + ObjectHeader = BODY_TO_HEADER(ObjectBody); + + ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED); + + NewEntry.u1.Object = ObjectHeader; + if(Inherit) + NewEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE; + else + NewEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE; + NewEntry.u2.GrantedAccess = GrantedAccess; + + ExHandle = ExCreateHandle(Process->ObjectTable, + &NewEntry); + DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader, *HandleReturn, Process->ObjectTable); + if(ExHandle != EX_INVALID_HANDLE) + { + if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1) { - InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount)); + ObReferenceObjectByPointer(ObjectBody, + 0, + NULL, + UserMode); } - HandleTable = &Process->HandleTable; - KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl); - current = HandleTable->ListHead.Flink; - /* - * Scan through the currently allocated handle blocks looking for a free - * slot - */ - while (current != (&HandleTable->ListHead)) - { - HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry); + + *HandleReturn = EX_HANDLE_TO_HANDLE(ExHandle); - DPRINT("Current %x\n",current); + return STATUS_SUCCESS; + } - if (blk->allocation_count == HANDLE_BLOCK_ENTRIES) - { - handle = handle + HANDLE_BLOCK_ENTRIES; - current = current->Flink; - continue; - } - - Index = blk->allocation_hint; - MaxIndex = HANDLE_BLOCK_ENTRIES; - for (Loop = 0; Loop < 2; Loop++) - { - for (Index = 0; Index < MaxIndex; Index++) - { - DPRINT("Considering slot %d containing %x\n", Index, blk->handles[Index]); - if (blk->handles[Index].ObjectBody == NULL) - { - blk->handles[Index].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody); - if (Inherit) - blk->handles[Index].ObjectBody = (PVOID)((ULONG_PTR)blk->handles[Index].ObjectBody | OB_HANDLE_FLAG_INHERIT); - blk->handles[Index].GrantedAccess = GrantedAccess; - blk->allocation_hint = Index + 1; - blk->allocation_count++; - KeReleaseSpinLock(&HandleTable->ListLock, oldlvl); - *HandleReturn = (HANDLE)((handle + Index) << 2); - return(STATUS_SUCCESS); - } - } - Index = 0; - MaxIndex = blk->allocation_hint; - } - - handle = handle + HANDLE_BLOCK_ENTRIES; - current = current->Flink; - } - - /* - * Add a new handle block to the end of the list - */ - new_blk = - (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK), - TAG_HANDLE_TABLE); - if (!new_blk) - { - *HandleReturn = (PHANDLE)NULL; - return(STATUS_INSUFFICIENT_RESOURCES); - } - RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK)); - InsertTailList(&(Process->HandleTable.ListHead), - &new_blk->entry); - new_blk->handles[0].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody); - if (Inherit) - new_blk->handles[0].ObjectBody = (PVOID)((ULONG_PTR)new_blk->handles[0].ObjectBody | OB_HANDLE_FLAG_INHERIT); - new_blk->handles[0].GrantedAccess = GrantedAccess; - new_blk->allocation_hint = 1; - new_blk->allocation_count++; - KeReleaseSpinLock(&HandleTable->ListLock, oldlvl); - *HandleReturn = (HANDLE)(handle << 2); - return(STATUS_SUCCESS); + return STATUS_UNSUCCESSFUL; } @@ -724,31 +576,35 @@ NTSTATUS STDCALL ObQueryObjectAuditingByHandle(IN HANDLE Handle, OUT PBOOLEAN GenerateOnClose) { + PHANDLE_TABLE_ENTRY HandleEntry; PEPROCESS Process; - KIRQL oldIrql; - PHANDLE_ENTRY HandleEntry; + LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); PAGED_CODE(); DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle); Process = PsGetCurrentProcess(); + + KeEnterCriticalRegion(); - KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql); - HandleEntry = ObpGetObjectByHandle(&Process->HandleTable, - Handle, - NULL); - if (HandleEntry == NULL) - { - KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql); - return STATUS_INVALID_HANDLE; - } + HandleEntry = ExMapHandleToPointer(Process->ObjectTable, + ExHandle); + if(HandleEntry != NULL) + { + *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0; + + ExUnlockHandleTableEntry(Process->ObjectTable, + HandleEntry); - *GenerateOnClose = (BOOLEAN)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_AUDIT); - - KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql); - - return STATUS_SUCCESS; + KeLeaveCriticalRegion(); + + return STATUS_SUCCESS; + } + + KeLeaveCriticalRegion(); + + return STATUS_INVALID_HANDLE; } @@ -775,13 +631,14 @@ ObReferenceObjectByHandle(HANDLE Handle, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation) { - PHANDLE_ENTRY HandleEntry; + PHANDLE_TABLE_ENTRY HandleEntry; POBJECT_HEADER ObjectHeader; - KIRQL oldIrql; PVOID ObjectBody; ACCESS_MASK GrantedAccess; + PGENERIC_MAPPING GenericMapping; ULONG Attributes; NTSTATUS Status; + LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); PAGED_CODE(); @@ -795,8 +652,6 @@ ObReferenceObjectByHandle(HANDLE Handle, if (Handle == NtCurrentProcess() && (ObjectType == PsProcessType || ObjectType == NULL)) { - DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]); - Status = ObReferenceObjectByPointer(PsGetCurrentProcess(), PROCESS_ALL_ACCESS, PsProcessType, @@ -808,7 +663,7 @@ ObReferenceObjectByHandle(HANDLE Handle, if (HandleInformation != NULL) { - HandleInformation->HandleAttributes = 0; /* FIXME? */ + HandleInformation->HandleAttributes = 0; HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS; } @@ -836,7 +691,7 @@ ObReferenceObjectByHandle(HANDLE Handle, if (HandleInformation != NULL) { - HandleInformation->HandleAttributes = 0; /* FIXME? */ + HandleInformation->HandleAttributes = 0; HandleInformation->GrantedAccess = THREAD_ALL_ACCESS; } @@ -850,47 +705,52 @@ ObReferenceObjectByHandle(HANDLE Handle, return(STATUS_OBJECT_TYPE_MISMATCH); } - KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock, - &oldIrql); - HandleEntry = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable, - Handle, - NULL); - if (HandleEntry == NULL || HandleEntry->ObjectBody == 0) + KeEnterCriticalRegion(); + + HandleEntry = ExMapHandleToPointer(PsGetCurrentProcess()->ObjectTable, + ExHandle); + if (HandleEntry == NULL) { - KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock, - oldIrql); - return(STATUS_INVALID_HANDLE); + KeLeaveCriticalRegion(); + DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle); + return(STATUS_INVALID_HANDLE); } - ObjectBody = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody); - DPRINT("ObjectBody %p\n",ObjectBody); - ObjectHeader = BODY_TO_HEADER(ObjectBody); - DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount); + + ObjectHeader = EX_HTE_TO_HDR(HandleEntry); + ObjectBody = HEADER_TO_BODY(ObjectHeader); + + DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, PsGetCurrentProcess()->ObjectTable); + ObReferenceObjectByPointer(ObjectBody, 0, NULL, UserMode); - Attributes = (ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_MASK; - GrantedAccess = HandleEntry->GrantedAccess; - KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock, - oldIrql); - - ObjectHeader = BODY_TO_HEADER(ObjectBody); - DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount); + Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE | + EX_HANDLE_ENTRY_INHERITABLE | + EX_HANDLE_ENTRY_AUDITONCLOSE); + GrantedAccess = HandleEntry->u2.GrantedAccess; + GenericMapping = ObjectHeader->ObjectType->Mapping; if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType) { - CHECKPOINT; - return(STATUS_OBJECT_TYPE_MISMATCH); + DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->TypeName, ObjectHeader->ObjectType ? &ObjectHeader->ObjectType->TypeName : NULL, Handle); + + ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable, + HandleEntry); + + KeLeaveCriticalRegion(); + + return(STATUS_OBJECT_TYPE_MISMATCH); } + + ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable, + HandleEntry); - if (ObjectHeader->ObjectType == PsProcessType) - { - DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]); - } + KeLeaveCriticalRegion(); - if (DesiredAccess && AccessMode == UserMode) + if (DesiredAccess && AccessMode != KernelMode) { - RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping); + RtlMapGenericMask(&DesiredAccess, GenericMapping); if (!(GrantedAccess & DesiredAccess) && !((~GrantedAccess) & DesiredAccess)) @@ -908,7 +768,6 @@ ObReferenceObjectByHandle(HANDLE Handle, *Object = ObjectBody; - CHECKPOINT; return(STATUS_SUCCESS); } @@ -932,17 +791,12 @@ ObReferenceObjectByHandle(HANDLE Handle, NTSTATUS STDCALL NtClose(IN HANDLE Handle) { - PVOID ObjectBody; - POBJECT_HEADER Header; NTSTATUS Status; PAGED_CODE(); - DPRINT("NtClose(Handle %x)\n",Handle); - Status = ObDeleteHandle(PsGetCurrentProcess(), - Handle, - &ObjectBody); + Handle); if (!NT_SUCCESS(Status)) { if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort) @@ -950,11 +804,6 @@ NtClose(IN HANDLE Handle) return Status; } - Header = BODY_TO_HEADER(ObjectBody); - - DPRINT("Dereferencing %x\n", ObjectBody); - ObDereferenceObject(ObjectBody); - return(STATUS_SUCCESS); } @@ -992,42 +841,7 @@ ObInsertObject(IN PVOID Object, ULONG ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable) { - PHANDLE_BLOCK blk; - POBJECT_HEADER Header; - PVOID ObjectBody; - KIRQL OldIrql; - PLIST_ENTRY current; - ULONG i; - ULONG Count=0; - - KeAcquireSpinLock(&HandleTable->ListLock, &OldIrql); - - current = HandleTable->ListHead.Flink; - while (current != &HandleTable->ListHead) - { - blk = CONTAINING_RECORD(current, HANDLE_BLOCK, entry); - - for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) - { - ObjectBody = OB_ENTRY_TO_POINTER(blk->handles[i].ObjectBody); - if (ObjectBody != NULL) - { - Header = BODY_TO_HEADER(ObjectBody); - - /* Make sure this is real. Okay! For real!*/ - if ((Header->ObjectType != NULL) && - (Header->ObjectType->Close != NULL)) - Count++; - } - } - - current = current->Flink; - } - - KeReleaseSpinLock(&HandleTable->ListLock, - OldIrql); - - return Count; + return HandleTable->HandleCount; } /* @@ -1085,7 +899,7 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi, int Count) { ULONG P; - KIRQL oldIrql; +// KIRQL oldIrql; // pshi->HandleValue; @@ -1097,14 +911,14 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi, P = (ULONG) Process->UniqueProcessId; pshi->UniqueProcessId = (USHORT) P; - KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql ); +// KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql ); // pshi->GrantedAccess; // pshi->Object; // pshi->ObjectTypeIndex; // pshi->HandleAttributes; - KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql ); +// KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql ); return; } diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c index d9e1580c088..25f7d593414 100644 --- a/reactos/ntoskrnl/ob/object.c +++ b/reactos/ntoskrnl/ob/object.c @@ -25,18 +25,6 @@ typedef struct _RETENTION_CHECK_PARAMS /* FUNCTIONS ************************************************************/ -PVOID HEADER_TO_BODY(POBJECT_HEADER obj) -{ - return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)); -} - - -POBJECT_HEADER BODY_TO_HEADER(PVOID body) -{ - PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body; - return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); -} - NTSTATUS ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, @@ -734,7 +722,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize)); /* Initialize the object header */ - DPRINT("Initalizing header\n"); + DPRINT("Initalizing header 0x%x (%wZ)\n", Header, &Type->TypeName); Header->HandleCount = 0; Header->RefCount = 1; Header->ObjectType = Type; @@ -1111,7 +1099,7 @@ ObfReferenceObject(IN PVOID Object) KEBUGCHECK(0); } - (VOID)InterlockedIncrement(&Header->RefCount); + InterlockedIncrement(&Header->RefCount); } @@ -1137,25 +1125,23 @@ ObfDereferenceObject(IN PVOID Object) POBJECT_HEADER Header; LONG NewRefCount; BOOL Permanent; - ULONG HandleCount; ASSERT(Object); /* Extract the object header. */ Header = BODY_TO_HEADER(Object); Permanent = Header->Permanent; - HandleCount = Header->HandleCount; /* Drop our reference and get the new count so we can tell if this was the last reference. */ NewRefCount = InterlockedDecrement(&Header->RefCount); + DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object, NewRefCount, &Header->ObjectType->TypeName); ASSERT(NewRefCount >= 0); /* Check whether the object can now be deleted. */ if (NewRefCount == 0 && - HandleCount == 0 && !Permanent) { ObpDeleteObjectDpcLevel(Header, NewRefCount); diff --git a/reactos/ntoskrnl/ps/cid.c b/reactos/ntoskrnl/ps/cid.c index e38842500f5..f311cd30c87 100644 --- a/reactos/ntoskrnl/ps/cid.c +++ b/reactos/ntoskrnl/ps/cid.c @@ -16,147 +16,126 @@ /* GLOBALS ******************************************************************/ -/* - * FIXME - use a global handle table instead! - */ - -KSPIN_LOCK CidLock; -LIST_ENTRY CidHead; -KEVENT CidReleaseEvent; -LONG CidCounter = 0; -LARGE_INTEGER ShortDelay, LongDelay; +PHANDLE_TABLE PspCidTable = NULL; #define TAG_CIDOBJECT TAG('C', 'I', 'D', 'O') +#define CID_FLAG_PROCESS 0x1 +#define CID_FLAG_THREAD 0x2 +#define CID_FLAGS_MASK (CID_FLAG_PROCESS | CID_FLAG_THREAD) + /* FUNCTIONS *****************************************************************/ VOID INIT_FUNCTION PsInitClientIDManagment(VOID) { - InitializeListHead(&CidHead); - KeInitializeSpinLock(&CidLock); - KeInitializeEvent(&CidReleaseEvent, SynchronizationEvent, FALSE); - ShortDelay.QuadPart = -100LL; - LongDelay.QuadPart = -100000LL; -} - -VOID -PspReferenceCidObject(PCID_OBJECT Object) -{ - InterlockedIncrement(&Object->ref); -} - -VOID -PspDereferenceCidObject(PCID_OBJECT Object) -{ - if(InterlockedDecrement(&Object->ref) == 0) - { - ExFreePool(Object); - } + PspCidTable = ExCreateHandleTable(NULL); + ASSERT(PspCidTable); } NTSTATUS PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle) { - KIRQL oldIrql; - PCID_OBJECT cido = ExAllocatePoolWithTag(NonPagedPool, - sizeof(CID_OBJECT), - TAG_CIDOBJECT); - if(cido != NULL) + HANDLE_TABLE_ENTRY NewEntry; + LONG ExHandle; + + PAGED_CODE(); + + NewEntry.u1.Object = Object; + if(ObjectType == PsThreadType) + NewEntry.u2.GrantedAccess = CID_FLAG_THREAD; + else if(ObjectType == PsProcessType) + NewEntry.u2.GrantedAccess = CID_FLAG_PROCESS; + else { - cido->ref = 1; - ExInitializeFastMutex(&cido->Lock); - cido->Obj.Object = Object; - - KeAcquireSpinLock(&CidLock, &oldIrql); - cido->Handle = (HANDLE)((ULONG_PTR)(++CidCounter) << 2); - InsertTailList(&CidHead, &cido->Entry); - KeReleaseSpinLock(&CidLock, oldIrql); - - *Handle = cido->Handle; + DPRINT1("Can't create CID handles for %wZ objects\n", &ObjectType->TypeName); + KEBUGCHECK(0); + } + + ExHandle = ExCreateHandle(PspCidTable, + &NewEntry); + if(ExHandle != EX_INVALID_HANDLE) + { + *Handle = EX_HANDLE_TO_HANDLE(ExHandle); return STATUS_SUCCESS; } - return STATUS_INSUFFICIENT_RESOURCES; + return STATUS_UNSUCCESSFUL; } NTSTATUS PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType) { - PCID_OBJECT cido, Found = NULL; - PLIST_ENTRY Current; - KIRQL oldIrql; + PHANDLE_TABLE_ENTRY Entry; + LONG ExHandle = HANDLE_TO_EX_HANDLE(CidHandle); - if(CidHandle == NULL) + PAGED_CODE(); + + Entry = ExMapHandleToPointer(PspCidTable, + ExHandle); + if(Entry != NULL) { - return STATUS_INVALID_PARAMETER; - } - - KeAcquireSpinLock(&CidLock, &oldIrql); - Current = CidHead.Flink; - while(Current != &CidHead) - { - cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry); - if(cido->Handle == CidHandle) + if((ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD)) || + (ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS))) { - RemoveEntryList(&cido->Entry); - cido->Handle = NULL; - Found = cido; - break; + ExDestroyHandleByEntry(PspCidTable, + Entry, + ExHandle); + return STATUS_SUCCESS; + } + else + { + ExUnlockHandleTableEntry(PspCidTable, + Entry); + return STATUS_OBJECT_TYPE_MISMATCH; } - Current = Current->Flink; - } - KeReleaseSpinLock(&CidLock, oldIrql); - - if(Found != NULL) - { - PspDereferenceCidObject(Found); - return STATUS_SUCCESS; } - return STATUS_UNSUCCESSFUL; + return STATUS_INVALID_HANDLE; } -PCID_OBJECT -PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType) +PHANDLE_TABLE_ENTRY +PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object) { - PCID_OBJECT cido, Found = NULL; - PLIST_ENTRY Current; - KIRQL oldIrql; + PHANDLE_TABLE_ENTRY Entry; - if(CidHandle == NULL) - { - return NULL; - } - - KeAcquireSpinLock(&CidLock, &oldIrql); - Current = CidHead.Flink; - while(Current != &CidHead) - { - cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry); - if(cido->Handle == CidHandle) - { - Found = cido; - PspReferenceCidObject(Found); - break; - } - Current = Current->Flink; - } - KeReleaseSpinLock(&CidLock, oldIrql); - - if(Found != NULL) - { - ExAcquireFastMutex(&Found->Lock); - } + PAGED_CODE(); - return Found; + KeEnterCriticalRegion(); + + Entry = ExMapHandleToPointer(PspCidTable, + HANDLE_TO_EX_HANDLE(CidHandle)); + if(Entry != NULL) + { + if((ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS)) || + (ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD))) + { + *Object = Entry->u1.Object; + return Entry; + } + else + { + DPRINT1("CID Obj type mismatch handle 0x%x %wZ vs 0x%x\n", CidHandle, + &ObjectType->TypeName, Entry->u2.GrantedAccess); + ExUnlockHandleTableEntry(PspCidTable, + Entry); + KEBUGCHECK(0); + } + } + + KeLeaveCriticalRegion(); + + return NULL; } VOID -PsUnlockCidObject(PCID_OBJECT CidObject) +PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry) { - ExReleaseFastMutex(&CidObject->Lock); - PspDereferenceCidObject(CidObject); + PAGED_CODE(); + + ExUnlockHandleTableEntry(PspCidTable, + CidEntry); + KeLeaveCriticalRegion(); } /* EOF */ diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index 8c85ab4e3ef..fca97ad3875 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -376,7 +376,10 @@ PiDeleteThread(PVOID ObjectBody) Process = Thread->ThreadsProcess; Thread->ThreadsProcess = NULL; - PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); + if(Thread->Cid.UniqueThread != NULL) + { + PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); + } if(Thread->Tcb.Win32Thread != NULL) { @@ -395,19 +398,39 @@ PiDeleteThread(PVOID ObjectBody) NTSTATUS PsInitializeThread(PEPROCESS Process, PETHREAD* ThreadPtr, - PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ThreadAttributes, + POBJECT_ATTRIBUTES ObjectAttributes, BOOLEAN First) { PETHREAD Thread; NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; KIRQL oldIrql; - + + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode(); + if (Process == NULL) { Process = PsInitialSystemProcess; } + + /* + * Create and initialize thread + */ + Status = ObCreateObject(PreviousMode, + PsThreadType, + ObjectAttributes, + KernelMode, + NULL, + sizeof(ETHREAD), + 0, + 0, + (PVOID*)&Thread); + if (!NT_SUCCESS(Status)) + { + return(Status); + } /* * Reference process @@ -416,35 +439,10 @@ PsInitializeThread(PEPROCESS Process, PROCESS_CREATE_THREAD, PsProcessType, KernelMode); - - /* - * Create and initialize thread - */ - Status = ObCreateObject(UserMode, - PsThreadType, - ThreadAttributes, - KernelMode, - NULL, - sizeof(ETHREAD), - 0, - 0, - (PVOID*)&Thread); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Process); - return(Status); - } - /* create a client id handle */ - Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Thread); - ObDereferenceObject (Process); - return Status; - } - Thread->ThreadsProcess = Process; - Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; + Thread->ThreadsProcess = Process; + Thread->Cid.UniqueThread = NULL; + Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; DPRINT("Thread = %x\n",Thread); @@ -477,14 +475,8 @@ PsInitializeThread(PEPROCESS Process, KeReleaseDispatcherDatabaseLock(oldIrql); *ThreadPtr = Thread; - - Status = ObInsertObject((PVOID)Thread, - NULL, - DesiredAccess, - 0, - NULL, - ThreadHandle); - return(Status); + + return STATUS_SUCCESS; } @@ -737,21 +729,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle, Status = PsInitializeThread(Process, &Thread, - &hThread, - DesiredAccess, ObjectAttributes, FALSE); ObDereferenceObject(Process); - + if (!NT_SUCCESS(Status)) { return(Status); } + + /* create a client id handle */ + Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Thread); + return Status; + } Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext); if (!NT_SUCCESS(Status)) { + PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); + ObDereferenceObject(Thread); return(Status); } @@ -761,6 +761,8 @@ NtCreateThread(OUT PHANDLE ThreadHandle, InitialTeb); if (!NT_SUCCESS(Status)) { + PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); + ObDereferenceObject(Thread); return(Status); } Thread->Tcb.Teb = TebBase; @@ -808,20 +810,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle, PsUnblockThread(Thread, NULL, 0); KeReleaseDispatcherDatabaseLock(oldIrql); - _SEH_TRY + Status = ObInsertObject((PVOID)Thread, + NULL, + DesiredAccess, + 0, + NULL, + &hThread); + if(NT_SUCCESS(Status)) { - if(ClientId != NULL) + _SEH_TRY { - *ClientId = Thread->Cid; + if(ClientId != NULL) + { + *ClientId = Thread->Cid; + } + *ThreadHandle = hThread; } - *ThreadHandle = hThread; + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - + return Status; } @@ -865,20 +876,28 @@ PsCreateSystemThread(PHANDLE ThreadHandle, Status = PsInitializeThread(NULL, &Thread, - ThreadHandle, - DesiredAccess, ObjectAttributes, FALSE); if (!NT_SUCCESS(Status)) { return(Status); } + + Status = PsCreateCidHandle(Thread, + PsThreadType, + &Thread->Cid.UniqueThread); + if(!NT_SUCCESS(Status)) + { + ObDereferenceObject(Thread); + return Status; + } Thread->StartAddress = StartRoutine; Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext); if (!NT_SUCCESS(Status)) { - return(Status); + ObDereferenceObject(Thread); + return(Status); } if (ClientId != NULL) @@ -890,7 +909,17 @@ PsCreateSystemThread(PHANDLE ThreadHandle, PsUnblockThread(Thread, NULL, 0); KeReleaseDispatcherDatabaseLock(oldIrql); - return(STATUS_SUCCESS); + Status = ObInsertObject((PVOID)Thread, + NULL, + DesiredAccess, + 0, + NULL, + ThreadHandle); + + /* don't dereference the thread, the initial reference serves as the keep-alive + reference which will be removed by the thread reaper */ + + return Status; } diff --git a/reactos/ntoskrnl/ps/idle.c b/reactos/ntoskrnl/ps/idle.c index 21bcd16b964..f77aa45d46b 100644 --- a/reactos/ntoskrnl/ps/idle.c +++ b/reactos/ntoskrnl/ps/idle.c @@ -52,34 +52,33 @@ PsInitIdleThread(VOID) { NTSTATUS Status; PETHREAD IdleThread; - HANDLE IdleThreadHandle; + KIRQL oldIrql; - Status = PsCreateSystemThread(&IdleThreadHandle, - THREAD_ALL_ACCESS, - NULL, - NULL, - NULL, - PsIdleThreadMain, - NULL); - if(!NT_SUCCESS(Status)) - { - DPRINT("Couldn't create Idle System Thread!"); - KEBUGCHECK(0); - return; - } - Status = ObReferenceObjectByHandle(IdleThreadHandle, - THREAD_ALL_ACCESS, - PsThreadType, - KernelMode, - (PVOID*)&IdleThread, - NULL); - if(!NT_SUCCESS(Status)) - { - DPRINT("Couldn't get pointer to Idle System Thread!"); - KEBUGCHECK(0); - return; - } - NtClose(IdleThreadHandle); + Status = PsInitializeThread(NULL, + &IdleThread, + NULL, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Couldn't create idle system thread! Status: 0x%x\n", Status); + KEBUGCHECK(0); + return; + } + + IdleThread->StartAddress = PsIdleThreadMain; + Status = KiArchInitThread(&IdleThread->Tcb, PsIdleThreadMain, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Couldn't initialize system idle thread! Status: 0x%x\n", Status); + ObDereferenceObject(IdleThread); + KEBUGCHECK(0); + return; + } + + oldIrql = KeAcquireDispatcherDatabaseLock (); + PsUnblockThread(IdleThread, NULL, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); + KeGetCurrentPrcb()->IdleThread = &IdleThread->Tcb; KeSetPriorityThread(&IdleThread->Tcb, LOW_PRIORITY); KeSetAffinityThread(&IdleThread->Tcb, 1 << 0); diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 7a3cde75b57..73c8d441de6 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -218,6 +218,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus) PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE); PsTerminateWin32Process(CurrentProcess); + PiTerminateProcess(CurrentProcess, ExitStatus); } @@ -315,19 +316,26 @@ PiTerminateProcess(PEPROCESS Process, ObGetObjectHandleCount(Process)); ObReferenceObject(Process); - if (InterlockedExchangeUL(&Process->Pcb.State, - PROCESS_STATE_TERMINATED) == - PROCESS_STATE_TERMINATED) + if (Process->Pcb.State == PROCESS_STATE_TERMINATED) { ObDereferenceObject(Process); return(STATUS_SUCCESS); } + + Process->Pcb.State = PROCESS_STATE_TERMINATED; + CurrentProcess = PsGetCurrentProcess(); if (Process != CurrentProcess) { KeAttachProcess(&Process->Pcb); } - ObCloseAllHandles(Process); + + ObDeleteHandleTable(Process); + if(Process->UniqueProcessId != NULL) + { + PsDeleteCidHandle(Process->UniqueProcessId, PsProcessType); + } + if (Process != CurrentProcess) { KeDetachProcess(); diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 6dd3f89890b..eee2f3a04b5 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -412,15 +412,6 @@ PsInitProcessManagment(VOID) strcpy(PsInitialSystemProcess->ImageFileName, "System"); - Status = PsCreateCidHandle(PsInitialSystemProcess, - PsProcessType, - &PsInitialSystemProcess->UniqueProcessId); - if(!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create CID handle (unique process id) for the system process!\n"); - return; - } - PsInitialSystemProcess->Win32WindowStation = (HANDLE)0; InsertHeadList(&PsActiveProcessHead, @@ -456,7 +447,6 @@ PiDeleteProcessWorker(PVOID pContext) KDB_DELETEPROCESS_HOOK(Process); ObDereferenceObject(Process->Token); - ObDeleteHandleTable(Process); if (CurrentProcess != Process) { @@ -1458,7 +1448,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, case ProcessHandleCount: { - ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable); + ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable); _SEH_TRY { @@ -2636,30 +2626,25 @@ NTSTATUS STDCALL PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process) { - PLIST_ENTRY current_entry; - PEPROCESS current; + PHANDLE_TABLE_ENTRY CidEntry; + PEPROCESS FoundProcess; - ExAcquireFastMutex(&PspActiveProcessMutex); + PAGED_CODE(); - current_entry = PsActiveProcessHead.Flink; - while (current_entry != &PsActiveProcessHead) - { - current = CONTAINING_RECORD(current_entry, - EPROCESS, - ProcessListEntry); - if (current->UniqueProcessId == ProcessId) - { - *Process = current; - ObReferenceObject(current); - ExReleaseFastMutex(&PspActiveProcessMutex); - return(STATUS_SUCCESS); - } - current_entry = current_entry->Flink; - } + ASSERT(Process); - ExReleaseFastMutex(&PspActiveProcessMutex); + CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess); + if(CidEntry != NULL) + { + ObReferenceObject(FoundProcess); - return(STATUS_INVALID_PARAMETER); + PsUnlockCidHandle(CidEntry); + + *Process = FoundProcess; + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; } VOID diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index 051d6ae9989..73338eccdb9 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -28,11 +28,23 @@ VOID PiShutdownProcessManager(VOID) VOID INIT_FUNCTION PiInitProcessManager(VOID) { + NTSTATUS Status; + PsInitClientIDManagment(); PsInitJobManagment(); PsInitProcessManagment(); PsInitThreadManagment(); PsInitIdleThread(); + + Status = PsCreateCidHandle(PsInitialSystemProcess, + PsProcessType, + &PsInitialSystemProcess->UniqueProcessId); + if(!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create CID handle (unique process id) for the system process!\n"); + KEBUGCHECK(0); + } + PsInitialiseSuspendImplementation(); PsInitialiseW32Call(); } diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index b9e033fd2f8..2d85c83b645 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -222,7 +222,7 @@ PsIsThreadTerminating(IN PETHREAD Thread) /* * @unimplemented - */ + */ BOOLEAN STDCALL PsIsSystemThread( @@ -235,7 +235,7 @@ PsIsSystemThread( /* * @implemented - */ + */ BOOLEAN STDCALL PsIsThreadImpersonating( @@ -251,7 +251,7 @@ KiRequestReschedule(CCHAR Processor) PKPCR Pcr; Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE); - Pcr->PrcbData.QuantumEnd = TRUE; + Pcr->Prcb->QuantumEnd = TRUE; KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC); } @@ -641,7 +641,7 @@ PsEnumThreadsByProcess(PEPROCESS Process) /* * @unimplemented - */ + */ NTSTATUS STDCALL PsRemoveCreateThreadNotifyRoutine ( @@ -704,13 +704,10 @@ VOID INIT_FUNCTION PsPrepareForApplicationProcessorInit(ULONG Id) { PETHREAD IdleThread; - HANDLE IdleThreadHandle; - PKPCR Pcr = (PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE); + PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb; PsInitializeThread(NULL, &IdleThread, - &IdleThreadHandle, - THREAD_ALL_ACCESS, NULL, FALSE); IdleThread->Tcb.State = THREAD_STATE_RUNNING; @@ -719,12 +716,11 @@ PsPrepareForApplicationProcessorInit(ULONG Id) IdleThread->Tcb.UserAffinity = 1 << Id; IdleThread->Tcb.Priority = LOW_PRIORITY; IdleThread->Tcb.BasePriority = LOW_PRIORITY; - Pcr->PrcbData.IdleThread = &IdleThread->Tcb; - Pcr->PrcbData.CurrentThread = &IdleThread->Tcb; + Prcb->IdleThread = &IdleThread->Tcb; + Prcb->CurrentThread = &IdleThread->Tcb; Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit; - NtClose(IdleThreadHandle); DPRINT("IdleThread for Processor %d has PID %d\n", Id, IdleThread->Cid.UniqueThread); } @@ -738,7 +734,6 @@ PsInitThreadManagment(VOID) HANDLE PiReaperThreadHandle; PETHREAD FirstThread; ULONG i; - HANDLE FirstThreadHandle; NTSTATUS Status; for (i=0; i < MAXIMUM_PRIORITY; i++) @@ -771,14 +766,12 @@ PsInitThreadManagment(VOID) ObpCreateTypeObject(PsThreadType); - PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle, - THREAD_ALL_ACCESS,NULL, TRUE); + PsInitializeThread(NULL, &FirstThread, NULL, TRUE); FirstThread->Tcb.State = THREAD_STATE_RUNNING; FirstThread->Tcb.FreezeCount = 0; FirstThread->Tcb.UserAffinity = (1 << 0); /* Set the affinity of the first thread to the boot processor */ FirstThread->Tcb.Affinity = (1 << 0); KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread; - NtClose(FirstThreadHandle); DPRINT("FirstThread %x\n",FirstThread); @@ -895,8 +888,8 @@ KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority) { for (i = 0; i < KeNumberProcessors; i++) { - Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE); - if (Pcr->PrcbData.CurrentThread == Thread) + Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE); + if (Pcr->Prcb->CurrentThread == Thread) { KeReleaseDispatcherDatabaseLockFromDpcLevel(); KiRequestReschedule(i); @@ -959,7 +952,7 @@ KeSetAffinityThread(PKTHREAD Thread, for (i = 0; i < KeNumberProcessors; i++) { Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE); - if (Pcr->PrcbData.CurrentThread == Thread) + if (Pcr->Prcb->CurrentThread == Thread) { if (!(Affinity & ProcessorMask)) { @@ -988,63 +981,95 @@ KeSetAffinityThread(PKTHREAD Thread, NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId) + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PCLIENT_ID ClientId OPTIONAL) { - NTSTATUS Status = STATUS_INVALID_PARAMETER; - + KPROCESSOR_MODE PreviousMode; + CLIENT_ID SafeClientId; + HANDLE hThread; + NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); - if((NULL != ThreadHandle)&&(NULL != ObjectAttributes)) - { - PETHREAD EThread = NULL; + PreviousMode = ExGetPreviousMode(); - if((ClientId) - && (ClientId->UniqueThread)) - { - // It is an error to specify both - // ObjectAttributes.ObjectName - // and ClientId. - if((ObjectAttributes) - && (ObjectAttributes->ObjectName) - && (0 < ObjectAttributes->ObjectName->Length)) - { - return(STATUS_INVALID_PARAMETER_MIX); - } - // Parameters mix OK - Status = PsLookupThreadByThreadId(ClientId->UniqueThread, - & EThread); - } - else if((ObjectAttributes) - && (ObjectAttributes->ObjectName) - && (0 < ObjectAttributes->ObjectName->Length)) - { - // Three Ob attributes are forbidden - if(!(ObjectAttributes->Attributes & - (OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENIF))) - { - Status = ObReferenceObjectByName(ObjectAttributes->ObjectName, - ObjectAttributes->Attributes, - NULL, - DesiredAccess, - PsThreadType, - UserMode, - NULL, - (PVOID*) & EThread); - } - } - // EThread may be OK... - if(STATUS_SUCCESS == Status) - { - Status = ObCreateHandle(PsGetCurrentProcess(), - EThread, - DesiredAccess, - FALSE, - ThreadHandle); - ObDereferenceObject(EThread); - } + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(ThreadHandle, + sizeof(HANDLE), + sizeof(ULONG)); + if(ClientId != NULL) + { + ProbeForRead(ClientId, + sizeof(CLIENT_ID), + sizeof(ULONG)); + SafeClientId = *ClientId; + ClientId = &SafeClientId; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } } - return(Status); + + if(!((ObjectAttributes == NULL) ^ (ClientId == NULL))) + { + DPRINT("NtOpenThread should be called with either ObjectAttributes or ClientId!\n"); + return STATUS_INVALID_PARAMETER; + } + + if(ClientId != NULL) + { + PETHREAD Thread; + + Status = PsLookupThreadByThreadId(ClientId->UniqueThread, + &Thread); + if(NT_SUCCESS(Status)) + { + Status = ObInsertObject(Thread, + NULL, + DesiredAccess, + 0, + NULL, + &hThread); + + ObDereferenceObject(Thread); + } + } + else + { + Status = ObOpenObjectByName(ObjectAttributes, + PsThreadType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hThread); + } + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *ThreadHandle = hThread; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; } NTSTATUS STDCALL @@ -1074,22 +1099,26 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, OUT PEPROCESS *Process OPTIONAL, OUT PETHREAD *Thread) { - PCID_OBJECT CidObject; + PHANDLE_TABLE_ENTRY CidEntry; PETHREAD FoundThread; - CidObject = PsLockCidHandle((HANDLE)Cid->UniqueThread, PsThreadType); - if(CidObject != NULL) + PAGED_CODE(); + + ASSERT(Thread); + ASSERT(Cid); + + CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread); + if(CidEntry != NULL) { - FoundThread = CidObject->Obj.Thread; ObReferenceObject(FoundThread); - + + PsUnlockCidHandle(CidEntry); + if(Process != NULL) { *Process = FoundThread->ThreadsProcess; - ObReferenceObject(FoundThread->ThreadsProcess); } - - PsUnlockCidObject(CidObject); + *Thread = FoundThread; return STATUS_SUCCESS; } @@ -1104,15 +1133,21 @@ NTSTATUS STDCALL PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread) { - PCID_OBJECT CidObject; - - CidObject = PsLockCidHandle(ThreadId, PsThreadType); - if(CidObject != NULL) + PHANDLE_TABLE_ENTRY CidEntry; + PETHREAD FoundThread; + + PAGED_CODE(); + + ASSERT(Thread); + + CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread); + if(CidEntry != NULL) { - *Thread = CidObject->Obj.Thread; - ObReferenceObject(*Thread); - - PsUnlockCidObject(CidObject); + ObReferenceObject(FoundThread); + + PsUnlockCidHandle(CidEntry); + + *Thread = FoundThread; return STATUS_SUCCESS; } diff --git a/reactos/subsys/win32k/misc/object.c b/reactos/subsys/win32k/misc/object.c index 7b382bbbfea..28b04eb9936 100644 --- a/reactos/subsys/win32k/misc/object.c +++ b/reactos/subsys/win32k/misc/object.c @@ -34,10 +34,10 @@ #define NDEBUG #include -#define HEADER_TO_BODY(ObjectHeader) \ +#define USER_HEADER_TO_BODY(ObjectHeader) \ ((PVOID)(((PUSER_OBJECT_HEADER)ObjectHeader) + 1)) -#define BODY_TO_HEADER(ObjectBody) \ +#define USER_BODY_TO_HEADER(ObjectBody) \ ((PUSER_OBJECT_HEADER)(((PUSER_OBJECT_HEADER)ObjectBody) - 1)) /* FUNCTIONS *****************************************************************/ @@ -125,7 +125,7 @@ ObmpCloseAllHandles(PUSER_HANDLE_TABLE HandleTable) if (ObjectBody != NULL) { - PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); ObmReferenceObjectByPointer(ObjectBody, otUnknown); ObjectHeader->HandleCount--; @@ -191,7 +191,7 @@ ObmpDeleteHandle(PUSER_HANDLE_TABLE HandleTable, if (ObjectBody != NULL) { - ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); ObjectHeader->HandleCount--; ObmReferenceObjectByPointer(ObjectBody, otUnknown); Entry->ObjectBody = NULL; @@ -219,7 +219,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable, if (Handle != NULL) { Status = ObmCreateHandle(HandleTable, - HEADER_TO_BODY(ObjectHeader), + USER_HEADER_TO_BODY(ObjectHeader), Handle); } @@ -230,7 +230,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable, ULONG FASTCALL ObmGetReferenceCount(PVOID ObjectBody) { - PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); return ObjectHeader->RefCount; } @@ -238,7 +238,7 @@ ObmGetReferenceCount(PVOID ObjectBody) ULONG FASTCALL ObmGetHandleCount(PVOID ObjectBody) { - PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); return ObjectHeader->HandleCount; } @@ -260,7 +260,7 @@ ObmReferenceObject(PVOID ObjectBody) return; } - ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); ObjectHeader->RefCount++; @@ -284,7 +284,7 @@ ObmDereferenceObject(PVOID ObjectBody) return; } - ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); ObjectHeader->RefCount--; ObmpPerformRetentionChecks(ObjectHeader); @@ -303,7 +303,7 @@ ObmReferenceObjectByPointer(PVOID ObjectBody, { PUSER_OBJECT_HEADER ObjectHeader; - ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType)) { @@ -331,7 +331,7 @@ ObmCreateObject(PUSER_HANDLE_TABLE HandleTable, return NULL; } - ObjectBody = HEADER_TO_BODY(ObjectHeader); + ObjectBody = USER_HEADER_TO_BODY(ObjectHeader); RtlZeroMemory(ObjectBody, ObjectSize); @@ -369,7 +369,7 @@ ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable, if (ObjectBody != NULL) { - BODY_TO_HEADER(ObjectBody)->HandleCount++; + USER_BODY_TO_HEADER(ObjectBody)->HandleCount++; } ObmpLockHandleTable(HandleTable); @@ -456,7 +456,7 @@ ObmReferenceObjectByHandle(PUSER_HANDLE_TABLE HandleTable, ObmpUnlockHandleTable(HandleTable); - ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader = USER_BODY_TO_HEADER(ObjectBody); if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType)) {