windows-nt/Source/XPSP1/NT/windows/winstate/cobra/modules/script/attrib.c
2020-09-26 16:20:57 +08:00

657 lines
16 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
attrib.c
Abstract:
Implements the v1 script application attributes.
Author:
Jim Schmidt (jimschm) 08-Jun-2000
Revision History:
<alias> <date> <comments>
--*/
//
// Includes
//
#include "pch.h"
#include "v1p.h"
#define DBG_ATTRIB "Attrib"
//
// Strings
//
// None
//
// Constants
//
// None
//
// Macros
//
// None
//
// Types
//
typedef struct _MIGDB_ATTRIB {
INT AttribIndex;
UINT ArgCount;
PCTSTR Arguments;
BOOL NotOperator;
struct _MIGDB_ATTRIB *Next;
} MIGDB_ATTRIB, *PMIGDB_ATTRIB;
typedef BOOL(ATTRIBUTE_FUNCTION)(PCTSTR ArgMultiSz, PATTRIB_DATA Content);
typedef ATTRIBUTE_FUNCTION *PATTRIBUTE_FUNCTION;
typedef struct {
PCTSTR AttributeName;
PATTRIBUTE_FUNCTION Function;
UINT RequiredArgs;
} ATTRIBUTE_FUNCTION_ITEM, *PATTRIBUTE_FUNCTION_ITEM;
//
// Globals
//
extern BOOL g_VcmMode; // in sgmqueue.c
//
// Macro expansion list
//
#define ATTRIBUTE_LIST \
DEFMAC(EXISTS, pExists, 0) \
DEFMAC(SAMEOBJECTNAME, pSameObjectName, 1) \
DEFMAC(SAMEOBJECTCONTENT, pSameObjectContent, 2) \
DEFMAC(ISREGFLAGSET, pIsRegFlagSet, 1) \
DEFMAC(MATCHES, pMatches, 1) \
DEFMAC(SET_PERSIST_FLAG, pSetPersistFlag, 0) \
DEFMAC(NOTEMPTY, pNotEmpty, 0) \
DEFMAC(VERSION, pVersion, 2) \
//
// Private function prototypes
//
// None
//
// Macro expansion definition
//
#define DEFMAC(name,fn,req_args) ATTRIBUTE_FUNCTION fn;
ATTRIBUTE_LIST
#undef DEFMAC
#define DEFMAC(name,fn,req_args) TEXT(#name), fn, req_args,
ATTRIBUTE_FUNCTION_ITEM g_FnList[] = {
ATTRIBUTE_LIST /* , */
NULL, NULL, 0
};
//
// Code
//
#define STATE_ATTRNAME 1
#define STATE_ATTRARG 2
INT
pGetAttribIndex (
IN PCTSTR AttribName
)
/*++
Routine Description:
This routine returns the index in attribute functions array for a specified
attribute.
Arguments:
AttribName - Attribute name
Return value:
-1 - no such attribute in attribute table
--*/
{
INT attribIndex;
INT rc = 0;
PTSTR attrEnd = NULL;
TCHAR savedChar = 0;
attrEnd = (PTSTR) SkipSpaceR (AttribName, GetEndOfString (AttribName));
if (attrEnd != NULL) {
attrEnd = _tcsinc (attrEnd);
savedChar = attrEnd [0];
attrEnd [0] = 0;
}
__try {
for (attribIndex = 0 ; g_FnList[attribIndex].AttributeName ; attribIndex++) {
if (StringIMatch (g_FnList[attribIndex].AttributeName, AttribName)) {
break;
}
}
if (!g_FnList[attribIndex].AttributeName) {
attribIndex = -1;
LOG ((LOG_ERROR, (PCSTR) MSG_DETECT_ATTRIB_NOT_FOUND, AttribName));
}
rc = attribIndex;
}
__finally {
if (attrEnd != NULL) {
attrEnd [0] = savedChar;
}
}
return rc;
}
UINT
pGetReqArgCount (
IN INT AttributeIndex
)
{
if (AttributeIndex < 0 || AttributeIndex > ARRAYSIZE(g_FnList)) {
return 0;
}
return g_FnList[AttributeIndex].RequiredArgs;
}
BOOL
pValidateArg (
IN OUT PMIGDB_ATTRIB AttribStruct
)
{
//
// Validate all AttribStruct members
//
MYASSERT (AttribStruct);
if (AttribStruct->ArgCount != pGetReqArgCount (AttribStruct->AttribIndex)) {
AttribStruct->AttribIndex = -1;
return FALSE;
}
return TRUE;
}
PMIGDB_ATTRIB
pLoadAttribData (
IN PMHANDLE Pool,
IN PCTSTR MultiSzStr
)
/*++
Routine Description:
This routine creates a list of MIGDB_ATTRIBs from a multisz.
Arguments:
Pool - Specifies a pool that temporary structures and the return value
will be allocated from
MultiSzStr - Specifies the multisz to be processed. The multi-sz must
be in the form of ATTRIB or ATTRIB(arg[,arg,...])
Return value:
MIGDB_ATTRIB nodes
--*/
{
MULTISZ_ENUM multiSzEnum;
PMIGDB_ATTRIB result = NULL;
PMIGDB_ATTRIB tmpAttr = NULL;
INT state = STATE_ATTRNAME;
PTSTR currStrPtr = NULL;
PTSTR currArgPtr = NULL;
PTSTR endArgPtr = NULL;
TCHAR savedChar = 0;
GROWBUFFER argList = INIT_GROWBUFFER;
if (EnumFirstMultiSz (&multiSzEnum, MultiSzStr)) {
do {
currStrPtr = (PTSTR) SkipSpace (multiSzEnum.CurrentString);
if (state == STATE_ATTRNAME) {
tmpAttr = (PMIGDB_ATTRIB) PmGetMemory (Pool, sizeof (MIGDB_ATTRIB));
ZeroMemory (tmpAttr, sizeof (MIGDB_ATTRIB));
if (_tcsnextc (currStrPtr) == TEXT('!')) {
currStrPtr = _tcsinc (currStrPtr);
currStrPtr = (PTSTR) SkipSpace (currStrPtr);
tmpAttr->NotOperator = TRUE;
}
currArgPtr = _tcschr (currStrPtr, TEXT('('));
if (currArgPtr) {
endArgPtr = _tcsdec (currStrPtr, currArgPtr);
if (endArgPtr) {
endArgPtr = (PTSTR) SkipSpaceR (currStrPtr, endArgPtr);
endArgPtr = _tcsinc (endArgPtr);
}
else {
endArgPtr = currStrPtr;
}
savedChar = *endArgPtr;
*endArgPtr = 0;
tmpAttr->AttribIndex = pGetAttribIndex (currStrPtr);
*endArgPtr = savedChar;
currStrPtr = _tcsinc (currArgPtr);
state = STATE_ATTRARG;
}
else {
// this attribute has no arguments.
tmpAttr->AttribIndex = pGetAttribIndex (currStrPtr);
tmpAttr->Next = result;
result = tmpAttr;
pValidateArg (result);
continue;
}
}
if (state == STATE_ATTRARG) {
currStrPtr = (PTSTR) SkipSpace (currStrPtr);
endArgPtr = _tcsrchr (currStrPtr, TEXT(')'));
if (endArgPtr && endArgPtr[1] == 0) {
endArgPtr = _tcsdec (currStrPtr, endArgPtr);
if (endArgPtr) {
endArgPtr = (PTSTR) SkipSpaceR (currStrPtr, endArgPtr);
endArgPtr = _tcsinc (endArgPtr);
}
else {
endArgPtr = currStrPtr;
}
savedChar = *endArgPtr;
*endArgPtr = 0;
} else {
endArgPtr = NULL;
}
GbMultiSzAppend (&argList, currStrPtr);
tmpAttr->ArgCount++;
if (endArgPtr) {
*endArgPtr = savedChar;
tmpAttr->Arguments = PmDuplicateMultiSz (Pool, (PTSTR) argList.Buf);
GbFree (&argList);
state = STATE_ATTRNAME;
tmpAttr->Next = result;
result = tmpAttr;
pValidateArg (result);
}
}
} while (EnumNextMultiSz (&multiSzEnum));
}
return result;
}
BOOL
TestAttributes (
IN PMHANDLE WorkPool,
IN PCTSTR ArgumentMultiSz,
IN PATTRIB_DATA AttribData
)
/*++
Routine Description:
TestAttributes executes the attribute functions specified in the
ArgumentMultiSz parameter. Each argument is tested until they all succeed
or until one fails.
Arguments:
WorkPool - Specifies a pool handle for fast allocations
ArgumentMultiSz - Specifies the multi-sz that contains argument
specifications
AttribData - Specifies the object name, script specifications and
object content
Return Value:
TRUE if all attributes pass (or if zero attributes were specified), FALSE
otherwise.
--*/
{
PMIGDB_ATTRIB attrib;
PMIGDB_ATTRIB tmpAttrib;
BOOL result = TRUE;
attrib = pLoadAttribData (WorkPool, ArgumentMultiSz);
tmpAttrib = attrib;
while (result && attrib) {
if (attrib->AttribIndex < 0 || attrib->AttribIndex >= ARRAYSIZE(g_FnList)) {
DEBUGMSG ((DBG_WHOOPS, "Invalid attribute index %i", attrib->AttribIndex));
result = FALSE;
} else {
result = g_FnList[attrib->AttribIndex].Function (attrib->Arguments, AttribData);
if (attrib->NotOperator) {
result = !result;
}
}
attrib = attrib->Next;
}
// now free the attribute list
attrib = tmpAttrib;
while (attrib) {
tmpAttrib = attrib->Next;
if (attrib->Arguments) {
PmReleaseMemory (WorkPool, attrib->Arguments);
}
PmReleaseMemory (WorkPool, attrib);
attrib = tmpAttrib;
}
return result;
}
//
// Attribute functions (see ATTRIBUTE_LIST)
//
BOOL
pExists (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
return (Data->ReturnString != NULL);
}
BOOL
pSameObjectName (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
return (StringIMatch (FunctionArguments, Data->ScriptSpecifiedObject));
}
BOOL
pSameObjectContent (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
PCTSTR scriptObjectType = NULL;
PCTSTR scriptObjectName = NULL;
ATTRIB_DATA attribData;
BOOL result = FALSE;
scriptObjectType = FunctionArguments;
scriptObjectName = GetEndOfString (FunctionArguments);
if (scriptObjectName) {
scriptObjectName ++;
}
if (!scriptObjectType || !scriptObjectName) {
return FALSE;
}
ZeroMemory (&attribData, sizeof (ATTRIB_DATA));
attribData.ScriptSpecifiedType = scriptObjectType;
attribData.ScriptSpecifiedObject = scriptObjectName;
attribData.ApplicationName = Data->ApplicationName;
if (!AllocScriptType (&attribData)) {
return FALSE;
}
// let's persist the object in VCM mode so we can look at it later
if (g_VcmMode && attribData.ObjectName) {
if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
}
}
if (Data->ObjectContent && attribData.ObjectContent) {
if (Data->ObjectContent->ObjectTypeId == attribData.ObjectContent->ObjectTypeId) {
if (Data->ObjectContent->Details.DetailsSize == attribData.ObjectContent->Details.DetailsSize) {
if (!Data->ObjectContent->Details.DetailsSize ||
TestBuffer (
Data->ObjectContent->Details.DetailsData,
attribData.ObjectContent->Details.DetailsData,
Data->ObjectContent->Details.DetailsSize
)
) {
if (Data->ObjectContent->ContentInFile == attribData.ObjectContent->ContentInFile) {
if (Data->ObjectContent->ContentInFile) {
if (StringIMatch (
Data->ObjectContent->FileContent.ContentPath,
attribData.ObjectContent->FileContent.ContentPath
)
) {
result = TRUE;
}
} else {
if (Data->ObjectContent->MemoryContent.ContentSize == attribData.ObjectContent->MemoryContent.ContentSize) {
if (!Data->ObjectContent->MemoryContent.ContentSize ||
TestBuffer (
Data->ObjectContent->MemoryContent.ContentBytes,
attribData.ObjectContent->MemoryContent.ContentBytes,
Data->ObjectContent->MemoryContent.ContentSize
)
) {
result = TRUE;
}
}
}
}
}
}
}
}
FreeScriptType (&attribData);
return result;
}
BOOL
pIsRegFlagSet (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
DWORD inValue;
DWORD value;
if (!Data) {
return FALSE;
}
if (!FunctionArguments) {
return FALSE;
}
if (!Data->ObjectContent) {
return FALSE;
}
if ((Data->ObjectContent->ObjectTypeId & ~PLATFORM_MASK) != MIG_REGISTRY_TYPE) {
return FALSE;
}
if (Data->ObjectContent->Details.DetailsSize != sizeof (DWORD)) {
return FALSE;
}
if ((*((PDWORD)(Data->ObjectContent->Details.DetailsData)) != REG_DWORD) &&
(*((PDWORD)(Data->ObjectContent->Details.DetailsData)) != REG_SZ)
) {
return FALSE;
}
if (Data->ObjectContent->ContentInFile) {
return FALSE;
}
if (Data->ObjectContent->MemoryContent.ContentSize == 0) {
return FALSE;
}
if (Data->ObjectContent->MemoryContent.ContentBytes == NULL) {
return FALSE;
}
if (*((PDWORD)(Data->ObjectContent->Details.DetailsData)) == REG_DWORD) {
inValue = *((PDWORD)(Data->ObjectContent->MemoryContent.ContentBytes));
} else {
_stscanf ((PCTSTR)Data->ObjectContent->MemoryContent.ContentBytes, TEXT("%ld"), &inValue);
}
_stscanf (FunctionArguments, TEXT("%lx"), &value);
if (!(inValue & value)) {
return FALSE;
}
return TRUE;
}
BOOL
pMatches (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
if (!Data->ReturnString) {
return FALSE;
}
return (StringIMatch (FunctionArguments, Data->ReturnString));
}
BOOL
pSetPersistFlag (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
if (IsmDoesObjectExist (Data->ObjectTypeId, Data->ObjectName)) {
IsmMakePersistentObject (Data->ObjectTypeId, Data->ObjectName);
}
return TRUE;
}
BOOL
pNotEmpty (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
if (!Data->ReturnString) {
return FALSE;
}
return (Data->ReturnString[0] != 0);
}
BOOL
pVersion (
IN PCTSTR FunctionArguments,
IN PATTRIB_DATA Data
)
{
PCTSTR versionStr = NULL;
PCTSTR versionValue = NULL;
ATTRIB_DATA attribData;
BOOL result = FALSE;
versionStr = FunctionArguments;
if (!versionStr) {
return FALSE;
}
versionValue = GetEndOfString (FunctionArguments);
if (!versionValue) {
return FALSE;
}
versionValue ++;
if (!Data) {
return FALSE;
}
if (!Data->ReturnString) {
return FALSE;
}
ZeroMemory (&attribData, sizeof (ATTRIB_DATA));
attribData.ScriptSpecifiedType = TEXT("File");
attribData.ScriptSpecifiedObject = Data->ReturnString;
attribData.ApplicationName = Data->ApplicationName;
if (!AllocScriptType (&attribData)) {
return FALSE;
}
// let's persist the object in VCM mode so we can look at it later
if (g_VcmMode && attribData.ObjectName) {
if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
}
}
if (attribData.ObjectContent &&
attribData.ObjectContent->ContentInFile &&
attribData.ObjectContent->FileContent.ContentPath
) {
result = VrCheckFileVersion (attribData.ObjectContent->FileContent.ContentPath, versionStr, versionValue);
}
FreeScriptType (&attribData);
return result;
}