/* **============================================================================== ** ** 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 "context.h" #include #include static const MI_Uint32 _MAGIC = 0x35eb3d3b; static MI_Result _ProcessResult( MI_Context* self_, MI_Result result, const MI_Char* message, const MI_Instance* error) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC) return MI_RESULT_INVALID_PARAMETER; LOGD_CHAR(("post result from provider, %d", (int)result)); /* If no instances matched during GetInstance over EnumerateInstance */ if (self->instanceName && !self->matchedInstanceName) { if (result == MI_RESULT_OK) result = MI_RESULT_NOT_FOUND; } message = message; error = error; if (self->request && !self->cancelled) { PostResultMsg* resp = PostResultMsg_New( self->request ? self->request->msgID : 0 ); if (!resp) return MI_RESULT_FAILED; resp->result = result; Message_SetRequest(&resp->base,self->request); (*self->request->callback)(&resp->base, self->request->callbackData); PostResultMsg_Release(resp); } if (self->result) *self->result = result; /* destory context */ Context_Destroy(self); return MI_RESULT_OK; } static MI_Boolean _FilterProperty(const MI_Char* name, void *data) { WQL* wql = (WQL*)data; if (WQL_ContainsProperty(wql, name)) return MI_FALSE; else return MI_TRUE; } static MI_Result _PostInstanceToCallback( Context* self, const MI_Instance* instance) { PostInstanceMsg* resp = PostInstanceMsg_New(self->request->msgID); if (!resp) return MI_RESULT_FAILED; if (self->request->flags & WSMANFlag) { const MI_ClassDecl* castToClassDecl = 0; /* Enumerate response with 'base-properties-only' option may require instance conversion */ if (EnumerateInstancesReqTag == self->request->tag) { EnumerateInstancesReq* req = (EnumerateInstancesReq*)self->request; if (req->requestClassName) { castToClassDecl = instance->classDecl; while (castToClassDecl && Zcasecmp(req->requestClassName, castToClassDecl->name) != 0) { castToClassDecl = castToClassDecl->superClassDecl; } } } { EnumerateInstancesReq* req = NULL; if (EnumerateInstancesReqTag == self->request->tag) req = (EnumerateInstancesReq*)self->request; if (req && req->wql) { WSBuf_InstanceToBuf( instance, _FilterProperty, req->wql, castToClassDecl, resp->base.batch, self->request->flags, &resp->packedInstancePtr, &resp->packedInstanceSize); } else { WSBuf_InstanceToBuf( instance, NULL, /* filterProperty */ NULL, /* filterPropertyData */ castToClassDecl, resp->base.batch, self->request->flags, &resp->packedInstancePtr, &resp->packedInstanceSize); } } resp->base.flags |= self->request->flags; } else { EnumerateInstancesReq* req = NULL; if (EnumerateInstancesReqTag == self->request->tag) req = (EnumerateInstancesReq*)self->request; if (req && req->wql) { InstanceToBatch(instance, _FilterProperty, req->wql, resp->base.batch, &resp->packedInstancePtr, &resp->packedInstanceSize); } else { InstanceToBatch(instance, NULL, NULL, resp->base.batch, &resp->packedInstancePtr, &resp->packedInstanceSize); } resp->base.flags |= BinaryProtocolFlag; } /* count message in for back-pressure feature (only Instances) */ if (self->provider) Provider_NewInstanceCreated(self->provider, &resp->base); Message_SetRequest(&resp->base,self->request); (*self->request->callback)(&resp->base, self->request->callbackData); PostInstanceMsg_Release(resp); return MI_RESULT_OK; } /* successfully received instance from 'gi' - call invoke with this instance now */ static void _CallInvoke( Context* self, const MI_Instance* instance) { Context* ctx = (Context*)Batch_GetClear(self->request->batch, sizeof(Context));; Context_Init(ctx, self->provider); ctx->request = self->request; /* message will be freed in context release*/ Message_AddRef(ctx->request); /* disregard all other messages for this context */ self->cancelled = MI_TRUE; /* ATTN! clone instance, since invoke can overlive instance (if it's async)!!! */ (*self->md->function)(self->prov_self, &ctx->base, __nameSpace, __className, __methodName, instance, self->instParams); } static MI_Result MI_CALL _PostResult( MI_Context* self_, MI_Result result) { return _ProcessResult(self_, result, 0, 0); } static MI_Result MI_CALL _PostResultWithMessage( MI_Context* self_, MI_Result result, const MI_Char* message) { return _ProcessResult(self_, result, message, 0); } static MI_Result MI_CALL _PostResultWithError( _In_ MI_Context* self_, MI_Result result, _In_ const MI_Instance* error) { return _ProcessResult(self_, result, 0, error); } static MI_Result MI_CALL _PostInstance( MI_Context* self_, const MI_Instance* instance) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !instance) return MI_RESULT_INVALID_PARAMETER; if (self->request && !self->cancelled) { if (self->instanceName == NULL) { if (CTX_TYPE_INVOKE_WITH_INSTANCE == self->chainType) { _CallInvoke(self, instance); return MI_RESULT_OK; } else if (EnumerateInstancesReqTag == self->request->tag) { EnumerateInstancesReq* req = (EnumerateInstancesReq*)self->request; if (req->wql) { int r; r = WQL_Eval(req->wql, WQL_LookupInstanceProperty, (void*)instance); if (r == 0) { /* Instance matched the query */ return _PostInstanceToCallback(self, instance); } else { /* Mismatch or failure */ return MI_RESULT_OK; } } } return _PostInstanceToCallback(self, instance); } else if (Instance_MatchKeys(instance, self->instanceName)) { /* Handle GetInstance through EnumerateInstances */ if (!self->matchedInstanceName) { self->matchedInstanceName = MI_TRUE; return _PostInstanceToCallback(self, instance); } } } return MI_RESULT_OK; } static MI_Result MI_CALL _ConstructInstance( MI_Context* self_, const MI_ClassDecl* classDecl, MI_Instance* instance) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !instance || !classDecl) return MI_RESULT_INVALID_PARAMETER; return Instance_Construct(instance, classDecl, self->request->batch); } static MI_Result MI_CALL _ConstructParameters( MI_Context* self_, const MI_MethodDecl* methodDecl, MI_Instance* instance) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !instance || !methodDecl) return MI_RESULT_INVALID_PARAMETER; return Parameters_Init(instance, methodDecl, self->request->batch); } static MI_Result MI_CALL _NewInstance( MI_Context* self_, const MI_ClassDecl* classDecl, MI_Instance** instance) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !classDecl || !instance) return MI_RESULT_INVALID_PARAMETER; return Instance_New(instance, classDecl, self->request->batch); } static MI_Result MI_CALL _NewDynamicInstance( MI_Context* self_, const MI_Char* className, MI_Uint32 flags, MI_Instance** instance) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !className || !instance) return MI_RESULT_INVALID_PARAMETER; return Instance_NewDynamic(instance, className, flags, self->request->batch); } static MI_Result MI_CALL _NewParameters( MI_Context* self_, const MI_MethodDecl* methodDecl, MI_Instance** instance) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !methodDecl || !instance) return MI_RESULT_INVALID_PARAMETER; return Parameters_New(instance, methodDecl, self->request->batch); } static MI_Result MI_CALL _Canceled( const MI_Context* self_, MI_Boolean* flag) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !flag) return MI_RESULT_INVALID_PARAMETER; *flag = self->cancelled; return MI_RESULT_OK; } static MI_Result MI_CALL _PostIndication( MI_Context* context, const MI_Instance* indication, MI_Uint32 subscriptionIDCount, const MI_Char* bookmark) { /* ATTN: just use _PostInstance() for now */ MI_UNUSED(subscriptionIDCount); MI_UNUSED(bookmark); return _PostInstance(context, indication); } static MI_Result MI_CALL _GetLocale( const MI_Context* context, MI_LocaleType localeType, MI_Char locale[MI_MAX_LOCALE_SIZE]) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result MI_CALL _RegisterCancel( MI_Context* context, MI_CancelCallback callback, void* callbackData) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result MI_CALL _RequestUnload( MI_Context* self_) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !self->provider) return MI_RESULT_INVALID_PARAMETER; Provider_SetRefuseUnloadFlag(self->provider, MI_FALSE); return MI_RESULT_OK; } static MI_Result MI_CALL _RefuseUnload( MI_Context* self_) { Context* self = (Context*)self_; if (!self || self->magic != _MAGIC || !self->provider) return MI_RESULT_INVALID_PARAMETER; Provider_SetRefuseUnloadFlag(self->provider, MI_TRUE); return MI_RESULT_OK; } static MI_Result _GetLocalSession( _In_ const MI_Context* context, _Out_ MI_Session* session) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _SetStringOption( _In_ MI_Context* context, _In_z_ const MI_Char* name, _In_z_ const MI_Char* value) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _GetStringOption( _In_ MI_Context* context, _In_z_ const MI_Char* name, _Outptr_result_z_ const MI_Char** value) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _GetNumberOption( _In_ MI_Context* context, _In_z_ const MI_Char *name, _Out_opt_ MI_Uint32* value) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _GetCustomOption( _In_ MI_Context* context, _In_z_ const MI_Char* name, _Out_opt_ MI_Type* valueType, _Out_opt_ MI_Value* value) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _GetCustomOptionCount( _In_ MI_Context* context, _Out_opt_ MI_Uint32* count) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _GetCustomOptionAt( _In_ MI_Context* context, _In_ MI_Uint32 index, _Outptr_opt_result_maybenull_z_ const MI_Char** name, _Out_opt_ MI_Type* valueType, _Out_opt_ MI_Value* value) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _WriteMessage( _In_ MI_Context* context, MI_Uint32 channel, _In_z_ const MI_Char* message) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _WriteProgress( _In_ MI_Context* context, _In_z_ const MI_Char* activity, _In_z_ const MI_Char* currentOperation, _In_z_ const MI_Char* statusDescription, MI_Uint32 percentComplete, MI_Uint32 secondsRemaining) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _WriteStreamParameter( _In_ MI_Context* context, _In_z_ const MI_Char* name, _In_ const MI_Value* value, _In_ MI_Type type, _In_ MI_Uint32 flags) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _WriteCimError( _In_ MI_Context* context, _In_ const MI_Instance *error, _Out_ MI_Boolean *flag) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _PromptUser( _In_ MI_Context* context, _In_z_ const MI_Char* message, MI_PromptType promptType, _Out_ MI_Boolean* result) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _ShouldProcess( _In_ MI_Context* context, _In_z_ const MI_Char* target, _In_z_ const MI_Char* action, _Out_ MI_Boolean* result) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _ShouldContinue( _In_ MI_Context* context, _In_z_ const MI_Char* message, _Out_ MI_Boolean* result) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _PostError( _In_ MI_Context* context, MI_Uint32 resultCode, _In_z_ const MI_Char* resultType, _In_z_ const MI_Char* errorMessage) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _PostCimError( _In_ MI_Context* context, _In_ const MI_Instance *error) { return MI_RESULT_NOT_SUPPORTED; } static MI_Result _WriteError( _In_ MI_Context* context, MI_Uint32 resultCode, _In_z_ const MI_Char* resultType, _In_z_ const MI_Char* errorMessage, _Out_ MI_Boolean *flag) { return MI_RESULT_NOT_SUPPORTED; } MI_ContextFT __mi_contextFT = { _PostResult, _PostResultWithMessage, _PostResultWithError, _PostInstance, _PostIndication, _ConstructInstance, _ConstructParameters, _NewInstance, _NewDynamicInstance, _NewParameters, _Canceled, _GetLocale, _RegisterCancel, _RequestUnload, _RefuseUnload, _GetLocalSession, _SetStringOption, _GetStringOption, _GetNumberOption, _GetCustomOption, _GetCustomOptionCount, _GetCustomOptionAt, _WriteMessage, _WriteProgress, _WriteStreamParameter, _WriteCimError, _PromptUser, _ShouldProcess, _ShouldContinue, _PostError, _PostCimError, _WriteError, }; void Context_Init( Context* self, Provider* provider) { memset(self, 0, sizeof(Context)); self->base.ft = &__mi_contextFT; self->magic = _MAGIC; self->provider = provider; Provider_Addref(self->provider); } void Context_Destroy( Context* self) { Message* req = self ? self->request : 0; if (self) Provider_Release(self->provider); memset(self, -1, sizeof(Context)); /* Context typ[ically allocated from message's batch so it may be freed right inside 'Release' call */ if (req) Message_Release(req); }