Example #1
0
HRESULT CpiSubscriptionsRead(
    CPI_ASSEMBLY_LIST* pAsmList,
    CPI_SUBSCRIPTION_LIST* pSubList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

    CPI_SUBSCRIPTION* pItm = NULL;
    LPWSTR pwzData = NULL;
    BOOL fMatchingArchitecture = FALSE;

    // loop through all applications
    hr = WcaOpenExecuteView(vcsSubscriptionQuery, &hView);
    ExitOnFailure(hr, "Failed to execute view on ComPlusSubscription table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // get component
        hr = WcaGetRecordString(hRec, sqComponent, &pwzData);
        ExitOnFailure(hr, "Failed to get component");

        // check if the component is our processor architecture
        hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
        ExitOnFailure(hr, "Failed to get component architecture.");

        if (!fMatchingArchitecture)
        {
            continue; // not the same architecture, ignore
        }

        // create entry
        pItm = (CPI_SUBSCRIPTION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_SUBSCRIPTION));
        if (!pItm)
            ExitFunction1(hr = E_OUTOFMEMORY);

        // get component install state
        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
        ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");

        // get key
        hr = WcaGetRecordString(hRec, sqSubscription, &pwzData);
        ExitOnFailure(hr, "Failed to get key");
        StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);

        // get com+ component
        hr = WcaGetRecordString(hRec, sqComPlusComponent, &pwzData);
        ExitOnFailure(hr, "Failed to get COM+ component");

        hr = ComponentFindByKey(pAsmList, pwzData, &pItm->pAssembly, &pItm->pComponent);

        if (S_FALSE == hr)
        {
            // component not found
            ExitOnFailure1(hr = E_FAIL, "Failed to find component, key: %S", pwzData);
        }

        // get id
        hr = WcaGetRecordFormattedString(hRec, sqID, &pwzData);
        ExitOnFailure(hr, "Failed to get id");

        if (pwzData && *pwzData)
        {
            hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID));
            ExitOnFailure2(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData);
        }

        // get name
        hr = WcaGetRecordFormattedString(hRec, sqName, &pwzData);
        ExitOnFailure(hr, "Failed to get name");
        StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);

        // get event clsid
        hr = WcaGetRecordFormattedString(hRec, sqEventCLSID, &pwzData);
        ExitOnFailure(hr, "Failed to get event clsid");
        StringCchCopyW(pItm->wzEventCLSID, countof(pItm->wzEventCLSID), pwzData);

        // get publisher id
        hr = WcaGetRecordFormattedString(hRec, sqPublisherID, &pwzData);
        ExitOnFailure(hr, "Failed to get publisher id");
        StringCchCopyW(pItm->wzPublisherID, countof(pItm->wzPublisherID), pwzData);

        // get properties
        if (CpiTableExists(cptComPlusSubscriptionProperty))
        {
            hr = CpiPropertiesRead(vcsSubscriptionPropertyQuery, pItm->wzKey, pdlSubscriptionProperties, &pItm->pProperties, &pItm->iPropertyCount);
            ExitOnFailure(hr, "Failed to get subscription properties");
        }

        // set references & increment counters
        if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
        {
            CpiApplicationAddReferenceInstall(pItm->pAssembly->pApplication);
            pItm->pAssembly->fReferencedForInstall = TRUE;
            pSubList->iInstallCount++;
            if (pItm->pAssembly->iAttributes & aaRunInCommit)
                pSubList->iCommitCount++;
        }
        if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
        {
            CpiApplicationAddReferenceUninstall(pItm->pAssembly->pApplication);
            pItm->pAssembly->fReferencedForUninstall = TRUE;
            pSubList->iUninstallCount++;
        }

        // add entry
        if (pSubList->pFirst)
            pItm->pNext = pSubList->pFirst;
        pSubList->pFirst = pItm;
        pItm = NULL;
    }

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

LExit:
    // clean up
    if (pItm)
        FreeSubscription(pItm);

    ReleaseStr(pwzData);

    return hr;
}
HRESULT CpiRollbackConfigureUsersInPartitionRoles(
	LPWSTR* ppwzData,
	CPI_ROLLBACK_DATA* pRollbackDataList
	)
{
	HRESULT hr = S_OK;

	int iRollbackStatus;

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

	// read action text
	hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
	ExitOnFailure(hr, "Failed to send action start message");

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

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

		// rollback status
		hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);

		if (S_FALSE == hr)
			continue; // not found, nothing to rollback

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

		if (S_FALSE == hr)
			ExitFunction();

		// action
		switch (attrs.iActionType)
		{
		case atCreate:
			hr = CreateUserInPartitionRole(&attrs);
			if (FAILED(hr))
				WcaLog(LOGMSG_STANDARD, "Failed to add user to partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
			break;
		case atRemove:
			hr = RemoveUserInPartitionRole(&attrs);
			if (FAILED(hr))
				WcaLog(LOGMSG_STANDARD, "Failed to remove user from partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
			break;
		}

		// check rollback status
		if (0 == iRollbackStatus)
			continue; // operation did not complete, skip progress

		// progress
		hr = WcaProgressMessage(attrs.iActionCost, FALSE);
		ExitOnFailure(hr, "Failed to update progress");
	}

	hr = S_OK;

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

	return hr;
}
static HRESULT RemoveUserInPartitionRole(
	CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
	)
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	ICatalogCollection* piUsrInRoleColl = NULL;

	PSID pSid = NULL;
	long lChanges = 0;

	// log
	WcaLog(LOGMSG_VERBOSE, "Removing user from partition role, key: %S", pAttrs->pwzKey);

	// get users in partition role collection
	hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl);
	ExitOnFailure(hr, "Failed to get users in partition role collection");

	if (S_FALSE == hr)
	{
		// users in role collection not found
		WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in partition role collection, nothing to delete, key: %S", pAttrs->pwzKey);
		ExitFunction1(hr = S_OK);
	}

	// get SID for account
	do {
		er = ERROR_SUCCESS;
		hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
		if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
		{
			WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
			er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
			switch (er)
			{
			case IDABORT:
				ExitFunction(); // exit with error code from CpiAccountNameToSid()
			case IDRETRY:
				break;
			case IDIGNORE:
				ExitFunction1(hr = S_OK);
			}
		}
		else
			ExitOnFailure(hr, "Failed to get SID for account");
	} while (IDRETRY == er);

	// remove
	hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid);
	if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
	{
		WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
		hr = S_FALSE;
	}
	else
		ExitOnFailure(hr, "Failed to remove user");

	if (S_FALSE == hr)
	{
		// role not found
		WcaLog(LOGMSG_VERBOSE, "User not found for partition role, nothing to delete, key: %S", pAttrs->pwzKey);
		ExitFunction1(hr = S_OK);
	}

	// save changes
	hr = piUsrInRoleColl->SaveChanges(&lChanges);
	if (COMADMIN_E_OBJECTERRORS == hr)
		CpiLogCatalogErrorInfo();
	ExitOnFailure(hr, "Failed to save changes");

	// log
	WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);

	hr = S_OK;

LExit:
	// clean up
	ReleaseObject(piUsrInRoleColl);

	if (pSid)
		::HeapFree(::GetProcessHeap(), 0, pSid);

	return hr;
}
static HRESULT TrusteesInPartitionRolesRead(
    LPCWSTR pwzQuery,
    CPI_PARTITION_ROLE_LIST* pPartRoleList,
    CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

    CPI_USER_IN_PARTITION_ROLE* pItm = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzDomain = NULL;
    LPWSTR pwzName = NULL;
    BOOL fMatchingArchitecture = FALSE;

    // loop through all application roles
    hr = WcaOpenExecuteView(pwzQuery, &hView);
    ExitOnFailure(hr, "Failed to execute view on table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // get component
        hr = WcaGetRecordString(hRec, tiprqComponent, &pwzData);
        ExitOnFailure(hr, "Failed to get component");

        // check if the component is our processor architecture
        hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
        ExitOnFailure(hr, "Failed to get component architecture.");

        if (!fMatchingArchitecture)
        {
            continue; // not the same architecture, ignore
        }

        // create entry
        pItm = (CPI_USER_IN_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_PARTITION_ROLE));
        if (!pItm)
            ExitFunction1(hr = E_OUTOFMEMORY);

        // get component install state
        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
        ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");

        // get key
        hr = WcaGetRecordString(hRec, tiprqUserInPartitionRole, &pwzData);
        ExitOnFailure(hr, "Failed to get key");
        StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);

        // get partition role
        hr = WcaGetRecordString(hRec, tiprqPartitionRole, &pwzData);
        ExitOnFailure(hr, "Failed to get partition role");

        hr = CpiPartitionRoleFindByKey(pPartRoleList, pwzData, &pItm->pPartitionRole);
        ExitOnFailure1(hr, "Failed to find partition role, key: %S", pwzData);

        // get user domain
        hr = WcaGetRecordFormattedString(hRec, tiprqDomain, &pwzDomain);
        ExitOnFailure(hr, "Failed to get domain");

        // get user name
        hr = WcaGetRecordFormattedString(hRec, tiprqName, &pwzName);
        ExitOnFailure(hr, "Failed to get name");

        // build account name
        hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount);
        ExitOnFailure(hr, "Failed to build account name");

        // increment counters
        if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
            pUsrInPartRoleList->iInstallCount++;
        if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
            pUsrInPartRoleList->iUninstallCount++;

        // add entry
        if (pUsrInPartRoleList->pFirst)
            pItm->pNext = pUsrInPartRoleList->pFirst;
        pUsrInPartRoleList->pFirst = pItm;
        pItm = NULL;
    }

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

LExit:
    // clean up
    if (pItm)
        FreeUserInPartitionRole(pItm);

    ReleaseStr(pwzData);
    ReleaseStr(pwzDomain);
    ReleaseStr(pwzName);

    return hr;
}
Example #5
0
extern "C" HRESULT DAPI LocProbeForFile(
    __in_z LPCWSTR wzBasePath,
    __in_z LPCWSTR wzLocFileName,
    __in_z_opt LPCWSTR wzLanguage,
    __inout LPWSTR* psczPath
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczProbePath = NULL;
    LANGID langid = 0;
    LPWSTR sczLangIdFile = NULL;

    // If a language was specified, look for a loc file in that as a directory.
    if (wzLanguage && *wzLanguage)
    {
        hr = PathConcat(wzBasePath, wzLanguage, &sczProbePath);
        ExitOnFailure(hr, "Failed to concat base path to language.");

        hr = PathConcat(sczProbePath, wzLocFileName, &sczProbePath);
        ExitOnFailure(hr, "Failed to concat loc file name to probe path.");

        if (FileExistsEx(sczProbePath, NULL))
        {
            ExitFunction();
        }
    }

    langid = ::GetUserDefaultLangID();

    hr = StrAllocFormatted(&sczLangIdFile, L"%u\\%ls", langid, wzLocFileName);
    ExitOnFailure(hr, "Failed to format user langid.");

    hr = PathConcat(wzBasePath, sczLangIdFile, &sczProbePath);
    ExitOnFailure(hr, "Failed to concat user langid file name to base path.");

    if (FileExistsEx(sczProbePath, NULL))
    {
        ExitFunction();
    }

    if (MAKELANGID(langid & 0x3FF, SUBLANG_DEFAULT) != langid) 
    { 
        langid = MAKELANGID(langid & 0x3FF, SUBLANG_DEFAULT); 
        
        hr = StrAllocFormatted(&sczLangIdFile, L"%u\\%ls", langid, wzLocFileName); 
        ExitOnFailure(hr, "Failed to format user langid (default sublang).");

        hr = PathConcat(wzBasePath, sczLangIdFile, &sczProbePath); 
        ExitOnFailure(hr, "Failed to concat user langid file name to base path (default sublang).");

        if (FileExistsEx(sczProbePath, NULL)) 
        { 
            ExitFunction(); 
        } 
    }

    langid = ::GetSystemDefaultUILanguage();

    hr = StrAllocFormatted(&sczLangIdFile, L"%u\\%ls", langid, wzLocFileName);
    ExitOnFailure(hr, "Failed to format system langid.");

    hr = PathConcat(wzBasePath, sczLangIdFile, &sczProbePath);
    ExitOnFailure(hr, "Failed to concat system langid file name to base path.");

    if (FileExistsEx(sczProbePath, NULL))
    {
        ExitFunction();
    }

    if (MAKELANGID(langid & 0x3FF, SUBLANG_DEFAULT) != langid) 
    { 
        langid = MAKELANGID(langid & 0x3FF, SUBLANG_DEFAULT); 
        
        hr = StrAllocFormatted(&sczLangIdFile, L"%u\\%ls", langid, wzLocFileName); 
        ExitOnFailure(hr, "Failed to format user langid (default sublang).");

        hr = PathConcat(wzBasePath, sczLangIdFile, &sczProbePath); 
        ExitOnFailure(hr, "Failed to concat user langid file name to base path (default sublang).");

        if (FileExistsEx(sczProbePath, NULL)) 
        { 
            ExitFunction(); 
        } 
    }

    // Finally, look for the loc file in the base path.
    hr = PathConcat(wzBasePath, wzLocFileName, &sczProbePath);
    ExitOnFailure(hr, "Failed to concat loc file name to base path.");

    if (!FileExistsEx(sczProbePath, NULL))
    {
        hr = E_FILENOTFOUND;
    }

LExit:
    if (SUCCEEDED(hr))
    {
        hr = StrAllocString(psczPath, sczProbePath, 0);
    }

    ReleaseStr(sczLangIdFile);
    ReleaseStr(sczProbePath);

    return hr;
}
Example #6
0
HRESULT ScaWebsRead(
    __in IMSAdminBase* piMetabase,
    __in SCA_MIMEMAP** ppsmmList,
    __in SCA_WEB** ppswList,
    __in SCA_HTTP_HEADER** ppshhList,
    __in SCA_WEB_ERROR** ppsweList,
    __in WCA_WRAPQUERY_HANDLE hUserQuery,
    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
    __in WCA_WRAPQUERY_HANDLE hSslCertQuery,
    __in WCA_WRAPQUERY_HANDLE hWebLogQuery,
    __in WCA_WRAPQUERY_HANDLE hWebAppQuery,
    __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery,
    __inout LPWSTR *ppwzCustomActionData
    )
{
    Assert(piMetabase && ppswList);

    HRESULT hr = S_OK;

    MSIHANDLE hRec;
    MSIHANDLE hRecAddresses;

    SCA_WEB* psw = NULL;
    LPWSTR pwzData = NULL;
    int iSiteId;

    DWORD dwLen = 0;
    WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL;
    WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL;

    hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");

    hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData);
    ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead");

    if (0 == WcaGetQueryRecords(hQueryWebSite))
    {
        WcaLog(LOGMSG_VERBOSE, "Required tables not present");
        ExitFunction1(hr = S_FALSE);
    }

    // loop through all the webs
    while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec)))
    {
        psw = NewWeb();
        ExitOnNull(psw, hr, E_OUTOFMEMORY, "Failed to allocate memory for web object in memory");

        // get the darwin information
        hr = WcaGetRecordString(hRec, wqWeb, &pwzData);
        ExitOnFailure(hr, "Failed to get Web");
        hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData);
        ExitOnFailure(hr, "Failed to copy key string to web object");

        if (*pwzData && *ppsmmList)
        {
            hr = ScaGetMimeMap(mmptWeb, pwzData, ppsmmList, &psw->psmm);
            ExitOnFailure(hr, "Failed to get mimemap for VirtualDir");
        }

        // get component install state
        hr = WcaGetRecordString(hRec, wqComponent, &pwzData);
        ExitOnFailure(hr, "Failed to get Component for Web");
        hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData);
        ExitOnFailure(hr, "Failed to copy component string to web object");
        if (*(psw->wzComponent))
        {
            psw->fHasComponent = TRUE;

            hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled);
            ExitOnFailure(hr, "Failed to get web Component's installed state");

            WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction);
            ExitOnFailure(hr, "Failed to get web Component's action state");

            if (!WcaIsInstalling(psw->isInstalled, psw->isAction) && !WcaIsUninstalling(psw->isInstalled, psw->isAction)
                && !WcaIsReInstalling(psw->isInstalled, psw->isAction))
            {
                FreeWeb(psw);
                psw = NULL;

                continue; // If we aren't acting on this component, skip it
            }
        }

        hr = WcaGetRecordInteger(hRec, wqId, &iSiteId);
        ExitOnFailure(hr, "Failed to get SiteId for Web");

        // Get the web's key address.
        hr = WcaGetRecordString(hRec, wqAddress, &pwzData);
        ExitOnFailure(hr, "Failed to get Address for Web");
        hr = ::StringCchCopyW(psw->swaKey.wzKey, countof(psw->swaKey.wzKey), pwzData);
        ExitOnFailure(hr, "Failed to copy key string to web object");

        hr = WcaGetRecordString(hRec, wqIP, &pwzData);
        ExitOnFailure(hr, "Failed to get IP for Web");
        hr = ::StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData);
        ExitOnFailure(hr, "Failed to copy IP string to web object");

        hr = WcaGetRecordString(hRec, wqPort, &pwzData);
        ExitOnFailure(hr, "Failed to get Web Address port");
        psw->swaKey.iPort = wcstol(pwzData, NULL, 10);

        hr = WcaGetRecordString(hRec, wqHeader, &pwzData);
        ExitOnFailure(hr, "Failed to get Header for Web");
        hr = ::StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData);
        ExitOnFailure(hr, "Failed to copy header string to web object");

        hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaKey.fSecure);
        ExitOnFailure(hr, "Failed to get if Web is secure");
        if (S_FALSE == hr)
        {
            psw->swaKey.fSecure = FALSE;
        }

        // Get the web's description.
        hr = WcaGetRecordString(hRec, wqDescription, &pwzData);
        ExitOnFailure(hr, "Failed to get Description for Web");
        hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData);
        ExitOnFailure(hr, "Failed to copy description string to web object");

        // Try to find the web root in case it already exists.
        dwLen = METADATA_MAX_NAME_LEN;
        hr = ScaWebFindBase(piMetabase, *ppswList,
                            psw->wzKey,
                            iSiteId,
                            psw->swaKey.wzIP,
                            psw->swaKey.iPort,
                            psw->swaKey.wzHeader,
                            psw->swaKey.fSecure,
                            psw->wzDescription,
                            psw->wzWebBase, dwLen);
        if (S_OK == hr)
        {
            psw->fBaseExists = TRUE;
        }
        else if (S_FALSE == hr) // didn't find the web site.
        {
            psw->fBaseExists = FALSE;

            // If we're actually configuring the web site.
            if (psw->fHasComponent)
            {
                if (WcaIsInstalling(psw->isInstalled, psw->isAction))
                {
                    hr = ScaWebFindFreeBase(piMetabase, *ppswList, iSiteId, psw->wzDescription, psw->wzWebBase, countof(psw->wzWebBase));
                    ExitOnFailure(hr, "Failed to find free web root.");
                }
                else if (WcaIsUninstalling(psw->isInstalled, psw->isAction))
                {
                    WcaLog(LOGMSG_VERBOSE, "Web site: '%ls' was already removed, skipping.", psw->wzKey);

                    hr = S_OK;
                    continue;
                }
            }
        }
        ExitOnFailure(hr, "Failed to find web root");

        // get any extra web addresses
        WcaFetchWrappedReset(hQueryWebAddress);
        while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses)))
        {
            if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses)
            {
                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
                ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded.");
            }

            hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData);
            ExitOnFailure(hr, "Failed to get extra web Address");

            // if this isn't the key address add it
            if (0 != lstrcmpW(pwzData, psw->swaKey.wzKey))
            {
                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData);
                ExitOnFailure(hr, "Failed to copy extra addresses key string to web object");

                hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData);
                ExitOnFailure(hr, "Failed to get extra web IP");
                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData);
                ExitOnFailure(hr, "Failed to copy extra addresses IP string to web object");

                hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData);
                ExitOnFailure(hr, "Failed to get port for extra web IP");
                psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10);

                hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData);
                ExitOnFailure(hr, "Failed to get header for extra web IP");
                hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData);
                ExitOnFailure(hr, "Failed to copy extra addresses header string to web object");

                hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure);
                ExitOnFailure(hr, "Failed to get if secure extra web IP");
                if (S_FALSE == hr)
                    psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE;

                ++psw->cExtraAddresses;
            }
        }

        if (E_NOMOREITEMS == hr)
            hr = S_OK;
        ExitOnFailure(hr, "Failure occured while getting extra web addresses");

        hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout);
        ExitOnFailure(hr, "Failed to get connection timeout for Web");

        if (psw->fHasComponent) // If we're installing it, it needs a dir
        {
            // get the web's directory
            if (INSTALLSTATE_SOURCE == psw->isAction)
            {
                hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData);
            }
            else
            {
                hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData);
            }
            ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");

            // remove trailing backslashes
            while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\')
            {
                pwzData[lstrlenW(pwzData)-1] = 0;
            }
            hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData);
            ExitOnFailure(hr, "Failed to copy directory string to web object");
        }

        hr = WcaGetRecordInteger(hRec, wqState, &psw->iState);
        ExitOnFailure(hr, "Failed to get state for Web");

        hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes);
        ExitOnFailure(hr, "Failed to get attributes for Web");

        // get the dir properties for this web
        hr = WcaGetRecordString(hRec, wqProperties, &pwzData);
        ExitOnFailure(hr, "Failed to get directory property record for Web");
        if (*pwzData)
        {
            hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp);
            ExitOnFailure(hr, "Failed to get directory properties for Web");

            psw->fHasProperties = TRUE;
        }

        // get the application information for this web
        hr = WcaGetRecordString(hRec, wqApplication, &pwzData);
        ExitOnFailure(hr, "Failed to get application identifier for Web");
        if (*pwzData)
        {
            hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp);
            ExitOnFailure(hr, "Failed to get application for Web");

            psw->fHasApplication = TRUE;
        }

        // get the SSL certificates
        hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList));
        ExitOnFailure(hr, "Failed to get SSL Certificates.");

        // get the custom headers
        if (*ppshhList)
        {
            hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList));
            ExitOnFailure(hr, "Failed to get Custom HTTP Headers");
        }

        // get the errors
        if (*ppsweList)
        {
            hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList));
            ExitOnFailure(hr, "Failed to get Custom Errors");
        }

        // get the log information for this web
        hr = WcaGetRecordString(hRec, wqLog, &pwzData);
        ExitOnFailure(hr, "Failed to get log identifier for Web");
        if (*pwzData)
        {
            hr = ScaGetWebLog(piMetabase, pwzData, hWebLogQuery, &psw->swl);
            ExitOnFailure(hr, "Failed to get Log for Web.");

            psw->fHasLog = TRUE;
        }

        *ppswList = AddWebToList(*ppswList, psw);
        psw = NULL; // set the web NULL so it doesn't accidentally get freed below
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }

LExit:
    // if anything was left over after an error clean it all up
    WcaFinishUnwrapQuery(hQueryWebSite);
    WcaFinishUnwrapQuery(hQueryWebAddress);

    if (psw)
    {
        ScaWebsFreeList(psw);
    }

    ReleaseStr(pwzData);

    return hr;
}
Example #7
0
/*
  Checks SERVICENAME, PORT and BUFFERSIZE parameters 
*/
extern "C" UINT  __stdcall CheckDatabaseProperties (MSIHANDLE hInstall) 
{
  wchar_t ServiceName[MAX_PATH]={0};
  wchar_t SkipNetworking[MAX_PATH]={0};
  wchar_t QuickConfig[MAX_PATH]={0};
  wchar_t Password[MAX_PATH]={0};
  wchar_t EscapedPassword[2*MAX_PATH+2];
  wchar_t Port[6];
  wchar_t BufferPoolSize[16];
  DWORD PortLen=6;
  bool haveInvalidPort=false;
  const wchar_t *ErrorMsg=0;
  HRESULT hr= S_OK;
  UINT er= ERROR_SUCCESS;


  hr = WcaInitialize(hInstall, __FUNCTION__);
  ExitOnFailure(hr, "Failed to initialize");
  WcaLog(LOGMSG_STANDARD, "Initialized.");

  DWORD ServiceNameLen = MAX_PATH;
  MsiGetPropertyW (hInstall, L"SERVICENAME", ServiceName, &ServiceNameLen);
  if(ServiceName[0])
  {
    if(ServiceNameLen > 256)
    {
      ErrorMsg= L"Invalid service name. The maximum length is 256 characters.";
      goto LExit;
    }
    for(DWORD i=0; i< ServiceNameLen;i++)
    {
      if(ServiceName[i] == L'\\' || ServiceName[i] == L'/' 
        || ServiceName[i]=='\'' || ServiceName[i] ==L'"')
      {
        ErrorMsg = 
          L"Invalid service name. Forward slash and back slash are forbidden."
          L"Single and double quotes are also not permitted.";
        goto LExit;
      }
    }
    if(CheckServiceExists(ServiceName))
    {
      ErrorMsg=
        L"A service with the same name already exists. "
        L"Please use a different name.";
      goto LExit;
    }
  }

  DWORD PasswordLen= MAX_PATH;
  MsiGetPropertyW (hInstall, L"PASSWORD", Password, &PasswordLen);
  EscapeCommandLine(Password, EscapedPassword,
    sizeof(EscapedPassword)/sizeof(EscapedPassword[0]));
  MsiSetPropertyW(hInstall,L"ESCAPEDPASSWORD",EscapedPassword);

  DWORD SkipNetworkingLen= MAX_PATH;
  MsiGetPropertyW(hInstall, L"SKIPNETWORKING", SkipNetworking, 
    &SkipNetworkingLen);
  MsiGetPropertyW(hInstall, L"PORT", Port, &PortLen);
  
  if(SkipNetworking[0]==0 && Port[0] != 0)
  {
    /* Strip spaces */
    for(DWORD i=PortLen-1; i > 0; i--)
    {
      if(Port[i]== ' ')
        Port[i] = 0;
    }

    if(PortLen > 5 || PortLen <= 3)
      haveInvalidPort = true;
    else
    {
      for (DWORD i=0; i< PortLen && Port[i] != 0;i++)
      {
        if(Port[i] < '0' || Port[i] >'9')
        {
          haveInvalidPort=true;
          break;
        }
      }
    }
    if (haveInvalidPort)
    {
      ErrorMsg =
        L"Invalid port number. Please use a number between 1025 and 65535.";
      goto LExit;
    }

    short port = (short)_wtoi(Port);
    if (!IsPortFree(port))
    {
      ErrorMsg = 
        L"The TCP Port you selected is already in use. "
        L"Please choose a different port.";
      goto LExit;
    }
  }
  
  
  DWORD QuickConfigLen = MAX_PATH;
  MsiGetPropertyW (hInstall, L"STDCONFIG", QuickConfig, &QuickConfigLen);
  if(QuickConfig[0] !=0)
  {
     MEMORYSTATUSEX memstatus;
     memstatus.dwLength =sizeof(memstatus);
     wchar_t invalidValueMsg[256];

     if (!GlobalMemoryStatusEx(&memstatus))
     {
        WcaLog(LOGMSG_STANDARD, "Error %u from GlobalMemoryStatusEx", 
          GetLastError());
        er= ERROR_INSTALL_FAILURE;
        goto LExit;
     }
     DWORD BufferPoolSizeLen= 16;
     MsiGetPropertyW(hInstall, L"BUFFERPOOLSIZE", BufferPoolSize, &BufferPoolSizeLen);
     /* Strip spaces */
     for(DWORD i=BufferPoolSizeLen-1; i > 0; i--)
     {
      if(BufferPoolSize[i]== ' ')
        BufferPoolSize[i] = 0;
     }
     unsigned long long availableMemory=
       GetMaxBufferSize(memstatus.ullTotalPhys)/ONE_MB;
     swprintf_s(invalidValueMsg,
        L"Invalid buffer pool size. Please use a number between 1 and %llu",
         availableMemory);
     if(BufferPoolSizeLen == 0 || BufferPoolSizeLen > 15)
     {
       ErrorMsg= invalidValueMsg;
       goto LExit;
     }
     for (DWORD i=0; i < BufferPoolSizeLen && BufferPoolSize[BufferPoolSizeLen];
       i++)
     {
       if(BufferPoolSize[i]< '0' || BufferPoolSize[i] > '9')
       {
         ErrorMsg= invalidValueMsg;
         goto LExit;
       }
     }
     BufferPoolSize[BufferPoolSizeLen]=0;
     MsiSetPropertyW(hInstall, L"BUFFERPOOLSIZE", BufferPoolSize);
     long long sz = _wtoi64(BufferPoolSize);
     if(sz <= 0 || sz > (long long)availableMemory)
     {
       if(sz > 0)
       {
         swprintf_s(invalidValueMsg,
           L"Value for buffer pool size is too large."
           L"Only approximately %llu MB is available for allocation."
           L"Please use a number between 1 and %llu.",
          availableMemory, availableMemory);
       }
       ErrorMsg= invalidValueMsg;
       goto LExit;
     }
  }
LExit:
  MsiSetPropertyW (hInstall, L"WarningText", ErrorMsg);
  return WcaFinalize(er);
}
Example #8
0
static HRESULT RunElevated(
    __in HINSTANCE hInstance,
    __in LPCWSTR wzCommandLine,
    __in BURN_ENGINE_STATE* pEngineState
    )
{
    HRESULT hr = S_OK;
    HANDLE hLock = NULL;
    BOOL fDisabledAutomaticUpdates = FALSE;

    // If we were launched elevated implicitly, launch an unelevated copy of ourselves.
    if (BURN_ELEVATION_STATE_ELEVATED == pEngineState->elevationState)
    {
        Assert(!pEngineState->companionConnection.dwProcessId);
        Assert(!pEngineState->companionConnection.sczName);
        Assert(!pEngineState->companionConnection.sczSecret);

        hr = PipeCreateNameAndSecret(&pEngineState->companionConnection.sczName, &pEngineState->companionConnection.sczSecret);
        ExitOnFailure(hr, "Failed to create implicit elevated connection name and secret.");

        hr = PipeLaunchParentProcess(wzCommandLine, pEngineState->command.nCmdShow, pEngineState->companionConnection.sczName, pEngineState->companionConnection.sczSecret, pEngineState->fDisableUnelevate);
        ExitOnFailure(hr, "Failed to launch unelevated process.");
    }

    // connect to per-user process
    hr = PipeChildConnect(&pEngineState->companionConnection, TRUE);
    ExitOnFailure(hr, "Failed to connect to unelevated process.");

    // Set up the thread local storage to store the correct pipe to communicate logging.
    pEngineState->dwElevatedLoggingTlsId = ::TlsAlloc();
    if (TLS_OUT_OF_INDEXES == pEngineState->dwElevatedLoggingTlsId)
    {
        ExitWithLastError(hr, "Failed to allocate thread local storage for logging.");
    }

    if (!::TlsSetValue(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe))
    {
        ExitWithLastError(hr, "Failed to set elevated pipe into thread local storage for logging.");
    }

    // Create a top-level window to prevent shutting down the elevated process.
    hr = UiCreateMessageWindow(hInstance, pEngineState);
    ExitOnFailure(hr, "Failed to create the message window.");

    SrpInitialize(TRUE);

    // Override logging to write over the pipe.
    LogRedirect(RedirectLoggingOverPipe, pEngineState);

    // Pump messages from parent process.
    hr = ElevationChildPumpMessages(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe, pEngineState->companionConnection.hCachePipe, &pEngineState->containers, &pEngineState->packages, &pEngineState->payloads, &pEngineState->variables, &pEngineState->registration, &pEngineState->userExperience, &hLock, &fDisabledAutomaticUpdates, &pEngineState->userExperience.dwExitCode, &pEngineState->fRestart);
    LogRedirect(NULL, NULL); // reset logging so the next failure gets written to "log buffer" for the failure log.
    ExitOnFailure(hr, "Failed to pump messages from parent process.");

LExit:
    LogRedirect(NULL, NULL); // we're done talking to the child so always reset logging now.

    // If the message window is still around, close it.
    UiCloseMessageWindow(pEngineState);

    if (fDisabledAutomaticUpdates)
    {
        ElevationChildResumeAutomaticUpdates();
    }

    if (hLock)
    {
        ::ReleaseMutex(hLock);
        ::CloseHandle(hLock);
    }

    return hr;
}
Example #9
0
static HRESULT RunApplication(
    __in BURN_ENGINE_STATE* pEngineState,
    __out BOOL* pfReloadApp
    )
{
    HRESULT hr = S_OK;
    DWORD dwThreadId = 0;
    IBootstrapperEngine* pEngineForApplication = NULL;
    BOOL fStartupCalled = FALSE;
    BOOL fRet = FALSE;
    MSG msg = { };

    ::PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
    dwThreadId = ::GetCurrentThreadId();

    // Load the bootstrapper application.
    hr = EngineForApplicationCreate(pEngineState, dwThreadId, &pEngineForApplication);
    ExitOnFailure(hr, "Failed to create engine for UX.");

    hr = UserExperienceLoad(&pEngineState->userExperience, pEngineForApplication, &pEngineState->command);
    ExitOnFailure(hr, "Failed to load UX.");

    fStartupCalled = TRUE;
    hr = pEngineState->userExperience.pUserExperience->OnStartup();
    ExitOnFailure(hr, "Failed to start bootstrapper application.");

    // Enter the message pump.
    while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
    {
        if (-1 == fRet)
        {
            hr = E_UNEXPECTED;
            ExitOnRootFailure(hr, "Unexpected return value from message pump.");
        }
        else
        {
            ProcessMessage(pEngineState, &msg);
        }
    }

    // get exit code
    pEngineState->userExperience.dwExitCode = (DWORD)msg.wParam;

LExit:
    if (fStartupCalled)
    {
        int nResult = pEngineState->userExperience.pUserExperience->OnShutdown();
        if (IDRESTART == nResult)
        {
            LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RESTART, LoggingBoolToString(pEngineState->fRestart));
            pEngineState->fRestart = TRUE;
        }
        else if (IDRELOAD_BOOTSTRAPPER == nResult)
        {
            LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RELOAD);
            *pfReloadApp = TRUE;
        }
    }

    // unload UX
    UserExperienceUnload(&pEngineState->userExperience);

    ReleaseObject(pEngineForApplication);

    return hr;
}
Example #10
0
extern "C" HRESULT RegDefaultReadValue(
    __in CFGDB_STRUCT *pcdb,
    __in LEGACY_SYNC_PRODUCT_SESSION *pSyncProductSession,
    __in_z LPCWSTR wzNamespace,
    __in HKEY hkKey,
    __in_z LPCWSTR wzRegKey,
    __in_z LPCWSTR wzValueName,
    __in DWORD dwRegType
    )
{
    HRESULT hr = S_OK;
    BOOL fIgnore = FALSE;
    LPWSTR sczCfgValueName = NULL;

    hr = MapRegValueToCfgName(wzNamespace, wzRegKey, wzValueName, &sczCfgValueName);
    ExitOnFailure(hr, "Failed to format default legacy value name from namespace: %ls, key: %ls, valuename: %ls", wzNamespace, wzRegKey, wzValueName);

    hr = FilterCheckValue(&pSyncProductSession->product, sczCfgValueName, &fIgnore, NULL);
    ExitOnFailure(hr, "Failed to check if cfg value should be ignored: %ls", sczCfgValueName);

    if (fIgnore)
    {
        ExitFunction1(hr = S_OK);
    }

    hr = DictAddKey(pSyncProductSession->shDictValuesSeen, sczCfgValueName);
    ExitOnFailure(hr, "Failed to add to dictionary value: %ls", sczCfgValueName);

    switch (dwRegType)
    {
    case REG_BINARY:
        hr = RegDefaultReadValueBinary(pcdb, hkKey, wzValueName, sczCfgValueName);
        ExitOnFailure(hr, "Failed to handle binary value by default handler while reading from registry: %ls", wzValueName);
        break;

    case REG_SZ:
        hr = RegDefaultReadValueString(pcdb, hkKey, wzValueName, sczCfgValueName);
        ExitOnFailure(hr, "Failed to handle string value by default handler while reading from registry: %ls", wzValueName);
        break;

    case REG_DWORD:
        hr = RegDefaultReadValueDword(pcdb, hkKey, wzValueName, sczCfgValueName);
        ExitOnFailure(hr, "Failed to handle dword value by default handler while reading from registry: %ls", wzValueName);
        break;

    case REG_QWORD:
        hr = RegDefaultReadValueQword(pcdb, hkKey, wzValueName, sczCfgValueName);
        ExitOnFailure(hr, "Failed to handle qword value by default handler while reading from registry: %ls", wzValueName);
        break;

    default:
        // Ignore this value, it's unsupported
        ExitFunction1(hr = S_OK);
        break;
    }

LExit:
    ReleaseStr(sczCfgValueName);

    return hr;
}
Example #11
0
static HRESULT RunNormal(
    __in HINSTANCE hInstance,
    __in BURN_ENGINE_STATE* pEngineState
    )
{
    HRESULT hr = S_OK;
    HANDLE hPipesCreatedEvent = NULL;
    BOOL fContinueExecution = TRUE;
    BOOL fReloadApp = FALSE;

    // Initialize logging.
    hr = LoggingOpen(&pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->registration.sczDisplayName);
    ExitOnFailure(hr, "Failed to open log.");

    // Ensure the cache functions are initialized since we might use them soon.
    hr = CacheInitialize(&pEngineState->registration, &pEngineState->variables);
    ExitOnFailure(hr, "Failed to initialize internal cache functionality.");

    // When launched explicitly unelevated, create the pipes so the elevated process can connect.
    if (BURN_ELEVATION_STATE_UNELEVATED_EXPLICITLY == pEngineState->elevationState)
    {
        Assert(pEngineState->companionConnection.dwProcessId);
        Assert(pEngineState->companionConnection.sczName);
        Assert(pEngineState->companionConnection.sczSecret);
        Assert(!pEngineState->companionConnection.hProcess);
        Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe);
        Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hCachePipe);

        hr = PipeCreatePipes(&pEngineState->companionConnection, TRUE, &hPipesCreatedEvent);
        ExitOnFailure(hr, "Failed to create pipes to connect to elevated parent process.");

        hr = PipeWaitForChildConnect(&pEngineState->companionConnection);
        ExitOnFailure(hr, "Failed to connect to elevated parent process.");

        ReleaseHandle(hPipesCreatedEvent);
    }

    // Ensure we're on a supported operating system.
    hr = ConditionGlobalCheck(&pEngineState->variables, &pEngineState->condition, pEngineState->command.display, pEngineState->registration.sczDisplayName, &pEngineState->userExperience.dwExitCode, &fContinueExecution);
    ExitOnFailure(hr, "Failed to check global conditions");

    if (!fContinueExecution)
    {
        LogId(REPORT_STANDARD, MSG_FAILED_CONDITION_CHECK);

        // If the block told us to abort, abort!
        ExitFunction1(hr = S_OK);
    }

    if (pEngineState->userExperience.fSplashScreen && BOOTSTRAPPER_DISPLAY_NONE < pEngineState->command.display)
    {
        SplashScreenCreate(hInstance, NULL, &pEngineState->command.hwndSplashScreen);
    }

    // Create a top-level window to handle system messages.
    hr = UiCreateMessageWindow(hInstance, pEngineState);
    ExitOnFailure(hr, "Failed to create the message window.");

    // Query registration state.
    hr = CoreQueryRegistration(pEngineState);
    ExitOnFailure(hr, "Failed to query registration.");

    // Set some built-in variables before loading the BA.
    hr = PlanSetVariables(pEngineState->command.action, &pEngineState->variables);
    ExitOnFailure(hr, "Failed to set action variables.");

    hr = RegistrationSetVariables(&pEngineState->registration, &pEngineState->variables);
    ExitOnFailure(hr, "Failed to set registration variables.");

    // If a layout directory was specified on the command-line, set it as a well-known variable.
    if (pEngineState->command.wzLayoutDirectory && *pEngineState->command.wzLayoutDirectory)
    {
        hr = VariableSetString(&pEngineState->variables, BURN_BUNDLE_LAYOUT_DIRECTORY, pEngineState->command.wzLayoutDirectory, FALSE);
        ExitOnFailure(hr, "Failed to set layout directory variable to value provided from command-line.");
    }

    do
    {
        fReloadApp = FALSE;

        hr = RunApplication(pEngineState, &fReloadApp);
        ExitOnFailure(hr, "Failed while running ");
    } while (fReloadApp);

LExit:
    // If the message window is still around, close it.
    UiCloseMessageWindow(pEngineState);

    VariablesDump(&pEngineState->variables);

    // end per-machine process if running
    if (INVALID_HANDLE_VALUE != pEngineState->companionConnection.hPipe)
    {
        PipeTerminateChildProcess(&pEngineState->companionConnection, pEngineState->userExperience.dwExitCode, (BURN_ELEVATION_STATE_UNELEVATED_EXPLICITLY == pEngineState->elevationState) ? pEngineState->fRestart : FALSE);
    }

    // If the splash screen is still around, close it.
    if (::IsWindow(pEngineState->command.hwndSplashScreen))
    {
        ::PostMessageW(pEngineState->command.hwndSplashScreen, WM_CLOSE, 0, 0);
    }

    ReleaseHandle(hPipesCreatedEvent);

    return hr;
}
Example #12
0
extern "C" HRESULT RegDefaultWriteValue(
    __in LEGACY_PRODUCT *pProduct,
    __in_z LPCWSTR wzName,
    __in const CONFIG_VALUE *pcvValue,
    __out BOOL *pfHandled
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczValue = NULL;
    LPWSTR sczRegKey = NULL;
    LPWSTR sczRegValueName = NULL;
    BYTE *pbBuffer = NULL;
    SIZE_T cbBuffer = 0;
    BOOL fReleaseBuffer = FALSE;
    DWORD dwRoot = DWORD_MAX;
    HKEY hk = NULL;

    hr = MapCfgNameToRegValue(pProduct, wzName, &dwRoot, &sczRegKey, &sczRegValueName);
    if (E_INVALIDARG == hr)
    {
        *pfHandled = FALSE;
        // Not a regkey, so just ignore
        ExitFunction1(hr = S_OK);
    }
    ExitOnFailure(hr, "Failed to convert value name to registry information");
    *pfHandled = TRUE;

    hr = RegOpen(ManifestConvertToRootKey(dwRoot), sczRegKey, KEY_SET_VALUE, &hk);
    if (E_FILENOTFOUND == hr)
    {
        hr = S_OK;

        // The key doesn't exist, so no need to proceed with deleting the value
        if (VALUE_DELETED == pcvValue->cvType)
        {
            ExitFunction1(hr = S_OK);
        }
        hr = RegCreate(ManifestConvertToRootKey(dwRoot), sczRegKey, KEY_SET_VALUE, &hk);
        ExitOnFailure(hr, "Failed to create regkey: %ls", sczRegKey);
    }
    ExitOnFailure(hr, "Failed to open regkey: %ls", sczRegKey);

    switch (pcvValue->cvType)
    {
    case VALUE_DELETED:
        hr = RegWriteString(hk, sczRegValueName, NULL);
        ExitOnFailure(hr, "Failed to delete existing value");
        break;

    case VALUE_BLOB:
        switch (pcvValue->blob.cbType)
        {
        case CFG_BLOB_POINTER:
            pbBuffer = const_cast<BYTE *>(pcvValue->blob.pointer.pbValue);
            cbBuffer = pcvValue->blob.cbValue;
            break;
        case CFG_BLOB_DB_STREAM:
            fReleaseBuffer = TRUE;
            hr = StreamRead(pcvValue->blob.dbstream.pcdb, pcvValue->blob.dbstream.dwContentID, NULL, &pbBuffer, &cbBuffer);
            ExitOnFailure(hr, "Failed to read stream from database while writing binary to the registry");
            break;
        default:
            hr = E_INVALIDARG;
            ExitOnFailure(hr, "Invalid blob type encountered");
            break;
        }
        hr = RegWriteBinary(hk, sczRegValueName, pbBuffer, cbBuffer);
        ExitOnFailure(hr, "Failed to write binary value to registry");
        break;

    case VALUE_STRING:
        hr = RegWriteString(hk, sczRegValueName, pcvValue->string.sczValue);
        ExitOnFailure(hr, "Failed to write string to registry");
        break;

    case VALUE_DWORD:
        hr = RegWriteNumber(hk, sczRegValueName, pcvValue->dword.dwValue);
        ExitOnFailure(hr, "Failed to write dword to registry");
        break;

    case VALUE_QWORD:
        hr = RegWriteQword(hk, sczRegValueName, pcvValue->qword.qwValue);
        ExitOnFailure(hr, "Failed to write qword to registry");
        break;

    default:
        ExitFunction1(hr = E_INVALIDARG);
    }

LExit:
    ReleaseRegKey(hk);
    ReleaseStr(sczValue);
    ReleaseStr(sczRegKey);
    ReleaseStr(sczRegValueName);
    if (fReleaseBuffer)
    {
        ReleaseMem(pbBuffer);
    }

    return hr;
}
Example #13
0
int WINAPI wWinMain(
    __in HINSTANCE hInstance,
    __in_opt HINSTANCE /* hPrevInstance */,
    __in_z_opt LPWSTR lpCmdLine,
    __in int /*nCmdShow*/
    )
{
    ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);

    HRESULT hr = S_OK;
    BOOL fComInitialized = FALSE;
    LPWSTR sczThemeFile = NULL;
    ATOM atom = 0;
    HWND hWnd = NULL;

    HANDLE hDisplayThread = NULL;
    HANDLE hLoadThread = NULL;

    BOOL fRet = FALSE;
    MSG msg = { };

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

    hr = ProcessCommandLine(lpCmdLine, &sczThemeFile);
    ExitOnFailure(hr, "Failed to process command line.");

    hr = CreateTheme(hInstance, &vpTheme);
    ExitOnFailure(hr, "Failed to create theme.");

    hr = CreateMainWindowClass(hInstance, vpTheme, &atom);
    ExitOnFailure(hr, "Failed to create main window.");

    hWnd = ::CreateWindowExW(0, reinterpret_cast<LPCWSTR>(atom), vpTheme->sczCaption, vpTheme->dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, vpTheme->nWidth, vpTheme->nHeight, HWND_DESKTOP, NULL, hInstance, NULL);
    ExitOnNullWithLastError(hWnd, hr, "Failed to create window.");

    if (!sczThemeFile)
    {
        // Prompt for a path to the theme file.
        OPENFILENAMEW ofn = { };
        WCHAR wzFile[MAX_PATH] = { };

        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = hWnd;
        ofn.lpstrFile = wzFile;
        ofn.nMaxFile = countof(wzFile);
        ofn.lpstrFilter = L"Theme Files\0*.thm\0XML Files\0*.xml\0All Files\0*.*\0";
        ofn.nFilterIndex = 1;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
        ofn.lpstrTitle = vpTheme->sczCaption;

        if (::GetOpenFileNameW(&ofn))
        {
            hr = StrAllocString(&sczThemeFile, wzFile, 0);
            ExitOnFailure(hr, "Failed to copy opened file to theme file.");
        }
        else
        {
            ::MessageBoxW(hWnd, L"Must specify a path to theme file.", vpTheme->sczCaption, MB_OK | MB_ICONERROR);
            ExitFunction1(hr = E_INVALIDARG);
        }
    }

    hr = DisplayStart(hInstance, hWnd, &hDisplayThread, &vdwDisplayThreadId);
    ExitOnFailure(hr, "Failed to start display.");

    hr = LoadStart(sczThemeFile, hWnd, &hLoadThread);
    ExitOnFailure(hr, "Failed to start load.");

    // message pump
    while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
    {
        if (-1 == fRet)
        {
            hr = E_UNEXPECTED;
            ExitOnFailure(hr, "Unexpected return value from message pump.");
        }
        else if (!ThemeHandleKeyboardMessage(vpTheme, msg.hwnd, &msg))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessageW(&msg);
        }
    }

LExit:
    if (::IsWindow(hWnd))
    {
        ::DestroyWindow(hWnd);
    }

    if (hDisplayThread)
    {
        ::PostThreadMessageW(vdwDisplayThreadId, WM_QUIT, 0, 0);
        ::WaitForSingleObject(hDisplayThread, 10000);
        ::CloseHandle(hDisplayThread);
    }

    // TODO: come up with a good way to kill the load thread, probably need to switch
    // the ReadDirectoryW() to overlapped mode.
    ReleaseHandle(hLoadThread);

    if (atom && !::UnregisterClassW(reinterpret_cast<LPCWSTR>(atom), hInstance))
    {
        DWORD er = ::GetLastError();
        er = er;
    }

    ThemeFree(vpTheme);
    ThemeUninitialize();

    // uninitialize COM
    if (fComInitialized)
    {
        ::CoUninitialize();
    }

    ReleaseStr(sczThemeFile);
    return hr;
}
Example #14
0
extern "C" HRESULT MsuEngineExecutePackage(
    __in BURN_EXECUTE_ACTION* pExecuteAction,
    __in BOOL fRollback,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out BOOTSTRAPPER_APPLY_RESTART* pRestart
    )
{
    HRESULT hr = S_OK;
    int nResult = IDNOACTION;
    LPWSTR sczCachedDirectory = NULL;
    LPWSTR sczMsuPath = NULL;
    LPWSTR sczSystemPath = NULL;
    LPWSTR sczWusaPath = NULL;
    LPWSTR sczCommand = NULL;
    SC_HANDLE schWu = NULL;
    BOOL fWuWasDisabled = FALSE;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    GENERIC_EXECUTE_MESSAGE message = { };
    DWORD dwExitCode = 0;
    BOOL fDoDependency = FALSE;

    // get wusa.exe path
    hr = PathGetKnownFolder(CSIDL_SYSTEM, &sczSystemPath);
    ExitOnFailure(hr, "Failed to find System32 directory.");

    hr = PathConcat(sczSystemPath, L"wusa.exe", &sczWusaPath);
    ExitOnFailure(hr, "Failed to allocate WUSA.exe path.");

    // build command
    switch (pExecuteAction->msuPackage.action)
    {
    case BOOTSTRAPPER_ACTION_STATE_INSTALL:
        // get cached executable path
        hr = CacheGetCompletedPath(TRUE, pExecuteAction->msuPackage.pPackage->sczCacheId, &sczCachedDirectory);
        ExitOnFailure1(hr, "Failed to get cached path for package: %ls", pExecuteAction->msuPackage.pPackage->sczId);

        hr = PathConcat(sczCachedDirectory, pExecuteAction->msuPackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczMsuPath);
        ExitOnFailure(hr, "Failed to build executable path.");

        // format command
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\" \"%ls\" /quiet /norestart", sczWusaPath, sczMsuPath);
        ExitOnFailure(hr, "Failed to format MSU install command.");
        break;

    case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
        // format command
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pExecuteAction->msuPackage.pPackage->Msu.sczKB);
        ExitOnFailure(hr, "Failed to format MSU uninstall command.");
        break;

    default:
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Failed to get action arguments for MSU package.");
    }

    if (pExecuteAction->msuPackage.sczLogPath && *pExecuteAction->msuPackage.sczLogPath)
    {
        hr = StrAllocConcat(&sczCommand, L" /log:", 0);
        ExitOnFailure(hr, "Failed to append log switch to MSU command-line.");

        hr = StrAllocConcat(&sczCommand, pExecuteAction->msuPackage.sczLogPath, 0);
        ExitOnFailure(hr, "Failed to append log path to MSU command-line.");
    }

    LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->msuPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msuPackage.action), sczMsuPath ? sczMsuPath : pExecuteAction->msuPackage.pPackage->Msu.sczKB, sczCommand);

    hr = EnsureWUServiceEnabled(&schWu, &fWuWasDisabled);
    ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package.");

    // create process
    si.cb = sizeof(si);
    if (!::CreateProcessW(sczWusaPath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
    {
        ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", sczWusaPath);
    }

    do
    {
        message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
        message.dwAllowedResults = MB_OKCANCEL;
        message.progress.dwPercentage = 50;
        nResult = pfnGenericMessageHandler(&message, pvContext);
        hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
        ExitOnRootFailure(hr, "Bootstrapper application aborted during MSU progress.");

        // wait for process to terminate
        hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode);
        if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
        {
            ExitOnFailure1(hr, "Failed to wait for executable to complete: %ls", sczWusaPath);
        }
    } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);

    // get process exit code
    if (!::GetExitCodeProcess(pi.hProcess, &dwExitCode))
    {
        ExitWithLastError(hr, "Failed to get process exit code.");
    }

    // We'll normalize the restart required error code from wusa.exe just in case. Most likely
    // that on reboot we'll actually get WU_S_REBOOT_REQUIRED.
    if (HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) == static_cast<HRESULT>(dwExitCode))
    {
        dwExitCode = ERROR_SUCCESS_REBOOT_REQUIRED;
    }

    // handle exit code
    switch (dwExitCode)
    {
    case S_OK: __fallthrough;
    case WU_S_ALREADY_INSTALLED:
        fDoDependency = TRUE;
        __fallthrough;
    case S_FALSE: __fallthrough;
    case WU_E_NOT_APPLICABLE:
        *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
        hr = S_OK;
        break;

    case ERROR_SUCCESS_REBOOT_REQUIRED: __fallthrough;
    case WU_S_REBOOT_REQUIRED:
        fDoDependency = TRUE;
        *pRestart = BOOTSTRAPPER_APPLY_RESTART_REQUIRED;
        hr = S_OK;
        break;

    default:
        hr = E_UNEXPECTED;
        break;
    }

    if (fDoDependency)
    {
        if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->msuPackage.action)
        {
            hr = DependencyRegisterPackage(pExecuteAction->msuPackage.pPackage);
            ExitOnFailure(hr, "Failed to register the package dependency providers.");
        }
        else if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->msuPackage.action)
        {
            hr = DependencyUnregisterPackage(pExecuteAction->msuPackage.pPackage);
            ExitOnFailure(hr, "Failed to unregister the package dependency providers.");
        }
    }

LExit:
    ReleaseStr(sczCachedDirectory);
    ReleaseStr(sczMsuPath);
    ReleaseStr(sczSystemPath);
    ReleaseStr(sczWusaPath);
    ReleaseStr(sczCommand);

    ReleaseHandle(pi.hProcess);
    ReleaseHandle(pi.hThread);

    if (fWuWasDisabled)
    {
        SetServiceStartType(schWu, SERVICE_DISABLED);
    }

    return hr;
}
Example #15
0
//
// PlanAdd - adds the calculated execute and rollback actions for the package.
//
extern "C" HRESULT ExeEnginePlanAddPackage(
    __in_opt DWORD *pdwInsertSequence,
    __in BURN_PACKAGE* pPackage,
    __in BURN_PLAN* pPlan,
    __in BURN_LOGGING* pLog,
    __in BURN_VARIABLES* pVariables,
    __in_opt HANDLE hCacheEvent,
    __in BOOL fPlanPackageCacheRollback
    )
{
    HRESULT hr = S_OK;
    BURN_EXECUTE_ACTION* pAction = NULL;

    // add wait for cache
    if (hCacheEvent)
    {
        hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback);
        ExitOnFailure(hr, "Failed to plan package cache syncpoint");
    }

    hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
    ExitOnFailure(hr, "Failed to plan package dependency actions.");

    // add execute action
    if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
    {
        if (NULL != pdwInsertSequence)
        {
            hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction);
            ExitOnFailure(hr, "Failed to insert execute action.");
        }
        else
        {
            hr = PlanAppendExecuteAction(pPlan, &pAction);
            ExitOnFailure(hr, "Failed to append execute action.");
        }

        pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
        pAction->exePackage.pPackage = pPackage;
        pAction->exePackage.fFireAndForget = (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action);
        pAction->exePackage.action = pPackage->execute;

        if (pPackage->Exe.sczIgnoreDependencies)
        {
            hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
            ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
        }

        LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
    }

    // add rollback action
    if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
    {
        hr = PlanAppendRollbackAction(pPlan, &pAction);
        ExitOnFailure(hr, "Failed to append rollback action.");

        pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
        pAction->exePackage.pPackage = pPackage;
        pAction->exePackage.action = pPackage->rollback;

        if (pPackage->Exe.sczIgnoreDependencies)
        {
            hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
            ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
        }

        LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
    }

LExit:
    return hr;
}
Example #16
0
extern "C" HRESULT EngineRun(
    __in HINSTANCE hInstance,
    __in_z_opt LPCWSTR wzCommandLine,
    __in int nCmdShow,
    __out DWORD* pdwExitCode
    )
{
    HRESULT hr = S_OK;
    BOOL fComInitialized = FALSE;
    BOOL fLogInitialized = FALSE;
    BOOL fRegInitialized = FALSE;
    BOOL fWiuInitialized = FALSE;
    BOOL fXmlInitialized = FALSE;
    OSVERSIONINFOEXW ovix = { };
    LPWSTR sczExePath = NULL;
    BOOL fRunNormal = FALSE;
    BOOL fRestart = FALSE;

    BURN_ENGINE_STATE engineState = { };

    hr = InitializeEngineState(&engineState);
    ExitOnFailure(hr, "Failed to initialize engine state.");

    engineState.command.nCmdShow = nCmdShow;

    // Ensure that log contains approriate level of information
#ifdef _DEBUG
    LogSetLevel(REPORT_DEBUG, FALSE);
#else
    LogSetLevel(REPORT_VERBOSE, FALSE); // FALSE means don't write an additional text line to the log saying the level changed
#endif

    // initialize platform layer
    PlatformInitialize();

    // initialize COM
    hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ExitOnFailure(hr, "Failed to initialize COM.");
    fComInitialized = TRUE;

    // Initialize dutil.
    LogInitialize(::GetModuleHandleW(NULL));
    fLogInitialized = TRUE;

    hr = RegInitialize();
    ExitOnFailure(hr, "Failed to initialize Regutil.");
    fRegInitialized = TRUE;

    hr = WiuInitialize();
    ExitOnFailure(hr, "Failed to initialize Wiutil.");
    fWiuInitialized = TRUE;

    hr = XmlInitialize();
    ExitOnFailure(hr, "Failed to initialize XML util.");
    fXmlInitialized = TRUE;

    ovix.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
    if (!::GetVersionExW((LPOSVERSIONINFOW)&ovix))
    {
        ExitWithLastError(hr, "Failed to get OS info.");
    }

    PathForCurrentProcess(&sczExePath, NULL); // Ignore failure.
    LogId(REPORT_STANDARD, MSG_BURN_INFO, szVerMajorMinorBuild, ovix.dwMajorVersion, ovix.dwMinorVersion, ovix.dwBuildNumber, ovix.wServicePackMajor, sczExePath, wzCommandLine ? wzCommandLine : L"");
    ReleaseNullStr(sczExePath);

    // initialize core
    hr = CoreInitialize(wzCommandLine, &engineState);
    ExitOnFailure(hr, "Failed to initialize core.");

    // select run mode
    switch (engineState.mode)
    {
    case BURN_MODE_NORMAL:
        fRunNormal = TRUE;

        hr = RunNormal(hInstance, &engineState);
        ExitOnFailure(hr, "Failed to run per-user mode.");
        break;

    case BURN_MODE_ELEVATED:
        hr = RunElevated(hInstance, wzCommandLine, &engineState);
        ExitOnFailure(hr, "Failed to run per-machine mode.");
        break;

    case BURN_MODE_EMBEDDED:
        fRunNormal = TRUE;

        hr = RunEmbedded(hInstance, &engineState);
        ExitOnFailure(hr, "Failed to run embedded mode.");
        break;

    case BURN_MODE_RUNONCE:
        hr = RunRunOnce(wzCommandLine, nCmdShow);
        ExitOnFailure(hr, "Failed to run RunOnce mode.");
        break;

    default:
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Invalid run mode.");
    }

    // set exit code and remember if we are supposed to restart.
    *pdwExitCode = engineState.userExperience.dwExitCode;
    fRestart = engineState.fRestart;

LExit:
    ReleaseStr(sczExePath);

    // If anything went wrong but the log was never open, try to open a "failure" log
    // and that will dump anything captured in the log memory buffer to the log.
    if (FAILED(hr) && BURN_LOGGING_STATE_CLOSED == engineState.log.state)
    {
        LogOpen(NULL, L"Setup", L"_Failed", L"txt", FALSE, FALSE, NULL);
    }

    UserExperienceRemove(&engineState.userExperience);

    CacheRemoveWorkingFolder(engineState.registration.sczId);

    // If this is a related bundle (but not an update) suppress restart and return the standard restart error code.
    if (fRestart && BOOTSTRAPPER_RELATION_NONE != engineState.command.relationType && BOOTSTRAPPER_RELATION_UPDATE != engineState.command.relationType)
    {
        LogId(REPORT_STANDARD, MSG_RESTART_ABORTED, LoggingRelationTypeToString(engineState.command.relationType));

        fRestart = FALSE;
        hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
    }

    UninitializeEngineState(&engineState);

    if (fXmlInitialized)
    {
        XmlUninitialize();
    }

    if (fWiuInitialized)
    {
        WiuUninitialize();
    }

    if (fRegInitialized)
    {
        RegUninitialize();
    }

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

    if (fRunNormal)
    {
        LogId(REPORT_STANDARD, MSG_EXITING, FAILED(hr) ? (int)hr : *pdwExitCode, LoggingBoolToString(fRestart));

        if (fRestart)
        {
            LogId(REPORT_STANDARD, MSG_RESTARTING);
        }
    }

    if (fLogInitialized)
    {
        LogClose(FALSE);
    }

    if (fRestart)
    {
        Restart();
    }

    if (fLogInitialized)
    {
        LogUninitialize(FALSE);
    }

    return hr;
}
Example #17
0
extern "C" HRESULT ExeEngineExecutePackage(
    __in BURN_EXECUTE_ACTION* pExecuteAction,
    __in BURN_VARIABLES* pVariables,
    __in BOOL fRollback,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out BOOTSTRAPPER_APPLY_RESTART* pRestart
    )
{
    HRESULT hr = S_OK;
    WCHAR wzCurrentDirectory[MAX_PATH] = { };
    BOOL fChangedCurrentDirectory = FALSE;
    int nResult = IDNOACTION;
    LPCWSTR wzArguments = NULL;
    LPWSTR sczArgumentsFormatted = NULL;
    LPWSTR sczArgumentsObfuscated = NULL;
    LPWSTR sczCachedDirectory = NULL;
    LPWSTR sczExecutablePath = NULL;
    LPWSTR sczCommand = NULL;
    LPWSTR sczCommandObfuscated = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    DWORD dwExitCode = 0;
    GENERIC_EXECUTE_MESSAGE message = { };

    // get cached executable path
    hr = CacheGetCompletedPath(pExecuteAction->exePackage.pPackage->fPerMachine, pExecuteAction->exePackage.pPackage->sczCacheId, &sczCachedDirectory);
    ExitOnFailure1(hr, "Failed to get cached path for package: %ls", pExecuteAction->exePackage.pPackage->sczId);

    hr = PathConcat(sczCachedDirectory, pExecuteAction->exePackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczExecutablePath);
    ExitOnFailure(hr, "Failed to build executable path.");

    // pick arguments
    switch (pExecuteAction->exePackage.action)
    {
    case BOOTSTRAPPER_ACTION_STATE_INSTALL:
        wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczInstallArguments;
        break;

    case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
        wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczUninstallArguments;
        break;

    case BOOTSTRAPPER_ACTION_STATE_REPAIR:
        wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczRepairArguments;
        break;

    default:
        hr = E_UNEXPECTED;
        ExitOnFailure(hr, "Failed to get action arguments for executable package.");
    }

    // build command
    if (wzArguments && *wzArguments)
    {
        hr = VariableFormatString(pVariables, wzArguments, &sczArgumentsFormatted, NULL);
        ExitOnFailure(hr, "Failed to format argument string.");

        hr = StrAllocFormatted(&sczCommand, L"\"%ls\" %s", sczExecutablePath, sczArgumentsFormatted);
        ExitOnFailure(hr, "Failed to create executable command.");

        hr = VariableFormatStringObfuscated(pVariables, wzArguments, &sczArgumentsObfuscated, NULL);
        ExitOnFailure(hr, "Failed to format obfuscated argument string.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", sczExecutablePath, sczArgumentsObfuscated);
    }
    else
    {
        hr = StrAllocFormatted(&sczCommand, L"\"%ls\"", sczExecutablePath);
        ExitOnFailure(hr, "Failed to create executable command.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\"", sczExecutablePath);
    }
    ExitOnFailure(hr, "Failed to create obfuscated executable command.");

    // Add the list of dependencies to ignore, if any, to the burn command line.
    if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol)
    {
        hr = StrAllocFormatted(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
        ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");

        hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
        ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the obfuscated command line.");
    }

    // Log before we add the secret pipe name and client token for embedded processes.
    LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->exePackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);

    if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol)
    {
        hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
        ExitOnFailure1(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
    }
    else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pExecuteAction->exePackage.pPackage->Exe.protocol)
    {
        hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
        ExitOnFailure1(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
    }
    else // create and wait for the executable process while sending fake progress to allow cancel.
    {
        // Make the cache location of the executable the current directory to help those executables
        // that expect stuff to be relative to them.
        if (::GetCurrentDirectoryW(countof(wzCurrentDirectory), wzCurrentDirectory))
        {
            fChangedCurrentDirectory = ::SetCurrentDirectoryW(sczCachedDirectory);
        }

        si.cb = sizeof(si); // TODO: hookup the stdin/stdout/stderr pipes for logging purposes?
        if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
        {
            ExitWithLastError1(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
        }

        if (pExecuteAction->exePackage.fFireAndForget)
        {
            ::WaitForInputIdle(pi.hProcess, 5000);
            ExitFunction();
        }

        do
        {
            message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
            message.dwAllowedResults = MB_OKCANCEL;
            message.progress.dwPercentage = 50;
            nResult = pfnGenericMessageHandler(&message, pvContext);
            hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
            ExitOnRootFailure(hr, "Bootstrapper application aborted during EXE progress.");

            hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode);
            if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
            {
                ExitOnFailure1(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath);
            }
        } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
    }

    hr = HandleExitCode(pExecuteAction->exePackage.pPackage, dwExitCode, pRestart);
    ExitOnRootFailure1(hr, "Process returned error: 0x%x", dwExitCode);

LExit:
    if (fChangedCurrentDirectory)
    {
        ::SetCurrentDirectoryW(wzCurrentDirectory);
    }

    ReleaseStr(sczArgumentsFormatted);
    ReleaseStr(sczArgumentsObfuscated);
    ReleaseStr(sczCachedDirectory);
    ReleaseStr(sczExecutablePath);
    ReleaseStr(sczCommand);
    ReleaseStr(sczCommandObfuscated);

    ReleaseHandle(pi.hThread);
    ReleaseHandle(pi.hProcess);

    return hr;
}
Example #18
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;
}
Example #19
0
/*
  Checks if database directory or service are modified by user
  For example, service may point to different mysqld.exe that it was originally
  installed, or some different service might use this database directory. This 
  would normally mean user has done an upgrade of the database and in this case 
  uninstall should neither delete service nor database directory.

  If this function find that service is modified by user (mysqld.exe used by 
  service does not point to the installation bin directory), MSI public variable
  SERVICENAME is removed, if DATADIR is used by some other service, variables 
  DATADIR and CLEANUPDATA are removed.

  The effect of variable removal is that service does not get uninstalled and
  datadir is not touched by uninstallation.

  Note that this function is running without elevation and does not use anything
  that would require special privileges.

*/
extern "C" UINT CheckDBInUse(MSIHANDLE hInstall)
{
  static BYTE buf[256*1024]; /* largest possible buffer for EnumServices */
  static char config_buffer[8*1024]; /*largest buffer for QueryServiceConfig */
  HRESULT hr = S_OK;
  UINT er = ERROR_SUCCESS;
  wchar_t *servicename= NULL;
  wchar_t *datadir= NULL;
  wchar_t *bindir=NULL;

  SC_HANDLE scm    = NULL; 
  ULONG  bufsize   = sizeof(buf); 
  ULONG  bufneed   = 0x00; 
  ULONG  num_services = 0x00; 
  LPENUM_SERVICE_STATUS_PROCESS info = NULL;  

  hr = WcaInitialize(hInstall, __FUNCTION__);
  ExitOnFailure(hr, "Failed to initialize");
  WcaLog(LOGMSG_STANDARD, "Initialized.");

  WcaGetProperty(L"SERVICENAME", &servicename);
  WcaGetProperty(L"DATADIR", &datadir);
  WcaGetFormattedString(L"[INSTALLDIR]bin\\", &bindir);
  WcaLog(LOGMSG_STANDARD,"SERVICENAME=%S, DATADIR=%S, bindir=%S",
    servicename, datadir, bindir);

  scm = OpenSCManager(NULL, NULL, 
    SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);  
  if (scm == NULL) 
  { 
    ExitOnFailure(E_FAIL, "OpenSCManager failed");
  }

  BOOL ok= EnumServicesStatusExW(  scm,
    SC_ENUM_PROCESS_INFO, 
    SERVICE_WIN32,
    SERVICE_STATE_ALL,  
    buf, 
    bufsize,  
    &bufneed,  
    &num_services,  
    NULL, 
    NULL);
  if(!ok) 
  {
    WcaLog(LOGMSG_STANDARD, "last error %d", GetLastError());
    ExitOnFailure(E_FAIL, "EnumServicesStatusExW failed");
  }
  info = (LPENUM_SERVICE_STATUS_PROCESS)buf; 
  for (ULONG i=0; i < num_services; i++)
  {
    SC_HANDLE service= OpenServiceW(scm, info[i].lpServiceName, 
      SERVICE_QUERY_CONFIG);
    if (!service)
      continue;
    WcaLog(LOGMSG_VERBOSE, "Checking Service %S", info[i].lpServiceName);
    QUERY_SERVICE_CONFIGW *config= 
      (QUERY_SERVICE_CONFIGW *)(void *)config_buffer;
    DWORD needed;
    BOOL ok= QueryServiceConfigW(service, config,sizeof(config_buffer), 
      &needed);
    CloseServiceHandle(service);
    if (ok)
    {
       CheckServiceConfig(servicename, datadir, bindir, info[i].lpServiceName, 
         config);
    }
  }

LExit:
  if(scm)
    CloseServiceHandle(scm);

  ReleaseStr(servicename);
  ReleaseStr(datadir);
  ReleaseStr(bindir);
  return WcaFinalize(er); 
}
Example #20
0
static HRESULT InstallCertificatePackage(
    __in HCERTSTORE hStore,
    __in BOOL fUserCertificateStore,
    __in LPCWSTR wzName,
    __in_opt BYTE* rgbData,
    __in DWORD cbData,
    __in_opt LPCWSTR wzPFXPassword
    )
{
    HRESULT hr = S_OK;

    HCERTSTORE hPfxCertStore = NULL;
    PCCERT_CONTEXT pCertContext = NULL;
    CERT_BLOB blob = { 0 };
    DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;
    DWORD dwEncodingType;
    DWORD dwContentType;
    DWORD dwFormatType;
    LPWSTR pwzUniqueName = NULL;
    int iUniqueId = 0;

    // Figure out what type of blob (certificate or PFX) we're dealing with here.
    blob.pbData = rgbData;
    blob.cbData = cbData;

    if (!::CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, &dwEncodingType, &dwContentType, &dwFormatType, NULL, NULL, (LPCVOID*)&pCertContext))
    {
        ExitWithLastError1(hr, "Failed to parse the certificate blob: %ls", wzName);
    }

    hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
    ExitOnFailure(hr, "Failed to format unique name");

    if (!pCertContext)
    {
        // If we have a PFX blob, get the first certificate out of the PFX and use that instead of the PFX.
        if (dwContentType & CERT_QUERY_CONTENT_PFX)
        {
            ExitOnNull(wzPFXPassword, hr, E_INVALIDARG, "Failed to import PFX blob because no password was provided");

            // If we fail and our password is blank, also try passing in NULL for the password (according to the docs)
            hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, wzPFXPassword, dwKeyset);
            if (NULL == hPfxCertStore && !*wzPFXPassword)
            {
                hPfxCertStore = ::PFXImportCertStore((CRYPT_DATA_BLOB*)&blob, NULL, dwKeyset);
            }
            ExitOnNullWithLastError(hPfxCertStore, hr, "Failed to open PFX file.");

            // Install all certificates in the PFX
            for (pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext);
                 pCertContext;
                 pCertContext = ::CertEnumCertificatesInStore(hPfxCertStore, pCertContext))
            {
                WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", pwzUniqueName);
                hr = CertInstallSingleCertificate(hStore, pCertContext, pwzUniqueName);
                MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");

                hr = StrAllocFormatted(&pwzUniqueName, L"%s_wixCert_%d", wzName, ++iUniqueId);
                ExitOnFailure(hr, "Failed to format unique name");
            }
        }
        else
        {
            hr = E_UNEXPECTED;
            ExitOnFailure(hr, "Unexpected certificate type processed.");
        }
    }
    else
    {
        WcaLog(LOGMSG_STANDARD, "Adding certificate: %ls", pwzUniqueName);
        hr = CertInstallSingleCertificate(hStore, pCertContext, pwzUniqueName);
        MessageExitOnFailure(hr, msierrCERTFailedAdd, "Failed to add certificate to the store.");
    }

    hr = WcaProgressMessage(COST_CERT_ADD, FALSE);
    ExitOnFailure(hr, "Failed to send install progress message.");

LExit:
    ReleaseStr(pwzUniqueName);

    if (pCertContext)
    {
        ::CertFreeCertificateContext(pCertContext);
    }

    // Close the stores after the context's are released.
    if (hPfxCertStore)
    {
        if (!::CertCloseStore(hPfxCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
        {
            WcaLog(LOGMSG_VERBOSE, "PFX cert store was closed but not all resources were freed.  Error 0x%x", GetLastError());
        }
    }

    return hr;
}
Example #21
0
extern "C" UINT __stdcall CheckServiceUpgrades(MSIHANDLE hInstall) 
{
  HRESULT hr = S_OK;
  UINT er = ERROR_SUCCESS;
  wchar_t* service= 0;
  wchar_t* dir= 0;
  wchar_t installerVersion[MAX_VERSION_PROPERTY_SIZE];
  char installDir[MAX_PATH];
  DWORD size =MAX_VERSION_PROPERTY_SIZE;
  int installerMajorVersion, installerMinorVersion, installerPatchVersion;
  bool upgradableServiceFound=false;

  hr = WcaInitialize(hInstall, __FUNCTION__);
   WcaLog(LOGMSG_STANDARD, "Initialized.");
  if (MsiGetPropertyW(hInstall, L"ProductVersion", installerVersion, &size) 
    != ERROR_SUCCESS)
  {
    hr = HRESULT_FROM_WIN32(GetLastError());
    ExitOnFailure(hr, "MsiGetPropertyW failed");
  }
   if (swscanf(installerVersion,L"%d.%d.%d",
    &installerMajorVersion, &installerMinorVersion, &installerPatchVersion) !=3)
  {
    assert(FALSE);
  }

  size= MAX_PATH;
  if (MsiGetPropertyA(hInstall,"INSTALLDIR", installDir, &size)
    != ERROR_SUCCESS)
  {
    hr = HRESULT_FROM_WIN32(GetLastError());
    ExitOnFailure(hr, "MsiGetPropertyW failed");
  }
 

  SC_HANDLE scm = OpenSCManager(NULL, NULL, 
    SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);  
  if (scm == NULL) 
  { 
    hr = HRESULT_FROM_WIN32(GetLastError());
    ExitOnFailure(hr,"OpenSCManager failed");
  }

  static BYTE buf[64*1024];
  static BYTE config_buffer[8*1024];

  DWORD bufsize= sizeof(buf);
  DWORD bufneed;
  DWORD num_services;
  BOOL ok= EnumServicesStatusExW(scm, SC_ENUM_PROCESS_INFO,  SERVICE_WIN32,
    SERVICE_STATE_ALL,  buf, bufsize,  &bufneed, &num_services, NULL, NULL);
  if(!ok) 
  {
    hr = HRESULT_FROM_WIN32(GetLastError());
    ExitOnFailure(hr,"EnumServicesStatusEx failed");
  }
  LPENUM_SERVICE_STATUS_PROCESSW info =
    (LPENUM_SERVICE_STATUS_PROCESSW)buf;
  int index=-1;
  for (ULONG i=0; i < num_services; i++)
  {
    SC_HANDLE service= OpenServiceW(scm, info[i].lpServiceName, 
      SERVICE_QUERY_CONFIG);
    if (!service)
      continue;
    QUERY_SERVICE_CONFIGW *config= 
      (QUERY_SERVICE_CONFIGW*)(void *)config_buffer;
    DWORD needed;
    BOOL ok= QueryServiceConfigW(service, config,sizeof(config_buffer),
      &needed);
    CloseServiceHandle(service);
    if (ok)
    {
        mysqld_service_properties props;
       if (get_mysql_service_properties(config->lpBinaryPathName, &props))
                  continue;
        /* 
          Only look for services that have mysqld.exe outside of the current
          installation directory.
        */
       if(installDir[0] == 0 || strstr(props.mysqld_exe,installDir) == 0)
        {
           WcaLog(LOGMSG_STANDARD, "found service %S, major=%d, minor=%d",
            info[i].lpServiceName, props.version_major, props.version_minor);
          if(props.version_major < installerMajorVersion
            || (props.version_major == installerMajorVersion && 
                props.version_minor <= installerMinorVersion))
          {
            upgradableServiceFound= true;
            break;
          }
       }
    }
  }

  if(!upgradableServiceFound)
  {
    /* Disable optional checkbox at the end of installation */
    MsiSetPropertyW(hInstall, L"WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT", L"");
    MsiSetPropertyW(hInstall, L"WIXUI_EXITDIALOGOPTIONALCHECKBOX",L"");
  }
  else
  {
    MsiSetPropertyW(hInstall, L"UpgradableServiceFound", L"1");
    MsiSetPropertyW(hInstall, L"WIXUI_EXITDIALOGOPTIONALCHECKBOX",L"1");
  }
LExit:
  if(scm)
    CloseServiceHandle(scm);
  return WcaFinalize(er); 
}
Example #22
0
static HRESULT UninstallCertificatePackage(
    __in HCERTSTORE hStore,
    __in BOOL fUserCertificateStore,
    __in LPCWSTR wzName
    )
{
    HRESULT hr = S_OK;
    DWORD er = ERROR_SUCCESS;
    PCCERT_CONTEXT pCertContext = NULL;
    CRYPT_KEY_PROV_INFO* pPrivateKeyInfo = NULL;
    LPWSTR pwzUniquePrefix = NULL;
    int ccUniquePrefix = 0;

    hr = StrAllocFormatted(&pwzUniquePrefix, L"%s_wixCert_", wzName);
    ExitOnFailure(hr, "Failed to format unique name");
    ccUniquePrefix = ::lstrlenW(pwzUniquePrefix);

    WcaLog(LOGMSG_STANDARD, "Deleting certificate that begin with friendly name: %ls", pwzUniquePrefix);

    // Loop through all certificates in the store, deleting the ones that begin with our prefix.
    while (NULL != (pCertContext = ::CertFindCertificateInStore(hStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext)))
    {
        WCHAR wzFriendlyName[256] = { 0 };
        DWORD cbFriendlyName = sizeof(wzFriendlyName);

        if (::CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, reinterpret_cast<BYTE*>(wzFriendlyName), &cbFriendlyName) &&
            lstrlenW(wzFriendlyName) >= ccUniquePrefix &&
            CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, pwzUniquePrefix, ccUniquePrefix, wzFriendlyName, ccUniquePrefix))
        {
            PCCERT_CONTEXT pCertContextDelete = ::CertDuplicateCertificateContext(pCertContext); // duplicate the context so we can delete it with out disrupting the looping
            if(pCertContextDelete)
            {
                // Delete the certificate and if successful delete the matching private key as well.
                if (::CertDeleteCertificateFromStore(pCertContextDelete))
                {
                    // If we found private key info, delete it.
                    hr = CertReadProperty(pCertContextDelete, CERT_KEY_PROV_INFO_PROP_ID, &pPrivateKeyInfo, NULL);
                    if (SUCCEEDED(hr))
                    {
                        HCRYPTPROV hProvIgnored = NULL; // ignored on deletes.
                        DWORD dwKeyset = fUserCertificateStore ? CRYPT_USER_KEYSET : CRYPT_MACHINE_KEYSET;

                        if (!::CryptAcquireContextW(&hProvIgnored, pPrivateKeyInfo->pwszContainerName, pPrivateKeyInfo->pwszProvName, pPrivateKeyInfo->dwProvType, dwKeyset | CRYPT_DELETEKEYSET | CRYPT_SILENT))
                        {
                            er = ::GetLastError();
                            hr = HRESULT_FROM_WIN32(er);
                        }

                        ReleaseNullMem(pPrivateKeyInfo);
                    }
                    else // don't worry about failures to delete private keys.
                    {
                        hr = S_OK;
                    }
                }
                else
                {
                    er = ::GetLastError();
                    hr = HRESULT_FROM_WIN32(er);
                }

                if (FAILED(hr))
                {
                    WcaLog(LOGMSG_STANDARD, "Failed to delete certificate with friendly name: %ls, continuing anyway.  Error: 0x%x", wzFriendlyName, hr);
                }

                pCertContextDelete = NULL;
            }
        }
    }

    hr = WcaProgressMessage(COST_CERT_DELETE, FALSE);
    ExitOnFailure(hr, "Failed to send uninstall progress message.");

LExit:
    ReleaseStr(pwzUniquePrefix);
    ReleaseMem(pPrivateKeyInfo);
    if(pCertContext)
    {
        ::CertFreeCertificateContext(pCertContext);
    }

    return hr;
}
Example #23
0
HRESULT CpiPartitionRolesRead(
    CPI_PARTITION_LIST* pPartList,
    CPI_PARTITION_ROLE_LIST* pPartRoleList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

    CPI_PARTITION_ROLE* pItm = NULL;
    LPWSTR pwzData = NULL;

    // loop through all application roles
    hr = WcaOpenExecuteView(vcsPartitionRoleQuery, &hView);
    ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionRole table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // create entry
        pItm = (CPI_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_ROLE));
        if (!pItm)
            ExitFunction1(hr = E_OUTOFMEMORY);

        // get key
        hr = WcaGetRecordString(hRec, prqPartitionRole, &pwzData);
        ExitOnFailure(hr, "Failed to get key");
        StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);

        // get partition
        hr = WcaGetRecordString(hRec, prqPartition, &pwzData);
        ExitOnFailure(hr, "Failed to get application");

        hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition);
        if (S_FALSE == hr)
            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
        ExitOnFailure1(hr, "Failed to find partition, key: %S", pwzData);

        // get name
        hr = WcaGetRecordFormattedString(hRec, prqName, &pwzData);
        ExitOnFailure(hr, "Failed to get name");
        StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);

        // add entry
        if (pPartRoleList->pFirst)
            pItm->pNext = pPartRoleList->pFirst;
        pPartRoleList->pFirst = pItm;
        pItm = NULL;
    }

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

LExit:
    // clean up
    if (pItm)
        FreePartitionRole(pItm);

    ReleaseStr(pwzData);

    return hr;
}
Example #24
0
HRESULT ScaGetWebDirProperties(
    __in LPCWSTR wzProperties,
    __in WCA_WRAPQUERY_HANDLE hUserQuery,
    __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery,
    __inout SCA_WEB_PROPERTIES* pswp
    )
{
    Assert(*wzProperties && pswp);

    HRESULT hr = S_OK;
    MSIHANDLE hRec;
    LPWSTR pwzData = NULL;

    ExitOnNull(wzProperties, hr, E_INVALIDARG, "Failed to get web directory properties because no properties were provided to get");

    WcaFetchWrappedReset(hWebDirPropQuery);

    hr = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec);
    if (S_OK == hr)
    {
        hr = WcaGetRecordString(hRec, wpqProperties, &pwzData);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DirProperties");
        hr = ::StringCchCopyW(pswp->wzKey, countof(pswp->wzKey), pwzData);
        ExitOnFailure(hr, "Failed to copy key string to webdirproperties object");

        Assert(0 == lstrcmpW(pswp->wzKey, wzProperties));

        hr = WcaGetRecordInteger(hRec, wpqAccess, &pswp->iAccess);
        ExitOnFailure(hr, "Failed to get access value");

        hr = WcaGetRecordInteger(hRec, wpqAuthorization, &pswp->iAuthorization);
        ExitOnFailure(hr, "Failed to get authorization value");

        // if allow anonymous users
        if (S_OK == hr && pswp->iAuthorization & 1)
        {
            // if there is an anonymous user specified
            hr = WcaGetRecordString(hRec, wpqUser, &pwzData);
            ExitOnFailure(hr, "Failed to get AnonymousUser_");
            if (pwzData && *pwzData)
            {
                hr = WcaGetRecordInteger(hRec, wpqControlledPassword, &pswp->fIIsControlledPassword);
                ExitOnFailure(hr, "Failed to get IIsControlledPassword");
                if (S_FALSE == hr)
                {
                    pswp->fIIsControlledPassword = FALSE;
                    hr = S_OK;
                }

                hr = ScaGetUserDeferred(pwzData, hUserQuery, &pswp->scau);
                ExitOnFailure(hr, "Failed to get User information for Web");

                pswp->fHasUser = TRUE;
            }
            else
                pswp->fHasUser = FALSE;
        }

        hr = WcaGetRecordInteger(hRec, wpqLogVisits, &pswp->fLogVisits);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.LogVisits");

        hr = WcaGetRecordInteger(hRec, wpqIndex, &pswp->fIndex);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.Index");

        hr = WcaGetRecordString(hRec, wpqDefaultDoc, &pwzData);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.DefaultDoc");
        if (pwzData && *pwzData)
        {
            pswp->fHasDefaultDoc = TRUE;
            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default documents by setting them blank
            {
                pswp->wzDefaultDoc[0] = L'\0';
            }
            else   // set the default documents
            {
                hr = ::StringCchCopyW(pswp->wzDefaultDoc, countof(pswp->wzDefaultDoc), pwzData);
                ExitOnFailure(hr, "Failed to copy default document string to webdirproperties object");
            }
        }
        else
        {
            pswp->fHasDefaultDoc = FALSE;
        }

        hr = WcaGetRecordInteger(hRec, wpqAspDetailedError, &pswp->fAspDetailedError);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AspDetailedError");

        hr = WcaGetRecordString(hRec, wpqHttpExp, &pwzData);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.HttpExp");
        if (pwzData && *pwzData)
        {
            pswp->fHasHttpExp = TRUE;
            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default expiration settings by setting them blank
            {
                pswp->wzHttpExp[0] = L'\0';
            }
            else   // set the expiration setting
            {
                hr = ::StringCchCopyW(pswp->wzHttpExp, countof(pswp->wzHttpExp), pwzData);
                ExitOnFailure(hr, "Failed to copy http expiration string to webdirproperties object");
            }
        }
        else
        {
            pswp->fHasHttpExp = FALSE;
        }

        hr = WcaGetRecordInteger(hRec, wpqCCMaxAge, &pswp->iCacheControlMaxAge);
        ExitOnFailure(hr, "failed to get IIsWebDirProperties.CacheControlMaxAge");

        hr = WcaGetRecordString(hRec, wpqCCCustom, &pwzData);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.CacheControlCustom");
        if (pwzData && *pwzData)
        {
            pswp->fHasCacheControlCustom = TRUE;
            if (0 == lstrcmpW(L"-", pwzData))   // remove any existing default cache control custom settings by setting them blank
            {
                pswp->wzCacheControlCustom[0] = L'\0';
            }
            else   // set the custom cache control setting
            {
                hr = ::StringCchCopyW(pswp->wzCacheControlCustom, countof(pswp->wzCacheControlCustom), pwzData);
                ExitOnFailure(hr, "Failed to copy cache control custom settings to webdirproperites object");
            }
        }
        else
        {
            pswp->fHasCacheControlCustom = FALSE;
        }

        hr = WcaGetRecordInteger(hRec, wpqNoCustomError, &pswp->fNoCustomError);
        ExitOnFailure(hr, "failed to get IIsWebDirProperties.NoCustomError");
        if (MSI_NULL_INTEGER == pswp->fNoCustomError)
            pswp->fNoCustomError = FALSE;

        hr = WcaGetRecordInteger(hRec, wpqAccessSSLFlags, &pswp->iAccessSSLFlags);
        ExitOnFailure(hr, "failed to get IIsWebDirProperties.AccessSSLFlags");

        hr = WcaGetRecordString(hRec, wpqAuthenticationProviders, &pwzData);
        ExitOnFailure(hr, "Failed to get IIsWebDirProperties.AuthenticationProviders");
        if (pwzData && *pwzData)
        {
            hr = ::StringCchCopyW(pswp->wzAuthenticationProviders, countof(pswp->wzAuthenticationProviders), pwzData);
            ExitOnFailure(hr, "Failed to copy authentication providers string to webdirproperties object");
        }
        else
        {
            pswp->wzAuthenticationProviders[0] = L'\0';
        }
    }
    else if (E_NOMOREITEMS == hr)
    {
        WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebDirProperties.DirProperties='%ls'", wzProperties);
        hr = E_FAIL;
    }
    else
    {
        ExitOnFailure(hr, "Error getting appropriate webdirproperty");
    }

    // Let's check that there isn't more than one record found - if there is, throw an assert like WcaFetchSingleRecord() would
    HRESULT hrTemp = WcaFetchWrappedRecordWhereString(hWebDirPropQuery, 1, wzProperties, &hRec);
    if (SUCCEEDED(hrTemp))
    {
        AssertSz(E_NOMOREITEMS == hrTemp, "ScaGetWebDirProperties found more than one record");
    }

LExit:
    ReleaseStr(pwzData);

    return hr;
}
Example #25
0
static DWORD WINAPI LoadThreadProc(
    __in LPVOID pvContext
    )
{
    HRESULT hr = S_OK;

    LOAD_THREAD_CONTEXT* pContext = static_cast<LOAD_THREAD_CONTEXT*>(pvContext);
    LPWSTR sczThemePath = pContext->sczThemePath;
    HWND hWnd = pContext->hWnd;

    // We can signal the initialization event as soon as we have copied the context
    // values into local variables.
    ::SetEvent(pContext->hInit);

    BOOL fComInitialized = FALSE;
    HANDLE hDirectory = INVALID_HANDLE_VALUE;
    LPWSTR sczDirectory = NULL;
    LPWSTR wzFileName = NULL;

    THEME* pTheme = NULL;
    HANDLE_THEME* pHandle = NULL;

    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "Failed to initialize COM on load thread.");
    fComInitialized = TRUE;

    // Open a handle to the directory so we can put a notification on it.
    hr = PathGetDirectory(sczThemePath, &sczDirectory);
    ExitOnFailure(hr, "Failed to get path directory.");

     wzFileName = PathFile(sczThemePath);

    hDirectory = ::CreateFileW(sczDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (INVALID_HANDLE_VALUE == hDirectory)
    {
        ExitWithLastError1(hr, "Failed to open directory: %ls", sczDirectory);
    }

    BOOL fUpdated = FALSE;
    do
    {
        // Get the last modified time on the file we're loading for verification that the
        // file actually gets changed down below.
        FILETIME ftModified = { };
        FileGetTime(sczThemePath, NULL, NULL, &ftModified);

        // Try to load the theme file.
        hr = ThemeLoadFromFile(sczThemePath, &pTheme);
        if (FAILED(hr))
        {
            ::SendMessageW(hWnd, WM_THMVWR_THEME_LOAD_ERROR, 0, hr);
        }
        else
        {
            hr = AllocHandleTheme(pTheme, &pHandle);
            ExitOnFailure(hr, "Failed to allocate handle to theme");

            ::SendMessageW(hWnd, WM_THMVWR_NEW_THEME, 0, reinterpret_cast<LPARAM>(pHandle));
            pHandle = NULL;
        }

        fUpdated = FALSE;
        do
        {
            DWORD rgbNotifications[1024];
            DWORD cbRead = 0;
            if (!::ReadDirectoryChangesW(hDirectory, rgbNotifications, sizeof(rgbNotifications), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &cbRead, NULL, NULL))
            {
                ExitWithLastError1(hr, "Failed while watching directory: %ls", sczDirectory);
            }

            // Wait for half a second to let all the file handles get closed to minimize access
            // denied errors.
            ::Sleep(500);

            FILE_NOTIFY_INFORMATION* pNotification = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(rgbNotifications);
            while (pNotification)
            {
                // If our file was updated, check to see if the modified time really changed. The notifications
                // are often trigger happy thinking the file changed two or three times in a row. Maybe it's AV
                // software creating the problems but actually checking the modified date works well.
                if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pNotification->FileName, pNotification->FileNameLength / sizeof(WCHAR), wzFileName, -1))
                {
                    FILETIME ft = { };
                    FileGetTime(sczThemePath, NULL, NULL, &ft);

                    fUpdated = (ftModified.dwHighDateTime < ft.dwHighDateTime) || (ftModified.dwHighDateTime == ft.dwHighDateTime && ftModified.dwLowDateTime < ft.dwLowDateTime);
                    break;
                }

                pNotification = pNotification->NextEntryOffset ? reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<BYTE*>(pNotification) + pNotification->NextEntryOffset) : NULL;
            }
        } while (!fUpdated);
    } while(fUpdated);

LExit:
    if (fComInitialized)
    {
        ::CoUninitialize();
    }

    ReleaseFileHandle(hDirectory);
    ReleaseStr(sczDirectory);
    ReleaseStr(sczThemePath);
    return hr;
}
Example #26
0
HRESULT ScaWriteWebDirProperties(
    __in IMSAdminBase* piMetabase,
    __in LPCWSTR wzRootOfWeb,
    __inout SCA_WEB_PROPERTIES* pswp
    )
{
    HRESULT hr = S_OK;
    DWORD dw = 0;
    WCHAR wz[METADATA_MAX_NAME_LEN + 1];

    // write the access permissions to the metabase
    if (MSI_NULL_INTEGER != pswp->iAccess)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccess));
        ExitOnFailure(hr, "Failed to write access permissions for Web");
    }

    if (MSI_NULL_INTEGER != pswp->iAuthorization)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_AUTHORIZATION, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAuthorization));
        ExitOnFailure(hr, "Failed to write authorization for Web");
    }

    if (pswp->fHasUser)
    {
        Assert(pswp->scau.wzName);
        // write the user name
        if (*pswp->scau.wzDomain)
        {
            hr = ::StringCchPrintfW(wz, countof(wz), L"%s\\%s", pswp->scau.wzDomain, pswp->scau.wzName);
            ExitOnFailure(hr, "Failed to format domain\\username string");
        }
        else
        {
            hr = ::StringCchCopyW(wz, countof(wz), pswp->scau.wzName);
            ExitOnFailure(hr, "Failed to copy user name");
        }
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USER_NAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz);
        ExitOnFailure(hr, "Failed to write anonymous user name for Web");

        // write the password
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_PWD, METADATA_INHERIT | METADATA_SECURE, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->scau.wzPassword);
        ExitOnFailure(hr, "Failed to write anonymous user password for Web");

        // store whether IIs controls password
        dw = (pswp->fIIsControlledPassword) ? TRUE : FALSE;
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ANONYMOUS_USE_SUBAUTH, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
        ExitOnFailure(hr, "Failed to write if IIs controls user password for Web");
    }

    if (MSI_NULL_INTEGER != pswp->fLogVisits)
    {
        // The sense of this boolean value is reversed - it is "don't log", not "log visits."
        dw = (pswp->fLogVisits) ? FALSE : TRUE;
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DONT_LOG, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
        ExitOnFailure(hr, "Failed to write authorization for Web");
    }

    if (MSI_NULL_INTEGER != pswp->fIndex)
    {
        dw = (pswp->fIndex) ? TRUE : FALSE;
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_IS_CONTENT_INDEXED, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
        ExitOnFailure(hr, "Failed to write authorization for Web");
    }

    if (pswp->fHasDefaultDoc)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_DEFAULT_LOAD_FILE, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzDefaultDoc);
        ExitOnFailure(hr, "Failed to write default documents for Web");
    }

    if (MSI_NULL_INTEGER != pswp->fAspDetailedError)
    {
        dw = (pswp->fAspDetailedError) ? TRUE : FALSE;
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_ASP_SCRIPTERRORSSENTTOBROWSER, METADATA_INHERIT, ASP_MD_UT_APP, DWORD_METADATA, (LPVOID)((DWORD_PTR)dw));
        ExitOnFailure(hr, "Failed to write ASP script error for Web");
    }

    if (pswp->fHasHttpExp)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_HTTP_EXPIRES, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzHttpExp);
        ExitOnFailure(hr, "Failed to write HTTP Expiration for Web");
    }

    if (MSI_NULL_INTEGER != pswp->iCacheControlMaxAge)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_MAX_AGE, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iCacheControlMaxAge));
        ExitOnFailure(hr, "Failed to write Cache Control Max Age for Web");
    }

    if (pswp->fHasCacheControlCustom)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CC_OTHER, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)pswp->wzCacheControlCustom);
        ExitOnFailure(hr, "Failed to write Cache Control Custom for Web");
    }

    if (pswp->fNoCustomError)
    {
        memset(wz, 0, sizeof(wz));
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_CUSTOM_ERROR, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wz);
        ExitOnFailure(hr, "Failed to write Custom Error for Web");
    }

    if (MSI_NULL_INTEGER != pswp->iAccessSSLFlags)
    {
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_SSL_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)pswp->iAccessSSLFlags));
        ExitOnFailure(hr, "Failed to write AccessSSLFlags for Web");
    }

    if (*pswp->wzAuthenticationProviders)
    {
        hr = ::StringCchCopyW(wz, countof(wz), pswp->wzAuthenticationProviders);
        ExitOnFailure(hr, "Failed to copy authentication providers string");
        hr = ScaWriteMetabaseValue(piMetabase, wzRootOfWeb, NULL, MD_NTAUTHENTICATION_PROVIDERS, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)wz);
        ExitOnFailure(hr, "Failed to write AuthenticationProviders for Web");
    }

LExit:
    return hr;
}
static HRESULT CreateUserInPartitionRole(
	CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
	)
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	ICatalogCollection* piUsrInRoleColl = NULL;
	ICatalogObject* piUsrInRoleObj = NULL;

	PSID pSid = NULL;
	long lChanges = 0;

	// log
	WcaLog(LOGMSG_VERBOSE, "Adding user to partition role, key: %S", pAttrs->pwzKey);

	// get users in partition role collection
	hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl);
	if (S_FALSE == hr)
		hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
	ExitOnFailure(hr, "Failed to get users in partition role collection");

	// get SID for account
	do {
		er = ERROR_SUCCESS;
		hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
		if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
		{
			WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
			er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
			switch (er)
			{
			case IDABORT:
				ExitFunction(); // exit with error code from CpiAccountNameToSid()
			case IDRETRY:
				break;
			case IDIGNORE:
				ExitFunction1(hr = S_OK);
			}
		}
		else
			ExitOnFailure(hr, "Failed to get SID for account");
	} while (IDRETRY == er);

	// find any existing entry
	hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL);
	if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
		WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
	else
		ExitOnFailure(hr, "Failed to find user in partition role");

	if (S_OK == hr)
	{
		WcaLog(LOGMSG_VERBOSE, "User already assigned to partition role, key: %S", pAttrs->pwzKey);
		ExitFunction(); // exit with hr = S_OK
	}

	// convert SID back to account name
	hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount);
	ExitOnFailure(hr, "Failed to convert SID to account name");

	// add user
	hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj);
	ExitOnFailure(hr, "Failed to add user in role to collection");

	hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount);
	ExitOnFailure(hr, "Failed to set role name property");

	// save changes
	hr = piUsrInRoleColl->SaveChanges(&lChanges);
	if (COMADMIN_E_OBJECTERRORS == hr)
		CpiLogCatalogErrorInfo();
	ExitOnFailure(hr, "Failed to save changes");

	// log
	WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);

	hr = S_OK;

LExit:
	// clean up
	ReleaseObject(piUsrInRoleColl);
	ReleaseObject(piUsrInRoleObj);

	if (pSid)
		::HeapFree(::GetProcessHeap(), 0, pSid);

	return hr;
}
Example #28
0
extern "C" HRESULT ExeEngineParsePackageFromXml(
    __in IXMLDOMNode* pixnExePackage,
    __in BURN_PACKAGE* pPackage
    )
{
    HRESULT hr = S_OK;
    IXMLDOMNodeList* pixnNodes = NULL;
    IXMLDOMNode* pixnNode = NULL;
    DWORD cNodes = 0;
    LPWSTR scz = NULL;

    // @DetectCondition
    hr = XmlGetAttributeEx(pixnExePackage, L"DetectCondition", &pPackage->Exe.sczDetectCondition);
    ExitOnFailure(hr, "Failed to get @DetectCondition.");

    // @InstallArguments
    hr = XmlGetAttributeEx(pixnExePackage, L"InstallArguments", &pPackage->Exe.sczInstallArguments);
    ExitOnFailure(hr, "Failed to get @InstallArguments.");

    // @UninstallArguments
    hr = XmlGetAttributeEx(pixnExePackage, L"UninstallArguments", &pPackage->Exe.sczUninstallArguments);
    ExitOnFailure(hr, "Failed to get @UninstallArguments.");

    // @RepairArguments
    hr = XmlGetAttributeEx(pixnExePackage, L"RepairArguments", &pPackage->Exe.sczRepairArguments);
    ExitOnFailure(hr, "Failed to get @RepairArguments.");

    // @Repairable
    hr = XmlGetYesNoAttribute(pixnExePackage, L"Repairable", &pPackage->Exe.fRepairable);
    if (E_NOTFOUND != hr)
    {
        ExitOnFailure(hr, "Failed to get @Repairable.");
    }

    // @Protocol
    hr = XmlGetAttributeEx(pixnExePackage, L"Protocol", &scz);
    if (SUCCEEDED(hr))
    {
        if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"burn", -1))
        {
            pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
        }
        else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"netfx4", -1))
        {
            pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_NETFX4;
        }
        else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"none", -1))
        {
            pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_NONE;
        }
        else
        {
            hr = E_UNEXPECTED;
            ExitOnFailure1(hr, "Invalid exit code type: %ls", scz);
        }
    }
    else if (E_NOTFOUND != hr)
    {
        ExitOnFailure(hr, "Failed to get @Protocol.");
    }

    // select exit code nodes
    hr = XmlSelectNodes(pixnExePackage, L"ExitCode", &pixnNodes);
    ExitOnFailure(hr, "Failed to select exit code nodes.");

    // get exit code node count
    hr = pixnNodes->get_length((long*)&cNodes);
    ExitOnFailure(hr, "Failed to get exit code node count.");

    if (cNodes)
    {
        // allocate memory for exit codes
        pPackage->Exe.rgExitCodes = (BURN_EXE_EXIT_CODE*)MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE);
        ExitOnNull(pPackage->Exe.rgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs.");

        pPackage->Exe.cExitCodes = cNodes;

        // parse package elements
        for (DWORD i = 0; i < cNodes; ++i)
        {
            BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i];

            hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
            ExitOnFailure(hr, "Failed to get next node.");

            // @Type
            hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
            ExitOnFailure(hr, "Failed to get @Type.");

            if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"success", -1))
            {
                pExitCode->type = BURN_EXE_EXIT_CODE_TYPE_SUCCESS;
            }
            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"error", -1))
            {
                pExitCode->type = BURN_EXE_EXIT_CODE_TYPE_ERROR;
            }
            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"scheduleReboot", -1))
            {
                pExitCode->type = BURN_EXE_EXIT_CODE_TYPE_SCHEDULE_REBOOT;
            }
            else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"forceReboot", -1))
            {
                pExitCode->type = BURN_EXE_EXIT_CODE_TYPE_FORCE_REBOOT;
            }
            else
            {
                hr = E_UNEXPECTED;
                ExitOnFailure1(hr, "Invalid exit code type: %ls", scz);
            }

            // @Code
            hr = XmlGetAttributeEx(pixnNode, L"Code", &scz);
            ExitOnFailure(hr, "Failed to get @Code.");

            if (L'*' == scz[0])
            {
                pExitCode->fWildcard = TRUE;
            }
            else
            {
                hr = StrStringToUInt32(scz, 0, (UINT*)&pExitCode->dwCode);
                ExitOnFailure1(hr, "Failed to parse @Code value: %ls", scz);
            }

            // prepare next iteration
            ReleaseNullObject(pixnNode);
        }
    }

    hr = S_OK;

LExit:
    ReleaseObject(pixnNodes);
    ReleaseObject(pixnNode);
    ReleaseStr(scz);

    return hr;
}
HRESULT CpiConfigureUsersInPartitionRoles(
	LPWSTR* ppwzData,
	HANDLE hRollbackFile
	)
{
	HRESULT hr = S_OK;

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

	// read action text
	hr = CpiActionStartMessage(ppwzData, FALSE);
	ExitOnFailure(hr, "Failed to send action start message");

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

	// write count to rollback file
	hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
	ExitOnFailure(hr, "Failed to write count to rollback file");

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

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

		if (S_FALSE == hr)
			ExitFunction();

		// write key to rollback file
		hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
		ExitOnFailure(hr, "Failed to write key to rollback file");

		// action
		switch (attrs.iActionType)
		{
		case atCreate:
			hr = CreateUserInPartitionRole(&attrs);
			ExitOnFailure1(hr, "Failed to add user to partition role, key: %S", attrs.pwzKey);
			break;
		case atRemove:
			hr = RemoveUserInPartitionRole(&attrs);
			ExitOnFailure1(hr, "Failed to remove user from partition role, key: %S", attrs.pwzKey);
			break;
		}

		// write completion status to rollback file
		hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
		ExitOnFailure(hr, "Failed to write completion status to rollback file");

		// progress
		hr = WcaProgressMessage(attrs.iActionCost, FALSE);
		ExitOnFailure(hr, "Failed to update progress");
	}

	hr = S_OK;

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

	return hr;
}
Example #30
0
static HRESULT AddSubscriptionToActionData(
    CPI_SUBSCRIPTION* pItm,
    int iActionType,
    int iActionCost,
    LPWSTR* ppwzActionData
    )
{
    HRESULT hr = S_OK;

    // add action information to custom action data
    hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
    ExitOnFailure(hr, "Failed to add action type to custom action data");
    hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
    ExitOnFailure(hr, "Failed to add action cost to custom action data");

    // add application role information to custom action data
    hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
    ExitOnFailure(hr, "Failed to add subscription key to custom action data");
    hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData);
    ExitOnFailure(hr, "Failed to add subscription id to custom action data");
    hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
    ExitOnFailure(hr, "Failed to add subscription name to custom action data");
    hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzEventCLSID : L"", ppwzActionData);
    ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data");
    hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzPublisherID : L"", ppwzActionData);
    ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data");

    // add component information to custom action data
    hr = WcaWriteStringToCaData(pItm->pComponent->wzCLSID, ppwzActionData);
    ExitOnFailure(hr, "Failed to add application id to custom action data");

    // add application information to custom action data
    hr = WcaWriteStringToCaData(pItm->pAssembly->pApplication->wzID, ppwzActionData);
    ExitOnFailure(hr, "Failed to add application id to custom action data");

    // add partition information to custom action data
    LPCWSTR pwzPartID = pItm->pAssembly->pApplication->pPartition ? pItm->pAssembly->pApplication->pPartition->wzID : L"";
    hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData);
    ExitOnFailure(hr, "Failed to add partition id to custom action data");

    // add properties to custom action data
    hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
    ExitOnFailure(hr, "Failed to add properties to custom action data");

    hr = S_OK;

LExit:
    return hr;
}