Ejemplo n.º 1
0
HRESULT CpiActionStartMessage(
	LPWSTR* ppwzActionData,
	BOOL fSuppress
	)
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	PMSIHANDLE hRec;

	LPWSTR pwzData = NULL;

	// create record
	hRec = ::MsiCreateRecord(3);
	ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record");

	// action name
	hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
	ExitOnFailure(hr, "Failed to action name");

	er = ::MsiRecordSetStringW(hRec, 1, pwzData);
	ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set action name");

	// description
	hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
	ExitOnFailure(hr, "Failed to description");

	er = ::MsiRecordSetStringW(hRec, 2, pwzData);
	ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set description");

	// template
	hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
	ExitOnFailure(hr, "Failed to template");

	er = ::MsiRecordSetStringW(hRec, 3, pwzData);
	ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set template");

	// message
	if (!fSuppress)
	{
		er = WcaProcessMessage(INSTALLMESSAGE_ACTIONSTART, hRec);
		if (0 == er || IDOK == er || IDYES == er)
		{
			hr = S_OK;
		}
		else if (IDABORT == er || IDCANCEL == er)
		{
			WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit
			hr = S_FALSE;
		}
		else
			hr = E_UNEXPECTED;
	}

LExit:
	// clean up
	ReleaseStr(pwzData);

	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 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.º 4
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.º 5
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.º 6
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.º 7
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.º 8
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.º 9
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.º 10
0
/********************************************************************
ConfigureIIsExec - custom action for installing IIs settings - table
data will be wrapped and passed in from immediate CA
ReadIIsTables

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

    BOOL fInitializedCom = FALSE;
    IMSAdminBase* piMetabase = NULL;

    SCA_WEB* pswList = NULL;
    SCA_WEBDIR* pswdList = NULL;
    SCA_VDIR* psvdList = NULL;
    SCA_FILTER* psfList = NULL;
    SCA_APPPOOL *psapList = NULL;
    SCA_MIMEMAP* psmmList = NULL;
    SCA_HTTP_HEADER* pshhList = NULL;
    SCA_PROPERTY *pspList = NULL;
    SCA_WEBSVCEXT* psWseList = NULL;
    SCA_WEB_ERROR* psweList = NULL;

    LPWSTR pwzScriptKey = NULL;
    LPWSTR pwzCustomActionData = NULL;

    WCA_WRAPQUERY_HANDLE hUserQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL;
    WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL;

    // initialize
    hr = WcaInitialize(hInstall, "ConfigureIIsExec");
    ExitOnFailure(hr, "Failed to initialize");

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

    // Get the CaScript key
    hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey);
    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");

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

    // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the
    // user to still uninstall this package by clicking "Ignore"
    do
    {
        hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)&piMetabase);
        if (FAILED(hr))
        {
            WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object");
            er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
            switch (er)
            {
            case IDABORT:
                ExitFunction();   // bail with the error result from the CoCreate to kick off a rollback
            case IDRETRY:
                hr = S_FALSE;   // hit me, baby, one more time
                break;
            case IDIGNORE:
                __fallthrough;
            default:
                WcaLog(LOGMSG_STANDARD, "ignoring absent IIS");
                // We need to write the empty script to communicate to other deferred CA that there is noting to do.
                hr = ScaWriteConfigurationScript(pwzScriptKey);
                ExitOnFailure(hr, "failed to schedule metabase configuration");

                ExitFunction1(hr = S_OK);  // pretend everything is okay
                break;
            }
        }
    } while (S_FALSE == hr);

    // read the msi tables
    hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap user query");

    hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions");

    hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools");

    // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read
    hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps");

    hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders");

    hr = ScaWebErrorRead(&psweList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors");

    hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web dir properties query");

    hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap ssl certificate query");

    hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web log query");

    hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web application query");

    hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web application extension query");

    hr = ScaWebsRead(piMetabase, &psmmList, &pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites");

    hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web base query");

    hr = ScaWebDirsRead(piMetabase, pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList);
    MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs");

    hr = ScaVirtualDirsRead(piMetabase, pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs");

    hr = ScaFiltersRead(piMetabase, pswList, hWebBaseQuery, &psfList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters");

    hr = ScaPropertyRead(&pspList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties");

    // do uninstall actions (order is important!)
    hr = ScaPropertyUninstall(piMetabase, pspList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties");

    hr = ScaFiltersUninstall(piMetabase, psfList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters");

    hr = ScaVirtualDirsUninstall(piMetabase, psvdList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories");

    hr = ScaWebDirsUninstall(piMetabase, pswdList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories");

    hr = ScaWebsUninstall(piMetabase, pswList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs");

    hr = ScaAppPoolUninstall(piMetabase, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools");


    // do install actions (order is important!)
    // ScaWebSvcExtCommit contains both uninstall and install actions.
    hr = ScaWebSvcExtCommit(piMetabase, psWseList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt");

    hr = ScaAppPoolInstall(piMetabase, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools");

    hr = ScaWebsInstall(piMetabase, pswList, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs");

    hr = ScaWebDirsInstall(piMetabase, pswdList, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories");

    hr = ScaVirtualDirsInstall(piMetabase, psvdList, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories");

    hr = ScaFiltersInstall(piMetabase, psfList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters");

    hr = ScaPropertyInstall(piMetabase, pspList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties");

    hr = ScaWriteConfigurationScript(pwzScriptKey);
    ExitOnFailure(hr, "failed to schedule metabase configuration");

LExit:
    ReleaseStr(pwzScriptKey);
    ReleaseStr(pwzCustomActionData);

    WcaFinishUnwrapQuery(hUserQuery);
    WcaFinishUnwrapQuery(hWebBaseQuery);
    WcaFinishUnwrapQuery(hWebDirPropQuery);
    WcaFinishUnwrapQuery(hSslCertQuery);
    WcaFinishUnwrapQuery(hWebLogQuery);
    WcaFinishUnwrapQuery(hWebAppQuery);
    WcaFinishUnwrapQuery(hWebAppExtQuery);

    if (psWseList)
    {
        ScaWebSvcExtFreeList(psWseList);
    }

    if (psfList)
    {
        ScaFiltersFreeList(psfList);
    }

    if (psvdList)
    {
        ScaVirtualDirsFreeList(psvdList);
    }

    if (pswdList)
    {
        ScaWebDirsFreeList(pswdList);
    }

    if (pswList)
    {
        ScaWebsFreeList(pswList);
    }

    if (psmmList)
    {
        ScaMimeMapCheckList(psmmList);
        ScaMimeMapFreeList(psmmList);
    }

    if (pshhList)
    {
        ScaHttpHeaderCheckList(pshhList);
        ScaHttpHeaderFreeList(pshhList);
    }

    if (psweList)
    {
        ScaWebErrorCheckList(psweList);
        ScaWebErrorFreeList(psweList);
    }

    ReleaseObject(piMetabase);

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

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Ejemplo n.º 11
0
/********************************************************************
 ComPlusRollbackUninstallExecute - CUSTOM ACTION ENTRY POINT

  Input:  deferred CustomActionData - ComPlusRollbackUninstallExecute
********************************************************************/
extern "C" UINT __stdcall ComPlusRollbackUninstallExecute(MSIHANDLE hInstall)
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	LPWSTR pwzData = NULL;
	LPWSTR pwzRollbackFileName = NULL;

	HANDLE hRollbackFile = INVALID_HANDLE_VALUE;

	CPI_ROLLBACK_DATA* prdPartitions = NULL;
	CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL;
	CPI_ROLLBACK_DATA* prdPartitionUsers = NULL;
	CPI_ROLLBACK_DATA* prdApplications = NULL;
	CPI_ROLLBACK_DATA* prdApplicationRoles = NULL;
	CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL;
	CPI_ROLLBACK_DATA* prdAssemblies = NULL;
	CPI_ROLLBACK_DATA* prdRoleAssignments = NULL;
	CPI_ROLLBACK_DATA* prdSubscriptions = NULL;

	BOOL fInitializedCom = FALSE;

	// initialize
	hr = WcaInitialize(hInstall, "ComPlusRollbackUninstallExecute");
	ExitOnFailure(hr, "Failed to initialize ComPlusRollbackUninstallExecute");

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

	CpiInitialize();

	// get custom action data
	hr = WcaGetProperty(L"CustomActionData", &pwzData);
	ExitOnFailure(hr, "Failed to get CustomActionData");

	// open rollback file
	hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
	ExitOnFailure(hr, "Failed to read rollback file name");

	hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
	if (INVALID_HANDLE_VALUE == hRollbackFile)
		ExitOnFailure1(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);

	// read rollback data
	hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions);
	ExitOnFailure(hr, "Failed to read subscription rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments);
	ExitOnFailure(hr, "Failed to read role assignments rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies);
	ExitOnFailure(hr, "Failed to read assemblies rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles);
	ExitOnFailure(hr, "Failed to read users in application roles rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles);
	ExitOnFailure(hr, "Failed to read application roles rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications);
	ExitOnFailure(hr, "Failed to read applications rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers);
	ExitOnFailure(hr, "Failed to read partition users rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles);
	ExitOnFailure(hr, "Failed to read users in partition roles rollback data");
	hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions);
	ExitOnFailure(hr, "Failed to read partitions rollback data");

	::CloseHandle(hRollbackFile);
	hRollbackFile = INVALID_HANDLE_VALUE;

	// rollback remove partitions
	hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions);
	ExitOnFailure(hr, "Failed to rollback delete partitions");

	// rollback remove users in partition roles
	hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles);
	ExitOnFailure(hr, "Failed to rollback delete users in partition roles");

	// rollback remove partition users
	hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers);
	ExitOnFailure(hr, "Failed to rollback delete partition users");

	// rollback remove applications
	hr = CpiRollbackConfigureApplications(&pwzData, prdApplications);
	ExitOnFailure(hr, "Failed to rollback delete applications");

	// rollback remove application roles
	hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles);
	ExitOnFailure(hr, "Failed to rollback delete application roles");

	// rollback remove users in application roles
	hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles);
	ExitOnFailure(hr, "Failed to rollback delete users in application roles");

	// rollback unregister assemblies
	hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies);
	ExitOnFailure(hr, "Failed to rollback unregister assemblies");

	// rollback delete role assignments
	hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdAssemblies);
	ExitOnFailure(hr, "Failed to rollback delete role assignments");

	// rollback delete subscriptions
	hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions);
	ExitOnFailure(hr, "Failed to rollback delete subscriptions");

	hr = S_OK;

LExit:
	// clean up
	ReleaseStr(pwzData);
	ReleaseStr(pwzRollbackFileName);

	if (INVALID_HANDLE_VALUE != hRollbackFile)
		::CloseHandle(hRollbackFile);

	if (prdPartitions)
		CpiFreeRollbackDataList(prdPartitions);
	if (prdUsersInPartitionRoles)
		CpiFreeRollbackDataList(prdUsersInPartitionRoles);
	if (prdPartitionUsers)
		CpiFreeRollbackDataList(prdPartitionUsers);
	if (prdApplications)
		CpiFreeRollbackDataList(prdApplications);
	if (prdApplicationRoles)
		CpiFreeRollbackDataList(prdApplicationRoles);
	if (prdUsersApplicationRoles)
		CpiFreeRollbackDataList(prdUsersApplicationRoles);
	if (prdAssemblies)
		CpiFreeRollbackDataList(prdAssemblies);
	if (prdRoleAssignments)
		CpiFreeRollbackDataList(prdRoleAssignments);
	if (prdSubscriptions)
		CpiFreeRollbackDataList(prdSubscriptions);

	// unitialize
	CpiFinalize();

	if (fInitializedCom)
		::CoUninitialize();

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
Ejemplo n.º 12
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.º 13
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.º 14
0
/********************************************************************
 ComPlusInstallExecuteCommit - CUSTOM ACTION ENTRY POINT

  Input:  deferred CustomActionData - ComPlusInstallExecuteCommit
********************************************************************/
extern "C" UINT __stdcall ComPlusInstallExecuteCommit(MSIHANDLE hInstall)
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	LPWSTR pwzData = NULL;
	LPWSTR pwzRollbackFileName = NULL;

	HANDLE hRollbackFile = INVALID_HANDLE_VALUE;

	BOOL fInitializedCom = FALSE;

	// initialize
	hr = WcaInitialize(hInstall, "ComPlusInstallExecuteCommit");
	ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecuteCommit");

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

	CpiInitialize();

	// get custom action data
	hr = WcaGetProperty(L"CustomActionData", &pwzData);
	ExitOnFailure(hr, "Failed to get CustomActionData");

	// open rollback file
	hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
	ExitOnFailure(hr, "Failed to read rollback file name");

	hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
	if (INVALID_HANDLE_VALUE == hRollbackFile)
		ExitOnFailure1(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);

	if (INVALID_SET_FILE_POINTER == ::SetFilePointer(hRollbackFile, 0, NULL, FILE_END))
		ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set file pointer");

	// register assemblies
	hr = CpiConfigureAssemblies(&pwzData, hRollbackFile);
	ExitOnFailure(hr, "Failed to register assemblies");
	if (S_FALSE == hr) ExitFunction();

	// create role assignments
	hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile);
	ExitOnFailure(hr, "Failed to create role assignments");
	if (S_FALSE == hr) ExitFunction();

	// create subscriptions
	hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile);
	ExitOnFailure(hr, "Failed to create subscriptions");
	if (S_FALSE == hr) ExitFunction();

	hr = S_OK;

LExit:
	// clean up
	ReleaseStr(pwzData);

	if (INVALID_HANDLE_VALUE != hRollbackFile)
		::CloseHandle(hRollbackFile);

	// unitialize
	CpiFinalize();

	if (fInitializedCom)
		::CoUninitialize();

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
Ejemplo n.º 15
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.º 16
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);
}
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.º 18
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.º 19
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.º 20
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.º 21
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.º 22
0
/********************************************************************
ConfigureIIs - CUSTOM ACTION ENTRY POINT for installing IIs settings

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

    LPWSTR pwzScriptKey = NULL;
    LPWSTR pwzCustomActionData = NULL;

    SCA_WEB7* pswList = NULL;
    SCA_WEBDIR7* pswdList = NULL;
    SCA_VDIR7* psvdList = NULL;
    SCA_FILTER* psfList = NULL;
    SCA_APPPOOL *psapList = NULL;
    SCA_MIMEMAP* psmmList = NULL;
    SCA_HTTP_HEADER* pshhList = NULL;
    SCA_PROPERTY *pspList = NULL;
    SCA_WEBSVCEXT* psWseList = NULL;
    SCA_WEB_ERROR* psweList = NULL;

    WCA_WRAPQUERY_HANDLE hUserQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebBaseQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebDirPropQuery = NULL;
    WCA_WRAPQUERY_HANDLE hSslCertQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebLogQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebAppQuery = NULL;
    WCA_WRAPQUERY_HANDLE hWebAppExtQuery = NULL;

    // initialize
    hr = WcaInitialize(hInstall, "ConfigureIIs7Exec");
    ExitOnFailure(hr, "Failed to initialize");

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

    // Get the CaScript key
    hr = WcaReadStringFromCaData(&pwzCustomActionData, &pwzScriptKey);
    ExitOnFailure(hr, "Failed to get CaScript key from custom action data");

    // read the msi tables
    hr = WcaBeginUnwrapQuery(&hUserQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap user query");

    hr = ScaWebSvcExtRead(&psWseList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadWebSvcExt, "failed while processing WebServiceExtensions");

    hr = ScaAppPoolRead(&psapList, hUserQuery, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadAppPool, "failed while processing WebAppPools");

    // MimeMap, Error and HttpHeader need to be read before the virtual directory and web read
    hr = ScaMimeMapRead(&psmmList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadMimeMap, "failed while processing MimeMaps");

    hr = ScaHttpHeaderRead(&pshhList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadHttpHeader, "failed while processing HttpHeaders");

    hr = ScaWebErrorRead(&psweList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadWebError, "failed while processing WebErrors");

    hr = WcaBeginUnwrapQuery(&hWebDirPropQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web dir properties query");

    hr = WcaBeginUnwrapQuery(&hSslCertQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap ssl certificate query");

    hr = WcaBeginUnwrapQuery(&hWebLogQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web log query");

    hr = WcaBeginUnwrapQuery(&hWebAppQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web application query");

    hr = WcaBeginUnwrapQuery(&hWebAppExtQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web application extension query");

    hr = ScaWebsRead7(&pswList, &pshhList, &psweList, hUserQuery, hWebDirPropQuery, hSslCertQuery, hWebLogQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadWebSite, "failed while processing WebSites");

    hr = WcaBeginUnwrapQuery(&hWebBaseQuery, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap web base query");

    hr = ScaWebDirsRead7(pswList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData, &pswdList);
    MessageExitOnFailure(hr, msierrIISFailedReadWebDirs, "failed while processing WebDirs");

    hr = ScaVirtualDirsRead7(pswList, &psvdList, &psmmList, &pshhList, &psweList, hUserQuery, hWebBaseQuery, hWebDirPropQuery, hWebAppQuery, hWebAppExtQuery, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadVDirs, "failed while processing WebVirtualDirs");

    hr = ScaFiltersRead7(pswList, hWebBaseQuery, &psfList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadFilters, "failed while processing WebFilters");

    hr = ScaPropertyRead(&pspList, &pwzCustomActionData);
    MessageExitOnFailure(hr, msierrIISFailedReadProp, "failed while processing WebProperties");

    // do uninstall actions (order is important!)
    hr = ScaPropertyUninstall7(pspList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallProp, "failed to uninstall IIS properties");

    hr = ScaFiltersUninstall7(psfList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallFilters, "failed to schedule uninstall of filters");

    hr = ScaVirtualDirsUninstall7(psvdList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallVDirs, "failed to schedule uninstall of virtual directories");

    hr = ScaWebDirsUninstall7(pswdList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebDirs, "failed to schedule uninstall of web directories");

    hr = ScaWebsUninstall7(pswList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallWebs, "failed to schedule uninstall of webs");

    hr = ScaAppPoolUninstall7(psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedUninstallAppPool, "failed to schedule uninstall of AppPools");


    // do install actions (order is important!)
    // ScaWebSvcExtCommit contains both uninstall and install actions.
    hr = ScaWebSvcExtCommit7(psWseList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebSvcExt, "failed to schedule install/uninstall of WebSvcExt");

    hr = ScaAppPoolInstall7(psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallAppPool, "failed to schedule install of AppPools");

    hr = ScaWebsInstall7(pswList, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebs, "failed to schedule install of webs");

    hr = ScaWebDirsInstall7(pswdList, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallWebDirs, "failed to schedule install of web directories");

    hr = ScaVirtualDirsInstall7(psvdList, psapList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallVDirs, "failed to schedule install of virtual directories");

    hr = ScaFiltersInstall7(psfList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallFilters, "failed to schedule install of filters");

    hr = ScaPropertyInstall7(pspList);
    MessageExitOnFailure(hr, msierrIISFailedSchedInstallProp, "failed to schedule install of properties");

    hr = ScaWriteConfigurationScript(pwzScriptKey);
    ExitOnFailure(hr, "failed to schedule metabase configuration");

LExit:
    ReleaseNullStr(pwzScriptKey);
    ReleaseNullStr(pwzCustomActionData);

    WcaFinishUnwrapQuery(hUserQuery);
    WcaFinishUnwrapQuery(hWebBaseQuery);
    WcaFinishUnwrapQuery(hWebDirPropQuery);
    WcaFinishUnwrapQuery(hSslCertQuery);
    WcaFinishUnwrapQuery(hWebLogQuery);
    WcaFinishUnwrapQuery(hWebAppQuery);
    WcaFinishUnwrapQuery(hWebAppExtQuery);

    if (psWseList)
    {
        ScaWebSvcExtFreeList(psWseList);
    }

    if (psfList)
    {
        ScaFiltersFreeList(psfList);
    }

    if (psvdList)
    {
        ScaVirtualDirsFreeList7(psvdList);
    }

    if (pswdList)
    {
        ScaWebDirsFreeList7(pswdList);
    }

    if (pswList)
    {
        ScaWebsFreeList7(pswList);
    }

    if (psmmList)
    {
        ScaMimeMapFreeList(psmmList);
    }

    if (pshhList)
    {
        ScaHttpHeaderCheckList(pshhList);
        ScaHttpHeaderFreeList(pshhList);
    }

    if (psweList)
    {
        ScaWebErrorCheckList(psweList);
        ScaWebErrorFreeList(psweList);
    }

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Ejemplo n.º 23
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);
}
Ejemplo n.º 24
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.º 25
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;
}