- 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:
Alex Ionescu
2006-05-24 21:44:59 +00:00
parent 5c92d07c04
commit 901bb3dc40
13 changed files with 3972 additions and 4227 deletions
+15 -2
View File
@@ -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
+3
View File
@@ -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')
+6 -5
View File
@@ -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
-510
View File
@@ -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 */
-348
View File
@@ -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
+174
View File
@@ -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
+921
View File
@@ -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 */
+365
View File
@@ -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,
&current,
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 */
+455
View File
@@ -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 */