/********************************************************************
 ReadEulaText - Reads Eula text from the MSI

********************************************************************/
HRESULT ReadEulaText(
    __in MSIHANDLE /*hInstall*/,
    __out LPSTR* ppszEulaText
    )
{
    HRESULT hr = S_OK;
    PMSIHANDLE hDB;
    PMSIHANDLE hView;
    PMSIHANDLE hRec;
    LPWSTR pwzEula = NULL;

    hr = WcaOpenExecuteView(vcsEulaQuery, &hView);
    ExitOnFailure(hr, "failed to open and execute view for PrintEula query");

    hr = WcaFetchSingleRecord(hView, &hRec);
    ExitOnFailure(hr, "failed to fetch the row containing the LicenseText");

    hr = WcaGetRecordString(hRec, 1, &pwzEula);
    ExitOnFailure(hr, "failed to get LicenseText in PrintEula");

    hr = StrAnsiAllocString(ppszEulaText, pwzEula, 0, CP_ACP);
    ExitOnFailure(hr, "failed to convert LicenseText to ANSI code page");

LExit:
    return hr;
}
Beispiel #2
0
HRESULT CpiPartitionRolesRead(
    CPI_PARTITION_LIST* pPartList,
    CPI_PARTITION_ROLE_LIST* pPartRoleList
    )
{
    HRESULT hr = S_OK;
    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;
}
Beispiel #3
0
//
// ExtractBinary extracts the data from the Binary table row with the given ID into a file.
// If wzDirectory is NULL, ExtractBinary defaults to the temporary directory.
//
HRESULT ExtractBinary(
    __in LPCWSTR wzBinaryId,
    __out BYTE** pbData,
    __out DWORD* pcbData
)
{
    HRESULT hr = S_OK;
    LPWSTR pwzSql = NULL;
    PMSIHANDLE hView;
    PMSIHANDLE hRec;

    // make sure we're not horked from the get-go
    hr = WcaTableExists(L"Binary");
    if (S_OK != hr)
    {
        if (SUCCEEDED(hr))
        {
            hr = E_UNEXPECTED;
        }
        ExitOnFailure(hr, "There is no Binary table.");
    }

    ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null");
    ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string");

    hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId);
    ExitOnFailure(hr, "Failed to allocate Binary table query.");

    hr = WcaOpenExecuteView(pwzSql, &hView);
    ExitOnFailure(hr, "Failed to open view on Binary table");

    hr = WcaFetchSingleRecord(hView, &hRec);
    ExitOnFailure(hr, "Failed to retrieve request from Binary table");

    hr = WcaGetRecordStream(hRec, 1, pbData, pcbData);
    ExitOnFailure(hr, "Failed to read Binary.Data.");

LExit:
    ReleaseStr(pwzSql);

    return hr;
}
Beispiel #4
0
/******************************************************************
 CaSchedSecureObjects - entry point for CaReadSecureObjects Custom Action

 called as Type 1 CustomAction (binary DLL) from Windows Installer
 in InstallExecuteSequence before CaSecureObjects
******************************************************************/
extern "C" UINT __stdcall SchedSecureObjects(
	__in MSIHANDLE hInstall
	)
{
//	AssertSz(FALSE, "debug SchedSecureObjects");
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	LPWSTR pwzData = NULL;
	LPWSTR pwzTable = NULL;
	LPWSTR pwzTargetPath = NULL;
	LPWSTR pwzFormattedString = NULL;

	int iRoot = 0;
	int iAllUsers = 0;
	LPWSTR pwzKey = NULL;

	PMSIHANDLE hView = NULL;
	PMSIHANDLE hRec = NULL;

	MSIHANDLE hViewObject = NULL; // Don't free this since it's always a copy of either hViewService or hViewCreateFolder
	PMSIHANDLE hViewService = NULL;
	PMSIHANDLE hViewCreateFolder = NULL;
	PMSIHANDLE hViewFile = NULL;
	PMSIHANDLE hViewRegistry = NULL;
	PMSIHANDLE hRecObject = NULL;

	INSTALLSTATE isInstalled;
	INSTALLSTATE isAction;

	LPWSTR pwzCustomActionData = NULL;
	DWORD cchCustomActionData = 0;

	DWORD cObjects = 0;
	eOBJECTTYPE eType = OT_UNKNOWN;

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

	//
	// loop through all the objects to be secured
	//
	hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView);
	ExitOnFailure(hr, "failed to open view on SecureObjects table");
	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		hViewObject = NULL;
		eType = OT_UNKNOWN;

		hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable);
		ExitOnFailure(hr, "failed to get object table");

		// ensure we're looking at a known table
		if (0 == lstrcmpW(L"ServiceInstall", pwzTable))
		{
			eType = OT_SERVICE;
		}
		else if (0 == lstrcmpW(L"CreateFolder", pwzTable))
		{
			eType = OT_FOLDER;
		}
		else if (0 == lstrcmpW(L"File", pwzTable))
		{
			eType = OT_FILE;
		}
		else if (0 == lstrcmpW(L"Registry", pwzTable))
		{
			eType = OT_REGISTRY;
		}
		else
		{
			ExitOnFailure1(hr = E_INVALIDARG, "unknown SecureObject.Table: %S", pwzTable);
		}

		// if we haven't opened a view on the ServiceInstall/CreateFolder table, do that now
		if (OT_SERVICE == eType)
		{
			if (!hViewService)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_SERVICECOMPONENT, &hViewService);
				ExitOnFailure(hr, "failed to open view on ServiceInstall table");
			}

			hViewObject = hViewService;
		}
		else if (OT_FOLDER == eType)
		{
			if (!hViewCreateFolder)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_CREATEFOLDERCOMPONENT, &hViewCreateFolder);
				ExitOnFailure(hr, "failed to open view on CreateFolder table");
			}

			hViewObject = hViewCreateFolder;
		}
		else if (OT_FILE== eType)
		{
			if (!hViewFile)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_FILECOMPONENT, &hViewFile);
				ExitOnFailure(hr, "failed to open view on CreateFolder table");
			}

			hViewObject = hViewFile;
		}
		else if (OT_REGISTRY== eType)
		{
			if (!hViewRegistry)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_REGISTRYCOMPONENT, &hViewRegistry);
				ExitOnFailure(hr, "failed to open view on CreateFolder table");
			}

			hViewObject = hViewRegistry;
		}

		Assert(hViewObject);

		// execute a view looking for the object's Component_
		hr = WcaExecuteView(hViewObject, hRec);
		ExitOnFailure1(hr, "failed to execute view on %S table", pwzData);
		hr = WcaFetchSingleRecord(hViewObject, &hRecObject);
		ExitOnFailure(hr, "failed to fetch Component for secure object");

		hr = WcaGetRecordString(hRecObject, QSOC_COMPONENT, &pwzData);
		ExitOnFailure(hr, "failed to get Component name for secure object");

		//
		// if we are installing this Component
		//
		er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction);
		ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %S", pwzData);

		if (WcaIsInstalling(isInstalled, isAction))
		{
			// add the data to the CustomActionData
			hr = WcaGetRecordString(hRecObject, QSOC_OBJECTNAME, &pwzData);
			ExitOnFailure(hr, "failed to get name of object");

			if (OT_SERVICE == eType)
			{
				hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else if (OT_FOLDER == eType)
			{
				hr = WcaGetTargetPath(pwzData, &pwzTargetPath);
				ExitOnFailure1(hr, "failed to get target path for directory id: %S", pwzData);
				hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else if (OT_FILE == eType)
			{
				hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzData);
				ExitOnFailure1(hr, "failed to create formatted string for securing file object: %S", pwzData);

				hr = WcaGetFormattedString(pwzFormattedString, &pwzTargetPath);
				ExitOnFailure2(hr, "failed to get file path from formatted string: %S for secure object: %S", pwzFormattedString, pwzData);

				hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else if (OT_REGISTRY == eType)
			{
				hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot);
				ExitOnFailure1(hr, "Failed to get reg key root for secure object: %S", pwzData);

				hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey);
				ExitOnFailure1(hr, "Failed to get reg key for secure object: %S", pwzData);

				// Decode the root value
				if (-1 == iRoot)
				{
					// They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property
					hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers);
					ExitOnFailure(hr, "failed to get value of ALLUSERS property");

					if (1 == iAllUsers)
					{
						hr = StrAllocString(&pwzTargetPath, L"MACHINE\\", 0);
						ExitOnFailure(hr, "failed to allocate target registry string with HKLM root");
					}
					else
					{
						hr = StrAllocString(&pwzTargetPath, L"CURRENT_USER\\", 0);
						ExitOnFailure(hr, "failed to allocate target registry string with HKCU root");
					}
				}
				else if (/*msidbRegistryRootClassesRoot*/ 0 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"CLASSES_ROOT\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKCR root");
				}
				else if (/*msidbRegistryRootCurrentUser*/ 1 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"CURRENT_USER\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKCU root");
				}
				else if (/*msidbRegistryRootLocalMachine*/ 2 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"MACHINE\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKLM root");
				}
				else if (/*msidbRegistryRootUsers*/ 3 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"USERS\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKU root");
				}
				else
				{
					ExitOnFailure2(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%S' root: %d", pwzData, iRoot);
				}

				hr = StrAllocConcat(&pwzTargetPath, pwzKey, 0);
				ExitOnFailure2(hr, "Failed to concat key: %S for secure object: %S", pwzKey, pwzData);

				hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else
			{
				AssertSz(FALSE, "How did you get here?");
			}

			hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordFormattedString(hRec, QSO_DOMAIN, &pwzData);
			ExitOnFailure(hr, "failed to get domain for user to configure object");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordFormattedString(hRec, QSO_USER, &pwzData);
			ExitOnFailure(hr, "failed to get user to configure object");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSO_PERMISSION, &pwzData);
			ExitOnFailure(hr, "failed to get domain for user to configure object");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			cObjects++;
		}
	}

	// if we looped through all records all is well
	if (E_NOMOREITEMS == hr)
		hr = S_OK;
	ExitOnFailure(hr, "failed while looping through all objects to secure");

	//
	// schedule the custom action and add to progress bar
	//
	if (pwzCustomActionData && *pwzCustomActionData)
	{
		Assert(0 < cObjects);

		hr = WcaDoDeferredAction(L"ExecSecureObjects", pwzCustomActionData, cObjects * COST_SECUREOBJECT);
		ExitOnFailure(hr, "failed to schedule ExecSecureObjects action");
	}

LExit:
	ReleaseStr(pwzCustomActionData);
	ReleaseStr(pwzData);
	ReleaseStr(pwzTable);
	ReleaseStr(pwzTargetPath);
	ReleaseStr(pwzFormattedString);
	ReleaseStr(pwzKey);

	if (FAILED(hr))
		er = ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
Beispiel #5
0
/******************************************************************
 SchedFirewallExceptions - immediate custom action worker to 
   register and remove firewall exceptions.

********************************************************************/
static UINT SchedFirewallExceptions(
    __in MSIHANDLE hInstall,
    WCA_TODO todoSched
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    int cFirewallExceptions = 0;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzName = NULL;
    LPWSTR pwzRemoteAddresses = NULL;
    LPWSTR pwzPort = NULL;
    int iProtocol = 0;
    int iAttributes = 0;
    int iProfile = 0;
    LPWSTR pwzProgram = NULL;
    LPWSTR pwzComponent = NULL;
    LPWSTR pwzFormattedFile = NULL;
    LPWSTR pwzDescription = NULL;

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

    // anything to do?
    if (S_OK != WcaTableExists(L"WixFirewallException"))
    {
        WcaLog(LOGMSG_STANDARD, "WixFirewallException table doesn't exist, so there are no firewall exceptions to configure.");
        ExitFunction();
    }

    // query and loop through all the firewall exceptions
    hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView);
    ExitOnFailure(hr, "failed to open view on WixFirewallException table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = WcaGetRecordFormattedString(hRec, feqName, &pwzName);
        ExitOnFailure(hr, "failed to get firewall exception name");

        hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &pwzRemoteAddresses);
        ExitOnFailure(hr, "failed to get firewall exception remote addresses");

        hr = WcaGetRecordFormattedString(hRec, feqPort, &pwzPort);
        ExitOnFailure(hr, "failed to get firewall exception port");

        hr = WcaGetRecordInteger(hRec, feqProtocol, &iProtocol);
        ExitOnFailure(hr, "failed to get firewall exception protocol");

        hr = WcaGetRecordFormattedString(hRec, feqProgram, &pwzProgram);
        ExitOnFailure(hr, "failed to get firewall exception program");

        hr = WcaGetRecordInteger(hRec, feqAttributes, &iAttributes);
        ExitOnFailure(hr, "failed to get firewall exception attributes");
        
        hr = WcaGetRecordInteger(hRec, feqProfile, &iProfile);
        ExitOnFailure(hr, "failed to get firewall exception profile");

        hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent);
        ExitOnFailure(hr, "failed to get firewall exception component");

        hr = WcaGetRecordString(hRec, feqDescription, &pwzDescription);
        ExitOnFailure(hr, "failed to get firewall description");

        // figure out what we're doing for this exception, treating reinstall the same as install
        WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent);
        if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
        {
            WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d)", pwzComponent, todoComponent, todoSched);
            continue;
        }

        // action :: name :: profile :: remoteaddresses :: attributes :: target :: {port::protocol | path}
        ++cFirewallExceptions;
        hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write exception action to custom action data");

        hr = WcaWriteStringToCaData(pwzName, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write exception name to custom action data");

        hr = WcaWriteIntegerToCaData(iProfile, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write exception profile to custom action data");

        hr = WcaWriteStringToCaData(pwzRemoteAddresses, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write exception remote addresses to custom action data");

        hr = WcaWriteIntegerToCaData(iAttributes, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write exception attributes to custom action data");

        if (*pwzProgram)
        {
            // If program is defined, we have an application exception.
            hr = WcaWriteIntegerToCaData(fetApplication, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write exception target (application) to custom action data");

            hr = WcaWriteStringToCaData(pwzProgram, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write application path to custom action data");
        }
        else
        {
            // we have a port-only exception
            hr = WcaWriteIntegerToCaData(fetPort, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write exception target (port) to custom action data");
        }

        hr = WcaWriteStringToCaData(pwzPort, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write application path to custom action data");

        hr = WcaWriteIntegerToCaData(iProtocol, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write exception protocol to custom action data");

        hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData);
        ExitOnFailure(hr, "failed to write firewall rule description to custom action data");
    }

    // reaching the end of the list is actually a good thing, not an error
    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    } 
    ExitOnFailure(hr, "failure occured while processing WixFirewallException table");

    // schedule ExecFirewallExceptions if there's anything to do
    if (pwzCustomActionData && *pwzCustomActionData)
    {
        WcaLog(LOGMSG_STANDARD, "Scheduling firewall exception (%ls)", pwzCustomActionData);

        if (WCA_TODO_INSTALL == todoSched)
        {
            hr = WcaDoDeferredAction(L"WixRollbackFirewallExceptionsInstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
            ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");            
            hr = WcaDoDeferredAction(L"WixExecFirewallExceptionsInstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
            ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
        }
        else
        {
            hr = WcaDoDeferredAction(L"WixRollbackFirewallExceptionsUninstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
            ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");    
            hr = WcaDoDeferredAction(L"WixExecFirewallExceptionsUninstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
            ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
        }
    }
    else
    {
        WcaLog(LOGMSG_STANDARD, "No firewall exceptions scheduled");
    }

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzName);
    ReleaseStr(pwzRemoteAddresses);
    ReleaseStr(pwzPort);
    ReleaseStr(pwzProgram);
    ReleaseStr(pwzComponent);
    ReleaseStr(pwzDescription);
    ReleaseStr(pwzFormattedFile);

    return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
}
Beispiel #6
0
HRESULT CpiPartitionsRead(
    CPI_PARTITION_LIST* pPartList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

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

    // loop through all partitions
    hr = WcaOpenExecuteView(vcsPartitionQuery, &hView);
    ExitOnFailure(hr, "Failed to execute view on ComPlusPartition table");

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

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

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

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

        // get component install state
        if (pwzData && *pwzData)
        {
            pItm->fHasComponent = TRUE;

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

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

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

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

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

        // if partition is a locater, either an id or a name must be provided
        if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName)
            ExitOnFailure(hr = E_FAIL, "A partition locater must have either an id or a name associated, key: %S", pItm->wzKey);

        // if partition is not a locater, an name must be provided
        if (pItm->fHasComponent && !*pItm->wzName)
            ExitOnFailure(hr = E_FAIL, "A partition must have a name associated, key: %S", pItm->wzKey);

        // get properties
        if (CpiTableExists(cptComPlusPartitionProperty) && pItm->fHasComponent)
        {
            hr = CpiPropertiesRead(vcsPartitionPropertyQuery, pItm->wzKey, pdlPartitionProperties, &pItm->pProperties, &pItm->iPropertyCount);
            ExitOnFailure(hr, "Failed to get properties");
        }

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

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

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

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

    ReleaseStr(pwzData);

    return hr;
}
Beispiel #7
0
HRESULT ScaDbsRead(
    __inout SCA_DB** ppsdList,
    __in SCA_ACTION saAction
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    PMSIHANDLE hView;
    PMSIHANDLE hRec;
    PMSIHANDLE hViewFileSpec = NULL;

    LPWSTR pwzData = NULL;
    LPWSTR pwzId = NULL;
    LPWSTR pwzComponent = NULL;

    SCA_DB* psd = NULL;

    if (S_OK != WcaTableExists(L"SqlDatabase"))
    {
        WcaLog(LOGMSG_VERBOSE, "Skipping ScaCreateDatabase() - SqlDatabase table not present");
        ExitFunction1(hr = S_FALSE);
    }

    if (S_OK == WcaTableExists(L"SqlFileSpec"))
    {
        hr = WcaOpenView(vcsSqlFileSpecQuery, &hViewFileSpec);
        ExitOnFailure(hr, "failed to open view on SqlFileSpec table");
    }

    // loop through all the sql databases
    hr = WcaOpenExecuteView(vcsSqlDatabaseQuery, &hView);
    ExitOnFailure(hr, "Failed to open view on SqlDatabase table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        BOOL fHasComponent = FALSE;
        INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
        INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;

        hr = WcaGetRecordString(hRec, sdqSqlDb, &pwzId);
        ExitOnFailure(hr, "Failed to get SqlDatabase.SqlDb");

        hr = WcaGetRecordString(hRec, sdqComponent, &pwzComponent);
        ExitOnFailure1(hr, "Failed to get Component for database: '%ls'", psd->wzKey);
        if (pwzComponent && *pwzComponent)
        {
            fHasComponent = TRUE;

            er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction);
            hr = HRESULT_FROM_WIN32(er);
            ExitOnFailure1(hr, "Failed to get state for component: %ls", pwzComponent);

            // If we're doing install but the Component is not being installed or we're doing
            // uninstall but the Component is not being uninstalled, skip it.
            if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) ||
                (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction))
            {
                continue;
            }
        }

        hr  = NewDb(&psd);
        ExitOnFailure1(hr, "Failed to allocate memory for new database: %D", pwzId);

        hr = ::StringCchCopyW(psd->wzKey, countof(psd->wzKey), pwzId);
        ExitOnFailure1(hr, "Failed to copy SqlDatabase.SqlDbL: %ls", pwzId);

        hr = ::StringCchCopyW(psd->wzComponent, countof(psd->wzComponent), pwzComponent);
        ExitOnFailure1(hr, "Failed to copy SqlDatabase.Component_: %ls", pwzComponent);

        psd->fHasComponent = fHasComponent;
        psd->isInstalled = isInstalled;
        psd->isAction = isAction;

        hr = WcaGetRecordFormattedString(hRec, sdqServer, &pwzData);
        ExitOnFailure1(hr, "Failed to get Server for database: '%ls'", psd->wzKey);
        hr = ::StringCchCopyW(psd->wzServer, countof(psd->wzServer), pwzData);
        ExitOnFailure1(hr, "Failed to copy server string to database object:%ls", pwzData);

        hr = WcaGetRecordFormattedString(hRec, sdqInstance, &pwzData);
        ExitOnFailure1(hr, "Failed to get Instance for database: '%ls'", psd->wzKey);
        hr = ::StringCchCopyW(psd->wzInstance, countof(psd->wzInstance), pwzData);
        ExitOnFailure1(hr, "Failed to copy instance string to database object:%ls", pwzData);

        hr = WcaGetRecordFormattedString(hRec, sdqDatabase, &pwzData);
        ExitOnFailure1(hr, "Failed to get Database for database: '%ls'", psd->wzKey);
        hr = ::StringCchCopyW(psd->wzDatabase, countof(psd->wzDatabase), pwzData);
        ExitOnFailure1(hr, "Failed to copy database string to database object:%ls", pwzData);

        hr = WcaGetRecordInteger(hRec, sdqAttributes, &psd->iAttributes);
        ExitOnFailure(hr, "Failed to get SqlDatabase.Attributes");

        hr = WcaGetRecordFormattedString(hRec, sdqUser, &pwzData);
        ExitOnFailure1(hr, "Failed to get User record for database: '%ls'", psd->wzKey);

        // if a user was specified
        if (*pwzData)
        {
            psd->fUseIntegratedAuth = FALSE;
            hr = ScaGetUser(pwzData, &psd->scau);
            ExitOnFailure1(hr, "Failed to get user information for database: '%ls'", psd->wzKey);
        }
        else
        {
            psd->fUseIntegratedAuth = TRUE;
            // integrated authorization doesn't have a User record
        }

        hr = WcaGetRecordString(hRec, sdqDbFileSpec, &pwzData);
        ExitOnFailure1(hr, "Failed to get Database FileSpec for database: '%ls'", psd->wzKey);

        // if a database filespec was specified
        if (*pwzData)
        {
            hr = GetFileSpec(hViewFileSpec, pwzData, &psd->sfDb);
            ExitOnFailure1(hr, "failed to get FileSpec for: %ls", pwzData);
            if (S_OK == hr)
            {
                psd->fHasDbSpec = TRUE;
            }
        }

        hr = WcaGetRecordString(hRec, sdqLogFileSpec, &pwzData);
        ExitOnFailure1(hr, "Failed to get Log FileSpec for database: '%ls'", psd->wzKey);

        // if a log filespec was specified
        if (*pwzData)
        {
            hr = GetFileSpec(hViewFileSpec, pwzData, &psd->sfLog);
            ExitOnFailure1(hr, "failed to get FileSpec for: %ls", pwzData);
            if (S_OK == hr)
            {
                psd->fHasLogSpec = TRUE;
            }
        }

        *ppsdList = AddDbToList(*ppsdList, psd);
        psd = NULL; // set the db NULL so it doesn't accidentally get freed below
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while processing SqlDatabase table");

LExit:
    if (psd)
    {
        ScaDbsFreeList(psd);
    }

    ReleaseStr(pwzComponent);
    ReleaseStr(pwzId);
    ReleaseStr(pwzData);
    return hr;
}
/******************************************************************
 SchedAddinRegistration - entry point for AddinRegistration Custom Action

********************************************************************/
HRESULT SchedAddinRegistration(MSIHANDLE hInstall, BOOL fInstall)
{
    // AssertSz(FALSE, "debug SchedRegisterAddins");

    HRESULT hr = S_OK;

    LPWSTR pwzCustomActionData = NULL;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    LPWSTR pwzData = NULL;
    LPWSTR pwzTemp = NULL;
    LPWSTR pwzComponent = NULL;

    LPWSTR pwzId = NULL;
    LPWSTR pwzFile = NULL;
	LPWSTR pwzFriendlyName = NULL;
	LPWSTR pwzDescription = NULL;

	int iBitness = 0;
	int iCommandLineSafe = 1;
	int iLoadBehavior = 0;

	LPWSTR pwzAllUsers = NULL;

    int nAddins = 0;

	hr = WcaGetProperty(L"ALLUSERS", &pwzAllUsers);
	ExitOnFailure(hr, "failed to read value of ALLUSERS property");

    // loop through all the RegisterAddin records
    hr = WcaOpenExecuteView(vcsRegisterAddinsQuery, &hView);
    ExitOnFailure(hr, "failed to open view on AddinRegistration table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
		++nAddins;

        // Get Id
        hr = WcaGetRecordString(hRec, arqId, &pwzId);
        ExitOnFailure(hr, "failed to get AddinRegistration.AddinRegistration");

        // Get File
        hr = WcaGetRecordString(hRec, arqFile, &pwzData);
        ExitOnFailure1(hr, "failed to get AddinRegistration.File_ for record: %ls", pwzId);
        hr = StrAllocFormatted(&pwzTemp, L"[#%ls]", pwzData);
        ExitOnFailure1(hr, "failed to format file string for file: %ls", pwzData);
        hr = WcaGetFormattedString(pwzTemp, &pwzFile);
        ExitOnFailure1(hr, "failed to get formatted string for file: %ls", pwzData);

        // Get name
        hr = WcaGetRecordFormattedString(hRec, arqName, &pwzFriendlyName);
        ExitOnFailure1(hr, "failed to get AddinRegistration.Name for record: %ls", pwzId);

        // Get description
        hr = WcaGetRecordFormattedString(hRec, arqDescription, &pwzDescription);
        ExitOnFailure1(hr, "failed to get AddinRegistration.Description for record: %ls", pwzId);

        // Get description
        hr = WcaGetRecordInteger(hRec, arqBitness, &iBitness);
        ExitOnFailure1(hr, "failed to get AddinRegistration.Bitnesss for record: %ls", pwzId);

        // Get description
        hr = WcaGetRecordInteger(hRec, arqCommandLineSafe, &iCommandLineSafe);
        ExitOnFailure1(hr, "failed to get AddinRegistration.CommandLineSafe for record: %ls", pwzId);

        // Get description
        hr = WcaGetRecordInteger(hRec, arqLoadBehavior, &iLoadBehavior);
        ExitOnFailure1(hr, "failed to get AddinRegistration.LoadBehavior for record: %ls", pwzId);

		// get component and its install/action states
        hr = WcaGetRecordString(hRec, arqComponent, &pwzComponent);
        ExitOnFailure(hr, "failed to get addin component id");

        // we need to know if the component's being installed, uninstalled, or reinstalled
        WCA_TODO todo = WcaGetComponentToDo(pwzComponent);

        // skip this entry if this is the install CA and we are uninstalling the component
        if (fInstall && WCA_TODO_UNINSTALL == todo)
        {
            continue;
        }

        // skip this entry if this is an uninstall CA and we are not uninstalling the component
        if (!fInstall && WCA_TODO_UNINSTALL != todo)
        {
            continue;
        }

        // write custom action data: operation, instance guid, path, directory
        hr = WcaWriteIntegerToCaData(todo, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write operation to custom action data for instance id: %ls", pwzId);

        hr = WcaWriteStringToCaData(pwzId, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write id to custom action data for instance id: %ls", pwzId);

        hr = WcaWriteStringToCaData(pwzFile, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write custom action data for instance id: %ls", pwzId);

        hr = WcaWriteStringToCaData(pwzFriendlyName, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write addin name to custom action data for instance id: %ls", pwzId);

        hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write addin description to custom action data for instance id: %ls", pwzId);

        hr = WcaWriteIntegerToCaData(iBitness, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write Bitness to custom action data for instance id: %ls", pwzId);

        hr = WcaWriteIntegerToCaData(iCommandLineSafe, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write CommandLineSafe to custom action data for instance id: %ls", pwzId);

        hr = WcaWriteIntegerToCaData(iLoadBehavior, &pwzCustomActionData);
        ExitOnFailure1(hr, "failed to write LoadBehavior to custom action data for instance id: %ls", pwzId);

		hr = WcaWriteStringToCaData(pwzAllUsers, &pwzCustomActionData);
		ExitOnFailure(hr,  "failed to write allusers property to custom action data for instance id: %ls", pwzId);
	}

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

    ExitOnFailure(hr, "failed while looping through all files to create native images for");

    // Schedule the install custom action
    if (pwzCustomActionData && *pwzCustomActionData)
    {
        WcaLog(LOGMSG_STANDARD, "Scheduling Addin Registration (%ls)", pwzCustomActionData);

        hr = WcaDoDeferredAction(L"RollbackAddinRegistration", pwzCustomActionData, nAddins * COST_REGISTER_ADDIN);
        ExitOnFailure(hr, "Failed to schedule addin registration rollback");

        hr = WcaDoDeferredAction(L"ExecAddinRegistration", pwzCustomActionData, nAddins * COST_REGISTER_ADDIN);
        ExitOnFailure(hr, "Failed to schedule addin registration execution");
    }

LExit:
	ReleaseStr(pwzAllUsers);
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzId);
    ReleaseStr(pwzData);
	ReleaseStr(pwzData);
    ReleaseStr(pwzTemp);
    ReleaseStr(pwzComponent);
    ReleaseStr(pwzFile);
	ReleaseStr(pwzFriendlyName);
	ReleaseStr(pwzDescription);

    return hr;
}
extern "C" UINT WINAPI WixRemoveFoldersEx(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug WixRemoveFoldersEx");

    HRESULT hr = S_OK;
    PMSIHANDLE hView;
    PMSIHANDLE hRec;
    LPWSTR sczId = NULL;
    LPWSTR sczComponent = NULL;
    LPWSTR sczProperty = NULL;
    LPWSTR sczPath = NULL;
    LPWSTR sczExpandedPath = NULL;
    int iMode = 0;
    DWORD dwCounter = 0;
    DWORD_PTR cchLen = 0;
    MSIHANDLE hTable = NULL;
    MSIHANDLE hColumns = NULL;

    hr = WcaInitialize(hInstall, "WixRemoveFoldersEx");
    ExitOnFailure(hr, "Failed to initialize WixRemoveFoldersEx.");

    // anything to do?
    if (S_OK != WcaTableExists(L"WixRemoveFolderEx"))
    {
        WcaLog(LOGMSG_STANDARD, "WixRemoveFolderEx table doesn't exist, so there are no folders to remove.");
        ExitFunction();
    }

    // query and loop through all the remove folders exceptions
    hr = WcaOpenExecuteView(vcsRemoveFolderExQuery, &hView);
    ExitOnFailure(hr, "Failed to open view on WixRemoveFolderEx table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = WcaGetRecordString(hRec, rfqId, &sczId);
        ExitOnFailure(hr, "Failed to get remove folder identity.");

        hr = WcaGetRecordString(hRec, rfqComponent, &sczComponent);
        ExitOnFailure(hr, "Failed to get remove folder component.");

        hr = WcaGetRecordString(hRec, rfqProperty, &sczProperty);
        ExitOnFailure(hr, "Failed to get remove folder property.");

        hr = WcaGetRecordInteger(hRec, feqMode, &iMode);
        ExitOnFailure(hr, "Failed to get remove folder mode");

        hr = WcaGetProperty(sczProperty, &sczPath);
        ExitOnFailure2(hr, "Failed to resolve remove folder property: %S for row: %S", sczProperty, sczId);

        // fail early if the property isn't set as you probably don't want your installers trying to delete SystemFolder
        // StringCchLengthW succeeds only if the string is zero characters plus 1 for the terminating null
        hr = ::StringCchLengthW(sczPath, 1, reinterpret_cast<UINT_PTR*>(&cchLen));
        if (SUCCEEDED(hr))
        {
            ExitOnFailure2(hr = E_INVALIDARG, "Missing folder property: %S for row: %S", sczProperty, sczId);
        }

        hr = PathExpand(&sczExpandedPath, sczPath, PATH_EXPAND_ENVIRONMENT);
        ExitOnFailure2(hr, "Failed to expand path: %S for row: %S", sczPath, sczId);
        
        hr = PathBackslashTerminate(&sczExpandedPath);
        ExitOnFailure1(hr, "Failed to backslash-terminate path: %S", sczExpandedPath);
    
        WcaLog(LOGMSG_STANDARD, "Recursing path: %S for row: %S.", sczExpandedPath, sczId);
        hr = RecursePath(sczExpandedPath, sczId, sczComponent, sczProperty, iMode, &dwCounter, &hTable, &hColumns);
        ExitOnFailure2(hr, "Failed while navigating path: %S for row: %S", sczPath, sczId);
    }

    // reaching the end of the list is actually a good thing, not an error
    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while processing WixRemoveFolderEx table");

LExit:
    if (hColumns)
    {
        ::MsiCloseHandle(hColumns);
    }

    if (hTable)
    {
        ::MsiCloseHandle(hTable);
    }

    ReleaseStr(sczExpandedPath);
    ReleaseStr(sczPath);
    ReleaseStr(sczProperty);
    ReleaseStr(sczComponent);
    ReleaseStr(sczId);

    DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Beispiel #10
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;
}
Beispiel #11
0
static HRESULT ReadXmlConfigTable(
    __inout XML_CONFIG_CHANGE** ppxfcHead,
    __inout XML_CONFIG_CHANGE** ppxfcTail
    )
{
    Assert(ppxfcHead && ppxfcTail);

    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    LPWSTR pwzData = NULL;

    // loop through all the xml configurations
    hr = WcaOpenExecuteView(vcsXmlConfigQuery, &hView);
    ExitOnFailure(hr, "failed to open view on XmlConfig table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = AddXmlConfigChangeToList(ppxfcHead, ppxfcTail);
        ExitOnFailure(hr, "failed to add xml file change to list");

        // Get record Id
        hr = WcaGetRecordString(hRec, xfqXmlConfig, &pwzData);
        ExitOnFailure(hr, "failed to get XmlConfig record Id");
        hr = StringCchCopyW((*ppxfcTail)->wzId, countof((*ppxfcTail)->wzId), pwzData);
        ExitOnFailure(hr, "failed to copy XmlConfig record Id");

        // Get component name
        hr = WcaGetRecordString(hRec, xfqComponent, &pwzData);
        ExitOnFailure1(hr, "failed to get component name for XmlConfig: %ls", (*ppxfcTail)->wzId);

        // Get the component's state
        if (0 < lstrlenW(pwzData))
        {
            hr = StringCchCopyW((*ppxfcTail)->wzComponent, countof((*ppxfcTail)->wzComponent), pwzData);
            ExitOnFailure(hr, "failed to copy component id");

            er = ::MsiGetComponentStateW(WcaGetInstallHandle(), (*ppxfcTail)->wzComponent, &(*ppxfcTail)->isInstalled, &(*ppxfcTail)->isAction);
            ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "failed to get install state for component id");
        }

        // Get the xml file
        hr = WcaGetRecordFormattedString(hRec, xfqFile, &pwzData);
        ExitOnFailure1(hr, "failed to get xml file for XmlConfig: %ls", (*ppxfcTail)->wzId);
        hr = StringCchCopyW((*ppxfcTail)->wzFile, countof((*ppxfcTail)->wzFile), pwzData);
        ExitOnFailure(hr, "failed to copy xml file path");

        // Figure out if the file is already on the machine or if it's being installed
        hr = WcaGetRecordString(hRec, xfqFile, &pwzData);
        ExitOnFailure1(hr, "failed to get xml file for XmlConfig: %ls", (*ppxfcTail)->wzId);
        if (NULL != wcsstr(pwzData, L"[!") || NULL != wcsstr(pwzData, L"[#"))
        {
            (*ppxfcTail)->fInstalledFile = TRUE;
        }

        // Get the XmlConfig table flags
        hr = WcaGetRecordInteger(hRec, xfqXmlFlags, &(*ppxfcTail)->iXmlFlags);
        ExitOnFailure1(hr, "failed to get XmlConfig flags for XmlConfig: %ls", (*ppxfcTail)->wzId);

        // Get the Element Path
        hr = WcaGetRecordFormattedString(hRec, xfqElementPath, &(*ppxfcTail)->pwzElementPath);
        ExitOnFailure1(hr, "failed to get Element Path for XmlConfig: %ls", (*ppxfcTail)->wzId);

        // Get the Verify Path
        hr = WcaGetRecordFormattedString(hRec, xfqVerifyPath, &(*ppxfcTail)->pwzVerifyPath);
        ExitOnFailure1(hr, "failed to get Verify Path for XmlConfig: %ls", (*ppxfcTail)->wzId);

        // Get the name
        hr = WcaGetRecordFormattedString(hRec, xfqName, &pwzData);
        ExitOnFailure1(hr, "failed to get Name for XmlConfig: %ls", (*ppxfcTail)->wzId);
        hr = StringCchCopyW((*ppxfcTail)->wzName, countof((*ppxfcTail)->wzName), pwzData);
        ExitOnFailure(hr, "failed to copy name of element");

        // Get the value
        hr = WcaGetRecordFormattedString(hRec, xfqValue, &pwzData);
        ExitOnFailure1(hr, "failed to get Value for XmlConfig: %ls", (*ppxfcTail)->wzId);
        hr = StrAllocString(&(*ppxfcTail)->pwzValue, pwzData, 0);
        ExitOnFailure(hr, "failed to allocate buffer for value");

        // Get the component attributes
        hr = WcaGetRecordInteger(hRec, xfqCompAttributes, &(*ppxfcTail)->iCompAttributes);
        ExitOnFailure1(hr, "failed to get component attributes for XmlConfig: %ls", (*ppxfcTail)->wzId);
    }

    // if we looped through all records all is well
    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "failed while looping through all objects to secure");

LExit:
    ReleaseStr(pwzData);

    return hr;
}
Beispiel #12
0
/******************************************************************
 SchedSecureObjectsRollback - entry point for SchedSecureObjectsRollback Custom Action

 called as Type 1 CustomAction (binary DLL) from Windows Installer 
 in InstallExecuteSequence before SchedSecureObjects
******************************************************************/
extern "C" UINT __stdcall SchedSecureObjectsRollback(
    __in MSIHANDLE hInstall
    )
{
//    AssertSz(FALSE, "debug SchedSecureObjectsRollback");
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwzSecureObject = NULL;
    LPWSTR pwzTable = NULL;
    LPWSTR pwzTargetPath = NULL;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    LPWSTR pwzCustomActionData = NULL;

    eOBJECTTYPE eType = OT_UNKNOWN;

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

    //
    // loop through all the objects to be secured
    //
    hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView);
    ExitOnFailure(hr, "failed to open view on SecureObjects table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable);
        ExitOnFailure(hr, "failed to get object table");

        eType = EObjectTypeFromString(pwzTable);

        if (OT_UNKNOWN == eType)
        {
            ExitOnFailure1(hr = E_INVALIDARG, "unknown SecureObject.Table: %ls", pwzTable);
        }

        int iCompAttributes = 0;
        hr = WcaGetRecordInteger(hRec, QSO_COMPATTRIBUTES, &iCompAttributes);
        ExitOnFailure(hr, "failed to get Component attributes for secure object");

        BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit;

        // Only process entries in the SecureObjects table whose components match the bitness of this CA
#ifdef _WIN64
        if (!fIs64Bit)
        {
            continue;
        }
#else
        if (fIs64Bit)
        {
            continue;
        }
#endif

        // get the object being secured that we are planning to schedule rollback for
        hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzSecureObject);
        ExitOnFailure(hr, "failed to get name of object");

        hr = GetTargetPath(eType, pwzSecureObject, &pwzTargetPath);
        ExitOnFailure1(hr, "failed to get target path of object '%ls' in order to schedule rollback", pwzSecureObject);

        hr = StoreACLRollbackInfo(pwzTargetPath, pwzTable);
        if (FAILED(hr))
        {
            WcaLog(LOGMSG_STANDARD, "Failed to store ACL rollback information with error 0x%x - continuing", hr);
        }
    }

    // if we looped through all records all is well
    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "failed while looping through all objects to schedule rollback for");

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzSecureObject);
    ReleaseStr(pwzTable);
    ReleaseStr(pwzTargetPath);

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
Beispiel #13
0
/******************************************************************
SchedServiceConfig - entry point for SchedServiceConfig Custom Action

called as Type 1 CustomAction (binary DLL) from Windows Installer 
in InstallExecuteSequence before CaExecServiceConfig
********************************************************************/
extern "C" UINT __stdcall SchedServiceConfig(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug SchedServiceConfig");
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwzScriptKey = NULL;
    LPWSTR pwzCustomActionData = NULL;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;
    LPWSTR pwzData = NULL;
    int iData = 0;
    DWORD cServices = 0;

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

    // Get the script key for this CustomAction and put it on the front of the
    // CustomActionData of the install action.
    hr = WcaCaScriptCreateKey(&pwzScriptKey);
    ExitOnFailure(hr, "Failed to get encoding key.");

    hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData);
    ExitOnFailure(hr, "Failed to add encoding key to CustomActionData.");

    // Loop through all the services to be configured.
    hr = WcaOpenExecuteView(wzQUERY_SERVICECONFIG, &hView);
    ExitOnFailure(hr, "Failed to open view on ServiceConfig table.");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
        INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;

        // Get component name to check if we are installing it. If so
        // then add the table data to the CustomActionData, otherwise
        // skip it.
        hr = WcaGetRecordString(hRec, QSC_COMPONENT, &pwzData);
        ExitOnFailure(hr, "Failed to get component name");

        hr = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction);
        ExitOnFailure1(hr = HRESULT_FROM_WIN32(hr), "Failed to get install state for Component: %ls", pwzData);

        if (WcaIsInstalling(isInstalled, isAction))
        {
            // Add the data to the CustomActionData (for install).
            hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData);
            ExitOnFailure(hr, "Failed to get name of service.");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "Failed to add name to CustomActionData.");

            hr = WcaGetRecordInteger(hRec, QSC_NEWSERVICE, &iData);
            ExitOnFailure(hr, "Failed to get ServiceConfig.NewService.");
            hr = WcaWriteIntegerToCaData(0 != iData, &pwzCustomActionData);
            ExitOnFailure(hr, "Failed to add NewService data to CustomActionData");

            hr = WcaGetRecordString(hRec, QSC_FIRSTFAILUREACTIONTYPE, &pwzData);
            ExitOnFailure(hr, "failed to get first failure action type");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordString(hRec, QSC_SECONDFAILUREACTIONTYPE, &pwzData);
            ExitOnFailure(hr, "failed to get second failure action type");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordString(hRec, QSC_THIRDFAILUREACTIONTYPE, &pwzData);
            ExitOnFailure(hr, "failed to get third failure action type");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordInteger(hRec, QSC_RESETPERIODINDAYS, &iData);
            if (S_FALSE == hr) // deal w/ possible null value
            {
                iData = 0;
            }
            ExitOnFailure(hr, "failed to get reset period in days between service restart attempts.");
            hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordInteger(hRec, QSC_RESTARTSERVICEDELAYINSECONDS, &iData);
            if (S_FALSE == hr) // deal w/ possible null value
            {
                iData = 0;
            }
            ExitOnFailure(hr, "failed to get server restart delay value.");
            hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordFormattedString(hRec, QSC_PROGRAMCOMMANDLINE, &pwzData); // null value already dealt w/ properly
            ExitOnFailure(hr, "failed to get command line to run on service failure.");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordString(hRec, QSC_REBOOTMESSAGE, &pwzData); // null value already dealt w/ properly
            ExitOnFailure(hr, "failed to get message to send to users when server reboots due to service failure.");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            ++cServices;
        }
    }

    // if we looped through all records all is well
    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "failed while looping through all objects to secure");

    // setup CustomActionData and add to progress bar for download
    if (0 < cServices)
    {
        hr = WcaDoDeferredAction(L"RollbackServiceConfig", pwzScriptKey, cServices * COST_SERVICECONFIG);
        ExitOnFailure(hr, "failed to schedule RollbackServiceConfig action");

        hr = WcaDoDeferredAction(L"ExecServiceConfig", pwzCustomActionData, cServices * COST_SERVICECONFIG);
        ExitOnFailure(hr, "failed to schedule ExecServiceConfig action");
    }

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

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Beispiel #14
0
/******************************************************************
 SchedSecureObjects - entry point for SchedSecureObjects Custom Action

 called as Type 1 CustomAction (binary DLL) from Windows Installer 
 in InstallExecuteSequence, to schedule ExecSecureObjects
******************************************************************/
extern "C" UINT __stdcall SchedSecureObjects(
    __in MSIHANDLE hInstall
    )
{
//    AssertSz(FALSE, "debug SchedSecureObjects");
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwzSecureObject = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzTable = NULL;
    LPWSTR pwzTargetPath = NULL;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    INSTALLSTATE isInstalled;
    INSTALLSTATE isAction;

    LPWSTR pwzCustomActionData = NULL;

    DWORD cObjects = 0;
    eOBJECTTYPE eType = OT_UNKNOWN;

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

    // anything to do?
    if (S_OK != WcaTableExists(L"SecureObjects"))
    {
        WcaLog(LOGMSG_STANDARD, "SecureObjects table doesn't exist, so there are no objects to secure.");
        ExitFunction();
    }

    //
    // loop through all the objects to be secured
    //
    hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView);
    ExitOnFailure(hr, "failed to open view on SecureObjects table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable);
        ExitOnFailure(hr, "failed to get object table");

        eType = EObjectTypeFromString(pwzTable);

        if (OT_UNKNOWN == eType)
        {
            ExitOnFailure1(hr = E_INVALIDARG, "unknown SecureObject.Table: %ls", pwzTable);
        }

        int iCompAttributes = 0;
        hr = WcaGetRecordInteger(hRec, QSO_COMPATTRIBUTES, &iCompAttributes);
        ExitOnFailure(hr, "failed to get Component attributes for secure object");

        BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit;

        // Only process entries in the SecureObjects table whose components match the bitness of this CA
#ifdef _WIN64
        if (!fIs64Bit)
        {
            continue;
        }
#else
        if (fIs64Bit)
        {
            continue;
        }
#endif

        // Get the object to secure
        hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzSecureObject);
        ExitOnFailure(hr, "failed to get name of object");

        hr = GetTargetPath(eType, pwzSecureObject, &pwzTargetPath);
        ExitOnFailure1(hr, "failed to get target path of object '%ls'", pwzSecureObject);

        hr = WcaGetRecordString(hRec, QSO_COMPONENT, &pwzData);
        ExitOnFailure(hr, "failed to get Component name for secure object");

        //
        // if we are installing this Component
        //
        er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction);
        ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %ls", pwzData);

        if (WcaIsInstalling(isInstalled, isAction))
        {
            hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            // add the data to the CustomActionData
            hr = WcaGetRecordString(hRec, QSO_SECUREOBJECT, &pwzData);
            ExitOnFailure(hr, "failed to get name of object");

            hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordFormattedString(hRec, QSO_DOMAIN, &pwzData);
            ExitOnFailure(hr, "failed to get domain for user to configure object");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordFormattedString(hRec, QSO_USER, &pwzData);
            ExitOnFailure(hr, "failed to get user to configure object");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            hr = WcaGetRecordString(hRec, QSO_PERMISSION, &pwzData);
            ExitOnFailure(hr, "failed to get permission to configure object");
            hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to add data to CustomActionData");

            ++cObjects;
        }
    }

    // if we looped through all records all is well
    if (E_NOMOREITEMS == hr)
        hr = S_OK;
    ExitOnFailure(hr, "failed while looping through all objects to secure");

    //
    // schedule the custom action and add to progress bar
    //
    if (pwzCustomActionData && *pwzCustomActionData)
    {
        Assert(0 < cObjects);

        hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"ExecSecureObjects"), pwzCustomActionData, cObjects * COST_SECUREOBJECT);
        ExitOnFailure(hr, "failed to schedule ExecSecureObjects action");
    }

LExit:
    ReleaseStr(pwzSecureObject);
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzData);
    ReleaseStr(pwzTable);
    ReleaseStr(pwzTargetPath);

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
Beispiel #15
0
/******************************************************************
 SchedNetFx - entry point for NetFx Custom Action

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

    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    LPWSTR pwzInstallCustomActionData = NULL;
    LPWSTR pwzUninstallCustomActionData = NULL;
    UINT uiCost = 0;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;
    PMSIHANDLE hViewGac = NULL;
    PMSIHANDLE hRecGac = NULL;

    LPWSTR pwzId = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzTemp = NULL;
    LPWSTR pwzFile = NULL;
    int iPriority = 0;
    int iAssemblyCost = 0;
    int iAttributes = 0;
    LPWSTR pwzFileApp = NULL;
    LPWSTR pwzDirAppBase = NULL;
    LPWSTR pwzComponent = NULL;

    INSTALLSTATE isInstalled;
    INSTALLSTATE isAction;

    LPWSTR pwz32Ngen = NULL;
    LPWSTR pwz64Ngen = NULL;

    BOOL f32NgenExeExists = FALSE;
    BOOL f64NgenExeExists = FALSE;

    BOOL fNeedInstallUpdate32 = FALSE;
    BOOL fNeedUninstallUpdate32 = FALSE;
    BOOL fNeedInstallUpdate64 = FALSE;
    BOOL fNeedUninstallUpdate64 = FALSE;

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

    hr = GetNgenPath(&pwz32Ngen, FALSE);
    f32NgenExeExists = SUCCEEDED(hr);
    if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
    {
        hr = ERROR_SUCCESS;
        WcaLog(LOGMSG_STANDARD, "Failed to find 32bit ngen. No actions will be scheduled to create native images for 32bit.");
    }
    ExitOnFailure(hr, "failed to get 32bit ngen.exe path");

    hr = GetNgenPath(&pwz64Ngen, TRUE);
    f64NgenExeExists = SUCCEEDED(hr);
    if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
    {
        hr = ERROR_SUCCESS;
        WcaLog(LOGMSG_STANDARD, "Failed to find 64bit ngen. No actions will be scheduled to create native images for 64bit.");
    }
    ExitOnFailure(hr, "failed to get 64bit ngen.exe path");

    // loop through all the NetFx records
    hr = WcaOpenExecuteView(vcsNgenQuery, &hView);
    ExitOnFailure(hr, "failed to open view on NetFxNativeImage table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // Get Id
        hr = WcaGetRecordString(hRec, ngqId, &pwzId);
        ExitOnFailure(hr, "failed to get NetFxNativeImage.NetFxNativeImage");

        // Get File
        hr = WcaGetRecordString(hRec, ngqFile, &pwzData);
        ExitOnFailure1(hr, "failed to get NetFxNativeImage.File_ for record: %ls", pwzId);
        hr = StrAllocFormatted(&pwzTemp, vpwzUnformattedQuotedFile, pwzData);
        ExitOnFailure1(hr, "failed to format file string for file: %ls", pwzData);
        hr = WcaGetFormattedString(pwzTemp, &pwzFile);
        ExitOnFailure1(hr, "failed to get formatted string for file: %ls", pwzData);

        // Get Priority
        hr = WcaGetRecordInteger(hRec, ngqPriority, &iPriority);
        ExitOnFailure1(hr, "failed to get NetFxNativeImage.Priority for record: %ls", pwzId);

        if (0 == iPriority)
            iAssemblyCost = COST_NGEN_BLOCKING;
        else
            iAssemblyCost = COST_NGEN_NONBLOCKING;

        // Get Attributes
        hr = WcaGetRecordInteger(hRec, ngqAttributes, &iAttributes);
        ExitOnFailure1(hr, "failed to get NetFxNativeImage.Attributes for record: %ls", pwzId);

        // Get File_Application or leave pwzFileApp NULL.
        hr = WcaGetRecordFormattedString(hRec, ngqFileApp, &pwzData);
        ExitOnFailure1(hr, "failed to get NetFxNativeImage.File_Application for record: %ls", pwzId);

        // Check if the value resolves to a valid file ID.
        if (S_OK == FileIdExists(pwzData))
        {
            // Resolve the file ID to a path.
            hr = StrAllocFormatted(&pwzTemp, vpwzUnformattedQuotedFile, pwzData);
            ExitOnFailure1(hr, "failed to format file application string for file: %ls", pwzData);

            hr = WcaGetFormattedString(pwzTemp, &pwzFileApp);
            ExitOnFailure1(hr, "failed to get formatted string for file application: %ls", pwzData);
        }
        else
        {
            // Assume record formatted to a path already.
            hr = StrAllocString(&pwzFileApp, pwzData, 0);
            ExitOnFailure1(hr, "failed to allocate string for file path: %ls", pwzData);

            hr = PathEnsureQuoted(&pwzFileApp, FALSE);
            ExitOnFailure1(hr, "failed to quote file path: %ls", pwzData);
        }

        // Get Directory_ApplicationBase or leave pwzDirAppBase NULL.
        hr = WcaGetRecordFormattedString(hRec, ngqDirAppBase, &pwzData);
        ExitOnFailure1(hr, "failed to get NetFxNativeImage.Directory_ApplicationBase for record: %ls", pwzId);

        if (WcaIsUnicodePropertySet(pwzData))
        {
            // Resolve the directory ID to a path.
            hr = StrAllocFormatted(&pwzTemp, vpwzUnformattedQuotedDirectory, pwzData);
            ExitOnFailure1(hr, "failed to format directory application base string for property: %ls", pwzData);

            hr = WcaGetFormattedString(pwzTemp, &pwzDirAppBase);
            ExitOnFailure1(hr, "failed to get formatted string for directory application base: %ls", pwzData);
        }
        else
        {
            // Assume record formatted to a path already.
            hr = StrAllocString(&pwzDirAppBase, pwzData, 0);
            ExitOnFailure1(hr, "failed to allocate string for directory path: %ls", pwzData);

            hr = PathEnsureQuoted(&pwzDirAppBase, TRUE);
            ExitOnFailure1(hr, "failed to quote and backslashify directory: %ls", pwzData);
        }

        // Get Component
        hr = WcaGetRecordString(hRec, ngqComponent, &pwzComponent);
        ExitOnFailure1(hr, "failed to get NetFxNativeImage.Directory_ApplicationBase for record: %ls", pwzId);
        er = ::MsiGetComponentStateW(hInstall, pwzComponent, &isInstalled, &isAction);
        ExitOnWin32Error1(er, hr, "failed to get install state for Component: %ls", pwzComponent);

        //
        // Figure out if it's going to be GAC'd.  The possibility exists that no assemblies are going to be GAC'd 
        // so we have to check for the MsiAssembly table first.
        //
        if (S_OK == WcaTableExists(L"MsiAssembly"))
        {
            hr = WcaOpenView(vcsNgenGac, &hViewGac);
            ExitOnFailure(hr, "failed to open view on File/MsiAssembly table");

            hr = WcaExecuteView(hViewGac, hRec);
            ExitOnFailure(hr, "failed to execute view on File/MsiAssembly table");

            hr = WcaFetchSingleRecord(hViewGac, &hRecGac);
            ExitOnFailure(hr, "failed to fetch File_Assembly from File/MsiAssembly table");

            if (S_FALSE != hr)
            {
                hr = WcaGetRecordString(hRecGac, nggApplication, &pwzData);
                ExitOnFailure(hr, "failed to get MsiAssembly.File_Application");

                // If it's in the GAC replace the file name with the strong name
                if (L'\0' == pwzData[0])
                {
                    hr = GetStrongName(&pwzFile, pwzComponent);
                    ExitOnFailure1(hr, "failed to get strong name for component: %ls", pwzData);
                }
            }
        }

        //
        // Schedule the work
        //
        if (!(iAttributes & NGEN_32BIT) && !(iAttributes & NGEN_64BIT))
            ExitOnFailure1(hr = E_INVALIDARG, "Neither 32bit nor 64bit is specified for NGEN of file: %ls", pwzFile);

        if (WcaIsInstalling(isInstalled, isAction) || WcaIsReInstalling(isInstalled, isAction))
        {
            if (iAttributes & NGEN_32BIT && f32NgenExeExists)
            {
                // Assemble the install command line
                hr = CreateInstallCommand(&pwzData, pwz32Ngen, pwzFile, iPriority, iAttributes, pwzFileApp, pwzDirAppBase);
                ExitOnFailure(hr, "failed to create install command line");

                hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData);
                ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData);

                hr = WcaWriteIntegerToCaData(iAssemblyCost, &pwzInstallCustomActionData);
                ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData);

                uiCost += iAssemblyCost;

                fNeedInstallUpdate32 = TRUE;
            }

            if (iAttributes & NGEN_64BIT && f64NgenExeExists)
            {
                // Assemble the install command line
                hr = CreateInstallCommand(&pwzData, pwz64Ngen, pwzFile, iPriority, iAttributes, pwzFileApp, pwzDirAppBase);
                ExitOnFailure(hr, "failed to create install command line");

                hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); // command
                ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData);

                hr = WcaWriteIntegerToCaData(iAssemblyCost, &pwzInstallCustomActionData); // cost
                ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData);

                uiCost += iAssemblyCost;

                fNeedInstallUpdate64 = TRUE;
            }
        }
        else if (WcaIsUninstalling(isInstalled, isAction))
        {
            if (iAttributes & NGEN_32BIT && f32NgenExeExists)
            {
                hr = StrAllocFormatted(&pwzData, L"%s uninstall %s", pwz32Ngen, pwzFile);
                ExitOnFailure(hr, "failed to create update 32 command line");

                hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command
                ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData);

                hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost
                ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData);

                uiCost += COST_NGEN_NONBLOCKING;

                fNeedUninstallUpdate32 = TRUE;
            }

            if (iAttributes & NGEN_64BIT && f64NgenExeExists)
            {
                hr = StrAllocFormatted(&pwzData, L"%s uninstall %s", pwz64Ngen, pwzFile);
                ExitOnFailure(hr, "failed to create update 64 command line");

                hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command
                ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData);

                hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost
                ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData);

                uiCost += COST_NGEN_NONBLOCKING;

                fNeedUninstallUpdate64 = TRUE;
            }
        }
    }
    if (E_NOMOREITEMS == hr)
        hr = S_OK;
    ExitOnFailure(hr, "failed while looping through all files to create native images for");

    // If we need 32 bit install update
    if (fNeedInstallUpdate32)
    {
        hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz32Ngen);
        ExitOnFailure(hr, "failed to create install update 32 command line");

        hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); // command
        ExitOnFailure1(hr, "failed to add install command to install custom action data: %ls", pwzData);

        hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzInstallCustomActionData); // cost
        ExitOnFailure1(hr, "failed to add cost to install custom action data: %ls", pwzData);

        uiCost += COST_NGEN_NONBLOCKING;
    }

    // If we need 32 bit uninstall update
    if (fNeedUninstallUpdate32)
    {
        hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz32Ngen);
        ExitOnFailure(hr, "failed to create uninstall update 32 command line");

        hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command
        ExitOnFailure1(hr, "failed to add install command to uninstall custom action data: %ls", pwzData);

        hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost
        ExitOnFailure1(hr, "failed to add cost to uninstall custom action data: %ls", pwzData);

        uiCost += COST_NGEN_NONBLOCKING;
    }

    // If we need 64 bit install update
    if (fNeedInstallUpdate64)
    {
        hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz64Ngen);
        ExitOnFailure(hr, "failed to create install update 64 command line");

        hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); // command
        ExitOnFailure1(hr, "failed to add install command to install custom action data: %ls", pwzData);

        hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzInstallCustomActionData); // cost
        ExitOnFailure1(hr, "failed to add cost to install custom action data: %ls", pwzData);

        uiCost += COST_NGEN_NONBLOCKING;
    }

    // If we need 64 bit install update
    if (fNeedUninstallUpdate64)
    {
        hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz64Ngen);
        ExitOnFailure(hr, "failed to create uninstall update 64 command line");

        hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command
        ExitOnFailure1(hr, "failed to add install command to uninstall custom action data: %ls", pwzData);

        hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost
        ExitOnFailure1(hr, "failed to add cost to uninstall custom action data: %ls", pwzData);

        uiCost += COST_NGEN_NONBLOCKING;
    }

    // Add to progress bar
    if ((pwzInstallCustomActionData && *pwzInstallCustomActionData) || (pwzUninstallCustomActionData && *pwzUninstallCustomActionData))
    {
        hr = WcaProgressMessage(uiCost, TRUE);
        ExitOnFailure(hr, "failed to extend progress bar for NetFxExecuteNativeImage");
    }

    // Schedule the install custom action
    if (pwzInstallCustomActionData && *pwzInstallCustomActionData)
    {
        hr = WcaSetProperty(L"NetFxExecuteNativeImageInstall", pwzInstallCustomActionData);
        ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageInstall action");

        hr = WcaSetProperty(L"NetFxExecuteNativeImageCommitInstall", pwzInstallCustomActionData);
        ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageCommitInstall action");
    }

    // Schedule the uninstall custom action
    if (pwzUninstallCustomActionData && *pwzUninstallCustomActionData)
    {
        hr = WcaSetProperty(L"NetFxExecuteNativeImageUninstall", pwzUninstallCustomActionData);
        ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageUninstall action");

        hr = WcaSetProperty(L"NetFxExecuteNativeImageCommitUninstall", pwzUninstallCustomActionData);
        ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageCommitUninstall action");
    }


LExit:
    ReleaseStr(pwzInstallCustomActionData);
    ReleaseStr(pwzUninstallCustomActionData);
    ReleaseStr(pwzId);
    ReleaseStr(pwzData);
    ReleaseStr(pwzTemp);
    ReleaseStr(pwzFile);
    ReleaseStr(pwzFileApp);
    ReleaseStr(pwzDirAppBase);
    ReleaseStr(pwzComponent);
    ReleaseStr(pwz32Ngen);
    ReleaseStr(pwz64Ngen);

    if (FAILED(hr))
        er = ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Beispiel #16
0
HRESULT ScaWebErrorRead(SCA_WEB_ERROR **ppsweList)
{
//	AssertSz(0, "Debug ScaWebErrorRead here");
	Assert(ppsweList);

	HRESULT hr = S_OK;
	UINT er = 0;
	PMSIHANDLE hView, hRec;
	LPWSTR pwzData = NULL;
	SCA_WEB_ERROR* pswe;

	// bail quickly if the IIsWebError table isn't around
	if (S_OK != WcaTableExists(L"IIsWebError"))
	{
		WcaLog(LOGMSG_VERBOSE, "Skipping ScaGetWebErrors() - required tables not present.");
		ExitFunction1(hr = S_FALSE);
	}

	// loop through all the mimemappings
	hr = WcaOpenExecuteView(vcsWebErrorQuery, &hView);
	ExitOnFailure(hr, "Failed to open view on IIsMimeMap table");
	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		hr = AddWebErrorToList(ppsweList);
		ExitOnFailure(hr, "failed to add mime map to list");

		pswe = *ppsweList;

		hr = WcaGetRecordInteger(hRec, weqErrorCode, &(pswe->iErrorCode));
		ExitOnFailure(hr, "failed to get IIsWebError.ErrorCode");

		hr = WcaGetRecordInteger(hRec, weqSubCode, &(pswe->iSubCode));
		ExitOnFailure(hr, "failed to get IIsWebError.SubCode");

		hr = WcaGetRecordInteger(hRec, weqParentType, &(pswe->iParentType));
		ExitOnFailure(hr, "failed to get IIsWebError.ParentType");

		hr = WcaGetRecordString(hRec, weqParentValue, &pwzData);
		ExitOnFailure(hr, "Failed to get IIsWebError.ParentValue");
		hr = StringCchCopyW(pswe->wzParentValue, countof(pswe->wzParentValue), pwzData);
		ExitOnFailure(hr, "Failed to copy IIsWebError.ParentValue");

		hr = WcaGetRecordFormattedString(hRec, weqFile, &pwzData);
		ExitOnFailure(hr, "Failed to get IIsWebError.File");
		hr = StringCchCopyW(pswe->wzFile, countof(pswe->wzFile), pwzData);
		ExitOnFailure(hr, "Failed to copy IIsWebError.File");

		hr = WcaGetRecordFormattedString(hRec, weqURL, &pwzData);
		ExitOnFailure(hr, "Failed to get IIsWebError.URL");
		hr = StringCchCopyW(pswe->wzURL, countof(pswe->wzURL), pwzData);
		ExitOnFailure(hr, "Failed to copy IIsWebError.URL");

		// If they've specified both a file and a URL, that's invalid
		if (*(pswe->wzFile) && *(pswe->wzURL))
			ExitOnFailure2(hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA), "Both File and URL specified for web error.  File: %S, URL: %S", pswe->wzFile, pswe->wzURL);
	}

	if (E_NOMOREITEMS == hr)
		hr = S_OK;
	ExitOnFailure(hr, "Failure while processing web errors");

LExit:
	ReleaseNullStr(pwzData);

	return hr;
}
/********************************************************************
WixRegisterRestartResources - Immediate CA to register resources with RM.

Enumerates components before InstallValidate and registers resources
to be restarted by Restart Manager if the component action
is anything other than None.

Do not disable file system redirection.

********************************************************************/
extern "C" UINT __stdcall WixRegisterRestartResources(
    __in MSIHANDLE hInstall
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    LPWSTR wzSessionKey = NULL;
    size_t cchSessionKey = 0;
    PRMU_SESSION pSession = NULL;

    LPWSTR wzRestartResource = NULL;
    LPWSTR wzComponent = NULL;
    LPWSTR wzResource = NULL;
    int iAttributes = NULL;
    BOOL fIsComponentNull = FALSE;
    WCA_TODO todo = WCA_TODO_UNKNOWN;
    int iType = etInvalid;

    hr = WcaInitialize(hInstall, "WixRegisterRestartResources");
    ExitOnFailure(hr, "Failed to initialize.");

    // Skip if the table doesn't exist.
    if (S_OK != WcaTableExists(L"WixRestartResource"))
    {
        WcaLog(LOGMSG_STANDARD, "The RestartResource table does not exist; there are no resources to register with Restart Manager.");
        ExitFunction();
    }

    // Get the existing Restart Manager session if available.
    hr = WcaGetProperty(L"MsiRestartManagerSessionKey", &wzSessionKey);
    ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey property.");

    hr = ::StringCchLengthW(wzSessionKey, CCH_SESSION_KEY, &cchSessionKey);
    ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey string length.");

    // Skip if the property doesn't exist.
    if (0 == cchSessionKey)
    {
        WcaLog(LOGMSG_STANDARD, "The MsiRestartManagerSessionKey property is not available to join.");
        ExitFunction();
    }

    // Join the existing Restart Manager session if supported.
    hr = RmuJoinSession(&pSession, wzSessionKey);
    if (E_MODNOTFOUND == hr)
    {
        WcaLog(LOGMSG_STANDARD, "The Restart Manager is not supported on this platform. Skipping.");
        ExitFunction1(hr = S_OK);
    }
    else if (FAILED(hr))
    {
        WcaLog(LOGMSG_STANDARD, "Failed to join the existing Restart Manager session %ls.", wzSessionKey);
        ExitFunction1(hr = S_OK);
    }

    // Loop through each record in the table.
    hr = WcaOpenExecuteView(vcsRestartResourceQuery, &hView);
    ExitOnFailure(hr, "Failed to open a view on the RestartResource table.");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = WcaGetRecordString(hRec, rrqRestartResource, &wzRestartResource);
        ExitOnFailure(hr, "Failed to get the RestartResource field value.");

        hr = WcaGetRecordString(hRec, rrqComponent, &wzComponent);
        ExitOnFailure(hr, "Failed to get the Component_ field value.");

        hr = WcaGetRecordFormattedString(hRec, rrqResource, &wzResource);
        ExitOnFailure(hr, "Failed to get the Resource formatted field value.");

        hr = WcaGetRecordInteger(hRec, rrqAttributes, &iAttributes);
        ExitOnFailure(hr, "Failed to get the Attributes field value.");

        fIsComponentNull = ::MsiRecordIsNull(hRec, rrqComponent);
        todo = WcaGetComponentToDo(wzComponent);

        // Only register resources for components that are null, or being installed, reinstalled, or uninstalled.
        if (!fIsComponentNull && WCA_TODO_UNKNOWN == todo)
        {
            WcaLog(LOGMSG_VERBOSE, "Skipping resource %ls.", wzRestartResource);
            continue;
        }

        // Get the type from Attributes and add to the Restart Manager.
        iType = iAttributes & etTypeMask;
        switch (iType)
        {
        case etFilename:
            WcaLog(LOGMSG_VERBOSE, "Registering file name %ls with the Restart Manager.", wzResource);
            hr = RmuAddFile(pSession, wzResource);
            ExitOnFailure(hr, "Failed to register the file name with the Restart Manager session.");
            break;

        case etApplication:
            WcaLog(LOGMSG_VERBOSE, "Registering process name %ls with the Restart Manager.", wzResource);
            hr = RmuAddProcessesByName(pSession, wzResource);
            ExitOnFailure(hr, "Failed to register the process name with the Restart Manager session.");
            break;

        case etServiceName:
            WcaLog(LOGMSG_VERBOSE, "Registering service name %ls with the Restart Manager.", wzResource);
            hr = RmuAddService(pSession, wzResource);
            ExitOnFailure(hr, "Failed to register the service name with the Restart Manager session.");
            break;

        default:
            WcaLog(LOGMSG_VERBOSE, "The resource type %d for %ls is not supported and will not be registered.", iType, wzRestartResource);
            break;
        }
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failed while looping through all rows to register resources.");

    // Register the resources and unjoin the session.
    hr = RmuEndSession(pSession);
    if (FAILED(hr))
    {
        WcaLog(LOGMSG_VERBOSE, "Failed to register the resources with the Restart Manager.");
        ExitFunction1(hr = S_OK);
    }

LExit:
    ReleaseStr(wzRestartResource);
    ReleaseStr(wzComponent);
    ReleaseStr(wzResource);

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }

    return WcaFinalize(er);
}
Beispiel #18
0
HRESULT ScaSqlStrsReadScripts(
    __inout SCA_SQLSTR** ppsssList,
    __in SCA_ACTION saAction
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;
    PMSIHANDLE hViewBinary, hRecBinary;
    PMSIHANDLE hViewUser, hRecUser;

    LPWSTR pwzComponent = NULL;
    LPWSTR pwzData = NULL;

    BYTE* pbScript = NULL;
    DWORD cbRead = 0;
    DWORD cbScript = 0;
    DWORD cchScript = 0;

    LPWSTR pwzScriptBuffer = NULL;
    WCHAR* pwzScript = NULL;
    WCHAR* pwz;
    DWORD cch = 0;

    SCA_SQLSTR sss;
    SCA_SQLSTR* psss = NULL;

    if (S_OK != WcaTableExists(L"SqlScript") || S_OK != WcaTableExists(L"SqlDatabase") || S_OK != WcaTableExists(L"Binary"))
    {
        WcaLog(LOGMSG_VERBOSE, "Skipping ScaSqlStrsReadScripts() - SqlScripts and/or SqlDatabase table not present");
        ExitFunction1(hr = S_FALSE);
    }

    // open a view on the binary table
    hr = WcaOpenView(vcsSqlBinaryScriptQuery, &hViewBinary);
    ExitOnFailure(hr, "Failed to open view on Binary table for SqlScripts");

    // loop through all the sql scripts
    hr = WcaOpenExecuteView(vcsSqlScriptQuery, &hView);
    ExitOnFailure(hr, "Failed to open view on SqlScript table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
        INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;

        hr = WcaGetRecordString(hRec, sscrqComponent, &pwzComponent);
        ExitOnFailure(hr, "Failed to get Component for SQL Script.");

        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction);
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure1(hr, "Failed to get state for component: %ls", pwzComponent);

        // If we're doing install but the Component is not being installed or we're doing
        // uninstall but the Component is not being uninstalled, skip it.
        if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) ||
            (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction))
        {
            continue;
        }

        ::ZeroMemory(&sss, sizeof(sss));

        sss.isInstalled = isInstalled;
        sss.isAction = isAction;

        hr = WcaGetRecordString(hRec, sscrqSqlScript, &pwzData);
        ExitOnFailure(hr, "Failed to get SqlScript.Script");
        hr = ::StringCchCopyW(sss.wzKey, countof(sss.wzKey), pwzData);
        ExitOnFailure1(hr, "Failed to copy SqlScript.Script: %ls", pwzData);

        // find the database information for this string
        hr = WcaGetRecordString(hRec, sscrqSqlDb, &pwzData);
        ExitOnFailure1(hr, "Failed to get SqlScript.SqlDb_ for SqlScript '%ls'", sss.wzKey);
        hr = ::StringCchCopyW(sss.wzSqlDb, countof(sss.wzSqlDb), pwzData);
        ExitOnFailure1(hr, "Failed to copy SqlScritp.SqlDbb: %ls", pwzData);

        hr = WcaGetRecordInteger(hRec, sscrqAttributes, &sss.iAttributes);
        ExitOnFailure1(hr, "Failed to get SqlScript.Attributes for SqlScript '%ls'", sss.wzKey);

        hr = WcaGetRecordInteger(hRec, sscrqSequence, &sss.iSequence);
        ExitOnFailure1(hr, "Failed to get SqlScript.Sequence for SqlScript '%ls'", sss.wzKey);

        // get the sql script out of the binary stream
        hr = WcaExecuteView(hViewBinary, hRec);
        ExitOnFailure1(hr, "Failed to open SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey);
        hr = WcaFetchSingleRecord(hViewBinary, &hRecBinary);
        ExitOnFailure1(hr, "Failed to fetch SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey);

        // Note: We need to allocate an extra character on the stream to NULL terminate the SQL script.
        //       The WcaGetRecordStream() function won't let us add extra space on the end of the stream
        //       so we'll read the stream "the old fashioned way".
        //hr = WcaGetRecordStream(hRecBinary, ssbsqData, (BYTE**)&pbScript, &cbScript);
        //ExitOnFailure1(hr, "Failed to read SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey);
        er = ::MsiRecordReadStream(hRecBinary, ssbsqData, NULL, &cbRead);
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure(hr, "failed to get size of stream");

        cbScript = cbRead + sizeof(WCHAR); // we may have an ANSI SQL script but leave enough to even NULL terminate a WCHAR string
        hr = WcaAllocStream(&pbScript, cbScript); // this will allocate a fully zeroed out buffer so our string will be NULL terminated
        ExitOnFailure(hr, "failed to allocate data for stream");

        er = ::MsiRecordReadStream(hRecBinary, ssbsqData, reinterpret_cast<char*>(pbScript), &cbRead); //read the buffer but leave the space for the NULL terminator
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure(hr, "failed to read from stream");

        Assert(cbRead + sizeof(WCHAR) == cbScript);

        // Check for the UNICODE BOM file marker.
        if ((0xFF == *pbScript) && (0xFE == *(pbScript + 1)))
        {
            // Copy the UNICODE string after the BOM marker (subtract one because we'll skip the BOM marker).
            cchScript = (cbScript / sizeof(WCHAR)) - 1;

            hr = StrAllocString(&pwzScriptBuffer, reinterpret_cast<LPWSTR>(pbScript) + 1, 0);
            ExitOnFailure1(hr, "Failed to allocate WCHAR string of size '%d'", cchScript);
        }
        else
        {
            // We have an ANSI string so convert it to UNICODE.
            cchScript = cbScript;

            hr = StrAllocStringAnsi(&pwzScriptBuffer, reinterpret_cast<LPCSTR>(pbScript), 0, CP_ACP);
            ExitOnFailure1(hr, "Failed to allocate WCHAR string of size '%d'", cchScript);
        }

        // Free the byte buffer since it has been converted to a new UNICODE string, one way or another.
        if (pbScript)
        {
            WcaFreeStream(pbScript);
            pbScript = NULL;
        }

        // Process the SQL script stripping out unnecessary stuff (like comments) and looking for "GO" statements.
        pwzScript = pwzScriptBuffer;
        while (cchScript && pwzScript && *pwzScript)
        {
            // strip off leading whitespace
            while (cchScript && *pwzScript && iswspace(*pwzScript))
            {
                ++pwzScript;
                --cchScript;
            }

            Assert(0 <= cchScript);

            // if there is a SQL comment remove it
            while (cchScript && L'/' == *pwzScript && L'*' == *(pwzScript + 1))
            {
                // go until end of comment
                while (cchScript && *pwzScript && *(pwzScript + 1) && !(L'*' == *pwzScript && L'/' == *(pwzScript + 1)))
                {
                    ++pwzScript;
                    --cchScript;
                }

                Assert(2 <= cchScript);

                if (2 <= cchScript)
                {
                    // to account for */ at end
                    pwzScript+=2;
                    cchScript-=2;
                }

                Assert(0 <= cchScript);

                // strip off any new leading whitespace
                while (cchScript && *pwzScript && iswspace(*pwzScript))
                {
                    ++pwzScript;
                    --cchScript;
                }
            }

            while (cchScript && L'-' == *pwzScript && L'-' == *(pwzScript + 1))
            {
                // go past the new line character
                while (cchScript && *pwzScript && L'\n' != *pwzScript)
                {
                    ++pwzScript;
                    --cchScript;
                }

                Assert(0 <= cchScript);

                if (cchScript && L'\n' == *pwzScript)
                {
                    ++pwzScript;
                    --cchScript;
                }

                Assert(0 <= cchScript);

                // strip off any new leading whitespace
                while (cchScript && *pwzScript && iswspace(*pwzScript))
                {
                    ++pwzScript;
                    --cchScript;
                }
            }

            Assert(0 <= cchScript);

            // try to isolate a "GO" keyword and count the characters in the SQL string
            pwz = pwzScript;
            cch = 0;
            while (cchScript && *pwz)
            {
                //skip past comment lines that might have "go" in them
                //note that these comments are "in the middle" of our function,
                //or possibly at the end of a line
                if (cchScript && L'-' == *pwz && L'-' == *(pwz + 1))
                {
                    // skip past chars until the new line character
                    while (cchScript && *pwz && (L'\n' != *pwz))
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }
                }

                //skip past comment lines of form /* to */ that might have "go" in them
                //note that these comments are "in the middle" of our function,
                //or possibly at the end of a line
                if (cchScript && L'/' == *pwz && L'*' == *(pwz + 1))
                {
                    // skip past chars until the new line character
                    while (cchScript && *pwz && *(pwz + 1) && !((L'*' == *pwz) && (L'/' == *(pwz + 1))))
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }

                    if (2 <= cchScript)
                    {
                        // to account for */ at end
                        pwz+=2;
                        cch+=2;
                        cchScript-=2;
                    }
                }

                // Skip past strings that may be part of the SQL statement that might have a "go" in them
                if ( cchScript && L'\'' == *pwz )
                {
                    ++pwz;
                    ++cch;
                    --cchScript;

                    // Skip past chars until the end of the string
                    while ( cchScript && *pwz && !(L'\'' == *pwz) )
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }
                }

                // Skip past strings that may be part of the SQL statement that might have a "go" in them
                if ( cchScript && L'\"' == *pwz )
                {
                    ++pwz;
                    ++cch;
                    --cchScript;

                    // Skip past chars until the end of the string
                    while ( cchScript && *pwz && !(L'\"' == *pwz) )
                    {
                        ++pwz;
                        ++cch;
                        --cchScript;
                    }
                }

                // if "GO" is isolated
                if ((pwzScript == pwz || iswspace(*(pwz - 1))) && 
                    (L'G' == *pwz || L'g' == *pwz) && 
                    (L'O' == *(pwz + 1) || L'o' == *(pwz + 1)) &&
                    (0 == *(pwz + 2) || iswspace(*(pwz + 2))))
                {
                    *pwz = 0; // null terminate the SQL string on the "G"
                    pwz += 2;
                    cchScript -= 2;
                    break;   // found "GO" now add SQL string to list
                }

                ++pwz;
                ++cch;
                --cchScript;
            }

            Assert(0 <= cchScript);

            if (0 < cch) //don't process if there's nothing to process
            {
                // replace tabs with spaces
                for (LPWSTR pwzTab = wcsstr(pwzScript, L"\t"); pwzTab; pwzTab = wcsstr(pwzTab, L"\t"))
                    *pwzTab = ' ';

                // strip off whitespace at the end of the script string
                for (LPWSTR pwzErase = pwzScript + cch - 1; pwzScript < pwzErase && iswspace(*pwzErase); pwzErase--)
                {
                    *(pwzErase) = 0;
                    cch--;
                }
            }

            if (0 < cch)
            {
                hr = NewSqlStr(&psss);
                ExitOnFailure(hr, "failed to allocate new sql string element");

                // copy everything over
                hr = ::StringCchCopyW(psss->wzKey, countof(psss->wzKey), sss.wzKey);
                ExitOnFailure(hr, "Failed to copy key string to sqlstr object");
                hr = ::StringCchCopyW(psss->wzSqlDb, countof(psss->wzSqlDb), sss.wzSqlDb);
                ExitOnFailure(hr, "Failed to copy DB string to sqlstr object");
                hr = ::StringCchCopyW(psss->wzComponent, countof(psss->wzComponent), sss.wzComponent);
                ExitOnFailure(hr, "Failed to copy component string to sqlstr object");
                psss->isInstalled = sss.isInstalled;
                psss->isAction = sss.isAction;
                psss->iAttributes = sss.iAttributes;
                psss->iSequence = sss.iSequence;

                // cchRequired includes the NULL terminating char
                hr = StrAllocString(&psss->pwzSql, pwzScript, 0);
                ExitOnFailure1(hr, "Failed to allocate string for SQL script: '%ls'", psss->wzKey);

                *ppsssList = AddSqlStrToList(*ppsssList, psss);
                psss = NULL; // set the db NULL so it doesn't accidentally get freed below
            }

            pwzScript = pwz;
        }
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while reading SqlString table");

LExit:
    // if anything was left over after an error clean it all up
    if (psss)
    {
        ScaSqlStrsFreeList(psss);
    }

    if (pbScript)
    {
        WcaFreeStream(pbScript);
    }

    ReleaseStr(pwzScriptBuffer);
    ReleaseStr(pwzData);
    ReleaseStr(pwzComponent);

    return hr;
}
/******************************************************************
 CaSchedServiceConfig - entry point for CaSchedServiceConfig Custom Action

 called as Type 1 CustomAction (binary DLL) from Windows Installer
 in InstallExecuteSequence before CaExecServiceConfig
********************************************************************/
extern "C" UINT __stdcall SchedServiceConfig(
	__in MSIHANDLE hInstall
	)
{
//	AssertSz(FALSE, "debug SchedServiceConfig");
	HRESULT hr = S_OK;
	UINT uiResult = ERROR_SUCCESS;
	DWORD dwError = 0;

	LPWSTR pwzData = NULL;
	int iData = 0;
	BOOL fExistingService = FALSE;

	PMSIHANDLE hView = NULL;
	PMSIHANDLE hRec = NULL;

	INSTALLSTATE isInstalled;
	INSTALLSTATE isAction;

	SC_HANDLE hSCM = NULL;
	SC_HANDLE hService = NULL;

	LPSERVICE_FAILURE_ACTIONSW psfa;

	LPWSTR pwzCustomActionData = NULL;
	LPWSTR pwzRollbackCustomActionData = NULL;

	DWORD cServices = 0;

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

	DWORD dwSizeNeeded = 0;

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

	//Get a handle to the service control manager
	hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
	if (hSCM == NULL)
		ExitOnLastError(hr, "failed to get handle to SCM");

	// loop through all the services to be configured
	hr = WcaOpenExecuteView(wzQUERY_SERVICECONFIG, &hView);
	ExitOnFailure(hr, "failed to open view on ServiceConfig table");

	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		hr = WcaGetRecordInteger(hRec, QSC_NEWSERVICE, &iData);
		ExitOnFailure(hr, "failed to get object NewService");

		fExistingService = 1 != iData;

		// Get component name
		hr = WcaGetRecordString(hRec, QSC_COMPONENT, &pwzData);
		ExitOnFailure(hr, "failed to get component name");

		// check if we are installing this Component
		hr = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction);
		ExitOnFailure1(hr = HRESULT_FROM_WIN32(hr), "failed to get install state for Component: %S", pwzData);

		// We want to configure either a service we're installing or one already on the box
		if (WcaIsInstalling(isInstalled, isAction))
		{
			// Check if we're configuring an existing service
			if (fExistingService)
			{
				// Confirm the service is actually on the box
				hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData);
				ExitOnFailure(hr, "failed to get object NewService");

				//Get a handle to the service
				hService = ::OpenServiceW(hSCM, pwzData, SERVICE_QUERY_CONFIG);
				if (hService == NULL)
				{
					dwError = ::GetLastError();
					hr = HRESULT_FROM_WIN32(dwError);
					if (hr == ERROR_SERVICE_DOES_NOT_EXIST)
					{
						ExitOnFailure1(hr, "Service \"%s\" does not exist on this system.", pwzData);
					}
					else
					{
						ExitOnFailure1(hr, "Failed to get handle to the service \"%S\".", pwzData);
					}
				}

				// Get Current Service Config info
				if(!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, NULL, 0, &dwSizeNeeded) && ERROR_INSUFFICIENT_BUFFER != ::GetLastError())
				{
					ExitOnLastError(hr, "Failed to get current service config info.");
				}

				// Alloc space we were told we needed
				psfa = (LPSERVICE_FAILURE_ACTIONSW) MemAlloc(dwSizeNeeded, TRUE);
				ExitOnNull(psfa, hr, E_OUTOFMEMORY, "failed to allocate memory for service failure actions.");

				// Now do the real query
				if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)psfa, dwSizeNeeded, &dwSizeNeeded))
					ExitOnLastError(hr, "failed to Query Service.");

				// Build up rollback CA data so we can restore service state if necessary
				hr = WcaWriteStringToCaData(pwzData, &pwzRollbackCustomActionData);
				ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

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

					hr = WcaWriteStringToCaData(c_wzActionTypeNone, &pwzRollbackCustomActionData);
					ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

					hr = WcaWriteStringToCaData(c_wzActionTypeNone, &pwzRollbackCustomActionData);
					ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");
				}
				else
				{
					// psfa actually had actions defined, so use them

					// action 1
					hr = GetSCActionTypeString(psfa->lpsaActions[0].Type, (LPWSTR)wzActionName, 32);
					ExitOnFailure(hr, "failed to query SFA object");

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

					hr = WcaWriteStringToCaData(wzActionName, &pwzRollbackCustomActionData);
					ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

					// action 2
					hr = GetSCActionTypeString(psfa->lpsaActions[1].Type, (LPWSTR)wzActionName, 32);
					ExitOnFailure(hr, "failed to query SFA object");

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

					hr = WcaWriteStringToCaData(wzActionName, &pwzRollbackCustomActionData);
					ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

					// action 3
					hr = GetSCActionTypeString(psfa->lpsaActions[2].Type, (LPWSTR)wzActionName, 32);
					ExitOnFailure(hr, "failed to query SFA object");

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

					hr = WcaWriteStringToCaData(wzActionName, &pwzRollbackCustomActionData);
					ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");
				}

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

				hr = WcaWriteIntegerToCaData(dwRestartDelay, &pwzRollbackCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");

				// check for value being null
				if(!psfa->lpCommand)
					psfa->lpCommand = L"";
				hr = WcaWriteStringToCaData(psfa->lpCommand, &pwzRollbackCustomActionData);
				ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

				// check for value being null
				if(!psfa->lpRebootMsg)
					psfa->lpRebootMsg = L"";
				hr = WcaWriteStringToCaData(psfa->lpRebootMsg, &pwzRollbackCustomActionData);
				ExitOnFailure(hr, "failed to add data to Rollback CustomActionData");

				// Clear up per-service values
				if(psfa)
					MemFree(psfa);
			}

			// add the data to the CustomActionData (for install)
			hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData);
			ExitOnFailure(hr, "failed to get name of service");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSC_FIRSTFAILUREACTIONTYPE, &pwzData);
			ExitOnFailure(hr, "failed to get first failure action type");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSC_SECONDFAILUREACTIONTYPE, &pwzData);
			ExitOnFailure(hr, "failed to get second failure action type");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSC_THIRDFAILUREACTIONTYPE, &pwzData);
			ExitOnFailure(hr, "failed to get third failure action type");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordInteger(hRec, QSC_RESETPERIODINDAYS, &iData);
			if (hr == S_FALSE) // deal w/ possible null value
				iData = 0;
			ExitOnFailure(hr, "failed to get reset period in days between service restart attempts.");
			hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordInteger(hRec, QSC_RESTARTSERVICEDELAYINSECONDS, &iData);
			if (hr == S_FALSE) // deal w/ possible null value
				iData = 0;
			ExitOnFailure(hr, "failed to get server restart delay value.");
			hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSC_PROGRAMCOMMANDLINE, &pwzData); // null value already dealt w/ properly
			ExitOnFailure(hr, "failed to get command line to run on service failure.");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSC_REBOOTMESSAGE, &pwzData); // null value already dealt w/ properly
			ExitOnFailure(hr, "failed to get message to send to users when server reboots due to service failure.");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			cServices++;
			::CloseServiceHandle(hService);
			hService = NULL;
		}
	}

	// if we looped through all records all is well
	if (E_NOMOREITEMS == hr)
		hr = S_OK;
	ExitOnFailure(hr, "failed while looping through all objects to secure");

	// setup CustomActionData and add to progress bar for download
	if (pwzRollbackCustomActionData && *pwzRollbackCustomActionData)
	{
		Assert(0 < cServices);

		hr = WcaDoDeferredAction(L"ExecServiceConfigRollback", pwzRollbackCustomActionData, cServices * COST_SERVICECONFIG);
		ExitOnFailure(hr, "failed to schedule ExecSecureObjects action");
	}

	// schedule the custom action and add to progress bar
	if (pwzCustomActionData && *pwzCustomActionData)
	{
		Assert(0 < cServices);

		hr = WcaDoDeferredAction(L"ExecServiceConfig", pwzCustomActionData, cServices * COST_SERVICECONFIG);
		ExitOnFailure(hr, "failed to schedule ExecSecureObjects action");
	}

LExit:
	// Clean up handles
	if (hService != NULL)
		::CloseServiceHandle(hService);
	if (hSCM != NULL)
		::CloseServiceHandle(hSCM);

	ReleaseStr(pwzCustomActionData);
	ReleaseStr(pwzRollbackCustomActionData);
	ReleaseStr(pwzData);

	if (FAILED(hr))
		uiResult = ERROR_INSTALL_FAILURE;
	return WcaFinalize(uiResult);
}
Beispiel #20
0
HRESULT ScaSqlStrsRead(
    __inout SCA_SQLSTR** ppsssList,
    __in SCA_ACTION saAction
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    PMSIHANDLE hView, hRec;
    PMSIHANDLE hViewUser, hRecUser;

    LPWSTR pwzComponent = NULL;
    LPWSTR pwzData = NULL;

    SCA_SQLSTR* psss = NULL;

    if (S_OK != WcaTableExists(L"SqlString") || S_OK != WcaTableExists(L"SqlDatabase"))
    {
        WcaLog(LOGMSG_VERBOSE, "Skipping ScaSqlStrsRead() - SqlString and/or SqlDatabase table not present");
        ExitFunction1(hr = S_FALSE);
    }

    // loop through all the sql strings
    hr = WcaOpenExecuteView(vcsSqlStringQuery, &hView);
    ExitOnFailure(hr, "Failed to open view on SqlString table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN;
        INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN;

        hr = WcaGetRecordString(hRec, ssqComponent, &pwzComponent);
        ExitOnFailure(hr, "Failed to get Component for SQL String.");

        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction);
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure1(hr, "Failed to get state for component: %ls", pwzComponent);

        // If we're doing install but the Component is not being installed or we're doing
        // uninstall but the Component is not being uninstalled, skip it.
        if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) ||
            (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction))
        {
            continue;
        }

        hr = NewSqlStr(&psss);
        ExitOnFailure(hr, "failed to allocation new sql string element");

        psss->isInstalled = isInstalled;
        psss->isAction = isAction;

        hr = WcaGetRecordString(hRec, ssqSqlString, &pwzData);
        ExitOnFailure(hr, "Failed to get SqlString.String");
        hr = ::StringCchCopyW(psss->wzKey, countof(psss->wzKey), pwzData);
        ExitOnFailure1(hr, "Failed to copy SqlString.String: %ls", pwzData);

        // find the database information for this string
        hr = WcaGetRecordString(hRec, ssqSqlDb, &pwzData);
        ExitOnFailure1(hr, "Failed to get SqlString.SqlDb_ for SqlString '%ls'", psss->wzKey);
        hr = ::StringCchCopyW(psss->wzSqlDb, countof(psss->wzSqlDb), pwzData);
        ExitOnFailure1(hr, "Failed to copy SqlString.SqlDb_: %ls", pwzData);

        hr = WcaGetRecordInteger(hRec, ssqAttributes, &psss->iAttributes);
        ExitOnFailure1(hr, "Failed to get SqlString.Attributes for SqlString '%ls'", psss->wzKey);

        //get the sequence number for the string (note that this will be sequenced with scripts too)
        hr = WcaGetRecordInteger(hRec, ssqSequence, &psss->iSequence);
        ExitOnFailure1(hr, "Failed to get SqlString.Sequence for SqlString '%ls'", psss->wzKey);

        // execute SQL
        hr = WcaGetRecordFormattedString(hRec, ssqSQL, &pwzData);
        ExitOnFailure1(hr, "Failed to get SqlString.SQL for SqlString '%ls'", psss->wzKey);

        Assert(!psss->pwzSql);
        hr = StrAllocString(&psss->pwzSql, pwzData, 0);
        ExitOnFailure1(hr, "Failed to alloc string for SqlString '%ls'", psss->wzKey);

        *ppsssList = AddSqlStrToList(*ppsssList, psss);
        psss = NULL; // set the sss to NULL so it doesn't get freed below
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while reading SqlString table");

LExit:
    // if anything was left over after an error clean it all up
    if (psss)
    {
        ScaSqlStrsFreeList(psss);
    }

    ReleaseStr(pwzData);
    ReleaseStr(pwzComponent);

    return hr;
}
Beispiel #21
0
UINT __stdcall ScaFiltersRead(IMSAdminBase* piMetabase,
							  SCA_WEB* pswList, SCA_FILTER** ppsfList)
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;
	PMSIHANDLE hView, hRec;
	PMSIHANDLE hViewWeb, hRecWeb;

	BOOL fIIsWebFilterTable = FALSE;

	LPWSTR pwzData = NULL;

	SCA_FILTER* psf = NULL;
	DWORD dwLen = 0;

	// check for required table
	if (S_OK != WcaTableExists(L"IIsFilter"))
	{
		WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallFilters() - no IIsFilter table");
		ExitFunction1(hr = S_FALSE);
	}

	// loop through all the filters
	hr = WcaOpenExecuteView(vcsFilterQuery, &hView);
	ExitOnFailure(hr, "Failed to open view on IIsFilter table");
	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		hr = AddFilterToList(ppsfList);
		ExitOnFailure(hr, "failed to add filter to list");

		psf = *ppsfList;

		// get component install state
		hr = WcaGetRecordString(hRec, fqComponent, &pwzData);
		ExitOnFailure(hr, "Failed to get Filter.Component_");
		er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &psf->isInstalled, &psf->isAction);
		hr = HRESULT_FROM_WIN32(er);
		ExitOnFailure(hr, "Failed to get Component state for filter");

		::ZeroMemory(psf->wzFilterRoot, sizeof(psf->wzFilterRoot));

		hr = WcaGetRecordString(hRec, fqWeb, &pwzData);
		ExitOnFailure(hr, "Failed to get Web for VirtualDir");

		if (*pwzData)
		{
			dwLen = countof(psf->wzWebBase);
			hr = ScaWebsGetBase(piMetabase, pswList, pwzData, psf->wzWebBase, &dwLen);
			ExitOnFailure(hr, "Failed to get base of web for Filter");

			StringCchPrintfW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"%s/Filters", psf->wzWebBase);
		}
		else
		{
			StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/LM/W3SVC/Filters");
		}

		// filter key
		hr = WcaGetRecordString(hRec, fqFilter, &pwzData);
		ExitOnFailure(hr, "Failed to get Filter.Filter");
		StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData);

		// filter path
		hr = WcaGetRecordFormattedString(hRec, fqPath, &pwzData);
		ExitOnFailure(hr, "Failed to get Filter.Path");
		StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData);

		// filter description
		hr = WcaGetRecordFormattedString(hRec, fqDescription, &pwzData);
		ExitOnFailure(hr, "Failed to get Filter.Description");
		StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData);

		// filter flags
		hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags);
		ExitOnFailure(hr, "Failed to get Filter.Flags");

		// filter load order
		hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder);
		ExitOnFailure(hr, "Failed to get Filter.LoadOrder");
	}

	if (E_NOMOREITEMS == hr)
		hr = S_OK;
	ExitOnFailure(hr, "Failure while processing filters");

LExit:
	ReleaseStr(pwzData);
	return hr;
}
Beispiel #22
0
HRESULT MqiMessageQueueRead(
    MQI_MESSAGE_QUEUE_LIST* pList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

    MQI_MESSAGE_QUEUE* pItm = NULL;
    LPWSTR pwzData = NULL;

    // loop through all partitions
    hr = WcaOpenExecuteView(vcsMessageQueueQuery, &hView);
    ExitOnFailure(hr, "Failed to execute view on MessageQueue table");

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

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

        // get component install state
        hr = WcaGetRecordString(hRec, mqqComponent, &pwzData);
        ExitOnFailure(hr, "Failed to get component");

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

        // get base priority
        hr = WcaGetRecordInteger(hRec, mqqBasePriority, &pItm->iBasePriority);
        ExitOnFailure(hr, "Failed to get base priority");

        // get journal quota
        hr = WcaGetRecordInteger(hRec, mqqJournalQuota, &pItm->iJournalQuota);
        ExitOnFailure(hr, "Failed to get journal quota");

        // get label
        hr = WcaGetRecordFormattedString(hRec, mqqLabel, &pwzData);
        ExitOnFailure(hr, "Failed to get label");
        StringCchCopyW(pItm->wzLabel, countof(pItm->wzLabel), pwzData);

        // get multicast address
        hr = WcaGetRecordFormattedString(hRec, mqqMulticastAddress, &pwzData);
        ExitOnFailure(hr, "Failed to get multicast address");
        StringCchCopyW(pItm->wzMulticastAddress, countof(pItm->wzMulticastAddress), pwzData);

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

        // get privacy level
        hr = WcaGetRecordInteger(hRec, mqqPrivLevel, &pItm->iPrivLevel);
        ExitOnFailure(hr, "Failed to get privacy level");

        // get quota
        hr = WcaGetRecordInteger(hRec, mqqQuota, &pItm->iQuota);
        ExitOnFailure(hr, "Failed to get quota");

        // get service type guid
        hr = WcaGetRecordFormattedString(hRec, mqqServiceTypeGuid, &pwzData);
        ExitOnFailure(hr, "Failed to get service type guid");
        StringCchCopyW(pItm->wzServiceTypeGuid, countof(pItm->wzServiceTypeGuid), pwzData);

        // get attributes
        hr = WcaGetRecordInteger(hRec, mqqAttributes, &pItm->iAttributes);
        ExitOnFailure(hr, "Failed to get attributes");

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

        // add entry
        pItm->pNext = pList->pFirst;
        pList->pFirst = pItm;
        pItm = NULL;
    }

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

LExit:
    // clean up
    if (pItm)
        ::HeapFree(::GetProcessHeap(), 0, pItm);

    ReleaseStr(pwzData);

    return hr;
}
Beispiel #23
0
HRESULT CpiPartitionUsersRead(
    CPI_PARTITION_LIST* pPartList,
    CPI_PARTITION_USER_LIST* pPartUsrList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

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

    // loop through all partition users
    hr = WcaOpenExecuteView(vcsPartitionUserQuery, &hView);
    ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionUser table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // get component
        hr = WcaGetRecordString(hRec, puqComponent, &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_PARTITION_USER*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_USER));
        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, puqPartitionUser, &pwzData);
        ExitOnFailure(hr, "Failed to get key");
        StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);

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

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

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

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

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

        // set references & increment counters
        if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
        {
            pItm->pPartition->fReferencedForInstall = TRUE;
            pPartUsrList->iInstallCount++;
        }
        if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
        {
            pItm->pPartition->fReferencedForUninstall = TRUE;
            pPartUsrList->iUninstallCount++;
        }

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

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

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

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

    return hr;
}
Beispiel #24
0
HRESULT ScaUserRead(
    __out SCA_USER** ppsuList
    )
{
    //Assert(FALSE);
    Assert(ppsuList);

    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;
    PMSIHANDLE hView, hRec, hUserRec, hUserGroupView;

    LPWSTR pwzData = NULL;

    BOOL fUserGroupExists  = FALSE;

    SCA_USER *psu = NULL;

    INSTALLSTATE isInstalled, isAction;

    if (S_OK != WcaTableExists(L"User"))
    {
        WcaLog(LOGMSG_VERBOSE, "User Table does not exist, exiting");
        ExitFunction1(hr = S_FALSE);
    }

    if (S_OK == WcaTableExists(L"UserGroup"))
    {
        fUserGroupExists = TRUE;
    }

    //
    // loop through all the users
    //
    hr = WcaOpenExecuteView(vActionableQuery, &hView);
    ExitOnFailure(hr, "failed to open view on User table");
    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        hr = WcaGetRecordString(hRec, vaqComponent, &pwzData);
        ExitOnFailure(hr, "failed to get User.Component");

        er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &isInstalled, &isAction);
        hr = HRESULT_FROM_WIN32(er);
        ExitOnFailure(hr, "failed to get Component state for User");

        // don't bother if we aren't installing or uninstalling this component
        if (WcaIsInstalling(isInstalled,  isAction) || WcaIsUninstalling(isInstalled, isAction))
        {
            //
            // Add the user to the list and populate it's values
            //
            hr = AddUserToList(ppsuList);
            ExitOnFailure(hr, "failed to add user to list");

            psu = *ppsuList;

            psu->isInstalled = isInstalled;
            psu->isAction = isAction;
            hr = ::StringCchCopyW(psu->wzComponent, countof(psu->wzComponent), pwzData);
            ExitOnFailure1(hr, "failed to copy component name: %ls", pwzData);

            hr = WcaGetRecordString(hRec, vaqUser, &pwzData);
            ExitOnFailure(hr, "failed to get User.User");
            hr = ::StringCchCopyW(psu->wzKey, countof(psu->wzKey), pwzData);
            ExitOnFailure1(hr, "failed to copy user key: %ls", pwzData);

            hr = WcaGetRecordFormattedString(hRec, vaqName, &pwzData);
            ExitOnFailure(hr, "failed to get User.Name");
            hr = ::StringCchCopyW(psu->wzName, countof(psu->wzName), pwzData);
            ExitOnFailure1(hr, "failed to copy user name: %ls", pwzData);

            hr = WcaGetRecordFormattedString(hRec, vaqDomain, &pwzData);
            ExitOnFailure(hr, "failed to get User.Domain");
            hr = ::StringCchCopyW(psu->wzDomain, countof(psu->wzDomain), pwzData);
            ExitOnFailure1(hr, "failed to copy user domain: %ls", pwzData);

            hr = WcaGetRecordFormattedString(hRec, vaqPassword, &pwzData);
            ExitOnFailure(hr, "failed to get User.Password");
            hr = ::StringCchCopyW(psu->wzPassword, countof(psu->wzPassword), pwzData);
            ExitOnFailure(hr, "failed to copy user password");

            hr = WcaGetRecordInteger(hRec, vaqAttributes, &psu->iAttributes);
            ExitOnFailure(hr, "failed to get User.Attributes"); 

            // Check if this user is to be added to any groups
            if (fUserGroupExists)
            {
                hUserRec = ::MsiCreateRecord(1);
                hr = WcaSetRecordString(hUserRec, 1, psu->wzKey);
                ExitOnFailure(hr, "Failed to create user record for querying UserGroup table");

                hr = WcaOpenView(vcsUserGroupQuery, &hUserGroupView);
                ExitOnFailure1(hr, "Failed to open view on UserGroup table for user %ls", psu->wzKey);
                hr = WcaExecuteView(hUserGroupView, hUserRec);
                ExitOnFailure1(hr, "Failed to execute view on UserGroup table for user: %ls", psu->wzKey);

                while (S_OK == (hr = WcaFetchRecord(hUserGroupView, &hRec)))
                {
                    hr = WcaGetRecordString(hRec, vugqGroup, &pwzData);
                    ExitOnFailure(hr, "failed to get UserGroup.Group");

                    hr = AddGroupToList(&(psu->psgGroups));
                    ExitOnFailure(hr, "failed to add group to list");

                    hr = ScaGetGroup(pwzData, psu->psgGroups);
                    ExitOnFailure1(hr, "failed to get information for group: %ls", pwzData);
                }

                if (E_NOMOREITEMS == hr)
                {
                    hr = S_OK;
                }
                ExitOnFailure(hr, "failed to enumerate selected rows from UserGroup table");
            }
        }
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "failed to enumerate selected rows from User table");

LExit:
    ReleaseStr(pwzData);

    return hr;
}
Beispiel #25
0
static HRESULT MessageQueueTrusteePermissionsRead(
    LPCWSTR pwzQuery,
    MQI_MESSAGE_QUEUE_LIST* pMessageQueueList,
    MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

    LPWSTR pwzData = NULL;

    MQI_MESSAGE_QUEUE_PERMISSION* pItm = NULL;

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

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

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

        // get component
        hr = WcaGetRecordString(hRec, mqpqComponent, &pwzData);
        ExitOnFailure(hr, "Failed to get component");

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

        // get message queue
        hr = WcaGetRecordString(hRec, mqpqMessageQueue, &pwzData);
        ExitOnFailure(hr, "Failed to get application role");

        hr = MqiMessageQueueFindByKey(pMessageQueueList, pwzData, &pItm->pMessageQueue);
        if (S_FALSE == hr)
            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
        ExitOnFailure(hr, "Failed to find message queue, key: %S", pwzData);

        // get user domain
        hr = WcaGetRecordFormattedString(hRec, mqpqDomain, &pwzData);
        ExitOnFailure(hr, "Failed to get domain");
        StringCchCopyW(pItm->wzDomain, countof(pItm->wzDomain), pwzData);

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

        // get permissions
        hr = WcaGetRecordInteger(hRec, mqpqPermissions, &pItm->iPermissions);
        ExitOnFailure(hr, "Failed to get permissions");

        // set references & increment counters
        if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
            pList->iInstallCount++;
        if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
            pList->iUninstallCount++;

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

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

LExit:
    // clean up
    ReleaseStr(pwzData);

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

    return hr;
}
Beispiel #26
0
HRESULT ScaWebsRead(
	__in IMSAdminBase* piMetabase,
	__in SCA_WEB** ppswList,
	__in SCA_HTTP_HEADER** ppshhList,
	__in SCA_WEB_ERROR** ppsweList
	)
{
	Assert(piMetabase && ppswList);

	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	BOOL fIIsWebSiteTable = FALSE;
	BOOL fIIsWebAddressTable = FALSE;
	BOOL fIIsWebApplicationTable = FALSE;

	PMSIHANDLE hView, hRec;
	PMSIHANDLE hViewAddresses, hRecAddresses;
	PMSIHANDLE hViewApplications, hRecApplications;

	SCA_WEB* psw = NULL;
	LPWSTR pwzData = NULL;

	DWORD dwLen = 0;

	// check to see what tables are available
	fIIsWebSiteTable = (S_OK == WcaTableExists(L"IIsWebSite"));
	fIIsWebAddressTable = (S_OK == WcaTableExists(L"IIsWebAddress"));
	fIIsWebApplicationTable = (S_OK == WcaTableExists(L"IIsWebApplication"));

	if (!fIIsWebSiteTable || !fIIsWebAddressTable)
	{
		WcaLog(LOGMSG_VERBOSE, "Required tables not present");
		hr = S_FALSE;
		goto LExit;
	}

	// open the view on webs' addresses
	hr = WcaOpenView(vcsWebAddressQuery, &hViewAddresses);
	ExitOnFailure(hr, "Failed to open view on IIsWebAddress table");

	// open the view on webs' applications
	if (fIIsWebApplicationTable)
	{
		hr = WcaOpenView(vcsWebApplicationQuery, &hViewApplications);
		ExitOnFailure(hr, "Failed to open view on IIsWebApplication table");
	}

	// loop through all the webs
	hr = WcaOpenExecuteView(vcsWebQuery, &hView);
	ExitOnFailure(hr, "Failed to execute view on IIsWebSite table");
	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		psw = NewWeb();
		if (!psw)
		{
			hr = E_OUTOFMEMORY;
			break;
		}

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

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

			er = ::MsiGetComponentStateW(WcaGetInstallHandle(), psw->wzComponent, &psw->isInstalled, &psw->isAction);
			hr = HRESULT_FROM_WIN32(er);
			ExitOnFailure(hr, "Failed to get web Component state");
		}

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

		hr = WcaGetRecordFormattedString(hRec, wqIP, &pwzData);
		ExitOnFailure(hr, "Failed to get IP for Web");
		StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData);

		hr = WcaGetRecordFormattedString(hRec, wqPort, &pwzData);
		ExitOnFailure(hr, "Failed to get Web Address port");
		psw->swaKey.iPort = wcstol(pwzData, NULL, 10);
		if (0 == psw->swaKey.iPort)
			ExitOnFailure1(hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA), "invalid port provided for web site: %S", psw->wzDescription);

		hr = WcaGetRecordFormattedString(hRec, wqHeader, &pwzData);
		ExitOnFailure(hr, "Failed to get Header for Web");
		StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData);

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

		// TODO: fix this to look for the description as well (or is address enough)?
		// find the web root
		dwLen = METADATA_MAX_NAME_LEN;
		hr = ScaWebFindBase(piMetabase, *ppswList,
							psw->wzKey,
							psw->swaKey.wzIP,
							psw->swaKey.iPort,
							psw->swaKey.wzHeader,
							psw->swaKey.fSecure,
							psw->wzWebBase, &dwLen);
		if (S_OK == hr)
		{
			psw->fBaseExists = TRUE;
		}
		else if (S_FALSE == hr && FALSE == psw->fHasComponent) // if we're not installing it, fail if it wasn't found
		{
			ExitOnFailure1(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "failed to find web site: '%S'", psw->wzKey);
		}
		else if (S_FALSE == hr)
		{
			dwLen = METADATA_MAX_NAME_LEN;
			hr = ScaWebFindFreeBase(piMetabase, *ppswList, psw->wzWebBase, dwLen);
			psw->fBaseExists = FALSE;
		}
		ExitOnFailure(hr, "Failed to find web root");

		// get any extra web addresses
		hr = WcaExecuteView(hViewAddresses, hRec);
		ExitOnFailure(hr, "Failed to execute view on extra IIsWebAddress table");
		while (S_OK == (hr = WcaFetchRecord(hViewAddresses, &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))
			{
				StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey,
					countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData);

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

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

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

				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");

		// get the web's description
		hr = WcaGetRecordFormattedString(hRec, wqDescription, &pwzData);
		ExitOnFailure(hr, "Failed to get Description for Web");
		StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData);

		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
			hr = WcaGetRecordString(hRec, wqDirectory, &pwzData);
			ExitOnFailure(hr, "Failed to get Directory for Web");

			WCHAR wzPath[MAX_PATH];
			dwLen = countof(wzPath);
			if (INSTALLSTATE_SOURCE == psw->isAction)
				er = ::MsiGetSourcePathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen);
			else
				er = ::MsiGetTargetPathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen);
			hr = HRESULT_FROM_WIN32(er);
			ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory");

			if (dwLen > countof(wzPath))
			{
				hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
				ExitOnFailure(hr, "Failed because Source/TargetPath for Directory was greater than MAX_PATH.");
			}

			// remove traling backslash
			if (dwLen > 0 && wzPath[dwLen-1] == L'\\')
				wzPath[dwLen-1] = 0;
			StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), wzPath);
		}

		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 properties for Web");
		if (*pwzData)
		{
			hr = ScaGetWebDirProperties(pwzData, &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, &psw->swapp);
			ExitOnFailure(hr, "Failed to get application for Web");

			psw->fHasApplication = TRUE;
		}

		// get the SSL certificates
		hr = ScaSslCertificateRead(psw->wzKey, &(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, &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
	if (psw)
		ScaWebsFreeList(psw);

	ReleaseStr(pwzData);

	return hr;
}
Beispiel #27
0
static HRESULT TrusteesInApplicationRolesRead(
    LPCWSTR pwzQuery,
    CPI_APPLICATION_ROLE_LIST* pAppRoleList,
    CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

    CPI_USER_IN_APPLICATION_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, tiarqComponent, &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_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_APPLICATION_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, tiarqUserInApplicationRole, &pwzData);
        ExitOnFailure(hr, "Failed to get key");
        StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);

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

        hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole);
        if (S_FALSE == hr)
            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
        ExitOnFailure1(hr, "Failed to find application role, key: %S", pwzData);

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

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

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

        // set references & increment counters
        if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
        {
            CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole);
            pUsrInAppRoleList->iInstallCount++;
        }
        if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
        {
            CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole);
            pUsrInAppRoleList->iUninstallCount++;
        }

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

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

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

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

    return hr;
}
Beispiel #28
0
HRESULT CpiApplicationRolesRead(
    CPI_APPLICATION_LIST* pAppList,
    CPI_APPLICATION_ROLE_LIST* pAppRoleList
    )
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    PMSIHANDLE hView, hRec;

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

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

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

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

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

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

        // get component install state
        if (pwzData && *pwzData)
        {
            pItm->fHasComponent = TRUE;

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

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

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

        hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication);
        if (S_FALSE == hr)
            hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
        ExitOnFailure1(hr, "Failed to find application, key: %S", pwzData);

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

        // get properties
        if (CpiTableExists(cptComPlusApplicationRoleProperty))
        {
            hr = CpiPropertiesRead(vcsApplicationRolePropertyQuery, pItm->wzKey, pdlApplicationRoleProperties, &pItm->pProperties, &pItm->iPropertyCount);
            ExitOnFailure(hr, "Failed to get properties");
        }

        // set references & increment counters
        if (pItm->fHasComponent)
        {
            if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
            {
                CpiApplicationAddReferenceInstall(pItm->pApplication);
                pAppRoleList->iInstallCount++;
            }
            if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
            {
                CpiApplicationAddReferenceUninstall(pItm->pApplication);
                pAppRoleList->iUninstallCount++;
            }
        }

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

    if (E_NOMOREITEMS == hr)
        hr = S_OK;

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

    ReleaseStr(pwzData);

    return hr;
}
Beispiel #29
0
/******************************************************************
 WixSchedInternetShortcuts - entry point

********************************************************************/
extern "C" UINT __stdcall WixSchedInternetShortcuts(
    __in MSIHANDLE hInstall
)
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    UINT uiCost = 0;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    MSIHANDLE hCreateFolderTable = NULL;
    MSIHANDLE hCreateFolderColumns = NULL;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzComponent = NULL;
    LPWSTR pwzDirectory = NULL;
    LPWSTR pwzFilename = NULL;
    LPWSTR pwzTarget = NULL;
    LPWSTR pwzShortcutPath = NULL;
    int iAttr = 0;
    LPWSTR pwzIconFile = NULL;
    int iIconIndex = 0;
    IUniformResourceLocatorW* piURL = NULL;
    IShellLinkW* piShellLink = NULL;
    BOOL fInitializedCom = FALSE;

    hr = WcaInitialize(hInstall, "WixSchedInternetShortcuts");
    ExitOnFailure(hr, "failed to initialize WixSchedInternetShortcuts.");

    // anything to do?
    if (S_OK != WcaTableExists(L"WixInternetShortcut"))
    {
        WcaLog(LOGMSG_STANDARD, "WixInternetShortcut table doesn't exist, so there are no Internet shortcuts to process");
        goto LExit;
    }

    // check to see if we can create a shortcut - Server Core and others may not have a shell registered.  
    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "failed to initialize COM");
    fInitializedCom = TRUE;

    hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL);
    if (S_OK != hr)
    {
        WcaLog(LOGMSG_STANDARD, "failed to create an instance of IUniformResourceLocatorW, skipping shortcut creation");
        ExitFunction1(hr = S_OK);
    }

    hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink);
    if (S_OK != hr)
    {
        WcaLog(LOGMSG_STANDARD, "failed to create an instance of IShellLinkW, skipping shortcut creation");
        ExitFunction1(hr = S_OK);
    }

    // query and loop through all the shortcuts
    hr = WcaOpenExecuteView(vcsShortcutsQuery, &hView);
    ExitOnFailure(hr, "failed to open view on WixInternetShortcut table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // read column values
        hr = WcaGetRecordString(hRec, esqComponent, &pwzComponent);
        ExitOnFailure(hr, "failed to get shortcut component");
        hr = WcaGetRecordString(hRec, esqDirectory, &pwzDirectory);
        ExitOnFailure(hr, "failed to get shortcut directory");
        hr = WcaGetRecordString(hRec, esqFilename, &pwzFilename);
        ExitOnFailure(hr, "failed to get shortcut filename");
        hr = WcaGetRecordFormattedString(hRec, esqTarget, &pwzTarget);
        ExitOnFailure(hr, "failed to get shortcut target");
        hr = WcaGetRecordInteger(hRec, esqAttributes, &iAttr);
        ExitOnFailure(hr, "failed to get shortcut attributes");
        hr = WcaGetRecordFormattedString(hRec, esqIconFile, &pwzIconFile);
        ExitOnFailure(hr, "failed to get shortcut icon file");
        hr = WcaGetRecordInteger(hRec, esqIconIndex, &iIconIndex);
        ExitOnFailure(hr, "failed to get shortcut icon index");

        // skip processing this WixInternetShortcut row if the component isn't being configured
        WCA_TODO todo = WcaGetComponentToDo(pwzComponent);
        if (WCA_TODO_UNKNOWN == todo)
        {
            WcaLog(LOGMSG_VERBOSE, "Skipping shortcut for null-action component '%ls'", pwzComponent);
            continue;
        }

        // we need to create the directory where the shortcut is supposed to live; rather
        // than doing so in our deferred custom action, use the CreateFolder table to have MSI 
        // make (and remove) them on our behalf (including the correct cleanup of parent directories).
        MSIDBERROR dbError = MSIDBERROR_NOERROR;
        WcaLog(LOGMSG_STANDARD, "Adding folder '%ls', component '%ls' to the CreateFolder table", pwzDirectory, pwzComponent);
        hr = WcaAddTempRecord(&hCreateFolderTable, &hCreateFolderColumns, L"CreateFolder", &dbError, 0, 2, pwzDirectory, pwzComponent);
        if (MSIDBERROR_DUPLICATEKEY == dbError)
        {
            WcaLog(LOGMSG_STANDARD, "Folder '%ls' already exists in the CreateFolder table; the above error is harmless", pwzDirectory);
            hr = S_OK;
        }
        ExitOnFailure(hr, "Couldn't add temporary CreateFolder row");

        // only if we're installing/reinstalling do we need to schedule the deferred CA
        // (uninstallation is handled via permanent RemoveFile rows and temporary CreateFolder rows)
        if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo)
        {
            // turn the Directory_ id into a path
            hr = WcaGetTargetPath(pwzDirectory, &pwzShortcutPath);
            ExitOnFailure(hr, "failed to allocate string for shortcut directory");

            // append the shortcut filename
            hr = StrAllocConcat(&pwzShortcutPath, pwzFilename, 0);
            ExitOnFailure(hr, "failed to allocate string for shortcut filename");

            // write the shortcut path and target to custom action data for deferred CAs
            hr = WcaWriteStringToCaData(pwzShortcutPath, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write shortcut path to custom action data");
            hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write shortcut target to custom action data");
            hr = WcaWriteIntegerToCaData(iAttr, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write shortcut attributes to custom action data");
            hr = WcaWriteStringToCaData(pwzIconFile, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write icon file to custom action data");
            hr = WcaWriteIntegerToCaData(iIconIndex, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write icon index to custom action data");

            uiCost += COST_INTERNETSHORTCUT;
        }
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while processing WixInternetShortcut table");

    // if we have any shortcuts to install
    if (pwzCustomActionData && *pwzCustomActionData)
    {
        // add cost to progress bar
        hr = WcaProgressMessage(uiCost, TRUE);
        ExitOnFailure(hr, "failed to extend progress bar for InternetShortcuts");

        // provide custom action data to deferred and rollback CAs
        hr = WcaSetProperty(PLATFORM_DECORATION(L"WixRollbackInternetShortcuts"), pwzCustomActionData);
        ExitOnFailure(hr, "failed to set WixRollbackInternetShortcuts rollback custom action data");
        hr = WcaSetProperty(PLATFORM_DECORATION(L"WixCreateInternetShortcuts"), pwzCustomActionData);
        ExitOnFailure(hr, "failed to set WixCreateInternetShortcuts custom action data");
    }

LExit:
    if (hCreateFolderTable)
    {
        ::MsiCloseHandle(hCreateFolderTable);
    }

    if (hCreateFolderColumns)
    {
        ::MsiCloseHandle(hCreateFolderColumns);
    }

    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzComponent);
    ReleaseStr(pwzDirectory);
    ReleaseStr(pwzFilename);
    ReleaseStr(pwzTarget);
    ReleaseStr(pwzShortcutPath);
    ReleaseObject(piShellLink);
    ReleaseObject(piURL);

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

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Beispiel #30
0
HRESULT __stdcall ScaVirtualDirsRead(
	__in IMSAdminBase* piMetabase,
	__in SCA_WEB* pswList,
	__in SCA_VDIR** ppsvdList,
	__in SCA_MIMEMAP** ppsmmList,
	__in SCA_HTTP_HEADER** ppshhList,
	__in SCA_WEB_ERROR** ppsweList
	)
{
	Assert(piMetabase && ppsvdList);

	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;
	PMSIHANDLE hView, hRec;

	SCA_VDIR* pvdir = NULL;
	LPWSTR pwzData = NULL;
	DWORD cchData = 0;

	DWORD dwLen = 0;

	// check to see if necessary tables are specified
	if (S_OK != WcaTableExists(L"IIsWebVirtualDir"))
	{
		WcaLog(LOGMSG_VERBOSE, "Skipping ScaIntsallVirtualDirs() because IIsWebVirtualDir table not present");
		hr = S_FALSE;
		goto LExit;
	}

	// loop through all the vdirs
	hr = WcaOpenExecuteView(vcsVDirQuery, &hView);
	ExitOnFailure(hr, "Failed to open view on IIsWebVirtualDir table");
	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		hr = AddVirtualDirToList(ppsvdList);
		ExitOnFailure(hr, "failed to add virtual dir to list");

		pvdir = *ppsvdList;

		// get component install state
		hr = WcaGetRecordString(hRec, vdqComponent, &pwzData);
		ExitOnFailure(hr, "Failed to get Component for VirtualDirs");

		er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pvdir->isInstalled, &pvdir->isAction);
		hr = HRESULT_FROM_WIN32(er);
		ExitOnFailure(hr, "Failed to get Component state for VirtualDirs");

		// get the web key
		hr = WcaGetRecordString(hRec, vdqWeb, &pwzData);
		ExitOnFailure(hr, "Failed to get Web for VirtualDir");

		dwLen = countof(pvdir->wzWebBase);
		hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pvdir->wzWebBase, &dwLen);
		ExitOnFailure1(hr, "Failed to get base of web: %S for VirtualDir", pwzData);

		hr = WcaGetRecordFormattedString(hRec, vdqAlias, &pwzData);
		ExitOnFailure(hr, "Failed to get Alias for VirtualDir");

		hr = StringCchPrintfW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), L"%s/Root/%s", pvdir->wzWebBase, pwzData);
		ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir");

		// get the vdir's directory
		hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData);
		ExitOnFailure(hr, "Failed to get Directory for VirtualDir");

		WCHAR wzTargetPath[MAX_PATH];
		dwLen = countof(wzTargetPath);
		if (INSTALLSTATE_SOURCE == pvdir->isAction)
			er = ::MsiGetSourcePathW(WcaGetInstallHandle(), pwzData, wzTargetPath, &dwLen);
		else
			er = ::MsiGetTargetPathW(WcaGetInstallHandle(), pwzData, wzTargetPath, &dwLen);
		hr = HRESULT_FROM_WIN32(er);
		ExitOnFailure(hr, "Failed to get TargetPath for Directory for VirtualDir");
		// remove trailing backslash(es)
		while (dwLen > 0 && wzTargetPath[dwLen-1] == L'\\')
		{
			wzTargetPath[dwLen-1] = L'\0';
			dwLen--;
		}
		StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), wzTargetPath);

		// get the security information for this web
		hr = WcaGetRecordString(hRec, vdqProperties, &pwzData);
		ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir");
		if (*pwzData)
		{
			hr = ScaGetWebDirProperties(pwzData, &pvdir->swp);
			ExitOnFailure(hr, "Failed to get web directory for VirtualDir");

			pvdir->fHasProperties = TRUE;
		}

		// get the application information for this web
		hr = WcaGetRecordString(hRec, vdqApplication, &pwzData);
		ExitOnFailure(hr, "Failed to get application identifier for VirtualDir");
		if (*pwzData)
		{
			hr = ScaGetWebApplication(NULL, pwzData, &pvdir->swapp);
			ExitOnFailure(hr, "Failed to get application for VirtualDir");

			pvdir->fHasApplication = TRUE;
		}

		hr = WcaGetRecordString(hRec, vdqVDir, &pwzData);
		ExitOnFailure(hr, "Failed to get VDir for VirtualDir");

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

		if (*pwzData && *ppshhList)
		{
			hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh);
			ExitOnFailure1(hr, "Failed to get custom HTTP headers for VirtualDir: %S", pwzData);
		}

		if (*pwzData && *ppsweList)
		{
			hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe);
			ExitOnFailure1(hr, "Failed to get custom web errors for VirtualDir: %S", pwzData);
		}
	}

	if (E_NOMOREITEMS == hr)
		hr = S_OK;
	ExitOnFailure(hr, "Failure while processing VirtualDirs");

LExit:
	ReleaseStr(pwzData);
	return hr;
}