/* **============================================================================== ** ** Open Management Infrastructure (OMI) ** ** Copyright (c) Microsoft Corporation ** ** Licensed under the Apache License, Version 2.0 (the "License"); you may not ** use this file except in compliance with the License. You may obtain a copy ** of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABLITY OR NON-INFRINGEMENT. ** ** See the Apache 2 License for the specific language governing permissions ** and limitations under the License. ** **============================================================================== */ #include "filter.h" #include #include #include #include static const MI_Uint32 _MAGIC = 0xDEADBEEF; /* * Structure and handler for WQL queries. */ typedef struct _InstanceFilter_WQL { InstanceFilter filterBase; WQL* wql; } InstanceFilter_WQL; /* * Structure and handler for CQL queries. Right now, CQL queries are handled * exactly like WQL queries. */ typedef struct _InstanceFilter_CQL { InstanceFilter filterBase; WQL* wql; } InstanceFilter_CQL; /* * Additional derived structures for new filter types go here. */ /* * Internal InstanceFilterFT function definitions */ MI_Result _DoWqlEval( WQL* wql, const MI_Instance* instance, MI_Boolean* isMatch ) { int r = 0; if (NULL == wql) { *isMatch = MI_FALSE; return MI_RESULT_INVALID_PARAMETER; } r = WQL_Eval(wql, WQL_LookupInstanceProperty, (void*)instance); if (r == 0) { /* Instance matched the query */ *isMatch = MI_TRUE; } else { /* Mismatch */ *isMatch = MI_FALSE; } return MI_RESULT_OK; } MI_Result _FilterFunc_WQL( InstanceFilter* self, const MI_Instance* instance, MI_Boolean* isMatch ) { return _DoWqlEval(((InstanceFilter_WQL*)self)->wql, instance, isMatch); } MI_Result _FilterFunc_CQL( InstanceFilter* self, const MI_Instance* instance, MI_Boolean* isMatch) { return _DoWqlEval(((InstanceFilter_CQL*)self)->wql, instance, isMatch); } MI_Result _FilterFunc_UnFiltered( InstanceFilter* self, const MI_Instance* indication, MI_Boolean* isMatch) { /*This Unfilter filter doesn't have wql or WQL is NULL, so evaluate doesn't have any meaning*/ *isMatch = MI_FALSE; /*Return MI_RESULT_INVALID_PARAMETER and not MI_RESULT_NOT_SUPPORTED, just to follow MSDN documentation*/ return MI_RESULT_INVALID_PARAMETER; } void _Destroy_WQL( _In_ InstanceFilter* self ) { WQL_Delete( ((InstanceFilter_WQL*)self)->wql ); } void _Destroy_CQL( _In_ InstanceFilter* self ) { WQL_Delete( ((InstanceFilter_CQL*)self)->wql ); } void _Destroy_UnFiltered( _In_ InstanceFilter* self ) { /*This Unfilter filter doesn't have WQL or WQL is NULL so there is nothing to clean*/ } WQL* _GetWQL( _In_ InstanceFilter* self) { return ((InstanceFilter_WQL*)self)->wql; } WQL* _GetCQL( _In_ InstanceFilter* self) { return ((InstanceFilter_CQL*)self)->wql; } WQL* _GetUnFiltered( _In_ InstanceFilter* self) { /*This Unfilter filter doesn't have wql or WQL is NULL*/ return NULL; } InstanceFilterFT _filterFT_WQL = { _FilterFunc_WQL, _Destroy_WQL, _GetWQL }; InstanceFilterFT _filterFT_CQL = { _FilterFunc_CQL, _Destroy_CQL, _GetCQL }; InstanceFilterFT _filterFT_UnFiltered = { _FilterFunc_UnFiltered, _Destroy_UnFiltered, _GetUnFiltered }; MI_ConstString _GetQueryLanguage( _In_ Message* msg) { if(!msg) return NULL; if(msg->tag == EnumerateInstancesReqTag) { /* This is EnumerateInstancesReq */ EnumerateInstancesReq *enumMsg = (EnumerateInstancesReq*) msg; return enumMsg->queryLanguage; } else if(msg->tag == SubscribeReqTag) { /* This is SubscribeReq */ SubscribeReq *subscMsg = (SubscribeReq*) msg; return subscMsg->language; } else { trace_InstanceFilter_GetQueryLanguageUnsupportedMessageTag(); return NULL; } } MI_ConstString _GetQueryExpression( _In_ Message* msg) { if(!msg) return NULL; if(msg->tag == EnumerateInstancesReqTag) { /* This is EnumerateInstancesReq */ EnumerateInstancesReq *enumMsg = (EnumerateInstancesReq*) msg; return enumMsg->queryExpression; } else if(msg->tag == SubscribeReqTag) { /* This is SubscribeReq */ SubscribeReq *subscMsg = (SubscribeReq*) msg; return subscMsg->filter; } else { trace_InstanceFilter_GetQueryExpressionUnsupportedMessageTag(); return NULL; } } static MI_Result MI_CALL _Evaluate( _In_ const MI_Filter* self, _In_ const MI_Instance* instance, _Out_ MI_Boolean* result) { InstanceFilter* filter = (InstanceFilter*)self; if (!filter || filter->magic != _MAGIC || !instance || !result) { trace_InstanceFilter_EvaluateWithNullInput(); return MI_RESULT_INVALID_PARAMETER; } return filter->ft->Filter( filter, instance, result ); } static MI_Result MI_CALL _GetExpression( _In_ const MI_Filter* self, _Outptr_result_maybenull_z_ const MI_Char** queryLang, _Outptr_result_maybenull_z_ const MI_Char** queryExpr) { InstanceFilter* filter = (InstanceFilter*)self; if (!filter || filter->magic != _MAGIC) { trace_InstanceFilter_GetExpressionWithNullInput(); return MI_RESULT_INVALID_PARAMETER; } if (queryLang) { *queryLang = _GetQueryLanguage(filter->msg); } if (queryExpr) { *queryExpr = _GetQueryExpression(filter->msg); } return MI_RESULT_OK; } MI_FilterFT __mi_FilterFT = { _Evaluate, _GetExpression }; _Use_decl_annotations_ InstanceFilter* InstanceFilter_New( Message* msg) { MI_ConstString queryLanguage = _GetQueryLanguage(msg); MI_ConstString queryExpression = _GetQueryExpression(msg); if (queryLanguage == NULL || queryExpression == NULL) { trace_InstanceFilter_NewWithNullInput(); return NULL; } if (Tcscasecmp(queryLanguage, QUERY_LANGUAGE_WQL) == 0) { InstanceFilter_WQL* filter = (InstanceFilter_WQL*)Batch_GetClear(msg->batch, sizeof(InstanceFilter_WQL)); if(!filter) { trace_OutOfMemory(); return NULL; } /* Initialize "Base" struct */ filter->filterBase.base.ft = &__mi_FilterFT; filter->filterBase.magic = _MAGIC; filter->filterBase.msg = msg; filter->filterBase.ft = &_filterFT_WQL; /* Initialize WQL extension */ filter->wql = WQL_Parse(queryExpression, msg->batch, WQL_DIALECT_WQL); if (!filter->wql) { trace_InvalidQueryExpression(tcs(queryExpression)); /* filter will be freed when the Batch destructs */ return NULL; } return (InstanceFilter*)filter; } else if (Tcscasecmp(queryLanguage, QUERY_LANGUAGE_CQL) == 0) { InstanceFilter_CQL* filter = (InstanceFilter_CQL*)Batch_GetClear(msg->batch, sizeof(InstanceFilter_CQL)); if(!filter) { trace_OutOfMemory(); return NULL; } /* Initialize "Base" struct */ filter->filterBase.base.ft = &__mi_FilterFT; filter->filterBase.magic = _MAGIC; filter->filterBase.msg = msg; filter->filterBase.ft = &_filterFT_CQL; /* Initialize WQL extension since CQL covers the same type of supported * expressions. */ filter->wql = WQL_Parse(queryExpression, msg->batch, WQL_DIALECT_CQL); if (!filter->wql) { trace_InvalidQueryExpression(tcs(queryExpression)); /* filter will be freed when the Batch destructs */ return NULL; } return (InstanceFilter*)filter; } else { InstanceFilter* filter = (InstanceFilter*)Batch_GetClear(msg->batch, sizeof(InstanceFilter)); if(!filter) { trace_OutOfMemory(); return NULL; } /* Initialize "Base" struct */ filter->base.ft = &__mi_FilterFT; filter->magic = _MAGIC; filter->msg = msg; filter->ft = &_filterFT_UnFiltered; return filter; } } _Use_decl_annotations_ void InstanceFilter_Destroy( InstanceFilter* self ) { DEBUG_ASSERT( self ); /* Clean up specific to derived structs */ self->ft->Destroy( self ); /* Common clean up */ self->magic = 0xFFFFFFFF; } _Use_decl_annotations_ MI_Result InstanceFilter_Filter( InstanceFilter* self, const MI_Instance* indication, MI_Boolean* isMatch ) { DEBUG_ASSERT( self ); return self->ft->Filter( self, indication, isMatch ); } //_Use_decl_annotations_ WQL* InstanceFilter_GetWQL( _In_ InstanceFilter* self ) { if(!self) return NULL; return self->ft->GetWQL( self ); }