-/*
+/* $Id$
+ *
* 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
+ *
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES ***************************************************************/
-#include <windows.h>
-#include <wstring.h>
-#include <ddk/ntddk.h>
-#include <internal/ob.h>
-#include <internal/io.h>
-#include <internal/string.h>
-
+#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;
-static struct
-{
- OBJECT_HEADER hdr;
-// DIRECTORY_OBJECT directory;
- LIST_ENTRY head;
- KSPIN_LOCK Lock;
-} namespc_root = {{0,},};
+PDIRECTORY_OBJECT NameSpaceRoot = NULL;
+PDIRECTORY_OBJECT ObpTypeDirectoryObject = NULL;
+ /* FIXME: Move this somewhere else once devicemap support is in */
+PDEVICE_MAP ObSystemDeviceMap = NULL;
+KEVENT ObpDefaultObject;
-/* FUNCTIONS **************************************************************/
+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};
-NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- return(ZwOpenDirectoryObject(DirectoryHandle,
- DesiredAccess,
- ObjectAttributes));
-}
+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 **************************************************************/
-NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
/*
- * FUNCTION: Opens a namespace directory object
- * ARGUMENTS:
- * DirectoryHandle (OUT) = Variable which receives the directory handle
- * DesiredAccess = Desired access to the directory
- * ObjectAttributes = Structure describing the directory
- * RETURNS: Status
- * NOTES: Undocumented
+ * @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;
+ PVOID Object = NULL;
+ UNICODE_STRING RemainingPath;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
NTSTATUS Status;
- PWSTR Ignored;
-
- *DirectoryHandle = 0;
-
- Status = ObOpenObjectByName(ObjectAttributes,&Object,&Ignored);
+
+ 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);
+
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
if (!NT_SUCCESS(Status))
{
return(Status);
}
-
- if (BODY_TO_HEADER(Object)->Type!=OBJTYP_DIRECTORY)
- {
- return(STATUS_UNSUCCESSFUL);
+ 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);
}
-
- *DirectoryHandle = ObInsertHandle(KeGetCurrentProcess(),Object,
- DesiredAccess,FALSE);
- CHECKPOINT;
+ *ObjectPtr = Object;
+ RtlFreeUnicodeString (&RemainingPath);
return(STATUS_SUCCESS);
}
-NTSTATUS NtQueryDirectoryObject(IN HANDLE DirObjHandle,
- OUT POBJDIR_INFORMATION DirObjInformation,
- IN ULONG BufferLength,
- IN BOOLEAN GetNextIndex,
- IN BOOLEAN IgnoreInputIndex,
- IN OUT PULONG ObjectIndex,
- OUT PULONG DataWritten OPTIONAL)
-{
- return(ZwQueryDirectoryObject(DirObjHandle,
- DirObjInformation,
- BufferLength,
- GetNextIndex,
- IgnoreInputIndex,
- ObjectIndex,
- DataWritten));
-}
-NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle,
- OUT POBJDIR_INFORMATION DirObjInformation,
- IN ULONG BufferLength,
- IN BOOLEAN GetNextIndex,
- IN BOOLEAN IgnoreInputIndex,
- IN OUT PULONG ObjectIndex,
- OUT PULONG DataWritten OPTIONAL)
-/*
- * FUNCTION: Reads information from a namespace directory
- * ARGUMENTS:
- * DirObjInformation (OUT) = Buffer to hold the data read
- * BufferLength = Size of the buffer in bytes
- * GetNextIndex = If TRUE then set ObjectIndex to the index of the
- * next object
- * If FALSE then set ObjectIndex to the number of
- * objects in the directory
- * IgnoreInputIndex = If TRUE start reading at index 0
- * If FALSE start reading at the index specified
- * by object index
- * ObjectIndex = Zero based index into the directory, interpretation
- * depends on IgnoreInputIndex and GetNextIndex
- * DataWritten (OUT) = Caller supplied storage for the number of bytes
- * written (or NULL)
- * RETURNS: Status
+/**********************************************************************
+ * 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)
{
- PDIRECTORY_OBJECT dir = NULL;
- ULONG EntriesToRead;
- PLIST_ENTRY current_entry;
- POBJECT_HEADER current;
- ULONG i=0;
- ULONG EntriesToSkip;
+ UNICODE_STRING RemainingPath;
+ PVOID Object = NULL;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
NTSTATUS Status;
-
- DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle);
- DPRINT("dir %x namespc_root %x\n",dir,HEADER_TO_BODY(&(namespc_root.hdr)));
-
-// assert_irql(PASSIVE_LEVEL);
-
- Status = ObReferenceObjectByHandle(DirObjHandle,
- DIRECTORY_QUERY,
- ObDirectoryType,
- UserMode,
- (PVOID*)&dir,
- NULL);
- if (Status != STATUS_SUCCESS)
+
+ 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))
{
- return(Status);
+ DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+ return Status;
}
-
- EntriesToRead = BufferLength / sizeof(OBJDIR_INFORMATION);
- *DataWritten = 0;
-
- DPRINT("EntriesToRead %d\n",EntriesToRead);
-
- current_entry = dir->head.Flink;
-
- /*
- * Optionally, skip over some entries at the start of the directory
- */
- if (!IgnoreInputIndex)
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ &Object,
+ &RemainingPath,
+ ObjectType);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ if (!NT_SUCCESS(Status))
{
- CHECKPOINT;
-
- EntriesToSkip = *ObjectIndex;
- while ( i<EntriesToSkip && current_entry!=NULL)
- {
- current_entry = current_entry->Flink;
- }
+ DPRINT("ObFindObject() failed (Status %lx)\n", Status);
+ goto Cleanup;
}
-
- DPRINT("DirObjInformation %x\n",DirObjInformation);
-
- /*
- * Read the maximum entries possible into the buffer
- */
- while ( i<EntriesToRead && current_entry!=(&(dir->head)))
+
+ DPRINT("OBject: %p, Remaining Path: %wZ\n", Object, &RemainingPath);
+ if (Object == NULL)
{
- current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,Entry);
- DPRINT("Scanning %w\n",current->Name.Buffer);
- DirObjInformation[i].ObjectName.Buffer =
- ExAllocatePool(NonPagedPool,(current->Name.Length+1)*2);
- DirObjInformation[i].ObjectName.Length = current->Name.Length;
- DirObjInformation[i].ObjectName.MaximumLength = current->Name.Length;
- DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n",
- DirObjInformation[i].ObjectName.Buffer);
- RtlCopyUnicodeString(&DirObjInformation[i].ObjectName,
- &(current->Name));
- i++;
- current_entry = current_entry->Flink;
- (*DataWritten) = (*DataWritten) + sizeof(OBJDIR_INFORMATION);
- CHECKPOINT;
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
- CHECKPOINT;
+ 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;
+ }
- /*
- * Optionally, count the number of entries in the directory
- */
- if (GetNextIndex)
- {
- *ObjectIndex=i;
- }
- else
- {
- while ( current_entry!=(&(dir->head)) )
- {
- current_entry=current_entry->Flink;
- i++;
- }
- *ObjectIndex=i;
- }
- return(STATUS_SUCCESS);
-}
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ ObjectCreateInfo.Attributes,
+ Handle);
+Cleanup:
+ if (Object != NULL)
+ {
+ ObDereferenceObject(Object);
+ }
+ RtlFreeUnicodeString(&RemainingPath);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
-NTSTATUS ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
- ULONG Attributes,
- PACCESS_STATE PassedAccessState,
- ACCESS_MASK DesiredAccess,
- POBJECT_TYPE ObjectType,
- KPROCESSOR_MODE AccessMode,
- PVOID ParseContext,
- PVOID* ObjectPtr)
-{
- UNIMPLEMENTED;
+ return Status;
}
-NTSTATUS ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes,
- PVOID* Object, PWSTR* UnparsedSection)
+VOID
+STDCALL
+ObQueryDeviceMapInformation(PEPROCESS Process,
+ PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
{
- NTSTATUS Status;
-
- DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n",
- ObjectAttributes,Object);
- DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n",
- ObjectAttributes->ObjectName,ObjectAttributes->ObjectName->Buffer);
- DPRINT("ObjectAttributes->ObjectName->Length %d\n",
- ObjectAttributes->ObjectName->Length);
-
- *Object = NULL;
- Status = ObLookupObject(ObjectAttributes->RootDirectory,
- ObjectAttributes->ObjectName->Buffer,
- Object,
- UnparsedSection,
- ObjectAttributes->Attributes);
- DPRINT("*Object %x\n",*Object);
- DPRINT("ObjectAttributes->ObjectName->Length %d\n",
- ObjectAttributes->ObjectName->Length);
- return(Status);
+ //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 ObInit(void)
+VOID
+NTAPI
+ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
+ POBJECT_HEADER Header,
+ PWSTR Name)
/*
- * FUNCTION: Initialize the object manager namespace
+ * 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
*/
{
- ANSI_STRING AnsiString;
-
- ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
- ObDirectoryType->TotalObjects = 0;
- ObDirectoryType->TotalHandles = 0;
- ObDirectoryType->MaxObjects = ULONG_MAX;
- ObDirectoryType->MaxHandles = ULONG_MAX;
- ObDirectoryType->PagedPoolCharge = 0;
- ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
- ObDirectoryType->Dump = NULL;
- ObDirectoryType->Open = NULL;
- ObDirectoryType->Close = NULL;
- ObDirectoryType->Delete = NULL;
- ObDirectoryType->Parse = NULL;
- ObDirectoryType->Security = NULL;
- ObDirectoryType->QueryName = NULL;
- ObDirectoryType->OkayToClose = NULL;
-
- RtlInitAnsiString(&AnsiString,"Directory");
- RtlAnsiStringToUnicodeString(&ObDirectoryType->TypeName,
- &AnsiString,TRUE);
-
- ObInitializeObjectHeader(ObDirectoryType,NULL,&namespc_root.hdr);
- InitializeListHead(&namespc_root.head);
-}
+ KIRQL oldlvl;
-NTSTATUS NtCreateDirectoryObject(PHANDLE DirectoryHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- return(ZwCreateDirectoryObject(DirectoryHandle,
- DesiredAccess,
- ObjectAttributes));
+ ASSERT(HEADER_TO_OBJECT_NAME(Header));
+ HEADER_TO_OBJECT_NAME(Header)->Directory = Parent;
+
+ KeAcquireSpinLock(&Parent->Lock, &oldlvl);
+ InsertTailList(&Parent->head, &Header->Entry);
+ KeReleaseSpinLock(&Parent->Lock, oldlvl);
}
-NTSTATUS ZwCreateDirectoryObject(PHANDLE DirectoryHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
+
+VOID
+NTAPI
+ObpRemoveEntryDirectory(POBJECT_HEADER Header)
/*
- * FUNCTION: Creates or opens a directory object (a container for other
- * objects)
+ * FUNCTION: Remove an entry from a namespace directory
* ARGUMENTS:
- * DirectoryHandle (OUT) = Caller supplied storage for the handle
- * of the directory
- * DesiredAccess = Access desired to the directory
- * ObjectAttributes = Object attributes initialized with
- * InitializeObjectAttributes
- * RETURNS: Status
+ * Header = Header of the object to remove
*/
{
- PDIRECTORY_OBJECT dir;
-
- dir = ObGenericCreateObject(DirectoryHandle,DesiredAccess,ObjectAttributes,
- ObDirectoryType);
-
- /*
- * Initialize the object body
- */
- InitializeListHead(&dir->head);
- KeInitializeSpinLock(&(dir->Lock));
-
- return(STATUS_SUCCESS);
+ KIRQL oldlvl;
+
+ DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
+
+ KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),&oldlvl);
+ if (Header->Entry.Flink && Header->Entry.Blink)
+ {
+ RemoveEntryList(&(Header->Entry));
+ Header->Entry.Flink = Header->Entry.Blink = NULL;
+ }
+ KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl);
}
-VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes,
- PUNICODE_STRING ObjectName,
- ULONG Attributes,
- HANDLE RootDirectory,
- PSECURITY_DESCRIPTOR SecurityDescriptor)
-/*
- * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a
- * subsequent call to ZwCreateXXX or ZwOpenXXX
- * ARGUMENTS:
- * InitializedAttributes (OUT) = Caller supplied storage for the
- * object attributes
- * ObjectName = Full path name for object
- * Attributes = Attributes for the object
- * RootDirectory = Where the object should be placed or NULL
- * SecurityDescriptor = Ignored
- *
- * NOTE:
- * Either ObjectName is a fully qualified pathname or a path relative
- * to RootDirectory
- */
+NTSTATUS
+STDCALL
+ObpCreateDirectory(OB_OPEN_REASON Reason,
+ PVOID ObjectBody,
+ PEPROCESS Process,
+ ULONG HandleCount,
+ ACCESS_MASK GrantedAccess)
{
- DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
- "ObjectName %x Attributes %x RootDirectory %x)\n",
- InitializedAttributes,ObjectName,Attributes,RootDirectory);
- InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES);
- InitializedAttributes->RootDirectory=RootDirectory;
- InitializedAttributes->ObjectName=ObjectName;
- InitializedAttributes->Attributes=Attributes;
- InitializedAttributes->SecurityDescriptor=SecurityDescriptor;
- InitializedAttributes->SecurityQualityOfService=NULL;
+ PDIRECTORY_OBJECT Directory = ObjectBody;
+
+ if (Reason == ObCreateHandle)
+ {
+ InitializeListHead(&Directory->head);
+ KeInitializeSpinLock(&Directory->Lock);
+ }
+
+ return STATUS_SUCCESS;
}
-static PVOID ObDirLookup(PDIRECTORY_OBJECT dir, PWSTR name,
- ULONG Attributes)
-/*
- * FUNCTION: Looks up an entry within a namespace directory
- * ARGUMENTS:
- * dir = Directory to lookup in
- * name = Entry name to find
- * RETURNS: A pointer to the object body if found
- * NULL otherwise
- */
+PVOID
+ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
+ PWSTR Name,
+ ULONG Attributes)
{
- LIST_ENTRY* current = dir->head.Flink;
+ PLIST_ENTRY current = DirectoryObject->head.Flink;
POBJECT_HEADER current_obj;
-
- DPRINT("ObDirLookup(dir %x, name %w)\n",dir,name);
-
- if (name[0]==0)
+
+ DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
+
+ if (Name[0]==0)
{
- return(dir);
+ return(DirectoryObject);
}
- if (name[0]=='.'&&name[1]==0)
+ if (Name[0]=='.' && Name[1]==0)
{
- return(dir);
+ return(DirectoryObject);
}
- if (name[0]=='.'&&name[1]=='.'&&name[2]==0)
+ if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
{
- return(BODY_TO_HEADER(dir)->Parent);
+ return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory);
}
- while (current!=(&(dir->head)))
+ while (current!=(&(DirectoryObject->head)))
{
current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
- DPRINT("Scanning %w\n",current_obj->Name.Buffer);
+ DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name);
if (Attributes & OBJ_CASE_INSENSITIVE)
{
- if (wcsicmp(current_obj->Name.Buffer, name)==0)
+ if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
{
- DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
- return(HEADER_TO_BODY(current_obj));
+ DPRINT("Found it %x\n",¤t_obj->Body);
+ return(¤t_obj->Body);
}
}
else
{
- if ( wcscmp(current_obj->Name.Buffer, name)==0)
+ if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
{
- DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
- return(HEADER_TO_BODY(current_obj));
+ DPRINT("Found it %x\n",¤t_obj->Body);
+ return(¤t_obj->Body);
}
}
current = current->Flink;
}
- DPRINT("%s() = NULL\n",__FUNCTION__);
+ DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
return(NULL);
}
-VOID ObRemoveEntry(POBJECT_HEADER Header)
+
+NTSTATUS STDCALL
+ObpParseDirectory(PVOID Object,
+ PVOID * NextObject,
+ PUNICODE_STRING FullPath,
+ PWSTR * Path,
+ ULONG Attributes)
{
- KIRQL oldlvl;
-
- DPRINT("ObRemoveEntry(Header %x)\n",Header);
-
- KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
- RemoveEntryList(&(Header->Entry));
- KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
+ PWSTR Start;
+ PWSTR End;
+ PVOID FoundObject;
+ KIRQL oldlvl;
+
+ DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
+ Object,Path,*Path);
+
+ *NextObject = NULL;
+
+ if ((*Path) == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Start = *Path;
+ if (*Start == L'\\')
+ Start++;
+
+ End = wcschr(Start, L'\\');
+ if (End != NULL)
+ {
+ *End = 0;
+ }
+
+ KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
+ FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
+ if (FoundObject == NULL)
+ {
+ KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
+ if (End != NULL)
+ {
+ *End = L'\\';
+ }
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ ObReferenceObjectByPointer(FoundObject,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
+ KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
+ if (End != NULL)
+ {
+ *End = L'\\';
+ *Path = End;
+ }
+ else
+ {
+ *Path = NULL;
+ }
+
+ *NextObject = FoundObject;
+
+ return STATUS_SUCCESS;
}
-VOID ObCreateEntry(PDIRECTORY_OBJECT parent,POBJECT_HEADER Object)
-/*
- * FUNCTION: Add an entry to a namespace directory
- * ARGUMENTS:
- * parent = directory to add in
- * name = Name to give the entry
- * Object = Header of the object to add the entry for
- */
+VOID
+INIT_FUNCTION
+ObInit(VOID)
{
- DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent,Object,Object->Name.Buffer,
- Object->Name.Buffer);
-
- /*
- * Insert ourselves in our parents list
- */
- InsertTailList(&parent->head,&Object->Entry);
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING Name;
+ SECURITY_DESCRIPTOR SecurityDescriptor;
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+
+ /* 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.OpenProcedure = ObpCreateDirectory;
+ ObjectTypeInitializer.ParseProcedure = ObpParseDirectory;
+ ObjectTypeInitializer.MaintainTypeList = FALSE;
+ ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DIRECTORY_OBJECT);
+ 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(DIRECTORY_OBJECT),
+ 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(DIRECTORY_OBJECT),
+ 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 */
+ ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObTypeObjectType), NULL);
+ ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObDirectoryType), NULL);
+
+ /* Create 'symbolic link' object type */
+ ObInitSymbolicLinkImplementation();
+
+ /* FIXME: Hack Hack! */
+ ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
+ RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
}
-NTSTATUS ObLookupObject(HANDLE rootdir,
- PWSTR string,
- PVOID* Object,
- PWSTR* UnparsedSection,
- ULONG Attributes)
-/*
- * FUNCTION: Lookup an object within the system namespc
- * ARGUMENTS:
- * root = Directory to start lookup from
- * _string = Pathname to lookup
- * RETURNS: On success a pointer to the object body
- * On failure NULL
- */
+NTSTATUS
+STDCALL
+ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
+ PUNICODE_STRING TypeName,
+ POBJECT_TYPE *ObjectType)
{
- PWSTR current;
- PWSTR next;
- PDIRECTORY_OBJECT current_dir = NULL;
- NTSTATUS Status;
-
- DPRINT("ObLookupObject(rootdir %x, string %x, string %w, Object %x, "
- "UnparsedSection %x)\n",rootdir,string,string,Object,
- UnparsedSection);
- *UnparsedSection = NULL;
- *Object = NULL;
-
- if (rootdir == NULL)
+ 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)),
+ &Header);
+ if (!NT_SUCCESS(Status))
{
- current_dir = HEADER_TO_BODY(&(namespc_root.hdr));
+ DPRINT1("ObpAllocateObject failed!\n");
+ return Status;
}
- else
+
+ LocalObjectType = (POBJECT_TYPE)&Header->Body;
+ DPRINT("Local ObjectType: %p Header: %p \n", LocalObjectType, Header);
+
+ /* Check if this is the first Object Type */
+ if (!ObTypeObjectType)
{
- ObReferenceObjectByHandle(rootdir,
- DIRECTORY_TRAVERSE,
- NULL,
- UserMode,
- (PVOID*)¤t_dir,
- NULL);
- }
-
- /*
- * Bit of a hack this
- */
- if (string[0] == 0)
+ 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)
{
- *Object = current_dir;
- return STATUS_SUCCESS;
+ /* Enable support */
+ LocalObjectType->TypeInfo.MaintainTypeList = TRUE;
}
- if (string[0] != '\\')
+ /* 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)
{
- DbgPrint("Non absolute pathname passed\n");
- return STATUS_UNSUCCESSFUL;
+ LocalObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderSize;
}
-
- next = string;
- current = next + 1;
-
- while (next != NULL &&
- BODY_TO_HEADER(current_dir)->ObjectType == ObDirectoryType)
+ else
{
- *next = '\\';
- current = next + 1;
- next = wcschr(next + 1,'\\');
- if (next != NULL)
- {
- *next = 0;
- }
-
- DPRINT("current %w current[5] %x next %x ", current, current[5], next);
- if (next != NULL)
- {
- DPRINT("(next+1) %w", next + 1);
- }
- DPRINT("\n",0);
-
- current_dir = (PDIRECTORY_OBJECT)ObDirLookup(current_dir,
- current,
- Attributes);
- if (current_dir == NULL)
- {
- DbgPrint("Path component %w not found\n", current);
- return STATUS_UNSUCCESSFUL;
- }
-
- if (BODY_TO_HEADER(current_dir)->ObjectType == IoSymbolicLinkType)
- {
- current_dir = IoOpenSymlink(current_dir);
- }
-
+ LocalObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderSize;
}
- DPRINT("next %x\n",next);
- DPRINT("current %x current %w\n",current,current);
- if (next == NULL)
+
+ /* All objects types need a security procedure */
+ if (!ObjectTypeInitializer->SecurityProcedure)
{
- if (current_dir == NULL)
- {
- Status = STATUS_UNSUCCESSFUL;
- }
- else
- {
- Status = STATUS_SUCCESS;
- }
+ LocalObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod;
}
- else
+
+ /* Select the Wait Object */
+ if (LocalObjectType->TypeInfo.UseDefaultObject)
{
- CHECKPOINT;
- *next = '\\';
- *UnparsedSection = next;
- if (BODY_TO_HEADER(current_dir)->ObjectType == IoDeviceType)
- {
- Status = STATUS_FS_QUERY_REQUIRED;
- }
- else if (BODY_TO_HEADER(current_dir)->ObjectType->Parse != NULL)
- {
- current_dir = BODY_TO_HEADER(current_dir)->ObjectType->
- Parse(current_dir,
- UnparsedSection);
- Status = (current_dir != NULL) ? STATUS_SUCCESS :
- STATUS_UNSUCCESSFUL;
- }
- else
- {
- Status = STATUS_UNSUCCESSFUL;
- }
+ /* Add the SYNCHRONIZE access mask since it's waitable */
+ LocalObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
+
+ /* Use the "Default Object", a simple event */
+ LocalObjectType->DefaultObject = &ObpDefaultObject;
}
- CHECKPOINT;
- *Object = current_dir;
- DPRINT("current_dir %x\n", current_dir);
-
- return Status;
-}
-
+ /* 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)
+ {
+ ObpAddEntryDirectory(ObpTypeDirectoryObject, Header, TypeName->Buffer);
+ ObReferenceObject(ObpTypeDirectoryObject);
+ }
+
+ *ObjectType = LocalObjectType;
+ return Status;
+}
+
+/* EOF */