in LCM/dsc/engine/ConfigurationManager/LocalConfigManagerHelper.c [2352:2646]
MI_Result ProcessPartialConfigurations(
_In_ LCMProviderContext *lcmContext,
_In_ ModuleManager *moduleManager,
_In_ MI_Uint32 flags,
_Inout_ MI_Uint32 *resultStatus,
_In_ MI_Result(*ConfigurationProcessor)
(
_In_ LCMProviderContext *lcmContext,
_In_ ModuleManager *moduleManager,
_In_ MI_Uint32 flags,
_In_ MI_Instance * documentIns,
_In_ MI_InstanceA *resourceInstances,
_In_ MI_Instance *metaConfigInstance,
_Inout_ MI_Uint32 *resultStatus,
_Outptr_result_maybenull_ MI_Instance **cimErrorDetails
),
_In_ MI_Instance *metaConfigInstance,
_In_ MI_InstanceA* resourceInstances,
_Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
MI_Result r = MI_RESULT_OK;
MI_Uint32 result_Flags;
MI_Boolean hashInited = MI_FALSE;
int hashResult;
const size_t NUM_LISTS = 32;
HashMap partialConfigDocumentInMap;
PartialConfigBucket *bucket = NULL;
PartialConfigBucket searchBucket;
MI_Instance **tempInstance = NULL;
MI_Uint32 xCount = 0;
MI_InstanceA partialConfigIns = { 0 };
MI_InstanceA partialConfigDocumentIns = { 0 };
ExecutionOrderContainer executionContainer = { 0 };
MI_InstanceA partialConfigResourceInstances = { 0 };
MSFT_PartialConfiguration *partialConfigIn = NULL;
MI_Boolean flagAtleastOnePartialWasSet = MI_FALSE;
MI_Boolean flagPartialConfigFailedToApply = MI_FALSE;
MI_Char expandedPartialConfigName[MAX_PATH];
size_t concatResult;
MI_Value value;
MI_Value valueId;
hashResult = HashMap_Init(&partialConfigDocumentInMap, NUM_LISTS, PartialConfigHash, PartialConfigEqual, PartialConfigRelease);
if (hashResult != 0)
{
EH_Fail();
}
hashInited = MI_TRUE;
// build a list of resourceInstance and documentIns
r = DSC_MI_Instance_GetElement(metaConfigInstance, MSFT_DSCMetaConfiguration_PartialConfigurations, &value, NULL, &result_Flags, NULL);
if (r != MI_RESULT_OK || (result_Flags & MI_FLAG_NULL) != 0)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(r, cimErrorDetails, ID_MODMAN_VALIDATE_DOCINS));
}
tempInstance = (MI_Instance **) DSC_malloc(value.instancea.size * sizeof(MI_Instance*), NitsHere());
if (tempInstance == NULL)
{
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
for (xCount = 0; xCount < value.instancea.size; xCount++)
{
tempInstance[xCount] = value.instancea.data[xCount];
bucket = (PartialConfigBucket*) DSC_malloc(sizeof(PartialConfigBucket), NitsHere());
if (bucket == NULL)
{
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
r = DSC_MI_Instance_GetElement(tempInstance[xCount], MSFT_DSCMetaConfiguration_ResourceId, &valueId, NULL, &result_Flags, NULL);
if (r != MI_RESULT_OK || (result_Flags & MI_FLAG_NULL) != 0)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(r, cimErrorDetails, ID_MODMAN_VALIDATE_DOCINS));
}
bucket->key = valueId.string;
bucket->partialConfig = tempInstance[xCount];
bucket->size = 0;
bucket->count = 0;
r = HashMap_Insert(&partialConfigDocumentInMap, (HashBucket*) bucket);
EH_CheckResult(r);
}
partialConfigIns.data = tempInstance;
partialConfigIns.size = value.instancea.size;
r = ResolveDependency(&partialConfigIns, &executionContainer, cimErrorDetails);
EH_CheckResult(r);
r = GetArrayInstancesFromSingleMof(moduleManager, 0, GetPartialConfigBaseDocumentInstanceFileName(), &partialConfigDocumentIns, cimErrorDetails, MI_TRUE);
EH_CheckResult(r);
//insert partialConfiguration document into the hashmap
for (xCount = 0; xCount < partialConfigDocumentIns.size; xCount++)
{
r = DSC_MI_Instance_GetElement(partialConfigDocumentIns.data[xCount], MI_T("Name"), &value, NULL, &result_Flags, NULL);
if (r != MI_RESULT_OK || (result_Flags & MI_FLAG_NULL) != 0)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(r, cimErrorDetails, ID_MODMAN_VALIDATE_DOCINS));
}
concatResult = Stprintf(expandedPartialConfigName, MAX_PATH, MI_T("%T%T"), MI_T("[PartialConfiguration]"), value.string);
if (concatResult == -1)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
searchBucket.key = expandedPartialConfigName;
bucket = (PartialConfigBucket*) HashMap_Find(&partialConfigDocumentInMap, (const HashBucket*) &searchBucket);
if (bucket == NULL)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
bucket->documentIns = partialConfigDocumentIns.data[xCount];
}
//count each partial configuration resource instances, save in hashmap->size
for (xCount = 0; xCount < resourceInstances->size; xCount++)
{
r = DSC_MI_Instance_GetElement(resourceInstances->data[xCount], OMI_BaseResource_ConfigurationName, &value, NULL, &result_Flags, NULL);
if (r != MI_RESULT_OK || (result_Flags & MI_FLAG_NULL) != 0)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(r, cimErrorDetails, ID_MODMAN_VALIDATE_DOCINS));
}
concatResult = Stprintf(expandedPartialConfigName, MAX_PATH, MI_T("%T%T"), MI_T("[PartialConfiguration]"), value.string);
if (concatResult == -1)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
searchBucket.key = expandedPartialConfigName;
bucket = (PartialConfigBucket*) HashMap_Find(&partialConfigDocumentInMap, (const HashBucket*) &searchBucket);
if (bucket == NULL)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
bucket->size++;
}
//collect each partial configuration resource instances into hashmap
for (xCount = 0; xCount < resourceInstances->size; xCount++)
{
r = DSC_MI_Instance_GetElement(resourceInstances->data[xCount], OMI_BaseResource_ConfigurationName, &value, NULL, &result_Flags, NULL);
if (r != MI_RESULT_OK || (result_Flags & MI_FLAG_NULL) != 0)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(r, cimErrorDetails, ID_MODMAN_VALIDATE_DOCINS));
}
concatResult = Stprintf(expandedPartialConfigName, MAX_PATH, MI_T("%T%T"), MI_T("[PartialConfiguration]"), value.string);
if (concatResult == -1)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
searchBucket.key = expandedPartialConfigName;
bucket = (PartialConfigBucket*) HashMap_Find(&partialConfigDocumentInMap, (const HashBucket*) &searchBucket);
if (bucket == NULL)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
if (bucket->count == 0 && bucket->size > 0)
{
bucket->resourceInstances = (MI_Instance **) DSC_malloc(bucket->size * sizeof(MI_Instance*), NitsHere());
if (bucket->resourceInstances == NULL)
{
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
}
bucket->resourceInstances[bucket->count++] = resourceInstances->data[xCount];
}
for (xCount = 0; xCount < executionContainer.executionListSize; xCount++)
{
partialConfigIn = (MSFT_PartialConfiguration*) partialConfigIns.data[executionContainer.ExecutionList[xCount].resourceIndex];
searchBucket.key = (MI_Char*) partialConfigIn->ResourceId.value;
bucket = (PartialConfigBucket*) HashMap_Find(&partialConfigDocumentInMap, (const HashBucket*) &searchBucket);
if (bucket == NULL)
{
// todo: add proper error message
EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
}
partialConfigResourceInstances.data = bucket->resourceInstances;
partialConfigResourceInstances.size = bucket->size;
if (bucket->count > 0)
{
MI_Boolean dependsExist;
r = DependPartialConfigExist(bucket->partialConfig, &partialConfigDocumentInMap, &dependsExist, cimErrorDetails);
EH_CheckResult(r);
if (dependsExist)
{
DSC_EventWriteLCMApplyingPartial(searchBucket.key);
r = ConfigurationProcessor(lcmContext, moduleManager, flags, bucket->documentIns, &partialConfigResourceInstances, (MI_Instance*) metaConfigInstance, resultStatus, cimErrorDetails);
DSC_free(partialConfigResourceInstances.data);
if (r != MI_RESULT_OK)
{
//Get the message and print a warning
r = DSC_MI_Instance_GetElement(*cimErrorDetails, MSFT_WMIERROR_MESSAGE, &value, NULL, NULL, NULL);
if (value.string != NULL)
{
DSC_WriteWarning2Param((MI_Context*) lcmContext->context, ID_LCMHELPER_APPLYPARTIALCONFIG_FAILED_WITHERROR, searchBucket.key, value.string);
}
if (*cimErrorDetails != NULL)
{
MI_Instance_Delete(*cimErrorDetails);
*cimErrorDetails = NULL;//Clear error details
}
flagPartialConfigFailedToApply = MI_TRUE;
r = MI_RESULT_OK;
}
else
{
//Check the flag where atleast one was set.
flagAtleastOnePartialWasSet = MI_TRUE;
if (!(flags & LCM_EXECUTE_TESTONLY) && (DSC_RESTART_SYSTEM_FLAG & *resultStatus))
{
//Log the message here; log different message depends on the value of RebootNodeIfNeeded(winblue:366265)
MI_Value configModeValue;
r = DSC_MI_Instance_GetElement(metaConfigInstance, MSFT_DSCMetaConfiguration_RebootNodeIfNeeded, &configModeValue, NULL, NULL, NULL);
if (r != MI_RESULT_OK)
{
return r;
}
//telling user that reboot is scheduled
if (configModeValue.boolean == MI_TRUE)
{
LCM_BuildMessage(lcmContext, ID_LCM_WRITEMESSAGE_REBOOT, EMPTY_STRING, MI_WRITEMESSAGE_CHANNEL_VERBOSE);
}
//telling user that manual reboot is needed
else
{
LCM_BuildMessage(lcmContext, ID_LCM_WRITEMESSAGE_REBOOTMANUALLY, EMPTY_STRING, MI_WRITEMESSAGE_CHANNEL_VERBOSE);
}
// this is the result from ApplyConfigGroup which requires reboot, we know it is ok in the Else clause
return MI_RESULT_OK;
}
}
}
else
{
//Only a warning that the dependent configuration was not available.
DSC_WriteWarning1Param((MI_Context*) lcmContext->context, ID_LCMHELPER_DEPENDSONFILEDOESNTEXIST_MESSAGE, searchBucket.key);
flagPartialConfigFailedToApply = MI_TRUE;
}
}
EH_CheckResult(r);
}
if (!flagAtleastOnePartialWasSet)
{
if (flagPartialConfigFailedToApply)
{
EH_CheckResult(r = GetCimMIError(MI_RESULT_NOT_FOUND, cimErrorDetails, ID_PARTIALCONFIG_FAILEDPARTIALCONFIGS));
}
else
{
EH_CheckResult(r = GetCimMIError(MI_RESULT_NOT_FOUND, cimErrorDetails, ID_PARTIALCONFIG_NOPARTIALCONFIGPRESENT));
}
}
EH_UNWIND;
CleanUpInstanceCache(&partialConfigDocumentIns);
if (tempInstance != NULL)
{
DSC_free(tempInstance);
}
if (hashInited)
{
HashMap_Destroy(&partialConfigDocumentInMap);
}
FreeExecutionOrderContainer(&executionContainer);
return r;
}