MI_Result MI_CALL LCM_Pull_Execute()

in LCM/dsc/engine/ConfigurationManager/LocalConfigManagerHelper.c [6033:6250]


MI_Result MI_CALL LCM_Pull_Execute(
        _In_ LCMProviderContext *lcmContext,
        _In_ MI_Instance *metaConfigInstance,
        _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
        //get the meta config instance.
        MI_Char* resultStatus = NULL;
        MI_Result result = MI_RESULT_OK;
        ModuleManager *moduleManager = NULL;
        MI_Boolean bComplianceStatus;
        MI_Uint32 getActionStatusCode;
        MI_Uint32 lcmStatusCode;
        MI_Uint32 resultExecutionStatus = 0;
        MI_Char *checkSumValue = NULL;
        MI_Char *partialConfigName = NULL;
        MI_InstanceA partialConfigurations = { 0 };
        MI_Boolean complianceStatus = MI_FALSE;
        MI_Boolean bFullConfiguration = MI_FALSE;
        MI_Boolean bGotNewConfiguration = MI_FALSE;
        MI_Result updateResult = MI_RESULT_OK;
        MI_Instance* updateErrorDetails = NULL;
        MI_Uint32 xCount;
        MI_Uint32 numModulesInstalled = 0;
        int retval;
        OverAllGetActionResponse* serverAssignedConfigurations = NULL;


        SetLCMProviderContext( lcmContext, (LCM_EXECUTIONMODE_OFFLINE | LCM_EXECUTIONMODE_ONLINE) , NULL);
        result = InitializeModuleManager(0, cimErrorDetails, &moduleManager);
        if (result != MI_RESULT_OK)
        {
                return result;
        }

        if (moduleManager == NULL)
        {
                return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_ENGINEHELPER_MEMORY_ERROR);
        }

        result = RegisterWithPullServers(lcmContext, metaConfigInstance, cimErrorDetails);
        if (result != MI_RESULT_OK)
        {
            moduleManager->ft->Close(moduleManager, NULL);
            return result;
        }

        GetLatestStatus(&bComplianceStatus, &getActionStatusCode, &lcmStatusCode);

        /* Now we need to figure out if we have to download partial configurations.*/
        // r = GetPartialConfigurationPath(value.string, configFileName, cimErrorDetails);
        if (ShouldUsePartialConfigurations(metaConfigInstance, MI_FALSE)) //Don't need to check if there are files in the partial config directory
        {
                result = GetPartialConfigurations((MI_Instance*) metaConfigInstance, &partialConfigurations, cimErrorDetails);
                if (result != MI_RESULT_OK)
                {
                        moduleManager->ft->Close(moduleManager, NULL);
                        return result;
                }
        }
        else
        {
                // We have exactly 1 element to process, GetPartialConfigurationName handles NULL and return
                // appropriately for full configurations for rest of the system to work properly
                partialConfigurations.size = 1;
                bFullConfiguration = MI_TRUE;
        }
        for (xCount = 0; xCount < partialConfigurations.size && result == MI_RESULT_OK; xCount++)
        {
            result = GetPartialConfigurationName(bFullConfiguration ? NULL : partialConfigurations.data[xCount], (const MI_Char**)&partialConfigName, cimErrorDetails);
            if (partialConfigName != NULL)
            {
                DSC_EventWriteLCMPullingPartial(partialConfigName);//Log that we're pulling this partial configuration
            }
            if (result != MI_RESULT_OK)
            {
                    moduleManager->ft->Close(moduleManager, NULL);
                    return result;
            }
            result = GetMofChecksum(&checkSumValue, partialConfigName, cimErrorDetails);
            if (result != MI_RESULT_OK)
            {
                    moduleManager->ft->Close(moduleManager, NULL);
                    return result;
            }
            result = LCM_Pull_ExecuteActionPerConfiguration(lcmContext, metaConfigInstance, partialConfigName,
                                                            checkSumValue, bComplianceStatus, getActionStatusCode, 
                                                            &numModulesInstalled, &resultStatus, &getActionStatusCode, &serverAssignedConfigurations,
                                                            moduleManager, cimErrorDetails);
            DSC_free(checkSumValue);

            if (serverAssignedConfigurations)
            {
                // Release the memory block assigned to each configuration status and then release the overall configurationstatus (serverAssignedConfigurations)
                // Please refer to the struct definition of 'OverAllGetActionResponse' to understand the logic below easily. 
                if (serverAssignedConfigurations != NULL)
                {
                    MI_Uint32 totalConfigCounts = (serverAssignedConfigurations)->NumberOfConfiguration;
                    MI_Uint32 memoryOffset;
                    for (memoryOffset = 0; memoryOffset < totalConfigCounts; memoryOffset++)
                    {
                        ConfigurationStatus* currentMemoryBlock = (serverAssignedConfigurations)->Details + memoryOffset;
                        if (currentMemoryBlock != NULL)
                        {
                            DSC_free(currentMemoryBlock);
                            currentMemoryBlock = NULL;
                        }
                    }
                    DSC_free(serverAssignedConfigurations);
                }            
                serverAssignedConfigurations = NULL;       
            }

            if (result == MI_RESULT_OK)
            {
                // If GetAction required us to get the configuraiton then only we have to apply the new configuration.
                if (resultStatus && Tcscasecmp(resultStatus, PULL_STATUSCODE_GETCONFIG) == 0)
                {
                        bGotNewConfiguration = MI_TRUE;
                }
                else if (resultStatus && Tcscasecmp(resultStatus, PULL_STATUSCODE_RETRY) == 0)
                {
                        // Pull server didn't have configuration file, ignore the failure, it will be handled later.
                        DSC_EventWritePartialConfigurationNotAvailable(partialConfigName);
                }
                if (resultStatus)
                {
                        DSC_free(resultStatus);
                }
            }
        }
        if (result == MI_RESULT_OK && bGotNewConfiguration)
        {
            if (!bFullConfiguration)
            {
                //If the partial configurations directory contains partial files, combine them and save into pending.mof
                result = MergePartialConfigurations(lcmContext, moduleManager, GetPendingConfigFileName(), GetPartialConfigBaseDocumentInstanceFileName(), cimErrorDetails);
                EH_CheckResult(result);
            }
            // If everything is good we will apply the configuration here.
            if (result == MI_RESULT_OK)
            {
                // If Current.mof exists, move Current.mof to Previous.mof
                if (File_ExistT(GetCurrentConfigFileName()) == 0)
                {
                    result = CopyConfigAndRemoveSource(CONFIGURATION_LOCATION_CURRENT, CONFIGURATION_LOCATION_PREVIOUS, cimErrorDetails);
                    EH_CheckResult(result);
                }

                if (numModulesInstalled > 0)
                {
                    result = ModuleManager_Update(moduleManager, cimErrorDetails);
                    if (result != MI_RESULT_OK)
                    {
                        return result;
                    }
#if defined(BUILD_OMS)
                    if (g_DscHost == MI_FALSE)
                    {
                        system(OMI_RELOAD_COMMAND);
                    }
#else
                    system(OMI_RELOAD_COMMAND);
#endif
                }

                result = ApplyPendingConfig(lcmContext, moduleManager, 0, &resultExecutionStatus, cimErrorDetails);
                if (result == MI_RESULT_OK && (resultExecutionStatus & DSC_RESTART_SYSTEM_FLAG))
                {
                    SetLCMStatusReboot(lcmContext);
                }
                
                if (result == MI_RESULT_OK)
                {
                    // update compliance result.
                    complianceStatus = MI_TRUE;
                    result = UpdateCurrentStatus(&complianceStatus, NULL, NULL, NULL, cimErrorDetails);
                    if (result == MI_RESULT_OK)
                    {
                        // result = CopyConfigurationChecksum(mofFileName, cimErrorDetails);
                    }
                }
            }
        }

        if (result != MI_RESULT_OK)
        {
                // log it here.
                DSC_EventWriteLCMPullEngineError(CA_ACTIVITY_NAME,
                        GetDownloadManagerName(metaConfigInstance),
                        result,
                        GetErrorDetail(*cimErrorDetails));
        }

        updateResult = UpdateCurrentStatus(NULL, &getActionStatusCode, NULL, NULL, &updateErrorDetails);
        if (updateResult != MI_RESULT_OK)
        {
                if (result == MI_RESULT_OK)
                {
                        // update the error with it.
                        result = updateResult;
                        *cimErrorDetails = updateErrorDetails;
                }
                else
                {
                        // retain original error and delete error instance.
                        if (updateErrorDetails)
                        {
                                MI_Instance_Delete(updateErrorDetails);
                        }
                }
        }

EH_UNWIND;
        moduleManager->ft->Close(moduleManager, NULL);


        return result;
}