Implement core Object Manager subsystem
This commit is contained in:
@@ -89,6 +89,13 @@ list(APPEND XTOSKRNL_SOURCE
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/probe.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/pte.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/mm/quota.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/data.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/devmap.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/lifecycl.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/obdir.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/obmgr.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/security.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ob/typereg.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/po/idle.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ps/data.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/ps/process.cc
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
#define TAG_MM_OVERFLOW SIGNATURE32('O', 'V', 'F', 'L')
|
||||
#define TAG_MM_MEMORY_POOL SIGNATURE32('P', 'O', 'O', 'L')
|
||||
#define TAG_MM_NONE SIGNATURE32('N', 'O', 'N', 'E')
|
||||
#define TAG_OB_CREATE_INFO SIGNATURE32('O', 'B', 'C', 'I')
|
||||
#define TAG_OB_DIRECTORY SIGNATURE32('O', 'B', 'D', 'I')
|
||||
#define TAG_OB_MEMORY_POOL SIGNATURE32('O', 'B', 'J', 'M')
|
||||
#define TAG_OB_NAME SIGNATURE32('O', 'B', 'N', 'M')
|
||||
#define TAG_OB_OBJECT_TYPE SIGNATURE32('O', 'B', 'J', 'T')
|
||||
#define TAG_PS_QUOTA_BLOCK SIGNATURE32('P', 'S', 'Q', 'B')
|
||||
#define TAG_SE_DESCRIPTOR SIGNATURE32('S', 'E', 'S', 'D')
|
||||
|
||||
|
||||
22
xtoskrnl/includes/ob.hh
Normal file
22
xtoskrnl/includes/ob.hh
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob.hh
|
||||
* DESCRIPTION: Object Manager
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_HH
|
||||
#define __XTOSKRNL_OB_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
#include <ob/devmap.hh>
|
||||
#include <ob/lifecycl.hh>
|
||||
#include <ob/obdir.hh>
|
||||
#include <ob/obmgr.hh>
|
||||
#include <ob/security.hh>
|
||||
#include <ob/typereg.hh>
|
||||
|
||||
|
||||
#endif /* __XTOSKRNL_OB_HH */
|
||||
31
xtoskrnl/includes/ob/devmap.hh
Normal file
31
xtoskrnl/includes/ob/devmap.hh
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob/devmap.hh
|
||||
* DESCRIPTION: Object Manager Device Map
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_DEVMAP_HH
|
||||
#define __XTOSKRNL_OB_DEVMAP_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Object Manager */
|
||||
namespace OB
|
||||
{
|
||||
class DeviceMap
|
||||
{
|
||||
private:
|
||||
STATIC KPUSH_LOCK DeviceMapLock;
|
||||
STATIC BOOLEAN UniqueDeviceMaps;
|
||||
|
||||
public:
|
||||
STATIC XTAPI POBJECT_DIRECTORY GetGlobalDevicesDirectory(IN POBJECT_DIRECTORY Directory);
|
||||
STATIC XTAPI BOOLEAN GetUniqueDeviceMaps(VOID);
|
||||
STATIC XTAPI XTSTATUS InitializeDeviceMap(VOID);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_OB_DEVMAP_HH */
|
||||
86
xtoskrnl/includes/ob/lifecycl.hh
Normal file
86
xtoskrnl/includes/ob/lifecycl.hh
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob/lifecycl.hh
|
||||
* DESCRIPTION: Object Manager Lifecycle Management
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_LIFECYCL_HH
|
||||
#define __XTOSKRNL_OB_LIFECYCL_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Object Manager */
|
||||
namespace OB
|
||||
{
|
||||
class LifeCycle
|
||||
{
|
||||
private:
|
||||
STATIC PVOID RemoveObjectList;
|
||||
STATIC WORK_QUEUE_ITEM RemoveObjectWorkItem;
|
||||
|
||||
public:
|
||||
STATIC XTAPI XTSTATUS AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo,
|
||||
IN KPROCESSOR_MODE OwnerProcessorMode,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN PUNICODE_STRING ObjectName,
|
||||
IN ULONG ObjectBodySize,
|
||||
OUT POBJECT_HEADER *ReturnedObjectHeader);
|
||||
STATIC XTAPI VOID DeferObjectDeletion(IN POBJECT_HEADER ObjectHeader);
|
||||
STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object);
|
||||
STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object,
|
||||
IN ULONG Count);
|
||||
STATIC XTFASTCALL LONG_PTR DereferenceObjectDeferDelete(IN PVOID Object);
|
||||
STATIC XTFASTCALL VOID DereferenceObjectNameInformation(IN POBJECT_HEADER_NAME_INFO NameInfo);
|
||||
STATIC XTFASTCALL POBJECT_HEADER_CREATOR_INFO GetObjectCreatorInformation(IN POBJECT_HEADER Header);
|
||||
STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO GetObjectNameInformation(IN POBJECT_HEADER Header);
|
||||
STATIC XTAPI VOID InitializeObjectLifeCycle(VOID);
|
||||
STATIC XTFASTCALL LONG_PTR ReferenceObject(IN PVOID Object);
|
||||
STATIC XTFASTCALL LONG_PTR ReferenceObject(IN PVOID Object,
|
||||
IN ULONG Count);
|
||||
STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO ReferenceObjectNameInformation(IN POBJECT_HEADER ObjectHeader);
|
||||
|
||||
private:
|
||||
STATIC XTFASTCALL PWCH AllocateObjectName(IN ULONG Length,
|
||||
IN BOOLEAN UseLookaside,
|
||||
IN OUT PUNICODE_STRING ObjectName);
|
||||
STATIC XTAPI VOID CalculateOptionalHeaderSize(IN POBJECT_CREATE_INFORMATION CreateInfo,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN PUNICODE_STRING ObjectName,
|
||||
OUT POBJECT_OPTIONAL_HEADER_LAYOUT Layout);
|
||||
STATIC XTAPI XTSTATUS CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
|
||||
IN KPROCESSOR_MODE ProcessorMode,
|
||||
IN KPROCESSOR_MODE OwnerProcessorMode,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN OUT PUNICODE_STRING CapturedObjectName,
|
||||
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||
IN BOOLEAN UseLookaside);
|
||||
STATIC XTAPI XTSTATUS CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
|
||||
IN PUNICODE_STRING ObjectName,
|
||||
IN OUT PUNICODE_STRING CapturedObjectName,
|
||||
IN BOOLEAN UseLookaside);
|
||||
STATIC XTAPI XTSTATUS CreateObject(IN KPROCESSOR_MODE ProcessorMode,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN KPROCESSOR_MODE OwnerProcessorMode,
|
||||
IN OUT PVOID ParseContext,
|
||||
IN ULONG ObjectBodySize,
|
||||
IN ULONG PagedPoolCharge,
|
||||
IN ULONG NonPagedPoolCharge,
|
||||
OUT PVOID *Object);
|
||||
STATIC XTAPI VOID DeleteObject(IN PVOID Object,
|
||||
IN BOOLEAN CalledOnWorkerThread);
|
||||
STATIC XTAPI VOID FreeObject(IN PVOID Object);
|
||||
STATIC XTFASTCALL VOID FreeObjectCreateInformation(IN POBJECT_CREATE_INFORMATION CreateInfo);
|
||||
STATIC XTFASTCALL VOID FreeObjectName(IN OUT PUNICODE_STRING ObjectName);
|
||||
STATIC XTAPI PVOID GetObjectAllocationBase(IN POBJECT_HEADER ObjectHeader);
|
||||
STATIC XTAPI VOID ProcessDeferredDeletionQueue(IN PVOID Parameter);
|
||||
STATIC XTFASTCALL VOID ReleaseObjectCreateInformation(IN POBJECT_CREATE_INFORMATION CreateInfo);
|
||||
STATIC XTAPI VOID ReturnObjectQuota(IN POBJECT_HEADER ObjectHeader,
|
||||
IN POBJECT_TYPE ObjectType);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_OB_LIFECYCL_HH */
|
||||
53
xtoskrnl/includes/ob/obdir.hh
Normal file
53
xtoskrnl/includes/ob/obdir.hh
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob/obdir.hh
|
||||
* DESCRIPTION: Object Manager Security API
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_OBDIR_HH
|
||||
#define __XTOSKRNL_OB_OBDIR_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Object Manager */
|
||||
namespace OB
|
||||
{
|
||||
class Directory
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI BOOLEAN DeleteDirectoryEntry(IN POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTFASTCALL VOID InitializeLookupContext(OUT POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTAPI BOOLEAN InsertDirectoryEntry(IN OUT POBJECT_DIRECTORY Directory,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext,
|
||||
IN OUT POBJECT_HEADER ObjectHeader);
|
||||
STATIC XTFASTCALL VOID LockLookupContext(IN POBJECT_DIRECTORY Directory,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
|
||||
STATIC XTAPI PVOID LookupDirectoryEntry(IN POBJECT_DIRECTORY Directory,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN ULONG Attributes,
|
||||
IN BOOLEAN SearchGlobalDirectory,
|
||||
OUT POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTFASTCALL VOID ReleaseLookupContext(IN OUT POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
|
||||
private:
|
||||
STATIC XTFASTCALL VOID AcquireExclusiveDirectoryLock(IN OUT POBJECT_DIRECTORY Directory,
|
||||
IN OUT POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTFASTCALL VOID AcquireSharedDirectoryLock(IN POBJECT_DIRECTORY Directory,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTFASTCALL ULONG ComputeObjectNameHash(IN PCUNICODE_STRING Name);
|
||||
STATIC XTFASTCALL VOID ReleaseDirectoryLock(IN OUT POBJECT_DIRECTORY Directory,
|
||||
IN OUT POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTFASTCALL VOID ReleaseLookupContextObject(IN OUT POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
STATIC XTFASTCALL PVOID SearchDirectory(IN POBJECT_DIRECTORY Directory,
|
||||
IN PCUNICODE_STRING Name,
|
||||
IN BOOLEAN CaseInsensitive,
|
||||
IN ULONG HashIndex,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_OB_OBDIR_HH */
|
||||
30
xtoskrnl/includes/ob/obmgr.hh
Normal file
30
xtoskrnl/includes/ob/obmgr.hh
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob/obmgr.hh
|
||||
* DESCRIPTION: Object Manager
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_OBMGR_HH
|
||||
#define __XTOSKRNL_OB_OBMGR_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Object Manager */
|
||||
namespace OB
|
||||
{
|
||||
class Manager
|
||||
{
|
||||
private:
|
||||
STATIC GENERAL_LOOKASIDE CreateInfoList;
|
||||
STATIC GENERAL_LOOKASIDE NameBufferList;
|
||||
|
||||
public:
|
||||
STATIC XTAPI XTSTATUS InitializeObjectManager(VOID);
|
||||
STATIC XTAPI VOID InitializeSystemLookasideList(VOID);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_OB_OBMGR_HH */
|
||||
32
xtoskrnl/includes/ob/security.hh
Normal file
32
xtoskrnl/includes/ob/security.hh
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob/security.hh
|
||||
* DESCRIPTION: Object Manager Security API
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_SECURITY_HH
|
||||
#define __XTOSKRNL_OB_SECURITY_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Object Manager */
|
||||
namespace OB
|
||||
{
|
||||
class Security
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI XTSTATUS ProcessObjectSecurityDescriptor(IN PVOID Object,
|
||||
IN SECURITY_OPERATION_CODE OperationCode,
|
||||
IN PSECURITY_INFORMATION SecurityInformation,
|
||||
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN OUT PULONG Length,
|
||||
IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
|
||||
IN MMPOOL_TYPE PoolType,
|
||||
IN PGENERIC_MAPPING GenericMapping);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_OB_SECURITY_HH */
|
||||
44
xtoskrnl/includes/ob/typereg.hh
Normal file
44
xtoskrnl/includes/ob/typereg.hh
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/includes/ob/typereg.hh
|
||||
* DESCRIPTION: Object Manager Type Registry
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTOSKRNL_OB_TYPEREG_HH
|
||||
#define __XTOSKRNL_OB_TYPEREG_HH
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Object Manager */
|
||||
namespace OB
|
||||
{
|
||||
class TypeRegistry
|
||||
{
|
||||
private:
|
||||
STATIC KEVENT DefaultEvent;
|
||||
STATIC POBJECT_TYPE MasterObjectType;
|
||||
STATIC POBJECT_DIRECTORY ObjectTypeDirectory;
|
||||
STATIC POBJECT_TYPE ObjectTypesTable[OBJECT_MAX_DEFINED_OBJECT_TYPES];
|
||||
|
||||
public:
|
||||
STATIC XTAPI XTSTATUS CreateObjectType(IN PUNICODE_STRING TypeName,
|
||||
IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
OUT POBJECT_TYPE *ObjectType);
|
||||
STATIC XTAPI VOID DeleteObjectType(IN PVOID Object);
|
||||
STATIC XTAPI XTSTATUS InitializeObjectTypeRegistry(VOID);
|
||||
|
||||
private:
|
||||
STATIC XTAPI ULONG GenerateObjectPoolTag(IN PUNICODE_STRING TypeName);
|
||||
STATIC XTAPI VOID InitializeObjectType(IN OUT POBJECT_TYPE ObjectType,
|
||||
IN POBJECT_TYPE_INITIALIZER Initializer,
|
||||
IN PUNICODE_STRING ObjectName);
|
||||
STATIC XTAPI XTSTATUS ValidateObjectTypeParameters(IN PUNICODE_STRING TypeName,
|
||||
IN POBJECT_TYPE_INITIALIZER Initializer);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTOSKRNL_OB_TYPEREG_HH */
|
||||
40
xtoskrnl/ob/data.cc
Normal file
40
xtoskrnl/ob/data.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/ob/data.cc
|
||||
* DESCRIPTION: Object Manager global and static data
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* Synchronizes shared read and exclusive write access to system device map structures */
|
||||
KPUSH_LOCK OB::DeviceMap::DeviceMapLock;
|
||||
|
||||
/* Indicates whether the system employs unique device maps */
|
||||
BOOLEAN OB::DeviceMap::UniqueDeviceMaps;
|
||||
|
||||
/* System work queue item responsible for scheduling the deferred object deletion */
|
||||
WORK_QUEUE_ITEM OB::LifeCycle::RemoveObjectWorkItem;
|
||||
|
||||
/* Default kernel event utilized by the Object Manager */
|
||||
KEVENT OB::TypeRegistry::DefaultEvent;
|
||||
|
||||
/* Fundamental Type object type */
|
||||
POBJECT_TYPE OB::TypeRegistry::MasterObjectType;
|
||||
|
||||
/* Points to the Object Types directory */
|
||||
POBJECT_DIRECTORY OB::TypeRegistry::ObjectTypeDirectory;
|
||||
|
||||
/* Index-based lookup for all registered object types */
|
||||
POBJECT_TYPE OB::TypeRegistry::ObjectTypesTable[OBJECT_MAX_DEFINED_OBJECT_TYPES];
|
||||
|
||||
/* General lookaside list used for allocation and deallocation of OBJECT_CREATE_INFORMATION structures */
|
||||
GENERAL_LOOKASIDE OB::Manager::CreateInfoList;
|
||||
|
||||
/* General lookaside list used for allocation and deallocation buffers for Unicode object names */
|
||||
GENERAL_LOOKASIDE OB::Manager::NameBufferList;
|
||||
|
||||
/* The list head for tracking objects that have been marked for deferred deletion */
|
||||
PVOID OB::LifeCycle::RemoveObjectList;
|
||||
82
xtoskrnl/ob/devmap.cc
Normal file
82
xtoskrnl/ob/devmap.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/ob/devmap.cc
|
||||
* DESCRIPTION: Object Manager Device Map
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the Global Devices Directory associated with a given directory's device map.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the object directory to query.
|
||||
*
|
||||
* @return Returns a pointer to the global devices directory, or NULLPTR if none exists.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
POBJECT_DIRECTORY
|
||||
OB::DeviceMap::GetGlobalDevicesDirectory(IN POBJECT_DIRECTORY Directory)
|
||||
{
|
||||
POBJECT_DIRECTORY GlobalDevicesDirectory;
|
||||
|
||||
/* Assume no mapping exists */
|
||||
GlobalDevicesDirectory = NULLPTR;
|
||||
|
||||
/* Acquire the device map lock */
|
||||
KE::PushLock::AcquireExclusivePushLock(&DeviceMapLock);
|
||||
|
||||
/* Check if the directory has an associated device map */
|
||||
if(Directory->DeviceMap)
|
||||
{
|
||||
/* Extract the global devices directory */
|
||||
GlobalDevicesDirectory = Directory->DeviceMap->GlobalDevicesDirectory;
|
||||
}
|
||||
|
||||
/* Release the device map lock */
|
||||
KE::PushLock::ReleaseExclusivePushLock(&DeviceMapLock);
|
||||
|
||||
/* Return the resolved directory */
|
||||
return GlobalDevicesDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current state of the unique device maps configuration.
|
||||
*
|
||||
* @return This routine returns TRUE if unique device maps are enabled, or FALSE otherwise.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
BOOLEAN
|
||||
OB::DeviceMap::GetUniqueDeviceMaps(VOID)
|
||||
{
|
||||
/* Return the unique device maps flag */
|
||||
return UniqueDeviceMaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Object Manager's device map subsystem.
|
||||
*
|
||||
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
OB::DeviceMap::InitializeDeviceMap(VOID)
|
||||
{
|
||||
/* Initialize device map lock */
|
||||
KE::PushLock::InitializePushLock(&DeviceMapLock);
|
||||
|
||||
/* Temporarily disable unique device maps */
|
||||
UniqueDeviceMaps = FALSE;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
1541
xtoskrnl/ob/lifecycl.cc
Normal file
1541
xtoskrnl/ob/lifecycl.cc
Normal file
File diff suppressed because it is too large
Load Diff
582
xtoskrnl/ob/obdir.cc
Normal file
582
xtoskrnl/ob/obdir.cc
Normal file
@@ -0,0 +1,582 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/ob/obdir.cc
|
||||
* DESCRIPTION: Object Manager Directory
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Acquires an exclusive pushlock for the specified object directory.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the object directory being locked.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the lookup context used to track the lock state.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::AcquireExclusiveDirectoryLock(IN OUT POBJECT_DIRECTORY Directory,
|
||||
IN OUT POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
/* Set the initial lock state */
|
||||
LookupContext->LockStateSignature = OBJECT_LOCK_STATE_WAIT_EXCLUSIVE;
|
||||
|
||||
/* Disable kernel APCs */
|
||||
KE::KThread::EnterCriticalRegion();
|
||||
|
||||
/* Acquire the directory lock for exclusive access */
|
||||
KE::PushLock::AcquireExclusivePushLock(&Directory->Lock);
|
||||
|
||||
/* Update the lock state */
|
||||
LookupContext->LockStateSignature = OBJECT_LOCK_STATE_OWNED_EXCLUSIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires a shared pushlock for the specified object directory.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the object directory being locked.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the lookup context used to track the lock state.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::AcquireSharedDirectoryLock(IN POBJECT_DIRECTORY Directory,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
/* Set the initial lock state */
|
||||
LookupContext->LockStateSignature = OBJECT_LOCK_WAITSHARED_SIGNATURE;
|
||||
|
||||
/* Disable kernel APCs */
|
||||
KE::KThread::EnterCriticalRegion();
|
||||
|
||||
/* Acquire the directory lock for shared access */
|
||||
KE::PushLock::AcquireSharedPushLock(&Directory->Lock);
|
||||
|
||||
/* Update the lock state */
|
||||
LookupContext->LockStateSignature = OBJECT_LOCK_OWNEDSHARED_SIGNATURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the case-insensitive hash index for an object name.
|
||||
*
|
||||
* @param Name
|
||||
* Supplies a pointer to the unicode string containing the object name.
|
||||
*
|
||||
* @return This routine returns the computed hash index.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
ULONG
|
||||
OB::Directory::ComputeObjectNameHash(IN PCUNICODE_STRING Name)
|
||||
{
|
||||
ULONG CharacterLength, HashIndex;
|
||||
WCHAR Character;
|
||||
PWCH Buffer;
|
||||
|
||||
/* Initialize the buffer pointer, character count, and starting hash value */
|
||||
Buffer = Name->Buffer;
|
||||
CharacterLength = Name->Length / sizeof(WCHAR);
|
||||
HashIndex = 0;
|
||||
|
||||
/* Iterate through each wide character */
|
||||
while(CharacterLength--)
|
||||
{
|
||||
/* Fetch the current character and advance the buffer pointer */
|
||||
Character = *Buffer++;
|
||||
|
||||
/* Apply the NT string hashing polynomial */
|
||||
HashIndex += (HashIndex << 1) + (HashIndex >> 1);
|
||||
|
||||
/* Check if the character is uppercase, numeric, or a symbol */
|
||||
if(Character < L'a')
|
||||
{
|
||||
/* Add the unmodified character */
|
||||
HashIndex += Character;
|
||||
}
|
||||
else if(Character > L'z')
|
||||
{
|
||||
/* Convert extended Unicode characters to uppercase */
|
||||
HashIndex += RTL::Nls::ToUpperUnicodeCharacter(Character);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perform ASCII conversion from lowercase to uppercase */
|
||||
HashIndex += (Character - (L'a' - L'A'));
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the final hash value */
|
||||
return HashIndex % OBJECT_NUMBER_HASH_BUCKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an object directory entry from its hash bucket and frees its memory.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the lookup context containing the directory and hash index.
|
||||
*
|
||||
* @return This routine returns TRUE if the entry was successfully unlinked and freed, or FALSE otherwise.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
BOOLEAN
|
||||
OB::Directory::DeleteDirectoryEntry(IN POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
POBJECT_DIRECTORY_ENTRY DirectoryEntry, *HashBucket;
|
||||
POBJECT_DIRECTORY Directory;
|
||||
|
||||
/* Extract the directory from the lookup context */
|
||||
Directory = LookupContext->Directory;
|
||||
|
||||
/* Verify that the directory pointer is valid */
|
||||
if(Directory)
|
||||
{
|
||||
/* Resolve the head of the collision chain */
|
||||
HashBucket = (POBJECT_DIRECTORY_ENTRY*)&Directory->HashBuckets[LookupContext->HashIndex];
|
||||
|
||||
/* Retrieve the entry at the head of the chain */
|
||||
DirectoryEntry = *HashBucket;
|
||||
|
||||
/* Ensure there isan entry to delete */
|
||||
if(DirectoryEntry)
|
||||
{
|
||||
/* Unlink the entry from the hash bucket chain */
|
||||
*HashBucket = DirectoryEntry->ChainLink;
|
||||
DirectoryEntry->ChainLink = NULLPTR;
|
||||
|
||||
/* Free the memory */
|
||||
MM::Allocator::FreePool(DirectoryEntry);
|
||||
|
||||
/* Return TRUE */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* No entry found, return FALSE */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Object Manager lookup context.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the caller-allocated lookup context to initialize.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::InitializeLookupContext(OUT POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
/* Initialize the lookup context */
|
||||
LookupContext->Directory = NULLPTR;
|
||||
LookupContext->DirectoryLocked = FALSE;
|
||||
LookupContext->LockStateSignature = OBJECT_LOCK_STATE_INITIALIZED;
|
||||
LookupContext->Object = NULLPTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a newly created object into an object directory.
|
||||
*
|
||||
* @param Directory
|
||||
* Pointer to the object directory where the object will be inserted.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Pointer to the lookup context containing the precomputed hash index.
|
||||
*
|
||||
* @param ObjectHeader
|
||||
* Pointer to the object header of the object being inserted.
|
||||
*
|
||||
* @return TRUE if the insertion was successful, FALSE if pool allocation failed.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
BOOLEAN
|
||||
OB::Directory::InsertDirectoryEntry(IN OUT POBJECT_DIRECTORY Directory,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext,
|
||||
IN OUT POBJECT_HEADER ObjectHeader)
|
||||
{
|
||||
POBJECT_DIRECTORY_ENTRY *HashBucket, NewEntry;
|
||||
POBJECT_HEADER_NAME_INFO NameInfo;
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Extract the name information header */
|
||||
NameInfo = OB::LifeCycle::GetObjectNameInformation(ObjectHeader);
|
||||
|
||||
/* Allocate the directory entry */
|
||||
Status = MM::Allocator::AllocatePool(PagedPool, sizeof(OBJECT_DIRECTORY_ENTRY),
|
||||
(PVOID *)&NewEntry, TAG_OB_DIRECTORY);
|
||||
if(Status != STATUS_SUCCESS || !NewEntry)
|
||||
{
|
||||
/* Allocation failed, return FALSE */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Resolve the hash bucket head */
|
||||
HashBucket = (POBJECT_DIRECTORY_ENTRY*)&Directory->HashBuckets[LookupContext->HashIndex];
|
||||
|
||||
/* Insert the entry at the head of the collision chain */
|
||||
NewEntry->ChainLink = *HashBucket;
|
||||
*HashBucket = NewEntry;
|
||||
|
||||
/* Link the entry to the object body and establish the parent directory */
|
||||
NewEntry->Object = &ObjectHeader->Body;
|
||||
NameInfo->Directory = Directory;
|
||||
|
||||
/* Return TRUE */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires an exclusive lock on the specified object directory.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the object directory to lock.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the active lookup context used to track the lock state.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::LockLookupContext(IN POBJECT_DIRECTORY Directory,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
/* Acquire exclusive access to the directory */
|
||||
AcquireExclusiveDirectoryLock(Directory, LookupContext);
|
||||
|
||||
/* Cache the directory pointer and lock ownership */
|
||||
LookupContext->Directory = Directory;
|
||||
LookupContext->DirectoryLocked = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up an object directory entry by name within the namespace.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the primary object directory to search.
|
||||
*
|
||||
* @param Name
|
||||
* Supplies a pointer to the name of the object to locate.
|
||||
*
|
||||
* @param Attributes
|
||||
* Supplies the object attributes bitmask.
|
||||
*
|
||||
* @param SearchGlobalDirectory
|
||||
* Specifies whether to fallback into the device map's global shadow directory if the object is not found
|
||||
* in the primary directory.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the tracking context.
|
||||
*
|
||||
* @return This routine returns a pointer to the referenced object body, or NULLPTR if resolution fails.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
PVOID
|
||||
OB::Directory::LookupDirectoryEntry(IN POBJECT_DIRECTORY Directory,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN ULONG Attributes,
|
||||
IN BOOLEAN SearchGlobalDirectory,
|
||||
OUT POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
POBJECT_HEADER_NAME_INFO PreviousNameInfo;
|
||||
POBJECT_DIRECTORY CurrentDirectory;
|
||||
BOOLEAN CaseInsensitive;
|
||||
PVOID FoundObject;
|
||||
ULONG HashIndex;
|
||||
|
||||
/* Initialize the default return value */
|
||||
FoundObject = NULLPTR;
|
||||
|
||||
/* Check if global device map traversal is available */
|
||||
if(!OB::DeviceMap::GetUniqueDeviceMaps())
|
||||
{
|
||||
/* Override caller's request to prevent shadow directory traversal */
|
||||
SearchGlobalDirectory = FALSE;
|
||||
}
|
||||
|
||||
/* Guard against invalid parameter combination */
|
||||
if(Directory != NULLPTR && Name != NULLPTR && Name->Length != 0 && Name->Buffer != NULLPTR)
|
||||
{
|
||||
/* Determine if the string comparison should ignore case */
|
||||
CaseInsensitive = (Attributes & OBJECT_CASE_INSENSITIVE) ? TRUE : FALSE;
|
||||
|
||||
/* Precompute the hash index */
|
||||
HashIndex = ComputeObjectNameHash(Name);
|
||||
|
||||
/* Initialize the traversal pointer */
|
||||
CurrentDirectory = Directory;
|
||||
|
||||
/* Cache the computed hash index in the lookup context */
|
||||
LookupContext->HashIndex = (USHORT)HashIndex;
|
||||
|
||||
/* Iterate through the directory and linked shadow boundaries */
|
||||
while(CurrentDirectory)
|
||||
{
|
||||
/* Check if the directory is locked */
|
||||
if(!LookupContext->DirectoryLocked)
|
||||
{
|
||||
/* Acquire the directory lock */
|
||||
AcquireSharedDirectoryLock(CurrentDirectory, LookupContext);
|
||||
}
|
||||
|
||||
/* Traverse the hash bucket chain to find a matching entry */
|
||||
FoundObject = SearchDirectory(CurrentDirectory, Name, CaseInsensitive, HashIndex, LookupContext);
|
||||
if(FoundObject)
|
||||
{
|
||||
/* Match found, secure the object and its name info */
|
||||
OB::LifeCycle::ReferenceObjectNameInformation(CONTAIN_RECORD(FoundObject, OBJECT_HEADER, Body));
|
||||
OB::LifeCycle::ReferenceObject(FoundObject);
|
||||
|
||||
/* Check if the directory is locked */
|
||||
if(!LookupContext->DirectoryLocked)
|
||||
{
|
||||
/* Drop the lock and restore standard kernel APC delivery */
|
||||
OB::Directory::ReleaseDirectoryLock(CurrentDirectory, LookupContext);
|
||||
}
|
||||
|
||||
/* Target resolved, break the loop */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if the directory is locked */
|
||||
if(!LookupContext->DirectoryLocked)
|
||||
{
|
||||
/* Drop the lock and restore standard kernel APC delivery */
|
||||
OB::Directory::ReleaseDirectoryLock(CurrentDirectory, LookupContext);
|
||||
}
|
||||
|
||||
/* Check if fallback to the global shadow directory is possible */
|
||||
if(SearchGlobalDirectory && CurrentDirectory->DeviceMap != NULLPTR)
|
||||
{
|
||||
/* Resolve the shadow global devices directory in next iteration */
|
||||
CurrentDirectory = OB::DeviceMap::GetGlobalDevicesDirectory(CurrentDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Terminate the traversal loop */
|
||||
CurrentDirectory = NULLPTR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the lookup context contains a previously resolved object */
|
||||
if(LookupContext->Object != NULLPTR)
|
||||
{
|
||||
/* Resolve the old object's name information header */
|
||||
PreviousNameInfo = OB::LifeCycle::GetObjectNameInformation(CONTAIN_RECORD(LookupContext->Object,
|
||||
OBJECT_HEADER,
|
||||
Body));
|
||||
|
||||
/* Release the references */
|
||||
OB::LifeCycle::DereferenceObjectNameInformation(PreviousNameInfo);
|
||||
OB::LifeCycle::DereferenceObject(LookupContext->Object);
|
||||
}
|
||||
|
||||
/* Store the newly found object payload inside the caller's lookup context */
|
||||
LookupContext->Object = FoundObject;
|
||||
|
||||
/* Return the object body */
|
||||
return FoundObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a previously acquired object directory lock.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the object directory to unlock.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the lookup context for state tracking.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::ReleaseDirectoryLock(IN OUT POBJECT_DIRECTORY Directory,
|
||||
IN OUT POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
/* Release the directory lock */
|
||||
KE::PushLock::ReleasePushLock(&Directory->Lock);
|
||||
|
||||
/* Update the lock state */
|
||||
LookupContext->LockStateSignature = OBJECT_LOCK_STATE_RELEASED_SIGNATURE;
|
||||
|
||||
/* Restore APC delivery */
|
||||
KE::KThread::LeaveCriticalRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources held within an Object Manager lookup context.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the active lookup context to be released.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::ReleaseLookupContext(IN OUT POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
/* Verify if a directory lock is held */
|
||||
if(LookupContext->DirectoryLocked)
|
||||
{
|
||||
/* Release the directory lock */
|
||||
ReleaseDirectoryLock(LookupContext->Directory, LookupContext);
|
||||
|
||||
/* Update lookup context state */
|
||||
LookupContext->Directory = NULLPTR;
|
||||
LookupContext->DirectoryLocked = FALSE;
|
||||
}
|
||||
|
||||
/* Release the object references held within a lookup context */
|
||||
ReleaseLookupContextObject(LookupContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the object reference held within a lookup context.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the active lookup context containing the object to be released.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
VOID
|
||||
OB::Directory::ReleaseLookupContextObject(IN OUT POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
POBJECT_HEADER_NAME_INFO NameInfo;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
PVOID Object;
|
||||
|
||||
/* Extract the cached object pointer from the lookup context */
|
||||
Object = LookupContext->Object;
|
||||
if(Object)
|
||||
{
|
||||
/* Resolve the object header */
|
||||
ObjectHeader = CONTAIN_RECORD(Object, OBJECT_HEADER, Body);
|
||||
|
||||
/* Retrieve the optional name information header */
|
||||
NameInfo = OB::LifeCycle::GetObjectNameInformation(ObjectHeader);
|
||||
|
||||
/* Verify if the object has a registered name */
|
||||
if(NameInfo)
|
||||
{
|
||||
/* Drop the name query reference */
|
||||
OB::LifeCycle::DereferenceObjectNameInformation(NameInfo);
|
||||
}
|
||||
|
||||
/* Release the pointer reference */
|
||||
OB::LifeCycle::DereferenceObject(Object);
|
||||
|
||||
/* Purge the pointer */
|
||||
LookupContext->Object = NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses an object directory hash bucket to find a matching entry.
|
||||
*
|
||||
* @param Directory
|
||||
* Supplies a pointer to the object directory being searched.
|
||||
*
|
||||
* @param Name
|
||||
* Supplies ap ointer to the target object name.
|
||||
*
|
||||
* @param CaseInsensitive
|
||||
* Specifies whether the string comparison should ignore case.
|
||||
*
|
||||
* @param HashIndex
|
||||
* Supplies the pre-computed hash bucket index used to locate the collision chain.
|
||||
*
|
||||
* @param LookupContext
|
||||
* Supplies a pointer to the caller's lookup context.
|
||||
*
|
||||
* @return This routine returns a pointer to the resolved object body if found, or NULLPTR otherwise.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTFASTCALL
|
||||
PVOID
|
||||
OB::Directory::SearchDirectory(IN POBJECT_DIRECTORY Directory,
|
||||
IN PCUNICODE_STRING Name,
|
||||
IN BOOLEAN CaseInsensitive,
|
||||
IN ULONG HashIndex,
|
||||
IN POBJECT_LOOKUP_CONTEXT LookupContext)
|
||||
{
|
||||
POBJECT_DIRECTORY_ENTRY DirectoryEntry, *HeadDirectoryEntry, *LookupBucket;
|
||||
POBJECT_HEADER_NAME_INFO NameInfo;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
|
||||
/* Resolve the head pointer of the target hash bucket chain */
|
||||
LookupBucket = (POBJECT_DIRECTORY_ENTRY*)&Directory->HashBuckets[HashIndex];
|
||||
|
||||
/* Iterate through the collision chain */
|
||||
HeadDirectoryEntry = LookupBucket;
|
||||
while((DirectoryEntry = *HeadDirectoryEntry) != NULLPTR)
|
||||
{
|
||||
/* Resolve the underlying object header */
|
||||
ObjectHeader = CONTAIN_RECORD(DirectoryEntry->Object, OBJECT_HEADER, Body);
|
||||
|
||||
/* Retrieve the optional name information header */
|
||||
NameInfo = OB::LifeCycle::GetObjectNameInformation(ObjectHeader);
|
||||
|
||||
/* Check if the names match */
|
||||
if((Name->Length == NameInfo->Name.Length) &&
|
||||
RTL::Unicode::CompareString(Name, &NameInfo->Name, CaseInsensitive) == 0)
|
||||
{
|
||||
/* Check if it is already at the head of the bucket */
|
||||
if(HeadDirectoryEntry != LookupBucket)
|
||||
{
|
||||
/* Check if the directory is locked */
|
||||
if(LookupContext->DirectoryLocked || KE::PushLock::ConvertSharedPushLockToExclusive(&Directory->Lock))
|
||||
{
|
||||
/* Relocate the entry to the front */
|
||||
*HeadDirectoryEntry = DirectoryEntry->ChainLink;
|
||||
DirectoryEntry->ChainLink = *LookupBucket;
|
||||
*LookupBucket = DirectoryEntry;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the pointer to the object body */
|
||||
return DirectoryEntry->Object;
|
||||
}
|
||||
|
||||
/* Advance to the next node entry */
|
||||
HeadDirectoryEntry = &DirectoryEntry->ChainLink;
|
||||
}
|
||||
|
||||
/* Return NULL pointer*/
|
||||
return NULLPTR;
|
||||
}
|
||||
120
xtoskrnl/ob/obmgr.cc
Normal file
120
xtoskrnl/ob/obmgr.cc
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/ob/obmgr.cc
|
||||
* DESCRIPTION: Object Manager
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the Object Manager subsystem.
|
||||
*
|
||||
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
OB::Manager::InitializeObjectManager(VOID)
|
||||
{
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Zero out the static global lookaside structures */
|
||||
RTL::Memory::ZeroMemory(&CreateInfoList, sizeof(GENERAL_LOOKASIDE));
|
||||
RTL::Memory::ZeroMemory(&NameBufferList, sizeof(GENERAL_LOOKASIDE));
|
||||
|
||||
/* Initialize the system-wide global lookaside list for object create information structures */
|
||||
EX::LookasideList::InitializeLookasideList(&CreateInfoList, NonPagedPool,
|
||||
sizeof(OBJECT_CREATE_INFORMATION), TAG_OB_CREATE_INFO,
|
||||
64, EX::LookasideList::GetSystemLookasideListHead());
|
||||
|
||||
/* Initialize the system-wide global lookaside list for object name buffers */
|
||||
EX::LookasideList::InitializeLookasideList(&NameBufferList, PagedPool,
|
||||
OBJECT_NAME_BUFFER_SIZE, TAG_OB_NAME,
|
||||
32, EX::LookasideList::GetSystemLookasideListHead());
|
||||
|
||||
/* Initialize system lookaside list for BSP */
|
||||
InitializeSystemLookasideList();
|
||||
|
||||
/* Initialize device map support */
|
||||
OB::DeviceMap::InitializeDeviceMap();
|
||||
|
||||
OB::LifeCycle::InitializeObjectLifeCycle();
|
||||
|
||||
/* Initialize object type registry */
|
||||
Status = OB::TypeRegistry::InitializeObjectTypeRegistry();
|
||||
if(Status != STATUS_SUCCESS)
|
||||
{
|
||||
/* Initialization failed, return error code */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the per-processor lookaside lists for the Object Manager.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
OB::Manager::InitializeSystemLookasideList(VOID)
|
||||
{
|
||||
PKPROCESSOR_CONTROL_BLOCK Prcb;
|
||||
PGENERAL_LOOKASIDE LookasideList;
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Retrieve the Processor Control Block */
|
||||
Prcb = KE::Processor::GetCurrentProcessorControlBlock();
|
||||
|
||||
/* Allocate a contiguous memory block for lookaside lists */
|
||||
Status = MM::Allocator::AllocatePool(NonPagedPool, sizeof(GENERAL_LOOKASIDE) * 2,
|
||||
(PVOID*)&LookasideList, TAG_OB_CREATE_INFO);
|
||||
|
||||
/* Wire the global pointer for create information structures */
|
||||
Prcb->LookasideList[LookasideCreateInfoList].Global = &CreateInfoList;
|
||||
|
||||
/* Check if the contiguous allocation was successful */
|
||||
if(Status == STATUS_SUCCESS && LookasideList)
|
||||
{
|
||||
/* Map the pointer to the first half of the contiguous block */
|
||||
Prcb->LookasideList[LookasideCreateInfoList].Local = &LookasideList[0];
|
||||
|
||||
/* Initialize the local list */
|
||||
EX::LookasideList::InitializeLookasideList(&LookasideList[0], NonPagedPool,
|
||||
sizeof(OBJECT_CREATE_INFORMATION), TAG_OB_CREATE_INFO,
|
||||
64, EX::LookasideList::GetSystemLookasideListHead());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocation failed, use shared global list */
|
||||
Prcb->LookasideList[LookasideCreateInfoList].Local = &CreateInfoList;
|
||||
}
|
||||
|
||||
/* Wire the global pointer for object name buffers */
|
||||
Prcb->LookasideList[LookasideNameBufferList].Global = &NameBufferList;
|
||||
|
||||
/* Check if the contiguous allocation was successful */
|
||||
if(Status == STATUS_SUCCESS && LookasideList)
|
||||
{
|
||||
/* Map the pointer to the second half of the contiguous block */
|
||||
Prcb->LookasideList[LookasideNameBufferList].Local = &LookasideList[1];
|
||||
|
||||
/* Initialize the local list */
|
||||
EX::LookasideList::InitializeLookasideList(&LookasideList[1], PagedPool,
|
||||
OBJECT_NAME_BUFFER_SIZE, TAG_OB_NAME,
|
||||
32, EX::LookasideList::GetSystemLookasideListHead());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocation failed, use shared global list */
|
||||
Prcb->LookasideList[LookasideNameBufferList].Local = &NameBufferList;
|
||||
}
|
||||
}
|
||||
60
xtoskrnl/ob/security.cc
Normal file
60
xtoskrnl/ob/security.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/ob/security.cc
|
||||
* DESCRIPTION: Object Manager Security API
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Provides the default security procedure for handling object security descriptors.
|
||||
*
|
||||
* @param Object
|
||||
* Supplies a pointer to the object whose security descriptor is being processed.
|
||||
*
|
||||
* @param OperationCode
|
||||
* Supplies the specific security operation to perform (e.g., Assign, Delete, Query, Set).
|
||||
*
|
||||
* @param SecurityInformation
|
||||
* Supplies a bitmask indicating which specific components of the security descriptor are involved.
|
||||
*
|
||||
* @param SecurityDescriptor
|
||||
* Supplies a pointer to a caller-allocated buffer. For a set/assign operation, this contains the new
|
||||
* security data. For a query operation, it receives the requested data.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies a pointer to a variable that specifies the size of the SecurityDescriptor buffer.
|
||||
* On return for a query operation, it receives the actual number of bytes required.
|
||||
*
|
||||
* @param OldSecurityDescriptor
|
||||
* Supplies a pointer to a variable that holds the current security descriptor of the object.
|
||||
*
|
||||
* @param PoolType
|
||||
* Supplies the type of memory pool to use if a new security descriptor must be allocated.
|
||||
*
|
||||
* @param GenericMapping
|
||||
* Supplies a pointer to the generic access mapping associated with the object's type.
|
||||
*
|
||||
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
OB::Security::ProcessObjectSecurityDescriptor(IN PVOID Object,
|
||||
IN SECURITY_OPERATION_CODE OperationCode,
|
||||
IN PSECURITY_INFORMATION SecurityInformation,
|
||||
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN OUT PULONG Length,
|
||||
IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
|
||||
IN MMPOOL_TYPE PoolType,
|
||||
IN PGENERIC_MAPPING GenericMapping)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
447
xtoskrnl/ob/typereg.cc
Normal file
447
xtoskrnl/ob/typereg.cc
Normal file
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/ob/typereg.cc
|
||||
* DESCRIPTION: Object Manager Type Registry
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Creates and initializes a new object type within the Object Manager namespace.
|
||||
*
|
||||
* @param TypeName
|
||||
* Supplies the requested name of the new object type.
|
||||
*
|
||||
* @param Initializer
|
||||
* Supplies the initialization parameters for the new object type.
|
||||
*
|
||||
* @param SecurityDescriptor
|
||||
* Supplies an optional security descriptor. (Currently ignored).
|
||||
*
|
||||
* @param ObjectType
|
||||
* Receives a pointer to the newly created object type.
|
||||
*
|
||||
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
OB::TypeRegistry::CreateObjectType(IN PUNICODE_STRING TypeName,
|
||||
IN POBJECT_TYPE_INITIALIZER Initializer,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
OUT POBJECT_TYPE *ObjectType)
|
||||
{
|
||||
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
|
||||
OBJECT_LOOKUP_CONTEXT LookupContext;
|
||||
POBJECT_HEADER NewObjectTypeHeader;
|
||||
POBJECT_TYPE NewObjectType;
|
||||
UNICODE_STRING ObjectName;
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Validate incoming parameters */
|
||||
Status = ValidateObjectTypeParameters(TypeName, Initializer);
|
||||
if(Status != STATUS_SUCCESS)
|
||||
{
|
||||
/* Parameter validation failed, return error code */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Initialize the lookup context */
|
||||
OB::Directory::InitializeLookupContext(&LookupContext);
|
||||
|
||||
/* Check if the global type directory exists */
|
||||
if(ObjectTypeDirectory)
|
||||
{
|
||||
/* Acquire the directory lock and prepare for namespace lookup */
|
||||
OB::Directory::LockLookupContext(ObjectTypeDirectory, &LookupContext);
|
||||
|
||||
/* Search the directory to check if an object type with this name already exists */
|
||||
if(OB::Directory::LookupDirectoryEntry(ObjectTypeDirectory, TypeName, OBJECT_CASE_INSENSITIVE,
|
||||
FALSE, &LookupContext))
|
||||
{
|
||||
/* A collision detected, release the directory lock and lookup context */
|
||||
OB::Directory::ReleaseLookupContext(&LookupContext);
|
||||
|
||||
/* Reject the creation due to a naming conflict */
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate paged memory for the persistent object type name */
|
||||
Status = MM::Allocator::AllocatePool(PagedPool, (ULONG)TypeName->MaximumLength,
|
||||
(PVOID*)&ObjectName.Buffer, TAG_OB_NAME);
|
||||
if(Status != STATUS_SUCCESS || ObjectName.Buffer == NULLPTR)
|
||||
{
|
||||
/* Pool allocation failed; release the lookup context and return error code */
|
||||
OB::Directory::ReleaseLookupContext(&LookupContext);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Copy the requested type name */
|
||||
ObjectName.MaximumLength = TypeName->MaximumLength;
|
||||
RTL::Unicode::CopyString(&ObjectName, TypeName);
|
||||
|
||||
/* Allocate the physical memory block for the Object Type */
|
||||
Status = OB::LifeCycle::AllocateObject(NULLPTR, KernelMode, MasterObjectType, &ObjectName,
|
||||
sizeof(OBJECT_TYPE), &NewObjectTypeHeader);
|
||||
if(Status != STATUS_SUCCESS)
|
||||
{
|
||||
/* Object allocation failed; release the directory lock and free allocated name buffer */
|
||||
OB::Directory::ReleaseLookupContext(&LookupContext);
|
||||
MM::Allocator::FreePool(ObjectName.Buffer);
|
||||
|
||||
/* Return error code */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Resolve the object body pointer and assign the captured name */
|
||||
NewObjectTypeHeader->Flags |= OBJECT_FLAG_KERNEL_MODE | OBJECT_FLAG_PERMANENT;
|
||||
NewObjectType = (POBJECT_TYPE)&NewObjectTypeHeader->Body;
|
||||
NewObjectType->Name = ObjectName;
|
||||
|
||||
/* Zero out the statistics block */
|
||||
RTL::Memory::ZeroMemory(&NewObjectType->TotalNumberOfObjects,
|
||||
FIELD_OFFSET(OBJECT_TYPE, TypeInfo) - FIELD_OFFSET(OBJECT_TYPE, TotalNumberOfObjects));
|
||||
|
||||
/* Check if master object type is already initialized */
|
||||
if(MasterObjectType == NULLPTR)
|
||||
{
|
||||
/* Set the global master type, link its header to itself, and set the default tag */
|
||||
MasterObjectType = NewObjectType;
|
||||
NewObjectTypeHeader->Type = MasterObjectType;
|
||||
NewObjectType->Key = TAG_OB_OBJECT_TYPE;
|
||||
NewObjectType->TotalNumberOfObjects = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generate a clean tag from object name */
|
||||
NewObjectType->Key = GenerateObjectPoolTag(TypeName);
|
||||
}
|
||||
|
||||
/* Initialize default objects and pool charges */
|
||||
InitializeObjectType(NewObjectType, Initializer, &ObjectName);
|
||||
|
||||
/* Suspend APCs and acquire exclusive access to the master type tracking list */
|
||||
KE::KThread::EnterCriticalRegion();
|
||||
KE::PushLock::AcquireExclusivePushLock(&MasterObjectType->TypeLock);
|
||||
|
||||
/* Retrieve the creator information header */
|
||||
CreatorInfo = OB::LifeCycle::GetObjectCreatorInformation(NewObjectTypeHeader);
|
||||
if(CreatorInfo != NULLPTR)
|
||||
{
|
||||
/* Link the new object type */
|
||||
RTL::LinkedList::InsertTailList(&MasterObjectType->TypeList, &CreatorInfo->TypeList);
|
||||
|
||||
/* Prevent double-insertion during handle creation */
|
||||
NewObjectTypeHeader->Flags &= ~OBJECT_FLAG_CREATOR_INFO;
|
||||
}
|
||||
|
||||
/* Assign a type index */
|
||||
NewObjectType->Index = MasterObjectType->TotalNumberOfObjects;
|
||||
if(NewObjectType->Index < OBJECT_MAX_DEFINED_OBJECT_TYPES)
|
||||
{
|
||||
/* Register the new type in the global table */
|
||||
ObjectTypesTable[NewObjectType->Index - 1] = NewObjectType;
|
||||
}
|
||||
|
||||
/* Release the master type lock and restore APC delivery */
|
||||
KE::PushLock::ReleaseExclusivePushLock(&MasterObjectType->TypeLock);
|
||||
KE::KThread::LeaveCriticalRegion();
|
||||
|
||||
/* Publish into the namespace directory */
|
||||
if(ObjectTypeDirectory == NULLPTR ||
|
||||
OB::Directory::InsertDirectoryEntry(ObjectTypeDirectory, &LookupContext, NewObjectTypeHeader))
|
||||
{
|
||||
/* Verify if the directory is present */
|
||||
if(ObjectTypeDirectory)
|
||||
{
|
||||
/* Increment the reference count */
|
||||
OB::LifeCycle::ReferenceObject(ObjectTypeDirectory);
|
||||
}
|
||||
|
||||
/* Release the directory lock and context */
|
||||
OB::Directory::ReleaseLookupContext(&LookupContext);
|
||||
|
||||
/* Return the pointer to the object type */
|
||||
*ObjectType = NewObjectType;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Directory insertion failed, release lock and return error code */
|
||||
OB::Directory::ReleaseLookupContext(&LookupContext);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up internal resources associated with an object type before its deletion.
|
||||
*
|
||||
* @param Object
|
||||
* Supplies a pointer to the Object Type body being deleted.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
OB::TypeRegistry::DeleteObjectType(IN PVOID Object)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a 4-byte pool tag based on the object type name.
|
||||
*
|
||||
* @param TypeName
|
||||
* Supplies the name of the object type.
|
||||
*
|
||||
* @return This routine returns a 32-bit pool tag.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
ULONG
|
||||
OB::TypeRegistry::GenerateObjectPoolTag(IN PUNICODE_STRING TypeName)
|
||||
{
|
||||
ULONG Index, Tag;
|
||||
PUCHAR TagBytes;
|
||||
|
||||
/* Default tag to four spaces */
|
||||
Tag = SIGNATURE32(' ', ' ', ' ', ' ');
|
||||
TagBytes = (PUCHAR)&Tag;
|
||||
|
||||
/* Extract up to the first 4 characters */
|
||||
for(Index = 0; Index < 4; Index++)
|
||||
{
|
||||
/* Verify if the current index falls within the valid bounds */
|
||||
if(Index < (TypeName->Length / sizeof(WCHAR)))
|
||||
{
|
||||
/* Strip the high unicode byte and store the resulting ASCII character */
|
||||
TagBytes[Index] = (UCHAR)(TypeName->Buffer[Index] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the tag */
|
||||
return Tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the internal body and configuration of a newly allocated object type.
|
||||
*
|
||||
* @param ObjectType
|
||||
* Supplies a pointer to the object type to initialize.
|
||||
*
|
||||
* @param Initializer
|
||||
* Supplies the initialization parameters.
|
||||
*
|
||||
* @param TypeName
|
||||
* Supplies the name of the object type.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
OB::TypeRegistry::InitializeObjectType(IN OUT POBJECT_TYPE ObjectType,
|
||||
IN POBJECT_TYPE_INITIALIZER Initializer,
|
||||
IN PUNICODE_STRING TypeName)
|
||||
{
|
||||
ULONG HeaderCharge;
|
||||
|
||||
/* Calculate standard header charges */
|
||||
HeaderCharge = sizeof(OBJECT_HEADER) + sizeof(OBJECT_HEADER_NAME_INFO);
|
||||
|
||||
/* Verify if the object type requires handle count tracking */
|
||||
if(Initializer->MaintainHandleCount)
|
||||
{
|
||||
/* Include the size of the handle information header in the total charge */
|
||||
HeaderCharge += sizeof(OBJECT_HEADER_HANDLE_INFO);
|
||||
}
|
||||
|
||||
/* Copy initialization data */
|
||||
RTL::Memory::CopyMemory(&ObjectType->TypeInfo, Initializer, sizeof(OBJECT_TYPE_INITIALIZER));
|
||||
|
||||
/* Enforce global type list maintenance and configure the target pool type */
|
||||
ObjectType->TypeInfo.MaintainTypeList = TRUE;
|
||||
ObjectType->TypeInfo.PoolType = Initializer->PoolType;
|
||||
|
||||
/* Check pool type */
|
||||
if(Initializer->PoolType == NonPagedPool)
|
||||
{
|
||||
/* Apply the charge to the non-paged pool requirement */
|
||||
ObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderCharge;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Apply the charge to the paged pool requirement */
|
||||
ObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderCharge;
|
||||
}
|
||||
|
||||
/* Check if the caller supplied a custom procedure for security descriptor operations */
|
||||
if(Initializer->SecurityProcedure == NULLPTR)
|
||||
{
|
||||
/* No custom procedure provided, attach the generic system handler */
|
||||
ObjectType->TypeInfo.SecurityProcedure = OB::Security::ProcessObjectSecurityDescriptor;
|
||||
}
|
||||
|
||||
/* Initialize synchronization mechanisms */
|
||||
KE::PushLock::InitializePushLock(&ObjectType->TypeLock);
|
||||
|
||||
/* Initialize the queue for registered callbacks and the tracking list */
|
||||
RTL::LinkedList::InitializeListHead(&ObjectType->CallbackList);
|
||||
RTL::LinkedList::InitializeListHead(&ObjectType->TypeList);
|
||||
|
||||
/* Check if the object type has a default object */
|
||||
if(ObjectType->TypeInfo.UseDefaultObject)
|
||||
{
|
||||
/* Map to the global default event and append the SYNCHRONIZE access right */
|
||||
ObjectType->DefaultObject = &DefaultEvent;
|
||||
ObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
|
||||
}
|
||||
else if(TypeName->Length == 8 && !RTL::WideString::CompareWideString(TypeName->Buffer, L"File", 0))
|
||||
{
|
||||
/* Point the synchronization offset directly to the internal Event field */
|
||||
ObjectType->DefaultObject = (PVOID)(ULONG_PTR)FIELD_OFFSET(FILE_OBJECT, Event);
|
||||
}
|
||||
else if(TypeName->Length == 24 && !RTL::WideString::CompareWideString(TypeName->Buffer, L"WaitablePort", 0))
|
||||
{
|
||||
/* Point the synchronization offset directly to the WaitEvent field */
|
||||
ObjectType->DefaultObject = (PVOID)(ULONG_PTR)FIELD_OFFSET(LPCP_PORT_OBJECT, WaitEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable synchronization for this object type */
|
||||
ObjectType->DefaultObject = NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the global Object Type Registry and bootstraps the master type object.
|
||||
*
|
||||
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
OB::TypeRegistry::InitializeObjectTypeRegistry(VOID)
|
||||
{
|
||||
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
||||
UNICODE_STRING TypeName;
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Initialize the global directory pointer */
|
||||
ObjectTypeDirectory = NULLPTR;
|
||||
|
||||
/* Clear the global object type lookup table and the default synchronization event block */
|
||||
RTL::Memory::ZeroMemory(ObjectTypesTable, sizeof(ObjectTypesTable));
|
||||
RTL::Memory::ZeroMemory(&DefaultEvent, sizeof(KEVENT));
|
||||
|
||||
/* Clear the initialization structure */
|
||||
RTL::Memory::ZeroMemory(&ObjectTypeInitializer, sizeof(OBJECT_TYPE_INITIALIZER));
|
||||
|
||||
/* Configure the attributes and pool charges for the master "Type" object */
|
||||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
|
||||
ObjectTypeInitializer.InvalidAttributes = OBJECT_OPENLINK;
|
||||
ObjectTypeInitializer.Length = sizeof(OBJECT_TYPE_INITIALIZER);
|
||||
ObjectTypeInitializer.MaintainTypeList = TRUE;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
|
||||
|
||||
/* Register default destructor */
|
||||
ObjectTypeInitializer.DeleteProcedure = &DeleteObjectType;
|
||||
|
||||
/* Initialize the descriptor for the "Type" name */
|
||||
RTL::Unicode::InitializeString(&TypeName, L"Type");
|
||||
|
||||
/* Create the master object type */
|
||||
Status = CreateObjectType(&TypeName, &ObjectTypeInitializer, NULLPTR, &MasterObjectType);
|
||||
if(Status != STATUS_SUCCESS)
|
||||
{
|
||||
/* Object type creation failed, return error code */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the parameters supplied for creating a new object type.
|
||||
*
|
||||
* @param TypeName
|
||||
* Supplies the requested name of the new object type.
|
||||
*
|
||||
* @param Initializer
|
||||
* Supplies the initialization parameters for the new object type.
|
||||
*
|
||||
* @return This routine returns a status code indicating the success or failure of the operation.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
OB::TypeRegistry::ValidateObjectTypeParameters(IN PUNICODE_STRING TypeName,
|
||||
IN POBJECT_TYPE_INITIALIZER Initializer)
|
||||
{
|
||||
ULONG Index;
|
||||
PWCH Buffer;
|
||||
|
||||
/* Check the basic string validity and alignment */
|
||||
if(TypeName == NULLPTR || TypeName->Length == 0 || (TypeName->Length % sizeof(WCHAR)) != 0)
|
||||
{
|
||||
/* Invalid type name, return error code */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check initializer block integrity and allowed flags */
|
||||
if(Initializer == NULLPTR ||
|
||||
(Initializer->InvalidAttributes & ~OBJECT_VALID_ATTRIBUTES) != 0 ||
|
||||
Initializer->Length != sizeof(OBJECT_TYPE_INITIALIZER))
|
||||
{
|
||||
/* Invalid initializer block, return error code */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check the maintaining handle count and procedure presence */
|
||||
if(Initializer->MaintainHandleCount &&
|
||||
Initializer->OpenProcedure == NULLPTR &&
|
||||
Initializer->CloseProcedure == NULLPTR)
|
||||
{
|
||||
/* Invalid initializer block, return error code */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Validate memory pool type */
|
||||
if(!Initializer->UseDefaultObject && Initializer->PoolType != NonPagedPool)
|
||||
{
|
||||
/* Invalid pool type, return error code */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Extract the buffer pointer */
|
||||
Buffer = TypeName->Buffer;
|
||||
Index = TypeName->Length / sizeof(WCHAR);
|
||||
|
||||
/* Scan for illegal path separators in the type name */
|
||||
while(Index--)
|
||||
{
|
||||
/* Check for path separator */
|
||||
if(*Buffer++ == OBJECT_NAME_PATH_SEPARATOR)
|
||||
{
|
||||
/* Invalid type name, return error code */
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user