Ejemplo n.º 1
0
static HRESULT ReadMessageQueueAttributes(
	LPWSTR* ppwzData,
	MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
	)
{
	HRESULT hr = S_OK;

	// read message queue information from custom action data
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
	ExitOnFailure(hr, "Failed to read key from custom action data");
	hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iBasePriority);
	ExitOnFailure(hr, "Failed to read base priority from custom action data");
	hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iJournalQuota);
	ExitOnFailure(hr, "Failed to read journal quota from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzLabel);
	ExitOnFailure(hr, "Failed to read label from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzMulticastAddress);
	ExitOnFailure(hr, "Failed to read multicast address from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPathName);
	ExitOnFailure(hr, "Failed to read path name from custom action data");
	hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iPrivLevel);
	ExitOnFailure(hr, "Failed to read privacy level from custom action data");
	hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iQuota);
	ExitOnFailure(hr, "Failed to read quota from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzServiceTypeGuid);
	ExitOnFailure(hr, "Failed to read service type guid from custom action data");
	hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iAttributes);
	ExitOnFailure(hr, "Failed to read attributes from custom action data");

	hr = S_OK;

LExit:
	return hr;
}
Ejemplo n.º 2
0
static HRESULT ReadApplicationRoleAttributes(
    LPWSTR* ppwzData,
    CPI_APPLICATION_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->pwzName);
    ExitOnFailure(hr, "Failed to read name");
    hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID);
    ExitOnFailure(hr, "Failed to read application id");
    hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
    ExitOnFailure(hr, "Failed to read partition id");
    hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList);
    ExitOnFailure(hr, "Failed to read properties");

    hr = S_OK;

LExit:
    return hr;
}
Ejemplo n.º 3
0
static HRESULT ReadUsersInApplicationRoleAttributes(
    LPWSTR* ppwzData,
    CPI_USER_IN_APPLICATION_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->pwzAppID);
    ExitOnFailure(hr, "Failed to read application id");
    hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
    ExitOnFailure(hr, "Failed to read partition id");

    hr = S_OK;

LExit:
    return hr;
}
Ejemplo n.º 4
0
HRESULT MqiRollbackRemoveMessageQueuePermissions(
	LPWSTR* ppwzData
	)
{
	HRESULT hr = S_OK;

	int iCnt = 0;

	MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs;
	::ZeroMemory(&attrs, sizeof(attrs));

	// ger count
	hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
	ExitOnFailure(hr, "Failed to read count");

	for (int i = 0; i < iCnt; i++)
	{
		// read attributes from CustomActionData
		hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs);
		ExitOnFailure(hr, "Failed to read attributes");

		// add message queue permission
		hr = SetMessageQueuePermissions(&attrs, FALSE);
		if (FAILED(hr))
			WcaLog(LOGMSG_STANDARD, "Failed to rollback remove message queue permission, hr: 0x%x, key: %S", hr, attrs.pwzKey);
	}

	hr = S_OK;

LExit:
	// clean up
	FreeMessageQueuePermissionAttributes(&attrs);

	return hr;
}
Ejemplo n.º 5
0
/******************************************************************
 ExecNetFx - entry point for NetFx Custom Action

*******************************************************************/
extern "C" UINT __stdcall ExecNetFx(
    __in MSIHANDLE hInstall
    )
{
//    AssertSz(FALSE, "debug ExecNetFx");

    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwz = NULL;
    int iCost = 0;

    // initialize
    hr = WcaInitialize(hInstall, "ExecNetFx");
    ExitOnFailure(hr, "failed to initialize");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    // loop through all the passed in data
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzData);
        ExitOnFailure(hr, "failed to read command line from custom action data");

        hr = WcaReadIntegerFromCaData(&pwz, &iCost);
        ExitOnFailure(hr, "failed to read cost from custom action data");

        hr = QuietExec(pwzData, NGEN_TIMEOUT);
        // If we fail here it isn't critical - keep looping through to try to act on the other assemblies on our list
        if (FAILED(hr))
        {
            WcaLog(LOGMSG_STANDARD, "failed to execute Ngen command (with error 0x%x): %ls, continuing anyway", hr, pwzData);
            hr = S_OK;
        }

        // Tick the progress bar along for this assembly
        hr = WcaProgressMessage(iCost, FALSE);
        ExitOnFailure1(hr, "failed to tick progress bar for command line: %ls", pwzData);
    }

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzData);

    if (FAILED(hr))
        er = ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Ejemplo n.º 6
0
HRESULT CpiReadPropertyList(
	LPWSTR* ppwzData,
	CPI_PROPERTY** ppPropList
	)
{
	HRESULT hr = S_OK;

	CPI_PROPERTY* pItm = NULL;
	LPWSTR pwzName = NULL;

	// clear list if it already contains items
	if (*ppPropList)
		CpiFreePropertyList(*ppPropList);
	*ppPropList = NULL;

	// read property count
	int iPropCnt = 0;
	hr = WcaReadIntegerFromCaData(ppwzData, &iPropCnt);
	ExitOnFailure(hr, "Failed to read property count");

	for (int i = 0; i < iPropCnt; i++)
	{
		// allocate new element
		pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY));
		if (!pItm)
			ExitFunction1(hr = E_OUTOFMEMORY);

		// Name
		hr = WcaReadStringFromCaData(ppwzData, &pwzName);
		ExitOnFailure(hr, "Failed to read name");
		StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzName);

		// Value
		hr = WcaReadStringFromCaData(ppwzData, &pItm->pwzValue);
		ExitOnFailure(hr, "Failed to read property value");

		// add to list
		if (*ppPropList)
			pItm->pNext = *ppPropList;
		*ppPropList = pItm;
		pItm = NULL;
	}

	hr = S_OK;

LExit:
	// clean up
	ReleaseStr(pwzName);

	if (pItm)
		CpiFreePropertyList(pItm);

	return hr;
}
Ejemplo n.º 7
0
static HRESULT ReadPartitionUserAttributes(
    LPWSTR* ppwzData,
    CPI_PARTITION_USER_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->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;
}
Ejemplo n.º 8
0
/******************************************************************
 WixRollbackInternetShortcuts - entry point for Internet shortcuts
    custom action (rollback)
*******************************************************************/
extern "C" UINT __stdcall WixRollbackInternetShortcuts(
    __in MSIHANDLE hInstall
)
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwz = NULL;
    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzShortcutPath = NULL;
    int iAttr = 0;

    // initialize
    hr = WcaInitialize(hInstall, "WixRemoveInternetShortcuts");
    ExitOnFailure(hr, "failed to initialize WixRemoveInternetShortcuts");

    hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    // loop through all the custom action data
    pwz = pwzCustomActionData;
    while (pwz && *pwz)
    {
        // extract the custom action data we're interested in
        hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath);
        ExitOnFailure(hr, "failed to read shortcut path from custom action data for rollback");

        // delete file
        hr = FileEnsureDelete(pwzShortcutPath);
        ExitOnFailure1(hr, "failed to delete file '%ls'", pwzShortcutPath);

        // skip over the shortcut target and attributes
        hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath);
        ExitOnFailure(hr, "failed to skip shortcut target from custom action data for rollback");
        hr = WcaReadIntegerFromCaData(&pwz, &iAttr);
        ExitOnFailure(hr, "failed to read shortcut attributes from custom action data");
    }

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzShortcutPath);

    er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er;
    return WcaFinalize(er);
}
Ejemplo n.º 9
0
HRESULT MqiRemoveMessageQueuePermissions(
	LPWSTR* ppwzData
	)
{
	HRESULT hr = S_OK;

	int iCnt = 0;

	MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs;
	::ZeroMemory(&attrs, sizeof(attrs));

	// ger count
	hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
	ExitOnFailure(hr, "Failed to read count");

	for (int i = 0; i < iCnt; i++)
	{
		// read attributes from CustomActionData
		hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs);
		ExitOnFailure(hr, "Failed to read attributes");

		// progress message
		hr = PcaActionDataMessage(1, attrs.pwzPathName);
		ExitOnFailure(hr, "Failed to send progress messages");

		// add message queue permission
		hr = SetMessageQueuePermissions(&attrs, TRUE);
		ExitOnFailure(hr, "Failed to remove message queue permission");

		// progress tics
		hr = WcaProgressMessage(COST_MESSAGE_QUEUE_PERMISSION_ADD, FALSE);
		ExitOnFailure(hr, "Failed to update progress");
	}

	hr = S_OK;

LExit:
	// clean up
	FreeMessageQueuePermissionAttributes(&attrs);

	return hr;
}
Ejemplo n.º 10
0
HRESULT MqiDeleteMessageQueues(
	LPWSTR* ppwzData
	)
{
	HRESULT hr = S_OK;

	int iCnt = 0;

	MQI_MESSAGE_QUEUE_ATTRIBUTES attrs;
	::ZeroMemory(&attrs, sizeof(attrs));

	// ger count
	hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
	ExitOnFailure(hr, "Failed to read count");

	for (int i = 0; i < iCnt; i++)
	{
		// read attributes from CustomActionData
		hr = ReadMessageQueueAttributes(ppwzData, &attrs);
		ExitOnFailure(hr, "Failed to read attributes");

		// progress message
		hr = PcaActionDataMessage(1, attrs.pwzPathName);
		ExitOnFailure1(hr, "Failed to send progress messages, key: %S", attrs.pwzKey);

		// create message queue
		hr = DeleteMessageQueue(&attrs);
		ExitOnFailure1(hr, "Failed to delete message queue, key: %S", attrs.pwzKey);

		// progress tics
		hr = WcaProgressMessage(COST_MESSAGE_QUEUE_DELETE, FALSE);
		ExitOnFailure(hr, "Failed to update progress");
	}

	hr = S_OK;

LExit:
	// clean up
	FreeMessageQueueAttributes(&attrs);

	return hr;
}
Ejemplo n.º 11
0
static HRESULT ReadMessageQueuePermissionAttributes(
	LPWSTR* ppwzData,
	MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
	)
{
	HRESULT hr = S_OK;

	// read message queue permission information from custom action data
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
	ExitOnFailure(hr, "Failed to read key from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPathName);
	ExitOnFailure(hr, "Failed to read path name from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzDomain);
	ExitOnFailure(hr, "Failed to read domain from custom action data");
	hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
	ExitOnFailure(hr, "Failed to read name from custom action data");
	hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iPermissions);
	ExitOnFailure(hr, "Failed to read permissions from custom action data");

	hr = S_OK;

LExit:
	return hr;
}
Ejemplo n.º 12
0
HRESULT CpiConfigureApplicationRoles(
    LPWSTR* ppwzData,
    HANDLE hRollbackFile
    )
{
    HRESULT hr = S_OK;

    CPI_APPLICATION_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 = ReadApplicationRoleAttributes(ppwzData, &attrs);
        ExitOnFailure(hr, "Failed to read attributes");

        // progress message
        hr = CpiActionDataMessage(1, attrs.pwzName);
        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 = CreateApplicationRole(&attrs);
            ExitOnFailure1(hr, "Failed to create application role, key: %S", attrs.pwzKey);
            break;
        case atRemove:
            hr = RemoveApplicationRole(&attrs);
            ExitOnFailure1(hr, "Failed to remove application 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
    FreeApplicationRoleAttributes(&attrs);

    return hr;
}
Ejemplo n.º 13
0
/******************************************************************
CaExecServiceConfig - entry point for ServiceConfig Custom Action.

NOTE: deferred CustomAction since it modifies the machine
NOTE: CustomActionData == wzServiceName\tfNewService\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\tfNewService\t...
*******************************************************************/
extern "C" UINT __stdcall ExecServiceConfig(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug ExecServiceConfig");
    HRESULT hr = S_OK;
    DWORD er = 0;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwz = NULL;

    LPWSTR pwzScriptKey = NULL;
    WCA_CASCRIPT_HANDLE hRollbackScript = NULL;

    LPWSTR pwzServiceName = NULL;
    BOOL fNewService = FALSE;
    LPWSTR pwzFirstFailureActionType = NULL;
    LPWSTR pwzSecondFailureActionType = NULL;
    LPWSTR pwzThirdFailureActionType = NULL;
    LPWSTR pwzProgramCommandLine = NULL;
    LPWSTR pwzRebootMessage = NULL;
    DWORD dwResetPeriodInDays = 0;
    DWORD dwRestartServiceDelayInSeconds = 0;

    LPVOID lpMsgBuf = NULL;
    SC_HANDLE hSCM = NULL;
    SC_HANDLE hService = NULL;

    DWORD dwRestartDelay = 0;
    WCHAR wzActionName[32] = { 0 };

    DWORD cbExistingServiceConfig = 0;

    SERVICE_FAILURE_ACTIONSW* psfa = NULL;

    // initialize
    hr = WcaInitialize(hInstall, "ExecServiceConfig");
    ExitOnFailure(hr, "failed to initialize");

    // Open the Services Control Manager up front.
    hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
    if (NULL == hSCM)
    {
        er = ::GetLastError();
        hr = HRESULT_FROM_WIN32(er);

#pragma prefast(push)
#pragma prefast(disable:25028)
        ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL);
#pragma prefast(pop)

        ExitOnFailure1(hr, "Failed to get handle to SCM. Error: %ls", (LPWSTR)lpMsgBuf);
    }

    // First, get the script key out of the CustomActionData and
    // use that to create the rollback script for this action.
    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey);
    if (!pwzScriptKey)
    {
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Failed due to unexpected CustomActionData passed.");
    }
    ExitOnFailure(hr, "Failed to read encoding key from CustomActionData.");

    hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript);
    ExitOnFailure(hr, "Failed to open rollback CustomAction script.");

    // Next, loop through the rest of the CustomActionData, processing
    // each service config row in turn.
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzServiceName);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&fNewService));
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwResetPeriodInDays));
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwRestartServiceDelayInSeconds));
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage);
        ExitOnFailure(hr, "failed to process CustomActionData");

        WcaLog(LOGMSG_VERBOSE, "Configuring Service: %ls", pwzServiceName);

        // Open the handle with all the permissions we might need:
        //  SERVICE_QUERY_CONFIG is needed for QueryServiceConfig2().
        //  SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2().
        //  SERVICE_START is required in order to handle SC_ACTION_RESTART action.
        hr = GetService(hSCM, pwzServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START, &hService);
        ExitOnFailure1(hr, "Failed to get service: %ls", pwzServiceName);

        // If we are configuring a service that existed on the machine, we need to
        // read the existing service configuration and write it out to the rollback
        // log so rollback can put it back if anything goes wrong.
        if (!fNewService)
        {
            // First, read the existing service config.
            if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, NULL, 0, &cbExistingServiceConfig) && ERROR_INSUFFICIENT_BUFFER != ::GetLastError())
            {
                ExitWithLastError(hr, "Failed to get current service config info.");
            }

            psfa = static_cast<LPSERVICE_FAILURE_ACTIONSW>(MemAlloc(cbExistingServiceConfig, TRUE));
            ExitOnNull(psfa, hr, E_OUTOFMEMORY, "failed to allocate memory for service failure actions.");

            if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)psfa, cbExistingServiceConfig, &cbExistingServiceConfig))
            {
                ExitOnLastError(hr, "failed to Query Service.");
            }

            // Build up rollback log so we can restore service state if necessary
            hr = WcaCaScriptWriteString(hRollbackScript, pwzServiceName);
            ExitOnFailure(hr, "Failed to add service name to Rollback Log");

            // If this service struct is empty, fill in default values
            if (3 > psfa->cActions)
            {
                hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone);
                ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

                hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone);
                ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

                hr = WcaCaScriptWriteString(hRollbackScript, c_wzActionTypeNone);
                ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");
            }
            else
            {
                // psfa actually had actions defined, so use the first three.
                for (int i = 0; i < 3; ++i)
                {
                    hr = GetSCActionTypeString(psfa->lpsaActions[i].Type, wzActionName, countof(wzActionName));
                    ExitOnFailure(hr, "failed to query SFA object");

                    if (SC_ACTION_RESTART == psfa->lpsaActions[i].Type)
                    {
                        dwRestartDelay = psfa->lpsaActions[i].Delay / 1000;
                    }

                    hr = WcaCaScriptWriteString(hRollbackScript, wzActionName);
                    ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");
                }
            }

            hr = WcaCaScriptWriteNumber(hRollbackScript, psfa->dwResetPeriod / (24 * 60 * 60));
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaCaScriptWriteNumber(hRollbackScript, dwRestartDelay);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            // Handle the null cases.
            if (!psfa->lpCommand)
            {
                psfa->lpCommand = L"";
            }
            hr = WcaCaScriptWriteString(hRollbackScript, psfa->lpCommand);
            ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

            // Handle the null cases.
            if (!psfa->lpRebootMsg)
            {
                psfa->lpRebootMsg = L"";
            }
            hr = WcaCaScriptWriteString(hRollbackScript, psfa->lpRebootMsg);
            ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

            // Nudge the system to get all our rollback data written to disk.
            WcaCaScriptFlush(hRollbackScript);

            ReleaseNullMem(psfa);
        }

        hr = ConfigureService(hSCM, hService, pwzServiceName, dwRestartServiceDelayInSeconds, pwzFirstFailureActionType,
                              pwzSecondFailureActionType, pwzThirdFailureActionType, dwResetPeriodInDays, pwzRebootMessage, pwzProgramCommandLine);
        ExitOnFailure1(hr, "Failed to configure service: %ls", pwzServiceName);

        hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE);
        ExitOnFailure(hr, "failed to send progress message");

        // Per-service cleanup
        ::CloseServiceHandle(hService);
        hService = NULL;
        dwResetPeriodInDays = 0;
        dwRestartServiceDelayInSeconds = 0;
    }

LExit:
    WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE);

    if (lpMsgBuf)
    {
        ::LocalFree(lpMsgBuf);
    }

    if (hService)
    {
        ::CloseServiceHandle(hService);
    }

    if (hSCM)
    {
        ::CloseServiceHandle(hSCM);
    }

    ReleaseMem(psfa);

    ReleaseStr(pwzRebootMessage);
    ReleaseStr(pwzProgramCommandLine);
    ReleaseStr(pwzThirdFailureActionType);
    ReleaseStr(pwzSecondFailureActionType);
    ReleaseStr(pwzFirstFailureActionType);
    ReleaseStr(pwzServiceName);
    ReleaseStr(pwzScriptKey);
    ReleaseStr(pwzCustomActionData);

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Ejemplo n.º 14
0
/******************************************************************
RollbackServiceConfig - entry point for ServiceConfig rollback
                        Custom Action.

NOTE: CustomActionScript Data == wzServiceName\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\t...
*******************************************************************/
extern "C" UINT __stdcall RollbackServiceConfig(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug RollbackServiceConfig");
    HRESULT hr = S_OK;
    DWORD er = 0;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwz = NULL;

    LPWSTR pwzScriptKey = NULL;
    WCA_CASCRIPT_HANDLE hRollbackScript = NULL;

    LPWSTR pwzServiceName = NULL;
    LPWSTR pwzFirstFailureActionType = NULL;
    LPWSTR pwzSecondFailureActionType = NULL;
    LPWSTR pwzThirdFailureActionType = NULL;
    LPWSTR pwzProgramCommandLine = NULL;
    LPWSTR pwzRebootMessage = NULL;
    DWORD dwResetPeriodInDays = 0;
    DWORD dwRestartServiceDelayInSeconds = 0;

    LPVOID lpMsgBuf = NULL;
    SC_HANDLE hSCM = NULL;
    SC_HANDLE hService = NULL;

    // initialize
    hr = WcaInitialize(hInstall, "RollbackServiceConfig");
    ExitOnFailure(hr, "Failed to initialize 'RollbackServiceConfig'.");

    // Open the Services Control Manager up front.
    hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
    if (NULL == hSCM)
    {
        er = ::GetLastError();
        hr = HRESULT_FROM_WIN32(er);

#pragma prefast(push)
#pragma prefast(disable:25028)
        ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, er, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL);
#pragma prefast(pop)

        ExitOnFailure1(hr, "Failed to get handle to SCM. Error: %ls", (LPWSTR)lpMsgBuf);

        // Make sure we still abort, in case hSCM was NULL but no error was returned from GetLastError
        ExitOnNull(hSCM, hr, E_POINTER, "Getting handle to SCM reported success, but no handle was returned.");
    }

    // Get the script key from the CustomAction data and use it to open
    // the rollback log and read the data over the CustomActionData
    // because all of the information is in the script data not the
    // CustomActionData.
    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey);
    if (!pwzScriptKey)
    {
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Failed due to unexpected CustomActionData passed.");
    }
    ExitOnFailure(hr, "Failed to read encoding key from CustomActionData.");

    hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript);
    ExitOnFailure(hr, "Failed to open rollback CustomAction script.");

    hr = WcaCaScriptReadAsCustomActionData(hRollbackScript, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to read rollback script into CustomAction data.");

    // Loop through the script's CustomActionData, processing each
    // service config in turn.
    pwz = pwzCustomActionData;
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzServiceName);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwResetPeriodInDays));
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwRestartServiceDelayInSeconds));
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine);
        ExitOnFailure(hr, "failed to process CustomActionData");
        hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage);
        ExitOnFailure(hr, "failed to process CustomActionData");

        WcaLog(LOGMSG_VERBOSE, "Reconfiguring Service: %ls", pwzServiceName);

        // Open the handle with all the permissions we might need.
        //  SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2().
        //  SERVICE_START is required in order to handle SC_ACTION_RESTART action.
        hr = GetService(hSCM, pwzServiceName, SERVICE_CHANGE_CONFIG | SERVICE_START, &hService);
        ExitOnFailure1(hr, "Failed to get service: %ls", pwzServiceName);

        hr = ConfigureService(hSCM, hService, pwzServiceName, dwRestartServiceDelayInSeconds, pwzFirstFailureActionType,
                              pwzSecondFailureActionType, pwzThirdFailureActionType, dwResetPeriodInDays, pwzRebootMessage, pwzProgramCommandLine);
        ExitOnFailure1(hr, "Failed to configure service: %ls", pwzServiceName);

        hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE);
        ExitOnFailure(hr, "failed to send progress message");

        // Per-service cleanup
        ::CloseServiceHandle(hService);
        hService = NULL;
        dwResetPeriodInDays = 0;
        dwRestartServiceDelayInSeconds = 0;
    }

LExit:
    if (lpMsgBuf) // Allocated with FormatString.
    {
        ::LocalFree(lpMsgBuf);
    }

    if (hService)
    {
        ::CloseServiceHandle(hService);
    }

    if (hSCM)
    {
        ::CloseServiceHandle(hSCM);
    }

    WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE);

    ReleaseStr(pwzRebootMessage);
    ReleaseStr(pwzProgramCommandLine);
    ReleaseStr(pwzThirdFailureActionType);
    ReleaseStr(pwzSecondFailureActionType);
    ReleaseStr(pwzFirstFailureActionType);
    ReleaseStr(pwzServiceName);
    ReleaseStr(pwzScriptKey);
    ReleaseStr(pwzCustomActionData);

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Ejemplo n.º 15
0
HRESULT CpiRollbackConfigureUsersInApplicationRoles(
    LPWSTR* ppwzData,
    CPI_ROLLBACK_DATA* pRollbackDataList
    )
{
    HRESULT hr = S_OK;

    int iRollbackStatus;

    CPI_USER_IN_APPLICATION_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 = ReadUsersInApplicationRoleAttributes(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 = CreateUsersInApplicationRole(&attrs);
            if (FAILED(hr))
                WcaLog(LOGMSG_STANDARD, "Failed to add user to application role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
            break;
        case atRemove:
            hr = RemoveUsersInApplicationRole(&attrs);
            if (FAILED(hr))
                WcaLog(LOGMSG_STANDARD, "Failed to remove user from application 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
    FreeUsersInApplicationRoleAttributes(&attrs);

    return hr;
}
Ejemplo n.º 16
0
static HRESULT ExecuteCertificateOperation(
	__in MSIHANDLE hInstall,
	__in SCA_ACTION saAction,
	__in DWORD dwStoreLocation
	)
{
	//AssertSz(FALSE, "Debug ExecuteCertificateOperation() here.");
	Assert(saAction & SCA_ACTION_INSTALL || saAction & SCA_ACTION_UNINSTALL);

	HRESULT hr = S_OK;
	LPWSTR pwzCaData = NULL;
	LPWSTR pwz;
	LPWSTR pwzName = NULL;
	LPWSTR pwzStore = NULL;
	int iAttributes = 0;
	LPWSTR pwzPFXPassword = NULL;
	LPWSTR pwzFilePath = NULL;
	BYTE* pbData = NULL;
	DWORD cbData = 0;

	HCERTSTORE hCertStore = NULL;

	hr = WcaGetProperty(L"CustomActionData", &pwzCaData);
	ExitOnFailure(hr, "Failed to get CustomActionData");

	WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %S", pwzCaData);

	pwz = pwzCaData;
	hr = WcaReadStringFromCaData(&pwz, &pwzName);
	ExitOnFailure(hr, "Failed to parse certificate name.");
	hr = WcaReadStringFromCaData(&pwz, &pwzStore);
	ExitOnFailure(hr, "Failed to parse CustomActionData, StoreName");
	hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
	ExitOnFailure(hr, "Failed to parse certificate attribute");
	if (SCA_ACTION_INSTALL == saAction) // install operations need more data
	{
		if (iAttributes & SCA_CERT_INSTALLED_FILE_PATH)
		{
			hr = WcaReadStringFromCaData(&pwz, &pwzFilePath);
			ExitOnFailure(hr, "Failed to parse path to certficate file.");

			hr = FileReadUntil(&pbData, &cbData, pwzFilePath, SIXTY_FOUR_MEG);
			ExitOnFailure(hr, "Failed to read certificate from file path.");
		}
		else
		{
			hr = WcaReadStreamFromCaData(&pwz, &pbData, (DWORD_PTR*)&cbData);
			ExitOnFailure(hr, "Failed to parse certficate stream.");
		}

		hr = WcaReadStringFromCaData(&pwz, &pwzPFXPassword);
		ExitOnFailure(hr, "Failed to parse certificate password.");
	}

	// Open the right store.
	hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation, pwzStore);
	MessageExitOnNullWithLastError1(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store: %S", pwzStore);

	if (SCA_ACTION_INSTALL == saAction) // install operations need more data
	{
		hr = InstallCertificate(hCertStore, (dwStoreLocation == CERT_SYSTEM_STORE_CURRENT_USER), pwzName, pbData, cbData, pwzPFXPassword);
		ExitOnFailure(hr, "Failed to install certificate.");
	}
	else
	{
		Assert(SCA_ACTION_UNINSTALL == saAction);

		hr = UninstallCertificate(hCertStore, pwzName);
		ExitOnFailure(hr, "Failed to uninstall certificate.");
	}

LExit:
	if (hCertStore)
	{
		::CertCloseStore(hCertStore, 0);
	}

	ReleaseMem(pbData);
	ReleaseStr(pwzFilePath);
	ReleaseStr(pwzPFXPassword);
	ReleaseStr(pwzStore);
	ReleaseStr(pwzName);
	ReleaseStr(pwzCaData);
	return hr;
}
Ejemplo n.º 17
0
/******************************************************************
 ExecXmlConfig - entry point for XmlConfig Custom Action

*******************************************************************/
extern "C" UINT __stdcall ExecXmlConfig(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug ExecXmlConfig");
    HRESULT hr = S_OK;
    HRESULT hrOpenFailure = S_OK;
    UINT er = ERROR_SUCCESS;

    BOOL fIsWow64Process = FALSE;
    BOOL fIsFSRedirectDisabled = FALSE;
    BOOL fPreserveDate = FALSE;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzFile = NULL;
    LPWSTR pwzElementPath = NULL;
    LPWSTR pwzVerifyPath = NULL;
    LPWSTR pwzName = NULL;
    LPWSTR pwzValue = NULL;
    LPWSTR pwz = NULL;
    int cAdditionalChanges = 0;

    IXMLDOMDocument* pixd = NULL;
    IXMLDOMNode* pixn = NULL;
    IXMLDOMNode* pixnVerify = NULL;
    IXMLDOMNode* pixnNewNode = NULL;
    IXMLDOMNode* pixnRemovedChild = NULL;

    IXMLDOMDocument* pixdNew = NULL;
    IXMLDOMElement* pixeNew = NULL;

    FILETIME ft;

    int id = IDRETRY;

    eXmlAction xa;
    eXmlPreserveDate xd;

    // initialize
    hr = WcaInitialize(hInstall, "ExecXmlConfig");
    ExitOnFailure(hr, "failed to initialize");

    hr = XmlInitialize();
    ExitOnFailure(hr, "failed to initialize xml utilities");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa);
    ExitOnFailure(hr, "failed to process CustomActionData");

    // Initialize the Wow64 API - store the result in fWow64APIPresent
    // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases
    WcaInitializeWow64();
    fIsWow64Process = WcaIsWow64Process();

    if (xaOpenFile != xa && xaOpenFilex64 != xa)
    {
        ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data");
    }

    // loop through all the passed in data
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzFile);
        ExitOnFailure(hr, "failed to read file name from custom action data");

        // Default to not preserve date, preserve it if any modifications require us to
        fPreserveDate = FALSE;

        // Open the file
        ReleaseNullObject(pixd);

        if (xaOpenFilex64 == xa)
        {
            if (!fIsWow64Process)
            {
                hr = E_NOTIMPL;
                ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW.");
            }

            hr = WcaDisableWow64FSRedirection();
            ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API.");

            fIsFSRedirectDisabled = TRUE;
        }

        hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd);
        if (FAILED(hr))
        {
            // Ignore the return code for now.  If they try to add something, we'll fail the install.  If all they do is remove stuff then it doesn't matter.
            hrOpenFailure = hr;
            hr = S_OK;
        }
        else
        {
            hrOpenFailure = S_OK;
        }

        WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile);

        while (pwz && *pwz)
        {
            // If we skip past an element that has additional changes we need to strip them off the stream before
            // moving on to the next element. Do that now and then restart the outer loop.
            if (cAdditionalChanges > 0)
            {
                while (cAdditionalChanges > 0)
                {
                    hr = WcaReadStringFromCaData(&pwz, &pwzName);
                    ExitOnFailure(hr, "failed to process CustomActionData");
                    hr = WcaReadStringFromCaData(&pwz, &pwzValue);
                    ExitOnFailure(hr, "failed to process CustomActionData");

                    cAdditionalChanges--;
                }
                continue;
            }

            hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa);
            ExitOnFailure(hr, "failed to process CustomActionData");

            // Break if we need to move on to a different file
            if (xaOpenFile == xa || xaOpenFilex64 == xa)
            {
                break;
            }

            hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd);
            ExitOnFailure(hr, "failed to process CustomActionData");

            if (xdPreserve == xd)
            {
                fPreserveDate = TRUE;
            }

            // Get path, name, and value to be written
            hr = WcaReadStringFromCaData(&pwz, &pwzElementPath);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzVerifyPath);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzName);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzValue);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadIntegerFromCaData(&pwz, &cAdditionalChanges);
            ExitOnFailure(hr, "failed to process CustomActionData");

            // If we failed to open the file and we're adding something to the file, we've got a problem.  Otherwise, just continue on since the file's already gone.
            if (FAILED(hrOpenFailure))
            {
                if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa)
                {
                    MessageExitOnFailure1(hr = hrOpenFailure, msierrXmlConfigFailedOpen, "failed to load XML file: %ls", pwzFile);
                }
                else
                {
                    continue;
                }
            }

            // Select the node we're about to modify
            ReleaseNullObject(pixn);

            hr = XmlSelectSingleNode(pixd, pwzElementPath, &pixn);

            // If we failed to find the node that we are going to add to, we've got a problem. Otherwise, just continue since the node's already gone.
            if (S_FALSE == hr)
            {
                if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa)
                {
                    hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND);
                }
                else
                {
                    hr = S_OK;
                    continue;
                }
            }

            MessageExitOnFailure2(hr, msierrXmlConfigFailedSelect, "failed to find node: %ls in XML file: %ls", pwzElementPath, pwzFile);

            // Make the modification
            switch (xa)
            {
            case xaWriteValue:
                if (pwzName && *pwzName)
                {
                    // We're setting an attribute
                    hr = XmlSetAttribute(pixn, pwzName, pwzValue);
                    ExitOnFailure2(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue);
                }
                else
                {
                    // We're setting the text of the node
                    hr = XmlSetText(pixn, pwzValue);
                    ExitOnFailure2(hr, "failed to set text to: %ls for element %ls.  Make sure that XPath points to an element.", pwzValue, pwzElementPath);
                }
                break;
            case xaWriteDocument:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        // We found the verify path which means we have no further work to do
                        continue;
                    }
                    ExitOnFailure1(hr, "failed to query verify path: %ls", pwzVerifyPath);
                }

                hr = XmlLoadDocumentEx(pwzValue, XML_LOAD_PRESERVE_WHITESPACE, &pixdNew);
                ExitOnFailure(hr, "Failed to load value as document.");

                hr = pixdNew->get_documentElement(&pixeNew);
                ExitOnFailure(hr, "Failed to get document element.");

                hr = pixn->appendChild(pixeNew, NULL);
                ExitOnFailure(hr, "Failed to append document element on to parent element.");

                ReleaseNullObject(pixeNew);
                ReleaseNullObject(pixdNew);
                break;

            case xaCreateElement:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        // We found the verify path which means we have no further work to do
                        continue;
                    }
                    ExitOnFailure1(hr, "failed to query verify path: %ls", pwzVerifyPath);
                }

                hr = XmlCreateChild(pixn, pwzName, &pixnNewNode);
                ExitOnFailure1(hr, "failed to create child element: %ls", pwzName);

                if (pwzValue && *pwzValue)
                {
                    hr = XmlSetText(pixnNewNode, pwzValue);
                    ExitOnFailure2(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName);
                }

                while (cAdditionalChanges > 0)
                {
                    hr = WcaReadStringFromCaData(&pwz, &pwzName);
                    ExitOnFailure(hr, "failed to process CustomActionData");
                    hr = WcaReadStringFromCaData(&pwz, &pwzValue);
                    ExitOnFailure(hr, "failed to process CustomActionData");

                    // Set the additional attribute
                    hr = XmlSetAttribute(pixnNewNode, pwzName, pwzValue);
                    ExitOnFailure2(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue);

                    cAdditionalChanges--;
                }

                ReleaseNullObject(pixnNewNode);
                break;
            case xaDeleteValue:
                if (pwzName && *pwzName)
                {
                    // Delete the attribute
                    hr = XmlRemoveAttribute(pixn, pwzName);
                    ExitOnFailure1(hr, "failed to remove attribute: %ls", pwzName);
                }
                else
                {
                    // Clear the text value for the node
                    hr = XmlSetText(pixn, L"");
                    ExitOnFailure(hr, "failed to clear text value");
                }
                break;
            case xaDeleteElement:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        hr = pixn->removeChild(pixnVerify, &pixnRemovedChild);
                        ExitOnFailure(hr, "failed to remove created child element");

                        ReleaseNullObject(pixnRemovedChild);
                    }
                    else
                    {
                        WcaLog(LOGMSG_VERBOSE, "Failed to select path %ls for deleting.  Skipping...", pwzVerifyPath);
                        hr = S_OK;
                    }
                }
                else
                {
                    // TODO: This requires a VerifyPath to delete an element.  Should we support not having one?
                    WcaLog(LOGMSG_VERBOSE, "No VerifyPath specified for delete element of ID: %ls", pwzElementPath);
                }
                break;
            default:
                ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data");
                break;
            }
        }


        // Now that we've made all of the changes to this file, save it and move on to the next
        if (S_OK == hrOpenFailure)
        {
            if (fPreserveDate)
            {
                hr = FileGetTime(pwzFile, NULL, NULL, &ft);
                ExitOnFailure1(hr, "failed to get modified time of file : %ls", pwzFile);
            }

            int iSaveAttempt = 0;

            do
            {
                hr = XmlSaveDocument(pixd, pwzFile);
                if (FAILED(hr))
                {
                    id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile);
                    switch (id)
                    {
                    case IDABORT:
                        ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                    case IDRETRY:
                        hr = S_FALSE;   // hit me, baby, one more time
                        break;
                    case IDIGNORE:
                        hr = S_OK;  // pretend everything is okay and bail
                        break;
                    case 0: // No UI case, MsiProcessMessage returns 0
                        if (STIERR_SHARING_VIOLATION == hr)
                        {
                            // Only in case of sharing violation do we retry 30 times, once a second.
                            if (iSaveAttempt < 30)
                            {
                                hr = S_FALSE;
                                ++iSaveAttempt;
                                WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt);
                                Sleep(1000);
                            }
                            else
                            {
                                ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                            }
                        }
                        break;
                    default: // Unknown error
                        ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                    }
                }
            } while (S_FALSE == hr);

            if (fPreserveDate)
            {
                hr = FileSetTime(pwzFile, NULL, NULL, &ft);
                ExitOnFailure1(hr, "failed to set modified time of file : %ls", pwzFile);
            }

            if (fIsFSRedirectDisabled)
            {
                fIsFSRedirectDisabled = FALSE;
                WcaRevertWow64FSRedirection();
            }
        }
    }

LExit:
    // Make sure we revert FS Redirection if necessary before exiting
    if (fIsFSRedirectDisabled)
    {
        fIsFSRedirectDisabled = FALSE;
        WcaRevertWow64FSRedirection();
    }
    WcaFinalizeWow64();

    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzData);
    ReleaseStr(pwzFile);
    ReleaseStr(pwzElementPath);
    ReleaseStr(pwzVerifyPath);
    ReleaseStr(pwzName);
    ReleaseStr(pwzValue);

    ReleaseObject(pixeNew);
    ReleaseObject(pixdNew);

    ReleaseObject(pixn);
    ReleaseObject(pixd);
    ReleaseObject(pixnNewNode);
    ReleaseObject(pixnRemovedChild);

    XmlUninitialize();

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
UINT __stdcall ExecAddinRegistration(MSIHANDLE hInstall)
{
    // AssertSz(FALSE, "debug ExecAddinRegistration");

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwz = NULL;

    int iOperation = 0;
    LPWSTR pwzId = NULL;
    LPWSTR pwzFile = NULL;
	LPWSTR pwzName = NULL;
	LPWSTR pwzDescription = NULL;
	int iBitness = REG_KEY_DEFAULT;
	int iCommandLineSafe = 1;
	int iLoadBehavior = 3;

	LPWSTR pwzAllUsers = NULL;

	HRESULT hr = WcaInitialize(hInstall, "ExecAddinRegistration");
	ExitOnFailure(hr, "Failed to initialize");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = RegInitialize();
    ExitOnFailure(hr, "Failed to initialize the registry functions.");

    // loop through all the passed in data
    while (pwz && *pwz)
    {
        // extract the custom action data
        hr = WcaReadIntegerFromCaData(&pwz, &iOperation);
        ExitOnFailure(hr, "failed to read operation from custom action data");

        hr = WcaReadStringFromCaData(&pwz, &pwzId);
        ExitOnFailure(hr, "failed to read id from custom action data");

        hr = WcaReadStringFromCaData(&pwz, &pwzFile);
        ExitOnFailure(hr, "failed to read path from custom action data");

        hr = WcaReadStringFromCaData(&pwz, &pwzName);
        ExitOnFailure(hr, "failed to read name from custom action data");

        hr = WcaReadStringFromCaData(&pwz, &pwzDescription);
        ExitOnFailure(hr, "failed to read description from custom action data");

		hr = WcaReadIntegerFromCaData(&pwz, &iBitness);
		ExitOnFailure(hr, "failed to read bitness from custom action data");

		hr = WcaReadIntegerFromCaData(&pwz, &iCommandLineSafe);
		ExitOnFailure(hr, "failed to read CommandLineSafe from custom action data");

		hr = WcaReadIntegerFromCaData(&pwz, &iLoadBehavior);
		ExitOnFailure(hr, "failed to read LoadBehavior from custom action data");

		hr = WcaReadStringFromCaData(&pwz, &pwzAllUsers);
		ExitOnFailure(hr, "failed to read ALLUSERS from custom action data");

		BOOL fPerUserInstall = (!pwzAllUsers || !*pwzAllUsers);

        // if rolling back, swap INSTALL and UNINSTALL
        if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK))
        {
            if (WCA_TODO_INSTALL == iOperation)
            {
                iOperation = WCA_TODO_UNINSTALL;
            }
            else if (WCA_TODO_UNINSTALL == iOperation)
            {
                iOperation = WCA_TODO_INSTALL;
            }
        }

        switch (iOperation)
        {
        case WCA_TODO_INSTALL:
        case WCA_TODO_REINSTALL:
			hr = CreateOfficeRegistryKey(pwzId, pwzFile, pwzName, pwzDescription, iCommandLineSafe, iLoadBehavior, fPerUserInstall, iBitness);
			ExitOnFailure1(hr, "failed to register addin %ls", pwzId);
            break;

        case WCA_TODO_UNINSTALL:
			hr = DeleteOfficeRegistryKey(pwzId, fPerUserInstall, iBitness);
			ExitOnFailure1(hr, "failed to unregister addin %ls", pwzId);
            break;
        }

        // Tick the progress bar along for this addin
        hr = WcaProgressMessage(COST_REGISTER_ADDIN, FALSE);
        ExitOnFailure1(hr, "failed to tick progress bar for addin registration: %ls", pwzId);
	}

LExit:
    RegUninitialize();

	ReleaseStr(pwzAllUsers);
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzData);

    ReleaseStr(pwzId);
    ReleaseStr(pwzFile);
	ReleaseStr(pwzName);
	ReleaseStr(pwzDescription);

	return WcaFinalize(SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE);
}
Ejemplo n.º 19
0
/******************************************************************
 CaExecServiceConfig - entry point for ServiceConfig Custom Action
				   called as Type 1025 CustomAction (deferred binary DLL)

 NOTE: deferred CustomAction since it modifies the machine
 NOTE: CustomActionData == wzServiceName\twzFirstFailureActionType\twzSecondFailureActionType\twzThirdFailureActionType\tdwResetPeriodInDays\tdwRestartServiceDelayInSeconds\twzProgramCommandLine\twzRebootMessage\twzServiceName\t...
*******************************************************************/
extern "C" UINT __stdcall ExecServiceConfig(
	__in MSIHANDLE hInstall
	)
{
//	AssertSz(FALSE, "debug ExecServiceConfig");
	HRESULT hr = S_OK;
	UINT uiResult = ERROR_SUCCESS;
	DWORD dwError = 0;
	LPVOID lpMsgBuf = NULL;

	LPWSTR pwzData = NULL;
	LPWSTR pwz = NULL;

	LPWSTR pwzServiceName = NULL;
	LPWSTR pwzFirstFailureActionType = NULL;
	LPWSTR pwzSecondFailureActionType = NULL;
	LPWSTR pwzThirdFailureActionType = NULL;
	LPWSTR pwzProgramCommandLine = NULL;
	LPWSTR pwzRebootMessage = NULL;
	DWORD dwResetPeriodInDays = 0;
	DWORD dwRestartServiceDelayInSeconds = 0;

	SC_HANDLE hSCM = NULL;
	SC_HANDLE hService = NULL;
	DWORD dwOpenServiceAccess = SERVICE_CHANGE_CONFIG; // SERVICE_CHANGE_CONFIG is needed for ChangeServiceConfig2()

	SERVICE_FAILURE_ACTIONSW sfa;
	SC_ACTION actions[3];
	BOOL fResult = FALSE;

	// initialize
	hr = WcaInitialize(hInstall, "ExecServiceConfig");
	ExitOnFailure(hr, "failed to initialize");

	hr = WcaGetProperty( L"CustomActionData", &pwzData);
	ExitOnFailure(hr, "failed to get CustomActionData");

	WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %S", pwzData);

	pwz = pwzData;

	// loop through all the passed in data
	while (pwz && *pwz)
	{
		hr = WcaReadStringFromCaData(&pwz, &pwzServiceName);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzFirstFailureActionType);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzSecondFailureActionType);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzThirdFailureActionType);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwResetPeriodInDays));
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwRestartServiceDelayInSeconds));
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzProgramCommandLine);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzRebootMessage);
		ExitOnFailure(hr, "failed to process CustomActionData");

		WcaLog(LOGMSG_VERBOSE, "Configuring Service: %S", pwzServiceName);

		// build up SC_ACTION array
		// TODO: why is delay only respected when SC_ACTION_RESTART is requested?
		actions[0].Type = GetSCActionType(pwzFirstFailureActionType);
		actions[0].Delay = 0;
		if (SC_ACTION_RESTART == actions[0].Type)
		{
			actions[0].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds
			dwOpenServiceAccess |= SERVICE_START; // must have SERVICE_START access in order to handle SC_ACTION_RESTART action;
		}

		actions[1].Type = GetSCActionType(pwzSecondFailureActionType);
		actions[1].Delay = 0;
		if (SC_ACTION_RESTART == actions[1].Type)
		{
			actions[1].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds
			dwOpenServiceAccess |= SERVICE_START; // must have SERVICE_START access in order to handle SC_ACTION_RESTART action;
		}

		actions[2].Type = GetSCActionType(pwzThirdFailureActionType);
		actions[2].Delay = 0;
		if (SC_ACTION_RESTART == actions[2].Type)
		{
			actions[2].Delay = dwRestartServiceDelayInSeconds * 1000; // seconds to milliseconds
			dwOpenServiceAccess |= SERVICE_START; // must have SERVICE_START access in order to handle SC_ACTION_RESTART action;
		}

		// build up the SERVICE_FAILURE_ACTIONSW struct
		sfa.dwResetPeriod = dwResetPeriodInDays * 24 * 60 * 60; // days to seconds
		sfa.lpRebootMsg = pwzRebootMessage;
		sfa.lpCommand = pwzProgramCommandLine;
		sfa.cActions = 3;  // the UI always shows 3 actions, so we'll always do 3
		sfa.lpsaActions = actions;

		// Get a handle to the service control manager (if we don't already have)
		if (NULL == hSCM)
		{
			hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
			if (hSCM == NULL)
			{
				dwError = ::GetLastError();
				::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL);

				ExitOnFailure1(hr = HRESULT_FROM_WIN32(dwError), "failed to get handle to SCM. Error: %S", (LPWSTR)lpMsgBuf);
			}
		}

		hService = ::OpenServiceW(hSCM, pwzServiceName, dwOpenServiceAccess);
		if (hService == NULL)
		{
			dwError = ::GetLastError();
			hr = HRESULT_FROM_WIN32(dwError);
			if (dwError == ERROR_SERVICE_DOES_NOT_EXIST)
			{
				ExitOnFailure1(hr, "Service \"%S\" does not exist on this system.", pwzServiceName);
			}
			else
			{
				::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL);
				ExitOnFailure2(hr, "Failed to get handle to the service \"%S\". Error: %S", pwzServiceName, (LPWSTR)lpMsgBuf);
			}
		}

		// Call ChangeServiceConfig2 to actually set up the failure actions
		fResult = ChangeServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPVOID)&sfa);
		if (fResult == FALSE)
		{
			dwError = ::GetLastError();
			hr = HRESULT_FROM_WIN32(dwError);
			::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf, 0, NULL);

			// check if this is a service that can't be modified
			if(dwError == ERROR_CANNOT_DETECT_PROCESS_ABORT)
			{
				WcaLog(LOGMSG_STANDARD, "WARNING: Service \"%S\" is not configurable on this server and will not be set.", pwzServiceName);
			}
			ExitOnFailure1(hr, "Cannot change service configuration. Error: %S", (LPWSTR)lpMsgBuf);
		}

		// Per-service cleanup
		dwResetPeriodInDays = 0;
		dwRestartServiceDelayInSeconds = 0;

		hr = WcaProgressMessage(COST_SERVICECONFIG, FALSE);
		ExitOnFailure(hr, "failed to send progress message");
	}

LExit:
	// Clean up handles
	ReleaseStr(pwzServiceName);
	ReleaseStr(pwzFirstFailureActionType);
	ReleaseStr(pwzSecondFailureActionType);
	ReleaseStr(pwzThirdFailureActionType);
	ReleaseStr(pwzProgramCommandLine);
	ReleaseStr(pwzRebootMessage);
	ReleaseStr(pwzData);

	if (lpMsgBuf) // Allocated with FormatString
		::LocalFree(lpMsgBuf);

	if (hService)
		::CloseServiceHandle(hService);
	if (hSCM)
		::CloseServiceHandle(hSCM);

	if (FAILED(hr))
		uiResult = ERROR_INSTALL_FAILURE;
	return WcaFinalize(uiResult);
}
Ejemplo n.º 20
0
/******************************************************************
 CaExecSecureObjects - entry point for SecureObjects Custom Action
				   called as Type 1025 CustomAction (deferred binary DLL)

 NOTE: deferred CustomAction since it modifies the machine
 NOTE: CustomActionData == wzObject\twzTable\twzDomain\twzUser\tdwPermissions\twzObject\t...
******************************************************************/
extern "C" UINT __stdcall ExecSecureObjects(
	__in MSIHANDLE hInstall
	)
{
//	AssertSz(FALSE, "debug ExecSecureObjects");
	HRESULT hr = S_OK;
	DWORD er = ERROR_SUCCESS;

	LPWSTR pwz = NULL;
	LPWSTR pwzData = NULL;
	LPWSTR pwzObject = NULL;
	LPWSTR pwzTable = NULL;
	LPWSTR pwzDomain = NULL;
	DWORD dwRevision = 0;
	LPWSTR pwzUser = NULL;
	DWORD dwPermissions = 0;
	LPWSTR pwzAccount = NULL;
	PSID psid = NULL;

	EXPLICIT_ACCESSW ea = {0};
	SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE;
	PSECURITY_DESCRIPTOR psd = NULL;
	SECURITY_DESCRIPTOR_CONTROL sdc = {0};
	SECURITY_INFORMATION si = {0};
	PACL pAclExisting = NULL;   // doesn't get freed
	PACL pAclNew = NULL;

	PMSIHANDLE hActionRec = ::MsiCreateRecord(1);

	//
	// initialize
	//
	hr = WcaInitialize(hInstall, "ExecSecureObjects");
	ExitOnFailure(hr, "failed to initialize");

	hr = WcaGetProperty(L"CustomActionData", &pwzData);
	ExitOnFailure(hr, "failed to get CustomActionData");

	WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %S", pwzData);

	pwz = pwzData;

	//
	// loop through all the passed in data
	//
	while (pwz && *pwz)
	{
		hr = WcaReadStringFromCaData(&pwz, &pwzObject);
		ExitOnFailure(hr, "failed to process CustomActionData");

		hr = WcaReadStringFromCaData(&pwz, &pwzTable);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzDomain);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadStringFromCaData(&pwz, &pwzUser);
		ExitOnFailure(hr, "failed to process CustomActionData");
		hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&dwPermissions));
		ExitOnFailure(hr, "failed to processCustomActionData");

		WcaLog(LOGMSG_VERBOSE, "Securing Object: %S Type: %S User: %S", pwzObject, pwzTable, pwzUser);

		//
		// create the appropriate SID
		//

		// figure out the right user to put into the access block
		if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Everyone"))
		{
			hr = AclGetWellKnownSid(WinWorldSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Administrators"))
		{
			hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalSystem"))
		{
			hr = AclGetWellKnownSid(WinLocalSystemSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"LocalService"))
		{
			hr = AclGetWellKnownSid(WinLocalServiceSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"NetworkService"))
		{
			hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"AuthenticatedUser"))
		{
			hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Guests"))
		{
			hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid);
		}
		else if(!*pwzDomain && 0 == lstrcmpW(pwzUser, L"CREATOR OWNER"))
		{
			hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid);
		}
		else if (!*pwzDomain && 0 == lstrcmpW(pwzUser, L"INTERACTIVE"))
		{
			hr = AclGetWellKnownSid(WinInteractiveSid, &psid);
		}
		else if(!*pwzDomain && 0 == lstrcmpW(pwzUser, L"Users"))
		{
			hr = AclGetWellKnownSid(WinBuiltinUsersSid, &psid);
		}
		else
		{
			hr = StrAllocFormatted(&pwzAccount, L"%s\\%s", *pwzDomain ? pwzDomain : L".", pwzUser);
			ExitOnFailure(hr, "failed to build domain user name");

			hr = AclGetAccountSid(NULL, pwzAccount, &psid);
		}
		ExitOnFailure3(hr, "failed to get sid for account: %S%S%S", pwzDomain, *pwzDomain ? L"\\" : L"", pwzUser);

		//
		// build up the explicit access
		//
		ea.grfAccessPermissions = dwPermissions;
		ea.grfAccessMode = SET_ACCESS;

		if (0 == lstrcmpW(L"CreateFolder", pwzTable))
		{
			ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
		}
		else
		{
			ea.grfInheritance = NO_INHERITANCE;
		}

		::BuildTrusteeWithSidW(&ea.Trustee, psid);

		if (0 == lstrcmpW(L"ServiceInstall", pwzTable))
		{
			objectType = SE_SERVICE;

			// always add these permissions for services
			// these are basic permissions that are often forgotten
			dwPermissions |= SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_INTERROGATE;
		}
		else if (0 == lstrcmpW(L"CreateFolder", pwzTable) || 0 == lstrcmpW(L"File", pwzTable))
		{
			objectType = SE_FILE_OBJECT;
		}
		else if (0 == lstrcmpW(L"Registry", pwzTable))
		{
			objectType = SE_REGISTRY_KEY;
		}

		if (SE_UNKNOWN_OBJECT_TYPE != objectType)
		{
			er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pAclExisting, NULL, &psd);
			ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get security info for object: %S", pwzObject);

			//Need to see if DACL is protected so getting Descriptor information
			if(!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision))
			{
				ExitOnLastError1(hr, "failed to get security descriptor control for object: %S", pwzObject);
			}

			er = ::SetEntriesInAclW(1, &ea, pAclExisting, &pAclNew);
			ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to add ACLs for object: %S", pwzObject);

			if (sdc & SE_DACL_PROTECTED)
			{
				si = DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION;
			}
			else
			{
				si = DACL_SECURITY_INFORMATION;
			}
			er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pAclNew, NULL);
			MessageExitOnFailure1(hr = HRESULT_FROM_WIN32(er), msierrSecureObjectsFailedSet, "failed to set security info for object: %S", pwzObject);
		}
		else
		{
			MessageExitOnFailure1(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %S", pwzTable);
		}

		hr = WcaProgressMessage(COST_SECUREOBJECT, FALSE);
		ExitOnFailure(hr, "failed to send progress message");

		objectType = SE_UNKNOWN_OBJECT_TYPE;
	}

LExit:
	ReleaseStr(pwzUser);
	ReleaseStr(pwzDomain);
	ReleaseStr(pwzTable);
	ReleaseStr(pwzObject);
	ReleaseStr(pwzData);
	ReleaseStr(pwzAccount);

	if (pAclNew)
		::LocalFree(pAclNew);
	if (psd)
		::LocalFree(psd);
	if (psid)
		AclFreeSid(psid);

	if (FAILED(hr))
		er = ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
Ejemplo n.º 21
0
extern "C" UINT __stdcall ExecSecureObjectsRollback(
    __in MSIHANDLE hInstall
    )
{
//    AssertSz(FALSE, "debug ExecSecureObjectsRollback");
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;

    LPWSTR pwz = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzObject = NULL;
    LPWSTR pwzTable = NULL;
    LPWSTR pwzSecurityInfo = NULL;

    SE_OBJECT_TYPE objectType = SE_UNKNOWN_OBJECT_TYPE;
    PSECURITY_DESCRIPTOR psd = NULL;
    ULONG psdSize;
    SECURITY_DESCRIPTOR_CONTROL sdc = {0};
    SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
    PACL pDacl = NULL;
    BOOL bDaclPresent = false;
    BOOL bDaclDefaulted = false;
    DWORD dwRevision = 0;
    int iProtected;

    // initialize
    hr = WcaInitialize(hInstall, "ExecSecureObjectsRollback");
    ExitOnFailure(hr, "failed to initialize");

    hr = WcaGetProperty(L"CustomActionData", &pwzData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData);

    pwz = pwzData;

    hr = WcaReadStringFromCaData(&pwz, &pwzObject);
    ExitOnFailure(hr, "failed to process CustomActionData");

    hr = WcaReadStringFromCaData(&pwz, &pwzTable);
    ExitOnFailure(hr, "failed to process CustomActionData");

    objectType = SEObjectTypeFromString(const_cast<LPCWSTR> (pwzTable));

    if (SE_UNKNOWN_OBJECT_TYPE != objectType)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzSecurityInfo);
        ExitOnFailure(hr, "failed to process CustomActionData");

        hr = WcaReadIntegerFromCaData(&pwz, &iProtected);
        ExitOnFailure(hr, "failed to process CustomActionData");

        if (!::ConvertStringSecurityDescriptorToSecurityDescriptorW(pwzSecurityInfo,SDDL_REVISION_1,&psd,&psdSize))
        {
            ExitOnLastError(hr, "failed to convert security descriptor string to a valid security descriptor");
        }

        if (!::GetSecurityDescriptorDacl(psd,&bDaclPresent,&pDacl,&bDaclDefaulted))
        {
            hr = E_UNEXPECTED;
            ExitOnFailure2(hr, "failed to get security descriptor's DACL - error code: %d",pwzSecurityInfo,GetLastError());
        }

        // The below situation may always be caught by the above if block - the documentation isn't very clear. To be safe, we're going to test for it.
        if (!bDaclPresent)
        {
            hr = E_UNEXPECTED;
            ExitOnFailure(hr, "security descriptor does not contain a DACL");
        }

        //Need to see if DACL is protected so getting Descriptor information
        if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision))
        {
            ExitOnLastError1(hr, "failed to get security descriptor control for object: %ls", pwzObject);
        }

        // Write a 1 if DACL is protected, 0 otherwise
        switch (iProtected)
        {
        case 0:
            // Unnecessary to do anything - leave si to the default flags
            break;

        case 1:
            si = si | PROTECTED_DACL_SECURITY_INFORMATION;
            break;

        default:
            hr = E_UNEXPECTED;
            ExitOnFailure(hr, "unrecognized value in CustomActionData");
            break;
        }

        er = ::SetNamedSecurityInfoW(pwzObject, objectType, si, NULL, NULL, pDacl, NULL);
        ExitOnFailure2(hr = HRESULT_FROM_WIN32(er), "failed to set security info for object: %ls error code: %d", pwzObject, GetLastError());
    }
    else
    {
        MessageExitOnFailure1(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable);
    }

LExit:
    ReleaseStr(pwzData);
    ReleaseStr(pwzObject);
    ReleaseStr(pwzTable);
    ReleaseStr(pwzSecurityInfo);

    if (psd)
    {
        ::LocalFree(psd);
    }

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
Ejemplo n.º 22
0
/******************************************************************
 ExecXmlConfigRollback - entry point for XmlConfig rollback Custom Action

*******************************************************************/
extern "C" UINT __stdcall ExecXmlConfigRollback(
    __in MSIHANDLE hInstall
    )
{
//    AssertSz(FALSE, "debug ExecXmlConfigRollback");
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    int iIs64Bit;
    BOOL fIs64Bit = FALSE;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwz = NULL;
    LPWSTR pwzFileName = NULL;
    LPBYTE pbData = NULL;
    DWORD_PTR cbData = 0;
    DWORD cbDataWritten = 0;

    FILETIME ft;

    HANDLE hFile = INVALID_HANDLE_VALUE;

    // initialize
    hr = WcaInitialize(hInstall, "ExecXmlConfigRollback");
    ExitOnFailure(hr, "failed to initialize");


    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadIntegerFromCaData(&pwz, &iIs64Bit);
    ExitOnFailure(hr, "failed to read component bitness from custom action data");

    hr = WcaReadStringFromCaData(&pwz, &pwzFileName);
    ExitOnFailure(hr, "failed to read file name from custom action data");

    hr = WcaReadStreamFromCaData(&pwz, &pbData, &cbData);
    ExitOnFailure(hr, "failed to read file contents from custom action data");

    fIs64Bit = (BOOL)iIs64Bit;

    if (fIs64Bit)
    {
        hr = WcaInitializeWow64();
        if (S_FALSE == hr)
        {
            hr = TYPE_E_DLLFUNCTIONNOTFOUND;
        }
        ExitOnFailure(hr, "failed to initialize Wow64 API");

        if (!WcaIsWow64Process())
        {
            hr = E_NOTIMPL;
            ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but the Wow64 API is unavailable.");
        }

        hr = WcaDisableWow64FSRedirection();
        ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but was unable to Disable Filesystem Redirection through the Wow64 API.");
    }

    hr = FileGetTime(pwzFileName, NULL, NULL, &ft);
    ExitOnFailure1(hr, "Failed to get modified date of file %ls.", pwzFileName);

    // Open the file
    hFile = ::CreateFileW(pwzFileName, GENERIC_WRITE, NULL, NULL, TRUNCATE_EXISTING, NULL, NULL);
    ExitOnInvalidHandleWithLastError1(hFile, hr, "failed to open file: %ls", pwzFileName);

    // Write out the old data
    if (!::WriteFile(hFile, pbData, (DWORD)cbData, &cbDataWritten, NULL))
    {
        ExitOnLastError1(hr, "failed to write to file: %ls", pwzFileName);
    }

    Assert(cbData == cbDataWritten);

    ReleaseFile(hFile);

    hr = FileSetTime(pwzFileName, NULL, NULL, &ft);
    ExitOnFailure1(hr, "Failed to set modified date of file %ls.", pwzFileName);

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzFileName);

    ReleaseFile(hFile);

    if (fIs64Bit)
    {
        WcaRevertWow64FSRedirection();
        WcaFinalizeWow64();
    }

    ReleaseMem(pbData);

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
Ejemplo n.º 23
0
static HRESULT ExecuteCertificateOperation(
    __in MSIHANDLE hInstall,
    __in SCA_ACTION saAction,
    __in DWORD dwStoreLocation
    )
{
    //AssertSz(FALSE, "Debug ExecuteCertificateOperation() here.");
    Assert(saAction & SCA_ACTION_INSTALL || saAction & SCA_ACTION_UNINSTALL);

    HRESULT hr = S_OK;
    LPWSTR pwzCaData = NULL;
    LPWSTR pwz;
    LPWSTR pwzName = NULL;
    LPWSTR pwzStore = NULL;
    int iAttributes = 0;
    LPWSTR pwzPFXPassword = NULL;
    LPWSTR pwzFilePath = NULL;
    BYTE* pbData = NULL;
    DWORD cbData = 0;
    DWORD cbPFXPassword = 0;

    BOOL fUserStoreLocation = (CERT_SYSTEM_STORE_CURRENT_USER == dwStoreLocation);
    HCERTSTORE hCertStore = NULL;

    hr = WcaGetProperty(L"CustomActionData", &pwzCaData);
    ExitOnFailure(hr, "Failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCaData);

    pwz = pwzCaData;
    hr = WcaReadStringFromCaData(&pwz, &pwzName);
    ExitOnFailure(hr, "Failed to parse certificate name.");
    hr = WcaReadStringFromCaData(&pwz, &pwzStore);
    ExitOnFailure(hr, "Failed to parse CustomActionData, StoreName");
    hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
    ExitOnFailure(hr, "Failed to parse certificate attribute");
    if (SCA_ACTION_INSTALL == saAction) // install operations need more data
    {
        hr = WcaReadStreamFromCaData(&pwz, &pbData, (DWORD_PTR*)&cbData);
        ExitOnFailure(hr, "Failed to parse certificate stream.");

        hr = WcaReadStringFromCaData(&pwz, &pwzPFXPassword);
        ExitOnFailure(hr, "Failed to parse certificate password.");
    }

    // Open the right store.
    hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, dwStoreLocation, pwzStore);
    MessageExitOnNullWithLastError1(hCertStore, hr, msierrCERTFailedOpen, "Failed to open certificate store: %ls", pwzStore);

    if (SCA_ACTION_INSTALL == saAction) // install operations need more data
    {
        // Uninstall existing versions of this package.  Ignore any failures
        // This is needed to clean up the private key of a cert when we replace an existing cert
        // CertAddCertificateContextToStore(CERT_STORE_ADD_REPLACE_EXISTING) does not remove the private key if the cert is replaced
        UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName);

        hr = InstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName, pbData, cbData, pwzPFXPassword);
        ExitOnFailure(hr, "Failed to install certificate.");
    }
    else
    {
        Assert(SCA_ACTION_UNINSTALL == saAction);

        hr = UninstallCertificatePackage(hCertStore, fUserStoreLocation, pwzName);
        ExitOnFailure(hr, "Failed to uninstall certificate.");
    }

LExit:
    if (NULL != pwzPFXPassword && SUCCEEDED(StrSize(pwzPFXPassword, &cbPFXPassword)))
    {
        SecureZeroMemory(pwzPFXPassword, cbPFXPassword);
    }

    if (hCertStore)
    {
        if (!::CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
        {
            WcaLog(LOGMSG_VERBOSE, "Cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
        }
    }

    ReleaseMem(pbData);
    ReleaseStr(pwzFilePath);
    ReleaseStr(pwzPFXPassword);
    ReleaseStr(pwzStore);
    ReleaseStr(pwzName);
    ReleaseStr(pwzCaData);
    return hr;
}
Ejemplo n.º 24
0
/******************************************************************
 WixCreateInternetShortcuts - entry point for Internet shortcuts
    custom action
*******************************************************************/
extern "C" UINT __stdcall WixCreateInternetShortcuts(
    __in MSIHANDLE hInstall
)
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwz = NULL;
    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzTarget = NULL;
    LPWSTR pwzShortcutPath = NULL;
    LPWSTR pwzIconPath = NULL;
    BOOL fInitializedCom = FALSE;
    int iAttr = 0;
    int iIconIndex = 0;

    // initialize
    hr = WcaInitialize(hInstall, "WixCreateInternetShortcuts");
    ExitOnFailure(hr, "failed to initialize WixCreateInternetShortcuts");

    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "failed to initialize COM");
    fInitializedCom = TRUE;

    // extract the custom action data
    hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    // loop through all the custom action data
    pwz = pwzCustomActionData;
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzShortcutPath);
        ExitOnFailure(hr, "failed to read shortcut path from custom action data");
        hr = WcaReadStringFromCaData(&pwz, &pwzTarget);
        ExitOnFailure(hr, "failed to read shortcut target from custom action data");
        hr = WcaReadIntegerFromCaData(&pwz, &iAttr);
        ExitOnFailure(hr, "failed to read shortcut attributes from custom action data");
        hr = WcaReadStringFromCaData(&pwz, &pwzIconPath);
        ExitOnFailure(hr, "failed to read shortcut icon path from custom action data");
        hr = WcaReadIntegerFromCaData(&pwz, &iIconIndex);
        ExitOnFailure(hr, "failed to read shortcut icon index from custom action data");

        if ((iAttr & esaURL) == esaURL)
        {
            hr = CreateUrl(pwzTarget, pwzShortcutPath, pwzIconPath, iIconIndex);
        }
        else
        {
            hr = CreateLink(pwzTarget, pwzShortcutPath, pwzIconPath, iIconIndex);
        }
        ExitOnFailure(hr, "failed to create Internet shortcut");

        // tick the progress bar
        hr = WcaProgressMessage(COST_INTERNETSHORTCUT, FALSE);
        ExitOnFailure1(hr, "failed to tick progress bar for shortcut: %ls", pwzShortcutPath);
    }

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzTarget);
    ReleaseStr(pwzShortcutPath);

    if (fInitializedCom)
    {
        ::CoUninitialize();
    }

    er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er;
    return WcaFinalize(er);
}
Ejemplo n.º 25
0
/******************************************************************
 ExecFirewallExceptions - deferred custom action entry point to 
   register and remove firewall exceptions.

********************************************************************/
extern "C" UINT __stdcall ExecFirewallExceptions(
    __in MSIHANDLE hInstall
    )
{
    HRESULT hr = S_OK;
    BOOL fSupportProfiles = FALSE;
    LPWSTR pwz = NULL;
    LPWSTR pwzCustomActionData = NULL;
    int iTodo = WCA_TODO_UNKNOWN;
    LPWSTR pwzName = NULL;
    LPWSTR pwzRemoteAddresses = NULL;
    int iAttributes = 0;
    int iTarget = fetUnknown;
    LPWSTR pwzFile = NULL;
    LPWSTR pwzPort = NULL;
    LPWSTR pwzDescription = NULL;
    int iProtocol = 0;
    int iProfile = 0;

    // initialize
    hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
    ExitOnFailure(hr, "failed to initialize");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");
    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "failed to initialize COM");

    // Find out if we support profiles (only on Vista or later)
    fSupportProfiles = FSupportProfiles();

    // loop through all the passed in data
    pwz = pwzCustomActionData;
    while (pwz && *pwz)
    {
        // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL
        hr = WcaReadIntegerFromCaData(&pwz, &iTodo);
        ExitOnFailure(hr, "failed to read todo from custom action data");
        if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK))
        {
            if (WCA_TODO_INSTALL == iTodo)
            {
                iTodo = WCA_TODO_UNINSTALL;
            }
            else if (WCA_TODO_UNINSTALL == iTodo)
            {
                iTodo = WCA_TODO_INSTALL;
            }
        }

        hr = WcaReadStringFromCaData(&pwz, &pwzName);
        ExitOnFailure(hr, "failed to read name from custom action data");

        hr = WcaReadIntegerFromCaData(&pwz, &iProfile);
        ExitOnFailure(hr, "failed to read profile from custom action data");

        hr = WcaReadStringFromCaData(&pwz, &pwzRemoteAddresses);
        ExitOnFailure(hr, "failed to read remote addresses from custom action data");

        hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
        ExitOnFailure(hr, "failed to read attributes from custom action data");
        BOOL fIgnoreFailures = feaIgnoreFailures == (iAttributes & feaIgnoreFailures);

        hr = WcaReadIntegerFromCaData(&pwz, &iTarget);
        ExitOnFailure(hr, "failed to read target from custom action data");

        if (iTarget == fetApplication)
        {
            hr = WcaReadStringFromCaData(&pwz, &pwzFile);
            ExitOnFailure(hr, "failed to read file path from custom action data");
        }

        hr = WcaReadStringFromCaData(&pwz, &pwzPort);
        ExitOnFailure(hr, "failed to read port from custom action data");
        hr = WcaReadIntegerFromCaData(&pwz, &iProtocol);
        ExitOnFailure(hr, "failed to read protocol from custom action data");
        hr = WcaReadStringFromCaData(&pwz, &pwzDescription);
        ExitOnFailure(hr, "failed to read protocol from custom action data");

        switch (iTarget)
        {
        case fetPort:
            switch (iTodo)
            {
            case WCA_TODO_INSTALL:
            case WCA_TODO_REINSTALL:
                WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription);
                ExitOnFailure3(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                break;

            case WCA_TODO_UNINSTALL:
                WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                hr = RemovePortException(fSupportProfiles, pwzName, pwzPort, iProtocol, fIgnoreFailures);
                ExitOnFailure3(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
                break;
            }
            break;

        case fetApplication:
            switch (iTodo)
            {
            case WCA_TODO_INSTALL:
            case WCA_TODO_REINSTALL:
                WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile);
                hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription);
                ExitOnFailure2(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile);
                break;

            case WCA_TODO_UNINSTALL:
                WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile);
                hr = RemoveApplicationException(fSupportProfiles, pwzName, pwzFile, fIgnoreFailures, pwzPort, iProtocol);
                ExitOnFailure2(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile);
                break;
            }
            break;
        }
    }

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzName);
    ReleaseStr(pwzRemoteAddresses);
    ReleaseStr(pwzFile);
    ReleaseStr(pwzPort);
    ReleaseStr(pwzDescription);
    ::CoUninitialize();

    return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
}
Ejemplo n.º 26
0
HRESULT CpiRollbackConfigurePartitionUsers(
    LPWSTR* ppwzData,
    CPI_ROLLBACK_DATA* pRollbackDataList
    )
{
    HRESULT hr = S_OK;

    int iRollbackStatus;

    CPI_PARTITION_USER_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 partition attributes from CustomActionData
        hr = ReadPartitionUserAttributes(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.pwzAccount);
        ExitOnFailure(hr, "Failed to send progress messages");

        if (S_FALSE == hr)
            ExitFunction();

        // action
        switch (attrs.iActionType)
        {
        case atCreate:
            hr = CreatePartitionUser(&attrs);
            ExitOnFailure1(hr, "Failed to create partition user, key: %S", attrs.pwzKey);
            break;
        case atRemove:
            hr = RemovePartitionUser(&attrs);
            ExitOnFailure1(hr, "Failed to remove partition user, key: %S", 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
    FreePartitionUserAttributes(&attrs);

    return hr;
}