mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
- Reorganize most of /ob so that functions inside each module actually follow some sort of cohesive model instead of complete randomness.
svn path=/trunk/; revision=22024
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -265,11 +265,12 @@
|
||||
<file>elf64.c</file>
|
||||
</directory>
|
||||
<directory name="ob">
|
||||
<file>dirobj.c</file>
|
||||
<file>handle.c</file>
|
||||
<file>namespc.c</file>
|
||||
<file>ntobj.c</file>
|
||||
<file>object.c</file>
|
||||
<file>obdir.c</file>
|
||||
<file>obinit.c</file>
|
||||
<file>obhandle.c</file>
|
||||
<file>obname.c</file>
|
||||
<file>oblife.c</file>
|
||||
<file>obref.c</file>
|
||||
<file>sdcache.c</file>
|
||||
<file>security.c</file>
|
||||
<file>symlink.c</file>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES ***************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#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 */
|
||||
@@ -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 ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*++
|
||||
* @name ObpSetPermanentObject
|
||||
*
|
||||
* The ObpSetPermanentObject routine <FILLMEIN>
|
||||
*
|
||||
* @param ObjectBody
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param Permanent
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 <FILLMEIN>
|
||||
*
|
||||
* @param ObjectBody
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @remarks None.
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
ObMakeTemporaryObject(IN PVOID ObjectBody)
|
||||
{
|
||||
ObpSetPermanentObject (ObjectBody, FALSE);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name NtSetInformationObject
|
||||
* @implemented NT4
|
||||
*
|
||||
* The NtSetInformationObject routine <FILLMEIN>
|
||||
*
|
||||
* @param ObjectHandle
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformationClass
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformation
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param Length
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 <FILLMEIN>
|
||||
*
|
||||
* @param ObjectHandle
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformationClass
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformation
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param Length
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ResultLength
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 <FILLMEIN>
|
||||
*
|
||||
* @param ObjectHandle
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 <FILLMEIN>
|
||||
*
|
||||
* @param ObjectHandle
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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 ([email protected])
|
||||
* Eric Kohl
|
||||
* Thomas Weidenmueller ([email protected])
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
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 <FILLMEIN>
|
||||
*
|
||||
* @param ObjectHandle
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformationClass
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformation
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param Length
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ResultLength
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 <FILLMEIN>
|
||||
*
|
||||
* @param ObjectHandle
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformationClass
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param ObjectInformation
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @param Length
|
||||
* <FILLMEIN>
|
||||
*
|
||||
* @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 */
|
||||
@@ -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 <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
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 */
|
||||
@@ -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 <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* 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 */
|
||||
Reference in New Issue
Block a user