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; }
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; }
//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); } } } }
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); } } } }
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; }
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; }
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; }
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(®istrationPayload); 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; }