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;
}
MI_Result WriteServerURLToCache(
    _In_ RegistrationManager* self,
    _In_z_ MI_Char* serverURL,
    _In_z_ MI_Char* thumbprint,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    size_t dwSize;
    int retValue;
    MI_Result result = MI_RESULT_OK;

    if (cimErrorDetails)
    {
        *cimErrorDetails = NULL;
    }

    if (self->serverURLs == NULL)
    {
        result = InitializeServerURLs(self, cimErrorDetails);
        EH_CheckResult(result);
    }
    
    dwSize = Tcslen(serverURL) + 1;
    self->serverURLs[self->numberOfServerURLs] = (MI_Char*)DSC_malloc(dwSize* sizeof(MI_Char), NitsHere());
    if (self->serverURLs[self->numberOfServerURLs] == NULL)
    {
        EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
    }
    retValue = Stprintf(self->serverURLs[self->numberOfServerURLs], dwSize, MI_T("%T"), serverURL);
    if (retValue == -1 || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        DSC_free(self->serverURLs[self->numberOfServerURLs]);
        EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_LCMHELPER_PRINTF_ERROR));
    }

    dwSize = Tcslen(thumbprint) + 1;
    self->serverCertificateThumbprints[self->numberOfServerURLs] = (MI_Char*)DSC_malloc(dwSize* sizeof(MI_Char), NitsHere());
    if (self->serverCertificateThumbprints[self->numberOfServerURLs] == NULL)
    {
        EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
    }
    retValue = Stprintf(self->serverCertificateThumbprints[self->numberOfServerURLs], dwSize, MI_T("%T"), thumbprint);
    if (retValue == -1 || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        DSC_free(self->serverCertificateThumbprints[self->numberOfServerURLs]);
        EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_LCMHELPER_PRINTF_ERROR));
    }

    self->numberOfServerURLs++;

    EH_UNWIND:

        return result;
}
예제 #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;
}
예제 #4
0
파일: CALog.c 프로젝트: 40a/WPSDSCLinux
//Logs the Whatif messages that arrive from the provider.
void LogCAWhatIfMessage( _In_ void *provContext, _In_z_ const MI_Char *message)
{
    if(message != NULL && provContext != NULL)
    {
        ProviderCallbackContext *providerContext = (ProviderCallbackContext *) provContext;
        LCMProviderContext *lcmContext = providerContext->lcmProviderContext;
        if((lcmContext->executionMode & LCM_EXECUTIONMODE_ONLINE) && lcmContext->context)
        {
            MI_Char *fullMessage = NULL;
            size_t msgLen;
            //The message arrived contains whatif : <actualmessage> , and we need to truncate it to the start of the actual message first.
            const MI_Char * truncatedMsg=(Tcslen(message)<WHATIFMESSAGE_STARTINDEX)?message:message+WHATIFMESSAGE_STARTINDEX;
            msgLen = Tcslen(truncatedMsg) + Tcslen(providerContext->resourceId) + Tcslen(EMPTY_STRING) +Tcslen(VERBOSE_FORMAT) + Tcslen(g_CAJobInformation.deviceName)+TOKENIZED_MESSAGE_PADDING; 
            
            fullMessage = (MI_Char*) DSC_malloc(sizeof(MI_Char)*msgLen, NitsHere());

            if( fullMessage)
            {
                //Full message looks like "What if: [PS3319275115]:                                 [[WindowsFeature]x] Continue with removal?"
                if(Stprintf(fullMessage, msgLen,VERBOSE_FORMAT , g_CAJobInformation.deviceName, EMPTY_STRING,  providerContext->resourceId, truncatedMsg) > 0 )
                {
                    MI_Boolean flag;
                    //Changed it from should process to prompt user since shouldprocess is being done within the provider. Here we just output the message.
                    MI_Context_PromptUser((MI_Context*) lcmContext->context,fullMessage, MI_PROMPTTYPE_NORMAL,&flag);
                }
                
                DSC_free(fullMessage);
                    
            }
        }
    }
}
예제 #5
0
파일: CALog.c 프로젝트: 40a/WPSDSCLinux
void LogCAWarningMessage(_In_ void *provContext,_In_opt_z_ const MI_Char *message)
{
    MI_Result result = MI_RESULT_OK;
        
    if(message != NULL && provContext != NULL)
    {
        ProviderCallbackContext *providerContext = (ProviderCallbackContext *) provContext;
        LCMProviderContext *lcmContext = providerContext->lcmProviderContext;
        

        if((lcmContext->executionMode & LCM_EXECUTIONMODE_ONLINE) && lcmContext->context)
        {
            MI_Char *fullMessage = NULL;
            size_t msgLen; 
            msgLen = Tcslen(message) + Tcslen(providerContext->resourceId) + Tcslen(VERBOSE_FORMAT)+Tcslen(EMPTY_STRING)+Tcslen(g_CAJobInformation.deviceName)+TOKENIZED_MESSAGE_PADDING; //DeviceName: LCM:  \t   \t   [Package]SQL
            fullMessage = (MI_Char*) DSC_malloc(sizeof(MI_Char)*msgLen, NitsHere());

            if( fullMessage!=NULL)
            {                
                if(Stprintf(fullMessage, msgLen,VERBOSE_FORMAT , g_CAJobInformation.deviceName, EMPTY_STRING, providerContext->resourceId, message) >0 )
                {
                    result = MI_Context_WriteWarning((MI_Context*) lcmContext->context, fullMessage);

                    if(result != MI_RESULT_OK)
                    {
                        // Ignore the failure, this doesn't impact the functionality.
                    }
                }

                DSC_free(fullMessage);
            }
        }
    }
}
예제 #6
0
파일: CALog.c 프로젝트: 40a/WPSDSCLinux
const MI_Char *  LogCAVerboseMessage(_In_ void *provContext,_In_opt_z_ const MI_Char *message)
{
    MI_Result result = MI_RESULT_OK;
    if(message != NULL && provContext != NULL)
    {
        ProviderCallbackContext *providerContext = (ProviderCallbackContext *) provContext;
        LCMProviderContext *lcmContext = providerContext->lcmProviderContext;
        MI_Boolean whatifEnabled=CAWhatIfEnabled(provContext);     
        if((lcmContext->executionMode & LCM_EXECUTIONMODE_ONLINE) && lcmContext->context)
        {
            MI_Char *fullMessage = NULL;
            size_t msgLen;
			msgLen = Tcslen(message) + Tcslen(providerContext->resourceId) + Tcslen(VERBOSE_FORMAT) + Tcslen(EMPTY_STRING) + Tcslen(g_CAJobInformation.deviceName) + TOKENIZED_MESSAGE_PADDING; //'ResourceId': <message>\0
            fullMessage = (MI_Char*) DSC_malloc(sizeof(MI_Char)*msgLen, NitsHere());

            if(fullMessage != NULL)
            {
				if (Stprintf(fullMessage, msgLen, VERBOSE_FORMAT,g_CAJobInformation.deviceName, EMPTY_STRING, providerContext->resourceId, message) >0)
                {
                    if(!whatifEnabled)
                    {
                        result = MI_Context_WriteVerbose((MI_Context*) lcmContext->context, fullMessage);
                    }
                    if(result != MI_RESULT_OK)
                    {
                        // Ignore the failure, this doesn't impact the functionality.
                    }
                }

                return fullMessage;
            }
        }
    }
    return NULL;
}
MI_Char* InhaleTextFile(MI_Char* filePath)
{
    long length;
    MI_Char * result;
    FILE * myfile = fopen (filePath, "r");
    if (myfile)
    {
        if ( fseek (myfile, 0, SEEK_END) == -1 )
        {
            return NULL;
        }
        if ( (length = ftell (myfile)) == -1 )
        {
            return NULL;
        }
        if ( fseek (myfile, 0, SEEK_SET) == -1 )
        {
            return NULL;
        }
        if ( (result = DSC_malloc ((length+1) * sizeof(MI_Char), NitsHere())) == NULL )
        {
            return NULL;
        }
        
        fread (result, 1, length, myfile);
        result[length] = '\0';
        fclose (myfile);
        return result;
    }
    else
    {
        return NULL;
    }
}                       
ssize_t readline(MI_Char **lineptr, size_t *n, FILE *stream)
{
	MI_Char ch;
	MI_Char *line = *lineptr;
	size_t allocated = *n;
	size_t length = 0;

	do {
		ch = fgetc(stream);
		if (ch == EOF)
			break;
		if (length + 1 >= allocated)
		{
			allocated += UNIT_LINE_SIZE;
			line = (MI_Char *)DSC_realloc(line, allocated * sizeof(MI_Char), NitsHere());
			if (line == NULL)
			{
				allocated = -1;
				break;
			}
		}
		line[length++] = ch;
	} while (ch != '\n');

	*n = allocated;

	if (length == 0 || allocated == -1)
		return -1;

	line[length] = '\0';
	*lineptr = line;
	return length;
}
/*caller will cleanup inputClassArray and outputClassArray*/
MI_Result UpdateClassArray(_In_ MI_ClassA *inputClassArray,
                           _Inout_ MI_ClassA *outputClassArray,
                           _Outptr_result_maybenull_ MI_Instance **extendedError,
                           _In_ MI_Boolean bInputUsingSerializedAPI)
{
    MI_Uint32 xCount = 0;
    size_t newSize = inputClassArray->size + outputClassArray->size;
    // Fail if newSize would be truncated later on
    if ( newSize > 0xFFFFFFFF )
    {
        return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_ENGINEHELPER_MEMORY_ERROR);
    }

    MI_Class **tempOutput = NULL;

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

    if( inputClassArray->size == 0 )
    {
        return MI_RESULT_OK;
    }
    tempOutput = (MI_Class **)DSC_malloc( newSize * sizeof(MI_Class*), NitsHere());
    if( tempOutput == NULL)
    {
        return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_ENGINEHELPER_MEMORY_ERROR);
    }
    /*Copy current list to bigger list*/
    for( xCount = 0 ; xCount < outputClassArray->size; xCount++)
    {
        tempOutput[xCount] = outputClassArray->data[xCount];
    }
    /*Copy new list to bigger list*/
    for( xCount = outputClassArray->size ; xCount < newSize; xCount++)
    {
        tempOutput[xCount] = inputClassArray->data[xCount - outputClassArray->size];
        inputClassArray->data[xCount - outputClassArray->size] = NULL;
    }

    /*Update pointers*/
    if( bInputUsingSerializedAPI)
        MI_Deserializer_ReleaseClassArray(inputClassArray);
    else
        DSC_free(inputClassArray->data);

    DSC_free(outputClassArray->data);
    outputClassArray->data = tempOutput;
    outputClassArray->size = newSize;
    return MI_RESULT_OK;

}
MI_Result GetRegisteredServerURLsFromCache(
    _Outptr_result_maybenull_z_ MI_Char** registeredServerURLs,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    MI_Value value;
    MI_Type  type;
    MI_Uint32 flags;
    size_t dwSize;
    int retValue;

    if (cimErrorDetails)
    {
        *cimErrorDetails = NULL;
    }

    memset(registeredServerURLs, 0, sizeof(MI_Char));

    if (g_DSCInternalCache)
    {
        if (DSC_MI_Instance_GetElement(g_DSCInternalCache, DSC_InternalStateCache_RegisteredServerURLs, &value, &type, &flags, NULL) == MI_RESULT_OK)
        {
            dwSize = Tcslen(value.string) + 1;
            *registeredServerURLs = (MI_Char*)DSC_malloc(dwSize*sizeof(MI_Char), NitsHere());
            if (*registeredServerURLs == NULL)
            {
                EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
            }
            memset(*registeredServerURLs, 0, dwSize);

            retValue = Stprintf(*registeredServerURLs, dwSize, MI_T("%T"), value.string);
            if (retValue == -1 || NitsShouldFault(NitsHere(), NitsAutomatic))
            {
                DSC_free(*registeredServerURLs);
                EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_LCMHELPER_PRINTF_ERROR));
            }
        }
    }

    EH_UNWIND:
        return MI_RESULT_OK;
}
MI_Result EnableShutdownPrivilege(
    _In_ HANDLE hToken,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    MI_Uint32 dwLen = 0;
    BOOL res = TRUE;
    BYTE *pBuffer;
    TOKEN_USER tu;
    TOKEN_PRIVILEGES * pPrivs = NULL;
    MI_Uint32 xCount = 0;

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

    memset(&tu, 0, sizeof(TOKEN_USER));
    res = GetTokenInformation(hToken, TokenPrivileges, &tu, sizeof(TOKEN_USER), (PDWORD)&dwLen);
    if (!res && ERROR_INSUFFICIENT_BUFFER !=  GetLastError())
    {

        return GetCimWin32Error(GetLastError(), cimErrorDetails, ID_LCMHELPER_COMPUTERNAMECONTEXT_ERROR);
    }

    pBuffer = (BYTE*)DSC_malloc(dwLen, NitsHere());
    if (pBuffer == NULL)
    {
        return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR);
    }

    res = GetTokenInformation(hToken, TokenPrivileges, pBuffer, dwLen, (PDWORD)&dwLen);
    if (!res && ERROR_INSUFFICIENT_BUFFER !=  GetLastError())
    {
        DSC_free(pBuffer);
        return GetCimWin32Error(GetLastError(), cimErrorDetails, ID_LCMHELPER_COMPUTERNAMECONTEXT_ERROR);
    }

    pPrivs = (TOKEN_PRIVILEGES*)(BYTE*)pBuffer;
    for (xCount = 0; xCount < pPrivs->PrivilegeCount; xCount++)
    {
        pPrivs->Privileges[xCount].Attributes |= SE_PRIVILEGE_ENABLED;
    }

    if (!AdjustTokenPrivileges(hToken, FALSE, pPrivs, 0, NULL, NULL))
    {
        DSC_free(pBuffer);
        return GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_LCMHELPER_COMPUTERNAMECONTEXT_ERROR);
    }

    DSC_free(pBuffer);
    return MI_RESULT_OK;
}
MI_Result InitializeServerURLs(
    _In_ RegistrationManager *self,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    self->serverURLs = (MI_Char**)DSC_malloc(NUMBEROFSERVERURLS * sizeof(MI_Char*), NitsHere());
    if (self->serverURLs == NULL)
    {
        EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
    }
    self->serverCertificateThumbprints = (MI_Char**)DSC_malloc(NUMBEROFSERVERURLS * sizeof(MI_Char*), NitsHere());
    if (self->serverCertificateThumbprints == NULL)
    {
        EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
    }
    self->numberOfServerURLs = 0;

    EH_UNWIND:
        return MI_RESULT_OK;
}
예제 #13
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;
}
MI_Result FormatServerURLsForDscCache(
    _In_ RegistrationManager *self,
    _Outptr_result_maybenull_z_ MI_Char** registeredServerURLs,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    MI_Result result = MI_RESULT_OK;
    size_t totalLengthOfServerURLs = 0;
    MI_Uint32 i = 0;

    for (i = 0; i < self->numberOfServerURLs; i++)
    {
        totalLengthOfServerURLs += Tcslen(self->serverURLs[i]);
        // Add 1 for ; between each ServerURL and thumbprint
        totalLengthOfServerURLs += 1;

        totalLengthOfServerURLs += Tcslen(self->serverCertificateThumbprints[i]);
        // Add 1 for ; between each series
        totalLengthOfServerURLs += 1;
    }

    // For '\0'
    totalLengthOfServerURLs += 1;
    
    memset(registeredServerURLs, 0, sizeof(MI_Char));
    *registeredServerURLs = (MI_Char*)DSC_malloc(totalLengthOfServerURLs*sizeof(MI_Char), NitsHere());
    if (*registeredServerURLs == NULL)
    {
        EH_Fail_(GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR));
    }
    memset(*registeredServerURLs, 0, totalLengthOfServerURLs);

    for (i = 0; i < self->numberOfServerURLs; i++)
    {
        *registeredServerURLs = Tcscat(*registeredServerURLs, totalLengthOfServerURLs, self->serverURLs[i]);
        if (*registeredServerURLs == NULL)
        {
            EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_ENGINEHELPER_CAT_ERROR));
        }
        *registeredServerURLs = Tcscat(*registeredServerURLs, totalLengthOfServerURLs, ";");
        if (*registeredServerURLs == NULL)
        {
            EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_ENGINEHELPER_CAT_ERROR));
        }
        *registeredServerURLs = Tcscat(*registeredServerURLs, totalLengthOfServerURLs, self->serverCertificateThumbprints[i]);
        if (*registeredServerURLs == NULL)
        {
            EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_ENGINEHELPER_CAT_ERROR));
        }
        *registeredServerURLs = Tcscat(*registeredServerURLs, totalLengthOfServerURLs, ";");
        if (*registeredServerURLs == NULL)
        {
            EH_Fail_(GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_ENGINEHELPER_CAT_ERROR));
        }
    }

    EH_UNWIND:
        return result;
}
MI_Result UpdateTask(
    _In_z_ MI_Char* taskName,
    _In_z_ MI_Char* taskTime,
    _In_ MI_Uint32 refreshFrequencyInSeconds,
    _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result r = MI_RESULT_OK;
    PROCESS_INFORMATION ProcInfo;
    STARTUPINFO si;
    HRESULT hr = S_OK;
    MI_Uint32 dwExitCode = 0;
    BOOL bRes = MI_TRUE;
    UINT retVal = 0;
    HANDLE hXmlFileHandle = NULL;
    BOOL bHandleUsageSuccess = FALSE;
    const char BOM [] = {0xFF, 0xFE};
    MI_Uint32 dwWmiMethodArg = 0;
    size_t sFormattedXMLFileLength = 0;

    // The task scheduler filename
    // This will double as the buffer for GetTempPath and for the command
    wchar_t wSchedTaskPath[MAX_PATH];
    wchar_t wTmpFilePath[MAX_PATH];
    wchar_t wSchedTaskFile[(sizeof(LocalConfigManagerTaskXMLFormatString)+sizeof(L"2013-04-11T18:10:48")+sizeof("2678400"))/sizeof(wchar_t)];
    wchar_t wSchedTaskParam[LCM_MAX_PATH];
    MI_Uint32 len = 0;

    LPWSTR wCommandFormat = NULL;

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

    wSchedTaskPath[0] = L'\0';
    wTmpFilePath[0] = L'\0';
    wSchedTaskFile[0] = L'\0';
    wSchedTaskParam[0] = L'\0';
    memset(&si,0,sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_FORCEOFFFEEDBACK;

    if (refreshFrequencyInSeconds > THIRTY_ONE_DAYS_IN_SECONDS)
    {
        refreshFrequencyInSeconds = THIRTY_ONE_DAYS_IN_SECONDS;
    }
    if (refreshFrequencyInSeconds < FIFTEEN_MINUTES_IN_SECONDS)
    {
        refreshFrequencyInSeconds = THIRTY_ONE_DAYS_IN_SECONDS;
    }



    wCommandFormat = LocalConfigManagerTaskConsistencyCommand;
    dwWmiMethodArg = 1;

    retVal = GetTempPath(MAX_PATH, wSchedTaskPath);
    if (!retVal)
    {
        hr = E_FAIL;
        return GetCimError(hr, extendedError, ID_LCMHELPER_GETTEMPPATH_ERROR);
    }

    // 0 here signifies our willingness to let the system create and close the file for us
    // This means we cannot specify FILE_ATTRIBUTE_TEMPORARY to CreateFile
    // but in return we can be sure that nobody will take our filename in the microsecond before we use it
    retVal = GetTempFileName(wSchedTaskPath, L"LCM", 0u, wTmpFilePath);
    if (!retVal)
    {
        hr = E_FAIL;
        return GetCimError(hr, extendedError, ID_LCMHELPER_GETTEMPFILENAME_ERROR);
    }

    hr = StringCchPrintf(wSchedTaskParam, sizeof(wSchedTaskParam)/sizeof(wchar_t), wCommandFormat, wTmpFilePath);
    if (FAILED(hr) || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if (SUCCEEDED(hr)) hr = E_FAIL;
        return GetCimError(hr, extendedError, ID_LCMHELPER_PRINTF_ERROR);
    }

    if (GetEnvironmentVariable(L"windir", wSchedTaskPath, MAX_PATH) ==0 )
    {
        return  GetCimWin32Error(GetLastError(), extendedError, ID_MODMAN_WINDIRENV_FAILED);
    }

    hr = StringCchCatW(wSchedTaskPath, MAX_PATH, L"\\system32\\schtasks.exe");
    if (FAILED(hr))
    {
        return GetCimError(hr, extendedError, ID_ENGINEHELPER_CAT_ERROR);
    }

    hr = StringCchPrintf(wSchedTaskFile, sizeof(wSchedTaskFile)/sizeof(wchar_t), LocalConfigManagerTaskXMLFormatString, refreshFrequencyInSeconds, taskTime, dwWmiMethodArg);
    if (FAILED(hr) || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if( SUCCEEDED(hr)) hr = E_FAIL;
        return GetCimError(hr, extendedError, ID_LCMHELPER_PRINTF_ERROR);
    }

    hr = StringCchLength(wSchedTaskFile, STRSAFE_MAX_CCH, &sFormattedXMLFileLength);
    if (FAILED(hr) || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if( SUCCEEDED(hr)) hr = E_FAIL;
        return GetCimError(hr, extendedError, ID_LCMHELPER_STRLEN_ERROR);
    }

    // We've done everything we can do ahead of time. Now we actually start changing the system

    hXmlFileHandle = CreateFile(wTmpFilePath, GENERIC_WRITE, 0 /* Prevent sharing */, NULL /* Children don't inherit */, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /* No template */);
    if (hXmlFileHandle == INVALID_HANDLE_VALUE)
    {
        return GetCimWin32Error(GetLastError(), extendedError, ID_ENGINEHELPER_OPENFILE_ERROR);
    }

    bHandleUsageSuccess = WriteFile(hXmlFileHandle, BOM, sizeof(BOM), (LPDWORD)&len, NULL);
    if (!bHandleUsageSuccess)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        CloseHandle(hXmlFileHandle);
        DeleteFile(wTmpFilePath);
        return GetCimError(hr, extendedError, ID_LCMHELPER_WRITEFILE_ERROR);
    }

    bHandleUsageSuccess = WriteFile(hXmlFileHandle, wSchedTaskFile, (DWORD)(sFormattedXMLFileLength*sizeof(wchar_t)), (LPDWORD)&len, NULL);
    if (!bHandleUsageSuccess)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        CloseHandle(hXmlFileHandle);
        DeleteFile(wTmpFilePath);
        return GetCimError(hr, extendedError, ID_LCMHELPER_WRITEFILE_ERROR);
    }

    bHandleUsageSuccess = CloseHandle(hXmlFileHandle);
    if (!bHandleUsageSuccess)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        DeleteFile(wTmpFilePath);
        return GetCimError(hr, extendedError, ID_LCMHELPER_CLOSEHANDLE_ERROR);
    }

    bRes = CreateProcess(wSchedTaskPath, wSchedTaskParam, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &ProcInfo);
    if (!bRes)
    {
        CloseHandle(hXmlFileHandle);
        DeleteFile(wTmpFilePath);
        return GetCimWin32Error(GetLastError(), extendedError, ID_ENGINEHELPER_CREATEPROCESS_ERROR);
    }

    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    if (GetExitCodeProcess(ProcInfo.hProcess,(LPDWORD)&dwExitCode) && dwExitCode != 0)
    {
        r = GetCimMIError(MI_RESULT_FAILED, extendedError, ID_ENGINEHELPER_CREATEPROCESS_ERROR);
    }

    bHandleUsageSuccess = DeleteFile(wTmpFilePath);
    if (!bHandleUsageSuccess && r == MI_RESULT_OK)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        return GetCimError(hr, extendedError, ID_LCMHELPER_DELETEFILE_ERROR);
    }

    CloseHandle(ProcInfo.hThread);
    CloseHandle(ProcInfo.hProcess);

    return r;
}
MI_Result RegisterStartAtBootTask(
    _In_ MI_Boolean bregisterTask,
    _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Result r = MI_RESULT_OK;
    PROCESS_INFORMATION ProcInfo;
    STARTUPINFO si;
    HRESULT hr = S_OK;
    MI_Uint32 dwExitCode = 0;
    BOOL bRes = MI_TRUE;
    wchar_t param[LCM_MAX_PATH] ;
    wchar_t wExe[LCM_MAX_PATH];
    DSC_EventWriteMessageScheduleTaskAfterReboot();

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

    wExe[0] = L'\0';
    param[0] = L'\0';
    memset(&si,0,sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_FORCEOFFFEEDBACK;

    if (bregisterTask)
    {
        hr = StringCchPrintf(param, LCM_MAX_PATH, L" /Create /SC ONSTART /TN \"%s\" /RU System /F /TR \"PowerShell.exe -NonInt -Window Hidden -Command \'Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration -ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]2 }\'\"",
                             DSC_RESTART_BOOTUP_TASK);
    }
    else
    {
        hr = StringCchPrintf(param, LCM_MAX_PATH, L" /Delete /F /TN \"%s\" ", DSC_RESTART_BOOTUP_TASK);
    }


    if (FAILED(hr) || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if (SUCCEEDED(hr)) hr = E_FAIL;
        return GetCimError(hr, extendedError, ID_LCMHELPER_PRINTF_ERROR);
    }
    if(GetEnvironmentVariable(L"windir", wExe, LCM_MAX_PATH) ==0 )
    {
        return  GetCimWin32Error(GetLastError(), extendedError, ID_MODMAN_WINDIRENV_FAILED);
    }
    hr = StringCchCatW(wExe, LCM_MAX_PATH, L"\\system32\\schtasks.exe");
    if( FAILED(hr))
    {
        return GetCimError(hr, extendedError, ID_ENGINEHELPER_CAT_ERROR);
    }

    bRes = CreateProcess(wExe, param,
                         NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &ProcInfo);
    if (!bRes)
    {
        return  GetCimWin32Error(GetLastError(), extendedError, ID_ENGINEHELPER_CREATEPROCESS_ERROR);
    }

    WaitForSingleObject( ProcInfo.hProcess, INFINITE);
    if (GetExitCodeProcess(ProcInfo.hProcess,(LPDWORD)&dwExitCode) && dwExitCode != 0)
    {
        r = GetCimMIError(MI_RESULT_FAILED, extendedError, ID_ENGINEHELPER_CREATEPROCESS_ERROR);
    }

    CloseHandle(ProcInfo.hThread);
    CloseHandle(ProcInfo.hProcess);

    return r;
}
예제 #17
0
MI_Result ResolvePath(_Outptr_opt_result_maybenull_z_ MI_Char **envResolvedPath,
                      _Outptr_opt_result_maybenull_z_ MI_Char **searchPath,
                      _In_z_ const MI_Char *envPath,
                      _In_z_ const MI_Char *searchPattern,
                      _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    MI_Uint32 dwReturnSizeInitial = 0, dwReturnSize = (MI_Uint32) (Tcslen(envPath)+1);
    int result = 0;
    const MI_Char *pathToUse = envPath;

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

    if( searchPath)
    {
        *searchPath = NULL;
    }

    if( envResolvedPath != NULL )
    {
#if defined(_MSC_VER)
        dwReturnSizeInitial = ExpandEnvironmentStrings(envPath, NULL, 0);
#else
        dwReturnSizeInitial = Tcslen(envPath) + 1;
#endif

        *envResolvedPath = (MI_Char*)DSC_malloc(dwReturnSizeInitial* sizeof(MI_Char), NitsHere());
        if( *envResolvedPath == NULL)
        {
            return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_LCMHELPER_MEMORY_ERROR);
        }

#if defined(_MSC_VER)
        dwReturnSize = ExpandEnvironmentStrings(envPath, *envResolvedPath, dwReturnSizeInitial);
        if( dwReturnSize == 0 || (dwReturnSize >  dwReturnSizeInitial ) || NitsShouldFault(NitsHere(), NitsAutomatic))
        {
            //memory error
            DSC_free(*envResolvedPath);
            *envResolvedPath = NULL;
            return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_LCMHELPER_EXPANDENV_FAILED);
        }
#else
        memcpy(*envResolvedPath, envPath, dwReturnSizeInitial * sizeof(MI_Char));
#endif
        pathToUse = *envResolvedPath;
    }

    if( searchPath != NULL)
    {

        dwReturnSize += (MI_Uint32) (Tcslen(searchPattern) + 1);// %s\\%s

        /* Create Search Path*/
        *searchPath = (MI_Char*)DSC_malloc(dwReturnSize* sizeof(MI_Char), NitsHere()); // %s\\%s
        if( *searchPath == NULL)
        {
            if( envResolvedPath != NULL )
            {
                DSC_free(*envResolvedPath);
                *envResolvedPath = NULL;
            }
            return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, ID_LCMHELPER_MEMORY_ERROR);
        }
#if defined(_MSC_VER)
        result = Stprintf(*searchPath, dwReturnSize, MI_T("%T\\%T"), pathToUse, searchPattern);
#else
        result = Stprintf(*searchPath, dwReturnSize, MI_T("%T/%T"), pathToUse, searchPattern);
#endif

        if( result <= 0 || NitsShouldFault(NitsHere(), NitsAutomatic))
        {
            if( envResolvedPath != NULL )
            {
                DSC_free(*envResolvedPath);
                *envResolvedPath = NULL;
            }

            DSC_free(*searchPath);
            return GetCimMIError(MI_RESULT_FAILED, extendedError, ID_LCMHELPER_PRINTF_ERROR);
        }
    }
    return MI_RESULT_OK;
}
예제 #18
0
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;
}
/*Function to perform registration*/
MI_Result Register(
    _In_ RegistrationManager* self,
    _In_ RegistrationRequest* request,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    MI_Result result = MI_RESULT_OK;
    MI_Instance* registrationPayload = NULL;
    MI_Uint32 getActionStatusCode;
    MI_Char* resultStatus = NULL;
    MI_Char* thumbprint = NULL;
    MI_Value value;
    MI_Uint32 flags;
    int systemResult = 0;

    if (cimErrorDetails)
    {
        *cimErrorDetails = NULL;
    }


    // Check if RegistrationKey is specified. If not specified, do not attempt to register.
    result = MI_Instance_GetElement(request->registrationData, MSFT_RegistrationKey_Name, &value, NULL, &flags, NULL);
    if (result != MI_RESULT_OK || flags & MI_FLAG_NULL || value.string == NULL || value.string[0] == '\0')
    {
	return MI_RESULT_OK;
    }


    if ( (access(OAAS_KEYPATH, F_OK) == -1) || (access(OAAS_CERTPATH, F_OK) == -1) )
    {
        system("touch "  OAAS_KEYPATH "; chmod 0600 "  OAAS_KEYPATH);
        system("touch "  OAAS_KEYPATH "_old; chmod 0600 "  OAAS_KEYPATH "_old");
        systemResult = system("openssl req -subj '/CN=DSC-OaaS' -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout " OAAS_KEYPATH "_old -out " OAAS_CERTPATH " && openssl rsa -in " OAAS_KEYPATH "_old -out " OAAS_KEYPATH " && rm -f " OAAS_KEYPATH "_old");
        if (systemResult != 0 && errno != 10)
        {
            DSC_EventWriteLCMServerRegCertGenFailed(g_ConfigurationDetails.jobGuidString, self->agentId);
            return GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_PULL_FAILEDTOGENERATECERT);
        }
        
        systemResult = system("openssl x509 -noout -in " OAAS_CERTPATH " -fingerprint | sed 's/^.*=//' > " OAAS_THUMBPRINTPATH);
        if (systemResult != 0 && errno != 10)
        {
            DSC_EventWriteLCMServerRegCertGenFailed(g_ConfigurationDetails.jobGuidString, self->agentId);
            return GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_PULL_FAILEDTOGENERATECERT);
        }
        
        {
            long length;
            FILE * fingerprint_file = fopen (OAAS_THUMBPRINTPATH, "r");
            if (fingerprint_file)
            {
                fseek (fingerprint_file, 0, SEEK_END);
                length = ftell (fingerprint_file);
                fseek (fingerprint_file, 0, SEEK_SET);
                thumbprint = DSC_malloc (length * sizeof(MI_Char), NitsHere());
                fread (thumbprint, 1, length, fingerprint_file);
                // There's a newline at the end, so null terminate overwriting it.
                thumbprint[length-1] = '\0';
                fclose (fingerprint_file);
            }
            else
            {
                DSC_EventWriteLCMServerRegCertGenFailed(g_ConfigurationDetails.jobGuidString, self->agentId);
                return MI_RESULT_FAILED;
            }
        }

        // Cache this URL.
        // result = CacheServerURL(self, request->registrationData, thumbprint, cimErrorDetails);
        //EH_CheckResult(result);

        // Write this cache to DSC Cache
        //result = UpdateServerURLsToDSCCache(self, cimErrorDetails);
        //EH_CheckResult(result);
    }

    result = GetAgentInformation(&registrationPayload);
    EH_CheckResult(result);

    result = LCM_Do_Register((MI_Instance *)g_metaConfig, request->registrationData, self->agentId, thumbprint, 
                             registrationPayload, &request->configurationNames, request->typeOfManagerInstance, &resultStatus, &getActionStatusCode, cimErrorDetails);
    EH_CheckResult(result);

    EH_UNWIND:

    if (registrationPayload != NULL)
    {
        MI_Instance_Delete(registrationPayload);
    }
    if (thumbprint != NULL)
    {
        DSC_free(thumbprint);
    }
#ifdef _MSC_VER
    DSC_GlobalFree(resultStatus);
#else
    DSC_free(resultStatus);
#endif
    return result;
}
MI_Result UpdateTask(
    _In_z_ MI_Char* taskName,
    _In_z_ MI_Char* taskTime,
    _In_ MI_Uint32 refreshFrequencyInSeconds,
    _Outptr_result_maybenull_ MI_Instance **extendedError)
{
    int retValue = -1;
    ssize_t read = 0;
    size_t readLength = 0, writeLength = 0;
	MI_Char *line = NULL, *lineToWrite = NULL, *taskInCrontab = NULL;
	FILE *cronFile = NULL, *cronFileTmp = NULL;
	MI_Uint32 errorCode = 0;

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


    // Preparation
    if (refreshFrequencyInSeconds > THIRTY_ONE_DAYS_IN_SECONDS)
    {
		refreshFrequencyInSeconds = THIRTY_ONE_DAYS_IN_SECONDS;
    }
    if (refreshFrequencyInSeconds < FIFTEEN_MINUTES_IN_SECONDS)
    {
		refreshFrequencyInSeconds = FIFTEEN_MINUTES_IN_SECONDS;
    }

    // PLAN 1 -- process each line of crontab file to a tmp file and then copy tmp file back
    // taskTime string is not used in Linux since we can simply register a task with frequency

	// Allocate memory
	line = (MI_Char *)DSC_malloc(UNIT_LINE_SIZE * sizeof(MI_Char), NitsHere());
	if (line == NULL)
	{
		errorCode = ID_LCMHELPER_MEMORY_ERROR;
		goto ExitWithError;
	}
    lineToWrite = (MI_Char *)DSC_malloc(UNIT_LINE_SIZE * sizeof(MI_Char), NitsHere());
	if (lineToWrite == NULL)
	{
		errorCode = ID_LCMHELPER_MEMORY_ERROR;
		goto ExitWithError;
	}
	taskInCrontab = (MI_Char *)DSC_malloc(UNIT_LINE_SIZE * sizeof(MI_Char), NitsHere());
	if (taskInCrontab == NULL)
	{
		errorCode = ID_LCMHELPER_MEMORY_ERROR;
		goto ExitWithError;
	}

	// Open files
	if (File_ExistT(CRON_FILE) != -1)
	{
		cronFile = File_OpenT(CRON_FILE, MI_T("r"));
		if (cronFile == NULL)
		{
			// Fail to open existing cron file should lead to error exit
			errorCode = ID_ENGINEHELPER_OPENFILE_ERROR;
			goto ExitWithError;
		}
	}
    cronFileTmp = File_OpenT(CRON_FILE_TMP, MI_T("w"));
    if (cronFileTmp == NULL)
	{
		// Fail to create tmp file should lead to error exit
		errorCode = ID_LCMHELPER_CREATEFILE_ERROR;
		goto ExitWithError;
    }

	// Read and process crontab file if it exists and opens appropriately
    while (cronFile != NULL && (read = readline(&line, &readLength, cronFile)) != -1)
    {
        retValue = TcsStrlcpy(lineToWrite, line, Tcslen(line)+1);
		retValue = sscanf(line, MI_T("%*s %*s %*s %*s %*s %*s %s"), taskInCrontab);
		if (retValue == 0)
		{
			// Ignore the bad line that does not comply with crontab file format
			continue;
		}
		else
		{
			if (Tcsncasecmp(taskName, taskInCrontab, Tcslen(taskName)) == 0)
			{
				// Ignore entry that duplicates registration of task
				continue;
			}
			else
			{
				// Write the entry to tmp file
				writeLength = fwrite(lineToWrite, 1, Tcslen(lineToWrite), cronFileTmp);
				if (writeLength != read)
				{
					errorCode = ID_LCMHELPER_WRITEFILE_ERROR;
					goto ExitWithError;
				}
			}
		}
    }
    if (readLength == -1)
	{
		// Deal memory failure in readline function
		errorCode = ID_ENGINEHELPER_READFILE_ERROR;
		goto ExitWithError;
	}

    // Add the task entry
    retValue = Stprintf(lineToWrite, UNIT_LINE_SIZE, MI_T("*/%d * * * * root %T\n"), refreshFrequencyInSeconds / 60, taskName);
	if (retValue == -1)
	{
		errorCode = ID_LCMHELPER_PRINTF_ERROR;
		goto ExitWithError;
	}
    writeLength = fwrite(lineToWrite, 1, Tcslen(lineToWrite), cronFileTmp);
	if (writeLength != Tcslen(lineToWrite))
	{
		errorCode = ID_LCMHELPER_WRITEFILE_ERROR;
		goto ExitWithError;
	}

	if (cronFile != NULL)
		File_Close(cronFile);
    File_Close(cronFileTmp);

    File_CopyT(CRON_FILE_TMP, CRON_FILE);
    File_RemoveT(CRON_FILE_TMP);    
    
    DSC_free(line);
    DSC_free(lineToWrite);
	DSC_free(taskInCrontab);

    return MI_RESULT_OK;

ExitWithError:
	// Close files and remove temp file if it exists
	if (cronFile)
		File_Close(cronFile);
	if (cronFileTmp)
		File_Close(cronFileTmp);
    if (File_ExistT(CRON_FILE_TMP) != -1)
        File_RemoveT(CRON_FILE_TMP);
	
	// Free memory allocations
	if (line != NULL)
		DSC_free(line);
	if (lineToWrite != NULL)
		DSC_free(lineToWrite);
	if (taskInCrontab != NULL)
		DSC_free(taskInCrontab);

	// Form rich CIM error
	if (errorCode != 0)
		return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, extendedError, errorCode);
	else
		return MI_RESULT_FAILED;
}
MI_Result RepudicationHelper(
    _In_opt_ MI_Context* context,
    _In_ HANDLE token,
    _In_z_ const MI_Char* methodName,
    _Outptr_result_maybenull_ MI_Instance **cimErrorDetails)
{
    MI_Type type;
    MI_Value value;
    MI_Result result;
    size_t computerLength;
    DWORD sidLength;
    MI_Char* pComputerName=NULL;
    BOOL success = FALSE;
    PWSTR pstrUserSid = NULL;
    PTOKEN_USER userInformation = NULL;
    LCMProviderContext lcmContext = {0};

    if (context)
    {
        result = MI_Context_GetCustomOption(context,DSCCOMPUTERNAME, &type, &value);
        if (result == MI_RESULT_OK && type == MI_STRING)
        {
            computerLength = Tcslen(value.string)+1;
            pComputerName = (MI_Char*)DSC_malloc(computerLength* sizeof(wchar_t), NitsHere());
            if (pComputerName == NULL)
            {
                return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR);
            }

            memcpy(pComputerName, value.string, computerLength * sizeof(wchar_t));
        }
    }

    GetTokenInformation(token, TokenUser, userInformation, 0, &sidLength);
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if (pComputerName != NULL)
        {
            DSC_free(pComputerName);
        }

        return GetCimMIError(MI_RESULT_FAILED, cimErrorDetails, ID_LCMHELPER_COMPUTERNAMECONTEXT_ERROR);
    }

    userInformation = (PTOKEN_USER)DSC_malloc(sidLength, NitsHere());
    if (userInformation == NULL)
    {
        if (pComputerName != NULL)
        {
            DSC_free(pComputerName);
        }

        return GetCimMIError(MI_RESULT_SERVER_LIMITS_EXCEEDED, cimErrorDetails, ID_LCMHELPER_MEMORY_ERROR);
    }

    success = GetTokenInformation(token, TokenUser, userInformation, sidLength, &sidLength);
    if (!success || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if (pComputerName != NULL)
        {
            DSC_free(pComputerName);
        }

        DSC_free(userInformation);

        if (success)
        {
            // Pass through a bogus error if we've faulted in an error otherwise success will be returned.
            SetLastError(ERROR_ACCESS_DENIED);
        }
        return GetCimWin32Error(MI_RESULT_FAILED, cimErrorDetails, GetLastError());
    }

    success = ConvertSidToStringSidW(userInformation->User.Sid, &pstrUserSid);
    DSC_free(userInformation);
    if (!success || NitsShouldFault(NitsHere(), NitsAutomatic))
    {
        if (pComputerName != NULL)
        {
            DSC_free(pComputerName);
        }
        if (pstrUserSid != NULL)
        {
            LocalFree(pstrUserSid);
        }

        if (success)
        {
            // Pass through a bogus error if we've faulted in an error otherwise success will be returned.
            SetLastError(ERROR_ACCESS_DENIED);
        }
        return GetCimWin32Error(MI_RESULT_FAILED, cimErrorDetails, GetLastError());
    }

    lcmContext.executionMode = (LCM_EXECUTIONMODE_OFFLINE | LCM_EXECUTIONMODE_ONLINE);
    lcmContext.context = (void*)context;
    LCM_WriteMessageInfo(&lcmContext, pComputerName, MI_WRITEMESSAGE_CHANNEL_VERBOSE, pstrUserSid);
    LocalFree(pstrUserSid);
    if (pComputerName != NULL)
    {
        DSC_free(pComputerName);
    }

    return MI_RESULT_OK;
}