* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: handle.c,v 1.60 2004/09/13 14:43:50 ekohl Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
#define NDEBUG
#include <internal/debug.h>
-/* TYPES *******************************************************************/
+#define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
-/*
- * 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))
+/* GLOBALS *****************************************************************/
-#define OB_HANDLE_FLAG_MASK 0x00000007
-#define OB_HANDLE_FLAG_AUDIT 0x00000004
-#define OB_HANDLE_FLAG_PROTECT 0x00000002
-#define OB_HANDLE_FLAG_INHERIT 0x00000001
+PHANDLE_TABLE ObpKernelHandleTable = NULL;
-#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')
+/* TEMPORARY HACK. DO NOT REMOVE -- Alex */
+NTSTATUS
+STDCALL
+ExpDesktopCreate(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ POBJECT_CREATE_INFORMATION ObjectCreateInformation);
/* 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)
+static 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);
+ DPRINT("Header: %x\n", ObjectHeader);
+ DPRINT("NewHandleCount: %x\n", NewHandleCount);
+ DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader));
+
+ if ((ObjectHeader->Type != NULL) &&
+ (ObjectHeader->Type->TypeInfo.CloseProcedure != NULL))
+ {
+ /* the handle count should be decremented but we pass the previous value
+ to the callback */
+ ObjectHeader->Type->TypeInfo.CloseProcedure(ObjectBody, NewHandleCount + 1);
+ }
+
+ if(NewHandleCount == 0)
+ {
+ if(HEADER_TO_OBJECT_NAME(ObjectHeader) &&
+ HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory != NULL &&
+ !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
+ {
+ /* delete the object from the namespace when the last handle got closed.
+ Only do this if it's actually been inserted into the namespace and
+ if it's not a permanent object. */
+ ObpRemoveEntryDirectory(ObjectHeader);
+ }
+
+ /* remove the keep-alive reference */
+ ObDereferenceObject(ObjectBody);
+ }
}
NTSTATUS
+NTAPI
ObpQueryHandleAttributes(HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
{
- PEPROCESS Process;
- KIRQL oldIrql;
- PHANDLE_ENTRY HandleEntry;
+ PHANDLE_TABLE HandleTable;
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+
+ PAGED_CODE();
DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
- Process = PsGetCurrentProcess();
+ if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+ {
+ HandleTable = ObpKernelHandleTable;
+ Handle = ObKernelHandleToHandle(Handle);
+ }
+ else
+ {
+ HandleTable = PsGetCurrentProcess()->ObjectTable;
+ }
+
+ KeEnterCriticalRegion();
- KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL)
+ HandleTableEntry = ExMapHandleToPointer(HandleTable,
+ Handle);
+ 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;
+
+ ExUnlockHandleTableEntry(HandleTable,
+ HandleTableEntry);
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+ KeLeaveCriticalRegion();
return STATUS_SUCCESS;
}
NTSTATUS
+NTAPI
ObpSetHandleAttributes(HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
{
- PHANDLE_ENTRY HandleEntry;
- PEPROCESS Process;
- KIRQL oldIrql;
+ PHANDLE_TABLE HandleTable;
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
- DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
+ PAGED_CODE();
- Process = PsGetCurrentProcess();
+ DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle);
+
+ if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+ {
+ HandleTable = ObpKernelHandleTable;
+ Handle = ObKernelHandleToHandle(Handle);
+ }
+ else
+ {
+ HandleTable = PsGetCurrentProcess()->ObjectTable;
+ }
+
+ KeEnterCriticalRegion();
- KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL)
+ HandleTableEntry = ExMapHandleToPointer(HandleTable,
+ Handle);
+ 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(HandleTable,
+ HandleTableEntry);
+
+ KeLeaveCriticalRegion();
return STATUS_SUCCESS;
}
+static NTSTATUS
+ObpDeleteHandle(PHANDLE_TABLE HandleTable,
+ HANDLE Handle)
+{
+ PHANDLE_TABLE_ENTRY HandleEntry;
+ PVOID Body;
+ POBJECT_HEADER ObjectHeader;
+
+ PAGED_CODE();
+
+ DPRINT("ObpDeleteHandle(Handle %x)\n",Handle);
+
+ KeEnterCriticalRegion();
+
+ HandleEntry = ExMapHandleToPointer(HandleTable,
+ Handle);
+ if(HandleEntry != NULL)
+ {
+ if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
+ {
+ ExUnlockHandleTableEntry(HandleTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_HANDLE_NOT_CLOSABLE;
+ }
+
+ ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+ Body = &ObjectHeader->Body;
+
+ ObpDecrementHandleCount(Body);
+
+ /* destroy and unlock the handle entry */
+ ExDestroyHandleByEntry(HandleTable,
+ HandleEntry,
+ Handle);
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_SUCCESS;
+ }
+ KeLeaveCriticalRegion();
+ return STATUS_INVALID_HANDLE;
+}
+
+
NTSTATUS
+NTAPI
ObDuplicateObject(PEPROCESS SourceProcess,
PEPROCESS TargetProcess,
HANDLE SourceHandle,
BOOLEAN InheritHandle,
ULONG Options)
{
- KIRQL oldIrql;
- PHANDLE_ENTRY SourceHandleEntry;
+ PHANDLE_TABLE SourceHandleTable;
+ PHANDLE_TABLE_ENTRY SourceHandleEntry;
+ HANDLE_TABLE_ENTRY NewHandleEntry;
PVOID ObjectBody;
+ POBJECT_HEADER ObjectHeader;
+ ULONG NewHandleCount;
+ HANDLE NewTargetHandle;
+
+ PAGED_CODE();
+
+ if(ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
+ {
+ SourceHandleTable = ObpKernelHandleTable;
+ SourceHandle = ObKernelHandleToHandle(SourceHandle);
+ }
+ else
+ {
+ SourceHandleTable = SourceProcess->ObjectTable;
+ }
- KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
- SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable,
- SourceHandle,
- NULL);
+ KeEnterCriticalRegion();
+
+ SourceHandleEntry = ExMapHandleToPointer(SourceHandleTable,
+ SourceHandle);
if (SourceHandleEntry == NULL)
{
- KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
+ KeLeaveCriticalRegion();
return STATUS_INVALID_HANDLE;
}
- ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody);
- ObReferenceObjectByPointer(ObjectBody,
- 0,
- NULL,
- UserMode);
-
+ ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
+ ObjectBody = &ObjectHeader->Body;
+
+ 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)
+ {
+ NewHandleEntry.u2.GrantedAccess = SourceHandleEntry->u2.GrantedAccess;
+ }
+ else
+ {
+ if (DesiredAccess & GENERIC_ANY)
{
- DesiredAccess = SourceHandleEntry->GrantedAccess;
+ RtlMapGenericMask(&DesiredAccess,
+ &ObjectHeader->Type->TypeInfo.GenericMapping);
}
-
- KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
- ObCreateHandle(TargetProcess,
- ObjectBody,
- DesiredAccess,
- InheritHandle,
- TargetHandle);
-
- if (Options & DUPLICATE_CLOSE_SOURCE)
+ NewHandleEntry.u2.GrantedAccess = DesiredAccess;
+ }
+
+ /* reference the object so it doesn't get deleted after releasing the lock
+ and before creating a new handle for it */
+ ObReferenceObject(ObjectBody);
+
+ /* 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. */
+ NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount);
+ ASSERT(NewHandleCount >= 2);
+
+ ExUnlockHandleTableEntry(SourceHandleTable,
+ SourceHandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ /* attempt to create the new handle */
+ NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
+ &NewHandleEntry);
+ if (NewTargetHandle != NULL)
+ {
+ if (Options & DUPLICATE_CLOSE_SOURCE)
{
- ZwClose(SourceHandle);
+ ObpDeleteHandle(SourceHandleTable,
+ SourceHandle);
}
- ObDereferenceObject(ObjectBody);
+ ObDereferenceObject(ObjectBody);
- return STATUS_SUCCESS;
+ *TargetHandle = NewTargetHandle;
+
+ 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;
+ }
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS STDCALL
NtDuplicateObject (IN HANDLE SourceProcessHandle,
IN HANDLE SourceHandle,
IN HANDLE TargetProcessHandle,
- OUT PHANDLE UnsafeTargetHandle,
+ OUT PHANDLE TargetHandle OPTIONAL,
IN ACCESS_MASK DesiredAccess,
- IN BOOLEAN InheritHandle,
- ULONG Options)
+ IN ULONG InheritHandle,
+ IN ULONG Options)
/*
* FUNCTION: Copies a handle from one process space to another
* ARGUMENTS:
- * SourceProcessHandle = The source process owning the handle. The
+ * SourceProcessHandle = The source process owning the handle. The
* source process should have opened
- * the SourceHandle with PROCESS_DUP_HANDLE
+ * the SourceHandle with PROCESS_DUP_HANDLE
* access.
* SourceHandle = The handle to the object.
- * TargetProcessHandle = The destination process owning the handle
- * TargetHandle (OUT) = Caller should supply storage for the
- * duplicated handle.
+ * TargetProcessHandle = The destination process owning the handle
+ * TargetHandle (OUT) = Caller should supply storage for the
+ * duplicated handle.
* DesiredAccess = The desired access to the handle.
* InheritHandle = Indicates wheter the new handle will be inheritable
* or not.
- * Options = Specifies special actions upon duplicating the handle.
- * Can be one of the values DUPLICATE_CLOSE_SOURCE |
- * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
- * that the source handle should be closed after duplicating.
- * DUPLICATE_SAME_ACCESS specifies to ignore the
- * DesiredAccess paramter and just grant the same access to
+ * Options = Specifies special actions upon duplicating the handle.
+ * Can be one of the values DUPLICATE_CLOSE_SOURCE |
+ * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
+ * that the source handle should be closed after duplicating.
+ * DUPLICATE_SAME_ACCESS specifies to ignore the
+ * DesiredAccess paramter and just grant the same access to
* the new handle.
* RETURNS: Status
* REMARKS: This function maps to the win32 DuplicateHandle.
{
PEPROCESS SourceProcess;
PEPROCESS TargetProcess;
- PHANDLE_ENTRY SourceHandleEntry;
- KIRQL oldIrql;
- PVOID ObjectBody;
- HANDLE TargetHandle;
- NTSTATUS Status;
-
- ASSERT_IRQL(PASSIVE_LEVEL);
-
+ HANDLE hTarget;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(TargetHandle != NULL && PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(TargetHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
Status = ObReferenceObjectByHandle(SourceProcessHandle,
PROCESS_DUP_HANDLE,
NULL,
- UserMode,
+ PreviousMode,
(PVOID*)&SourceProcess,
NULL);
if (!NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle(TargetProcessHandle,
PROCESS_DUP_HANDLE,
NULL,
- UserMode,
+ PreviousMode,
(PVOID*)&TargetProcess,
NULL);
if (!NT_SUCCESS(Status))
}
/* Check for magic handle first */
- if (SourceHandle == NtCurrentThread())
+ if (SourceHandle == NtCurrentThread() ||
+ SourceHandle == NtCurrentProcess())
{
- ObReferenceObjectByHandle(SourceHandle,
- PROCESS_DUP_HANDLE,
- NULL,
- UserMode,
- &ObjectBody,
- NULL);
-
- ObCreateHandle(TargetProcess,
- ObjectBody,
- THREAD_ALL_ACCESS,
- InheritHandle,
- &TargetHandle);
- }
- 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);
- if (!((ULONG_PTR)SourceHandleEntry->ObjectBody & OB_HANDLE_FLAG_INHERIT))
+ PVOID ObjectBody;
+ POBJECT_TYPE ObjectType;
+
+ ObjectType = (SourceHandle == NtCurrentThread()) ? PsThreadType : PsProcessType;
+
+ Status = ObReferenceObjectByHandle(SourceHandle,
+ 0,
+ ObjectType,
+ PreviousMode,
+ &ObjectBody,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ if (Options & DUPLICATE_SAME_ACCESS)
+ {
+ /* grant all access rights */
+ DesiredAccess = ((ObjectType == PsThreadType) ? THREAD_ALL_ACCESS : PROCESS_ALL_ACCESS);
+ }
+ else
+ {
+ if (DesiredAccess & GENERIC_ANY)
+ {
+ RtlMapGenericMask(&DesiredAccess,
+ &ObjectType->TypeInfo.GenericMapping);
+ }
+ }
+ Status = ObpCreateHandle(TargetProcess,
+ ObjectBody,
+ DesiredAccess,
+ InheritHandle,
+ &hTarget);
+
+ ObDereferenceObject(ObjectBody);
+
+ if (Options & DUPLICATE_CLOSE_SOURCE)
{
- ObDereferenceObject(TargetProcess);
- ObDereferenceObject(SourceProcess);
- ObDereferenceObject(ObjectBody);
- return STATUS_INVALID_HANDLE;
- }
- ObCreateHandle(TargetProcess,
- ObjectBody,
- DesiredAccess,
- InheritHandle,
- &TargetHandle);
+ ObpDeleteHandle(SourceProcess->ObjectTable,
+ SourceHandle);
+ }
+ }
}
-
- if (Options & DUPLICATE_CLOSE_SOURCE)
+ else
{
- ZwClose(SourceHandle);
+ Status = ObDuplicateObject(SourceProcess,
+ TargetProcess,
+ SourceHandle,
+ &hTarget,
+ DesiredAccess,
+ InheritHandle,
+ Options);
}
-
+
ObDereferenceObject(TargetProcess);
ObDereferenceObject(SourceProcess);
- ObDereferenceObject(ObjectBody);
-
- Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
- if (!NT_SUCCESS(Status))
+
+ if(NT_SUCCESS(Status) && TargetHandle != NULL)
+ {
+ _SEH_TRY
{
- return(Status);
+ *TargetHandle = hTarget;
}
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
- return(STATUS_SUCCESS);
+ return Status;
}
-VOID ObCloseAllHandles(PEPROCESS Process)
+static VOID STDCALL
+DeleteHandleCallback(PHANDLE_TABLE HandleTable,
+ PVOID Object,
+ ULONG GrantedAccess,
+ PVOID Context)
{
- KIRQL oldIrql;
- PHANDLE_TABLE HandleTable;
- PLIST_ENTRY current_entry;
- PHANDLE_BLOCK current;
- ULONG i;
- PVOID ObjectBody;
-
- DPRINT("ObCloseAllHandles(Process %x)\n", Process);
-
- HandleTable = &Process->HandleTable;
-
- KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-
- current_entry = HandleTable->ListHead.Flink;
-
- while (current_entry != &HandleTable->ListHead)
- {
- current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
-
- for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
- {
- ObjectBody = OB_ENTRY_TO_POINTER(current->handles[i].ObjectBody);
-
- if (ObjectBody != NULL)
- {
- POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-
- if (Header->ObjectType == PsProcessType ||
- Header->ObjectType == PsThreadType)
- {
- DPRINT("Deleting handle to %x\n", ObjectBody);
- }
-
- 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 = &ObjectHeader->Body;
+
+ ObpDecrementHandleCount(ObjectBody);
}
-VOID ObDeleteHandleTable(PEPROCESS Process)
-/*
- * FUNCTION: Deletes the handle table associated with a process
- */
+static BOOLEAN STDCALL
+DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
+ PHANDLE_TABLE_ENTRY HandleTableEntry,
+ PVOID Context)
{
- 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);
- }
-}
+ 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)
+ {
+ ObReferenceObject(&ObjectHeader->Body);
+ }
+ }
+ return Ret;
+}
-VOID ObCreateHandleTable(PEPROCESS Parent,
+VOID
+NTAPI
+ObCreateHandleTable(PEPROCESS Parent,
BOOLEAN Inherit,
PEPROCESS Process)
/*
* Process = Process whose handle table is to be created
*/
{
- PHANDLE_TABLE ParentHandleTable, HandleTable;
- KIRQL oldIrql;
- PLIST_ENTRY parent_current;
- ULONG i;
- PHANDLE_BLOCK current_block, new_block;
+ PAGED_CODE();
DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
Parent,Inherit,Process);
-
- InitializeListHead(&(Process->HandleTable.ListHead));
- KeInitializeSpinLock(&(Process->HandleTable.ListLock));
-
- if (Parent != NULL)
- {
- ParentHandleTable = &Parent->HandleTable;
- HandleTable = &Process->HandleTable;
-
- KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
- KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock);
-
- parent_current = ParentHandleTable->ListHead.Flink;
-
- while (parent_current != &ParentHandleTable->ListHead)
- {
- current_block = CONTAINING_RECORD(parent_current,
- HANDLE_BLOCK,
- entry);
- new_block = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(HANDLE_BLOCK),
- TAG_HANDLE_TABLE);
- if (new_block == NULL)
- {
- break;
- }
- RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK));
-
- for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
- {
- if (current_block->handles[i].ObjectBody)
- {
- if ((ULONG_PTR)current_block->handles[i].ObjectBody & OB_HANDLE_FLAG_INHERIT)
- {
- new_block->handles[i].ObjectBody =
- current_block->handles[i].ObjectBody;
- new_block->handles[i].GrantedAccess =
- current_block->handles[i].GrantedAccess;
- InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block->handles[i].ObjectBody))->HandleCount));
- }
- }
- }
- InsertTailList(&Process->HandleTable.ListHead, &new_block->entry);
- parent_current = parent_current->Flink;
- }
- KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock);
- KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
- }
+ if(Parent != NULL)
+ {
+ Process->ObjectTable = ExDupHandleTable(Process,
+ DuplicateHandleCallback,
+ NULL,
+ Parent->ObjectTable);
+ }
+ else
+ {
+ Process->ObjectTable = ExCreateHandleTable(Process);
+ }
}
-NTSTATUS
-ObDeleteHandle(PEPROCESS Process,
- HANDLE Handle,
- PVOID *ObjectBody)
+VOID
+STDCALL
+ObKillProcess(PEPROCESS Process)
{
- PHANDLE_ENTRY HandleEntry;
- PVOID Body;
- KIRQL oldIrql;
- PHANDLE_TABLE HandleTable;
- POBJECT_HEADER Header;
- HANDLE_BLOCK *Block;
-
- DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
-
- HandleTable = &Process->HandleTable;
-
- KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-
- HandleEntry = ObpGetObjectByHandle(HandleTable, Handle, &Block);
- if (HandleEntry == NULL)
- {
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- *ObjectBody = NULL;
- return STATUS_INVALID_HANDLE;
- }
-
- if ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT)
- {
- KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
- *ObjectBody = NULL;
- return STATUS_HANDLE_NOT_CLOSABLE;
- }
-
- Body = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody);
- DPRINT("ObjectBody %x\n", Body);
- if (Body == NULL)
- {
- 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);
+ PAGED_CODE();
- if ((Header->ObjectType != NULL) &&
- (Header->ObjectType->Close != NULL))
- {
- Header->ObjectType->Close(Body, Header->HandleCount);
- }
-
- *ObjectBody = Body;
-
- DPRINT("Finished ObDeleteHandle()\n");
-
- return STATUS_SUCCESS;
+ ExDestroyHandleTable(Process->ObjectTable,
+ DeleteHandleCallback,
+ Process);
}
NTSTATUS
-ObCreateHandle(PEPROCESS Process,
+NTAPI
+ObpCreateHandle(PEPROCESS Process,
PVOID ObjectBody,
ACCESS_MASK GrantedAccess,
BOOLEAN Inherit,
* 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;
+ HANDLE Handle;
+
+ PAGED_CODE();
- DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
+ DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
- assert(Process);
+ ASSERT(Process);
+ ASSERT(ObjectBody);
+
+ ObjectHeader = BODY_TO_HEADER(ObjectBody);
- if (ObjectBody != NULL)
+ ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
+
+ if (GrantedAccess & MAXIMUM_ALLOWED)
{
- InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
+ GrantedAccess &= ~MAXIMUM_ALLOWED;
+ GrantedAccess |= GENERIC_ALL;
}
- 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))
+
+ if (GrantedAccess & GENERIC_ANY)
{
- HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
+ RtlMapGenericMask(&GrantedAccess,
+ &ObjectHeader->Type->TypeInfo.GenericMapping);
+ }
- DPRINT("Current %x\n",current);
+ 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;
+
+ Handle = ExCreateHandle(Process->ObjectTable,
+ &NewEntry);
+ DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader, Handle, Process->ObjectTable);
+ if(Handle != NULL)
+ {
+ if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+ {
+ ObReferenceObjectByPointer(ObjectBody,
+ 0,
+ NULL,
+ UserMode);
+ }
- if (blk->allocation_count == HANDLE_BLOCK_ENTRIES)
- {
- handle = handle + HANDLE_BLOCK_ENTRIES;
- current = current->Flink;
- continue;
- }
+ *HandleReturn = Handle;
- 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;
- }
+ return STATUS_SUCCESS;
+ }
- /*
- * 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;
}
ObQueryObjectAuditingByHandle(IN HANDLE Handle,
OUT PBOOLEAN GenerateOnClose)
{
+ PHANDLE_TABLE_ENTRY HandleEntry;
PEPROCESS Process;
- KIRQL oldIrql;
- PHANDLE_ENTRY HandleEntry;
+
+ PAGED_CODE();
DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
Process = PsGetCurrentProcess();
- KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL)
- {
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
- return STATUS_INVALID_HANDLE;
- }
+ KeEnterCriticalRegion();
- *GenerateOnClose = (BOOLEAN)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_AUDIT);
+ HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+ Handle);
+ if(HandleEntry != NULL)
+ {
+ *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
- KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
- return STATUS_SUCCESS;
+ KeLeaveCriticalRegion();
+
+ return STATUS_SUCCESS;
+ }
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_INVALID_HANDLE;
}
/*
- * @implemented
- */
-NTSTATUS STDCALL
-ObReferenceObjectByHandle(HANDLE Handle,
- ACCESS_MASK DesiredAccess,
- POBJECT_TYPE ObjectType,
- KPROCESSOR_MODE AccessMode,
- PVOID* Object,
- POBJECT_HANDLE_INFORMATION HandleInformation)
-/*
- * FUNCTION: Increments the reference count for an object and returns a
+ * FUNCTION: Increments the reference count for an object and returns a
* pointer to its body
* ARGUMENTS:
* Handle = Handle for the object
* DesiredAccess = Desired access to the object
* ObjectType
- * AccessMode
+ * AccessMode
* Object (OUT) = Points to the object body on return
- * HandleInformation (OUT) = Contains information about the handle
+ * HandleInformation (OUT) = Contains information about the handle
* on return
* RETURNS: Status
+ *
+ * @implemented
*/
+NTSTATUS STDCALL
+ObReferenceObjectByHandle(HANDLE Handle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_TYPE ObjectType,
+ KPROCESSOR_MODE AccessMode,
+ PVOID* Object,
+ POBJECT_HANDLE_INFORMATION HandleInformation)
{
- PHANDLE_ENTRY HandleEntry;
+ PHANDLE_TABLE_ENTRY HandleEntry;
POBJECT_HEADER ObjectHeader;
- KIRQL oldIrql;
+ PHANDLE_TABLE HandleTable;
PVOID ObjectBody;
ACCESS_MASK GrantedAccess;
ULONG Attributes;
- NTSTATUS Status;
-
- ASSERT_IRQL(PASSIVE_LEVEL);
-
+
+ PAGED_CODE();
+
DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
"ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
ObjectType,AccessMode,Object);
+ if (Handle == NULL)
+ {
+ return STATUS_INVALID_HANDLE;
+ }
/*
* Handle special handle names
*/
- if (Handle == NtCurrentProcess() &&
+ if (Handle == NtCurrentProcess() &&
(ObjectType == PsProcessType || ObjectType == NULL))
{
- DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
-
- Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
- PROCESS_ALL_ACCESS,
- PsProcessType,
- UserMode);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ PEPROCESS CurrentProcess = PsGetCurrentProcess();
+
+ ObReferenceObject(CurrentProcess);
if (HandleInformation != NULL)
{
- HandleInformation->HandleAttributes = 0; /* FIXME? */
+ HandleInformation->HandleAttributes = 0;
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
}
- *Object = PsGetCurrentProcess();
- DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
+ *Object = CurrentProcess;
+ DPRINT("Referencing current process %x\n", CurrentProcess);
return STATUS_SUCCESS;
}
else if (Handle == NtCurrentProcess())
return(STATUS_OBJECT_TYPE_MISMATCH);
}
- if (Handle == NtCurrentThread() &&
+ if (Handle == NtCurrentThread() &&
(ObjectType == PsThreadType || ObjectType == NULL))
{
- Status = ObReferenceObjectByPointer(PsGetCurrentThread(),
- THREAD_ALL_ACCESS,
- PsThreadType,
- UserMode);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ PETHREAD CurrentThread = PsGetCurrentThread();
+
+ ObReferenceObject(CurrentThread);
if (HandleInformation != NULL)
{
- HandleInformation->HandleAttributes = 0; /* FIXME? */
+ HandleInformation->HandleAttributes = 0;
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
}
- *Object = PsGetCurrentThread();
+ *Object = CurrentThread;
CHECKPOINT;
return STATUS_SUCCESS;
}
CHECKPOINT;
return(STATUS_OBJECT_TYPE_MISMATCH);
}
-
- KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
- &oldIrql);
- HandleEntry = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
- Handle,
- NULL);
- if (HandleEntry == NULL || HandleEntry->ObjectBody == 0)
+
+ /* desire as much access rights as possible */
+ if (DesiredAccess & MAXIMUM_ALLOWED)
{
- KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
- oldIrql);
- return(STATUS_INVALID_HANDLE);
+ DesiredAccess &= ~MAXIMUM_ALLOWED;
+ DesiredAccess |= GENERIC_ALL;
}
- ObjectBody = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody);
- DPRINT("ObjectBody %p\n",ObjectBody);
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
- DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
- 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);
- if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
+ if(ObIsKernelHandle(Handle, AccessMode))
+ {
+ HandleTable = ObpKernelHandleTable;
+ Handle = ObKernelHandleToHandle(Handle);
+ }
+ else
+ {
+ HandleTable = PsGetCurrentProcess()->ObjectTable;
+ }
+
+ KeEnterCriticalRegion();
+
+ HandleEntry = ExMapHandleToPointer(HandleTable,
+ Handle);
+ if (HandleEntry == NULL)
{
- CHECKPOINT;
- return(STATUS_OBJECT_TYPE_MISMATCH);
+ KeLeaveCriticalRegion();
+ DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle);
+ return(STATUS_INVALID_HANDLE);
}
-
- if (ObjectHeader->ObjectType == PsProcessType)
+
+ ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+ ObjectBody = &ObjectHeader->Body;
+
+ DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, HandleTable);
+
+ if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
{
- DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
+ DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
+
+ ExUnlockHandleTableEntry(HandleTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ return(STATUS_OBJECT_TYPE_MISMATCH);
}
-
- if (DesiredAccess && AccessMode == UserMode)
+
+ /* map the generic access masks if the caller asks for generic access */
+ if (DesiredAccess & GENERIC_ANY)
{
- RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping);
+ RtlMapGenericMask(&DesiredAccess,
+ &BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
+ }
- if (!(GrantedAccess & DesiredAccess) &&
- !((~GrantedAccess) & DesiredAccess))
- {
- CHECKPOINT;
- return(STATUS_ACCESS_DENIED);
- }
+ GrantedAccess = HandleEntry->u2.GrantedAccess;
+
+ /* Unless running as KernelMode, deny access if caller desires more access
+ rights than the handle can grant */
+ if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
+ {
+ ExUnlockHandleTableEntry(HandleTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess, ~GrantedAccess, DesiredAccess, ~GrantedAccess & DesiredAccess);
+
+ return(STATUS_ACCESS_DENIED);
}
+ ObReferenceObject(ObjectBody);
+
+ Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
+ EX_HANDLE_ENTRY_INHERITABLE |
+ EX_HANDLE_ENTRY_AUDITONCLOSE);
+
+ ExUnlockHandleTableEntry(HandleTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
if (HandleInformation != NULL)
{
HandleInformation->HandleAttributes = Attributes;
}
*Object = ObjectBody;
-
- CHECKPOINT;
+
return(STATUS_SUCCESS);
}
/**********************************************************************
* NAME EXPORTED
* NtClose
- *
+ *
* DESCRIPTION
* Closes a handle reference to an object.
- *
+ *
* ARGUMENTS
* Handle
* Handle to close.
- *
+ *
* RETURN VALUE
* Status.
*
NTSTATUS STDCALL
NtClose(IN HANDLE Handle)
{
- PVOID ObjectBody;
- POBJECT_HEADER Header;
+ PHANDLE_TABLE HandleTable;
NTSTATUS Status;
-
- ASSERT_IRQL(PASSIVE_LEVEL);
-
- DPRINT("NtClose(Handle %x)\n",Handle);
-
- Status = ObDeleteHandle(PsGetCurrentProcess(),
- Handle,
- &ObjectBody);
+
+ PAGED_CODE();
+
+ if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+ {
+ HandleTable = ObpKernelHandleTable;
+ Handle = ObKernelHandleToHandle(Handle);
+ }
+ else
+ {
+ HandleTable = PsGetCurrentProcess()->ObjectTable;
+ }
+
+ Status = ObpDeleteHandle(HandleTable,
+ Handle);
if (!NT_SUCCESS(Status))
{
- if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort)
+ if((ExGetPreviousMode() != KernelMode) &&
+ (PsGetCurrentProcess()->ExceptionPort))
+ {
KeRaiseUserException(Status);
+ }
return Status;
}
-
- Header = BODY_TO_HEADER(ObjectBody);
-
- DPRINT("Dereferencing %x\n", ObjectBody);
- ObDereferenceObject(ObjectBody);
-
+
return(STATUS_SUCCESS);
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
ObInsertObject(IN PVOID Object,
- IN PACCESS_STATE PassedAccessState OPTIONAL,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG AdditionalReferences,
- OUT PVOID* ReferencedObject OPTIONAL,
- OUT PHANDLE Handle)
+ IN PACCESS_STATE PassedAccessState OPTIONAL,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG AdditionalReferences,
+ OUT PVOID* ReferencedObject OPTIONAL,
+ OUT PHANDLE Handle)
{
- POBJECT_HEADER ObjectHeader;
- ACCESS_MASK Access;
+ POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ POBJECT_HEADER Header;
+ POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+ PVOID FoundObject = NULL;
+ POBJECT_HEADER FoundHeader = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ UNICODE_STRING RemainingPath;
+ BOOLEAN ObjectAttached = FALSE;
+ PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
+
+ PAGED_CODE();
+
+ /* Get the Header and Create Info */
+ DPRINT("ObInsertObject: %x\n", Object);
+ Header = BODY_TO_HEADER(Object);
+ ObjectCreateInfo = Header->ObjectCreateInfo;
+ ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
+
+ /* First try to find the Object */
+ if (ObjectNameInfo && ObjectNameInfo->Name.Buffer)
+ {
+ DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo->Name);
+ Status = ObFindObject(ObjectCreateInfo,
+ &ObjectNameInfo->Name,
+ &FoundObject,
+ &RemainingPath,
+ NULL);
+ DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject, &RemainingPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status);
+ return Status;
+ }
+
+ if (FoundObject)
+ {
+ DPRINT("Getting header: %x\n", FoundObject);
+ FoundHeader = BODY_TO_HEADER(FoundObject);
+ }
+
+ if (FoundHeader && RemainingPath.Buffer == NULL)
+ {
+ DPRINT("Object exists\n");
+ ObDereferenceObject(FoundObject);
+ return STATUS_OBJECT_NAME_COLLISION;
+ }
+ }
+ else
+ {
+ DPRINT("No name, empty remaining path\n");
+ RtlInitUnicodeString(&RemainingPath, NULL);
+ }
- Access = DesiredAccess;
- ObjectHeader = BODY_TO_HEADER(Object);
+ if (FoundHeader && FoundHeader->Type == ObDirectoryType &&
+ RemainingPath.Buffer)
+ {
+ /* The name was changed so let's update it */
+ /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
+ PVOID NewName;
+ PWSTR BufferPos = RemainingPath.Buffer;
+ ULONG Delta = 0;
+
+ ObpAddEntryDirectory(FoundObject, Header, NULL);
+ ObjectAttached = TRUE;
+
+ ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
+
+ if (BufferPos[0] == L'\\')
+ {
+ BufferPos++;
+ Delta = sizeof(WCHAR);
+ }
+ NewName = ExAllocatePool(NonPagedPool, RemainingPath.MaximumLength - Delta);
+ RtlMoveMemory(NewName, BufferPos, RemainingPath.MaximumLength - Delta);
+ if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
+ ObjectNameInfo->Name.Buffer = NewName;
+ ObjectNameInfo->Name.Length = RemainingPath.Length - Delta;
+ ObjectNameInfo->Name.MaximumLength = RemainingPath.MaximumLength - Delta;
+ DPRINT("Name: %S\n", ObjectNameInfo->Name.Buffer);
+ }
- RtlMapGenericMask(&Access,
- ObjectHeader->ObjectType->Mapping);
+ if ((Header->Type == IoFileObjectType) ||
+ (Header->Type == ExDesktopObjectType) ||
+ (Header->Type->TypeInfo.OpenProcedure != NULL))
+ {
+ DPRINT("About to call Open Routine\n");
+ if (Header->Type == IoFileObjectType)
+ {
+ /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
+ DPRINT("Calling IopCreateFile: %x\n", FoundObject);
+ Status = IopCreateFile(&Header->Body,
+ FoundObject,
+ RemainingPath.Buffer,
+ ObjectCreateInfo);
+ DPRINT("Called IopCreateFile: %x\n", Status);
+
+ }
+ else if (Header->Type == ExDesktopObjectType)
+ {
+ /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
+ DPRINT("Calling ExpDesktopCreate\n");
+ Status = ExpDesktopCreate(&Header->Body,
+ FoundObject,
+ RemainingPath.Buffer,
+ ObjectCreateInfo);
+ }
+ else if (Header->Type->TypeInfo.OpenProcedure != NULL)
+ {
+ DPRINT("Calling %x\n", Header->Type->TypeInfo.OpenProcedure);
+ Status = Header->Type->TypeInfo.OpenProcedure(ObCreateHandle,
+ &Header->Body,
+ NULL,
+ 0,
+ 0);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Create Failed\n");
+ if (ObjectAttached == TRUE)
+ {
+ ObpRemoveEntryDirectory(Header);
+ }
+ if (FoundObject)
+ {
+ ObDereferenceObject(FoundObject);
+ }
+ RtlFreeUnicodeString(&RemainingPath);
+ return Status;
+ }
+ }
- return(ObCreateHandle(PsGetCurrentProcess(),
- Object,
- Access,
- ObjectHeader->Inherit,
- Handle));
+ RtlFreeUnicodeString(&RemainingPath);
+
+ DPRINT("Security Assignment in progress\n");
+ SeCaptureSubjectContext(&SubjectContext);
+
+ /* Build the new security descriptor */
+ Status = SeAssignSecurity((FoundHeader != NULL) ? FoundHeader->SecurityDescriptor : NULL,
+ (ObjectCreateInfo != NULL) ? ObjectCreateInfo->SecurityDescriptor : NULL,
+ &NewSecurityDescriptor,
+ (Header->Type == ObDirectoryType),
+ &SubjectContext,
+ &Header->Type->TypeInfo.GenericMapping,
+ PagedPool);
+
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor);
+
+ if (Header->Type->TypeInfo.SecurityProcedure != NULL)
+ {
+ /* Call the security method */
+ Status = Header->Type->TypeInfo.SecurityProcedure(&Header->Body,
+ AssignSecurityDescriptor,
+ 0,
+ NewSecurityDescriptor,
+ NULL,
+ NULL,
+ NonPagedPool,
+ NULL);
+ }
+ else
+ {
+ /* Assign the security descriptor to the object header */
+ Status = ObpAddSecurityDescriptor(NewSecurityDescriptor,
+ &Header->SecurityDescriptor);
+ DPRINT("Object security descriptor %p\n", Header->SecurityDescriptor);
+ }
+
+ /* Release the new security descriptor */
+ SeDeassignSecurity(&NewSecurityDescriptor);
+ }
+
+ DPRINT("Security Complete\n");
+ SeReleaseSubjectContext(&SubjectContext);
+
+ /* Create the Handle */
+ /* HACKHACK: Because of ROS's incorrect startup, this can be called
+ * without a valid Process until I finalize the startup patch,
+ * so don't create a handle if this is the case. We also don't create
+ * a handle if Handle is NULL when the Registry Code calls it, because
+ * the registry code totally bastardizes the Ob and needs to be fixed
+ */
+ DPRINT("Creating handle\n");
+ if (Handle != NULL)
+ {
+ Status = ObpCreateHandle(PsGetCurrentProcess(),
+ &Header->Body,
+ DesiredAccess,
+ ObjectCreateInfo->Attributes & OBJ_INHERIT,
+ Handle);
+ DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
+ *Handle, Header->PointerCount, Header->HandleCount);
+ }
+
+ /* We can delete the Create Info now */
+ Header->ObjectCreateInfo = NULL;
+ ObpReleaseCapturedAttributes(ObjectCreateInfo);
+ ExFreePool(ObjectCreateInfo);
+
+ DPRINT("Status %x\n", Status);
+ return Status;
}
ULONG
+NTAPI
ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
{
- PHANDLE_BLOCK blk;
- POBJECT_HEADER Header;
- PVOID ObjectBody;
- KIRQL OldIrql;
- PLIST_ENTRY current;
- ULONG i;
- ULONG Count=0;
+ return HandleTable->HandleCount;
+}
+
+/*
+ * FUNCTION: Searches the handle table of a specified process whether it contains a
+ * valid handle to the Object we're looking for. If not, it'll create one.
+ *
+ * NOTES:
+ * The parameters of this function is basically a mixture of some of the parameters
+ * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
+ * about what this function does (by it's name) makes clear what parameters it requires.
+ * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
+ * required at all as it only has influence on the object security. This function doesn't
+ * want to get access to an object, it just looks for a valid handle and if it can't find
+ * one, it'll just create one. It wouldn't make sense to check for security again as the
+ * caller already has a pointer to the object.
+ *
+ * A test on an XP machine shows that this prototype appears to be correct.
+ *
+ * ARGUMENTS:
+ * Process = This parameter simply describes in which handle table we're looking
+ * for a handle to the object.
+ * Object = The object pointer that we're looking for
+ * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
+ * ObReferenceObjectByPointer() provides.
+ * HandleInformation = This one has to be the opposite meaning of the usage in
+ * ObReferenceObjectByHandle(). If we actually found a valid
+ * handle in the table, we need to check against the information
+ * provided so we make sure this handle has all access rights
+ * (and attributes?!) we need. If they don't match, we can't
+ * use this handle and keep looking because the caller is likely
+ * to depend on these access rights.
+ * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
+ * find a suitable handle in the handle table, return this handle, if
+ * not, we'll just create one using ObCreateHandle() with all access
+ * rights the caller needs.
+ *
+ * RETURNS: Status
+ *
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+ObFindHandleForObject(IN PEPROCESS Process,
+ IN PVOID Object,
+ IN POBJECT_TYPE ObjectType,
+ IN POBJECT_HANDLE_INFORMATION HandleInformation,
+ OUT PHANDLE HandleReturn)
+{
+ DPRINT("ObFindHandleForObject is unimplemented!\n");
+ return STATUS_UNSUCCESSFUL;
+}
- KeAcquireSpinLock(&HandleTable->ListLock, &OldIrql);
+VOID
+ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
+ PEPROCESS Process,
+ int Count)
+{
+ ULONG P;
+// KIRQL 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. */
- if (Header->ObjectType != NULL)
- Count++;
- }
- }
-
- current = current->Flink;
- }
+// pshi->HandleValue;
+
+/*
+ This will never work with ROS! M$, I guess uses 0 -> 65535.
+ Ros uses 0 -> 4294967295!
+ */
+
+ P = (ULONG) Process->UniqueProcessId;
+ pshi->UniqueProcessId = (USHORT) P;
- KeReleaseSpinLock(&HandleTable->ListLock,
- OldIrql);
+// KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
- return Count;
+// pshi->GrantedAccess;
+// pshi->Object;
+// pshi->TypeIndex;
+// pshi->HandleAttributes;
+
+// KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
+
+ return;
}
+
+
/* EOF */