/*++ Copyright (c) 1997 Microsoft Corporation Module Name: namespac.c Abstract: This file contains all of the namespace handling functions Author: Based on code by Mike Tsang (MikeTs) Stephane Plante (Splante) Environment: User mode only Revision History: --*/ #include "pch.h" PNSOBJ RootNameSpaceObject; PNSOBJ CurrentScopeNameSpaceObject; PNSOBJ CurrentOwnerNameSpaceObject; NTSTATUS CreateNameSpaceObject( PUCHAR ObjectName, PNSOBJ ObjectScope, PNSOBJ ObjectOwner, PNSOBJ *Object, ULONG Flags ) /*++ Routine Description: This routine creates a name space object under the current scope Arguments: ObjectName - Name Path String ObjectScope - Scope to start the search from (NULL == Root) ObjectOwner - The object which owns this one Object - Where to store the point to the object that we just created Flags - Options Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PNSOBJ localObject; ENTER( ( 3, "CreateNameSpaceObject(%s,Scope=%s,Owner=%p,Object=%p," "Flag=%08lx)\n", ObjectName, (ObjectScope ? LocalGetObjectPath( ObjectScope ) : "ROOT"), ObjectOwner, Object, Flags ) ); if (ObjectScope == NULL) { ObjectScope = RootNameSpaceObject; } status = GetNameSpaceObject( ObjectName, ObjectScope, &localObject, NSF_LOCAL_SCOPE ); if (NT_SUCCESS(status)) { if (!(Flags & NSF_EXIST_OK)) { status = STATUS_OBJECT_NAME_COLLISION; } } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { status = STATUS_SUCCESS; // // Are we creating root? // if (strcmp(ObjectName,"\\") == 0) { ASSERT( RootNameSpaceObject == NULL ); ASSERT( ObjectOwner == NULL ); localObject = MEMALLOC( sizeof(NSOBJ) ); if (localObject == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } else { memset( localObject, 0, sizeof(NSOBJ) ); localObject->dwSig = SIG_NSOBJ; localObject->dwNameSeg = NAMESEG_ROOT; RootNameSpaceObject = localObject; } } else { PUCHAR nameEnd; PNSOBJ objectParent; nameEnd = strrchr(ObjectName, '.'); if (nameEnd != NULL) { *nameEnd = '\0'; nameEnd++; status = GetNameSpaceObject( ObjectName, ObjectScope, &objectParent, NSF_LOCAL_SCOPE ); } else if (*ObjectName == '\\') { nameEnd = &ObjectName[1]; ASSERT( RootNameSpaceObject != NULL ); objectParent = RootNameSpaceObject; } else if (*ObjectName == '^') { nameEnd = ObjectName; objectParent = ObjectScope; while ( (*nameEnd == '^') && (objectParent != NULL)) { objectParent = objectParent->pnsParent; nameEnd++; } } else { ASSERT( ObjectScope ); nameEnd = ObjectName; objectParent = ObjectScope; } if (status == STATUS_SUCCESS) { ULONG length = strlen(nameEnd); localObject = MEMALLOC( sizeof(NSOBJ) ); if (localObject == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else if ( (*nameEnd != '\0') && (length > sizeof(NAMESEG))) { status = STATUS_OBJECT_NAME_INVALID; MEMFREE( localObject ); } else { memset( localObject, 0, sizeof(NSOBJ) ); localObject->dwSig = SIG_NSOBJ; localObject->dwNameSeg = NAMESEG_BLANK; memcpy( &(localObject->dwNameSeg), nameEnd, length ); localObject->hOwner = ObjectOwner; localObject->pnsParent = objectParent; ListInsertTail( &(localObject->list), (PPLIST) &(objectParent->pnsFirstChild) ); } } } } if (NT_SUCCESS(status) && Object != NULL) { *Object = localObject; } EXIT( ( 3, "CreateNameSpaceObject=%08lx (*Object=%p)\n", status, localObject ) ); return status; } NTSTATUS CreateObject( PUCHAR ObjectName, UCHAR ObjectType, PNSOBJ *Object ) /*++ Routine Description: Creates a NameSpace Object for the term Arguments: ObjectName - The name object object ObjectType - The type of object to create Object - Where to store a pointer to the created object Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PNSOBJ localObject; ENTER( ( 2, "CreateObject(%s,Type=%02x,Object=%p)\n", ObjectName, ObjectType, Object ) ); status = CreateNameSpaceObject( ObjectName, CurrentScopeNameSpaceObject, CurrentOwnerNameSpaceObject, &localObject, NSF_EXIST_OK ); if (NT_SUCCESS(status)) { switch (ObjectType) { case NSTYPE_UNKNOWN: break; case NSTYPE_FIELDUNIT: localObject->ObjData.dwDataType = OBJTYPE_FIELDUNIT; break; case NSTYPE_DEVICE: localObject->ObjData.dwDataType = OBJTYPE_DEVICE; break; case NSTYPE_EVENT: localObject->ObjData.dwDataType = OBJTYPE_EVENT; break; case NSTYPE_METHOD: localObject->ObjData.dwDataType = OBJTYPE_METHOD; break; case NSTYPE_MUTEX: localObject->ObjData.dwDataType = OBJTYPE_MUTEX; break; case NSTYPE_OPREGION: localObject->ObjData.dwDataType = OBJTYPE_OPREGION; break; case NSTYPE_POWERRES: localObject->ObjData.dwDataType = OBJTYPE_POWERRES; break; case NSTYPE_PROCESSOR: localObject->ObjData.dwDataType = OBJTYPE_PROCESSOR; break; case NSTYPE_THERMALZONE: localObject->ObjData.dwDataType = OBJTYPE_THERMALZONE; break; case NSTYPE_OBJALIAS: localObject->ObjData.dwDataType = OBJTYPE_OBJALIAS; break; case NSTYPE_BUFFFIELD: localObject->ObjData.dwDataType = OBJTYPE_BUFFFIELD; break; default: status = STATUS_OBJECT_TYPE_MISMATCH; } if (Object != NULL) { *Object = localObject; } } EXIT( ( 2, "CreateObject=%08lx (*Object=%p)\n", status, localObject ) ); return status; } //CreateObject NTSTATUS GetNameSpaceObject( PUCHAR ObjectPath, PNSOBJ ScopeObject, PNSOBJ *NameObject, ULONG Flags ) /*++ Routine Description: This routine searches the namespace until it finds a matching object Arguments: ObjectPath - String with the Name to search for ScopeObject - Scope to start search at (NULL == ROOT) NameObject - Where to store the object, if found Flags - Options Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PUCHAR subPath; ENTER( ( 3, "GetNameSpaceObject(%s,Scope=%s,Object=%p,Flags=%08lx\n", ObjectPath, (ScopeObject ? LocalGetObjectPath( ScopeObject ) : "ROOT"), NameObject, Flags ) ); if (ScopeObject == NULL) { ScopeObject = RootNameSpaceObject; } if (*ObjectPath == '\\') { subPath = &ObjectPath[1]; ScopeObject = RootNameSpaceObject; } else { subPath = ObjectPath; while ( (*subPath == '^') && (ScopeObject != NULL)) { subPath++; ScopeObject = ScopeObject->pnsParent; } } *NameObject = ScopeObject; if (ScopeObject == NULL) { status = STATUS_OBJECT_NAME_NOT_FOUND; } else if (*subPath != '\0') { BOOL searchUp; PNSOBJ tempObject; searchUp = (BOOL) ( !(Flags & NSF_LOCAL_SCOPE) && (ObjectPath[0] != '\\') && (ObjectPath[0] != '^') && (strlen(ObjectPath) <= sizeof(NAMESEG)) ); while (1) { do { tempObject = ScopeObject->pnsFirstChild; if (tempObject == NULL) { status = STATUS_OBJECT_NAME_NOT_FOUND; INFO( (5, "GetNameSpaceObject - %s has no children\n", LocalGetObjectPath( tempObject ) ) ); } else { BOOL found; PUCHAR bufferEnd; ULONG length; NAMESEG dwNameSeg; bufferEnd = strchr( subPath, '.' ); if (bufferEnd != NULL) { length = (ULONG)(bufferEnd - subPath); } else { length = strlen(subPath); } if (length > sizeof(NAMESEG)) { status = STATUS_OBJECT_NAME_INVALID; found = FALSE; } else { dwNameSeg = NAMESEG_BLANK; memcpy( &dwNameSeg, subPath, length ); INFO( (5, "GetNameSpaceObject - Looking for %*s\n", length, subPath) ); // // search all sibling fors a matching nameSeg // found = FALSE; do { INFO( (5, "GetNameSpaceObject - look at %s\n", LocalGetObjectPath( tempObject ) ) ); if (tempObject->dwNameSeg == dwNameSeg) { ScopeObject = tempObject; found = TRUE; break; } tempObject = (PNSOBJ) tempObject->list.plistNext; } while (tempObject != tempObject->pnsParent->pnsFirstChild ); } if (status == STATUS_SUCCESS) { if (!found) { status = STATUS_OBJECT_NAME_NOT_FOUND; } else { subPath += length; if (*subPath == '.') { subPath++; } else if (*subPath == '\0') { *NameObject = ScopeObject; break; } } } } } while ( status == STATUS_SUCCESS ); if (status == STATUS_OBJECT_NAME_NOT_FOUND && searchUp && ScopeObject != NULL && ScopeObject->pnsParent != NULL) { INFO( (5, "GetNameSpaceObject - Changing Scope to %s\n", LocalGetObjectPath( ScopeObject->pnsParent ) ) ); ScopeObject = ScopeObject->pnsParent; status = STATUS_SUCCESS; } else { break; } } } if (status != STATUS_SUCCESS) { *NameObject = NULL; } EXIT( ( 3, "GetNameSpaceObject=%08lx (*Object=%p)\n", status, *NameObject ) ); return status; } PUCHAR GetObjectTypeName( ULONG ObjectType ) /*++ Routine Description: Returns a string which corresponds to the type object the object Arugment: ObjectType - The type that we wish to know about Return Value: Globally Available String --*/ { PUCHAR type = NULL; ULONG i; static struct { ULONG ObjectType; PUCHAR ObjectTypeName; } ObjectTypeTable[] = { OBJTYPE_UNKNOWN, "Unknown", OBJTYPE_INTDATA, "Integer", OBJTYPE_STRDATA, "String", OBJTYPE_BUFFDATA, "Buffer", OBJTYPE_PKGDATA, "Package", OBJTYPE_FIELDUNIT, "FieldUnit", OBJTYPE_DEVICE, "Device", OBJTYPE_EVENT, "Event", OBJTYPE_METHOD, "Method", OBJTYPE_MUTEX, "Mutex", OBJTYPE_OPREGION, "OpRegion", OBJTYPE_POWERRES, "PowerResource", OBJTYPE_PROCESSOR, "Processor", OBJTYPE_THERMALZONE,"ThermalZone", OBJTYPE_BUFFFIELD, "BuffField", OBJTYPE_DDBHANDLE, "DDBHandle", OBJTYPE_DEBUG, "Debug", OBJTYPE_OBJALIAS, "ObjAlias", OBJTYPE_DATAALIAS, "DataAlias", OBJTYPE_BANKFIELD, "BankField", OBJTYPE_FIELD, "Field", OBJTYPE_INDEXFIELD, "IndexField", OBJTYPE_DATA, "Data", OBJTYPE_DATAFIELD, "DataField", OBJTYPE_DATAOBJ, "DataObject", OBJTYPE_PNP_RES, "PNPResource", OBJTYPE_RES_FIELD, "ResField", 0, NULL }; ENTER( (4, "GetObjectTypeName(Type=%02x)\n", ObjectType ) ); for (i = 0; ObjectTypeTable[i].ObjectTypeName != NULL; i++) { if (ObjectType == ObjectTypeTable[i].ObjectType) { type = ObjectTypeTable[i].ObjectTypeName; break; } } EXIT( (4, "GetObjectTypeName=%s\n", type ? type : "NULL" ) ); return type; } PUCHAR LocalGetObjectPath( PNSOBJ NameObject ) /*++ Routine Description: This routine takes a NameSpace Object and returns a string to represent its path Arguments: NameObject - The object whose path we want Return Value: Pointer to the string which represents the path --*/ { static UCHAR namePath[MAX_NAME_LEN + 1] = {0}; ULONG i; ENTER( (6, "LocalGetObjectPath(Object=%p)\n", NameObject ) ); if (NameObject != NULL) { if (NameObject->pnsParent == NULL) { strcpy(namePath, "\\"); } else { LocalGetObjectPath(NameObject->pnsParent); if (NameObject->pnsParent->pnsParent != NULL) { strcat(namePath, "."); } strncat(namePath, (PUCHAR)&NameObject->dwNameSeg, sizeof(NAMESEG)); } for (i = strlen(namePath) - 1; i >= 0; --i) { if (namePath[i] == '_') { namePath[i] = '\0'; } else { break; } } } else { namePath[0] = '\0'; } EXIT( (6, "LocalGetObjectPath=%s\n", namePath ) ); return namePath; } PUCHAR RemoteGetObjectPath( ULONG_PTR ObjectAddress ) /*++ Routine Description: This routine takes a NameSpace Object and returns a string to represent its path Arguments: NameObject - The object whose path we want Return Value: Pointer to the string which represents the path --*/ { static UCHAR namePath[MAX_NAME_LEN + 1] = {0}; NSOBJ nameObject; ULONG i; ENTER( (6, "RemoteGetObjectPath(Object=%p)\n", ObjectAddress ) ); if (ObjectAddress != 0 && ReadMemory( ObjectAddress, &nameObject, sizeof(nameObject), NULL) ) { if (nameObject.pnsParent == NULL) { strcpy(namePath, "\\"); } else { RemoteGetObjectPath( (ULONG_PTR) nameObject.pnsParent); if (strlen(namePath) > 1) { strcat(namePath, "."); } strncat(namePath, (PUCHAR)&nameObject.dwNameSeg, sizeof(NAMESEG)); } for (i = strlen(namePath) - 1; i >= 0; --i) { if (namePath[i] == '_') { namePath[i] = '\0'; } else { break; } } } else { namePath[0] = '\0'; } EXIT( (6, "RemoteGetObjectPath=%s\n", namePath ) ); return namePath; }