From 337124bed6a57b40fca11c5c2f5b554f570522a6 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 4 May 2021 11:41:55 -0700 Subject: Move ComPlus.wixext into ext --- src/ext/ComPlus/ca/cppartroleexec.cpp | 397 ++++++++++++++++++++++++++++++++++ 1 file changed, 397 insertions(+) create mode 100644 src/ext/ComPlus/ca/cppartroleexec.cpp (limited to 'src/ext/ComPlus/ca/cppartroleexec.cpp') diff --git a/src/ext/ComPlus/ca/cppartroleexec.cpp b/src/ext/ComPlus/ca/cppartroleexec.cpp new file mode 100644 index 00000000..4a503c79 --- /dev/null +++ b/src/ext/ComPlus/ca/cppartroleexec.cpp @@ -0,0 +1,397 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" + + +// private structs + +struct CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES +{ + int iActionType; + int iActionCost; + LPWSTR pwzKey; + LPWSTR pwzRoleName; + LPWSTR pwzAccount; + LPWSTR pwzPartID; +}; + + +// prototypes for private helper functions + +static HRESULT ReadUserInPartitionRoleAttributes( + LPWSTR* ppwzData, + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ); +static void FreeUserInPartitionRoleAttributes( + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ); +static HRESULT CreateUserInPartitionRole( + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ); +static HRESULT RemoveUserInPartitionRole( + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ); + + +// function definitions + +HRESULT CpiConfigureUsersInPartitionRoles( + LPWSTR* ppwzData, + HANDLE hRollbackFile + ) +{ + HRESULT hr = S_OK; + + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs; + ::ZeroMemory(&attrs, sizeof(attrs)); + + // read action text + hr = CpiActionStartMessage(ppwzData, FALSE); + ExitOnFailure(hr, "Failed to send action start message"); + + // ger count + int iCnt = 0; + hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); + ExitOnFailure(hr, "Failed to read count"); + + // write count to rollback file + hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); + ExitOnFailure(hr, "Failed to write count to rollback file"); + + for (int i = 0; i < iCnt; i++) + { + // read attributes from CustomActionData + hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs); + ExitOnFailure(hr, "Failed to read attributes"); + + // progress message + hr = CpiActionDataMessage(1, attrs.pwzRoleName); + ExitOnFailure(hr, "Failed to send progress messages"); + + if (S_FALSE == hr) + ExitFunction(); + + // write key to rollback file + hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); + ExitOnFailure(hr, "Failed to write key to rollback file"); + + // action + switch (attrs.iActionType) + { + case atCreate: + hr = CreateUserInPartitionRole(&attrs); + ExitOnFailure(hr, "Failed to add user to partition role, key: %S", attrs.pwzKey); + break; + case atRemove: + hr = RemoveUserInPartitionRole(&attrs); + ExitOnFailure(hr, "Failed to remove user from partition role, key: %S", attrs.pwzKey); + break; + } + + // write completion status to rollback file + hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); + ExitOnFailure(hr, "Failed to write completion status to rollback file"); + + // progress + hr = WcaProgressMessage(attrs.iActionCost, FALSE); + ExitOnFailure(hr, "Failed to update progress"); + } + + hr = S_OK; + +LExit: + // clean up + FreeUserInPartitionRoleAttributes(&attrs); + + return hr; +} + +HRESULT CpiRollbackConfigureUsersInPartitionRoles( + LPWSTR* ppwzData, + CPI_ROLLBACK_DATA* pRollbackDataList + ) +{ + HRESULT hr = S_OK; + + int iRollbackStatus; + + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs; + ::ZeroMemory(&attrs, sizeof(attrs)); + + // read action text + hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); + ExitOnFailure(hr, "Failed to send action start message"); + + // get count + int iCnt = 0; + hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); + ExitOnFailure(hr, "Failed to read count"); + + for (int i = 0; i < iCnt; i++) + { + // read attributes from CustomActionData + hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs); + ExitOnFailure(hr, "Failed to read attributes"); + + // rollback status + hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); + + if (S_FALSE == hr) + continue; // not found, nothing to rollback + + // progress message + hr = CpiActionDataMessage(1, attrs.pwzRoleName); + ExitOnFailure(hr, "Failed to send progress messages"); + + if (S_FALSE == hr) + ExitFunction(); + + // action + switch (attrs.iActionType) + { + case atCreate: + hr = CreateUserInPartitionRole(&attrs); + if (FAILED(hr)) + WcaLog(LOGMSG_STANDARD, "Failed to add user to partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey); + break; + case atRemove: + hr = RemoveUserInPartitionRole(&attrs); + if (FAILED(hr)) + WcaLog(LOGMSG_STANDARD, "Failed to remove user from partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey); + break; + } + + // check rollback status + if (0 == iRollbackStatus) + continue; // operation did not complete, skip progress + + // progress + hr = WcaProgressMessage(attrs.iActionCost, FALSE); + ExitOnFailure(hr, "Failed to update progress"); + } + + hr = S_OK; + +LExit: + // clean up + FreeUserInPartitionRoleAttributes(&attrs); + + return hr; +} + + +// helper function definitions + +static HRESULT ReadUserInPartitionRoleAttributes( + LPWSTR* ppwzData, + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ) +{ + HRESULT hr = S_OK; + + hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); + ExitOnFailure(hr, "Failed to read action type"); + hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); + ExitOnFailure(hr, "Failed to read action cost"); + hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); + ExitOnFailure(hr, "Failed to read key"); + hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName); + ExitOnFailure(hr, "Failed to read role name"); + hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); + ExitOnFailure(hr, "Failed to read account name"); + hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); + ExitOnFailure(hr, "Failed to read partition id"); + + hr = S_OK; + +LExit: + return hr; +} + +static void FreeUserInPartitionRoleAttributes( + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ) +{ + ReleaseStr(pAttrs->pwzKey); + ReleaseStr(pAttrs->pwzRoleName); + ReleaseStr(pAttrs->pwzAccount); + ReleaseStr(pAttrs->pwzPartID); +} + +static HRESULT CreateUserInPartitionRole( + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + ICatalogCollection* piUsrInRoleColl = NULL; + ICatalogObject* piUsrInRoleObj = NULL; + + PSID pSid = NULL; + long lChanges = 0; + + // log + WcaLog(LOGMSG_VERBOSE, "Adding user to partition role, key: %S", pAttrs->pwzKey); + + // get users in partition role collection + hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl); + if (S_FALSE == hr) + hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + ExitOnFailure(hr, "Failed to get users in partition role collection"); + + // get SID for account + do { + er = ERROR_SUCCESS; + hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); + if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) + { + WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); + er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); + switch (er) + { + case IDABORT: + ExitFunction(); // exit with error code from CpiAccountNameToSid() + case IDRETRY: + break; + case IDIGNORE: + default: + ExitFunction1(hr = S_OK); + } + } + else + ExitOnFailure(hr, "Failed to get SID for account"); + } while (IDRETRY == er); + + // find any existing entry + hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL); + if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) + WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); + else + ExitOnFailure(hr, "Failed to find user in partition role"); + + if (S_OK == hr) + { + WcaLog(LOGMSG_VERBOSE, "User already assigned to partition role, key: %S", pAttrs->pwzKey); + ExitFunction(); // exit with hr = S_OK + } + + // convert SID back to account name + hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount); + ExitOnFailure(hr, "Failed to convert SID to account name"); + + // add user + hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj); + ExitOnFailure(hr, "Failed to add user in role to collection"); + + hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount); + ExitOnFailure(hr, "Failed to set role name property"); + + // save changes + hr = piUsrInRoleColl->SaveChanges(&lChanges); + if (COMADMIN_E_OBJECTERRORS == hr) + CpiLogCatalogErrorInfo(); + ExitOnFailure(hr, "Failed to save changes"); + + // log + WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); + + hr = S_OK; + +LExit: + // clean up + ReleaseObject(piUsrInRoleColl); + ReleaseObject(piUsrInRoleObj); + + if (pSid) + ::HeapFree(::GetProcessHeap(), 0, pSid); + + return hr; +} + +static HRESULT RemoveUserInPartitionRole( + CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + ICatalogCollection* piUsrInRoleColl = NULL; + + PSID pSid = NULL; + long lChanges = 0; + + // log + WcaLog(LOGMSG_VERBOSE, "Removing user from partition role, key: %S", pAttrs->pwzKey); + + // get users in partition role collection + hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl); + ExitOnFailure(hr, "Failed to get users in partition role collection"); + + if (S_FALSE == hr) + { + // users in role collection not found + WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in partition role collection, nothing to delete, key: %S", pAttrs->pwzKey); + ExitFunction1(hr = S_OK); + } + + // get SID for account + do { + er = ERROR_SUCCESS; + hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); + if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) + { + WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); + er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); + switch (er) + { + case IDABORT: + ExitFunction(); // exit with error code from CpiAccountNameToSid() + case IDRETRY: + break; + case IDIGNORE: + default: + ExitFunction1(hr = S_OK); + } + } + else + ExitOnFailure(hr, "Failed to get SID for account"); + } while (IDRETRY == er); + + // remove + hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid); + if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) + { + WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); + hr = S_FALSE; + } + else + ExitOnFailure(hr, "Failed to remove user"); + + if (S_FALSE == hr) + { + // role not found + WcaLog(LOGMSG_VERBOSE, "User not found for partition role, nothing to delete, key: %S", pAttrs->pwzKey); + ExitFunction1(hr = S_OK); + } + + // save changes + hr = piUsrInRoleColl->SaveChanges(&lChanges); + if (COMADMIN_E_OBJECTERRORS == hr) + CpiLogCatalogErrorInfo(); + ExitOnFailure(hr, "Failed to save changes"); + + // log + WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); + + hr = S_OK; + +LExit: + // clean up + ReleaseObject(piUsrInRoleColl); + + if (pSid) + ::HeapFree(::GetProcessHeap(), 0, pSid); + + return hr; +} -- cgit v1.2.3-55-g6feb