diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h
index 85babbeb6e2..703d81fbba1 100644
--- a/reactos/ntoskrnl/include/internal/ob.h
+++ b/reactos/ntoskrnl/include/internal/ob.h
@@ -9,7 +9,10 @@
#ifndef __INCLUDE_INTERNAL_OBJMGR_H
#define __INCLUDE_INTERNAL_OBJMGR_H
-struct _EPROCESS;
+#define GENERIC_ACCESS (GENERIC_READ | \
+ GENERIC_WRITE | \
+ GENERIC_EXECUTE | \
+ GENERIC_ALL)
#define BODY_TO_HEADER(objbdy) \
CONTAINING_RECORD((objbdy), OBJECT_HEADER, Body)
@@ -34,8 +37,12 @@ struct _EPROCESS;
#define ObMarkHandleAsKernelHandle(Handle) \
(HANDLE)((ULONG_PTR)(Handle) | KERNEL_HANDLE_FLAG)
-extern POBJECT_DIRECTORY NameSpaceRoot;
+extern KEVENT ObpDefaultObject;
+extern POBJECT_TYPE ObpTypeObjectType;
extern POBJECT_TYPE ObSymbolicLinkType;
+extern POBJECT_TYPE ObTypeObjectType;
+extern POBJECT_DIRECTORY NameSpaceRoot;
+extern POBJECT_DIRECTORY ObpTypeDirectoryObject;
extern PHANDLE_TABLE ObpKernelHandleTable;
typedef NTSTATUS
@@ -184,6 +191,12 @@ VOID
STDCALL
ObKillProcess(PEPROCESS Process);
+NTSTATUS
+ObpDeleteObjectDpcLevel(
+ IN POBJECT_HEADER ObjectHeader,
+ IN LONG OldPointerCount
+);
+
/* Security descriptor cache functions */
NTSTATUS
diff --git a/reactos/ntoskrnl/include/internal/tag.h b/reactos/ntoskrnl/include/internal/tag.h
index a7d96d472f7..1f0ebfb66e8 100644
--- a/reactos/ntoskrnl/include/internal/tag.h
+++ b/reactos/ntoskrnl/include/internal/tag.h
@@ -118,6 +118,9 @@
#define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T')
#define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T')
+/* Object Name Tag */
+#define OB_NAME_TAG TAG('O','b','N','m')
+
/* formerly located in ps/cid.c */
#define TAG_CIDOBJECT TAG('C', 'I', 'D', 'O')
diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild
index 881d76617e3..64a0454df12 100644
--- a/reactos/ntoskrnl/ntoskrnl.rbuild
+++ b/reactos/ntoskrnl/ntoskrnl.rbuild
@@ -265,11 +265,12 @@
elf64.c
- dirobj.c
- handle.c
- namespc.c
- ntobj.c
- object.c
+ obdir.c
+ obinit.c
+ obhandle.c
+ obname.c
+ oblife.c
+ obref.c
sdcache.c
security.c
symlink.c
diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c
deleted file mode 100644
index 1c012f27904..00000000000
--- a/reactos/ntoskrnl/ob/handle.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/*
- * ReactOS kernel
- * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ob/handle.c
- * PURPOSE: Managing handles
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * REVISION HISTORY:
- * 17/06/98: Created
- */
-
-/* INCLUDES ****************************************************************/
-
-#include
-#define NDEBUG
-#include
-
-#define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
-
-/* GLOBALS *****************************************************************/
-
-PHANDLE_TABLE ObpKernelHandleTable = NULL;
-
-/* TEMPORARY HACK. DO NOT REMOVE -- Alex */
-NTSTATUS
-STDCALL
-ExpDesktopCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_CREATE_INFORMATION ObjectCreateInformation);
-
-/* FUNCTIONS ***************************************************************/
-
-static VOID
-ObpDecrementHandleCount(PVOID ObjectBody)
-{
- POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
- LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
- OBP_LOOKUP_CONTEXT Context;
- 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(NULL, ObjectBody, 0, NewHandleCount + 1, 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. */
-
- /* Make sure it's still inserted */
- Context.Directory = HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory;
- Context.DirectoryLocked = TRUE;
- if (ObpLookupEntryDirectory(HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory,
- &HEADER_TO_OBJECT_NAME(ObjectHeader)->Name,
- 0,
- FALSE,
- &Context))
- {
- ObpDeleteEntryDirectory(&Context);
- }
- }
-
- /* remove the keep-alive reference */
- ObDereferenceObject(ObjectBody);
- }
-}
-
-
-NTSTATUS
-NTAPI
-ObpQueryHandleAttributes(HANDLE Handle,
- POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
-{
- PHANDLE_TABLE_ENTRY HandleTableEntry;
- PEPROCESS Process, CurrentProcess;
- KAPC_STATE ApcState;
- BOOLEAN AttachedToProcess = FALSE;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle);
- CurrentProcess = PsGetCurrentProcess();
-
- KeEnterCriticalRegion();
-
- if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
- {
- Process = PsInitialSystemProcess;
- Handle = ObKernelHandleToHandle(Handle);
-
- if (Process != CurrentProcess)
- {
- KeStackAttachProcess(&Process->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
- }
- else
- {
- Process = CurrentProcess;
- }
-
- HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
- Handle);
- if (HandleTableEntry != NULL)
- {
- HandleInfo->Inherit = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
- HandleInfo->ProtectFromClose = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
-
- ExUnlockHandleTableEntry(Process->ObjectTable,
- HandleTableEntry);
- }
- else
- Status = STATUS_INVALID_HANDLE;
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- KeLeaveCriticalRegion();
-
- return Status;
-}
-
-
-NTSTATUS
-NTAPI
-ObpSetHandleAttributes(HANDLE Handle,
- POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
-{
- PHANDLE_TABLE_ENTRY HandleTableEntry;
- PEPROCESS Process, CurrentProcess;
- KAPC_STATE ApcState;
- BOOLEAN AttachedToProcess = FALSE;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle);
- CurrentProcess = PsGetCurrentProcess();
-
- KeEnterCriticalRegion();
-
- if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
- {
- Process = PsInitialSystemProcess;
- Handle = ObKernelHandleToHandle(Handle);
-
- if (Process != CurrentProcess)
- {
- KeStackAttachProcess(&Process->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
- }
- else
- {
- Process = CurrentProcess;
- }
-
- HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
- Handle);
- if (HandleTableEntry != NULL)
- {
- if (HandleInfo->Inherit)
- HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
- else
- HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
-
- if (HandleInfo->ProtectFromClose)
- HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
- else
- HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
-
- /* FIXME: Do we need to set anything in the object header??? */
-
- ExUnlockHandleTableEntry(Process->ObjectTable,
- HandleTableEntry);
- }
- else
- Status = STATUS_INVALID_HANDLE;
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- KeLeaveCriticalRegion();
-
- return Status;
-}
-
-
-static NTSTATUS
-ObpDeleteHandle(HANDLE Handle)
-{
- PHANDLE_TABLE_ENTRY HandleEntry;
- PVOID Body;
- POBJECT_HEADER ObjectHeader;
- PHANDLE_TABLE ObjectTable;
-
- PAGED_CODE();
-
- DPRINT("ObpDeleteHandle(Handle %p)\n",Handle);
-
- ObjectTable = PsGetCurrentProcess()->ObjectTable;
-
- KeEnterCriticalRegion();
-
- HandleEntry = ExMapHandleToPointer(ObjectTable,
- Handle);
- if(HandleEntry != NULL)
- {
- if(HandleEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
- {
- ExUnlockHandleTableEntry(ObjectTable,
- HandleEntry);
-
- KeLeaveCriticalRegion();
-
- return STATUS_HANDLE_NOT_CLOSABLE;
- }
-
- ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
- Body = &ObjectHeader->Body;
-
- /* destroy and unlock the handle entry */
- ExDestroyHandleByEntry(ObjectTable,
- HandleEntry,
- Handle);
-
- ObpDecrementHandleCount(Body);
-
- KeLeaveCriticalRegion();
-
- return STATUS_SUCCESS;
- }
- KeLeaveCriticalRegion();
- return STATUS_INVALID_HANDLE;
-}
-
-
-NTSTATUS
-NTAPI
-ObDuplicateObject(PEPROCESS SourceProcess,
- PEPROCESS TargetProcess,
- HANDLE SourceHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG HandleAttributes,
- ULONG Options)
-{
- PHANDLE_TABLE_ENTRY SourceHandleEntry;
- HANDLE_TABLE_ENTRY NewHandleEntry;
- BOOLEAN AttachedToProcess = FALSE;
- PVOID ObjectBody;
- POBJECT_HEADER ObjectHeader;
- ULONG NewHandleCount;
- HANDLE NewTargetHandle;
- PEPROCESS CurrentProcess;
- KAPC_STATE ApcState;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- if(SourceProcess == NULL ||
- ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
- {
- SourceProcess = PsInitialSystemProcess;
- SourceHandle = ObKernelHandleToHandle(SourceHandle);
- }
-
- CurrentProcess = PsGetCurrentProcess();
-
- KeEnterCriticalRegion();
-
- if (SourceProcess != CurrentProcess)
- {
- KeStackAttachProcess(&SourceProcess->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
- SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
- SourceHandle);
- if (SourceHandleEntry == NULL)
- {
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- KeLeaveCriticalRegion();
- return STATUS_INVALID_HANDLE;
- }
-
- ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
- ObjectBody = &ObjectHeader->Body;
-
- NewHandleEntry.Object = SourceHandleEntry->Object;
- if(HandleAttributes & OBJ_INHERIT)
- NewHandleEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
- else
- NewHandleEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
- NewHandleEntry.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
- SourceHandleEntry->GrantedAccess :
- DesiredAccess);
- if (Options & DUPLICATE_SAME_ACCESS)
- {
- NewHandleEntry.GrantedAccess = SourceHandleEntry->GrantedAccess;
- }
- else
- {
- if (DesiredAccess & GENERIC_ANY)
- {
- RtlMapGenericMask(&DesiredAccess,
- &ObjectHeader->Type->TypeInfo.GenericMapping);
- }
- NewHandleEntry.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(SourceProcess->ObjectTable,
- SourceHandleEntry);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- AttachedToProcess = FALSE;
- }
-
- if (TargetProcess != CurrentProcess)
- {
- KeStackAttachProcess(&TargetProcess->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
-
- /* attempt to create the new handle */
- NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
- &NewHandleEntry);
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- AttachedToProcess = FALSE;
- }
-
- if (NewTargetHandle != NULL)
- {
- if (Options & DUPLICATE_CLOSE_SOURCE)
- {
- if (SourceProcess != CurrentProcess)
- {
- KeStackAttachProcess(&SourceProcess->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
-
- /* delete the source handle */
- ObpDeleteHandle(SourceHandle);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
- }
-
- ObDereferenceObject(ObjectBody);
-
- *TargetHandle = NewTargetHandle;
- }
- 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);
- Status = STATUS_UNSUCCESSFUL;
- }
-
- KeLeaveCriticalRegion();
-
- return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-NtDuplicateObject (IN HANDLE SourceProcessHandle,
- IN HANDLE SourceHandle,
- IN HANDLE TargetProcessHandle,
- OUT PHANDLE TargetHandle OPTIONAL,
- IN ACCESS_MASK DesiredAccess,
- IN ULONG HandleAttributes,
- IN ULONG Options)
-/*
- * FUNCTION: Copies a handle from one process space to another
- * ARGUMENTS:
- * SourceProcessHandle = The source process owning the handle. The
- * source process should have opened
- * 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.
- * DesiredAccess = The desired access to the handle.
- * HandleAttributes = The desired handle attributes.
- * 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;
- PEPROCESS CurrentProcess;
- HANDLE hTarget;
- BOOLEAN AttachedToProcess = FALSE;
- KPROCESSOR_MODE PreviousMode;
- KAPC_STATE ApcState;
- 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,
- PreviousMode,
- (PVOID*)&SourceProcess,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = ObReferenceObjectByHandle(TargetProcessHandle,
- PROCESS_DUP_HANDLE,
- NULL,
- PreviousMode,
- (PVOID*)&TargetProcess,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(SourceProcess);
- return(Status);
- }
-
- CurrentProcess = PsGetCurrentProcess();
-
- /* Check for magic handle first */
- if (SourceHandle == NtCurrentThread() ||
- SourceHandle == NtCurrentProcess())
- {
- 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);
- }
- }
-
- if (TargetProcess != CurrentProcess)
- {
- KeStackAttachProcess(&TargetProcess->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
-
- Status = ObpCreateHandle(ObjectBody,
- DesiredAccess,
- HandleAttributes,
- &hTarget);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- AttachedToProcess = FALSE;
- }
-
- ObDereferenceObject(ObjectBody);
-
- if (Options & DUPLICATE_CLOSE_SOURCE)
- {
- if (SourceProcess != CurrentProcess)
- {
- KeStackAttachProcess(&SourceProcess->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
-
- ObpDeleteHandle(SourceHandle);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
- }
- }
- }
- else
- {
- Status = ObDuplicateObject(SourceProcess,
- TargetProcess,
- SourceHandle,
- &hTarget,
- DesiredAccess,
- HandleAttributes,
- Options);
- }
-
- ObDereferenceObject(TargetProcess);
- ObDereferenceObject(SourceProcess);
-
- if(NT_SUCCESS(Status) && TargetHandle != NULL)
- {
- _SEH_TRY
- {
- *TargetHandle = hTarget;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
-
- return Status;
-}
-
-static VOID STDCALL
-SweepHandleCallback(PHANDLE_TABLE HandleTable,
- PVOID Object,
- ULONG GrantedAccess,
- PVOID Context)
-{
- POBJECT_HEADER ObjectHeader;
- PVOID ObjectBody;
-
- PAGED_CODE();
-
- ObjectHeader = EX_OBJ_TO_HDR(Object);
- ObjectBody = &ObjectHeader->Body;
-
- ObpDecrementHandleCount(ObjectBody);
-}
-
-static BOOLEAN STDCALL
-DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
- PHANDLE_TABLE_ENTRY HandleTableEntry,
- PVOID Context)
-{
- POBJECT_HEADER ObjectHeader;
- BOOLEAN Ret = FALSE;
-
- PAGED_CODE();
-
- Ret = (HandleTableEntry->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
-NTAPI
-ObCreateHandleTable(PEPROCESS Parent,
- BOOLEAN Inherit,
- PEPROCESS Process)
-/*
- * FUNCTION: Creates a handle table for a process
- * ARGUMENTS:
- * Parent = Parent process (or NULL if this is the first process)
- * Inherit = True if the process should inherit its parent's handles
- * Process = Process whose handle table is to be created
- */
-{
- PAGED_CODE();
-
- DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
- Parent,Inherit,Process);
- if(Parent != NULL)
- {
- Process->ObjectTable = ExDupHandleTable(Process,
- DuplicateHandleCallback,
- NULL,
- Parent->ObjectTable);
- }
- else
- {
- Process->ObjectTable = ExCreateHandleTable(Process);
- }
-}
-
-
-VOID
-STDCALL
-ObKillProcess(PEPROCESS Process)
-{
- PAGED_CODE();
-
- /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */
- ExSweepHandleTable(Process->ObjectTable,
- SweepHandleCallback,
- Process);
- ExDestroyHandleTable(Process->ObjectTable);
- Process->ObjectTable = NULL;
-}
-
-
-NTSTATUS
-NTAPI
-ObpCreateHandle(PVOID ObjectBody,
- ACCESS_MASK GrantedAccess,
- ULONG HandleAttributes,
- PHANDLE HandleReturn)
-/*
- * FUNCTION: Add a handle referencing an object
- * ARGUMENTS:
- * obj = Object body that the handle should refer to
- * RETURNS: The created handle
- * NOTE: The handle is valid only in the context of the current process
- */
-{
- HANDLE_TABLE_ENTRY NewEntry;
- PEPROCESS Process, CurrentProcess;
- POBJECT_HEADER ObjectHeader;
- HANDLE Handle;
- KAPC_STATE ApcState;
- BOOLEAN AttachedToProcess = FALSE;
-
- PAGED_CODE();
-
- DPRINT("ObpCreateHandle(obj %p)\n",ObjectBody);
-
- ASSERT(ObjectBody);
-
- CurrentProcess = PsGetCurrentProcess();
-
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
-
- /* check that this is a valid kernel pointer */
- ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
-
- if (GrantedAccess & MAXIMUM_ALLOWED)
- {
- GrantedAccess &= ~MAXIMUM_ALLOWED;
- GrantedAccess |= GENERIC_ALL;
- }
-
- if (GrantedAccess & GENERIC_ANY)
- {
- RtlMapGenericMask(&GrantedAccess,
- &ObjectHeader->Type->TypeInfo.GenericMapping);
- }
-
- NewEntry.Object = ObjectHeader;
- if(HandleAttributes & OBJ_INHERIT)
- NewEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
- else
- NewEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
- NewEntry.GrantedAccess = GrantedAccess;
-
- if ((HandleAttributes & OBJ_KERNEL_HANDLE) &&
- ExGetPreviousMode == KernelMode)
- {
- Process = PsInitialSystemProcess;
- if (Process != CurrentProcess)
- {
- KeStackAttachProcess(&Process->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
- }
- else
- {
- Process = CurrentProcess;
- /* mask out the OBJ_KERNEL_HANDLE attribute */
- HandleAttributes &= ~OBJ_KERNEL_HANDLE;
- }
-
- Handle = ExCreateHandle(Process->ObjectTable,
- &NewEntry);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- if(Handle != NULL)
- {
- if (HandleAttributes & OBJ_KERNEL_HANDLE)
- {
- /* mark the handle value */
- Handle = ObMarkHandleAsKernelHandle(Handle);
- }
-
- if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
- {
- ObReferenceObject(ObjectBody);
- }
-
- *HandleReturn = Handle;
-
- return STATUS_SUCCESS;
- }
-
- return STATUS_UNSUCCESSFUL;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-ObQueryObjectAuditingByHandle(IN HANDLE Handle,
- OUT PBOOLEAN GenerateOnClose)
-{
- PHANDLE_TABLE_ENTRY HandleEntry;
- PEPROCESS Process, CurrentProcess;
- KAPC_STATE ApcState;
- BOOLEAN AttachedToProcess = FALSE;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- DPRINT("ObQueryObjectAuditingByHandle(Handle %p)\n", Handle);
-
- CurrentProcess = PsGetCurrentProcess();
-
- KeEnterCriticalRegion();
-
- if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
- {
- Process = PsInitialSystemProcess;
- Handle = ObKernelHandleToHandle(Handle);
-
- if (Process != CurrentProcess)
- {
- KeStackAttachProcess(&Process->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
- }
- else
- Process = CurrentProcess;
-
- HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
- Handle);
- if(HandleEntry != NULL)
- {
- *GenerateOnClose = (HandleEntry->ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
-
- ExUnlockHandleTableEntry(Process->ObjectTable,
- HandleEntry);
- }
- else
- Status = STATUS_INVALID_HANDLE;
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- KeLeaveCriticalRegion();
-
- return Status;
-}
-
-
-/*
- * 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
- * Object (OUT) = Points to the object body on return
- * 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_TABLE_ENTRY HandleEntry;
- POBJECT_HEADER ObjectHeader;
- PVOID ObjectBody;
- ACCESS_MASK GrantedAccess;
- ULONG Attributes;
- PEPROCESS CurrentProcess, Process;
- BOOLEAN AttachedToProcess = FALSE;
- KAPC_STATE ApcState;
-
- PAGED_CODE();
-
- DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
- "ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
- ObjectType,AccessMode,Object);
-
- if (Handle == NULL)
- {
- return STATUS_INVALID_HANDLE;
- }
-
- CurrentProcess = PsGetCurrentProcess();
-
- /*
- * Handle special handle names
- */
- if (Handle == NtCurrentProcess() &&
- (ObjectType == PsProcessType || ObjectType == NULL))
- {
- ObReferenceObject(CurrentProcess);
-
- if (HandleInformation != NULL)
- {
- HandleInformation->HandleAttributes = 0;
- HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
- }
-
- *Object = CurrentProcess;
- DPRINT("Referencing current process %p\n", CurrentProcess);
- return STATUS_SUCCESS;
- }
- else if (Handle == NtCurrentProcess())
- {
- CHECKPOINT;
- return(STATUS_OBJECT_TYPE_MISMATCH);
- }
-
- if (Handle == NtCurrentThread() &&
- (ObjectType == PsThreadType || ObjectType == NULL))
- {
- PETHREAD CurrentThread = PsGetCurrentThread();
-
- ObReferenceObject(CurrentThread);
-
- if (HandleInformation != NULL)
- {
- HandleInformation->HandleAttributes = 0;
- HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
- }
-
- *Object = CurrentThread;
- CHECKPOINT;
- return STATUS_SUCCESS;
- }
- else if (Handle == NtCurrentThread())
- {
- CHECKPOINT;
- return(STATUS_OBJECT_TYPE_MISMATCH);
- }
-
- /* desire as much access rights as possible */
- if (DesiredAccess & MAXIMUM_ALLOWED)
- {
- DesiredAccess &= ~MAXIMUM_ALLOWED;
- DesiredAccess |= GENERIC_ALL;
- }
-
- if(ObIsKernelHandle(Handle, AccessMode))
- {
- Process = PsInitialSystemProcess;
- Handle = ObKernelHandleToHandle(Handle);
- }
- else
- {
- Process = CurrentProcess;
- }
-
- KeEnterCriticalRegion();
-
- if (Process != CurrentProcess)
- {
- KeStackAttachProcess(&Process->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
-
- HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
- Handle);
- if (HandleEntry == NULL)
- {
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
- KeLeaveCriticalRegion();
- DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
- return(STATUS_INVALID_HANDLE);
- }
-
- ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
- ObjectBody = &ObjectHeader->Body;
-
- DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
-
- if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
- {
- DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
-
- ExUnlockHandleTableEntry(Process->ObjectTable,
- HandleEntry);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- KeLeaveCriticalRegion();
-
- return(STATUS_OBJECT_TYPE_MISMATCH);
- }
-
- /* map the generic access masks if the caller asks for generic access */
- if (DesiredAccess & GENERIC_ANY)
- {
- RtlMapGenericMask(&DesiredAccess,
- &BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
- }
-
- GrantedAccess = HandleEntry->GrantedAccess;
-
- /* Unless running as KernelMode, deny access if caller desires more access
- rights than the handle can grant */
- if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
- {
- ExUnlockHandleTableEntry(Process->ObjectTable,
- HandleEntry);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- 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->ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
- EX_HANDLE_ENTRY_INHERITABLE |
- EX_HANDLE_ENTRY_AUDITONCLOSE);
-
- ExUnlockHandleTableEntry(Process->ObjectTable,
- HandleEntry);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- KeLeaveCriticalRegion();
-
- if (HandleInformation != NULL)
- {
- HandleInformation->HandleAttributes = Attributes;
- HandleInformation->GrantedAccess = GrantedAccess;
- }
-
- *Object = ObjectBody;
-
- return(STATUS_SUCCESS);
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * NtClose
- *
- * DESCRIPTION
- * Closes a handle reference to an object.
- *
- * ARGUMENTS
- * Handle
- * Handle to close.
- *
- * RETURN VALUE
- * Status.
- *
- * @implemented
- */
-NTSTATUS STDCALL
-NtClose(IN HANDLE Handle)
-{
- PEPROCESS Process, CurrentProcess;
- BOOLEAN AttachedToProcess = FALSE;
- KAPC_STATE ApcState;
- NTSTATUS Status;
- KPROCESSOR_MODE PreviousMode;
-
- PAGED_CODE();
-
- PreviousMode = ExGetPreviousMode();
- CurrentProcess = PsGetCurrentProcess();
-
- if(ObIsKernelHandle(Handle, PreviousMode))
- {
- Process = PsInitialSystemProcess;
- Handle = ObKernelHandleToHandle(Handle);
-
- if (Process != CurrentProcess)
- {
- KeStackAttachProcess(&Process->Pcb,
- &ApcState);
- AttachedToProcess = TRUE;
- }
- }
- else
- Process = CurrentProcess;
-
- Status = ObpDeleteHandle(Handle);
-
- if (AttachedToProcess)
- {
- KeUnstackDetachProcess(&ApcState);
- }
-
- if (!NT_SUCCESS(Status))
- {
- if((PreviousMode != KernelMode) &&
- (CurrentProcess->ExceptionPort))
- {
- KeRaiseUserException(Status);
- }
- return Status;
- }
-
- return(STATUS_SUCCESS);
-}
-
-
-/*
- * @implemented
- */
-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)
-{
- 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;
- OBP_LOOKUP_CONTEXT Context;
-
- 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,
- &Context);
- 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);
- }
-
- 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;
-
- 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;
- ObpInsertEntryDirectory(FoundObject, &Context, Header);
- ObjectAttached = TRUE;
- }
-
- 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,
- NULL,
- &Header->Body,
- 0,
- 0);
- }
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Create Failed\n");
- if (ObjectAttached == TRUE)
- {
- ObpDeleteEntryDirectory(&Context);
- }
- if (FoundObject)
- {
- ObDereferenceObject(FoundObject);
- }
- RtlFreeUnicodeString(&RemainingPath);
- return Status;
- }
- }
-
- 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(&Header->Body,
- DesiredAccess,
- ObjectCreateInfo->Attributes,
- 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)
-{
- 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;
-}
-
-VOID
-ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
- PEPROCESS Process,
- int Count)
-{
- ULONG P;
-// KIRQL oldIrql;
-
-// 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;
-
-// KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
-
-// pshi->GrantedAccess;
-// pshi->Object;
-// pshi->TypeIndex;
-// pshi->HandleAttributes;
-
-// KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
-
- return;
-}
-
-
-
-/* EOF */
diff --git a/reactos/ntoskrnl/ob/namespc.c b/reactos/ntoskrnl/ob/namespc.c
deleted file mode 100644
index 787f75376f1..00000000000
--- a/reactos/ntoskrnl/ob/namespc.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ob/namespc.c
- * PURPOSE: Manages the system namespace
- *
- * PROGRAMMERS: David Welch (welch@mcmail.com)
- */
-
-/* INCLUDES ***************************************************************/
-
-#include
-#define NDEBUG
-#include
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, ObInit)
-#endif
-
-
-extern ULONG NtGlobalFlag;
-
-/* GLOBALS ****************************************************************/
-
-POBJECT_TYPE ObDirectoryType = NULL;
-POBJECT_TYPE ObTypeObjectType = NULL;
-
-POBJECT_DIRECTORY NameSpaceRoot = NULL;
-POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
- /* FIXME: Move this somewhere else once devicemap support is in */
-PDEVICE_MAP ObSystemDeviceMap = NULL;
-KEVENT ObpDefaultObject;
-
-static GENERIC_MAPPING ObpDirectoryMapping = {
- STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
- STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY,
- STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
- DIRECTORY_ALL_ACCESS};
-
-static GENERIC_MAPPING ObpTypeMapping = {
- STANDARD_RIGHTS_READ,
- STANDARD_RIGHTS_WRITE,
- STANDARD_RIGHTS_EXECUTE,
- 0x000F0001};
-
-NTSTATUS
-STDCALL
-ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
- PUNICODE_STRING ObjectName,
- POBJECT_TYPE ObjectType,
- ULONG ObjectSize,
- POBJECT_HEADER *ObjectHeader);
-
-/* FUNCTIONS **************************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
- ULONG Attributes,
- PACCESS_STATE PassedAccessState,
- ACCESS_MASK DesiredAccess,
- POBJECT_TYPE ObjectType,
- KPROCESSOR_MODE AccessMode,
- PVOID ParseContext,
- PVOID* ObjectPtr)
-{
- PVOID Object = NULL;
- UNICODE_STRING RemainingPath;
- UNICODE_STRING ObjectName;
- OBJECT_CREATE_INFORMATION ObjectCreateInfo;
- NTSTATUS Status;
- OBP_LOOKUP_CONTEXT Context;
-
- PAGED_CODE();
-
- /* Capture the name */
- DPRINT("Capturing Name\n");
- Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("ObpCaptureObjectName() failed (Status %lx)\n", Status);
- return Status;
- }
-
- /*
- * Create a fake ObjectCreateInfo structure. Note that my upcoming
- * ObFindObject refactoring will remove the need for this hack.
- */
- ObjectCreateInfo.RootDirectory = NULL;
- ObjectCreateInfo.Attributes = Attributes;
-
- Status = ObFindObject(&ObjectCreateInfo,
- &ObjectName,
- &Object,
- &RemainingPath,
- ObjectType,
- &Context);
-
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
-
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
-
- if (RemainingPath.Buffer != NULL || Object == NULL)
- {
- DPRINT("Object %p\n", Object);
- *ObjectPtr = NULL;
- RtlFreeUnicodeString (&RemainingPath);
- return(STATUS_OBJECT_NAME_NOT_FOUND);
- }
- *ObjectPtr = Object;
- RtlFreeUnicodeString (&RemainingPath);
- return(STATUS_SUCCESS);
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * ObOpenObjectByName
- *
- * DESCRIPTION
- * Obtain a handle to an existing object.
- *
- * ARGUMENTS
- * ObjectAttributes
- * ...
- * ObjectType
- * ...
- * ParseContext
- * ...
- * AccessMode
- * ...
- * DesiredAccess
- * ...
- * PassedAccessState
- * ...
- * Handle
- * Handle to close.
- *
- * RETURN VALUE
- * Status.
- *
- * @implemented
- */
-NTSTATUS STDCALL
-ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN POBJECT_TYPE ObjectType,
- IN OUT PVOID ParseContext,
- IN KPROCESSOR_MODE AccessMode,
- IN ACCESS_MASK DesiredAccess,
- IN PACCESS_STATE PassedAccessState,
- OUT PHANDLE Handle)
-{
- UNICODE_STRING RemainingPath;
- PVOID Object = NULL;
- UNICODE_STRING ObjectName;
- OBJECT_CREATE_INFORMATION ObjectCreateInfo;
- NTSTATUS Status;
- OBP_LOOKUP_CONTEXT Context;
-
- PAGED_CODE();
-
- DPRINT("ObOpenObjectByName(...)\n");
-
- /* Capture all the info */
- DPRINT("Capturing Create Info\n");
- Status = ObpCaptureObjectAttributes(ObjectAttributes,
- AccessMode,
- ObjectType,
- &ObjectCreateInfo,
- &ObjectName);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
- return Status;
- }
-
- Status = ObFindObject(&ObjectCreateInfo,
- &ObjectName,
- &Object,
- &RemainingPath,
- ObjectType,
- &Context);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("ObFindObject() failed (Status %lx)\n", Status);
- goto Cleanup;
- }
-
- DPRINT("OBject: %p, Remaining Path: %wZ\n", Object, &RemainingPath);
- if (Object == NULL)
- {
- Status = STATUS_UNSUCCESSFUL;
- goto Cleanup;
- }
- if (RemainingPath.Buffer != NULL)
- {
- if (wcschr(RemainingPath.Buffer + 1, L'\\') == NULL)
- Status = STATUS_OBJECT_NAME_NOT_FOUND;
- else
- Status =STATUS_OBJECT_PATH_NOT_FOUND;
- goto Cleanup;
- }
-
- Status = ObpCreateHandle(Object,
- DesiredAccess,
- ObjectCreateInfo.Attributes,
- Handle);
-
-Cleanup:
- if (Object != NULL)
- {
- ObDereferenceObject(Object);
- }
- RtlFreeUnicodeString(&RemainingPath);
- ObpReleaseCapturedAttributes(&ObjectCreateInfo);
-
- return Status;
-}
-
-VOID
-STDCALL
-ObQueryDeviceMapInformation(PEPROCESS Process,
- PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
-{
- //KIRQL OldIrql ;
-
- /*
- * FIXME: This is an ugly hack for now, to always return the System Device Map
- * instead of returning the Process Device Map. Not important yet since we don't use it
- */
-
- /* FIXME: Acquire the DeviceMap Spinlock */
- // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
-
- /* Make a copy */
- DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
- RtlMoveMemory(DeviceMapInfo->Query.DriveType, ObSystemDeviceMap->DriveType, sizeof(ObSystemDeviceMap->DriveType));
-
- /* FIXME: Release the DeviceMap Spinlock */
- // KeReleasepinLock(DeviceMap->Lock, OldIrql);
-}
-
-VOID
-INIT_FUNCTION
-ObInit(VOID)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING Name;
- SECURITY_DESCRIPTOR SecurityDescriptor;
- OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
- OBP_LOOKUP_CONTEXT Context;
-
- /* Initialize the security descriptor cache */
- ObpInitSdCache();
-
- /* Initialize the Default Event */
- KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
-
- /* Create the Type Type */
- DPRINT("Creating Type Type\n");
- RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
- RtlInitUnicodeString(&Name, L"Type");
- ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
- ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
- ObjectTypeInitializer.UseDefaultObject = TRUE;
- ObjectTypeInitializer.MaintainTypeList = TRUE;
- ObjectTypeInitializer.PoolType = NonPagedPool;
- ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
- ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
- ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
-
- /* Create the Directory Type */
- DPRINT("Creating Directory Type\n");
- RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
- RtlInitUnicodeString(&Name, L"Directory");
- ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
- ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
- ObjectTypeInitializer.UseDefaultObject = FALSE;
- ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ObpParseDirectory;
- ObjectTypeInitializer.MaintainTypeList = FALSE;
- ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
- ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
- ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
-
- /* Create security descriptor */
- RtlCreateSecurityDescriptor(&SecurityDescriptor,
- SECURITY_DESCRIPTOR_REVISION1);
- RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
- SeAliasAdminsSid,
- FALSE);
- RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
- SeLocalSystemSid,
- FALSE);
- RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
- TRUE,
- SePublicDefaultDacl,
- FALSE);
-
- /* Create root directory */
- DPRINT("Creating Root Directory\n");
- InitializeObjectAttributes(&ObjectAttributes,
- NULL,
- OBJ_PERMANENT,
- NULL,
- &SecurityDescriptor);
- ObCreateObject(KernelMode,
- ObDirectoryType,
- &ObjectAttributes,
- KernelMode,
- NULL,
- sizeof(OBJECT_DIRECTORY),
- 0,
- 0,
- (PVOID*)&NameSpaceRoot);
- ObInsertObject((PVOID)NameSpaceRoot,
- NULL,
- DIRECTORY_ALL_ACCESS,
- 0,
- NULL,
- NULL);
-
- /* Create '\ObjectTypes' directory */
- RtlInitUnicodeString(&Name, L"\\ObjectTypes");
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_PERMANENT,
- NULL,
- &SecurityDescriptor);
- ObCreateObject(KernelMode,
- ObDirectoryType,
- &ObjectAttributes,
- KernelMode,
- NULL,
- sizeof(OBJECT_DIRECTORY),
- 0,
- 0,
- (PVOID*)&ObpTypeDirectoryObject);
- ObInsertObject((PVOID)ObpTypeDirectoryObject,
- NULL,
- DIRECTORY_ALL_ACCESS,
- 0,
- NULL,
- NULL);
-
- /* Insert the two objects we already created but couldn't add */
- /* NOTE: Uses TypeList & Creator Info in OB 2.0 */
- Context.Directory = ObpTypeDirectoryObject;
- Context.DirectoryLocked = TRUE;
- if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
- &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObTypeObjectType))->Name,
- OBJ_CASE_INSENSITIVE,
- FALSE,
- &Context))
- {
- ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, BODY_TO_HEADER(ObTypeObjectType));
- }
- if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
- &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObDirectoryType))->Name,
- OBJ_CASE_INSENSITIVE,
- FALSE,
- &Context))
- {
- ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, BODY_TO_HEADER(ObDirectoryType));
- }
-
- /* Create 'symbolic link' object type */
- ObInitSymbolicLinkImplementation();
-
- /* FIXME: Hack Hack! */
- ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
- RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
-}
-
-NTSTATUS
-STDCALL
-ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
- PUNICODE_STRING TypeName,
- POBJECT_TYPE *ObjectType)
-{
- POBJECT_HEADER Header;
- POBJECT_TYPE LocalObjectType;
- ULONG HeaderSize;
- NTSTATUS Status;
-
- DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", TypeName);
-
- /* Allocate the Object */
- Status = ObpAllocateObject(NULL,
- TypeName,
- ObTypeObjectType,
- OBJECT_ALLOC_SIZE(sizeof(OBJECT_TYPE)),
- (POBJECT_HEADER*)&Header);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ObpAllocateObject failed!\n");
- return Status;
- }
-
- LocalObjectType = (POBJECT_TYPE)&Header->Body;
- DPRINT("Local ObjectType: %p Header: %p \n", LocalObjectType, Header);
-
- /* Check if this is the first Object Type */
- if (!ObTypeObjectType)
- {
- ObTypeObjectType = LocalObjectType;
- Header->Type = ObTypeObjectType;
- LocalObjectType->Key = TAG('O', 'b', 'j', 'T');
- }
- else
- {
- CHAR Tag[4];
- Tag[0] = TypeName->Buffer[0];
- Tag[1] = TypeName->Buffer[1];
- Tag[2] = TypeName->Buffer[2];
- Tag[3] = TypeName->Buffer[3];
-
- /* Set Tag */
- DPRINT("Convert: %s \n", Tag);
- LocalObjectType->Key = *(PULONG)Tag;
- }
-
- /* Set it up */
- LocalObjectType->TypeInfo = *ObjectTypeInitializer;
- LocalObjectType->Name = *TypeName;
- LocalObjectType->TypeInfo.PoolType = ObjectTypeInitializer->PoolType;
-
- /* These two flags need to be manually set up */
- Header->Flags |= OB_FLAG_KERNEL_MODE | OB_FLAG_PERMANENT;
-
- /* Check if we have to maintain a type list */
- if (NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST)
- {
- /* Enable support */
- LocalObjectType->TypeInfo.MaintainTypeList = TRUE;
- }
-
- /* Calculate how much space our header'll take up */
- HeaderSize = sizeof(OBJECT_HEADER) + sizeof(OBJECT_HEADER_NAME_INFO) +
- (ObjectTypeInitializer->MaintainHandleCount ?
- sizeof(OBJECT_HEADER_HANDLE_INFO) : 0);
-
- /* Update the Pool Charges */
- if (ObjectTypeInitializer->PoolType == NonPagedPool)
- {
- LocalObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderSize;
- }
- else
- {
- LocalObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderSize;
- }
-
- /* All objects types need a security procedure */
- if (!ObjectTypeInitializer->SecurityProcedure)
- {
- LocalObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod;
- }
-
- /* Select the Wait Object */
- if (LocalObjectType->TypeInfo.UseDefaultObject)
- {
- /* Add the SYNCHRONIZE access mask since it's waitable */
- LocalObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
-
- /* Use the "Default Object", a simple event */
- LocalObjectType->DefaultObject = &ObpDefaultObject;
- }
- /* Special system objects get an optimized hack so they can be waited on */
- else if (TypeName->Length == 8 && !wcscmp(TypeName->Buffer, L"File"))
- {
- LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(FILE_OBJECT, Event);
- }
- /* FIXME: When LPC stops sucking, add a hack for Waitable Ports */
- else
- {
- /* No default Object */
- LocalObjectType->DefaultObject = NULL;
- }
-
- /* Initialize Object Type components */
- ExInitializeResourceLite(&LocalObjectType->Mutex);
- InitializeListHead(&LocalObjectType->TypeList);
-
- /* Insert it into the Object Directory */
- if (ObpTypeDirectoryObject)
- {
- OBP_LOOKUP_CONTEXT Context;
- Context.Directory = ObpTypeDirectoryObject;
- Context.DirectoryLocked = TRUE;
- ObpLookupEntryDirectory(ObpTypeDirectoryObject,
- TypeName,
- OBJ_CASE_INSENSITIVE,
- FALSE,
- &Context);
- ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, Header);
- ObReferenceObject(ObpTypeDirectoryObject);
- }
-
- *ObjectType = LocalObjectType;
- return Status;
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/ob/ntobj.c b/reactos/ntoskrnl/ob/ntobj.c
deleted file mode 100644
index d7882d60d87..00000000000
--- a/reactos/ntoskrnl/ob/ntobj.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
-* PROJECT: ReactOS Kernel
-* LICENSE: GPL - See COPYING in the top level directory
-* FILE: ntoskrnl/ob/ntobj.c
-* PURPOSE: Bunch of random functions that got stuck here without purpose. FIXME.
-* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
-*/
-
-/* INCLUDES *****************************************************************/
-
-#include
-#define NDEBUG
-#include
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-/*++
-* @name ObpSetPermanentObject
-*
-* The ObpSetPermanentObject routine
-*
-* @param ObjectBody
-*
-*
-* @param Permanent
-*
-*
-* @return None.
-*
-* @remarks None.
-*
-*--*/
-VOID
-FASTCALL
-ObpSetPermanentObject(IN PVOID ObjectBody,
- IN BOOLEAN Permanent)
-{
- POBJECT_HEADER ObjectHeader;
- OBP_LOOKUP_CONTEXT Context;
-
- ObjectHeader = BODY_TO_HEADER(ObjectBody);
- ASSERT (ObjectHeader->PointerCount > 0);
- if (Permanent)
- {
- ObjectHeader->Flags |= OB_FLAG_PERMANENT;
- }
- else
- {
- ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
- if (ObjectHeader->HandleCount == 0 &&
- HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory)
- {
- /* Make sure it's still inserted */
- Context.Directory = HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory;
- Context.DirectoryLocked = TRUE;
- if (ObpLookupEntryDirectory(HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory,
- &HEADER_TO_OBJECT_NAME(ObjectHeader)->Name,
- 0,
- FALSE,
- &Context))
- {
- ObpDeleteEntryDirectory(&Context);
- }
- }
- }
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*++
-* @name ObMakeTemporaryObject
-* @implemented NT4
-*
-* The ObMakeTemporaryObject routine
-*
-* @param ObjectBody
-*
-*
-* @return None.
-*
-* @remarks None.
-*
-*--*/
-VOID
-NTAPI
-ObMakeTemporaryObject(IN PVOID ObjectBody)
-{
- ObpSetPermanentObject (ObjectBody, FALSE);
-}
-
-/*++
-* @name NtSetInformationObject
-* @implemented NT4
-*
-* The NtSetInformationObject routine
-*
-* @param ObjectHandle
-*
-*
-* @param ObjectInformationClass
-*
-*
-* @param ObjectInformation
-*
-*
-* @param Length
-*
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtSetInformationObject(IN HANDLE ObjectHandle,
- IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
- IN PVOID ObjectInformation,
- IN ULONG Length)
-{
- PVOID Object;
- NTSTATUS Status;
- PAGED_CODE();
-
- if (ObjectInformationClass != ObjectHandleInformation)
- return STATUS_INVALID_INFO_CLASS;
-
- if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
- return STATUS_INFO_LENGTH_MISMATCH;
-
- Status = ObReferenceObjectByHandle(ObjectHandle,
- 0,
- NULL,
- KeGetPreviousMode(),
- &Object,
- NULL);
- if (!NT_SUCCESS (Status)) return Status;
-
- Status = ObpSetHandleAttributes(ObjectHandle,
- (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
- ObjectInformation);
-
- ObDereferenceObject (Object);
- return Status;
-}
-
-/*++
-* @name NtQueryObject
-* @implemented NT4
-*
-* The NtQueryObject routine
-*
-* @param ObjectHandle
-*
-*
-* @param ObjectInformationClass
-*
-*
-* @param ObjectInformation
-*
-*
-* @param Length
-*
-*
-* @param ResultLength
-*
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtQueryObject(IN HANDLE ObjectHandle,
- IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
- OUT PVOID ObjectInformation,
- IN ULONG Length,
- OUT PULONG ResultLength OPTIONAL)
-{
- OBJECT_HANDLE_INFORMATION HandleInfo;
- POBJECT_HEADER ObjectHeader;
- ULONG InfoLength;
- PVOID Object;
- NTSTATUS Status;
- PAGED_CODE();
-
- Status = ObReferenceObjectByHandle(ObjectHandle,
- 0,
- NULL,
- KeGetPreviousMode(),
- &Object,
- &HandleInfo);
- if (!NT_SUCCESS (Status)) return Status;
-
- ObjectHeader = BODY_TO_HEADER(Object);
-
- switch (ObjectInformationClass)
- {
- case ObjectBasicInformation:
- InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
- if (Length != sizeof(OBJECT_BASIC_INFORMATION))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- POBJECT_BASIC_INFORMATION BasicInfo;
-
- BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation;
- BasicInfo->Attributes = HandleInfo.HandleAttributes;
- BasicInfo->GrantedAccess = HandleInfo.GrantedAccess;
- BasicInfo->HandleCount = ObjectHeader->HandleCount;
- BasicInfo->PointerCount = ObjectHeader->PointerCount;
- BasicInfo->PagedPoolUsage = 0; /* FIXME*/
- BasicInfo->NonPagedPoolUsage = 0; /* FIXME*/
- BasicInfo->NameInformationLength = 0; /* FIXME*/
- BasicInfo->TypeInformationLength = 0; /* FIXME*/
- BasicInfo->SecurityDescriptorLength = 0; /* FIXME*/
- if (ObjectHeader->Type == ObSymbolicLinkType)
- {
- BasicInfo->CreateTime.QuadPart =
- ((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart;
- }
- else
- {
- BasicInfo->CreateTime.QuadPart = (ULONGLONG)0;
- }
- Status = STATUS_SUCCESS;
- }
- break;
-
- case ObjectNameInformation:
- Status = ObQueryNameString(Object,
- (POBJECT_NAME_INFORMATION)ObjectInformation,
- Length,
- &InfoLength);
- break;
-
- case ObjectTypeInformation:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ObjectAllTypesInformation:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ObjectHandleInformation:
- InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
- if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- Status = ObpQueryHandleAttributes(
- ObjectHandle,
- (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)ObjectInformation);
- }
- break;
-
- default:
- Status = STATUS_INVALID_INFO_CLASS;
- break;
- }
-
- ObDereferenceObject (Object);
-
- if (ResultLength != NULL) *ResultLength = InfoLength;
-
- return Status;
-}
-
-/*++
-* @name NtMakeTemporaryObject
-* @implemented NT4
-*
-* The NtMakeTemporaryObject routine
-*
-* @param ObjectHandle
-*
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtMakeTemporaryObject(IN HANDLE ObjectHandle)
-{
- PVOID ObjectBody;
- NTSTATUS Status;
- PAGED_CODE();
-
- Status = ObReferenceObjectByHandle(ObjectHandle,
- 0,
- NULL,
- KeGetPreviousMode(),
- &ObjectBody,
- NULL);
- if (Status != STATUS_SUCCESS) return Status;
-
- ObpSetPermanentObject (ObjectBody, FALSE);
-
- ObDereferenceObject(ObjectBody);
-
- return STATUS_SUCCESS;
-}
-
-/*++
-* @name NtMakePermanentObject
-* @implemented NT4
-*
-* The NtMakePermanentObject routine
-*
-* @param ObjectHandle
-*
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtMakePermanentObject(IN HANDLE ObjectHandle)
-{
- PVOID ObjectBody;
- NTSTATUS Status;
- PAGED_CODE();
-
- Status = ObReferenceObjectByHandle(ObjectHandle,
- 0,
- NULL,
- KeGetPreviousMode(),
- &ObjectBody,
- NULL);
- if (Status != STATUS_SUCCESS) return Status;
-
- ObpSetPermanentObject (ObjectBody, TRUE);
-
- ObDereferenceObject(ObjectBody);
-
- return STATUS_SUCCESS;
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/ob/dirobj.c b/reactos/ntoskrnl/ob/obdir.c
similarity index 93%
rename from reactos/ntoskrnl/ob/dirobj.c
rename to reactos/ntoskrnl/ob/obdir.c
index 18c11ef0bbb..acf3911f24e 100644
--- a/reactos/ntoskrnl/ob/dirobj.c
+++ b/reactos/ntoskrnl/ob/obdir.c
@@ -1,619 +1,626 @@
-/*
- * PROJECT: ReactOS Kernel
- * LICENSE: GPL - See COPYING in the top level directory
- * FILE: ntoskrnl/ob/dirobj.c
- * PURPOSE: Directory Object Implementation
- * PROGRAMMER: David Welch (welch@mcmail.com)
- */
-
-/* INCLUDES ***************************************************************/
-
-#define NTDDI_VERSION NTDDI_WS03
-#include
-#define NDEBUG
-#include
-
-#define OBP_PROFILE
-#ifdef OBP_PROFILE
-
-LARGE_INTEGER ObpProfileTime;
-BOOLEAN ObpProfileComplete;
-
-#define ObpStartProfile() \
- LARGE_INTEGER StartTime; \
- LARGE_INTEGER EndTime; \
- StartTime = KeQueryPerformanceCounter(NULL);
-
-#define ObpEndProfile() \
- EndTime = KeQueryPerformanceCounter(NULL); \
- ObpProfileTime.QuadPart += (EndTime.QuadPart - \
- StartTime.QuadPart);
-
-#define ObpCompleteProfile() \
- if (!wcscmp(Name, L"NlsSectionCP1252") && \
- !ObpProfileComplete) \
- { \
- DPRINT1("******************************\n");\
- DPRINT1("Obp Profiling1 Complete: %I64d\n", \
- ObpProfileTime.QuadPart); \
- DPRINT1("******************************\n");\
- ObpProfileComplete = TRUE; \
- }
-
-#else
-
-#define ObpStartProfile()
-#define ObpEndProfile()
-#define ObpCompleteProfile()
-
-#endif
-
-/* PRIVATE FUNCTIONS ******************************************************/
-
-BOOLEAN
-NTAPI
-ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent,
- IN POBP_LOOKUP_CONTEXT Context,
- IN POBJECT_HEADER ObjectHeader)
-{
- POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
- POBJECT_DIRECTORY_ENTRY NewEntry;
- POBJECT_HEADER_NAME_INFO HeaderNameInfo;
-
- /* Make sure we have a name */
- ASSERT(ObjectHeader->NameInfoOffset != 0);
-
- /* Validate the context */
- if ((Context->Object) || !(Context->DirectoryLocked) || !Parent)
- {
- DbgPrint("OB: ObpInsertEntryDirectory - invalid context %p %ld\n",
- Context, Context->DirectoryLocked);
- DbgBreakPoint();
- return FALSE;
- }
-
- /* Allocate a new Directory Entry */
- NewEntry = ExAllocatePoolWithTag(PagedPool,
- sizeof(OBJECT_DIRECTORY_ENTRY),
- TAG('O', 'b', 'D', 'i'));
- if (!NewEntry) return FALSE;
-
- /* Save the hash */
- NewEntry->HashValue = Context->HashValue;
-
- /* Get the Object Name Information */
- HeaderNameInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
-
- /* Get the Allocated entry */
- AllocatedEntry = &Parent->HashBuckets[Context->HashIndex];
- DPRINT("ADD: Allocated Entry: %p. NewEntry: %p\n", AllocatedEntry, NewEntry);
- DPRINT("ADD: Name: %wZ, Hash: %lx\n", &HeaderNameInfo->Name, Context->HashIndex);
- DPRINT("ADD: Parent: %p. Name: %wZ\n",
- Parent,
- HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent)) ?
- &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name : NULL);
-
- /* Set it */
- NewEntry->ChainLink = *AllocatedEntry;
- *AllocatedEntry = NewEntry;
-
- /* Associate the Object */
- NewEntry->Object = &ObjectHeader->Body;
-
- /* Associate the Directory */
- HeaderNameInfo->Directory = Parent;
- return TRUE;
-}
-
-PVOID
-NTAPI
-ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
- IN PUNICODE_STRING Name,
- IN ULONG Attributes,
- IN UCHAR SearchShadow,
- IN POBP_LOOKUP_CONTEXT Context)
-{
- BOOLEAN CaseInsensitive = FALSE;
- POBJECT_HEADER_NAME_INFO HeaderNameInfo;
- ULONG HashValue;
- ULONG HashIndex;
- LONG TotalChars;
- WCHAR CurrentChar;
- POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
- POBJECT_DIRECTORY_ENTRY *LookupBucket;
- POBJECT_DIRECTORY_ENTRY CurrentEntry;
- PVOID FoundObject = NULL;
- PWSTR Buffer;
- PAGED_CODE();
-
- /* Always disable this until we have LUID Device Maps */
- SearchShadow = FALSE;
-
- /* Fail the following cases */
- TotalChars = Name->Length / sizeof(WCHAR);
- if (!(Directory) || !(Name) || !(Name->Buffer) || !(TotalChars))
- {
- goto Quickie;
- }
-
- /* Set up case-sensitivity */
- if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE;
-
- /* Create the Hash */
- Buffer = Name->Buffer;
- for (HashValue = 0; TotalChars; TotalChars--)
- {
- /* Go to the next Character */
- CurrentChar = *Buffer++;
-
- /* Prepare the Hash */
- HashValue += (HashValue << 1) + (HashValue >> 1);
-
- /* Create the rest based on the name */
- if (CurrentChar < 'a') HashValue += CurrentChar;
- else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
- else HashValue += (CurrentChar - ('a'-'A'));
- }
-
- /* Merge it with our number of hash buckets */
- HashIndex = HashValue % 37;
- DPRINT("LOOKUP: ObjectName: %wZ\n", Name);
- DPRINT("LOOKUP: Generated Hash: 0x%x. Generated Id: 0x%x\n", HashValue, HashIndex);
-
- /* Save the result */
- Context->HashValue = HashValue;
- Context->HashIndex = HashIndex;
-
- /* Get the root entry and set it as our lookup bucket */
- AllocatedEntry = &Directory->HashBuckets[HashIndex];
- LookupBucket = AllocatedEntry;
- DPRINT("LOOKUP: Allocated Entry: %p. LookupBucket: %p\n", AllocatedEntry, LookupBucket);
-
- /* Check if the directory is already locked */
- if (!Context->DirectoryLocked)
- {
- /* Lock it */
- KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&Directory->Lock, TRUE);
- Context->LockStateSignature = 0xDDDD1234;
- }
-
- /* Start looping */
- while ((CurrentEntry = *AllocatedEntry))
- {
- /* Do the hashes match? */
- DPRINT("CurrentEntry: %p. CurrentHash: %lx\n", CurrentEntry, CurrentEntry->HashValue);
- if (CurrentEntry->HashValue == HashValue)
- {
- /* Make sure that it has a name */
- ASSERT(BODY_TO_HEADER(CurrentEntry->Object)->NameInfoOffset != 0);
-
- /* Get the name information */
- HeaderNameInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(CurrentEntry->Object));
-
- /* Do the names match? */
- DPRINT("NameCheck: %wZ, %wZ\n", Name, &HeaderNameInfo->Name);
- if ((Name->Length == HeaderNameInfo->Name.Length) &&
- (RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
- {
- DPRINT("Found Name Match\n");
- break;
- }
- }
-
- /* Move to the next entry */
- AllocatedEntry = &CurrentEntry->ChainLink;
- }
-
- /* Check if we still have an entry */
- if (CurrentEntry)
- {
- /* Set this entry as the first, to speed up incoming insertion */
- if (AllocatedEntry != LookupBucket)
- {
- /* Set the Current Entry */
- *AllocatedEntry = CurrentEntry->ChainLink;
-
- /* Link to the old Hash Entry */
- CurrentEntry->ChainLink = *LookupBucket;
-
- /* Set the new Hash Entry */
- *LookupBucket = CurrentEntry;
- }
-
- /* Save the found object */
- FoundObject = CurrentEntry->Object;
- if (!FoundObject) goto Quickie;
-
- /* Add a reference to the object */
- ObReferenceObject(FoundObject);
- }
-
- /* Check if the directory was unlocked (which means we locked it) */
- if (!Context->DirectoryLocked)
- {
- /* Lock it */
- ExReleaseResourceLite(&Directory->Lock);
- KeLeaveCriticalRegion();
- Context->LockStateSignature = 0xEEEE1234;
- }
-
-Quickie:
- /* Return the object we found */
- DPRINT("Object Found: %p Context: %p\n", FoundObject, Context);
- Context->Object = FoundObject;
- return FoundObject;
-}
-
-BOOLEAN
-NTAPI
-ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context)
-{
- POBJECT_DIRECTORY Directory;
- POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
- POBJECT_DIRECTORY_ENTRY CurrentEntry;
-
- /* Get the Directory */
- Directory = Context->Directory;
- if (!Directory) return FALSE;
-
- /* Get the Entry */
- AllocatedEntry = &Directory->HashBuckets[Context->HashIndex];
- CurrentEntry = *AllocatedEntry;
- DPRINT("DEL: Parent: %p, Hash: %lx, AllocatedEntry: %p, CurrentEntry: %p\n",
- Directory, Context->HashIndex, AllocatedEntry, CurrentEntry);
-
- /* Unlink the Entry */
- *AllocatedEntry = CurrentEntry->ChainLink;
- CurrentEntry->ChainLink = NULL;
-
- /* Free it */
- ExFreePool(CurrentEntry);
-
- /* Return */
- return TRUE;
-}
-
-NTSTATUS
-NTAPI
-ObpParseDirectory(PVOID Object,
- PVOID * NextObject,
- PUNICODE_STRING FullPath,
- PWSTR * Path,
- ULONG Attributes,
- POBP_LOOKUP_CONTEXT Context)
-{
- PWSTR Start;
- PWSTR End;
- PVOID FoundObject;
- //KIRQL oldlvl;
- UNICODE_STRING StartUs;
-
- *NextObject = NULL;
-
- if ((*Path) == NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- Start = *Path;
- if (*Start == L'\\')
- Start++;
-
- End = wcschr(Start, L'\\');
- if (End != NULL)
- {
- *End = 0;
- }
-
- //KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
- RtlInitUnicodeString(&StartUs, Start);
- Context->DirectoryLocked = TRUE;
- Context->Directory = Object;
- FoundObject = ObpLookupEntryDirectory(Object, &StartUs, Attributes, FALSE, Context);
- if (FoundObject == NULL)
- {
- //KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
- if (End != NULL)
- {
- *End = L'\\';
- }
- return STATUS_UNSUCCESSFUL;
- }
-
- ObReferenceObjectByPointer(FoundObject,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
- //KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
- if (End != NULL)
- {
- *End = L'\\';
- *Path = End;
- }
- else
- {
- *Path = NULL;
- }
-
- *NextObject = FoundObject;
-
- return STATUS_SUCCESS;
-}
-
-/* FUNCTIONS **************************************************************/
-
-/*++
-* @name NtOpenDirectoryObject
-* @implemented NT4
-*
-* The NtOpenDirectoryObject opens a namespace directory object.
-*
-* @param DirectoryHandle
-* Variable which receives the directory handle.
-*
-* @param DesiredAccess
-* Desired access to the directory.
-*
-* @param ObjectAttributes
-* Structure describing the directory.
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
-{
- HANDLE hDirectory;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
-
- if(PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- ProbeForWriteHandle(DirectoryHandle);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenDirectoryObject failed, Status: 0x%x\n", Status);
- return Status;
- }
- }
-
- Status = ObOpenObjectByName(ObjectAttributes,
- ObDirectoryType,
- NULL,
- PreviousMode,
- DesiredAccess,
- NULL,
- &hDirectory);
- if(NT_SUCCESS(Status))
- {
- _SEH_TRY
- {
- *DirectoryHandle = hDirectory;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
-
- return Status;
-}
-
-/*++
-* @name NtQueryDirectoryObject
-* @implemented NT4
-*
-* The NtQueryDirectoryObject Reads information from a directory in
-* the system namespace.
-*
-* @param DirectoryHandle
-* Handle obtained with NtOpenDirectoryObject which
-* must grant DIRECTORY_QUERY access to the directory object.
-*
-* @param Buffer
-* Buffer to hold the data read.
-*
-* @param BufferLength
-* Size of the buffer in bytes.
-*
-* @param ReturnSingleEntry
-* When TRUE, only 1 entry is written in DirObjInformation;
-* otherwise as many as will fit in the buffer.
-*
-* @param RestartScan
-* If TRUE start reading at index 0.
-* If FALSE start reading at the index specified by *ObjectIndex.
-*
-* @param Context
-* Zero based index into the directory, interpretation
-* depends on RestartScan.
-*
-* @param ReturnLength
-* Caller supplied storage for the number of bytes
-* written (or NULL).
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks Although you can iterate over the directory by calling this
-* function multiple times, the directory is unlocked between
-* calls. This means that another thread can change the directory
-* and so iterating doesn't guarantee a consistent picture of the
-* directory. Best thing is to retrieve all directory entries in
-* one call.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
- OUT PVOID Buffer,
- IN ULONG BufferLength,
- IN BOOLEAN ReturnSingleEntry,
- IN BOOLEAN RestartScan,
- IN OUT PULONG Context,
- OUT PULONG ReturnLength OPTIONAL)
-{
- POBJECT_DIRECTORY Directory;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- ULONG SkipEntries = 0;
- NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
-
- if(PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- /* a test showed that the Buffer pointer just has to be 16 bit aligned,
- propably due to the fact that most information that needs to be copied
- is unicode strings */
- ProbeForWrite(Buffer, BufferLength, sizeof(WCHAR));
- ProbeForWriteUlong(Context);
- if(!RestartScan)
- {
- SkipEntries = *Context;
- }
- if(ReturnLength != NULL)
- {
- ProbeForWriteUlong(ReturnLength);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryDirectoryObject failed, Status: 0x%x\n", Status);
- return Status;
- }
- }
- else if(!RestartScan)
- {
- SkipEntries = *Context;
- }
-
- Status = ObReferenceObjectByHandle(DirectoryHandle,
- DIRECTORY_QUERY,
- ObDirectoryType,
- PreviousMode,
- (PVOID*)&Directory,
- NULL);
- if(NT_SUCCESS(Status))
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- return Status;
-}
-
-/*++
-* @name NtCreateDirectoryObject
-* @implemented NT4
-*
-* The NtOpenDirectoryObject creates or opens a directory object.
-*
-* @param DirectoryHandle
-* Variable which receives the directory handle.
-*
-* @param DesiredAccess
-* Desired access to the directory.
-*
-* @param ObjectAttributes
-* Structure describing the directory.
-*
-* @return STATUS_SUCCESS or appropriate error value.
-*
-* @remarks None.
-*
-*--*/
-NTSTATUS
-NTAPI
-NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
-{
- POBJECT_DIRECTORY Directory;
- HANDLE hDirectory;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
-
- DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
- "DesiredAccess %x, ObjectAttributes %x\n",
- DirectoryHandle, DesiredAccess, ObjectAttributes);
-
- if(PreviousMode != KernelMode)
- {
- _SEH_TRY
- {
- ProbeForWriteHandle(DirectoryHandle);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateDirectoryObject failed, Status: 0x%x\n", Status);
- return Status;
- }
- }
-
- Status = ObCreateObject(PreviousMode,
- ObDirectoryType,
- ObjectAttributes,
- PreviousMode,
- NULL,
- sizeof(OBJECT_DIRECTORY),
- 0,
- 0,
- (PVOID*)&Directory);
-
- if(NT_SUCCESS(Status))
- {
- Status = ObInsertObject((PVOID)Directory,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &hDirectory);
- if(NT_SUCCESS(Status))
- {
- _SEH_TRY
- {
- *DirectoryHandle = hDirectory;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
-
- ObDereferenceObject(Directory);
- }
-
- return Status;
-}
-
-/* EOF */
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ob/dirobj.c
+ * PURPOSE: Manages the Object Manager's Directory Implementation,
+ * such as functions for addition, deletion and lookup into
+ * the Object Manager's namespace. These routines are separate
+ * from the Namespace Implementation because they are largely
+ * independent and could be used for other namespaces.
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#define NTDDI_VERSION NTDDI_WS03
+#include
+#define NDEBUG
+#include
+
+#define OBP_PROFILE
+#ifdef OBP_PROFILE
+
+LARGE_INTEGER ObpProfileTime;
+BOOLEAN ObpProfileComplete;
+
+#define ObpStartProfile() \
+ LARGE_INTEGER StartTime; \
+ LARGE_INTEGER EndTime; \
+ StartTime = KeQueryPerformanceCounter(NULL);
+
+#define ObpEndProfile() \
+ EndTime = KeQueryPerformanceCounter(NULL); \
+ ObpProfileTime.QuadPart += (EndTime.QuadPart - \
+ StartTime.QuadPart);
+
+#define ObpCompleteProfile() \
+ if (!wcscmp(Name, L"NlsSectionCP1252") && \
+ !ObpProfileComplete) \
+ { \
+ DPRINT1("******************************\n");\
+ DPRINT1("Obp Profiling1 Complete: %I64d\n", \
+ ObpProfileTime.QuadPart); \
+ DPRINT1("******************************\n");\
+ ObpProfileComplete = TRUE; \
+ }
+
+#else
+
+#define ObpStartProfile()
+#define ObpEndProfile()
+#define ObpCompleteProfile()
+
+#endif
+
+POBJECT_TYPE ObDirectoryType = NULL;
+
+/* PRIVATE FUNCTIONS ******************************************************/
+
+BOOLEAN
+NTAPI
+ObpInsertEntryDirectory(IN POBJECT_DIRECTORY Parent,
+ IN POBP_LOOKUP_CONTEXT Context,
+ IN POBJECT_HEADER ObjectHeader)
+{
+ POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
+ POBJECT_DIRECTORY_ENTRY NewEntry;
+ POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+
+ /* Make sure we have a name */
+ ASSERT(ObjectHeader->NameInfoOffset != 0);
+
+ /* Validate the context */
+ if ((Context->Object) || !(Context->DirectoryLocked) || !Parent)
+ {
+ DbgPrint("OB: ObpInsertEntryDirectory - invalid context %p %ld\n",
+ Context, Context->DirectoryLocked);
+ DbgBreakPoint();
+ return FALSE;
+ }
+
+ /* Allocate a new Directory Entry */
+ NewEntry = ExAllocatePoolWithTag(PagedPool,
+ sizeof(OBJECT_DIRECTORY_ENTRY),
+ TAG('O', 'b', 'D', 'i'));
+ if (!NewEntry) return FALSE;
+
+ /* Save the hash */
+ NewEntry->HashValue = Context->HashValue;
+
+ /* Get the Object Name Information */
+ HeaderNameInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
+
+ /* Get the Allocated entry */
+ AllocatedEntry = &Parent->HashBuckets[Context->HashIndex];
+ DPRINT("ADD: Allocated Entry: %p. NewEntry: %p\n", AllocatedEntry, NewEntry);
+ DPRINT("ADD: Name: %wZ, Hash: %lx\n", &HeaderNameInfo->Name, Context->HashIndex);
+ DPRINT("ADD: Parent: %p. Name: %wZ\n",
+ Parent,
+ HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent)) ?
+ &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name : NULL);
+
+ /* Set it */
+ NewEntry->ChainLink = *AllocatedEntry;
+ *AllocatedEntry = NewEntry;
+
+ /* Associate the Object */
+ NewEntry->Object = &ObjectHeader->Body;
+
+ /* Associate the Directory */
+ HeaderNameInfo->Directory = Parent;
+ return TRUE;
+}
+
+PVOID
+NTAPI
+ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
+ IN PUNICODE_STRING Name,
+ IN ULONG Attributes,
+ IN UCHAR SearchShadow,
+ IN POBP_LOOKUP_CONTEXT Context)
+{
+ BOOLEAN CaseInsensitive = FALSE;
+ POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+ ULONG HashValue;
+ ULONG HashIndex;
+ LONG TotalChars;
+ WCHAR CurrentChar;
+ POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
+ POBJECT_DIRECTORY_ENTRY *LookupBucket;
+ POBJECT_DIRECTORY_ENTRY CurrentEntry;
+ PVOID FoundObject = NULL;
+ PWSTR Buffer;
+ PAGED_CODE();
+
+ /* Always disable this until we have LUID Device Maps */
+ SearchShadow = FALSE;
+
+ /* Fail the following cases */
+ TotalChars = Name->Length / sizeof(WCHAR);
+ if (!(Directory) || !(Name) || !(Name->Buffer) || !(TotalChars))
+ {
+ goto Quickie;
+ }
+
+ /* Set up case-sensitivity */
+ if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE;
+
+ /* Create the Hash */
+ Buffer = Name->Buffer;
+ for (HashValue = 0; TotalChars; TotalChars--)
+ {
+ /* Go to the next Character */
+ CurrentChar = *Buffer++;
+
+ /* Prepare the Hash */
+ HashValue += (HashValue << 1) + (HashValue >> 1);
+
+ /* Create the rest based on the name */
+ if (CurrentChar < 'a') HashValue += CurrentChar;
+ else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
+ else HashValue += (CurrentChar - ('a'-'A'));
+ }
+
+ /* Merge it with our number of hash buckets */
+ HashIndex = HashValue % 37;
+ DPRINT("LOOKUP: ObjectName: %wZ\n", Name);
+ DPRINT("LOOKUP: Generated Hash: 0x%x. Generated Id: 0x%x\n", HashValue, HashIndex);
+
+ /* Save the result */
+ Context->HashValue = HashValue;
+ Context->HashIndex = HashIndex;
+
+ /* Get the root entry and set it as our lookup bucket */
+ AllocatedEntry = &Directory->HashBuckets[HashIndex];
+ LookupBucket = AllocatedEntry;
+ DPRINT("LOOKUP: Allocated Entry: %p. LookupBucket: %p\n", AllocatedEntry, LookupBucket);
+
+ /* Check if the directory is already locked */
+ if (!Context->DirectoryLocked)
+ {
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&Directory->Lock, TRUE);
+ Context->LockStateSignature = 0xDDDD1234;
+ }
+
+ /* Start looping */
+ while ((CurrentEntry = *AllocatedEntry))
+ {
+ /* Do the hashes match? */
+ DPRINT("CurrentEntry: %p. CurrentHash: %lx\n", CurrentEntry, CurrentEntry->HashValue);
+ if (CurrentEntry->HashValue == HashValue)
+ {
+ /* Make sure that it has a name */
+ ASSERT(BODY_TO_HEADER(CurrentEntry->Object)->NameInfoOffset != 0);
+
+ /* Get the name information */
+ HeaderNameInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(CurrentEntry->Object));
+
+ /* Do the names match? */
+ DPRINT("NameCheck: %wZ, %wZ\n", Name, &HeaderNameInfo->Name);
+ if ((Name->Length == HeaderNameInfo->Name.Length) &&
+ (RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
+ {
+ DPRINT("Found Name Match\n");
+ break;
+ }
+ }
+
+ /* Move to the next entry */
+ AllocatedEntry = &CurrentEntry->ChainLink;
+ }
+
+ /* Check if we still have an entry */
+ if (CurrentEntry)
+ {
+ /* Set this entry as the first, to speed up incoming insertion */
+ if (AllocatedEntry != LookupBucket)
+ {
+ /* Set the Current Entry */
+ *AllocatedEntry = CurrentEntry->ChainLink;
+
+ /* Link to the old Hash Entry */
+ CurrentEntry->ChainLink = *LookupBucket;
+
+ /* Set the new Hash Entry */
+ *LookupBucket = CurrentEntry;
+ }
+
+ /* Save the found object */
+ FoundObject = CurrentEntry->Object;
+ if (!FoundObject) goto Quickie;
+
+ /* Add a reference to the object */
+ ObReferenceObject(FoundObject);
+ }
+
+ /* Check if the directory was unlocked (which means we locked it) */
+ if (!Context->DirectoryLocked)
+ {
+ /* Lock it */
+ ExReleaseResourceLite(&Directory->Lock);
+ KeLeaveCriticalRegion();
+ Context->LockStateSignature = 0xEEEE1234;
+ }
+
+Quickie:
+ /* Return the object we found */
+ DPRINT("Object Found: %p Context: %p\n", FoundObject, Context);
+ Context->Object = FoundObject;
+ return FoundObject;
+}
+
+BOOLEAN
+NTAPI
+ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context)
+{
+ POBJECT_DIRECTORY Directory;
+ POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
+ POBJECT_DIRECTORY_ENTRY CurrentEntry;
+
+ /* Get the Directory */
+ Directory = Context->Directory;
+ if (!Directory) return FALSE;
+
+ /* Get the Entry */
+ AllocatedEntry = &Directory->HashBuckets[Context->HashIndex];
+ CurrentEntry = *AllocatedEntry;
+ DPRINT("DEL: Parent: %p, Hash: %lx, AllocatedEntry: %p, CurrentEntry: %p\n",
+ Directory, Context->HashIndex, AllocatedEntry, CurrentEntry);
+
+ /* Unlink the Entry */
+ *AllocatedEntry = CurrentEntry->ChainLink;
+ CurrentEntry->ChainLink = NULL;
+
+ /* Free it */
+ ExFreePool(CurrentEntry);
+
+ /* Return */
+ return TRUE;
+}
+
+NTSTATUS
+NTAPI
+ObpParseDirectory(PVOID Object,
+ PVOID * NextObject,
+ PUNICODE_STRING FullPath,
+ PWSTR * Path,
+ ULONG Attributes,
+ POBP_LOOKUP_CONTEXT Context)
+{
+ PWSTR Start;
+ PWSTR End;
+ PVOID FoundObject;
+ //KIRQL oldlvl;
+ UNICODE_STRING StartUs;
+
+ *NextObject = NULL;
+
+ if ((*Path) == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Start = *Path;
+ if (*Start == L'\\')
+ Start++;
+
+ End = wcschr(Start, L'\\');
+ if (End != NULL)
+ {
+ *End = 0;
+ }
+
+ //KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
+ RtlInitUnicodeString(&StartUs, Start);
+ Context->DirectoryLocked = TRUE;
+ Context->Directory = Object;
+ FoundObject = ObpLookupEntryDirectory(Object, &StartUs, Attributes, FALSE, Context);
+ if (FoundObject == NULL)
+ {
+ //KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
+ if (End != NULL)
+ {
+ *End = L'\\';
+ }
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ ObReferenceObjectByPointer(FoundObject,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
+ //KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
+ if (End != NULL)
+ {
+ *End = L'\\';
+ *Path = End;
+ }
+ else
+ {
+ *Path = NULL;
+ }
+
+ *NextObject = FoundObject;
+
+ return STATUS_SUCCESS;
+}
+
+/* FUNCTIONS **************************************************************/
+
+/*++
+* @name NtOpenDirectoryObject
+* @implemented NT4
+*
+* The NtOpenDirectoryObject opens a namespace directory object.
+*
+* @param DirectoryHandle
+* Variable which receives the directory handle.
+*
+* @param DesiredAccess
+* Desired access to the directory.
+*
+* @param ObjectAttributes
+* Structure describing the directory.
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks None.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
+{
+ HANDLE hDirectory;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(DirectoryHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenDirectoryObject failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+ }
+
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ObDirectoryType,
+ NULL,
+ PreviousMode,
+ DesiredAccess,
+ NULL,
+ &hDirectory);
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *DirectoryHandle = hDirectory;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ return Status;
+}
+
+/*++
+* @name NtQueryDirectoryObject
+* @implemented NT4
+*
+* The NtQueryDirectoryObject Reads information from a directory in
+* the system namespace.
+*
+* @param DirectoryHandle
+* Handle obtained with NtOpenDirectoryObject which
+* must grant DIRECTORY_QUERY access to the directory object.
+*
+* @param Buffer
+* Buffer to hold the data read.
+*
+* @param BufferLength
+* Size of the buffer in bytes.
+*
+* @param ReturnSingleEntry
+* When TRUE, only 1 entry is written in DirObjInformation;
+* otherwise as many as will fit in the buffer.
+*
+* @param RestartScan
+* If TRUE start reading at index 0.
+* If FALSE start reading at the index specified by *ObjectIndex.
+*
+* @param Context
+* Zero based index into the directory, interpretation
+* depends on RestartScan.
+*
+* @param ReturnLength
+* Caller supplied storage for the number of bytes
+* written (or NULL).
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks Although you can iterate over the directory by calling this
+* function multiple times, the directory is unlocked between
+* calls. This means that another thread can change the directory
+* and so iterating doesn't guarantee a consistent picture of the
+* directory. Best thing is to retrieve all directory entries in
+* one call.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ IN BOOLEAN ReturnSingleEntry,
+ IN BOOLEAN RestartScan,
+ IN OUT PULONG Context,
+ OUT PULONG ReturnLength OPTIONAL)
+{
+ POBJECT_DIRECTORY Directory;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ ULONG SkipEntries = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ /* a test showed that the Buffer pointer just has to be 16 bit aligned,
+ propably due to the fact that most information that needs to be copied
+ is unicode strings */
+ ProbeForWrite(Buffer, BufferLength, sizeof(WCHAR));
+ ProbeForWriteUlong(Context);
+ if(!RestartScan)
+ {
+ SkipEntries = *Context;
+ }
+ if(ReturnLength != NULL)
+ {
+ ProbeForWriteUlong(ReturnLength);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryDirectoryObject failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+ }
+ else if(!RestartScan)
+ {
+ SkipEntries = *Context;
+ }
+
+ Status = ObReferenceObjectByHandle(DirectoryHandle,
+ DIRECTORY_QUERY,
+ ObDirectoryType,
+ PreviousMode,
+ (PVOID*)&Directory,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ return Status;
+}
+
+/*++
+* @name NtCreateDirectoryObject
+* @implemented NT4
+*
+* The NtOpenDirectoryObject creates or opens a directory object.
+*
+* @param DirectoryHandle
+* Variable which receives the directory handle.
+*
+* @param DesiredAccess
+* Desired access to the directory.
+*
+* @param ObjectAttributes
+* Structure describing the directory.
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks None.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
+{
+ POBJECT_DIRECTORY Directory;
+ HANDLE hDirectory;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
+ "DesiredAccess %x, ObjectAttributes %x\n",
+ DirectoryHandle, DesiredAccess, ObjectAttributes);
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(DirectoryHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtCreateDirectoryObject failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+ }
+
+ Status = ObCreateObject(PreviousMode,
+ ObDirectoryType,
+ ObjectAttributes,
+ PreviousMode,
+ NULL,
+ sizeof(OBJECT_DIRECTORY),
+ 0,
+ 0,
+ (PVOID*)&Directory);
+
+ if(NT_SUCCESS(Status))
+ {
+ Status = ObInsertObject((PVOID)Directory,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &hDirectory);
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *DirectoryHandle = hDirectory;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ ObDereferenceObject(Directory);
+ }
+
+ return Status;
+}
+
+/* EOF */
diff --git a/reactos/ntoskrnl/ob/obhandle.c b/reactos/ntoskrnl/ob/obhandle.c
new file mode 100644
index 00000000000..8810cb8aba6
--- /dev/null
+++ b/reactos/ntoskrnl/ob/obhandle.c
@@ -0,0 +1,1407 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ob/obhandle.c
+ * PURPOSE: Manages all functions related to the Object Manager handle
+ * implementation, including creating and destroying handles
+ * and/or handle tables, duplicating objects, and setting the
+ * permanent or temporary flags.
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Eric Kohl
+ * Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+PHANDLE_TABLE ObpKernelHandleTable = NULL;
+
+/* TEMPORARY HACK. DO NOT REMOVE -- Alex */
+NTSTATUS
+STDCALL
+ExpDesktopCreate(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ POBJECT_CREATE_INFORMATION ObjectCreateInformation);
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+* @name ObpSetPermanentObject
+*
+* The ObpSetPermanentObject routine
+*
+* @param ObjectBody
+*
+*
+* @param Permanent
+*
+*
+* @return None.
+*
+* @remarks None.
+*
+*--*/
+VOID
+FASTCALL
+ObpSetPermanentObject(IN PVOID ObjectBody,
+ IN BOOLEAN Permanent)
+{
+ POBJECT_HEADER ObjectHeader;
+ OBP_LOOKUP_CONTEXT Context;
+
+ ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ ASSERT (ObjectHeader->PointerCount > 0);
+ if (Permanent)
+ {
+ ObjectHeader->Flags |= OB_FLAG_PERMANENT;
+ }
+ else
+ {
+ ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
+ if (ObjectHeader->HandleCount == 0 &&
+ HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory)
+ {
+ /* Make sure it's still inserted */
+ Context.Directory = HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory;
+ Context.DirectoryLocked = TRUE;
+ if (ObpLookupEntryDirectory(HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory,
+ &HEADER_TO_OBJECT_NAME(ObjectHeader)->Name,
+ 0,
+ FALSE,
+ &Context))
+ {
+ ObpDeleteEntryDirectory(&Context);
+ }
+ }
+ }
+}
+
+ULONG
+NTAPI
+ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
+{
+ return HandleTable->HandleCount;
+}
+
+VOID
+ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
+ PEPROCESS Process,
+ int Count)
+{
+ ULONG P;
+ // KIRQL oldIrql;
+
+ // 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;
+
+ // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
+
+ // pshi->GrantedAccess;
+ // pshi->Object;
+ // pshi->TypeIndex;
+ // pshi->HandleAttributes;
+
+ // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
+
+ return;
+}
+static VOID
+ObpDecrementHandleCount(PVOID ObjectBody)
+{
+ POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+ LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
+ OBP_LOOKUP_CONTEXT Context;
+ 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(NULL, ObjectBody, 0, NewHandleCount + 1, 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. */
+
+ /* Make sure it's still inserted */
+ Context.Directory = HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory;
+ Context.DirectoryLocked = TRUE;
+ if (ObpLookupEntryDirectory(HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory,
+ &HEADER_TO_OBJECT_NAME(ObjectHeader)->Name,
+ 0,
+ FALSE,
+ &Context))
+ {
+ ObpDeleteEntryDirectory(&Context);
+ }
+ }
+
+ /* remove the keep-alive reference */
+ ObDereferenceObject(ObjectBody);
+ }
+}
+
+NTSTATUS
+NTAPI
+ObpQueryHandleAttributes(HANDLE Handle,
+ POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
+{
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+ PEPROCESS Process, CurrentProcess;
+ KAPC_STATE ApcState;
+ BOOLEAN AttachedToProcess = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle);
+ CurrentProcess = PsGetCurrentProcess();
+
+ KeEnterCriticalRegion();
+
+ if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+ {
+ Process = PsInitialSystemProcess;
+ Handle = ObKernelHandleToHandle(Handle);
+
+ if (Process != CurrentProcess)
+ {
+ KeStackAttachProcess(&Process->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ }
+ else
+ {
+ Process = CurrentProcess;
+ }
+
+ HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+ Handle);
+ if (HandleTableEntry != NULL)
+ {
+ HandleInfo->Inherit = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+ HandleInfo->ProtectFromClose = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
+
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleTableEntry);
+ }
+ else
+ Status = STATUS_INVALID_HANDLE;
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ KeLeaveCriticalRegion();
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+ObpSetHandleAttributes(HANDLE Handle,
+ POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
+{
+ PHANDLE_TABLE_ENTRY HandleTableEntry;
+ PEPROCESS Process, CurrentProcess;
+ KAPC_STATE ApcState;
+ BOOLEAN AttachedToProcess = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle);
+ CurrentProcess = PsGetCurrentProcess();
+
+ KeEnterCriticalRegion();
+
+ if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+ {
+ Process = PsInitialSystemProcess;
+ Handle = ObKernelHandleToHandle(Handle);
+
+ if (Process != CurrentProcess)
+ {
+ KeStackAttachProcess(&Process->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ }
+ else
+ {
+ Process = CurrentProcess;
+ }
+
+ HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+ Handle);
+ if (HandleTableEntry != NULL)
+ {
+ if (HandleInfo->Inherit)
+ HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+ else
+ HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+
+ if (HandleInfo->ProtectFromClose)
+ HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+ else
+ HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+
+ /* FIXME: Do we need to set anything in the object header??? */
+
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleTableEntry);
+ }
+ else
+ Status = STATUS_INVALID_HANDLE;
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ KeLeaveCriticalRegion();
+
+ return Status;
+}
+
+static NTSTATUS
+ObpDeleteHandle(HANDLE Handle)
+{
+ PHANDLE_TABLE_ENTRY HandleEntry;
+ PVOID Body;
+ POBJECT_HEADER ObjectHeader;
+ PHANDLE_TABLE ObjectTable;
+
+ PAGED_CODE();
+
+ DPRINT("ObpDeleteHandle(Handle %p)\n",Handle);
+
+ ObjectTable = PsGetCurrentProcess()->ObjectTable;
+
+ KeEnterCriticalRegion();
+
+ HandleEntry = ExMapHandleToPointer(ObjectTable,
+ Handle);
+ if(HandleEntry != NULL)
+ {
+ if(HandleEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
+ {
+ ExUnlockHandleTableEntry(ObjectTable,
+ HandleEntry);
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_HANDLE_NOT_CLOSABLE;
+ }
+
+ ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+ Body = &ObjectHeader->Body;
+
+ /* destroy and unlock the handle entry */
+ ExDestroyHandleByEntry(ObjectTable,
+ HandleEntry,
+ Handle);
+
+ ObpDecrementHandleCount(Body);
+
+ KeLeaveCriticalRegion();
+
+ return STATUS_SUCCESS;
+ }
+ KeLeaveCriticalRegion();
+ return STATUS_INVALID_HANDLE;
+}
+
+NTSTATUS
+NTAPI
+ObDuplicateObject(PEPROCESS SourceProcess,
+ PEPROCESS TargetProcess,
+ HANDLE SourceHandle,
+ PHANDLE TargetHandle,
+ ACCESS_MASK DesiredAccess,
+ ULONG HandleAttributes,
+ ULONG Options)
+{
+ PHANDLE_TABLE_ENTRY SourceHandleEntry;
+ HANDLE_TABLE_ENTRY NewHandleEntry;
+ BOOLEAN AttachedToProcess = FALSE;
+ PVOID ObjectBody;
+ POBJECT_HEADER ObjectHeader;
+ ULONG NewHandleCount;
+ HANDLE NewTargetHandle;
+ PEPROCESS CurrentProcess;
+ KAPC_STATE ApcState;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ if(SourceProcess == NULL ||
+ ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
+ {
+ SourceProcess = PsInitialSystemProcess;
+ SourceHandle = ObKernelHandleToHandle(SourceHandle);
+ }
+
+ CurrentProcess = PsGetCurrentProcess();
+
+ KeEnterCriticalRegion();
+
+ if (SourceProcess != CurrentProcess)
+ {
+ KeStackAttachProcess(&SourceProcess->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
+ SourceHandle);
+ if (SourceHandleEntry == NULL)
+ {
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ KeLeaveCriticalRegion();
+ return STATUS_INVALID_HANDLE;
+ }
+
+ ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
+ ObjectBody = &ObjectHeader->Body;
+
+ NewHandleEntry.Object = SourceHandleEntry->Object;
+ if(HandleAttributes & OBJ_INHERIT)
+ NewHandleEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+ else
+ NewHandleEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+ NewHandleEntry.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
+ SourceHandleEntry->GrantedAccess :
+ DesiredAccess);
+ if (Options & DUPLICATE_SAME_ACCESS)
+ {
+ NewHandleEntry.GrantedAccess = SourceHandleEntry->GrantedAccess;
+ }
+ else
+ {
+ if (DesiredAccess & GENERIC_ACCESS)
+ {
+ RtlMapGenericMask(&DesiredAccess,
+ &ObjectHeader->Type->TypeInfo.GenericMapping);
+ }
+ NewHandleEntry.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(SourceProcess->ObjectTable,
+ SourceHandleEntry);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ AttachedToProcess = FALSE;
+ }
+
+ if (TargetProcess != CurrentProcess)
+ {
+ KeStackAttachProcess(&TargetProcess->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+
+ /* attempt to create the new handle */
+ NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
+ &NewHandleEntry);
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ AttachedToProcess = FALSE;
+ }
+
+ if (NewTargetHandle != NULL)
+ {
+ if (Options & DUPLICATE_CLOSE_SOURCE)
+ {
+ if (SourceProcess != CurrentProcess)
+ {
+ KeStackAttachProcess(&SourceProcess->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+
+ /* delete the source handle */
+ ObpDeleteHandle(SourceHandle);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+ }
+
+ ObDereferenceObject(ObjectBody);
+
+ *TargetHandle = NewTargetHandle;
+ }
+ 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);
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ KeLeaveCriticalRegion();
+
+ return Status;
+}
+
+static VOID STDCALL
+SweepHandleCallback(PHANDLE_TABLE HandleTable,
+ PVOID Object,
+ ULONG GrantedAccess,
+ PVOID Context)
+{
+ POBJECT_HEADER ObjectHeader;
+ PVOID ObjectBody;
+
+ PAGED_CODE();
+
+ ObjectHeader = EX_OBJ_TO_HDR(Object);
+ ObjectBody = &ObjectHeader->Body;
+
+ ObpDecrementHandleCount(ObjectBody);
+}
+
+static BOOLEAN STDCALL
+DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
+ PHANDLE_TABLE_ENTRY HandleTableEntry,
+ PVOID Context)
+{
+ POBJECT_HEADER ObjectHeader;
+ BOOLEAN Ret = FALSE;
+
+ PAGED_CODE();
+
+ Ret = (HandleTableEntry->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
+NTAPI
+ObCreateHandleTable(PEPROCESS Parent,
+ BOOLEAN Inherit,
+ PEPROCESS Process)
+ /*
+ * FUNCTION: Creates a handle table for a process
+ * ARGUMENTS:
+ * Parent = Parent process (or NULL if this is the first process)
+ * Inherit = True if the process should inherit its parent's handles
+ * Process = Process whose handle table is to be created
+ */
+{
+ PAGED_CODE();
+
+ DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
+ Parent,Inherit,Process);
+ if(Parent != NULL)
+ {
+ Process->ObjectTable = ExDupHandleTable(Process,
+ DuplicateHandleCallback,
+ NULL,
+ Parent->ObjectTable);
+ }
+ else
+ {
+ Process->ObjectTable = ExCreateHandleTable(Process);
+ }
+}
+
+
+VOID
+STDCALL
+ObKillProcess(PEPROCESS Process)
+{
+ PAGED_CODE();
+
+ /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */
+ ExSweepHandleTable(Process->ObjectTable,
+ SweepHandleCallback,
+ Process);
+ ExDestroyHandleTable(Process->ObjectTable);
+ Process->ObjectTable = NULL;
+}
+
+
+NTSTATUS
+NTAPI
+ObpCreateHandle(PVOID ObjectBody,
+ ACCESS_MASK GrantedAccess,
+ ULONG HandleAttributes,
+ PHANDLE HandleReturn)
+ /*
+ * FUNCTION: Add a handle referencing an object
+ * ARGUMENTS:
+ * obj = Object body that the handle should refer to
+ * RETURNS: The created handle
+ * NOTE: The handle is valid only in the context of the current process
+ */
+{
+ HANDLE_TABLE_ENTRY NewEntry;
+ PEPROCESS Process, CurrentProcess;
+ POBJECT_HEADER ObjectHeader;
+ HANDLE Handle;
+ KAPC_STATE ApcState;
+ BOOLEAN AttachedToProcess = FALSE;
+
+ PAGED_CODE();
+
+ DPRINT("ObpCreateHandle(obj %p)\n",ObjectBody);
+
+ ASSERT(ObjectBody);
+
+ CurrentProcess = PsGetCurrentProcess();
+
+ ObjectHeader = BODY_TO_HEADER(ObjectBody);
+
+ /* check that this is a valid kernel pointer */
+ ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
+
+ if (GrantedAccess & MAXIMUM_ALLOWED)
+ {
+ GrantedAccess &= ~MAXIMUM_ALLOWED;
+ GrantedAccess |= GENERIC_ALL;
+ }
+
+ if (GrantedAccess & GENERIC_ACCESS)
+ {
+ RtlMapGenericMask(&GrantedAccess,
+ &ObjectHeader->Type->TypeInfo.GenericMapping);
+ }
+
+ NewEntry.Object = ObjectHeader;
+ if(HandleAttributes & OBJ_INHERIT)
+ NewEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+ else
+ NewEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+ NewEntry.GrantedAccess = GrantedAccess;
+
+ if ((HandleAttributes & OBJ_KERNEL_HANDLE) &&
+ ExGetPreviousMode == KernelMode)
+ {
+ Process = PsInitialSystemProcess;
+ if (Process != CurrentProcess)
+ {
+ KeStackAttachProcess(&Process->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ }
+ else
+ {
+ Process = CurrentProcess;
+ /* mask out the OBJ_KERNEL_HANDLE attribute */
+ HandleAttributes &= ~OBJ_KERNEL_HANDLE;
+ }
+
+ Handle = ExCreateHandle(Process->ObjectTable,
+ &NewEntry);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ if(Handle != NULL)
+ {
+ if (HandleAttributes & OBJ_KERNEL_HANDLE)
+ {
+ /* mark the handle value */
+ Handle = ObMarkHandleAsKernelHandle(Handle);
+ }
+
+ if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+ {
+ ObReferenceObject(ObjectBody);
+ }
+
+ *HandleReturn = Handle;
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+/*
+* @implemented
+*/
+NTSTATUS STDCALL
+ObQueryObjectAuditingByHandle(IN HANDLE Handle,
+ OUT PBOOLEAN GenerateOnClose)
+{
+ PHANDLE_TABLE_ENTRY HandleEntry;
+ PEPROCESS Process, CurrentProcess;
+ KAPC_STATE ApcState;
+ BOOLEAN AttachedToProcess = FALSE;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ DPRINT("ObQueryObjectAuditingByHandle(Handle %p)\n", Handle);
+
+ CurrentProcess = PsGetCurrentProcess();
+
+ KeEnterCriticalRegion();
+
+ if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+ {
+ Process = PsInitialSystemProcess;
+ Handle = ObKernelHandleToHandle(Handle);
+
+ if (Process != CurrentProcess)
+ {
+ KeStackAttachProcess(&Process->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ }
+ else
+ Process = CurrentProcess;
+
+ HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+ Handle);
+ if(HandleEntry != NULL)
+ {
+ *GenerateOnClose = (HandleEntry->ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
+
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
+ }
+ else
+ Status = STATUS_INVALID_HANDLE;
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ KeLeaveCriticalRegion();
+
+ return Status;
+}
+/* PUBLIC FUNCTIONS *********************************************************/
+
+ULONG
+NTAPI
+ObGetObjectHandleCount(PVOID Object)
+{
+ POBJECT_HEADER Header;
+
+ PAGED_CODE();
+
+ ASSERT(Object);
+ Header = BODY_TO_HEADER(Object);
+
+ return Header->HandleCount;
+}
+
+NTSTATUS STDCALL
+ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN POBJECT_TYPE ObjectType,
+ IN OUT PVOID ParseContext,
+ IN KPROCESSOR_MODE AccessMode,
+ IN ACCESS_MASK DesiredAccess,
+ IN PACCESS_STATE PassedAccessState,
+ OUT PHANDLE Handle)
+{
+ UNICODE_STRING RemainingPath;
+ PVOID Object = NULL;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ NTSTATUS Status;
+ OBP_LOOKUP_CONTEXT Context;
+
+ PAGED_CODE();
+
+ DPRINT("ObOpenObjectByName(...)\n");
+
+ /* Capture all the info */
+ DPRINT("Capturing Create Info\n");
+ Status = ObpCaptureObjectAttributes(ObjectAttributes,
+ AccessMode,
+ ObjectType,
+ &ObjectCreateInfo,
+ &ObjectName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ &Object,
+ &RemainingPath,
+ ObjectType,
+ &Context);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObFindObject() failed (Status %lx)\n", Status);
+ goto Cleanup;
+ }
+
+ DPRINT("OBject: %p, Remaining Path: %wZ\n", Object, &RemainingPath);
+ if (Object == NULL)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
+ }
+ if (RemainingPath.Buffer != NULL)
+ {
+ if (wcschr(RemainingPath.Buffer + 1, L'\\') == NULL)
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ else
+ Status =STATUS_OBJECT_PATH_NOT_FOUND;
+ goto Cleanup;
+ }
+
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ ObjectCreateInfo.Attributes,
+ Handle);
+
+Cleanup:
+ if (Object != NULL)
+ {
+ ObDereferenceObject(Object);
+ }
+ RtlFreeUnicodeString(&RemainingPath);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+
+ return Status;
+}
+
+/*
+* @implemented
+*/
+NTSTATUS STDCALL
+ObOpenObjectByPointer(IN PVOID Object,
+ IN ULONG HandleAttributes,
+ IN PACCESS_STATE PassedAccessState,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_TYPE ObjectType,
+ IN KPROCESSOR_MODE AccessMode,
+ OUT PHANDLE Handle)
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("ObOpenObjectByPointer()\n");
+
+ Status = ObReferenceObjectByPointer(Object,
+ 0,
+ ObjectType,
+ AccessMode);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ HandleAttributes,
+ Handle);
+
+ ObDereferenceObject(Object);
+
+ return STATUS_SUCCESS;
+}
+
+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;
+}
+
+/*++
+* @name ObMakeTemporaryObject
+* @implemented NT4
+*
+* The ObMakeTemporaryObject routine
+*
+* @param ObjectBody
+*
+*
+* @return None.
+*
+* @remarks None.
+*
+*--*/
+VOID
+NTAPI
+ObMakeTemporaryObject(IN PVOID ObjectBody)
+{
+ ObpSetPermanentObject (ObjectBody, FALSE);
+}
+
+/*
+* @implemented
+*/
+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)
+{
+ 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;
+ OBP_LOOKUP_CONTEXT Context;
+
+ 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,
+ &Context);
+ 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);
+ }
+
+ 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;
+
+ 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;
+ ObpInsertEntryDirectory(FoundObject, &Context, Header);
+ ObjectAttached = TRUE;
+ }
+
+ 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,
+ NULL,
+ &Header->Body,
+ 0,
+ 0);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Create Failed\n");
+ if (ObjectAttached == TRUE)
+ {
+ ObpDeleteEntryDirectory(&Context);
+ }
+ if (FoundObject)
+ {
+ ObDereferenceObject(FoundObject);
+ }
+ RtlFreeUnicodeString(&RemainingPath);
+ return Status;
+ }
+ }
+
+ 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(&Header->Body,
+ DesiredAccess,
+ ObjectCreateInfo->Attributes,
+ 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;
+}
+
+/*
+* @implemented
+*/
+NTSTATUS STDCALL
+NtDuplicateObject (IN HANDLE SourceProcessHandle,
+ IN HANDLE SourceHandle,
+ IN HANDLE TargetProcessHandle,
+ OUT PHANDLE TargetHandle OPTIONAL,
+ IN ACCESS_MASK DesiredAccess,
+ IN ULONG HandleAttributes,
+ IN ULONG Options)
+{
+ PEPROCESS SourceProcess;
+ PEPROCESS TargetProcess;
+ PEPROCESS CurrentProcess;
+ HANDLE hTarget;
+ BOOLEAN AttachedToProcess = FALSE;
+ KPROCESSOR_MODE PreviousMode;
+ KAPC_STATE ApcState;
+ 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,
+ PreviousMode,
+ (PVOID*)&SourceProcess,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = ObReferenceObjectByHandle(TargetProcessHandle,
+ PROCESS_DUP_HANDLE,
+ NULL,
+ PreviousMode,
+ (PVOID*)&TargetProcess,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(SourceProcess);
+ return(Status);
+ }
+
+ CurrentProcess = PsGetCurrentProcess();
+
+ /* Check for magic handle first */
+ if (SourceHandle == NtCurrentThread() ||
+ SourceHandle == NtCurrentProcess())
+ {
+ 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_ACCESS)
+ {
+ RtlMapGenericMask(&DesiredAccess,
+ &ObjectType->TypeInfo.GenericMapping);
+ }
+ }
+
+ if (TargetProcess != CurrentProcess)
+ {
+ KeStackAttachProcess(&TargetProcess->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+
+ Status = ObpCreateHandle(ObjectBody,
+ DesiredAccess,
+ HandleAttributes,
+ &hTarget);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ AttachedToProcess = FALSE;
+ }
+
+ ObDereferenceObject(ObjectBody);
+
+ if (Options & DUPLICATE_CLOSE_SOURCE)
+ {
+ if (SourceProcess != CurrentProcess)
+ {
+ KeStackAttachProcess(&SourceProcess->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+
+ ObpDeleteHandle(SourceHandle);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+ }
+ }
+ }
+ else
+ {
+ Status = ObDuplicateObject(SourceProcess,
+ TargetProcess,
+ SourceHandle,
+ &hTarget,
+ DesiredAccess,
+ HandleAttributes,
+ Options);
+ }
+
+ ObDereferenceObject(TargetProcess);
+ ObDereferenceObject(SourceProcess);
+
+ if(NT_SUCCESS(Status) && TargetHandle != NULL)
+ {
+ _SEH_TRY
+ {
+ *TargetHandle = hTarget;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ return Status;
+}
+
+NTSTATUS STDCALL
+NtClose(IN HANDLE Handle)
+{
+ PEPROCESS Process, CurrentProcess;
+ BOOLEAN AttachedToProcess = FALSE;
+ KAPC_STATE ApcState;
+ NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+ CurrentProcess = PsGetCurrentProcess();
+
+ if(ObIsKernelHandle(Handle, PreviousMode))
+ {
+ Process = PsInitialSystemProcess;
+ Handle = ObKernelHandleToHandle(Handle);
+
+ if (Process != CurrentProcess)
+ {
+ KeStackAttachProcess(&Process->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+ }
+ else
+ Process = CurrentProcess;
+
+ Status = ObpDeleteHandle(Handle);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ if((PreviousMode != KernelMode) &&
+ (CurrentProcess->ExceptionPort))
+ {
+ KeRaiseUserException(Status);
+ }
+ return Status;
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+/*++
+* @name NtMakeTemporaryObject
+* @implemented NT4
+*
+* The NtMakeTemporaryObject routine
+*
+* @param ObjectHandle
+*
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks None.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtMakeTemporaryObject(IN HANDLE ObjectHandle)
+{
+ PVOID ObjectBody;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ NULL,
+ KeGetPreviousMode(),
+ &ObjectBody,
+ NULL);
+ if (Status != STATUS_SUCCESS) return Status;
+
+ ObpSetPermanentObject (ObjectBody, FALSE);
+
+ ObDereferenceObject(ObjectBody);
+
+ return STATUS_SUCCESS;
+}
+
+/*++
+* @name NtMakePermanentObject
+* @implemented NT4
+*
+* The NtMakePermanentObject routine
+*
+* @param ObjectHandle
+*
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks None.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtMakePermanentObject(IN HANDLE ObjectHandle)
+{
+ PVOID ObjectBody;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ NULL,
+ KeGetPreviousMode(),
+ &ObjectBody,
+ NULL);
+ if (Status != STATUS_SUCCESS) return Status;
+
+ ObpSetPermanentObject (ObjectBody, TRUE);
+
+ ObDereferenceObject(ObjectBody);
+
+ return STATUS_SUCCESS;
+}
+/* EOF */
diff --git a/reactos/ntoskrnl/ob/obinit.c b/reactos/ntoskrnl/ob/obinit.c
new file mode 100644
index 00000000000..523bd0cb1eb
--- /dev/null
+++ b/reactos/ntoskrnl/ob/obinit.c
@@ -0,0 +1,174 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ob/init.c
+ * PURPOSE: Handles Object Manager Initialization and Shutdown
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Eric Kohl
+ * Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ObInit)
+#endif
+
+GENERIC_MAPPING ObpTypeMapping =
+{
+ STANDARD_RIGHTS_READ,
+ STANDARD_RIGHTS_WRITE,
+ STANDARD_RIGHTS_EXECUTE,
+ 0x000F0001
+};
+
+GENERIC_MAPPING ObpDirectoryMapping =
+{
+ STANDARD_RIGHTS_READ | DIRECTORY_QUERY |
+ DIRECTORY_TRAVERSE,
+ STANDARD_RIGHTS_WRITE | DIRECTORY_CREATE_SUBDIRECTORY |
+ DIRECTORY_CREATE_OBJECT,
+ STANDARD_RIGHTS_EXECUTE | DIRECTORY_QUERY |
+ DIRECTORY_TRAVERSE,
+ DIRECTORY_ALL_ACCESS
+};
+
+PDEVICE_MAP ObSystemDeviceMap = NULL;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+INIT_FUNCTION
+ObInit(VOID)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING Name;
+ SECURITY_DESCRIPTOR SecurityDescriptor;
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ OBP_LOOKUP_CONTEXT Context;
+
+ /* Initialize the security descriptor cache */
+ ObpInitSdCache();
+
+ /* Initialize the Default Event */
+ KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
+
+ /* Create the Type Type */
+ DPRINT("Creating Type Type\n");
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Type");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
+ ObjectTypeInitializer.UseDefaultObject = TRUE;
+ ObjectTypeInitializer.MaintainTypeList = TRUE;
+ ObjectTypeInitializer.PoolType = NonPagedPool;
+ ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
+
+ /* Create the Directory Type */
+ DPRINT("Creating Directory Type\n");
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Directory");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
+ ObjectTypeInitializer.UseDefaultObject = FALSE;
+ ObjectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD)ObpParseDirectory;
+ ObjectTypeInitializer.MaintainTypeList = FALSE;
+ ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
+
+ /* Create security descriptor */
+ RtlCreateSecurityDescriptor(&SecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION1);
+ RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
+ SeAliasAdminsSid,
+ FALSE);
+ RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
+ SeLocalSystemSid,
+ FALSE);
+ RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
+ TRUE,
+ SePublicDefaultDacl,
+ FALSE);
+
+ /* Create root directory */
+ DPRINT("Creating Root Directory\n");
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ NULL,
+ &SecurityDescriptor);
+ ObCreateObject(KernelMode,
+ ObDirectoryType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(OBJECT_DIRECTORY),
+ 0,
+ 0,
+ (PVOID*)&NameSpaceRoot);
+ ObInsertObject((PVOID)NameSpaceRoot,
+ NULL,
+ DIRECTORY_ALL_ACCESS,
+ 0,
+ NULL,
+ NULL);
+
+ /* Create '\ObjectTypes' directory */
+ RtlInitUnicodeString(&Name, L"\\ObjectTypes");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_PERMANENT,
+ NULL,
+ &SecurityDescriptor);
+ ObCreateObject(KernelMode,
+ ObDirectoryType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(OBJECT_DIRECTORY),
+ 0,
+ 0,
+ (PVOID*)&ObpTypeDirectoryObject);
+ ObInsertObject((PVOID)ObpTypeDirectoryObject,
+ NULL,
+ DIRECTORY_ALL_ACCESS,
+ 0,
+ NULL,
+ NULL);
+
+ /* Insert the two objects we already created but couldn't add */
+ /* NOTE: Uses TypeList & Creator Info in OB 2.0 */
+ Context.Directory = ObpTypeDirectoryObject;
+ Context.DirectoryLocked = TRUE;
+ if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
+ &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObTypeObjectType))->Name,
+ OBJ_CASE_INSENSITIVE,
+ FALSE,
+ &Context))
+ {
+ ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, BODY_TO_HEADER(ObTypeObjectType));
+ }
+ if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
+ &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObDirectoryType))->Name,
+ OBJ_CASE_INSENSITIVE,
+ FALSE,
+ &Context))
+ {
+ ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, BODY_TO_HEADER(ObDirectoryType));
+ }
+
+ /* Create 'symbolic link' object type */
+ ObInitSymbolicLinkImplementation();
+
+ /* FIXME: Hack Hack! */
+ ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
+ RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
+}
+/* EOF */
diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c
deleted file mode 100644
index 7078260614b..00000000000
--- a/reactos/ntoskrnl/ob/object.c
+++ /dev/null
@@ -1,1294 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ob/object.c
- * PURPOSE: Implements generic object managment functions
- *
- * PROGRAMMERS: David Welch (welch@cwcom.net)
- * Skywing (skywing@valhallalegends.com)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include
-#define NDEBUG
-#include
-
-#define UNICODE_PATH_SEP L'\\'
-#define UNICODE_NO_PATH L"..."
-#define OB_NAME_TAG TAG('O','b','N','m')
-
-typedef struct _RETENTION_CHECK_PARAMS
-{
- WORK_QUEUE_ITEM WorkItem;
- POBJECT_HEADER ObjectHeader;
-} RETENTION_CHECK_PARAMS, *PRETENTION_CHECK_PARAMS;
-
-/* FUNCTIONS ************************************************************/
-
-NTSTATUS
-STDCALL
-ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
- IN PUNICODE_STRING ObjectName,
- IN KPROCESSOR_MODE AccessMode)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- ULONG StringLength;
- PWCHAR StringBuffer = NULL;
- UNICODE_STRING LocalName = {}; /* <= GCC 4.0 + Optimizer */
-
- /* Initialize the Input String */
- RtlInitUnicodeString(CapturedName, NULL);
-
- /* Protect everything */
- _SEH_TRY
- {
- /* First Probe the String */
- DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName);
- if (AccessMode != KernelMode)
- {
- ProbeForRead(ObjectName,
- sizeof(UNICODE_STRING),
- sizeof(USHORT));
- LocalName = *ObjectName;
-
- ProbeForRead(LocalName.Buffer,
- LocalName.Length,
- sizeof(WCHAR));
- }
- else
- {
- /* No probing needed */
- LocalName = *ObjectName;
- }
-
- /* Make sure there really is a string */
- DPRINT("Probing OK\n");
- if ((StringLength = LocalName.Length))
- {
- /* Check that the size is a valid WCHAR multiple */
- if ((StringLength & (sizeof(WCHAR) - 1)) ||
- /* Check that the NULL-termination below will work */
- (StringLength == (MAXUSHORT - sizeof(WCHAR) + 1)))
- {
- /* PS: Please keep the checks above expanded for clarity */
- DPRINT1("Invalid String Length\n");
- Status = STATUS_OBJECT_NAME_INVALID;
- }
- else
- {
- /* Allocate a non-paged buffer for this string */
- DPRINT("Capturing String\n");
- CapturedName->Length = StringLength;
- CapturedName->MaximumLength = StringLength + sizeof(WCHAR);
- if ((StringBuffer = ExAllocatePoolWithTag(NonPagedPool,
- StringLength + sizeof(WCHAR),
- OB_NAME_TAG)))
- {
- /* Copy the string and null-terminate it */
- RtlMoveMemory(StringBuffer, LocalName.Buffer, StringLength);
- StringBuffer[StringLength / sizeof(WCHAR)] = UNICODE_NULL;
- CapturedName->Buffer = StringBuffer;
- DPRINT("String Captured: %wZ\n", CapturedName);
- }
- else
- {
- /* Fail */
- DPRINT1("Out of Memory!\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- }
- }
- }
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
- {
- Status = _SEH_GetExceptionCode();
-
- /* Remember to free the buffer in case of failure */
- DPRINT1("Failed\n");
- if (StringBuffer) ExFreePool(StringBuffer);
- }
- _SEH_END;
-
- /* Return */
- DPRINT("Returning: %lx\n", Status);
- return Status;
-}
-
-NTSTATUS
-STDCALL
-ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN KPROCESSOR_MODE AccessMode,
- IN POBJECT_TYPE ObjectType,
- IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
- OUT PUNICODE_STRING ObjectName)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- PSECURITY_DESCRIPTOR SecurityDescriptor;
- PSECURITY_QUALITY_OF_SERVICE SecurityQos;
- PUNICODE_STRING LocalObjectName = NULL;
-
- /* Zero out the Capture Data */
- DPRINT("ObpCaptureObjectAttributes\n");
- RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
-
- /* SEH everything here for protection */
- _SEH_TRY
- {
- /* Check if we got Oba */
- if (ObjectAttributes)
- {
- if (AccessMode != KernelMode)
- {
- DPRINT("Probing OBA\n");
- ProbeForRead(ObjectAttributes,
- sizeof(OBJECT_ATTRIBUTES),
- sizeof(ULONG));
- }
-
- /* Validate the Size and Attributes */
- DPRINT("Validating OBA\n");
- if ((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
- (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES))
- {
- Status = STATUS_INVALID_PARAMETER;
- DPRINT1("Invalid Size: %lx or Attributes: %lx\n",
- ObjectAttributes->Length, ObjectAttributes->Attributes);
- _SEH_LEAVE;
- }
-
- /* Set some Create Info */
- DPRINT("Creating OBCI\n");
- ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
- ObjectCreateInfo->Attributes = ObjectAttributes->Attributes;
- LocalObjectName = ObjectAttributes->ObjectName;
- SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
- SecurityQos = ObjectAttributes->SecurityQualityOfService;
-
- /* Validate the SD */
- if (SecurityDescriptor)
- {
- DPRINT("Probing SD: %x\n", SecurityDescriptor);
- Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
- AccessMode,
- NonPagedPool,
- TRUE,
- &ObjectCreateInfo->SecurityDescriptor);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("Unable to capture the security descriptor!!!\n");
- ObjectCreateInfo->SecurityDescriptor = NULL;
- _SEH_LEAVE;
- }
-
- DPRINT("Probe done\n");
- ObjectCreateInfo->SecurityDescriptorCharge = 2048; /* FIXME */
- ObjectCreateInfo->ProbeMode = AccessMode;
- }
-
- /* Validate the QoS */
- if (SecurityQos)
- {
- if (AccessMode != KernelMode)
- {
- DPRINT("Probing QoS\n");
- ProbeForRead(SecurityQos,
- sizeof(SECURITY_QUALITY_OF_SERVICE),
- sizeof(ULONG));
- }
-
- /* Save Info */
- ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
- ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
- }
- }
- else
- {
- LocalObjectName = NULL;
- }
- }
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
- {
- Status = _SEH_GetExceptionCode();
- DPRINT1("Failed\n");
- }
- _SEH_END;
-
- if (NT_SUCCESS(Status))
- {
- /* Now check if the Object Attributes had an Object Name */
- if (LocalObjectName)
- {
- DPRINT("Name Buffer: %wZ\n", LocalObjectName);
- Status = ObpCaptureObjectName(ObjectName,
- LocalObjectName,
- AccessMode);
- }
- else
- {
- /* Clear the string */
- RtlInitUnicodeString(ObjectName, NULL);
-
- /* He can't have specified a Root Directory */
- if (ObjectCreateInfo->RootDirectory)
- {
- DPRINT1("Invalid name\n");
- Status = STATUS_OBJECT_NAME_INVALID;
- }
- }
- }
- else
- {
- DPRINT1("Failed to capture, cleaning up\n");
- ObpReleaseCapturedAttributes(ObjectCreateInfo);
- }
-
- DPRINT("Return to caller %x\n", Status);
- return Status;
-}
-
-
-VOID
-STDCALL
-ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
-{
- /* Release the SD, it's the only thing we allocated */
- if (ObjectCreateInfo->SecurityDescriptor)
- {
- SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
- ObjectCreateInfo->ProbeMode,
- TRUE);
- ObjectCreateInfo->SecurityDescriptor = NULL;
- }
-}
-
-
-/**********************************************************************
- * NAME PRIVATE
- * ObFindObject@16
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- * ObjectAttributes
- *
- * ReturnedObject
- *
- * RemainigPath
- * Pointer to a unicode string that will contain the
- * remaining path if the function returns successfully.
- * The caller must free the buffer after use by calling
- * RtlFreeUnicodeString ().
- *
- * ObjectType
- * Optional pointer to an object type. This is used to
- * descide if a symbolic link object will be parsed or not.
- *
- * RETURN VALUE
- */
-NTSTATUS
-NTAPI
-ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
- PUNICODE_STRING ObjectName,
- PVOID* ReturnedObject,
- PUNICODE_STRING RemainingPath,
- POBJECT_TYPE ObjectType,
- POBP_LOOKUP_CONTEXT Context)
-{
- PVOID NextObject;
- PVOID CurrentObject;
- PVOID RootObject;
- POBJECT_HEADER CurrentHeader;
- NTSTATUS Status;
- PWSTR current;
- UNICODE_STRING PathString;
- ULONG Attributes;
-
- PAGED_CODE();
-
- DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
- "RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
-
- RtlInitUnicodeString (RemainingPath, NULL);
-
- if (ObjectCreateInfo->RootDirectory == NULL)
- {
- ObReferenceObjectByPointer(NameSpaceRoot,
- DIRECTORY_TRAVERSE,
- NULL,
- ObjectCreateInfo->ProbeMode);
- CurrentObject = NameSpaceRoot;
- }
- else
- {
- Status = ObReferenceObjectByHandle(ObjectCreateInfo->RootDirectory,
- 0,
- NULL,
- ObjectCreateInfo->ProbeMode,
- &CurrentObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- if (ObjectName->Length == 0 ||
- ObjectName->Buffer[0] == UNICODE_NULL)
- {
- *ReturnedObject = CurrentObject;
- return STATUS_SUCCESS;
- }
-
- if (ObjectCreateInfo->RootDirectory == NULL &&
- ObjectName->Buffer[0] != L'\\')
- {
- ObDereferenceObject (CurrentObject);
- DPRINT1("failed\n");
- return STATUS_UNSUCCESSFUL;
- }
-
- /* Create a zero-terminated copy of the object name */
- PathString.Length = ObjectName->Length;
- PathString.MaximumLength = ObjectName->Length + sizeof(WCHAR);
- PathString.Buffer = ExAllocatePool (NonPagedPool,
- PathString.MaximumLength);
- if (PathString.Buffer == NULL)
- {
- ObDereferenceObject (CurrentObject);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- RtlCopyMemory (PathString.Buffer,
- ObjectName->Buffer,
- ObjectName->Length);
- PathString.Buffer[PathString.Length / sizeof(WCHAR)] = UNICODE_NULL;
-
- current = PathString.Buffer;
-
- RootObject = CurrentObject;
- Attributes = ObjectCreateInfo->Attributes;
- if (ObjectType == ObSymbolicLinkType)
- Attributes |= OBJ_OPENLINK;
-
- while (TRUE)
- {
- DPRINT("current %S\n",current);
- CurrentHeader = BODY_TO_HEADER(CurrentObject);
-
- DPRINT("Current ObjectType %wZ\n",
- &CurrentHeader->Type->Name);
-
- if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL)
- {
- DPRINT("Current object can't parse\n");
- break;
- }
- Status = ((OB_ROS_PARSE_METHOD)CurrentHeader->Type->TypeInfo.ParseProcedure)(CurrentObject,
- &NextObject,
- &PathString,
- ¤t,
- Attributes,
- Context);
- if (Status == STATUS_REPARSE)
- {
- /* reparse the object path */
- NextObject = NameSpaceRoot;
- current = PathString.Buffer;
-
- ObReferenceObjectByPointer(NextObject,
- DIRECTORY_TRAVERSE,
- NULL,
- ObjectCreateInfo->ProbeMode);
- }
-
- if (NextObject == NULL)
- {
- break;
- }
- ObDereferenceObject(CurrentObject);
- CurrentObject = NextObject;
- }
-
- if (current)
- {
- RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
- }
-
- RtlFreeUnicodeString (&PathString);
- *ReturnedObject = CurrentObject;
-
- return STATUS_SUCCESS;
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * ObQueryNameString@16
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @implemented
- */
-NTSTATUS
-STDCALL
-ObQueryNameString(IN PVOID Object,
- OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
- IN ULONG Length,
- OUT PULONG ReturnLength)
-{
- POBJECT_HEADER_NAME_INFO LocalInfo;
- POBJECT_HEADER ObjectHeader;
- POBJECT_DIRECTORY ParentDirectory;
- ULONG NameSize;
- PWCH ObjectName;
- NTSTATUS Status;
-
- DPRINT("ObQueryNameString: %x, %x\n", Object, ObjectNameInfo);
-
- /* Get the Kernel Meta-Structures */
- ObjectHeader = BODY_TO_HEADER(Object);
- LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
-
- /* Check if a Query Name Procedure is available */
- if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
- {
- /* Call the procedure */
- DPRINT("Calling Object's Procedure\n");
- Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
- TRUE, //fixme
- ObjectNameInfo,
- Length,
- ReturnLength);
-
- /* Return the status */
- return Status;
- }
-
- /* Check if the object doesn't even have a name */
- if (!LocalInfo || !LocalInfo->Name.Buffer)
- {
- /* We're returning the name structure */
- DPRINT("Nameless Object\n");
- *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
-
- /* Check if we were given enough space */
- if (*ReturnLength > Length)
- {
- DPRINT1("Not enough buffer space\n");
- return STATUS_INFO_LENGTH_MISMATCH;
- }
-
- /* Return an empty buffer */
- ObjectNameInfo->Name.Length = 0;
- ObjectNameInfo->Name.MaximumLength = 0;
- ObjectNameInfo->Name.Buffer = NULL;
-
- return STATUS_SUCCESS;
- }
-
- /*
- * Find the size needed for the name. We won't do
- * this during the Name Creation loop because we want
- * to let the caller know that the buffer isn't big
- * enough right at the beginning, not work our way through
- * and find out at the end
- */
- if (Object == NameSpaceRoot)
- {
- /* Size of the '\' string */
- DPRINT("Object is Root\n");
- NameSize = sizeof(UNICODE_PATH_SEP);
- }
- else
- {
- /* Get the Object Directory and add name of Object */
- ParentDirectory = LocalInfo->Directory;
- NameSize = sizeof(UNICODE_PATH_SEP) + LocalInfo->Name.Length;
-
- /* Loop inside the directory to get the top-most one (meaning root) */
- while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
- {
- /* Get the Name Information */
- LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
-
- /* Add the size of the Directory Name */
- if (LocalInfo && LocalInfo->Directory)
- {
- /* Size of the '\' string + Directory Name */
- NameSize += sizeof(UNICODE_PATH_SEP) + LocalInfo->Name.Length;
-
- /* Move to next parent Directory */
- ParentDirectory = LocalInfo->Directory;
- }
- else
- {
- /* Directory with no name. We append "...\" */
- DPRINT("Nameless Directory\n");
- NameSize += sizeof(UNICODE_NO_PATH) + sizeof(UNICODE_PATH_SEP);
- break;
- }
- }
- }
-
- /* Finally, add the name of the structure and the null char */
- *ReturnLength = NameSize + sizeof(OBJECT_NAME_INFORMATION) + sizeof(UNICODE_NULL);
- DPRINT("Final Length: %x\n", *ReturnLength);
-
- /* Check if we were given enough space */
- if (*ReturnLength > Length)
- {
- DPRINT1("Not enough buffer space\n");
- return STATUS_INFO_LENGTH_MISMATCH;
- }
-
- /*
- * Now we will actually create the name. We work backwards because
- * it's easier to start off from the Name we have and walk up the
- * parent directories. We use the same logic as Name Length calculation.
- */
- LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
- ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
- *--ObjectName = UNICODE_NULL;
-
- if (Object == NameSpaceRoot)
- {
- /* This is already the Root Directory, return "\\" */
- DPRINT("Returning Root Dir\n");
- *--ObjectName = UNICODE_PATH_SEP;
- ObjectNameInfo->Name.Length = (USHORT)NameSize;
- ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
- ObjectNameInfo->Name.Buffer = ObjectName;
-
- return STATUS_SUCCESS;
- }
- else
- {
- /* Start by adding the Object's Name */
- ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
- RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
-
- /* Now parse the Parent directories until we reach the top */
- ParentDirectory = LocalInfo->Directory;
- while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
- {
- /* Get the name information */
- LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
-
- /* Add the "\" */
- *(--ObjectName) = UNICODE_PATH_SEP;
-
- /* Add the Parent Directory's Name */
- if (LocalInfo && LocalInfo->Name.Buffer)
- {
- /* Add the name */
- ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
- RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
-
- /* Move to next parent */
- ParentDirectory = LocalInfo->Directory;
- }
- else
- {
- /* Directory without a name, we add "..." */
- DPRINT("Nameless Directory\n");
- ObjectName -= sizeof(UNICODE_NO_PATH);
- ObjectName = UNICODE_NO_PATH;
- break;
- }
- }
-
- /* Add Root Directory Name */
- *(--ObjectName) = UNICODE_PATH_SEP;
- DPRINT("Current Buffer: %S\n", ObjectName);
- ObjectNameInfo->Name.Length = (USHORT)NameSize;
- ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
- ObjectNameInfo->Name.Buffer = ObjectName;
- DPRINT("Complete: %wZ\n", ObjectNameInfo);
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-STDCALL
-ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
- PUNICODE_STRING ObjectName,
- POBJECT_TYPE ObjectType,
- ULONG ObjectSize,
- POBJECT_HEADER *ObjectHeader)
-{
- POBJECT_HEADER Header;
- BOOLEAN HasHandleInfo = FALSE;
- BOOLEAN HasNameInfo = FALSE;
- BOOLEAN HasCreatorInfo = FALSE;
- POBJECT_HEADER_HANDLE_INFO HandleInfo;
- POBJECT_HEADER_NAME_INFO NameInfo;
- POBJECT_HEADER_CREATOR_INFO CreatorInfo;
- POOL_TYPE PoolType;
- ULONG FinalSize = ObjectSize;
- ULONG Tag;
-
- /* If we don't have an Object Type yet, force NonPaged */
- DPRINT("ObpAllocateObject\n");
- if (!ObjectType)
- {
- PoolType = NonPagedPool;
- Tag = TAG('O', 'b', 'j', 'T');
- }
- else
- {
- PoolType = ObjectType->TypeInfo.PoolType;
- Tag = ObjectType->Key;
- }
-
- DPRINT("Checking ObjectName: %x\n", ObjectName);
- /* Check if the Object has a name */
- if (ObjectName->Buffer)
- {
- FinalSize += sizeof(OBJECT_HEADER_NAME_INFO);
- HasNameInfo = TRUE;
- }
-
- if (ObjectType)
- {
- /* Check if the Object maintains handle counts */
- DPRINT("Checking ObjectType->TypeInfo: %x\n", &ObjectType->TypeInfo);
- if (ObjectType->TypeInfo.MaintainHandleCount)
- {
- FinalSize += sizeof(OBJECT_HEADER_HANDLE_INFO);
- HasHandleInfo = TRUE;
- }
-
- /* Check if the Object maintains type lists */
- if (ObjectType->TypeInfo.MaintainTypeList)
- {
- FinalSize += sizeof(OBJECT_HEADER_CREATOR_INFO);
- HasCreatorInfo = TRUE;
- }
- }
-
- /* Allocate memory for the Object and Header */
- DPRINT("Allocating: %x %x\n", FinalSize, Tag);
- Header = ExAllocatePoolWithTag(PoolType, FinalSize, Tag);
- if (!Header) {
- DPRINT1("Not enough memory!\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Initialize Handle Info */
- if (HasHandleInfo)
- {
- HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
- DPRINT("Info: %x\n", HandleInfo);
- HandleInfo->SingleEntry.HandleCount = 0;
- Header = (POBJECT_HEADER)(HandleInfo + 1);
- }
-
- /* Initialize the Object Name Info */
- if (HasNameInfo)
- {
- NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
- DPRINT("Info: %x %wZ\n", NameInfo, ObjectName);
- NameInfo->Name = *ObjectName;
- NameInfo->Directory = NULL;
- Header = (POBJECT_HEADER)(NameInfo + 1);
- }
-
- /* Initialize Creator Info */
- if (HasCreatorInfo)
- {
- CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
- DPRINT("Info: %x\n", CreatorInfo);
- /* FIXME: Needs Alex's Init patch
- * CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
- */
- InitializeListHead(&CreatorInfo->TypeList);
- Header = (POBJECT_HEADER)(CreatorInfo + 1);
- }
-
- /* Initialize the object header */
- RtlZeroMemory(Header, ObjectSize);
- DPRINT("Initalized header %p\n", Header);
- Header->HandleCount = 0;
- Header->PointerCount = 1;
- Header->Type = ObjectType;
- Header->Flags = OB_FLAG_CREATE_INFO;
-
- /* Set the Offsets for the Info */
- if (HasHandleInfo)
- {
- Header->HandleInfoOffset = HasNameInfo * sizeof(OBJECT_HEADER_NAME_INFO) +
- sizeof(OBJECT_HEADER_HANDLE_INFO) +
- HasCreatorInfo * sizeof(OBJECT_HEADER_CREATOR_INFO);
- Header->Flags |= OB_FLAG_SINGLE_PROCESS;
- }
- if (HasNameInfo)
- {
- Header->NameInfoOffset = sizeof(OBJECT_HEADER_NAME_INFO) +
- HasCreatorInfo * sizeof(OBJECT_HEADER_CREATOR_INFO);
- }
- if (HasCreatorInfo) Header->Flags |= OB_FLAG_CREATOR_INFO;
-
- if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_PERMANENT)
- {
- Header->Flags |= OB_FLAG_PERMANENT;
- }
- if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)
- {
- Header->Flags |= OB_FLAG_EXCLUSIVE;
- }
-
- /* Link stuff to Object Header */
- Header->ObjectCreateInfo = ObjectCreateInfo;
-
- /* Return Header */
- *ObjectHeader = Header;
- return STATUS_SUCCESS;
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * ObCreateObject@36
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- * Status
- *
- * @implemented
- */
-NTSTATUS
-STDCALL
-ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
- IN POBJECT_TYPE Type,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
- IN KPROCESSOR_MODE AccessMode,
- IN OUT PVOID ParseContext OPTIONAL,
- IN ULONG ObjectSize,
- IN ULONG PagedPoolCharge OPTIONAL,
- IN ULONG NonPagedPoolCharge OPTIONAL,
- OUT PVOID *Object)
-{
- NTSTATUS Status;
- POBJECT_CREATE_INFORMATION ObjectCreateInfo;
- UNICODE_STRING ObjectName;
- POBJECT_HEADER Header;
-
- DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
- Type, ObjectAttributes, Object);
-
- /* Allocate a Buffer for the Object Create Info */
- DPRINT("Allocating Create Buffer\n");
- ObjectCreateInfo = ExAllocatePoolWithTag(NonPagedPool,
- sizeof(*ObjectCreateInfo),
- TAG('O','b','C', 'I'));
-
- /* Capture all the info */
- DPRINT("Capturing Create Info\n");
- Status = ObpCaptureObjectAttributes(ObjectAttributes,
- ObjectAttributesAccessMode,
- Type,
- ObjectCreateInfo,
- &ObjectName);
-
- if (NT_SUCCESS(Status))
- {
- /* Allocate the Object */
- DPRINT("Allocating: %wZ\n", &ObjectName);
- Status = ObpAllocateObject(ObjectCreateInfo,
- &ObjectName,
- Type,
- OBJECT_ALLOC_SIZE(ObjectSize),
- &Header);
-
- if (NT_SUCCESS(Status))
- {
- /* Return the Object */
- DPRINT("Returning Object\n");
- *Object = &Header->Body;
-
- /* Return to caller, leave the Capture Info Alive for ObInsert */
- return Status;
- }
-
- /* Release the Capture Info, we don't need it */
- DPRINT1("Allocation failed\n");
- ObpReleaseCapturedAttributes(ObjectCreateInfo);
- if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
- }
-
- /* We failed, so release the Buffer */
- DPRINT1("Capture failed\n");
- ExFreePool(ObjectCreateInfo);
- return Status;
-}
-
-/*
- * FUNCTION: Increments the pointer reference count for a given object
- * ARGUMENTS:
- * ObjectBody = Object's body
- * DesiredAccess = Desired access to the object
- * ObjectType = Points to the object type structure
- * AccessMode = Type of access check to perform
- * RETURNS: Status
- *
- * @implemented
- */
-NTSTATUS STDCALL
-ObReferenceObjectByPointer(IN PVOID Object,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_TYPE ObjectType,
- IN KPROCESSOR_MODE AccessMode)
-{
- POBJECT_HEADER Header;
-
- /* NOTE: should be possible to reference an object above APC_LEVEL! */
-
- DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
- Object,ObjectType);
-
- Header = BODY_TO_HEADER(Object);
-
- if (ObjectType != NULL && Header->Type != ObjectType)
- {
- DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
- Header,
- Header->Type,
- &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Header->Type))->Name,
- ObjectType,
- &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObjectType))->Name);
- return(STATUS_UNSUCCESSFUL);
- }
- if (Header->Type == PsProcessType)
- {
- DPRINT("Ref p 0x%x PointerCount %d type %x ",
- Object, Header->PointerCount, PsProcessType);
- DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
- }
- if (Header->Type == PsThreadType)
- {
- DPRINT("Deref t 0x%x with PointerCount %d type %x ",
- Object, Header->PointerCount, PsThreadType);
- DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
- }
-
- if (Header->PointerCount == 0 && !(Header->Flags & OB_FLAG_PERMANENT))
- {
- if (Header->Type == PsProcessType)
- {
- return STATUS_PROCESS_IS_TERMINATING;
- }
- if (Header->Type == PsThreadType)
- {
- return STATUS_THREAD_IS_TERMINATING;
- }
- return(STATUS_UNSUCCESSFUL);
- }
-
- if (1 == InterlockedIncrement(&Header->PointerCount) && !(Header->Flags & OB_FLAG_PERMANENT))
- {
- KEBUGCHECK(0);
- }
-
- return(STATUS_SUCCESS);
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-ObOpenObjectByPointer(IN PVOID Object,
- IN ULONG HandleAttributes,
- IN PACCESS_STATE PassedAccessState,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_TYPE ObjectType,
- IN KPROCESSOR_MODE AccessMode,
- OUT PHANDLE Handle)
-{
- NTSTATUS Status;
-
- PAGED_CODE();
-
- DPRINT("ObOpenObjectByPointer()\n");
-
- Status = ObReferenceObjectByPointer(Object,
- 0,
- ObjectType,
- AccessMode);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Status = ObpCreateHandle(Object,
- DesiredAccess,
- HandleAttributes,
- Handle);
-
- ObDereferenceObject(Object);
-
- return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-ObpDeleteObject(POBJECT_HEADER Header)
-{
- PVOID HeaderLocation = Header;
- POBJECT_HEADER_HANDLE_INFO HandleInfo;
- POBJECT_HEADER_NAME_INFO NameInfo;
- POBJECT_HEADER_CREATOR_INFO CreatorInfo;
-
- DPRINT("ObpDeleteObject(Header %p)\n", Header);
- if (KeGetCurrentIrql() != PASSIVE_LEVEL)
- {
- DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
- KEBUGCHECK(0);
- }
-
- if (Header->Type != NULL &&
- Header->Type->TypeInfo.DeleteProcedure != NULL)
- {
- Header->Type->TypeInfo.DeleteProcedure(&Header->Body);
- }
-
- if (Header->SecurityDescriptor != NULL)
- {
- ObpRemoveSecurityDescriptor(Header->SecurityDescriptor);
- }
-
- if (HEADER_TO_OBJECT_NAME(Header))
- {
- if(HEADER_TO_OBJECT_NAME(Header)->Name.Buffer)
- {
- ExFreePool(HEADER_TO_OBJECT_NAME(Header)->Name.Buffer);
- }
- }
- if (Header->ObjectCreateInfo)
- {
- ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
- ExFreePool(Header->ObjectCreateInfo);
- }
-
- /* To find the header, walk backwards from how we allocated */
- if ((CreatorInfo = HEADER_TO_CREATOR_INFO(Header)))
- {
- HeaderLocation = CreatorInfo;
- }
- if ((NameInfo = HEADER_TO_OBJECT_NAME(Header)))
- {
- HeaderLocation = NameInfo;
- }
- if ((HandleInfo = HEADER_TO_HANDLE_INFO(Header)))
- {
- HeaderLocation = HandleInfo;
- }
-
- DPRINT("ObPerformRetentionChecks() = Freeing object\n");
- ExFreePool(HeaderLocation);
-
- return(STATUS_SUCCESS);
-}
-
-
-VOID STDCALL
-ObpDeleteObjectWorkRoutine (IN PVOID Parameter)
-{
- PRETENTION_CHECK_PARAMS Params = (PRETENTION_CHECK_PARAMS)Parameter;
- /* ULONG Tag; */ /* See below */
-
- ASSERT(Params);
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); /* We need PAGED_CODE somewhere... */
-
- /* Turn this on when we have ExFreePoolWithTag
- Tag = Params->ObjectHeader->Type->Tag; */
- ObpDeleteObject(Params->ObjectHeader);
- ExFreePool(Params);
- /* ExFreePoolWithTag(Params, Tag); */
-}
-
-
-STATIC NTSTATUS
-ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
- IN LONG OldPointerCount)
-{
-#if 0
- if (ObjectHeader->PointerCount < 0)
- {
- CPRINT("Object %p/%p has invalid reference count (%d)\n",
- ObjectHeader, HEADER_TO_BODY(ObjectHeader),
- ObjectHeader->PointerCount);
- KEBUGCHECK(0);
- }
-
- if (ObjectHeader->HandleCount < 0)
- {
- CPRINT("Object %p/%p has invalid handle count (%d)\n",
- ObjectHeader, HEADER_TO_BODY(ObjectHeader),
- ObjectHeader->HandleCount);
- KEBUGCHECK(0);
- }
-#endif
-
-
- switch (KeGetCurrentIrql ())
- {
- case PASSIVE_LEVEL:
- return ObpDeleteObject (ObjectHeader);
-
- case APC_LEVEL:
- case DISPATCH_LEVEL:
- {
- PRETENTION_CHECK_PARAMS Params;
-
- /*
- We use must succeed pool here because if the allocation fails
- then we leak memory.
- */
- Params = (PRETENTION_CHECK_PARAMS)
- ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
- sizeof(RETENTION_CHECK_PARAMS),
- ObjectHeader->Type->Key);
- Params->ObjectHeader = ObjectHeader;
- ExInitializeWorkItem(&Params->WorkItem,
- ObpDeleteObjectWorkRoutine,
- (PVOID)Params);
- ExQueueWorkItem(&Params->WorkItem,
- CriticalWorkQueue);
- }
- return STATUS_PENDING;
-
- default:
- DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
- "IRQL %u!\n", KeGetCurrentIrql());
- KEBUGCHECK(0);
- return STATUS_UNSUCCESSFUL;
- }
-
- return STATUS_SUCCESS;
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * ObfReferenceObject@4
- *
- * DESCRIPTION
- * Increments a given object's reference count and performs
- * retention checks.
- *
- * ARGUMENTS
- * ObjectBody = Body of the object.
- *
- * RETURN VALUE
- * None.
- *
- * @implemented
- */
-VOID FASTCALL
-ObfReferenceObject(IN PVOID Object)
-{
- POBJECT_HEADER Header;
-
- ASSERT(Object);
-
- Header = BODY_TO_HEADER(Object);
-
- /* No one should be referencing an object once we are deleting it. */
- if (InterlockedIncrement(&Header->PointerCount) == 1 && !(Header->Flags & OB_FLAG_PERMANENT))
- {
- KEBUGCHECK(0);
- }
-
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * ObfDereferenceObject@4
- *
- * DESCRIPTION
- * Decrements a given object's reference count and performs
- * retention checks.
- *
- * ARGUMENTS
- * ObjectBody = Body of the object.
- *
- * RETURN VALUE
- * None.
- *
- * @implemented
- */
-VOID FASTCALL
-ObfDereferenceObject(IN PVOID Object)
-{
- POBJECT_HEADER Header;
- LONG NewPointerCount;
- BOOL Permanent;
-
- ASSERT(Object);
-
- /* Extract the object header. */
- Header = BODY_TO_HEADER(Object);
- Permanent = Header->Flags & OB_FLAG_PERMANENT;
-
- /*
- Drop our reference and get the new count so we can tell if this was the
- last reference.
- */
- NewPointerCount = InterlockedDecrement(&Header->PointerCount);
- DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object, NewPointerCount);
- ASSERT(NewPointerCount >= 0);
-
- /* Check whether the object can now be deleted. */
- if (NewPointerCount == 0 &&
- !Permanent)
- {
- ObpDeleteObjectDpcLevel(Header, NewPointerCount);
- }
-}
-
-VOID
-FASTCALL
-ObInitializeFastReference(IN PEX_FAST_REF FastRef,
- PVOID Object)
-{
- /* FIXME: Fast Referencing is Unimplemented */
- FastRef->Object = Object;
-}
-
-
-PVOID
-FASTCALL
-ObFastReferenceObject(IN PEX_FAST_REF FastRef)
-{
- /* FIXME: Fast Referencing is Unimplemented */
-
- /* Do a normal Reference */
- ObReferenceObject(FastRef->Object);
-
- /* Return the Object */
- return FastRef->Object;
-}
-
-VOID
-FASTCALL
-ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
- PVOID Object)
-{
- /* FIXME: Fast Referencing is Unimplemented */
-
- /* Do a normal Dereference */
- ObDereferenceObject(FastRef->Object);
-}
-
-PVOID
-FASTCALL
-ObFastReplaceObject(IN PEX_FAST_REF FastRef,
- PVOID Object)
-{
- PVOID OldObject = FastRef->Object;
-
- /* FIXME: Fast Referencing is Unimplemented */
- FastRef->Object = Object;
-
- /* Do a normal Dereference */
- ObDereferenceObject(OldObject);
-
- /* Return old Object*/
- return OldObject;
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * ObGetObjectPointerCount@4
- *
- * DESCRIPTION
- * Retrieves the pointer(reference) count of the given object.
- *
- * ARGUMENTS
- * ObjectBody = Body of the object.
- *
- * RETURN VALUE
- * Reference count.
- *
- * @implemented
- */
-ULONG STDCALL
-ObGetObjectPointerCount(PVOID Object)
-{
- POBJECT_HEADER Header;
-
- PAGED_CODE();
-
- ASSERT(Object);
- Header = BODY_TO_HEADER(Object);
-
- return Header->PointerCount;
-}
-
-
-/**********************************************************************
- * NAME INTERNAL
- * ObGetObjectHandleCount@4
- *
- * DESCRIPTION
- * Retrieves the handle count of the given object.
- *
- * ARGUMENTS
- * ObjectBody = Body of the object.
- *
- * RETURN VALUE
- * Reference count.
- */
-ULONG
-NTAPI
-ObGetObjectHandleCount(PVOID Object)
-{
- POBJECT_HEADER Header;
-
- PAGED_CODE();
-
- ASSERT(Object);
- Header = BODY_TO_HEADER(Object);
-
- return Header->HandleCount;
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * ObDereferenceObject@4
- *
- * DESCRIPTION
- * Decrements a given object's reference count and performs
- * retention checks.
- *
- * ARGUMENTS
- * ObjectBody = Body of the object.
- *
- * RETURN VALUE
- * None.
- *
- * @implemented
- */
-
-#ifdef ObDereferenceObject
-#undef ObDereferenceObject
-#endif
-
-VOID STDCALL
-ObDereferenceObject(IN PVOID Object)
-{
- ObfDereferenceObject(Object);
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/ob/oblife.c b/reactos/ntoskrnl/ob/oblife.c
new file mode 100644
index 00000000000..d8ee10ad5bc
--- /dev/null
+++ b/reactos/ntoskrnl/ob/oblife.c
@@ -0,0 +1,921 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ob/create.c
+ * PURPOSE: Manages the lifetime of an Object, including its creation,
+ * and deletion, as well as setting or querying any of its
+ * information while it is active. Since Object Types are also
+ * Objects, those are also managed here.
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Eric Kohl
+ * Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+extern ULONG NtGlobalFlag;
+
+POBJECT_TYPE ObTypeObjectType = NULL;
+KEVENT ObpDefaultObject;
+
+typedef struct _RETENTION_CHECK_PARAMS
+{
+ WORK_QUEUE_ITEM WorkItem;
+ POBJECT_HEADER ObjectHeader;
+} RETENTION_CHECK_PARAMS, *PRETENTION_CHECK_PARAMS;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+static NTSTATUS
+ObpDeleteObject(POBJECT_HEADER Header)
+{
+ PVOID HeaderLocation = Header;
+ POBJECT_HEADER_HANDLE_INFO HandleInfo;
+ POBJECT_HEADER_NAME_INFO NameInfo;
+ POBJECT_HEADER_CREATOR_INFO CreatorInfo;
+
+ DPRINT("ObpDeleteObject(Header %p)\n", Header);
+ if (KeGetCurrentIrql() != PASSIVE_LEVEL)
+ {
+ DPRINT("ObpDeleteObject called at an unsupported IRQL. Use ObpDeleteObjectDpcLevel instead.\n");
+ KEBUGCHECK(0);
+ }
+
+ if (Header->Type != NULL &&
+ Header->Type->TypeInfo.DeleteProcedure != NULL)
+ {
+ Header->Type->TypeInfo.DeleteProcedure(&Header->Body);
+ }
+
+ if (Header->SecurityDescriptor != NULL)
+ {
+ ObpRemoveSecurityDescriptor(Header->SecurityDescriptor);
+ }
+
+ if (HEADER_TO_OBJECT_NAME(Header))
+ {
+ if(HEADER_TO_OBJECT_NAME(Header)->Name.Buffer)
+ {
+ ExFreePool(HEADER_TO_OBJECT_NAME(Header)->Name.Buffer);
+ }
+ }
+ if (Header->ObjectCreateInfo)
+ {
+ ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
+ ExFreePool(Header->ObjectCreateInfo);
+ }
+
+ /* To find the header, walk backwards from how we allocated */
+ if ((CreatorInfo = HEADER_TO_CREATOR_INFO(Header)))
+ {
+ HeaderLocation = CreatorInfo;
+ }
+ if ((NameInfo = HEADER_TO_OBJECT_NAME(Header)))
+ {
+ HeaderLocation = NameInfo;
+ }
+ if ((HandleInfo = HEADER_TO_HANDLE_INFO(Header)))
+ {
+ HeaderLocation = HandleInfo;
+ }
+
+ DPRINT("ObPerformRetentionChecks() = Freeing object\n");
+ ExFreePool(HeaderLocation);
+
+ return(STATUS_SUCCESS);
+}
+
+
+VOID STDCALL
+ObpDeleteObjectWorkRoutine (IN PVOID Parameter)
+{
+ PRETENTION_CHECK_PARAMS Params = (PRETENTION_CHECK_PARAMS)Parameter;
+ /* ULONG Tag; */ /* See below */
+
+ ASSERT(Params);
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); /* We need PAGED_CODE somewhere... */
+
+ /* Turn this on when we have ExFreePoolWithTag
+ Tag = Params->ObjectHeader->Type->Tag; */
+ ObpDeleteObject(Params->ObjectHeader);
+ ExFreePool(Params);
+ /* ExFreePoolWithTag(Params, Tag); */
+}
+
+
+NTSTATUS
+ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
+ IN LONG OldPointerCount)
+{
+#if 0
+ if (ObjectHeader->PointerCount < 0)
+ {
+ CPRINT("Object %p/%p has invalid reference count (%d)\n",
+ ObjectHeader, HEADER_TO_BODY(ObjectHeader),
+ ObjectHeader->PointerCount);
+ KEBUGCHECK(0);
+ }
+
+ if (ObjectHeader->HandleCount < 0)
+ {
+ CPRINT("Object %p/%p has invalid handle count (%d)\n",
+ ObjectHeader, HEADER_TO_BODY(ObjectHeader),
+ ObjectHeader->HandleCount);
+ KEBUGCHECK(0);
+ }
+#endif
+
+
+ switch (KeGetCurrentIrql ())
+ {
+ case PASSIVE_LEVEL:
+ return ObpDeleteObject (ObjectHeader);
+
+ case APC_LEVEL:
+ case DISPATCH_LEVEL:
+ {
+ PRETENTION_CHECK_PARAMS Params;
+
+ /*
+ We use must succeed pool here because if the allocation fails
+ then we leak memory.
+ */
+ Params = (PRETENTION_CHECK_PARAMS)
+ ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
+ sizeof(RETENTION_CHECK_PARAMS),
+ ObjectHeader->Type->Key);
+ Params->ObjectHeader = ObjectHeader;
+ ExInitializeWorkItem(&Params->WorkItem,
+ ObpDeleteObjectWorkRoutine,
+ (PVOID)Params);
+ ExQueueWorkItem(&Params->WorkItem,
+ CriticalWorkQueue);
+ }
+ return STATUS_PENDING;
+
+ default:
+ DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
+ "IRQL %u!\n", KeGetCurrentIrql());
+ KEBUGCHECK(0);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+STDCALL
+ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
+ IN PUNICODE_STRING ObjectName,
+ IN KPROCESSOR_MODE AccessMode)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG StringLength;
+ PWCHAR StringBuffer = NULL;
+ UNICODE_STRING LocalName = {}; /* <= GCC 4.0 + Optimizer */
+
+ /* Initialize the Input String */
+ RtlInitUnicodeString(CapturedName, NULL);
+
+ /* Protect everything */
+ _SEH_TRY
+ {
+ /* First Probe the String */
+ DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName);
+ if (AccessMode != KernelMode)
+ {
+ ProbeForRead(ObjectName,
+ sizeof(UNICODE_STRING),
+ sizeof(USHORT));
+ LocalName = *ObjectName;
+
+ ProbeForRead(LocalName.Buffer,
+ LocalName.Length,
+ sizeof(WCHAR));
+ }
+ else
+ {
+ /* No probing needed */
+ LocalName = *ObjectName;
+ }
+
+ /* Make sure there really is a string */
+ DPRINT("Probing OK\n");
+ if ((StringLength = LocalName.Length))
+ {
+ /* Check that the size is a valid WCHAR multiple */
+ if ((StringLength & (sizeof(WCHAR) - 1)) ||
+ /* Check that the NULL-termination below will work */
+ (StringLength == (MAXUSHORT - sizeof(WCHAR) + 1)))
+ {
+ /* PS: Please keep the checks above expanded for clarity */
+ DPRINT1("Invalid String Length\n");
+ Status = STATUS_OBJECT_NAME_INVALID;
+ }
+ else
+ {
+ /* Allocate a non-paged buffer for this string */
+ DPRINT("Capturing String\n");
+ CapturedName->Length = StringLength;
+ CapturedName->MaximumLength = StringLength + sizeof(WCHAR);
+ if ((StringBuffer = ExAllocatePoolWithTag(NonPagedPool,
+ StringLength + sizeof(WCHAR),
+ OB_NAME_TAG)))
+ {
+ /* Copy the string and null-terminate it */
+ RtlMoveMemory(StringBuffer, LocalName.Buffer, StringLength);
+ StringBuffer[StringLength / sizeof(WCHAR)] = UNICODE_NULL;
+ CapturedName->Buffer = StringBuffer;
+ DPRINT("String Captured: %wZ\n", CapturedName);
+ }
+ else
+ {
+ /* Fail */
+ DPRINT1("Out of Memory!\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ }
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+
+ /* Remember to free the buffer in case of failure */
+ DPRINT1("Failed\n");
+ if (StringBuffer) ExFreePool(StringBuffer);
+ }
+ _SEH_END;
+
+ /* Return */
+ DPRINT("Returning: %lx\n", Status);
+ return Status;
+}
+
+NTSTATUS
+STDCALL
+ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN KPROCESSOR_MODE AccessMode,
+ IN POBJECT_TYPE ObjectType,
+ IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+ OUT PUNICODE_STRING ObjectName)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ PSECURITY_QUALITY_OF_SERVICE SecurityQos;
+ PUNICODE_STRING LocalObjectName = NULL;
+
+ /* Zero out the Capture Data */
+ DPRINT("ObpCaptureObjectAttributes\n");
+ RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
+
+ /* SEH everything here for protection */
+ _SEH_TRY
+ {
+ /* Check if we got Oba */
+ if (ObjectAttributes)
+ {
+ if (AccessMode != KernelMode)
+ {
+ DPRINT("Probing OBA\n");
+ ProbeForRead(ObjectAttributes,
+ sizeof(OBJECT_ATTRIBUTES),
+ sizeof(ULONG));
+ }
+
+ /* Validate the Size and Attributes */
+ DPRINT("Validating OBA\n");
+ if ((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
+ (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ DPRINT1("Invalid Size: %lx or Attributes: %lx\n",
+ ObjectAttributes->Length, ObjectAttributes->Attributes);
+ _SEH_LEAVE;
+ }
+
+ /* Set some Create Info */
+ DPRINT("Creating OBCI\n");
+ ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
+ ObjectCreateInfo->Attributes = ObjectAttributes->Attributes;
+ LocalObjectName = ObjectAttributes->ObjectName;
+ SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
+ SecurityQos = ObjectAttributes->SecurityQualityOfService;
+
+ /* Validate the SD */
+ if (SecurityDescriptor)
+ {
+ DPRINT("Probing SD: %x\n", SecurityDescriptor);
+ Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
+ AccessMode,
+ NonPagedPool,
+ TRUE,
+ &ObjectCreateInfo->SecurityDescriptor);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to capture the security descriptor!!!\n");
+ ObjectCreateInfo->SecurityDescriptor = NULL;
+ _SEH_LEAVE;
+ }
+
+ DPRINT("Probe done\n");
+ ObjectCreateInfo->SecurityDescriptorCharge = 2048; /* FIXME */
+ ObjectCreateInfo->ProbeMode = AccessMode;
+ }
+
+ /* Validate the QoS */
+ if (SecurityQos)
+ {
+ if (AccessMode != KernelMode)
+ {
+ DPRINT("Probing QoS\n");
+ ProbeForRead(SecurityQos,
+ sizeof(SECURITY_QUALITY_OF_SERVICE),
+ sizeof(ULONG));
+ }
+
+ /* Save Info */
+ ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
+ ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
+ }
+ }
+ else
+ {
+ LocalObjectName = NULL;
+ }
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ DPRINT1("Failed\n");
+ }
+ _SEH_END;
+
+ if (NT_SUCCESS(Status))
+ {
+ /* Now check if the Object Attributes had an Object Name */
+ if (LocalObjectName)
+ {
+ DPRINT("Name Buffer: %wZ\n", LocalObjectName);
+ Status = ObpCaptureObjectName(ObjectName,
+ LocalObjectName,
+ AccessMode);
+ }
+ else
+ {
+ /* Clear the string */
+ RtlInitUnicodeString(ObjectName, NULL);
+
+ /* He can't have specified a Root Directory */
+ if (ObjectCreateInfo->RootDirectory)
+ {
+ DPRINT1("Invalid name\n");
+ Status = STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+ }
+ else
+ {
+ DPRINT1("Failed to capture, cleaning up\n");
+ ObpReleaseCapturedAttributes(ObjectCreateInfo);
+ }
+
+ DPRINT("Return to caller %x\n", Status);
+ return Status;
+}
+
+
+VOID
+STDCALL
+ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
+{
+ /* Release the SD, it's the only thing we allocated */
+ if (ObjectCreateInfo->SecurityDescriptor)
+ {
+ SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
+ ObjectCreateInfo->ProbeMode,
+ TRUE);
+ ObjectCreateInfo->SecurityDescriptor = NULL;
+ }
+}
+
+NTSTATUS
+STDCALL
+ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+ PUNICODE_STRING ObjectName,
+ POBJECT_TYPE ObjectType,
+ ULONG ObjectSize,
+ POBJECT_HEADER *ObjectHeader)
+{
+ POBJECT_HEADER Header;
+ BOOLEAN HasHandleInfo = FALSE;
+ BOOLEAN HasNameInfo = FALSE;
+ BOOLEAN HasCreatorInfo = FALSE;
+ POBJECT_HEADER_HANDLE_INFO HandleInfo;
+ POBJECT_HEADER_NAME_INFO NameInfo;
+ POBJECT_HEADER_CREATOR_INFO CreatorInfo;
+ POOL_TYPE PoolType;
+ ULONG FinalSize = ObjectSize;
+ ULONG Tag;
+
+ /* If we don't have an Object Type yet, force NonPaged */
+ DPRINT("ObpAllocateObject\n");
+ if (!ObjectType)
+ {
+ PoolType = NonPagedPool;
+ Tag = TAG('O', 'b', 'j', 'T');
+ }
+ else
+ {
+ PoolType = ObjectType->TypeInfo.PoolType;
+ Tag = ObjectType->Key;
+ }
+
+ DPRINT("Checking ObjectName: %x\n", ObjectName);
+ /* Check if the Object has a name */
+ if (ObjectName->Buffer)
+ {
+ FinalSize += sizeof(OBJECT_HEADER_NAME_INFO);
+ HasNameInfo = TRUE;
+ }
+
+ if (ObjectType)
+ {
+ /* Check if the Object maintains handle counts */
+ DPRINT("Checking ObjectType->TypeInfo: %x\n", &ObjectType->TypeInfo);
+ if (ObjectType->TypeInfo.MaintainHandleCount)
+ {
+ FinalSize += sizeof(OBJECT_HEADER_HANDLE_INFO);
+ HasHandleInfo = TRUE;
+ }
+
+ /* Check if the Object maintains type lists */
+ if (ObjectType->TypeInfo.MaintainTypeList)
+ {
+ FinalSize += sizeof(OBJECT_HEADER_CREATOR_INFO);
+ HasCreatorInfo = TRUE;
+ }
+ }
+
+ /* Allocate memory for the Object and Header */
+ DPRINT("Allocating: %x %x\n", FinalSize, Tag);
+ Header = ExAllocatePoolWithTag(PoolType, FinalSize, Tag);
+ if (!Header) {
+ DPRINT1("Not enough memory!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Initialize Handle Info */
+ if (HasHandleInfo)
+ {
+ HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
+ DPRINT("Info: %x\n", HandleInfo);
+ HandleInfo->SingleEntry.HandleCount = 0;
+ Header = (POBJECT_HEADER)(HandleInfo + 1);
+ }
+
+ /* Initialize the Object Name Info */
+ if (HasNameInfo)
+ {
+ NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
+ DPRINT("Info: %x %wZ\n", NameInfo, ObjectName);
+ NameInfo->Name = *ObjectName;
+ NameInfo->Directory = NULL;
+ Header = (POBJECT_HEADER)(NameInfo + 1);
+ }
+
+ /* Initialize Creator Info */
+ if (HasCreatorInfo)
+ {
+ CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
+ DPRINT("Info: %x\n", CreatorInfo);
+ /* FIXME: Needs Alex's Init patch
+ * CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
+ */
+ InitializeListHead(&CreatorInfo->TypeList);
+ Header = (POBJECT_HEADER)(CreatorInfo + 1);
+ }
+
+ /* Initialize the object header */
+ RtlZeroMemory(Header, ObjectSize);
+ DPRINT("Initalized header %p\n", Header);
+ Header->HandleCount = 0;
+ Header->PointerCount = 1;
+ Header->Type = ObjectType;
+ Header->Flags = OB_FLAG_CREATE_INFO;
+
+ /* Set the Offsets for the Info */
+ if (HasHandleInfo)
+ {
+ Header->HandleInfoOffset = HasNameInfo * sizeof(OBJECT_HEADER_NAME_INFO) +
+ sizeof(OBJECT_HEADER_HANDLE_INFO) +
+ HasCreatorInfo * sizeof(OBJECT_HEADER_CREATOR_INFO);
+ Header->Flags |= OB_FLAG_SINGLE_PROCESS;
+ }
+ if (HasNameInfo)
+ {
+ Header->NameInfoOffset = sizeof(OBJECT_HEADER_NAME_INFO) +
+ HasCreatorInfo * sizeof(OBJECT_HEADER_CREATOR_INFO);
+ }
+ if (HasCreatorInfo) Header->Flags |= OB_FLAG_CREATOR_INFO;
+
+ if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_PERMANENT)
+ {
+ Header->Flags |= OB_FLAG_PERMANENT;
+ }
+ if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)
+ {
+ Header->Flags |= OB_FLAG_EXCLUSIVE;
+ }
+
+ /* Link stuff to Object Header */
+ Header->ObjectCreateInfo = ObjectCreateInfo;
+
+ /* Return Header */
+ *ObjectHeader = Header;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
+ PUNICODE_STRING TypeName,
+ POBJECT_TYPE *ObjectType)
+{
+ POBJECT_HEADER Header;
+ POBJECT_TYPE LocalObjectType;
+ ULONG HeaderSize;
+ NTSTATUS Status;
+
+ DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", TypeName);
+
+ /* Allocate the Object */
+ Status = ObpAllocateObject(NULL,
+ TypeName,
+ ObTypeObjectType,
+ OBJECT_ALLOC_SIZE(sizeof(OBJECT_TYPE)),
+ (POBJECT_HEADER*)&Header);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObpAllocateObject failed!\n");
+ return Status;
+ }
+
+ LocalObjectType = (POBJECT_TYPE)&Header->Body;
+ DPRINT("Local ObjectType: %p Header: %p \n", LocalObjectType, Header);
+
+ /* Check if this is the first Object Type */
+ if (!ObTypeObjectType)
+ {
+ ObTypeObjectType = LocalObjectType;
+ Header->Type = ObTypeObjectType;
+ LocalObjectType->Key = TAG('O', 'b', 'j', 'T');
+ }
+ else
+ {
+ CHAR Tag[4];
+ Tag[0] = TypeName->Buffer[0];
+ Tag[1] = TypeName->Buffer[1];
+ Tag[2] = TypeName->Buffer[2];
+ Tag[3] = TypeName->Buffer[3];
+
+ /* Set Tag */
+ DPRINT("Convert: %s \n", Tag);
+ LocalObjectType->Key = *(PULONG)Tag;
+ }
+
+ /* Set it up */
+ LocalObjectType->TypeInfo = *ObjectTypeInitializer;
+ LocalObjectType->Name = *TypeName;
+ LocalObjectType->TypeInfo.PoolType = ObjectTypeInitializer->PoolType;
+
+ /* These two flags need to be manually set up */
+ Header->Flags |= OB_FLAG_KERNEL_MODE | OB_FLAG_PERMANENT;
+
+ /* Check if we have to maintain a type list */
+ if (NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST)
+ {
+ /* Enable support */
+ LocalObjectType->TypeInfo.MaintainTypeList = TRUE;
+ }
+
+ /* Calculate how much space our header'll take up */
+ HeaderSize = sizeof(OBJECT_HEADER) + sizeof(OBJECT_HEADER_NAME_INFO) +
+ (ObjectTypeInitializer->MaintainHandleCount ?
+ sizeof(OBJECT_HEADER_HANDLE_INFO) : 0);
+
+ /* Update the Pool Charges */
+ if (ObjectTypeInitializer->PoolType == NonPagedPool)
+ {
+ LocalObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderSize;
+ }
+ else
+ {
+ LocalObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderSize;
+ }
+
+ /* All objects types need a security procedure */
+ if (!ObjectTypeInitializer->SecurityProcedure)
+ {
+ LocalObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod;
+ }
+
+ /* Select the Wait Object */
+ if (LocalObjectType->TypeInfo.UseDefaultObject)
+ {
+ /* Add the SYNCHRONIZE access mask since it's waitable */
+ LocalObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
+
+ /* Use the "Default Object", a simple event */
+ LocalObjectType->DefaultObject = &ObpDefaultObject;
+ }
+ /* Special system objects get an optimized hack so they can be waited on */
+ else if (TypeName->Length == 8 && !wcscmp(TypeName->Buffer, L"File"))
+ {
+ LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(FILE_OBJECT, Event);
+ }
+ /* FIXME: When LPC stops sucking, add a hack for Waitable Ports */
+ else
+ {
+ /* No default Object */
+ LocalObjectType->DefaultObject = NULL;
+ }
+
+ /* Initialize Object Type components */
+ ExInitializeResourceLite(&LocalObjectType->Mutex);
+ InitializeListHead(&LocalObjectType->TypeList);
+
+ /* Insert it into the Object Directory */
+ if (ObpTypeDirectoryObject)
+ {
+ OBP_LOOKUP_CONTEXT Context;
+ Context.Directory = ObpTypeDirectoryObject;
+ Context.DirectoryLocked = TRUE;
+ ObpLookupEntryDirectory(ObpTypeDirectoryObject,
+ TypeName,
+ OBJ_CASE_INSENSITIVE,
+ FALSE,
+ &Context);
+ ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, Header);
+ ObReferenceObject(ObpTypeDirectoryObject);
+ }
+
+ *ObjectType = LocalObjectType;
+ return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+NTSTATUS
+NTAPI
+ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
+ IN POBJECT_TYPE Type,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN KPROCESSOR_MODE AccessMode,
+ IN OUT PVOID ParseContext OPTIONAL,
+ IN ULONG ObjectSize,
+ IN ULONG PagedPoolCharge OPTIONAL,
+ IN ULONG NonPagedPoolCharge OPTIONAL,
+ OUT PVOID *Object)
+{
+ NTSTATUS Status;
+ POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ UNICODE_STRING ObjectName;
+ POBJECT_HEADER Header;
+
+ DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
+ Type, ObjectAttributes, Object);
+
+ /* Allocate a Buffer for the Object Create Info */
+ DPRINT("Allocating Create Buffer\n");
+ ObjectCreateInfo = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(*ObjectCreateInfo),
+ TAG('O','b','C', 'I'));
+
+ /* Capture all the info */
+ DPRINT("Capturing Create Info\n");
+ Status = ObpCaptureObjectAttributes(ObjectAttributes,
+ ObjectAttributesAccessMode,
+ Type,
+ ObjectCreateInfo,
+ &ObjectName);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* Allocate the Object */
+ DPRINT("Allocating: %wZ\n", &ObjectName);
+ Status = ObpAllocateObject(ObjectCreateInfo,
+ &ObjectName,
+ Type,
+ OBJECT_ALLOC_SIZE(ObjectSize),
+ &Header);
+
+ if (NT_SUCCESS(Status))
+ {
+ /* Return the Object */
+ DPRINT("Returning Object\n");
+ *Object = &Header->Body;
+
+ /* Return to caller, leave the Capture Info Alive for ObInsert */
+ return Status;
+ }
+
+ /* Release the Capture Info, we don't need it */
+ DPRINT1("Allocation failed\n");
+ ObpReleaseCapturedAttributes(ObjectCreateInfo);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ }
+
+ /* We failed, so release the Buffer */
+ DPRINT1("Capture failed\n");
+ ExFreePool(ObjectCreateInfo);
+ return Status;
+}
+
+/*++
+* @name NtQueryObject
+* @implemented NT4
+*
+* The NtQueryObject routine
+*
+* @param ObjectHandle
+*
+*
+* @param ObjectInformationClass
+*
+*
+* @param ObjectInformation
+*
+*
+* @param Length
+*
+*
+* @param ResultLength
+*
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks None.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtQueryObject(IN HANDLE ObjectHandle,
+ IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
+ OUT PVOID ObjectInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength OPTIONAL)
+{
+ OBJECT_HANDLE_INFORMATION HandleInfo;
+ POBJECT_HEADER ObjectHeader;
+ ULONG InfoLength;
+ PVOID Object;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ NULL,
+ KeGetPreviousMode(),
+ &Object,
+ &HandleInfo);
+ if (!NT_SUCCESS (Status)) return Status;
+
+ ObjectHeader = BODY_TO_HEADER(Object);
+
+ switch (ObjectInformationClass)
+ {
+ case ObjectBasicInformation:
+ InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
+ if (Length != sizeof(OBJECT_BASIC_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ POBJECT_BASIC_INFORMATION BasicInfo;
+
+ BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation;
+ BasicInfo->Attributes = HandleInfo.HandleAttributes;
+ BasicInfo->GrantedAccess = HandleInfo.GrantedAccess;
+ BasicInfo->HandleCount = ObjectHeader->HandleCount;
+ BasicInfo->PointerCount = ObjectHeader->PointerCount;
+ BasicInfo->PagedPoolUsage = 0; /* FIXME*/
+ BasicInfo->NonPagedPoolUsage = 0; /* FIXME*/
+ BasicInfo->NameInformationLength = 0; /* FIXME*/
+ BasicInfo->TypeInformationLength = 0; /* FIXME*/
+ BasicInfo->SecurityDescriptorLength = 0; /* FIXME*/
+ if (ObjectHeader->Type == ObSymbolicLinkType)
+ {
+ BasicInfo->CreateTime.QuadPart =
+ ((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart;
+ }
+ else
+ {
+ BasicInfo->CreateTime.QuadPart = (ULONGLONG)0;
+ }
+ Status = STATUS_SUCCESS;
+ }
+ break;
+
+ case ObjectNameInformation:
+ Status = ObQueryNameString(Object,
+ (POBJECT_NAME_INFORMATION)ObjectInformation,
+ Length,
+ &InfoLength);
+ break;
+
+ case ObjectTypeInformation:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ObjectAllTypesInformation:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ObjectHandleInformation:
+ InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
+ if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ Status = ObpQueryHandleAttributes(
+ ObjectHandle,
+ (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)ObjectInformation);
+ }
+ break;
+
+ default:
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ ObDereferenceObject (Object);
+
+ if (ResultLength != NULL) *ResultLength = InfoLength;
+
+ return Status;
+}
+
+/*++
+* @name NtSetInformationObject
+* @implemented NT4
+*
+* The NtSetInformationObject routine
+*
+* @param ObjectHandle
+*
+*
+* @param ObjectInformationClass
+*
+*
+* @param ObjectInformation
+*
+*
+* @param Length
+*
+*
+* @return STATUS_SUCCESS or appropriate error value.
+*
+* @remarks None.
+*
+*--*/
+NTSTATUS
+NTAPI
+NtSetInformationObject(IN HANDLE ObjectHandle,
+ IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
+ IN PVOID ObjectInformation,
+ IN ULONG Length)
+{
+ PVOID Object;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ if (ObjectInformationClass != ObjectHandleInformation)
+ return STATUS_INVALID_INFO_CLASS;
+
+ if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ Status = ObReferenceObjectByHandle(ObjectHandle,
+ 0,
+ NULL,
+ KeGetPreviousMode(),
+ &Object,
+ NULL);
+ if (!NT_SUCCESS (Status)) return Status;
+
+ Status = ObpSetHandleAttributes(ObjectHandle,
+ (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
+ ObjectInformation);
+
+ ObDereferenceObject (Object);
+ return Status;
+}
+/* EOF */
diff --git a/reactos/ntoskrnl/ob/obname.c b/reactos/ntoskrnl/ob/obname.c
new file mode 100644
index 00000000000..13ca304923c
--- /dev/null
+++ b/reactos/ntoskrnl/ob/obname.c
@@ -0,0 +1,365 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ob/namespce.c
+ * PURPOSE: Manages all functions related to the Object Manager name-
+ * space, such as finding objects or querying their names.
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Eric Kohl
+ * Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+POBJECT_DIRECTORY NameSpaceRoot = NULL;
+POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+NTSTATUS
+NTAPI
+ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+ PUNICODE_STRING ObjectName,
+ PVOID* ReturnedObject,
+ PUNICODE_STRING RemainingPath,
+ POBJECT_TYPE ObjectType,
+ POBP_LOOKUP_CONTEXT Context)
+{
+ PVOID NextObject;
+ PVOID CurrentObject;
+ PVOID RootObject;
+ POBJECT_HEADER CurrentHeader;
+ NTSTATUS Status;
+ PWSTR current;
+ UNICODE_STRING PathString;
+ ULONG Attributes;
+
+ PAGED_CODE();
+
+ DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
+ "RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
+
+ RtlInitUnicodeString (RemainingPath, NULL);
+
+ if (ObjectCreateInfo->RootDirectory == NULL)
+ {
+ ObReferenceObjectByPointer(NameSpaceRoot,
+ DIRECTORY_TRAVERSE,
+ NULL,
+ ObjectCreateInfo->ProbeMode);
+ CurrentObject = NameSpaceRoot;
+ }
+ else
+ {
+ Status = ObReferenceObjectByHandle(ObjectCreateInfo->RootDirectory,
+ 0,
+ NULL,
+ ObjectCreateInfo->ProbeMode,
+ &CurrentObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ if (ObjectName->Length == 0 ||
+ ObjectName->Buffer[0] == UNICODE_NULL)
+ {
+ *ReturnedObject = CurrentObject;
+ return STATUS_SUCCESS;
+ }
+
+ if (ObjectCreateInfo->RootDirectory == NULL &&
+ ObjectName->Buffer[0] != L'\\')
+ {
+ ObDereferenceObject (CurrentObject);
+ DPRINT1("failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Create a zero-terminated copy of the object name */
+ PathString.Length = ObjectName->Length;
+ PathString.MaximumLength = ObjectName->Length + sizeof(WCHAR);
+ PathString.Buffer = ExAllocatePool (NonPagedPool,
+ PathString.MaximumLength);
+ if (PathString.Buffer == NULL)
+ {
+ ObDereferenceObject (CurrentObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyMemory (PathString.Buffer,
+ ObjectName->Buffer,
+ ObjectName->Length);
+ PathString.Buffer[PathString.Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+ current = PathString.Buffer;
+
+ RootObject = CurrentObject;
+ Attributes = ObjectCreateInfo->Attributes;
+ if (ObjectType == ObSymbolicLinkType)
+ Attributes |= OBJ_OPENLINK;
+
+ while (TRUE)
+ {
+ DPRINT("current %S\n",current);
+ CurrentHeader = BODY_TO_HEADER(CurrentObject);
+
+ DPRINT("Current ObjectType %wZ\n",
+ &CurrentHeader->Type->Name);
+
+ if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL)
+ {
+ DPRINT("Current object can't parse\n");
+ break;
+ }
+ Status = ((OB_ROS_PARSE_METHOD)CurrentHeader->Type->TypeInfo.ParseProcedure)(CurrentObject,
+ &NextObject,
+ &PathString,
+ ¤t,
+ Attributes,
+ Context);
+ if (Status == STATUS_REPARSE)
+ {
+ /* reparse the object path */
+ NextObject = NameSpaceRoot;
+ current = PathString.Buffer;
+
+ ObReferenceObjectByPointer(NextObject,
+ DIRECTORY_TRAVERSE,
+ NULL,
+ ObjectCreateInfo->ProbeMode);
+ }
+
+ if (NextObject == NULL)
+ {
+ break;
+ }
+ ObDereferenceObject(CurrentObject);
+ CurrentObject = NextObject;
+ }
+
+ if (current)
+ {
+ RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
+ }
+
+ RtlFreeUnicodeString (&PathString);
+ *ReturnedObject = CurrentObject;
+
+ return STATUS_SUCCESS;
+}
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+NTSTATUS
+STDCALL
+ObQueryNameString(IN PVOID Object,
+ OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
+ IN ULONG Length,
+ OUT PULONG ReturnLength)
+{
+ POBJECT_HEADER_NAME_INFO LocalInfo;
+ POBJECT_HEADER ObjectHeader;
+ POBJECT_DIRECTORY ParentDirectory;
+ ULONG NameSize;
+ PWCH ObjectName;
+ NTSTATUS Status;
+
+ DPRINT("ObQueryNameString: %x, %x\n", Object, ObjectNameInfo);
+
+ /* Get the Kernel Meta-Structures */
+ ObjectHeader = BODY_TO_HEADER(Object);
+ LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
+
+ /* Check if a Query Name Procedure is available */
+ if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
+ {
+ /* Call the procedure */
+ DPRINT("Calling Object's Procedure\n");
+ Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
+ TRUE, //fixme
+ ObjectNameInfo,
+ Length,
+ ReturnLength);
+
+ /* Return the status */
+ return Status;
+ }
+
+ /* Check if the object doesn't even have a name */
+ if (!LocalInfo || !LocalInfo->Name.Buffer)
+ {
+ /* We're returning the name structure */
+ DPRINT("Nameless Object\n");
+ *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
+
+ /* Check if we were given enough space */
+ if (*ReturnLength > Length)
+ {
+ DPRINT1("Not enough buffer space\n");
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Return an empty buffer */
+ ObjectNameInfo->Name.Length = 0;
+ ObjectNameInfo->Name.MaximumLength = 0;
+ ObjectNameInfo->Name.Buffer = NULL;
+
+ return STATUS_SUCCESS;
+ }
+
+ /*
+ * Find the size needed for the name. We won't do
+ * this during the Name Creation loop because we want
+ * to let the caller know that the buffer isn't big
+ * enough right at the beginning, not work our way through
+ * and find out at the end
+ */
+ if (Object == NameSpaceRoot)
+ {
+ /* Size of the '\' string */
+ DPRINT("Object is Root\n");
+ NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
+ }
+ else
+ {
+ /* Get the Object Directory and add name of Object */
+ ParentDirectory = LocalInfo->Directory;
+ NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
+
+ /* Loop inside the directory to get the top-most one (meaning root) */
+ while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
+ {
+ /* Get the Name Information */
+ LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
+
+ /* Add the size of the Directory Name */
+ if (LocalInfo && LocalInfo->Directory)
+ {
+ /* Size of the '\' string + Directory Name */
+ NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
+
+ /* Move to next parent Directory */
+ ParentDirectory = LocalInfo->Directory;
+ }
+ else
+ {
+ /* Directory with no name. We append "...\" */
+ DPRINT("Nameless Directory\n");
+ NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
+ break;
+ }
+ }
+ }
+
+ /* Finally, add the name of the structure and the null char */
+ *ReturnLength = NameSize + sizeof(OBJECT_NAME_INFORMATION) + sizeof(UNICODE_NULL);
+ DPRINT("Final Length: %x\n", *ReturnLength);
+
+ /* Check if we were given enough space */
+ if (*ReturnLength > Length)
+ {
+ DPRINT1("Not enough buffer space\n");
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /*
+ * Now we will actually create the name. We work backwards because
+ * it's easier to start off from the Name we have and walk up the
+ * parent directories. We use the same logic as Name Length calculation.
+ */
+ LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
+ ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
+ *--ObjectName = UNICODE_NULL;
+
+ if (Object == NameSpaceRoot)
+ {
+ /* This is already the Root Directory, return "\\" */
+ DPRINT("Returning Root Dir\n");
+ *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
+ ObjectNameInfo->Name.Length = (USHORT)NameSize;
+ ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
+ ObjectNameInfo->Name.Buffer = ObjectName;
+
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Start by adding the Object's Name */
+ ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
+ RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
+
+ /* Now parse the Parent directories until we reach the top */
+ ParentDirectory = LocalInfo->Directory;
+ while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
+ {
+ /* Get the name information */
+ LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
+
+ /* Add the "\" */
+ *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
+
+ /* Add the Parent Directory's Name */
+ if (LocalInfo && LocalInfo->Name.Buffer)
+ {
+ /* Add the name */
+ ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
+ RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
+
+ /* Move to next parent */
+ ParentDirectory = LocalInfo->Directory;
+ }
+ else
+ {
+ /* Directory without a name, we add "..." */
+ DPRINT("Nameless Directory\n");
+ ObjectName -= sizeof(L"...");
+ ObjectName = L"...";
+ break;
+ }
+ }
+
+ /* Add Root Directory Name */
+ *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
+ DPRINT("Current Buffer: %S\n", ObjectName);
+ ObjectNameInfo->Name.Length = (USHORT)NameSize;
+ ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
+ ObjectNameInfo->Name.Buffer = ObjectName;
+ DPRINT("Complete: %wZ\n", ObjectNameInfo);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+ObQueryDeviceMapInformation(IN PEPROCESS Process,
+ IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
+{
+ //KIRQL OldIrql ;
+
+ /*
+ * FIXME: This is an ugly hack for now, to always return the System Device Map
+ * instead of returning the Process Device Map. Not important yet since we don't use it
+ */
+
+ /* FIXME: Acquire the DeviceMap Spinlock */
+ // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
+
+ /* Make a copy */
+ DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
+ RtlMoveMemory(DeviceMapInfo->Query.DriveType,
+ ObSystemDeviceMap->DriveType,
+ sizeof(ObSystemDeviceMap->DriveType));
+
+ /* FIXME: Release the DeviceMap Spinlock */
+ // KeReleasepinLock(DeviceMap->Lock, OldIrql);
+}
+
+/* EOF */
diff --git a/reactos/ntoskrnl/ob/obref.c b/reactos/ntoskrnl/ob/obref.c
new file mode 100644
index 00000000000..cd29e5a5df0
--- /dev/null
+++ b/reactos/ntoskrnl/ob/obref.c
@@ -0,0 +1,455 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/ob/refderef.c
+ * PURPOSE: Manages the referencing and de-referencing of all Objects,
+ * as well as the Object Fast Reference implementation.
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Eric Kohl
+ * Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+FASTCALL
+ObInitializeFastReference(IN PEX_FAST_REF FastRef,
+ PVOID Object)
+{
+ /* FIXME: Fast Referencing is Unimplemented */
+ FastRef->Object = Object;
+}
+
+PVOID
+FASTCALL
+ObFastReferenceObject(IN PEX_FAST_REF FastRef)
+{
+ /* FIXME: Fast Referencing is Unimplemented */
+
+ /* Do a normal Reference */
+ ObReferenceObject(FastRef->Object);
+
+ /* Return the Object */
+ return FastRef->Object;
+}
+
+VOID
+FASTCALL
+ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
+ PVOID Object)
+{
+ /* FIXME: Fast Referencing is Unimplemented */
+
+ /* Do a normal Dereference */
+ ObDereferenceObject(FastRef->Object);
+}
+
+PVOID
+FASTCALL
+ObFastReplaceObject(IN PEX_FAST_REF FastRef,
+ PVOID Object)
+{
+ PVOID OldObject = FastRef->Object;
+
+ /* FIXME: Fast Referencing is Unimplemented */
+ FastRef->Object = Object;
+
+ /* Do a normal Dereference */
+ ObDereferenceObject(OldObject);
+
+ /* Return old Object*/
+ return OldObject;
+}
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+ULONG STDCALL
+ObGetObjectPointerCount(PVOID Object)
+{
+ POBJECT_HEADER Header;
+
+ PAGED_CODE();
+
+ ASSERT(Object);
+ Header = BODY_TO_HEADER(Object);
+
+ return Header->PointerCount;
+}
+
+VOID FASTCALL
+ObfReferenceObject(IN PVOID Object)
+{
+ POBJECT_HEADER Header;
+
+ ASSERT(Object);
+
+ Header = BODY_TO_HEADER(Object);
+
+ /* No one should be referencing an object once we are deleting it. */
+ if (InterlockedIncrement(&Header->PointerCount) == 1 && !(Header->Flags & OB_FLAG_PERMANENT))
+ {
+ KEBUGCHECK(0);
+ }
+
+}
+
+VOID
+FASTCALL
+ObfDereferenceObject(IN PVOID Object)
+{
+ POBJECT_HEADER Header;
+ LONG NewPointerCount;
+ BOOL Permanent;
+
+ ASSERT(Object);
+
+ /* Extract the object header. */
+ Header = BODY_TO_HEADER(Object);
+ Permanent = Header->Flags & OB_FLAG_PERMANENT;
+
+ /*
+ Drop our reference and get the new count so we can tell if this was the
+ last reference.
+ */
+ NewPointerCount = InterlockedDecrement(&Header->PointerCount);
+ DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object, NewPointerCount);
+ ASSERT(NewPointerCount >= 0);
+
+ /* Check whether the object can now be deleted. */
+ if (NewPointerCount == 0 &&
+ !Permanent)
+ {
+ ObpDeleteObjectDpcLevel(Header, NewPointerCount);
+ }
+}
+
+NTSTATUS STDCALL
+ObReferenceObjectByPointer(IN PVOID Object,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_TYPE ObjectType,
+ IN KPROCESSOR_MODE AccessMode)
+{
+ POBJECT_HEADER Header;
+
+ /* NOTE: should be possible to reference an object above APC_LEVEL! */
+
+ DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
+ Object,ObjectType);
+
+ Header = BODY_TO_HEADER(Object);
+
+ if (ObjectType != NULL && Header->Type != ObjectType)
+ {
+ DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
+ Header,
+ Header->Type,
+ &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Header->Type))->Name,
+ ObjectType,
+ &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObjectType))->Name);
+ return(STATUS_UNSUCCESSFUL);
+ }
+ if (Header->Type == PsProcessType)
+ {
+ DPRINT("Ref p 0x%x PointerCount %d type %x ",
+ Object, Header->PointerCount, PsProcessType);
+ DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
+ }
+ if (Header->Type == PsThreadType)
+ {
+ DPRINT("Deref t 0x%x with PointerCount %d type %x ",
+ Object, Header->PointerCount, PsThreadType);
+ DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
+ }
+
+ if (Header->PointerCount == 0 && !(Header->Flags & OB_FLAG_PERMANENT))
+ {
+ if (Header->Type == PsProcessType)
+ {
+ return STATUS_PROCESS_IS_TERMINATING;
+ }
+ if (Header->Type == PsThreadType)
+ {
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ if (1 == InterlockedIncrement(&Header->PointerCount) && !(Header->Flags & OB_FLAG_PERMANENT))
+ {
+ KEBUGCHECK(0);
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+NTSTATUS STDCALL
+ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
+ ULONG Attributes,
+ PACCESS_STATE PassedAccessState,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_TYPE ObjectType,
+ KPROCESSOR_MODE AccessMode,
+ PVOID ParseContext,
+ PVOID* ObjectPtr)
+{
+ PVOID Object = NULL;
+ UNICODE_STRING RemainingPath;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ NTSTATUS Status;
+ OBP_LOOKUP_CONTEXT Context;
+
+ PAGED_CODE();
+
+ /* Capture the name */
+ DPRINT("Capturing Name\n");
+ Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObpCaptureObjectName() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ /*
+ * Create a fake ObjectCreateInfo structure. Note that my upcoming
+ * ObFindObject refactoring will remove the need for this hack.
+ */
+ ObjectCreateInfo.RootDirectory = NULL;
+ ObjectCreateInfo.Attributes = Attributes;
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ &Object,
+ &RemainingPath,
+ ObjectType,
+ &Context);
+
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+ DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
+
+ if (RemainingPath.Buffer != NULL || Object == NULL)
+ {
+ DPRINT("Object %p\n", Object);
+ *ObjectPtr = NULL;
+ RtlFreeUnicodeString (&RemainingPath);
+ return(STATUS_OBJECT_NAME_NOT_FOUND);
+ }
+ *ObjectPtr = Object;
+ RtlFreeUnicodeString (&RemainingPath);
+ return(STATUS_SUCCESS);
+}
+
+NTSTATUS STDCALL
+ObReferenceObjectByHandle(HANDLE Handle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_TYPE ObjectType,
+ KPROCESSOR_MODE AccessMode,
+ PVOID* Object,
+ POBJECT_HANDLE_INFORMATION HandleInformation)
+{
+ PHANDLE_TABLE_ENTRY HandleEntry;
+ POBJECT_HEADER ObjectHeader;
+ PVOID ObjectBody;
+ ACCESS_MASK GrantedAccess;
+ ULONG Attributes;
+ PEPROCESS CurrentProcess, Process;
+ BOOLEAN AttachedToProcess = FALSE;
+ KAPC_STATE ApcState;
+
+ PAGED_CODE();
+
+ DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
+ "ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
+ ObjectType,AccessMode,Object);
+
+ if (Handle == NULL)
+ {
+ return STATUS_INVALID_HANDLE;
+ }
+
+ CurrentProcess = PsGetCurrentProcess();
+
+ /*
+ * Handle special handle names
+ */
+ if (Handle == NtCurrentProcess() &&
+ (ObjectType == PsProcessType || ObjectType == NULL))
+ {
+ ObReferenceObject(CurrentProcess);
+
+ if (HandleInformation != NULL)
+ {
+ HandleInformation->HandleAttributes = 0;
+ HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
+ }
+
+ *Object = CurrentProcess;
+ DPRINT("Referencing current process %p\n", CurrentProcess);
+ return STATUS_SUCCESS;
+ }
+ else if (Handle == NtCurrentProcess())
+ {
+ CHECKPOINT;
+ return(STATUS_OBJECT_TYPE_MISMATCH);
+ }
+
+ if (Handle == NtCurrentThread() &&
+ (ObjectType == PsThreadType || ObjectType == NULL))
+ {
+ PETHREAD CurrentThread = PsGetCurrentThread();
+
+ ObReferenceObject(CurrentThread);
+
+ if (HandleInformation != NULL)
+ {
+ HandleInformation->HandleAttributes = 0;
+ HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
+ }
+
+ *Object = CurrentThread;
+ CHECKPOINT;
+ return STATUS_SUCCESS;
+ }
+ else if (Handle == NtCurrentThread())
+ {
+ CHECKPOINT;
+ return(STATUS_OBJECT_TYPE_MISMATCH);
+ }
+
+ /* desire as much access rights as possible */
+ if (DesiredAccess & MAXIMUM_ALLOWED)
+ {
+ DesiredAccess &= ~MAXIMUM_ALLOWED;
+ DesiredAccess |= GENERIC_ALL;
+ }
+
+ if(ObIsKernelHandle(Handle, AccessMode))
+ {
+ Process = PsInitialSystemProcess;
+ Handle = ObKernelHandleToHandle(Handle);
+ }
+ else
+ {
+ Process = CurrentProcess;
+ }
+
+ KeEnterCriticalRegion();
+
+ if (Process != CurrentProcess)
+ {
+ KeStackAttachProcess(&Process->Pcb,
+ &ApcState);
+ AttachedToProcess = TRUE;
+ }
+
+ HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+ Handle);
+ if (HandleEntry == NULL)
+ {
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+ KeLeaveCriticalRegion();
+ DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
+ return(STATUS_INVALID_HANDLE);
+ }
+
+ ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+ ObjectBody = &ObjectHeader->Body;
+
+ DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
+
+ if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
+ {
+ DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
+
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ KeLeaveCriticalRegion();
+
+ return(STATUS_OBJECT_TYPE_MISMATCH);
+ }
+
+ /* map the generic access masks if the caller asks for generic access */
+ if (DesiredAccess & GENERIC_ACCESS)
+ {
+ RtlMapGenericMask(&DesiredAccess,
+ &BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
+ }
+
+ GrantedAccess = HandleEntry->GrantedAccess;
+
+ /* Unless running as KernelMode, deny access if caller desires more access
+ rights than the handle can grant */
+ if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
+ {
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ 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->ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
+ EX_HANDLE_ENTRY_INHERITABLE |
+ EX_HANDLE_ENTRY_AUDITONCLOSE);
+
+ ExUnlockHandleTableEntry(Process->ObjectTable,
+ HandleEntry);
+
+ if (AttachedToProcess)
+ {
+ KeUnstackDetachProcess(&ApcState);
+ }
+
+ KeLeaveCriticalRegion();
+
+ if (HandleInformation != NULL)
+ {
+ HandleInformation->HandleAttributes = Attributes;
+ HandleInformation->GrantedAccess = GrantedAccess;
+ }
+
+ *Object = ObjectBody;
+
+ return(STATUS_SUCCESS);
+}
+
+#ifdef ObDereferenceObject
+#undef ObDereferenceObject
+#endif
+
+VOID STDCALL
+ObDereferenceObject(IN PVOID Object)
+{
+ ObfDereferenceObject(Object);
+}
+/* EOF */