-/*\r
- * COPYRIGHT: See COPYING in the top level directory\r
- * PROJECT: ReactOS kernel\r
- * FILE: ntoskrnl/ob/namespc.c\r
- * PURPOSE: Manages the system namespace\r
- * PROGRAMMER: David Welch (welch@mcmail.com)\r
- * UPDATE HISTORY:\r
- * 22/05/98: Created\r
- */\r
-\r
-/* INCLUDES ***************************************************************/\r
-\r
-#include <windows.h>\r
-#include <wstring.h>\r
-#include <ddk/ntddk.h>\r
-#include <internal/ob.h>\r
-#include <internal/io.h>\r
-#include <internal/string.h>\r
-\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-/* GLOBALS ****************************************************************/\r
-\r
-POBJECT_TYPE ObDirectoryType = NULL;\r
-\r
-static struct\r
-{\r
- OBJECT_HEADER hdr;\r
-// DIRECTORY_OBJECT directory;\r
- LIST_ENTRY head;\r
- KSPIN_LOCK Lock;\r
-} namespc_root = {{0,},};\r
-\r
-/* FUNCTIONS **************************************************************/\r
-\r
-NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle,\r
- ACCESS_MASK DesiredAccess,\r
- POBJECT_ATTRIBUTES ObjectAttributes)\r
-{\r
- return(ZwOpenDirectoryObject(DirectoryHandle,\r
- DesiredAccess,\r
- ObjectAttributes));\r
-}\r
-\r
-NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle,\r
- ACCESS_MASK DesiredAccess,\r
- POBJECT_ATTRIBUTES ObjectAttributes)\r
-/*\r
- * FUNCTION: Opens a namespace directory object\r
- * ARGUMENTS:\r
- * DirectoryHandle (OUT) = Variable which receives the directory handle\r
- * DesiredAccess = Desired access to the directory\r
- * ObjectAttributes = Structure describing the directory\r
- * RETURNS: Status\r
- * NOTES: Undocumented\r
- */\r
-{\r
- PVOID Object;\r
- NTSTATUS Status;\r
- PWSTR Ignored;\r
- \r
- *DirectoryHandle = 0;\r
- \r
- Status = ObOpenObjectByName(ObjectAttributes,&Object,&Ignored);\r
- if (!NT_SUCCESS(Status))\r
- {\r
- return(Status);\r
- }\r
- \r
- if (BODY_TO_HEADER(Object)->Type!=OBJTYP_DIRECTORY)\r
- { \r
- return(STATUS_UNSUCCESSFUL);\r
- }\r
- \r
- *DirectoryHandle = ObInsertHandle(KeGetCurrentProcess(),Object,\r
- DesiredAccess,FALSE);\r
- CHECKPOINT;\r
- return(STATUS_SUCCESS);\r
-}\r
-\r
-NTSTATUS NtQueryDirectoryObject(IN HANDLE DirObjHandle,\r
- OUT POBJDIR_INFORMATION DirObjInformation, \r
- IN ULONG BufferLength, \r
- IN BOOLEAN GetNextIndex, \r
- IN BOOLEAN IgnoreInputIndex, \r
- IN OUT PULONG ObjectIndex,\r
- OUT PULONG DataWritten OPTIONAL)\r
-{\r
- return(ZwQueryDirectoryObject(DirObjHandle,\r
- DirObjInformation,\r
- BufferLength,\r
- GetNextIndex,\r
- IgnoreInputIndex,\r
- ObjectIndex,\r
- DataWritten));\r
-}\r
-\r
-NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle,\r
- OUT POBJDIR_INFORMATION DirObjInformation, \r
- IN ULONG BufferLength, \r
- IN BOOLEAN GetNextIndex, \r
- IN BOOLEAN IgnoreInputIndex, \r
- IN OUT PULONG ObjectIndex,\r
- OUT PULONG DataWritten OPTIONAL)\r
-/*\r
- * FUNCTION: Reads information from a namespace directory\r
- * ARGUMENTS:\r
- * DirObjInformation (OUT) = Buffer to hold the data read\r
- * BufferLength = Size of the buffer in bytes\r
- * GetNextIndex = If TRUE then set ObjectIndex to the index of the\r
- * next object\r
- * If FALSE then set ObjectIndex to the number of\r
- * objects in the directory\r
- * IgnoreInputIndex = If TRUE start reading at index 0\r
- * If FALSE start reading at the index specified\r
- * by object index\r
- * ObjectIndex = Zero based index into the directory, interpretation\r
- * depends on IgnoreInputIndex and GetNextIndex\r
- * DataWritten (OUT) = Caller supplied storage for the number of bytes\r
- * written (or NULL)\r
- * RETURNS: Status\r
- */\r
-{\r
- PDIRECTORY_OBJECT dir = NULL;\r
- ULONG EntriesToRead;\r
- PLIST_ENTRY current_entry;\r
- POBJECT_HEADER current;\r
- ULONG i=0;\r
- ULONG EntriesToSkip;\r
- NTSTATUS Status;\r
- \r
- DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle);\r
- DPRINT("dir %x namespc_root %x\n",dir,HEADER_TO_BODY(&(namespc_root.hdr)));\r
- \r
-// assert_irql(PASSIVE_LEVEL);\r
- \r
- Status = ObReferenceObjectByHandle(DirObjHandle,\r
- DIRECTORY_QUERY,\r
- ObDirectoryType,\r
- UserMode,\r
- (PVOID*)&dir,\r
- NULL);\r
- if (Status != STATUS_SUCCESS)\r
- {\r
- return(Status);\r
- }\r
- \r
- EntriesToRead = BufferLength / sizeof(OBJDIR_INFORMATION);\r
- *DataWritten = 0;\r
- \r
- DPRINT("EntriesToRead %d\n",EntriesToRead);\r
- \r
- current_entry = dir->head.Flink;\r
- \r
- /*\r
- * Optionally, skip over some entries at the start of the directory\r
- */\r
- if (!IgnoreInputIndex)\r
- {\r
- CHECKPOINT;\r
- \r
- EntriesToSkip = *ObjectIndex;\r
- while ( i<EntriesToSkip && current_entry!=NULL)\r
- {\r
- current_entry = current_entry->Flink;\r
- }\r
- }\r
- \r
- DPRINT("DirObjInformation %x\n",DirObjInformation);\r
- \r
- /*\r
- * Read the maximum entries possible into the buffer\r
- */\r
- while ( i<EntriesToRead && current_entry!=(&(dir->head)))\r
- {\r
- current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,Entry);\r
- DPRINT("Scanning %w\n",current->Name.Buffer);\r
- DirObjInformation[i].ObjectName.Buffer = \r
- ExAllocatePool(NonPagedPool,(current->Name.Length+1)*2);\r
- DirObjInformation[i].ObjectName.Length = current->Name.Length;\r
- DirObjInformation[i].ObjectName.MaximumLength = current->Name.Length;\r
- DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n",\r
- DirObjInformation[i].ObjectName.Buffer);\r
- RtlCopyUnicodeString(&DirObjInformation[i].ObjectName,\r
- &(current->Name));\r
- i++;\r
- current_entry = current_entry->Flink;\r
- (*DataWritten) = (*DataWritten) + sizeof(OBJDIR_INFORMATION);\r
- CHECKPOINT;\r
- }\r
- CHECKPOINT;\r
- \r
- /*\r
- * Optionally, count the number of entries in the directory\r
- */\r
- if (GetNextIndex)\r
- {\r
- *ObjectIndex=i;\r
- }\r
- else\r
- {\r
- while ( current_entry!=(&(dir->head)) )\r
- {\r
- current_entry=current_entry->Flink;\r
- i++;\r
- }\r
- *ObjectIndex=i;\r
- }\r
- return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-NTSTATUS ObReferenceObjectByName(PUNICODE_STRING ObjectPath,\r
- ULONG Attributes,\r
- PACCESS_STATE PassedAccessState,\r
- ACCESS_MASK DesiredAccess,\r
- POBJECT_TYPE ObjectType,\r
- KPROCESSOR_MODE AccessMode,\r
- PVOID ParseContext,\r
- PVOID* ObjectPtr)\r
-{\r
- UNIMPLEMENTED;\r
-}\r
-\r
-NTSTATUS ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes,\r
- PVOID* Object, PWSTR* UnparsedSection)\r
-{\r
- NTSTATUS Status;\r
- \r
- DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n",\r
- ObjectAttributes,Object);\r
- DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n",\r
- ObjectAttributes->ObjectName,ObjectAttributes->ObjectName->Buffer);\r
- DPRINT("ObjectAttributes->ObjectName->Length %d\n",\r
- ObjectAttributes->ObjectName->Length);\r
- \r
- *Object = NULL;\r
- Status = ObLookupObject(ObjectAttributes->RootDirectory, \r
- ObjectAttributes->ObjectName->Buffer, \r
- Object,\r
- UnparsedSection,\r
- ObjectAttributes->Attributes);\r
- DPRINT("*Object %x\n",*Object);\r
- DPRINT("ObjectAttributes->ObjectName->Length %d\n",\r
- ObjectAttributes->ObjectName->Length);\r
- return(Status);\r
-}\r
-\r
-void ObInit(void)\r
-/*\r
- * FUNCTION: Initialize the object manager namespace\r
- */\r
-{\r
- ANSI_STRING AnsiString;\r
- \r
- ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));\r
- \r
- ObDirectoryType->TotalObjects = 0;\r
- ObDirectoryType->TotalHandles = 0;\r
- ObDirectoryType->MaxObjects = ULONG_MAX;\r
- ObDirectoryType->MaxHandles = ULONG_MAX;\r
- ObDirectoryType->PagedPoolCharge = 0;\r
- ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);\r
- ObDirectoryType->Dump = NULL;\r
- ObDirectoryType->Open = NULL;\r
- ObDirectoryType->Close = NULL;\r
- ObDirectoryType->Delete = NULL;\r
- ObDirectoryType->Parse = NULL;\r
- ObDirectoryType->Security = NULL;\r
- ObDirectoryType->QueryName = NULL;\r
- ObDirectoryType->OkayToClose = NULL;\r
- \r
- RtlInitAnsiString(&AnsiString,"Directory");\r
- RtlAnsiStringToUnicodeString(&ObDirectoryType->TypeName,\r
- &AnsiString,TRUE);\r
- \r
- ObInitializeObjectHeader(ObDirectoryType,NULL,&namespc_root.hdr);\r
- InitializeListHead(&namespc_root.head);\r
-}\r
-\r
-NTSTATUS NtCreateDirectoryObject(PHANDLE DirectoryHandle,\r
- ACCESS_MASK DesiredAccess,\r
- POBJECT_ATTRIBUTES ObjectAttributes)\r
-{\r
- return(ZwCreateDirectoryObject(DirectoryHandle,\r
- DesiredAccess,\r
- ObjectAttributes));\r
-}\r
-\r
-NTSTATUS ZwCreateDirectoryObject(PHANDLE DirectoryHandle,\r
- ACCESS_MASK DesiredAccess,\r
- POBJECT_ATTRIBUTES ObjectAttributes)\r
-/*\r
- * FUNCTION: Creates or opens a directory object (a container for other\r
- * objects)\r
- * ARGUMENTS:\r
- * DirectoryHandle (OUT) = Caller supplied storage for the handle\r
- * of the directory\r
- * DesiredAccess = Access desired to the directory\r
- * ObjectAttributes = Object attributes initialized with\r
- * InitializeObjectAttributes\r
- * RETURNS: Status\r
- */\r
-{\r
- PDIRECTORY_OBJECT dir;\r
- \r
- dir = ObGenericCreateObject(DirectoryHandle,DesiredAccess,ObjectAttributes,\r
- ObDirectoryType);\r
- \r
- /*\r
- * Initialize the object body\r
- */\r
- InitializeListHead(&dir->head);\r
- KeInitializeSpinLock(&(dir->Lock));\r
- \r
- return(STATUS_SUCCESS);\r
-}\r
-\r
-VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes,\r
- PUNICODE_STRING ObjectName,\r
- ULONG Attributes,\r
- HANDLE RootDirectory,\r
- PSECURITY_DESCRIPTOR SecurityDescriptor)\r
-/*\r
- * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a \r
- * subsequent call to ZwCreateXXX or ZwOpenXXX\r
- * ARGUMENTS:\r
- * InitializedAttributes (OUT) = Caller supplied storage for the\r
- * object attributes\r
- * ObjectName = Full path name for object\r
- * Attributes = Attributes for the object\r
- * RootDirectory = Where the object should be placed or NULL\r
- * SecurityDescriptor = Ignored\r
- * \r
- * NOTE:\r
- * Either ObjectName is a fully qualified pathname or a path relative\r
- * to RootDirectory\r
- */\r
-{\r
- DPRINT("InitializeObjectAttributes(InitializedAttributes %x "\r
- "ObjectName %x Attributes %x RootDirectory %x)\n",\r
- InitializedAttributes,ObjectName,Attributes,RootDirectory);\r
- InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES);\r
- InitializedAttributes->RootDirectory=RootDirectory;\r
- InitializedAttributes->ObjectName=ObjectName;\r
- InitializedAttributes->Attributes=Attributes;\r
- InitializedAttributes->SecurityDescriptor=SecurityDescriptor;\r
- InitializedAttributes->SecurityQualityOfService=NULL;\r
-}\r
-\r
-static PVOID ObDirLookup(PDIRECTORY_OBJECT dir, PWSTR name,\r
- ULONG Attributes)\r
-/*\r
- * FUNCTION: Looks up an entry within a namespace directory\r
- * ARGUMENTS:\r
- * dir = Directory to lookup in\r
- * name = Entry name to find\r
- * RETURNS: A pointer to the object body if found\r
- * NULL otherwise\r
- */\r
-{\r
- LIST_ENTRY* current = dir->head.Flink;\r
- POBJECT_HEADER current_obj;\r
- \r
- DPRINT("ObDirLookup(dir %x, name %w)\n",dir,name);\r
- \r
- if (name[0]==0)\r
- {\r
- return(dir);\r
- }\r
- if (name[0]=='.'&&name[1]==0)\r
- {\r
- return(dir);\r
- }\r
- if (name[0]=='.'&&name[1]=='.'&&name[2]==0)\r
- {\r
- return(BODY_TO_HEADER(dir)->Parent);\r
- }\r
- while (current!=(&(dir->head)))\r
- {\r
- current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);\r
- DPRINT("Scanning %w\n",current_obj->Name.Buffer);\r
- if (Attributes & OBJ_CASE_INSENSITIVE)\r
- {\r
- if (wcsicmp(current_obj->Name.Buffer, name)==0)\r
- {\r
- DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));\r
- return(HEADER_TO_BODY(current_obj));\r
- }\r
- }\r
- else\r
- {\r
- if ( wcscmp(current_obj->Name.Buffer, name)==0)\r
- {\r
- DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));\r
- return(HEADER_TO_BODY(current_obj));\r
- }\r
- }\r
- current = current->Flink;\r
- }\r
- DPRINT("%s() = NULL\n",__FUNCTION__);\r
- return(NULL);\r
-}\r
-\r
-VOID ObRemoveEntry(POBJECT_HEADER Header)\r
-{\r
- KIRQL oldlvl;\r
- \r
- DPRINT("ObRemoveEntry(Header %x)\n",Header);\r
- \r
- KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);\r
- RemoveEntryList(&(Header->Entry));\r
- KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);\r
-}\r
-\r
-VOID ObCreateEntry(PDIRECTORY_OBJECT parent,POBJECT_HEADER Object)\r
-/*\r
- * FUNCTION: Add an entry to a namespace directory\r
- * ARGUMENTS:\r
- * parent = directory to add in\r
- * name = Name to give the entry\r
- * Object = Header of the object to add the entry for\r
- */\r
-{\r
- DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent,Object,Object->Name.Buffer,\r
- Object->Name.Buffer);\r
- \r
- /*\r
- * Insert ourselves in our parents list\r
- */\r
- InsertTailList(&parent->head,&Object->Entry);\r
-}\r
-\r
-NTSTATUS ObLookupObject(HANDLE rootdir, PWSTR string, PVOID* Object,\r
- PWSTR* UnparsedSection, ULONG Attributes)\r
-/*\r
- * FUNCTION: Lookup an object within the system namespc\r
- * ARGUMENTS:\r
- * root = Directory to start lookup from\r
- * _string = Pathname to lookup\r
- * RETURNS: On success a pointer to the object body\r
- * On failure NULL\r
- */\r
-{\r
- PWSTR current;\r
- PWSTR next;\r
- PDIRECTORY_OBJECT current_dir = NULL;\r
- NTSTATUS Status;\r
- \r
- DPRINT("ObLookupObject(rootdir %x, string %x, string %w, Object %x, "\r
- "UnparsedSection %x)\n",rootdir,string,string,Object,\r
- UnparsedSection);\r
- \r
- \r
- *UnparsedSection = NULL;\r
- *Object = NULL;\r
- \r
- if (rootdir==NULL)\r
- {\r
- current_dir = HEADER_TO_BODY(&(namespc_root.hdr));\r
- }\r
- else\r
- {\r
- ObReferenceObjectByHandle(rootdir,DIRECTORY_TRAVERSE,NULL,\r
- UserMode,(PVOID*)¤t_dir,NULL);\r
- }\r
- \r
- /*\r
- * Bit of a hack this\r
- */\r
- if (string[0]==0)\r
- {\r
- *Object=current_dir;\r
- return(STATUS_SUCCESS);\r
- }\r
-\r
- if (string[0]!='\\')\r
- {\r
- DbgPrint("(%s:%d) Non absolute pathname passed to %s\n",__FILE__,\r
- __LINE__,__FUNCTION__);\r
- return(STATUS_UNSUCCESSFUL);\r
- }\r
- \r
- next = &string[0];\r
- current = next+1;\r
- \r
- while (next!=NULL && \r
- BODY_TO_HEADER(current_dir)->ObjectType==ObDirectoryType)\r
- { \r
- *next = '\\';\r
- current = next+1;\r
- next = wcschr(next+1,'\\');\r
- if (next!=NULL)\r
- {\r
- *next=0;\r
- }\r
-\r
- DPRINT("current %w current[5] %x next %x ",current,current[5],next);\r
- if (next!=NULL)\r
- {\r
- DPRINT("(next+1) %w",next+1);\r
- }\r
- DPRINT("\n",0);\r
- \r
- current_dir=(PDIRECTORY_OBJECT)ObDirLookup(current_dir,current,\r
- Attributes);\r
- if (current_dir==NULL)\r
- {\r
- DbgPrint("(%s:%d) Path component %w not found\n",__FILE__,\r
- __LINE__,current);\r
- return(STATUS_UNSUCCESSFUL); \r
- }\r
- \r
- if (BODY_TO_HEADER(current_dir)->ObjectType==IoSymbolicLinkType)\r
- {\r
- current_dir = IoOpenSymlink(current_dir); \r
- }\r
- \r
- }\r
- DPRINT("next %x\n",next);\r
- DPRINT("current %x current %w\n",current,current);\r
- if (next==NULL)\r
- {\r
- if (current_dir==NULL)\r
- {\r
- Status = STATUS_UNSUCCESSFUL;\r
- }\r
- else\r
- {\r
- Status = STATUS_SUCCESS;\r
- }\r
- }\r
- else\r
- {\r
- CHECKPOINT;\r
- *next = '\\';\r
- *UnparsedSection = next;\r
- if (BODY_TO_HEADER(current_dir)->ObjectType == IoDeviceType)\r
- {\r
- Status = STATUS_FS_QUERY_REQUIRED;\r
- }\r
- else\r
- {\r
- Status = STATUS_UNSUCCESSFUL;\r
- } \r
- }\r
- CHECKPOINT;\r
- *Object = current_dir;\r
- DPRINT("(%s:%d) current_dir %x\n",__FILE__,__LINE__,current_dir);\r
-\r
- return(Status);\r
-}\r
- \r
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/ob/namespc.c
+ * PURPOSE: Manages the system namespace
+ *
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+
+/* GLOBALS ****************************************************************/
+
+POBJECT_TYPE ObDirectoryType = NULL;
+POBJECT_TYPE ObTypeObjectType = NULL;
+
+PDIRECTORY_OBJECT NameSpaceRoot = NULL;
+ /* FIXME: Move this somewhere else once devicemap support is in */
+PDEVICE_MAP ObSystemDeviceMap = 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 **************************************************************/
+
+/*
+ * @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;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ ObjectPath,
+ Attributes | OBJ_OPENIF,
+ 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_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;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("ObOpenObjectByName(...)\n");
+
+ Status = ObFindObject(ObjectAttributes,
+ &Object,
+ &RemainingPath,
+ ObjectType);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObFindObject() failed (Status %lx)\n", 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
+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
+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;
+
+ RtlpCreateUnicodeString(&Header->Name, Name, NonPagedPool);
+ 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 for: %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(" Not Found: %s() = NULL\n",__FUNCTION__);
+ return(NULL);
+}
+
+
+NTSTATUS STDCALL
+ObpParseDirectory(PVOID Object,
+ PVOID * NextObject,
+ PUNICODE_STRING FullPath,
+ PWSTR * Path,
+ ULONG Attributes)
+{
+ PWSTR Start;
+ PWSTR End;
+ PVOID FoundObject;
+
+ 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;
+ }
+
+ FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
+ if (FoundObject == NULL)
+ {
+ if (End != NULL)
+ {
+ *End = L'\\';
+ }
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ ObReferenceObjectByPointer(FoundObject,
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
+
+ if (End != NULL)
+ {
+ *End = L'\\';
+ *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 INIT_FUNCTION
+ObInit(VOID)
+/*
+ * FUNCTION: Initialize the object manager namespace
+ */
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING Name;
+ SECURITY_DESCRIPTOR SecurityDescriptor;
+
+ /* Initialize the security descriptor cache */
+ ObpInitSdCache();
+
+ /* create 'directory' object type */
+ ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
+
+ ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
+ ObDirectoryType->TotalObjects = 0;
+ ObDirectoryType->TotalHandles = 0;
+ ObDirectoryType->PeakObjects = 0;
+ ObDirectoryType->PeakHandles = 0;
+ 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->PeakObjects = 0;
+ ObTypeObjectType->PeakHandles = 0;
+ 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 security descriptor */
+ RtlCreateSecurityDescriptor(&SecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION1);
+
+ RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
+ SeAliasAdminsSid,
+ FALSE);
+
+ RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
+ SeLocalSystemSid,
+ FALSE);
+
+ RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
+ TRUE,
+ SePublicDefaultDacl,
+ FALSE);
+
+ /* Create root directory */
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ NULL,
+ &SecurityDescriptor);
+ ObCreateObject(KernelMode,
+ ObDirectoryType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(DIRECTORY_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&NameSpaceRoot);
+
+ /* Create '\ObjectTypes' directory */
+ RtlRosInitUnicodeStringFromLiteral(&Name,
+ L"\\ObjectTypes");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_PERMANENT,
+ NULL,
+ &SecurityDescriptor);
+ ObCreateObject(KernelMode,
+ ObDirectoryType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(DIRECTORY_OBJECT),
+ 0,
+ 0,
+ NULL);
+
+ ObpCreateTypeObject(ObDirectoryType);
+ ObpCreateTypeObject(ObTypeObjectType);
+
+ /* Create 'symbolic link' object type */
+ ObInitSymbolicLinkImplementation();
+
+ /* FIXME: Hack Hack! */
+ ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
+ RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
+}
+
+
+NTSTATUS
+ObpCreateTypeObject(POBJECT_TYPE ObjectType)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ WCHAR NameString[120];
+ PTYPE_OBJECT TypeObject = NULL;
+ UNICODE_STRING Name;
+ NTSTATUS Status;
+
+ DPRINT("ObpCreateTypeObject(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(KernelMode,
+ ObTypeObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(TYPE_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&TypeObject);
+ if (NT_SUCCESS(Status))
+ {
+ TypeObject->ObjectType = ObjectType;
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+/* EOF */