MI_Result SetResourcesInOrder()

in LCM/dsc/engine/ca/CAInfrastructure/CAEngine.c [617:877]


MI_Result SetResourcesInOrder(_In_ LCMProviderContext *lcmContext,
                              _In_ ModuleManager *moduleManager,
                              _In_ MI_InstanceA * instanceA,
                              _In_ MI_Session *miSession,
                              _In_ ExecutionOrderContainer *executionOrder,
                              _In_ MI_Uint32 flags,
                              _In_ MI_Instance *documentIns,
                              _Inout_ MI_Uint32 *resultStatus,
                              _Outptr_result_maybenull_ ResourceErrorList *resourceErrorList,
                              _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Uint32 xCount = 0;
    MI_Uint32 index = 0;
    MI_Instance *filteredInstance = NULL;
    MI_Instance *regInstance = NULL;
    ModuleLoaderObject *moduleLoader = NULL;
    MI_Result r = MI_RESULT_OK;
    MI_Result finalr = MI_RESULT_OK;
    ProviderCallbackContext providerContext = {0};
    MI_Char *certificateid = NULL;
    MI_Boolean bEncryptionEnabled = MI_FALSE;
    MI_Boolean canceled;
    DSC_EventWriteMessageSettingResourcesOrder(executionOrder->executionListSize);
    moduleLoader = (ModuleLoaderObject*) moduleManager->reserved2;

    if (extendedError == NULL)
    {
        return MI_RESULT_INVALID_PARAMETER;
    }

    *extendedError = NULL;  // Explicitly set *extendedError to NULL as _Outptr_ requires setting this at least once.

    providerContext.lcmProviderContext = lcmContext;

    r = GetDocumentEncryptionSetting(documentIns, &bEncryptionEnabled, &certificateid, extendedError);
    if (r != MI_RESULT_OK)
    {
        return r;
    }

    // Instantiate native resource manager, responsible to load/unload native resource provider.
    r = NativeResourceManager_New(&providerContext, &(providerContext.nativeResourceManager));
    if( r != MI_RESULT_OK)
    {
        if(certificateid != NULL)
        {
            DSC_free(certificateid);
            certificateid = NULL;
        }
        return r;
    }

    /*Assuming the dependencies is implicit (the order in which instances are specified in the list). */
    /*Get the instance compatible with the provider.*/
    for (xCount = 0 ; xCount < executionOrder->executionListSize ; xCount++)
    {
        MI_Boolean bDependentFailed = MI_FALSE;
        if (g_CancelConfiguration == TRUE)
        {
            if(certificateid != NULL)
            {
                DSC_free(certificateid);
                certificateid = NULL;
            }
            DSC_EventWriteConfigurationCancelledInTheMiddle(executionOrder->executionListSize, executionOrder->executionListSize - xCount);
            return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_CA_CANCEL_CONFIGURATION);
        }

        index = executionOrder->ExecutionList[xCount].resourceIndex;
        r = DependentResourceFailed(index, executionOrder, instanceA, &bDependentFailed, extendedError);
        if( r != MI_RESULT_OK )
        {
            if(certificateid != NULL)
            {
                DSC_free(certificateid);
                certificateid = NULL;
            }
            return r;
        }
        if( bDependentFailed == MI_TRUE )
        {
            // mark it as failed and continue;
            executionOrder->ExecutionList[xCount].resourceStatus = ResourceProcessedAndFailed;
            continue;

        }
        providerContext.resourceId = GetResourceId(instanceA->data[index]);

        //metaconfig doesn't have resourceID
        if(providerContext.resourceId == NULL &&
            Tcscasecmp(instanceA->data[index]->classDecl->name, METACONFIG_CLASSNAME) == 0)
        {
            providerContext.resourceId = METACONFIG_CLASSNAME;
        }

        if ( flags & LCM_EXECUTE_TESTONLY )
        {
            LogCAProgress(lcmContext,MI_T("Test"),MI_T("Testing Configuration"), xCount, instanceA->size);
        }
        else
        {
            LogCAProgress(lcmContext,MI_T("Set"),MI_T("Applying Configuration"), xCount, instanceA->size);
        }
        SetMessageInContext(ID_OUTPUT_OPERATION_START,ID_OUTPUT_ITEM_RESOURCE,lcmContext);
        LogCAMessage(lcmContext, ID_OUTPUT_EMPTYSTRING, providerContext.resourceId);

        if (index >= instanceA->size || NitsShouldFault(NitsHere(), NitsAutomatic))
        {
            if(certificateid != NULL)
            {
                DSC_free(certificateid);
                certificateid = NULL;
            }

            return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_CAINFRA_DEPENDCYRESOLVER_OUTOFBOUNDS);
        }

        DSC_EventWriteMessageRegisteringModule(instanceA->data[index]->classDecl->name);

        /* Get Registration Instance to find registration information.*/
        r = moduleManager->ft->GetRegistrationInstance(moduleManager, instanceA->data[index]->classDecl->name, (const MI_Instance **)&regInstance, extendedError);
        if (r != MI_RESULT_OK)
        {
            if(certificateid != NULL)
            {
                DSC_free(certificateid);
                certificateid = NULL;
            }
            return r;
        }

        /*Get provider compatible instance*/
        r = moduleManager->ft->GetProviderCompatibleInstance(moduleManager, instanceA->data[index], &filteredInstance, extendedError);
        if (r != MI_RESULT_OK)
        {
            if(certificateid != NULL)
            {
                DSC_free(certificateid);
                certificateid = NULL;
            }
            return r;
        }

        /* Move the resource to desired state.*/
        canceled = MI_FALSE;
        r = MoveToDesiredState(&providerContext, moduleLoader->application, miSession, filteredInstance, regInstance, flags, resultStatus, &canceled, resourceErrorList, extendedError);
        DSC_LOG_INFO("MoveToDesiredState = %d, *resultStatus = %d\n", r, *resultStatus);
        MI_Instance_Delete(filteredInstance);
        filteredInstance = NULL;

        if (r != MI_RESULT_OK)
        {
            DSC_LOG_INFO("SetResourcesInOrder failed in MoveToDesiredState\n");
            // Failure case, update the resource status
            Intlstr intlstr = Intlstr_Null;
            executionOrder->ExecutionList[xCount].resourceStatus = ResourceProcessedAndFailed;
            if (canceled)
            {
                if(certificateid != NULL)
                {
                    DSC_free(certificateid);
                    certificateid = NULL;
                }

                DSC_EventWriteConfigurationCancelledInTheMiddle(executionOrder->executionListSize, executionOrder->executionListSize - xCount);
                return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_CA_CANCEL_CONFIGURATION);
            }
            if( flags & LCM_EXECUTE_TESTONLY)
            {
                if(certificateid != NULL)
                {
                    DSC_free(certificateid);
                    certificateid = NULL;
                }

                return r;
            }

            GetResourceString(ID_LCMHELPER_SENDCONFIGAPPLY_ERROR, &intlstr);

            DSC_EventWriteLCMSendConfigurationError(CA_ACTIVITY_NAME,
                r,
                intlstr.str,
                providerContext.resourceId,
                GetSourceInfo(instanceA->data[index]),
                (MI_Char*)GetErrorDetail(*extendedError));

            if( intlstr.str)
                Intlstr_Free(intlstr);

            //send the error to WriteError stream.
            LCM_WriteError( lcmContext, *extendedError);

            // we need to continue moving other resources to their desired state.
            finalr = r;
            DSC_LOG_INFO("SetResourcesInOrder finalr = %d\n", finalr);
            if (extendedError)
            {
                if(certificateid != NULL)
                {
                    DSC_free(certificateid);
                    certificateid = NULL;
                }

                MI_Instance_Delete(*extendedError);
                *extendedError = NULL;
            }

            continue;
        }
        // Success Case 
        DSC_LOG_INFO("SetResourcesInOrder succeeded in MoveToDesiredState\n");

        if (resultStatus != NULL && *resultStatus == MI_TRUE)
        {
            Destroy_StatusReport_RNIDS(g_rnids);
            g_rnids = NULL;
        }

        executionOrder->ExecutionList[xCount].resourceStatus = ResourceProcessedAndSucceeded;
        r = finalr;
        SetMessageInContext(ID_OUTPUT_OPERATION_END,ID_OUTPUT_ITEM_RESOURCE,lcmContext);
        LogCAMessage(lcmContext, ID_OUTPUT_EMPTYSTRING, providerContext.resourceId);

        // if resultStatus is 1 then they are in their current state otherwise not.
        if (flags & LCM_EXECUTE_TESTONLY)
        {
            if (*resultStatus == MI_FALSE)
            {
                if(certificateid != NULL)
                {
                    DSC_free(certificateid);
                    certificateid = NULL;
                }

                return r;
            }
        }
        else if (DSC_RESTART_SYSTEM_FLAG & *resultStatus && r == MI_RESULT_OK)
        {
            if(certificateid != NULL)
            {
                DSC_free(certificateid);
                certificateid = NULL;
            }

            return MI_RESULT_OK;
        }
    }

    if(certificateid != NULL)
    {
        DSC_free(certificateid);
        certificateid = NULL;
    }

    // Ignore this call and do not delete the native resource manager instance. It will be cleaned up when the host process goes away.
    // NativeResourceManager_Delete(providerContext.nativeResourceManager);

    return finalr;
}