/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: Object manager * Author: Chloe M. */ #include #include #include #include #include ST_STATUS ObCreateDirectory(const CHAR *Name, ST_OBJECT **Result) { ST_STATUS Status; ST_OBJECT *DirecObj; OBJECT_DIRECTORY *Direc; if (Name == NULL || Result == NULL) { return STATUS_INVALID_PARAM; } Status = ObCreateObject( Name, OBJECT_TYPE_DIRECTORY, NULL, &DirecObj ); if (Status != STATUS_SUCCESS) { return Status; } Direc = ExAllocatePoolWithTag( POOL_NON_PAGED, sizeof(*Direc), OBJECT_POOL_TAG ); if (Direc == NULL) { ObReclaimObject(DirecObj); return STATUS_NO_MEMORY; } RtlMemSet(Direc, 0, sizeof(*Direc)); DirecObj->Data = Direc; *Result = DirecObj; return STATUS_SUCCESS; } ST_STATUS ObCreateObject(const CHAR *Name, OBJECT_TYPE Type, VOID *Data, ST_OBJECT **Result) { ST_OBJECT *Object; USIZE NameLen; if (Name == NULL || Result == NULL) { return STATUS_INVALID_PARAM; } NameLen = RtlStrLen(Name); if (NameLen >= OBJECT_NAMESZ - 1) { return STATUS_NAME_TOO_LONG; } /* * Try to pull an object from the cache, if there are not * objects to pull then we'll allocate one. */ Object = ObPopFromCache(&gObCache); if (Object == NULL) { Object = ExAllocatePoolWithTag( POOL_NON_PAGED, sizeof(*Object), OBJECT_POOL_TAG ); if (Object == NULL) return STATUS_NO_MEMORY; } RtlMemSet(Object, 0, sizeof(*Object)); RtlMemCpy(Object->Name, Name, NameLen); Object->Name[NameLen] = '\0'; Object->RefCount = 1; Object->Type = Type; Object->Data = Data; *Result = Object; return STATUS_SUCCESS; } VOID ObReclaimObject(ST_OBJECT *Object) { if (Object == NULL) { return; } if (AtomicDecLong(&Object->RefCount) == 0) { ObReclaimToCache(&gObCache, Object); } } ST_STATUS ObAppendDirectory(ST_OBJECT *DirecParent, ST_OBJECT *Object) { OBJECT_DIRECTORY *Directory; ST_OBJECT *Last; if (DirecParent == NULL || Object == NULL) { return STATUS_INVALID_PARAM; } if (DirecParent->Type != OBJECT_TYPE_DIRECTORY) { return STATUS_NOT_DIRECTORY; } Directory = DirecParent->Data; if (Directory == NULL) { return STATUS_IO_ERROR; } /* TODO: Place lock here */ if (Directory->First == NULL || Directory->Last == NULL) { Directory->First = Object; Directory->Last = Object; } else { Last = Directory->Last; Last->DirecNext = Object; Directory->Last = Object; } return STATUS_SUCCESS; } ST_STATUS ObLookupFromTop(ST_OBJECT *Parent, const CHAR *Name, ST_OBJECT **Result) { ST_OBJECT *Entry; OBJECT_DIRECTORY *ParentDirec; USIZE NameLen; if (Parent == NULL || Name == NULL) { return STATUS_INVALID_PARAM; } if (Result == NULL) { return STATUS_INVALID_PARAM; } /* Must be a directory */ if (Parent->Type != OBJECT_TYPE_DIRECTORY) { return STATUS_NOT_DIRECTORY; } ParentDirec = Parent->Data; if (ParentDirec == NULL) { return STATUS_IO_ERROR; } Entry = ParentDirec->First; NameLen = RtlStrLen(Name); if (NameLen >= OBJECT_NAMESZ - 1) { return STATUS_NAME_TOO_LONG; } while (Entry != NULL) { if (*Entry->Name != *Name) { Entry = Entry->DirecNext; continue; } if (RtlMemCmp(Entry->Name, Name, NameLen) == 0) { *Result = Entry; return STATUS_SUCCESS; } Entry = Entry->DirecNext; } return STATUS_NOT_FOUND; }