MI_Result Exec_WMIv2Provider()

in LCM/dsc/engine/ca/CAInfrastructure/CAEngine.c [1321:1631]


MI_Result Exec_WMIv2Provider(_In_ ProviderCallbackContext *provContext,
                             _In_ MI_Application *miApp,
                             _In_ MI_Session *miSession,
                             _In_ MI_Instance *instance,
                             _In_ const MI_Instance *regInstance,
                             _In_ MI_Uint32 flags,
                             _Inout_ MI_Uint32 *resultStatus,
                             _Inout_ MI_Boolean* canceled,
                             _Outptr_result_maybenull_ ResourceErrorList *resourceErrorList,
                             _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result r = MI_RESULT_OK;
    MI_Result result = MI_RESULT_OK;
    const MI_Char *provNamespace = NULL;
    MI_Operation operation = MI_OPERATION_NULL;
    MI_Instance *params = NULL;
    MI_Value value;
    MI_Value valueOperationOptions;
    MI_Boolean bTestResult = MI_TRUE;
    MI_Uint64 outProviderContext = 0;
    MI_Uint32 returnValue = 0;
    MI_OperationCallbacks callbacks = MI_OPERATIONCALLBACKS_NULL;
    MI_Real64 duration;
    MI_OperationOptions sessionOptions;
    const MI_Char * instanceNamespace;

    ptrdiff_t start,finish;

    //we don't have reginstance for meta configuration
    if (Tcscasecmp(instance->classDecl->name, METACONFIG_CLASSNAME) == 0)
    {
        instanceNamespace = MI_T("");
    }
    else
    {
        instanceNamespace = regInstance->nameSpace;
    }

    //Debug Log
    DSC_EventWriteEngineMethodParameters(__WFUNCTION__,
                                        instance->classDecl->name,
                                        provContext->resourceId,
                                        flags,
                                        provContext->lcmProviderContext->executionMode,
                                        instanceNamespace);
    DSC_EventWriteMessageExecutingWMI(instance->classDecl->name,provContext->resourceId);

    callbacks.writeMessage = DoWriteMessage;
    /* Sign up for progress only if we are in online mode*/
    if ((LCM_EXECUTIONMODE_ONLINE & provContext->lcmProviderContext->executionMode) == LCM_EXECUTIONMODE_ONLINE)
    {
        callbacks.writeProgress = DoWriteProgress;
    }

    /* Sign up for promptuser only if we are asked to do so.*/
    if ((LCM_SETFLAGS_ENABLEWHATIF & flags) == LCM_SETFLAGS_ENABLEWHATIF)
    {
        callbacks.promptUser = DoPromptUser;
    }

    callbacks.callbackContext = (void *)(provContext);

    if (extendedError == NULL)
    {
        return MI_RESULT_INVALID_PARAMETER;
    }
    *extendedError = NULL;  // Explicitly set *extendedError to NULL as _Outptr_ requires setting this at least once.

    *canceled = MI_FALSE;
    if (g_CancelConfiguration)
    {
        *canceled = MI_TRUE;
        return MI_RESULT_FAILED;
    }

    // If the input MI_Instance is a MSFT_LogResource then directly log the message using LCM log API's
    if (Tcscasecmp(instance->classDecl->name, LOGRESOURCE_CLASSNAME) == 0)
    {
        MI_Value value;
        const MI_Char *message = NULL;
        //Start timer for Set
        start=CPU_GetTimeStamp();

        //Starting Test
        SetMessageInContext(ID_OUTPUT_OPERATION_START,ID_OUTPUT_ITEM_TEST,provContext->lcmProviderContext);
        LogCAMessage(provContext->lcmProviderContext, ID_OUTPUT_EMPTYSTRING, provContext->resourceId);

        r = MI_Instance_GetElement(instance, LOGRESOURCE_MESSAGEPROPERTYNAME, &value, NULL, NULL, NULL);
        if (r != MI_RESULT_OK)
        {
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_LOGRESOURCE_FAILED);
        }

        message = value.string;
        //Stop the timer for test
        finish=CPU_GetTimeStamp();
        duration = (MI_Real64)(finish- start) / TIME_PER_SECONND;
        SetMessageInContext(ID_OUTPUT_OPERATION_END,ID_OUTPUT_ITEM_TEST,provContext->lcmProviderContext);
        LogCAMessageTime(provContext->lcmProviderContext, ID_CA_TEST_TIMEMESSAGE, (const MI_Real64)duration,provContext->resourceId);

        if (!(flags & LCM_EXECUTE_TESTONLY))
        {
            //Start timer for Set
            start=CPU_GetTimeStamp();
            SetMessageInContext(ID_OUTPUT_OPERATION_START,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
            LogCAMessage(provContext->lcmProviderContext, ID_OUTPUT_EMPTYSTRING, provContext->resourceId);

            LCM_WriteMessageFromProvider(provContext->lcmProviderContext, provContext->resourceId, MI_WRITEMESSAGE_CHANNEL_VERBOSE, message);
            //Stop the timer for set
            finish=CPU_GetTimeStamp();
            duration = (MI_Real64)(finish- start) / TIME_PER_SECONND;
            SetMessageInContext(ID_OUTPUT_OPERATION_END,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
            LogCAMessageTime(provContext->lcmProviderContext, ID_CA_SET_TIMEMESSAGE, (const MI_Real64)duration,provContext->resourceId);
        }
    }
    // If the input is a meta configuration then invoke LCM's API directly
    else if (Tcscasecmp(instance->classDecl->name, METACONFIG_CLASSNAME) == 0 && !( flags & LCM_EXECUTE_TESTONLY ))
    {
        //Start timer for Set
        start=CPU_GetTimeStamp();
        //meta configuration is always explicitly get invoked so no need to test before set.
        SetMessageInContext(ID_OUTPUT_OPERATION_START,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
        LogCAMessage(provContext->lcmProviderContext, ID_OUTPUT_EMPTYSTRING, provContext->resourceId);
        r = SetMetaConfig(instance, extendedError);
         //Stop the timer for set
        finish=CPU_GetTimeStamp();
        duration = (MI_Real64)(finish- start) / TIME_PER_SECONND;
        SetMessageInContext(ID_OUTPUT_OPERATION_END,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
        LogCAMessageTime(provContext->lcmProviderContext, ID_CA_SET_TIMEMESSAGE, (const MI_Real64)duration,provContext->resourceId);

        if(r == MI_RESULT_OK)
        {
            result = RegisterStandardTasks(extendedError);
        }
    }
    else
    {
        /*Get target namespace*/
        r = DSC_MI_Instance_GetElement(regInstance, MSFT_CimConfigurationProviderRegistration_Namespace, &value, NULL, NULL, NULL);
        if (r != MI_RESULT_OK)
        {
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_NAMESPACE_FAILED);
        }

        provNamespace = value.string;

        /*Set input parameters*/
        r = DSC_MI_Application_NewInstance(miApp, MI_T("__Parameters"), NULL, &params);
        if (r != MI_RESULT_OK)
        {
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_NEWAPPLICATIONINSTANCE_FAILED);
        }

        value.instance = instance;
        r = DSC_MI_Instance_AddElement(params, OMI_BaseResource_Method_InputResource, &value, MI_INSTANCE, 0 );
        if (r != MI_RESULT_OK)
        {
            MI_Instance_Delete(params);
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_ADDELEM_FAILED);
        }
        r = MI_Application_NewOperationOptions(miApp, MI_FALSE, &sessionOptions);
        if( r != MI_RESULT_OK )
        {
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_NEWOPERATIONOPTIONS_FAILED);
        }
        valueOperationOptions.string=g_ConfigurationDetails.jobGuidString;
        r =MI_OperationOptions_SetCustomOption(&sessionOptions,DSC_JOBIDSTRING,MI_STRING,&valueOperationOptions,MI_FALSE);
        if( r != MI_RESULT_OK)
        {
            MI_OperationOptions_Delete(&sessionOptions);
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_SETCUSTOMOPTION_FAILED);
        }
        if(r!=MI_RESULT_OK)
        {
            //INCHTODO: Say setcustomoptionfailed
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_ADDELEM_FAILED);
        }
        /* Perform Test*/
        //Start timer for test
        start=CPU_GetTimeStamp();
        DSC_EventWriteMessageInvokingSession(provNamespace,instance->classDecl->name,OMI_BaseResource_TestMethodName);
        SetMessageInContext(ID_OUTPUT_OPERATION_START,ID_OUTPUT_ITEM_TEST,provContext->lcmProviderContext);
        LogCAMessage(provContext->lcmProviderContext, ID_OUTPUT_EMPTYSTRING, provContext->resourceId);

        RecursiveLock_Acquire(&g_cs_CurrentWmiv2Operation);
        MI_Session_Invoke(miSession, 0, &sessionOptions, provNamespace,
                             instance->classDecl->name, OMI_BaseResource_TestMethodName,
                             NULL, params, &callbacks,&operation);
        g_CurrentWmiv2Operation = &operation;
        RecursiveLock_Release(&g_cs_CurrentWmiv2Operation);

        r = GetTestMethodResult(&operation, &bTestResult, &outProviderContext, extendedError);

        RecursiveLock_Acquire(&g_cs_CurrentWmiv2Operation);
        g_CurrentWmiv2Operation = NULL;
        MI_Operation_Close(&operation);
        RecursiveLock_Release(&g_cs_CurrentWmiv2Operation);
        if (r != MI_RESULT_OK)
        {
            MI_Instance_Delete(params);
            MI_OperationOptions_Delete(&sessionOptions);
            AddToResourceErrorList(resourceErrorList, provContext->resourceId);
            Destroy_StatusReport_RNIDS(g_rnids);
            g_rnids = Construct_StatusReport_RNIDS(GetSourceInfo(instance), GetModuleName(instance), "0", provContext->resourceId, "0", instance->classDecl->name, GetModuleVersion(instance), "False", provContext->resourceId, "", "False");
            return r;
        }

        //Stop the timer for test
        finish=CPU_GetTimeStamp();
        duration = (MI_Real64)(finish- start) / TIME_PER_SECONND;
        SetMessageInContext(ID_OUTPUT_OPERATION_END,ID_OUTPUT_ITEM_TEST,provContext->lcmProviderContext);
        LogCAMessageTime(provContext->lcmProviderContext, ID_CA_TEST_TIMEMESSAGE, (const MI_Real64)duration,provContext->resourceId);

        /* Skip rest of the operation if we were asked just to test.*/
        if (flags & LCM_EXECUTE_TESTONLY)
        {
            if(bTestResult == MI_TRUE)
            {
                *resultStatus = 1;
            }
            else
            {
                *resultStatus = 0;
                Destroy_StatusReport_RNIDS(g_rnids);
                g_rnids = Construct_StatusReport_RNIDS(GetSourceInfo(instance), GetModuleName(instance), "0", provContext->resourceId, "0", instance->classDecl->name, GetModuleVersion(instance), "False", provContext->resourceId, "", "False");
            }

            MI_Instance_Delete(params);
            MI_OperationOptions_Delete(&sessionOptions);
            return MI_RESULT_OK;
        }

        /* Perform Set if value returned is FALSE*/
        if( bTestResult == MI_TRUE)
        {
            SetMessageInContext(ID_OUTPUT_OPERATION_SKIP,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
            LogCAMessage(provContext->lcmProviderContext, ID_OUTPUT_EMPTYSTRING, provContext->resourceId);
            MI_Instance_Delete(params);
            MI_OperationOptions_Delete(&sessionOptions);
            return MI_RESULT_OK;
        }

        if (g_CancelConfiguration)
        {
            *canceled = MI_TRUE;
            MI_Instance_Delete(params);
            MI_OperationOptions_Delete(&sessionOptions);
            return MI_RESULT_FAILED;
        }

        /* Add outProviderContext to the params*/
        value.uint64 = outProviderContext;
        r = DSC_MI_Instance_AddElement(params, OMI_BaseResource_Method_ProviderContext, &value, MI_UINT64, 0 );
        if (r != MI_RESULT_OK)
        {
            MI_Instance_Delete(params);
            MI_OperationOptions_Delete(&sessionOptions);
            return GetCimMIError(r, extendedError,ID_CAINFRA_GET_ADDELEM_FAILED);
        }

        /* Perform Set*/
        //Start timer for set
        start=CPU_GetTimeStamp();
        SetMessageInContext(ID_OUTPUT_OPERATION_START,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
        LogCAMessage(provContext->lcmProviderContext, ID_OUTPUT_EMPTYSTRING, provContext->resourceId);
        DSC_EventWriteMessageInvokingSession(provNamespace,instance->classDecl->name,OMI_BaseResource_SetMethodName);

        RecursiveLock_Acquire(&g_cs_CurrentWmiv2Operation);
        memset(&operation, 0, sizeof(MI_Operation));
        MI_Session_Invoke(miSession, 0, &sessionOptions, provNamespace,
                             instance->classDecl->name, OMI_BaseResource_SetMethodName,
                             NULL, params, &callbacks,&operation);

        g_CurrentWmiv2Operation = &operation;
        RecursiveLock_Release(&g_cs_CurrentWmiv2Operation);

        r = GetSetMethodResult(&operation, &returnValue, provContext->resourceId, extendedError);
        MI_Instance_Delete(params);

        RecursiveLock_Acquire(&g_cs_CurrentWmiv2Operation);
        g_CurrentWmiv2Operation = NULL;
        MI_Operation_Close(&operation);
        RecursiveLock_Release(&g_cs_CurrentWmiv2Operation);

        if (r != MI_RESULT_OK)
        {
            MI_OperationOptions_Delete(&sessionOptions);
            AddToResourceErrorList(resourceErrorList, provContext->resourceId);
            Destroy_StatusReport_RNIDS(g_rnids);
            g_rnids = Construct_StatusReport_RNIDS(GetSourceInfo(instance), GetModuleName(instance), "0", provContext->resourceId, NULL, instance->classDecl->name, GetModuleVersion(instance), "False", provContext->resourceId, "", "False");
            return r;
        }

        *resultStatus = returnValue;
        if (returnValue != MI_TRUE)
        {
            Destroy_StatusReport_RNIDS(g_rnids);
            g_rnids = Construct_StatusReport_RNIDS(GetSourceInfo(instance), GetModuleName(instance), "0", provContext->resourceId, NULL, instance->classDecl->name, GetModuleVersion(instance), "False", provContext->resourceId, "", "False");
        }
        //Stop the timer for set
        finish=CPU_GetTimeStamp();
        duration = (MI_Real64)(finish- start) / TIME_PER_SECONND;
        SetMessageInContext(ID_OUTPUT_OPERATION_END,ID_OUTPUT_ITEM_SET,provContext->lcmProviderContext);
        LogCAMessageTime(provContext->lcmProviderContext, ID_CA_SET_TIMEMESSAGE, (const MI_Real64)duration,provContext->resourceId);
        MI_OperationOptions_Delete(&sessionOptions);
    }

    //Debug Log
    DSC_EventWriteMethodEnd(__WFUNCTION__);
    return r;
}