MI_Result MI_CALL PerformInventory()

in LCM/dsc/engine/ca/CAInfrastructure/CAEngine.c [2546:2707]


MI_Result MI_CALL PerformInventory( _In_ LCMProviderContext *lcmContext,
                                    _In_ MI_Uint32 flags,
                                    _In_ MI_InstanceA *instanceA,
                                    _In_ ModuleManager *moduleManager,
                                    _In_ MI_Instance *documentIns,
                                    _Out_ MI_InstanceA *outInstances,
                                    _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result r = MI_RESULT_OK;
    MI_Instance *filteredInstance = NULL;
    MI_Instance *regInstance = NULL;
    ModuleLoaderObject *moduleLoader = NULL;
    MI_InstanceA inventoryInstancesResult;
    MI_Session miSession = MI_SESSION_NULL;
    ProviderCallbackContext providerContext = {0};
    MI_InstanceA * inventoryInstancesResultArray = NULL;

    MI_Char *certificateid = NULL;
    MI_Boolean bEncryptionEnabled = MI_FALSE;
    MI_Uint32 xCount = 0;
    MI_Uint32 index = 0;
    MI_Instance * tempInstance;
    MI_Instance ** tempInstanceArray;
    MI_Uint32 i = 0;
    MI_Uint32 j = 0;
    MI_Uint32 totalInstanceCount = 0;

    if( outInstances == NULL  || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        return GetCimMIError(MI_RESULT_INVALID_PARAMETER, extendedError,ID_CAINFRA_INVENTORY_NULLPARAM);
    }

    memset(outInstances, 0, sizeof(MI_InstanceA));
    if( instanceA == 0 || moduleManager == 0 || instanceA->size == 0  || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        return GetCimMIError(MI_RESULT_INVALID_PARAMETER, extendedError,ID_CAINFRA_DEPENDCY_NULLPARAM);
    }

    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;
    }

    outInstances->data = NULL;
    outInstances->size = 0;
    inventoryInstancesResult.data = NULL;
    inventoryInstancesResult.size = 0;

    inventoryInstancesResultArray = (MI_InstanceA*)DSC_malloc(sizeof(MI_InstanceA) * instanceA->size, NitsHere());

    moduleLoader = (ModuleLoaderObject*) moduleManager->reserved2;

    /*Create MI session*/
    r = DSC_MI_Application_NewSession(moduleLoader->application, NULL, NULL, NULL, NULL, NULL, &miSession);
    if( r != MI_RESULT_OK)
    {
        return GetCimMIError(r, extendedError,ID_CAINFRA_NEWSESSION_FAILED);
    }

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

    /*Assuming the dependencies is implicit (the order in which instances are specified in instance document). */
    /*Get the instance compatible with the provider.*/
    for (xCount = 0 ; xCount < instanceA->size ; xCount++)
    {
        /* Get Registration Instance to find registration information.*/
        r = moduleManager->ft->GetRegistrationInstance(moduleManager, instanceA->data[xCount]->classDecl->name, (const MI_Instance **)&regInstance, extendedError);
        if( r != MI_RESULT_OK)
        {
            MI_Session_Close(&miSession, NULL, NULL);
            return r;
        }

        /*Get provider compatible instance*/
        r = moduleManager->ft->GetProviderCompatibleInstance(moduleManager, instanceA->data[xCount], &filteredInstance, extendedError);
        if( r != MI_RESULT_OK)
        {
            MI_Session_Close(&miSession, NULL, NULL);
            return r;
        }
        providerContext.resourceId = GetResourceId(instanceA->data[xCount]);

        /* Get the inventory.*/
        r = PerformInventoryState(&providerContext, moduleLoader->application, &miSession, filteredInstance, regInstance, &inventoryInstancesResult, extendedError);
        MI_Instance_Delete(filteredInstance);
        filteredInstance = NULL;

        if( r != MI_RESULT_OK)
        {
            Intlstr intlstr = Intlstr_Null;
            GetResourceString(ID_LCMHELPER_GETINVENTORY_ERROR, &intlstr);

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

            if( intlstr.str)
                Intlstr_Free(intlstr);

            MI_Session_Close(&miSession, NULL, NULL);
            return r;
        }

        inventoryInstancesResultArray[xCount].data = inventoryInstancesResult.data;
        inventoryInstancesResultArray[xCount].size = inventoryInstancesResult.size;
        totalInstanceCount += inventoryInstancesResult.size;
    }

    if (totalInstanceCount > 0)
    {
    outInstances->data = (MI_Instance**)DSC_malloc(sizeof(MI_Instance*) * totalInstanceCount, NitsHere());
    outInstances->size = totalInstanceCount;

    xCount = 0;
    for (i = 0; i < instanceA->size; ++i)
    {
        for (j = 0; j < inventoryInstancesResultArray[i].size; ++j)
        {
        outInstances->data[xCount] = inventoryInstancesResultArray[i].data[j];
        xCount += 1;
        }
    }
    }
    else
    {
        outInstances->data = NULL;
        outInstances->size = 0;
    }

    MI_Session_Close(&miSession, NULL, 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);

#if defined(BUILD_OMS)
    struct sigaction sa;
    sa.sa_handler = &handleSIGCHLDSignal;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
    sigaction(SIGCHLD, &sa, 0);
    DSC_EventWriteMessageRegisterProcessHandler();
#endif

    return r;
}