680 lines
14 KiB
C
680 lines
14 KiB
C
/*++
|
||
|
||
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
|
||
LOCAL
|
||
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( (
|
||
1,
|
||
"CreateNameSpaceObject(%s,Scope=%s,Owner=%p,Object=%p,"
|
||
"Flag=%08lx)\n",
|
||
ObjectName,
|
||
(ObjectScope ? GetObjectPath( 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->Signature = SIG_NSOBJ;
|
||
localObject->NameSeg = 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->ParentObject;
|
||
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->Signature = SIG_NSOBJ;
|
||
localObject->NameSeg = NAMESEG_BLANK;
|
||
memcpy( &(localObject->NameSeg), nameEnd, length );
|
||
localObject->Owner = ObjectOwner;
|
||
localObject->ParentObject = objectParent;
|
||
|
||
ListInsertTail(
|
||
&(localObject->List),
|
||
(PPLIST) &(objectParent->FirstChild)
|
||
);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if (NT_SUCCESS(status) && Object != NULL) {
|
||
|
||
*Object = localObject;
|
||
|
||
}
|
||
|
||
EXIT( (
|
||
1,
|
||
"CreateNameSpaceObject=%08lx (*Object=%p)\n",
|
||
status,
|
||
localObject
|
||
) );
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
LOCAL
|
||
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( (
|
||
1,
|
||
"CreateObject(%s,Type=%02x,Object=%p)\n",
|
||
ObjectName,
|
||
ObjectType,
|
||
Object
|
||
) );
|
||
|
||
status = CreateNameSpaceObject(
|
||
ObjectName,
|
||
CurrentScopeNameSpaceObject,
|
||
CurrentOwnerNameSpaceObject,
|
||
&localObject,
|
||
NSF_EXIST_ERR
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
switch (ObjectType) {
|
||
case NSTYPE_UNKNOWN:
|
||
break;
|
||
|
||
case NSTYPE_FIELDUNIT:
|
||
localObject->ObjectData.DataType = OBJTYPE_FIELDUNIT;
|
||
break;
|
||
|
||
case NSTYPE_DEVICE:
|
||
localObject->ObjectData.DataType = OBJTYPE_DEVICE;
|
||
break;
|
||
|
||
case NSTYPE_EVENT:
|
||
localObject->ObjectData.DataType = OBJTYPE_EVENT;
|
||
break;
|
||
|
||
case NSTYPE_METHOD:
|
||
localObject->ObjectData.DataType = OBJTYPE_METHOD;
|
||
break;
|
||
|
||
case NSTYPE_MUTEX:
|
||
localObject->ObjectData.DataType = OBJTYPE_MUTEX;
|
||
break;
|
||
|
||
case NSTYPE_OPREGION:
|
||
localObject->ObjectData.DataType = OBJTYPE_OPREGION;
|
||
break;
|
||
|
||
case NSTYPE_POWERRES:
|
||
localObject->ObjectData.DataType = OBJTYPE_POWERRES;
|
||
break;
|
||
|
||
case NSTYPE_PROCESSOR:
|
||
localObject->ObjectData.DataType = OBJTYPE_PROCESSOR;
|
||
break;
|
||
|
||
case NSTYPE_THERMALZONE:
|
||
localObject->ObjectData.DataType = OBJTYPE_THERMALZONE;
|
||
break;
|
||
|
||
case NSTYPE_OBJALIAS:
|
||
localObject->ObjectData.DataType = OBJTYPE_OBJALIAS;
|
||
break;
|
||
|
||
case NSTYPE_BUFFFIELD:
|
||
localObject->ObjectData.DataType = OBJTYPE_BUFFFIELD;
|
||
break;
|
||
|
||
default:
|
||
status = STATUS_OBJECT_TYPE_MISMATCH;
|
||
}
|
||
|
||
if (Object != NULL) {
|
||
|
||
*Object = localObject;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
EXIT( (
|
||
1,
|
||
"CreateObject=%08lx (*Object=%p)\n",
|
||
status,
|
||
localObject
|
||
) );
|
||
return status;
|
||
} //CreateObject
|
||
|
||
NTSTATUS
|
||
LOCAL
|
||
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( (
|
||
1,
|
||
"GetNameSpaceObject(%s,Scope=%s,Object=%p,Flags=%08lx\n",
|
||
ObjectPath,
|
||
(ScopeObject ? GetObjectPath( 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->ParentObject;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
*NameObject = ScopeObject;
|
||
if (ScopeObject == NULL) {
|
||
|
||
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||
|
||
} else if (*subPath != '\0') {
|
||
|
||
BOOL searchUp;
|
||
PNSOBJ tempObject;
|
||
|
||
searchUp = !(Flags & NSF_LOCAL_SCOPE) &&
|
||
(ObjectPath[0] == '\\') &&
|
||
(ObjectPath[0] == '^') &&
|
||
(strlen(ObjectPath) <= sizeof(NAMESEG));
|
||
|
||
while (1) {
|
||
|
||
do {
|
||
|
||
tempObject = ScopeObject->FirstChild;
|
||
if (tempObject == NULL) {
|
||
|
||
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||
|
||
} else {
|
||
|
||
BOOL found;
|
||
PUCHAR bufferEnd;
|
||
ULONG length;
|
||
NAMESEG nameSeg;
|
||
|
||
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 {
|
||
|
||
nameSeg = NAMESEG_BLANK;
|
||
memcpy( &nameSeg, subPath, length );
|
||
|
||
//
|
||
// search all sibling fors a matching nameSeg
|
||
//
|
||
found = FALSE;
|
||
do {
|
||
|
||
if (tempObject->NameSeg == nameSeg) {
|
||
|
||
ScopeObject = tempObject;
|
||
found = TRUE;
|
||
break;
|
||
|
||
}
|
||
|
||
tempObject = (PNSOBJ) tempObject->List.ListNext;
|
||
|
||
} while (tempObject != tempObject->ParentObject->FirstChild );
|
||
|
||
}
|
||
|
||
|
||
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->ParentObject != NULL) {
|
||
|
||
ScopeObject = ScopeObject->ParentObject;
|
||
status = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if (status != STATUS_SUCCESS) {
|
||
|
||
*NameObject = NULL;
|
||
|
||
}
|
||
|
||
|
||
EXIT( (
|
||
1,
|
||
"GetNameSpaceObject=%08lx (*Object=%p)\n",
|
||
status,
|
||
*NameObject
|
||
) );
|
||
return status;
|
||
|
||
}
|
||
|
||
PUCHAR
|
||
LOCAL
|
||
GetObjectPath(
|
||
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( (4, "GetObjectPath(Object=%p)\n", NameObject ) );
|
||
|
||
if (NameObject != NULL) {
|
||
|
||
if (NameObject->ParentObject == NULL) {
|
||
|
||
strcpy(namePath, "\\");
|
||
|
||
} else {
|
||
|
||
GetObjectPath(NameObject->ParentObject);
|
||
if (NameObject->ParentObject->ParentObject != NULL) {
|
||
|
||
strcat(namePath, ".");
|
||
|
||
}
|
||
strncat(namePath, (PUCHAR)&NameObject->NameSeg, sizeof(NAMESEG));
|
||
|
||
}
|
||
|
||
|
||
for (i = strlen(namePath) - 1; i >= 0; --i) {
|
||
|
||
if (namePath[i] == '_') {
|
||
|
||
namePath[i] = '\0';
|
||
|
||
} else {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
namePath[0] = '\0';
|
||
|
||
}
|
||
|
||
EXIT( (4, "GetObjectPath=%s\n", namePath ) );
|
||
return namePath;
|
||
}
|
||
|
||
PUCHAR
|
||
LOCAL
|
||
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;
|
||
}
|