reactos/reactos/ntoskrnl/ob/namespc.c
Eric Kohl 5bba28324f Fixed a long-standing hack to open symbolic link objects.
svn path=/trunk/; revision=3133
2002-06-20 21:31:39 +00:00

445 lines
10 KiB
C

/* $Id: namespc.c,v 1.31 2002/06/20 21:31:39 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ob/namespc.c
* PURPOSE: Manages the system namespace
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
* 22/05/98: Created
*/
/* INCLUDES ***************************************************************/
#include <limits.h>
#include <ddk/ntddk.h>
#include <internal/ob.h>
#include <internal/io.h>
#include <internal/pool.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ****************************************************************/
POBJECT_TYPE ObDirectoryType = NULL;
POBJECT_TYPE ObTypeObjectType = NULL;
PDIRECTORY_OBJECT NameSpaceRoot = NULL;
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};
/* FUNCTIONS **************************************************************/
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;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
InitializeObjectAttributes(&ObjectAttributes,
ObjectPath,
Attributes,
NULL,
NULL);
Status = ObFindObject(&ObjectAttributes,
&Object,
&RemainingPath,
ObjectType);
if (!NT_SUCCESS(Status))
{
return(Status);
}
CHECKPOINT;
DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
if (RemainingPath.Buffer != NULL || Object == NULL)
{
CHECKPOINT;
DPRINT("Object %p\n", Object);
*ObjectPtr = NULL;
RtlFreeUnicodeString (&RemainingPath);
return(STATUS_UNSUCCESSFUL);
}
*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.
*/
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;
NTSTATUS Status;
DPRINT("ObOpenObjectByName()\n");
Status = ObFindObject(ObjectAttributes,
&Object,
&RemainingPath,
ObjectType);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (RemainingPath.Buffer != NULL ||
Object == NULL)
{
RtlFreeUnicodeString(&RemainingPath);
return STATUS_UNSUCCESSFUL;
}
Status = ObCreateHandle(PsGetCurrentProcess(),
Object,
DesiredAccess,
FALSE,
Handle);
ObDereferenceObject(Object);
RtlFreeUnicodeString(&RemainingPath);
return Status;
}
VOID
ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
POBJECT_HEADER Header,
PWSTR Name)
/*
* FUNCTION: Add an entry to a namespace directory
* ARGUMENTS:
* Parent = directory to add in
* Header = Header of the object to add the entry for
* Name = Name to give the entry
*/
{
KIRQL oldlvl;
RtlCreateUnicodeString(&Header->Name, Name);
Header->Parent = Parent;
KeAcquireSpinLock(&Parent->Lock, &oldlvl);
InsertTailList(&Parent->head, &Header->Entry);
KeReleaseSpinLock(&Parent->Lock, oldlvl);
}
VOID
ObpRemoveEntryDirectory(POBJECT_HEADER Header)
/*
* FUNCTION: Remove an entry from a namespace directory
* ARGUMENTS:
* Header = Header of the object to remove
*/
{
KIRQL oldlvl;
DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
RemoveEntryList(&(Header->Entry));
KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
}
PVOID
ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
PWSTR Name,
ULONG Attributes)
{
PLIST_ENTRY current = DirectoryObject->head.Flink;
POBJECT_HEADER current_obj;
DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
if (Name[0]==0)
{
return(DirectoryObject);
}
if (Name[0]=='.' && Name[1]==0)
{
return(DirectoryObject);
}
if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
{
return(BODY_TO_HEADER(DirectoryObject)->Parent);
}
while (current!=(&(DirectoryObject->head)))
{
current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
DPRINT("Scanning %S %S\n",current_obj->Name.Buffer, Name);
if (Attributes & OBJ_CASE_INSENSITIVE)
{
if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
{
DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
return(HEADER_TO_BODY(current_obj));
}
}
else
{
if ( wcscmp(current_obj->Name.Buffer, Name)==0)
{
DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
return(HEADER_TO_BODY(current_obj));
}
}
current = current->Flink;
}
DPRINT("%s() = NULL\n",__FUNCTION__);
return(NULL);
}
NTSTATUS STDCALL
ObpParseDirectory(PVOID Object,
PVOID * NextObject,
PUNICODE_STRING FullPath,
PWSTR * Path,
ULONG Attributes)
{
PWSTR end;
PVOID FoundObject;
DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
Object,Path,*Path);
*NextObject = NULL;
if ((*Path) == NULL)
{
return STATUS_UNSUCCESSFUL;
}
end = wcschr((*Path)+1, '\\');
if (end != NULL)
{
*end = 0;
}
FoundObject = ObpFindEntryDirectory(Object, (*Path)+1, Attributes);
if (FoundObject == NULL)
{
if (end != NULL)
{
*end = '\\';
}
return STATUS_UNSUCCESSFUL;
}
ObReferenceObjectByPointer(FoundObject,
STANDARD_RIGHTS_REQUIRED,
NULL,
UserMode);
if (end != NULL)
{
*end = '\\';
*Path = end;
}
else
{
*Path = NULL;
}
*NextObject = FoundObject;
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
ObpCreateDirectory(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
InitializeListHead(&DirectoryObject->head);
KeInitializeSpinLock(&DirectoryObject->Lock);
return(STATUS_SUCCESS);
}
VOID
ObInit(VOID)
/*
* FUNCTION: Initialize the object manager namespace
*/
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING Name;
/* create 'directory' object type */
ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
ObDirectoryType->TotalObjects = 0;
ObDirectoryType->TotalHandles = 0;
ObDirectoryType->MaxObjects = ULONG_MAX;
ObDirectoryType->MaxHandles = ULONG_MAX;
ObDirectoryType->PagedPoolCharge = 0;
ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
ObDirectoryType->Mapping = &ObpDirectoryMapping;
ObDirectoryType->Dump = NULL;
ObDirectoryType->Open = NULL;
ObDirectoryType->Close = NULL;
ObDirectoryType->Delete = NULL;
ObDirectoryType->Parse = ObpParseDirectory;
ObDirectoryType->Security = NULL;
ObDirectoryType->QueryName = NULL;
ObDirectoryType->OkayToClose = NULL;
ObDirectoryType->Create = ObpCreateDirectory;
ObDirectoryType->DuplicationNotify = NULL;
RtlInitUnicodeString(&ObDirectoryType->TypeName,
L"Directory");
/* create 'type' object type*/
ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T');
ObTypeObjectType->TotalObjects = 0;
ObTypeObjectType->TotalHandles = 0;
ObTypeObjectType->MaxObjects = ULONG_MAX;
ObTypeObjectType->MaxHandles = ULONG_MAX;
ObTypeObjectType->PagedPoolCharge = 0;
ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT);
ObTypeObjectType->Mapping = &ObpTypeMapping;
ObTypeObjectType->Dump = NULL;
ObTypeObjectType->Open = NULL;
ObTypeObjectType->Close = NULL;
ObTypeObjectType->Delete = NULL;
ObTypeObjectType->Parse = NULL;
ObTypeObjectType->Security = NULL;
ObTypeObjectType->QueryName = NULL;
ObTypeObjectType->OkayToClose = NULL;
ObTypeObjectType->Create = NULL;
ObTypeObjectType->DuplicationNotify = NULL;
RtlInitUnicodeString(&ObTypeObjectType->TypeName,
L"ObjectType");
/* create root directory */
ObCreateObject(NULL,
STANDARD_RIGHTS_REQUIRED,
NULL,
ObDirectoryType,
(PVOID*)&NameSpaceRoot);
/* create '\ObjectTypes' directory */
RtlInitUnicodeString(&Name,
L"\\ObjectTypes");
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_PERMANENT,
NULL,
NULL);
ObCreateObject(NULL,
STANDARD_RIGHTS_REQUIRED,
&ObjectAttributes,
ObDirectoryType,
NULL);
ObpCreateTypeObject(ObDirectoryType);
ObpCreateTypeObject(ObTypeObjectType);
}
NTSTATUS
ObpCreateTypeObject(POBJECT_TYPE ObjectType)
{
OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR NameString[120];
PTYPE_OBJECT TypeObject = NULL;
UNICODE_STRING Name;
NTSTATUS Status;
DPRINT("ObjectType: %wZ\n", &ObjectType->TypeName);
wcscpy(NameString, L"\\ObjectTypes\\");
wcscat(NameString, ObjectType->TypeName.Buffer);
RtlInitUnicodeString(&Name,
NameString);
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_PERMANENT,
NULL,
NULL);
Status = ObCreateObject(NULL,
STANDARD_RIGHTS_REQUIRED,
&ObjectAttributes,
ObTypeObjectType,
(PVOID*)&TypeObject);
if (NT_SUCCESS(Status))
{
TypeObject->ObjectType = ObjectType;
}
return(STATUS_SUCCESS);
}
/* EOF */