/*Function to return agentId value from registry 
If registration has never been attempted on this machine, then this function returns an empty string and returns TRUE for shouldGenerateAgentId*/
MI_Result GetAgentIdFromRegistry(
    _Outptr_result_maybenull_z_ MI_Char** agentId, 
    _Inout_ MI_Boolean *shouldGenerateAgentId)
{    
    if (File_ExistT(AGENTID_FILE_PATH) != 0)
    {
        // We are not able to get the agent Id. 
        // We should generate a new agentId.
        *shouldGenerateAgentId = MI_TRUE ;
        return MI_RESULT_OK;        
    }
    
    /* inhale contents fails into agentId */
    *agentId = InhaleTextFile(AGENTID_FILE_PATH);

    if (Tcscasecmp(MI_T(" "), *agentId) == 0 || Tcscasecmp(MI_T(""), *agentId) == 0)
    {
        // We are not able to get the agent Id. 
        // We should generate a new agentId.
        *shouldGenerateAgentId = MI_TRUE;
        return MI_RESULT_OK;
    } 
    *shouldGenerateAgentId = MI_FALSE;    

    (*agentId)[36] = '\0';

    return MI_RESULT_OK;
}
/*Function to return true if registration needs to be done*/
MI_Boolean ShouldDoRegistration(
    _In_ RegistrationManager* self,
    _In_ RegistrationRequest* request,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{   
    MI_Result result = MI_RESULT_OK;
    MI_Uint32 i = 0;
    MI_Value value;
    MI_Char* url = NULL;    
    MI_Type type;
    MI_Uint32 flags;

    if (cimErrorDetails)
    {
        *cimErrorDetails = NULL;
    }

    MI_Instance *registrationDataInstance = request->registrationData;

    result = MI_Instance_GetElement(registrationDataInstance, MSFT_ServerURL_Name, &value, NULL, NULL, NULL);
    EH_CheckResult(result);
    url = value.string;
    
    result = DSC_MI_Instance_GetElement(registrationDataInstance, MSFT_RegistrationKey_Name, &value, &type, &flags, NULL);
    if (result == MI_RESULT_OK && type == MI_STRING && (!(flags & MI_FLAG_NULL)))
    {
        if (Tcscasecmp(value.string, MI_T("")) != 0)
        {
            // This means that a non-empty RegistrationKey is specified. Then, we always do registration. 
            // If RegistrationKey is not specified, then we check the cache and do/skip registration based on ServerURL
            DSC_EventWriteLCMAgentAttemptRegistration(g_ConfigurationDetails.jobGuidString, self->agentId, url);
            return MI_TRUE;
        }
    }

    for (i = 0; i < self->numberOfServerURLs; i++)
    {
        if (Tcscasecmp(self->serverURLs[i], url) == 0)
        {
            DSC_EventWriteLCMServerURLRegistered(g_ConfigurationDetails.jobGuidString, self->agentId, url);
            return MI_FALSE;
        }
    }
    
    EH_UNWIND:

    return MI_TRUE;
}
示例#3
0
MI_Result ValidateInfrastructureSchema(_In_ MI_ClassA *miClassArray, 
                                       _Outptr_result_maybenull_ MI_Instance **extendedError )
{
    MI_Result r = MI_RESULT_OK;
    MI_Uint32 xCount = 0, yCount = 0;
    if( extendedError )
        *extendedError = NULL;
    SetJobId();
    DSC_EventWriteValidatingInfrastructureSchema(miClassArray->size);
    //Validate various infrastructure classes
    for( xCount = 0 ; xCount < miClassArray->size ; xCount++)
    {
        for (yCount = 0; g_InfraSchemaValidators[yCount].wszClassName != NULL; yCount++)
        {
            if( Tcscasecmp(miClassArray->data[xCount]->classDecl->name, g_InfraSchemaValidators[yCount].wszClassName) == 0 )
            {
                break;
            }
        }

        if( g_InfraSchemaValidators[yCount].wszClassName == NULL || NitsShouldFault(NitsHere(), NitsAutomatic))
        {
            return GetCimMIError(MI_RESULT_INVALID_PARAMETER, extendedError, ID_MODMAN_VALIDATE_INFRASCHEMA); 
        }

        r = g_InfraSchemaValidators[yCount].Validator(miClassArray->data[xCount], extendedError);
        if( r != MI_RESULT_OK)
        {
            return r; 
        }
    }
    return r;
}
MI_Result GetThumbprintForRegisteredServerURL(
    _In_ RegistrationManager* self,
    _In_ MI_Instance* registrationData,
    _Outptr_result_maybenull_z_ MI_Char** thumbprint,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    size_t dwSize;
    MI_Value value;
    int retValue;
    MI_Uint32 i = 0;
    MI_Result result = MI_RESULT_OK;

    if (cimErrorDetails)
    {
        *cimErrorDetails = NULL;
    }

    *thumbprint = 0;

    if (self->serverURLs == NULL)
    {
        InitializeServerURLs(self, cimErrorDetails);
    }

    if (self->serverURLs != NULL)
    {
        result = MI_Instance_GetElement(registrationData, MSFT_ServerURL_Name, &value, NULL, NULL, NULL);
        EH_CheckResult(result);

        for (i = 0; i < self->numberOfServerURLs; i++)
        {
            if (self->serverURLs[i] != NULL && Tcscasecmp(self->serverURLs[i], value.string) == 0)
            {
                dwSize = Tcslen(self->serverCertificateThumbprints[i]) + 1;
                *thumbprint = (MI_Char*)DSC_malloc(dwSize*sizeof(MI_Char), NitsHere());
                if (*thumbprint == NULL)
                {
                    EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
                }

                retValue = Stprintf(*thumbprint, dwSize, MI_T("%T"), self->serverCertificateThumbprints[i]);
                if (retValue == -1 || NitsShouldFault(NitsHere(), NitsAutomatic))
                {
                    DSC_free(*thumbprint);
                    EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_LCMHELPER_PRINTF_ERROR));
                }

                result = MI_RESULT_OK;
                break;
            }
        }
    }

EH_UNWIND:

    return result;
}
示例#5
0
/// <summary>
/// Try begin general method if another method is not running currently. General methods don't include StopConfiguration
/// </summary>
MI_Result TryBeginLcmOperation(
    _In_z_ const MI_Char* methodName,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    MI_Char* originalMethodName;
    int waitResult = 0;

    *cimErrorDetails = NULL;
    originalMethodName = (MI_Char*)Atomic_CompareAndSwap(&g_activeOperationMethodName, (ptrdiff_t) NULL, (ptrdiff_t)methodName);

    if (originalMethodName != NULL)
	{
		// We silently let GetMetaConfiguration to go if the active operation is not SetMetaConfiguration
		if (Tcscasecmp(originalMethodName, MSFT_DSCLocalConfigManager_SendMetaConfigurationApply) == 0
			|| Tcscasecmp(methodName, MSFT_DSCLocalConfigManager_GetMetaConfiguration) != 0)
		{
			return GetCimMIError3Params(MI_RESULT_FAILED, cimErrorDetails, ID_LCM_MULTIPLE_METHOD_REQUEST, methodName, originalMethodName, methodName);
		}
	}
    waitResult = Sem_TimedWait(&g_h_ConfigurationStoppedEvent, (int)0); //Ignore the result
    return MI_RESULT_OK;
}
示例#6
0
ProvRegClassInheritanceNode* _FindClassNodeInTree(
    ProvRegClassInheritanceNode* root,
    const ZChar* cn)
{
    while (root)
    {
        if (Tcscasecmp(cn,root->cn)==0)
        {
            return root;
        }
        root = _GetNextTreeNode(root);
    }
    return root;
}
示例#7
0
ProvRegNamespaceNode* _FindNamespace(
    ProvReg* self,
    MI_ConstString ns,
    MI_Boolean extraClass)
{
    /* find namespace node in the list */
    ProvRegNamespaceNode* current;
    if(extraClass)
        current = self->namespacesForExtraClasses;
    else
        current = self->namespaces;

    while (current && Tcscasecmp(ns,current->ns) != 0)
        current = current->next;

    return current;
}
示例#8
0
/* Find event steam provider under given namespace */
_Use_decl_annotations_
const ProvRegEntry* ProvReg_FindProviderForClassByType(
    ProvReg* self,
    const ZChar* nameSpace,
    const ZChar* className,
    ProvRegType type,
    MI_Result *findError)
{
    ProvRegEntry* p;
    MI_Boolean namespaceFound = 0;
    unsigned int nameSpaceHash = Hash(nameSpace);
    unsigned int classNameHash = 0;
    if (!className)
    {
        if(findError)
            *findError = MI_RESULT_INVALID_PARAMETER;
        return NULL;
    }
    if (className)
        classNameHash = Hash(className);

    for (p = self->head; p; p = p->next)
    {
        // comparing namespace everytime may slightly affect perf
        // but it enables us to give right error back to the client
        if (nameSpaceHash == p->nameSpaceHash &&
            Tcscasecmp(p->nameSpace, nameSpace) == 0)
        {
            if (p->regType == type)
            {
                if (className)
                {
                    /* for normal and indication class */
                    if( classNameHash == p->classNameHash &&
                        Tcscasecmp(p->className, className) == 0)
                    {
                        if(findError)
                        {
                            *findError = MI_RESULT_OK;
                        }
                        return p;
                    }
                }
                else
                {
                    /* for event stream class */
                    if(findError)
                    {
                        *findError = MI_RESULT_OK;
                    }
                    return p;
                }
                namespaceFound = MI_TRUE;
            }
        }
    }

    if(findError)
    {
        *findError = (MI_TRUE == namespaceFound) ? MI_RESULT_INVALID_CLASS : MI_RESULT_INVALID_NAMESPACE;
    }
    /* Not found */
    return NULL;
}
MI_Boolean IsMatchedKeyProperties(
    _In_ MI_Instance* instance0,
    _In_ MI_Instance* instance1,
    _Outptr_result_maybenull_z_ MI_Char** keywords,
    _Out_ MI_Result* miResult,
    _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Uint32 i, j;
    MI_Result result0, result1;
    MI_Value value0, value1;
    MI_Type type0, type1;
    Intlstr intlstr = Intlstr_Null;
    MI_Char* tempKeywords = NULL;
    MI_Char* tempKeywordsBackup = NULL;
    size_t length;
    MI_PropertyDecl** properties;

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

    *miResult = MI_RESULT_OK;
    *keywords = NULL;
    properties = (MI_PropertyDecl**)instance0->classDecl->properties;
    for (i = 0; i < instance0->classDecl->numProperties; i++)
    {
        for (j = 0; j < properties[i]->numQualifiers; j++)
        {
            if (Tcscasecmp(properties[i]->qualifiers[j]->name, MI_T("Key")) == 0)
            {
                result0 = DSC_MI_Instance_GetElement(instance0, properties[i]->name, &value0, &type0, NULL, NULL);
                result1 = DSC_MI_Instance_GetElement(instance1, properties[i]->name, &value1, &type1, NULL, NULL);
                if (result0 == MI_RESULT_OK
                    && result1 == MI_RESULT_OK
                    && type0 == type1
                    && IsSameMiValue(&value0, &value1, type0))
                {
                    // key is the same, building keywords list.
                    length = Tcslen(properties[i]->name) + 1;
                    if (tempKeywords == NULL)
                    {
                        // the first keyword.
                        tempKeywords = (MI_Char*)DSC_malloc(length * sizeof (MI_Char), NitsHere());
                        if (tempKeywords == NULL)
                        {
                            *miResult = CreateMemoryError(extendedError);
                            return MI_TRUE;
                        }

                        memcpy(tempKeywords, properties[i]->name, length * sizeof(MI_Char) );
                    }
                    else
                    {
                        // the second or more keywords.
                        if (intlstr.str == NULL)
                        {
                            // create separator string once.
                            GetResourceString(ID_CA_COMMA_SEPARATOR, &intlstr);
                            if (intlstr.str == NULL)
                            {
                                *miResult = CreateMemoryError(extendedError);
                                DSC_free(tempKeywords);
                                return MI_TRUE;
                            }
                        }

                        length += Tcslen(tempKeywords) + Tcslen(intlstr.str);
                        tempKeywordsBackup = tempKeywords;
                        tempKeywords = (MI_Char*)DSC_realloc(tempKeywordsBackup, length * sizeof (MI_Char), NitsHere());
                        if (tempKeywords == NULL)
                        {
                            *miResult = CreateMemoryError(extendedError);
                            DSC_free(tempKeywordsBackup);
                            Intlstr_Free(intlstr);
                            return MI_TRUE;
                        }
                        Stprintf(tempKeywords, length, MI_T("%T%T"), intlstr.str, properties[i]->name);
                    }
                }
                else
                {
                    if (tempKeywords)
                    {
                        DSC_free(tempKeywords);
                    }
                    
                    if (intlstr.str)
                    {
                        Intlstr_Free(intlstr);
                    }
                    
                    if(result0 != MI_RESULT_OK)
                    {
                        *miResult = result0;
                    }
                    else if(result1 != MI_RESULT_OK)
                    {
                        *miResult = result1;
                    }

                    return MI_FALSE;
                }

                break;
            }
        }
    }

    if (intlstr.str)
    {
        Intlstr_Free(intlstr);
    }

    // at least one key was found, and all matched.
    if (tempKeywords)
    {
        *keywords = tempKeywords;
        return MI_TRUE;
    }

    return MI_FALSE;
}
MI_Result ValidateIfDuplicatedInstances(
    _In_ MI_InstanceA *instanceA,
    _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result miResult = MI_RESULT_OK;
    MI_Instance* instance0;
    MI_Instance* instance1;
    MI_Char* keywords;
    const MI_Char* resourceId0;
    const MI_Char* resourceId1;
    MI_Uint32 i, j;
    
    if (extendedError == NULL)
    {        
        return MI_RESULT_INVALID_PARAMETER; 
    }
    *extendedError = NULL;	// Explicitly set *extendedError to NULL as _Outptr_ requires setting this at least once.	

    for (i = 0; i < instanceA->size; i++)
    {
        instance0 = instanceA->data[i];
        if (instance0->classDecl->superClass != NULL &&Tcscasecmp(instance0->classDecl->superClass, BASE_RESOURCE_CLASSNAME) == 0)
        {
            for (j = i + 1; j < instanceA->size; j++)
            {
                instance1 = instanceA->data[j];
                if (Tcscasecmp(instance0->classDecl->name, instance1->classDecl->name) == 0
                    && IsMatchedKeyProperties(instance0, instance1, &keywords, &miResult, extendedError))
                {
                    if (miResult != MI_RESULT_OK && *extendedError)
                    {
                        return miResult;
                    }

                    resourceId0 = GetResourceId(instance0);
                    resourceId1 = GetResourceId(instance1);
                    if (resourceId0 == NULL || resourceId1 == NULL)
                    {
                        miResult = CreateMemoryError(extendedError);
                        DSC_free(keywords);
                        return miResult;
                    }

                    miResult = GetCimMIError4Params(MI_RESULT_ALREADY_EXISTS, extendedError, ID_CA_DUPLICATE_KEYS, instance0->classDecl->name, resourceId0, resourceId1, keywords);
                    if (keywords)
                    {
                        DSC_free(keywords);
                    }

                    return miResult;
                }
                else if (miResult != MI_RESULT_OK)
                {
                    return miResult;
                }
            }
        }
    }

    return MI_RESULT_OK;
}
示例#11
0
/*
**
** Find ISA operator and its target classname; Take following query for example,
**  Select * from CIM_InstCreation where SourceInstance isa "Win32_process"
**      (1) It's a lifecycle indication query
**      (2) It's target class is Win32_process
** 
** Following query is invalid since OR operator makes the target class ambiguous,
**  Select * from CIM_InstCreation where SourceInstance isa "Win32_process" OR (2>1)
** This query targets to all classes under the namespace, which is NOT a valid scenario
** to support; This function is to find whether an given query is a valid lifecycle
** indication query; If yes return 0 and output the target class name; otherwise return non 0;
**
**
*/
static MI_Result _FindLifecycleClass(
    _In_ SubscriptionTargetType stt,
    _In_ const WQL* wql,
    _Outptr_result_maybenull_z_ const ZChar** targetClassname,
    _Outptr_result_maybenull_z_ const MI_Char** errormessage)
{
    static const ZChar* sSourceInstanceProperty = ZT("SourceInstance");
    static const ZChar* sPreviousInstanceProperty = ZT("PreviousInstance");

    size_t i;
    WQL_SymbolEx symbols[WQL_MAX_SYMBOLS];
    size_t nsymbols = 0;
    MI_Boolean foundISA = MI_FALSE;
    MI_Result r = MI_RESULT_NOT_SUPPORTED;

    DEBUG_ASSERT (wql && wql->className && targetClassname && errormessage);

    *targetClassname = NULL;
    *errormessage = NULL;

    /* Fail if there is no WHERE clause */
    if (wql->nsymbols == 0)
        return MI_RESULT_OK;

    /* Perform postfix evaluation */
    for (i = 0; i < wql->nsymbols; i++)
    {
        const WQL_Symbol* sym = &wql->symbols[i];
        WQL_Type type = sym->type;

        if (nsymbols >= WQL_MAX_SYMBOLS)
            return r;

        switch (type)
        {
            case WQL_TYPE_AND:
            case WQL_TYPE_OR:
            {
                if (nsymbols < 2)
                    return r;

                {
                    WQL_SymbolEx s2 = symbols[--nsymbols];
                    WQL_SymbolEx s1 = symbols[--nsymbols];
                    WQL_SymbolEx s;
                    memset(&s, 0, sizeof(WQL_SymbolEx));
                    if (type == WQL_TYPE_OR)
                    {
                        if (s1.isa || s2.isa)
                        {
                            *errormessage = STR_LIFECYCLE_INDICATION_QUERY_ISA_OPERATOR_WITHIN_OR;
                            trace_FindLifecycleClass_InvalidLifecycleQuery();
                            return r;
                        }
                    }
                    if (s1.base.type != WQL_TYPE_BOOLEAN)
                        return r;
                    if (s2.base.type != WQL_TYPE_BOOLEAN)
                        return r;
                    s.base.type = WQL_TYPE_BOOLEAN;
                    s.base.value.boolean = 0;
                    s.isa = s1.isa || s2.isa;
                    symbols[nsymbols++] = s;
                }
                break;
            }
            case WQL_TYPE_NOT:
            {
                if (nsymbols < 1)
                    return r;
                {
                    WQL_SymbolEx s1 = symbols[--nsymbols];
                    WQL_SymbolEx s;
                    memset(&s, 0, sizeof(WQL_SymbolEx));
                    if (s1.base.type != WQL_TYPE_BOOLEAN)
                        return r;
                    s.base.type = WQL_TYPE_BOOLEAN;
                    s.base.value.boolean = 0;
                    s.isa = s1.isa;
                    symbols[nsymbols++] = s;
                }
                break;
            }
            case WQL_TYPE_EQ:
            case WQL_TYPE_NE:
            case WQL_TYPE_LT:
            case WQL_TYPE_LE:
            case WQL_TYPE_GT:
            case WQL_TYPE_GE:
            case WQL_TYPE_LIKE:
            {
                if (nsymbols < 2)
                    return r;
                {
                    WQL_SymbolEx s2 = symbols[--nsymbols];
                    WQL_SymbolEx s1 = symbols[--nsymbols];
                    WQL_SymbolEx s;
                    memset(&s, 0, sizeof(WQL_SymbolEx));
                    s.base.type = WQL_TYPE_BOOLEAN;
                    s.base.value.boolean = 0;
                    s.isa = s1.isa || s2.isa;
                    symbols[nsymbols++] = s;
                }
                break;
            }
            case WQL_TYPE_IDENTIFIER:
            {
                WQL_SymbolEx s;
                memset(&s, 0, sizeof(WQL_SymbolEx));
                s.base.type = WQL_TYPE_BOOLEAN;
                s.base.value.boolean = 0;
                s.isa = MI_FALSE;
                symbols[nsymbols++] = s;
                break;
            }
            case WQL_TYPE_BOOLEAN:
            case WQL_TYPE_INTEGER:
            case WQL_TYPE_REAL:
            case WQL_TYPE_STRING:
            case WQL_TYPE_NULL:
            case WQL_TYPE_ANY:
            {
                WQL_SymbolEx s;
                memcpy(&s.base, sym, sizeof(WQL_Symbol));
                s.isa = MI_FALSE;
                symbols[nsymbols++] = s;
                break;
            }
            case WQL_TYPE_ISA:
            {
                WQL_SymbolEx s2;
                WQL_SymbolEx s1;

                if (foundISA == MI_TRUE)
                {
                    *errormessage = STR_LIFECYCLE_INDICATION_QUERY_MORETHANONE_ISA_OPERATOR;
                    trace_FindLifecycleClass_UnsupportedLifecycleQuery();
                    return r;
                }

                if (nsymbols < 2)
                {
                    trace_FindLifecycleClass_TooFewOperandsISA();
                    return r;
                }

                s2 = symbols[--nsymbols];
                s1 = symbols[--nsymbols];

                if (s1.base.type != WQL_TYPE_STRING)
                {
                    trace_FindLifecycleClass_InvalidTokenType();
                    return r;
                }
                if (s2.base.type != WQL_TYPE_STRING)
                {
                    trace_FindLifecycleClass_InvalidTokenType();
                    return r;
                }

                /* Check Embedded property name is valid or not */
                {
                    int cmpresult = Tcscasecmp(sSourceInstanceProperty, s1.base.value.string);
                    if (cmpresult != 0)
                    {
                        if (stt == SUBSCRIP_TARGET_LIFECYCLE_MODIFY)
                        {
                            cmpresult = Tcscasecmp(sPreviousInstanceProperty, s1.base.value.string);
                        }
                    }
                    if (cmpresult != 0)
                    {
                        *errormessage = STR_LIFECYCLE_INDICATION_QUERY_ISA_HAS_WRONG_PROPERTYNAME;
                        r = MI_RESULT_INVALID_QUERY;
                        trace_FindLifecycleClass_InvalidEmbeddedProperty(s1.base.value.string);
                        return r;
                    }
                }

                /* Put ISA result symbol into stack */
                {
                    WQL_SymbolEx s;
                    memset(&s, 0, sizeof(WQL_SymbolEx));
                    s.base.type = WQL_TYPE_BOOLEAN;
                    s.base.value.boolean = MI_FALSE;
                    s.isa = MI_TRUE;
                    symbols[nsymbols++] = s;
                    *targetClassname = s2.base.value.string;
                    foundISA = MI_TRUE;
                    trace_FindLifecycleClass_FoundISAOperator(s1.base.value.string, s2.base.value.string);
                }
                break;
            }
        }
    }

    /* There should be exactly 1 symbol left on stack */
    if (nsymbols != 1)
    {
        trace_FindLifecycleClass_EvalHasMoreThanOneSymbol(nsymbols);
        return r;
    }

    /* There should be exactly 1 symbol left on stack */
    /* Final token on stack should be boolean */
    if (symbols[0].base.type != WQL_TYPE_BOOLEAN)
    {
        trace_FindLifecycleClass_EvalResultIsNotBool();
        return r;
    }

    if ( MI_FALSE == foundISA )
    {
        *errormessage = STR_LIFECYCLE_INDICATION_QUERY_NO_ISA_OPERATOR;
        return r;
    }
    else
        return MI_RESULT_OK;
}
示例#12
0
MI_Result ValidateProviderRegistrationAgainstSchema(_In_ MI_ClassA *miClassArray,
                                                    _In_ MI_InstanceA *miRegistrationArray,
                                                    _Outptr_result_maybenull_ MI_Instance **extendedError)

{
    MI_Result r = MI_RESULT_OK;
    MI_Uint32 xCount=0 , yCount = 0;
    MI_Uint32 registrationFoundCount = 0, schemaFoundCount = 0;
    MI_Value value;

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

    DSC_EventWriteValidatingProviderRegistration(miClassArray->size,miRegistrationArray->size);

    //Test1 : only 1 registration per class
    //Test2 : no class left out without registration(except for meta config), also validates that registration not targeting more than 1 class.
    //Test3: no registration instance left out without class
    //Test4 : no two classes with same name    

    for (xCount = 0 ; xCount < miClassArray->size ; xCount++)
    {
        if (miClassArray->data[xCount]->classDecl->superClass &&
            Tcscasecmp(miClassArray->data[xCount]->classDecl->superClass, BASE_RESOURCE_CLASSNAME) == 0)
        {
            schemaFoundCount++;
        }

        //Test4
        for (yCount = xCount + 1 ; yCount <  miClassArray->size ; yCount++)
        {
            if (Tcscasecmp(miClassArray->data[yCount]->classDecl->name, miClassArray->data[xCount]->classDecl->name) == 0  || NitsShouldFault(NitsHere(), NitsAutomatic))
            {
                return GetCimMIError(MI_RESULT_INVALID_PARAMETER, extendedError, ID_MODMAN_VALIDATE_PROVREG_MULTI);  
            }
        }
    }

    for (xCount = 0 ; xCount < miRegistrationArray->size ; xCount++)
    {
        for (yCount = 0 ; yCount < miClassArray->size ; yCount++)
        {
            if ((miClassArray->data[yCount]->classDecl->superClass &&
                 Tcscasecmp(miClassArray->data[yCount]->classDecl->superClass, BASE_RESOURCE_CLASSNAME) == 0) ||
                 Tcscasecmp(miClassArray->data[xCount]->classDecl->name, METACONFIG_CLASSNAME) == 0)
            {
                r = DSC_MI_Instance_GetElement(miRegistrationArray->data[xCount], MSFT_BaseConfigurationProviderRegistration_ClassName, 
                    &value, NULL, NULL, NULL); 
                if (r != MI_RESULT_OK )
                {
                    return GetCimMIError(r, extendedError, ID_MODMAN_VALIDATE_PROVREG_MANDATORY);
                }

                if (Tcscasecmp(value.string, miClassArray->data[yCount]->classDecl->name) == 0 )
                {
                    // Test1
                    registrationFoundCount++;
                    break;
                }
            }
        }

        // Test3
        if (yCount == miClassArray->size  || NitsShouldFault(NitsHere(), NitsAutomatic))
        {
            return GetCimMIError(MI_RESULT_INVALID_PARAMETER, extendedError, ID_MODMAN_VALIDATE_PROVREG_NOCLASS);    
        }
    }

    // Test2
    if (registrationFoundCount != schemaFoundCount  || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        return GetCimMIError(MI_RESULT_INVALID_PARAMETER, extendedError, ID_MODMAN_VALIDATE_PROVREG_NOREG);
    }

    return r;
}