예제 #1
0
/********************************************************************
 ComPlusPrepare - CUSTOM ACTION ENTRY POINT

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

	LPWSTR pwzData = NULL;

	HANDLE hRollbackFile = INVALID_HANDLE_VALUE;

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

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

	// create rollback file
	hRollbackFile = ::CreateFileW(pwzData, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL);
	if (INVALID_HANDLE_VALUE == hRollbackFile)
		ExitOnFailure1(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to create rollback file, name: %S", pwzData);

	hr = S_OK;

LExit:
	// clean up
	ReleaseStr(pwzData);

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

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
예제 #2
0
/********************************************************************
 ComPlusCleanup - CUSTOM ACTION ENTRY POINT

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

	LPWSTR pwzData = NULL;

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

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

	// delete rollback file
	if (!::DeleteFileW(pwzData))
	{
		// error, but not a showstopper
		hr = HRESULT_FROM_WIN32(::GetLastError());
		WcaLog(LOGMSG_STANDARD, "Failed to delete rollback file, hr: 0x%x, name: %S", hr, pwzData);
	}

	hr = S_OK;

LExit:
	// clean up
	ReleaseStr(pwzData);

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
예제 #3
0
파일: netfxca.cpp 프로젝트: 925coder/wix3
/******************************************************************
 ExecNetFx - entry point for NetFx Custom Action

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

    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

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

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

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

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

    pwz = pwzCustomActionData;

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

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

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

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

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

    if (FAILED(hr))
        er = ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
예제 #4
0
파일: netfxca.cpp 프로젝트: 925coder/wix3
// Gets the path to ngen.exe
static HRESULT GetNgenPath(
    __out LPWSTR* ppwzNgenPath,
    __in BOOL f64BitFramework
    )
{
    Assert(ppwzNgenPath);
    HRESULT hr = S_OK;

    LPWSTR pwzVersion = NULL;
    LPWSTR pwzWindowsFolder = NULL;

    hr = WcaGetProperty(L"WindowsFolder", &pwzWindowsFolder);
    ExitOnFailure(hr, "failed to get WindowsFolder property");

    hr = StrAllocString(ppwzNgenPath, pwzWindowsFolder, 0);
    ExitOnFailure1(hr, "failed to copy to NgenPath windows folder: %ls", pwzWindowsFolder);

    if (f64BitFramework)
    {
        WcaLog(LOGMSG_VERBOSE, "Searching for ngen under 64-bit framework path");

        hr = StrAllocConcat(ppwzNgenPath, L"Microsoft.NET\\Framework64\\", 0);
        ExitOnFailure(hr, "failed to copy platform portion of ngen path");
    }
    else
    {
        WcaLog(LOGMSG_VERBOSE, "Searching for ngen under 32-bit framework path");

        hr = StrAllocConcat(ppwzNgenPath, L"Microsoft.NET\\Framework\\", 0);
        ExitOnFailure(hr, "failed to copy platform portion of ngen path");
    }

    // We want to run the highest version of ngen possible, because they should be backwards compatible - so let's find the most appropriate directory now
    hr = GetNgenVersion(*ppwzNgenPath, &pwzVersion);
    ExitOnFailure1(hr, "failed to search for ngen under path %ls", *ppwzNgenPath);

    hr = StrAllocConcat(ppwzNgenPath, pwzVersion, 0);
    ExitOnFailure(hr, "failed to copy version portion of ngen path");

    hr = StrAllocConcat(ppwzNgenPath, L"\\ngen.exe", 0);
    ExitOnFailure(hr, "failed to copy \"\\ngen.exe\" portion of ngen path");

LExit:
    ReleaseStr(pwzVersion);
    ReleaseStr(pwzWindowsFolder);

    return hr;
}
예제 #5
0
/******************************************************************
 WixRollbackInternetShortcuts - entry point for Internet shortcuts
    custom action (rollback)
*******************************************************************/
extern "C" UINT __stdcall WixRollbackInternetShortcuts(
    __in MSIHANDLE hInstall
)
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

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

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

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

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

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

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

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

    er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er;
    return WcaFinalize(er);
}
예제 #6
0
/**
 *  Sets up logging for MSIs and then calls the appropriate custom action with argc/argv parameters.
 * 
 *  MSI deferred custom action dlls have to handle parameters (properties) a little differently,
 *  since the deferred action may not have an active session when it begins.  Since the easiest
 *  way to pass parameter(s) is to put them all into a CustomActionData property and then retrieve it,
 *  the easiest thing to do on this ( C/C++ ) end is to pull the parameter and then split it into
 *  a list of parameter(s) that we need.
 * 
 *  For this implementation, it made sense to treat the single string provided in CustomActionData
 *  as if it were a command line, and then parse it out just as if it were a command line.  Obviously,
 *  the "program name" isn't going to be the first argument unless the MSI writer is pedantic, but
 *  otherwise it seems to be a good way to do it.
 * 
 *  Since all entry points need to do this same work, it was easiest to have a single function that
 *  would do the setup, pull the CustomActionData parameter, split it into an argc/argv style of
 *  argument list, and then pass that argument list into a function that actually does something
 *  interesting.
 *
 *  @param hInstall The hInstall parameter provided by MSI/WiX.
 *  @param func The function to be called with argc/argv parameters.
 *  @param actionName The text description of the function.  It will be put in the log.
 *  @return Returns ERROR_SUCCESS or ERROR_INSTALL_FAILURE.
 */
UINT CustomActionArgcArgv( MSIHANDLE hInstall, CUSTOM_ACTION_ARGC_ARGV func, LPCSTR actionName )
{
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;
    LPWSTR pszCustomActionData = NULL;
    int argc = 0;
    LPWSTR* argv = NULL;

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

	WcaLog(LOGMSG_STANDARD, "Initialized.");
    
    // Retrieve our custom action property. This is one of
    // only three properties we can request on a Deferred
    // Custom Action.  So, we assume the caller puts all
    // parameters in this one property.
    pszCustomActionData = NULL;
    hr = WcaGetProperty(L"CustomActionData", &pszCustomActionData);
    ExitOnFailure(hr, "Failed to get Custom Action Data.");
    WcaLog(LOGMSG_STANDARD, "Custom Action Data = '%ls'.", pszCustomActionData);

    // Convert the string retrieved into a standard argc/arg layout
    // (ignoring the fact that the first parameter is whatever was
    // passed, not necessarily the application name/path).
    argv = CommandLineToArgvW( pszCustomActionData, &argc );
    if ( NULL == argv )
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        ExitOnFailure(hr, "Failed to convert Custom Action Data to argc/argv.");
    }

    hr = (func)( argc, argv );
    ExitOnFailure(hr, "Custom action failed");

LExit:
    // Resource freeing here!
    ReleaseStr(pszCustomActionData);
    if ( NULL != argv )
        LocalFree( argv );

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
예제 #7
0
파일: wcascript.cpp 프로젝트: aspnet/Home
static HRESULT CaScriptFileName(
    __in WCA_ACTION action,
    __in WCA_CASCRIPT script,
    __in BOOL fImpersonated,
    __in LPCWSTR wzScriptKey,
    __out LPWSTR* ppwzScriptName
    )
{
    HRESULT hr = S_OK;
    WCHAR wzTempPath[MAX_PATH];
    LPWSTR pwzProductCode = NULL;
    WCHAR chInstallOrUninstall = action == WCA_ACTION_INSTALL ? L'i' : L'u';
    WCHAR chScheduledOrRollback = script == WCA_CASCRIPT_SCHEDULED ? L's' : L'r';
    WCHAR chUserOrMachine = fImpersonated ? L'u' : L'm';

    if (fImpersonated)
    {
        if (!::GetTempPathW(countof(wzTempPath), wzTempPath))
        {
            ExitWithLastError(hr, "Failed to get temp path.");
        }
    }
    else
    {
        if (!::GetWindowsDirectoryW(wzTempPath, countof(wzTempPath)))
        {
            ExitWithLastError(hr, "Failed to get windows path.");
        }

        hr = ::StringCchCatW(wzTempPath, countof(wzTempPath), L"\\Installer\\");
        ExitOnFailure(hr, "Failed to concat Installer directory on windows path string.");
    }

    hr = WcaGetProperty(L"ProductCode", &pwzProductCode);
    ExitOnFailure(hr, "Failed to get ProductCode.");

    hr = StrAllocFormatted(ppwzScriptName, L"%swix%s.%s.%c%c%c", wzTempPath, pwzProductCode, wzScriptKey, chScheduledOrRollback, chUserOrMachine, chInstallOrUninstall);
    ExitOnFailure(hr, "Failed to allocate path to ca script.");

LExit:
    ReleaseStr(pwzProductCode);
    return hr;
}
예제 #8
0
파일: qtexecca.cpp 프로젝트: bleissem/wix3
HRESULT BuildCommandLine(
    __in LPCWSTR wzProperty,
    __out LPWSTR *ppwzCommand
)
{
    Assert(ppwzCommand);

    HRESULT hr = S_OK;
    BOOL fScheduled = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED);
    BOOL fRollback = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK);
    BOOL fCommit = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_COMMIT);

    if (fScheduled || fRollback || fCommit)
    {
        if (WcaIsPropertySet("CustomActionData"))
        {
            hr = WcaGetProperty( L"CustomActionData", ppwzCommand);
            ExitOnFailure(hr, "Failed to get CustomActionData");
        }
    }
    else if (WcaIsUnicodePropertySet(wzProperty))
    {
        hr = WcaGetFormattedProperty(wzProperty, ppwzCommand);
        ExitOnFailure(hr, "Failed to get %ls", wzProperty);
        hr = WcaSetProperty(wzProperty, L""); // clear out the property now that we've read it
        ExitOnFailure(hr, "Failed to set %ls", wzProperty);
    }

    if (!*ppwzCommand)
    {
        ExitOnFailure(hr = E_INVALIDARG, "Failed to get command line data");
    }

    if (L'"' != **ppwzCommand)
    {
        WcaLog(LOGMSG_STANDARD, "Command string must begin with quoted application name.");
        ExitOnFailure(hr = E_INVALIDARG, "invalid command line property value");
    }

LExit:
    return hr;
}
예제 #9
0
/********************************************************************
 MessageQueuingExecuteInstall - CUSTOM ACTION ENTRY POINT

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

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;

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

    hr = MqiInitialize();
    ExitOnFailure(hr, "Failed to initialize");

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

    // create message queues
    hr = MqiCreateMessageQueues(&pwzData);
    ExitOnFailure(hr, "Failed to create message queues");
    if (S_FALSE == hr) ExitFunction();

    // add message queue permissions
    hr = MqiAddMessageQueuePermissions(&pwzData);
    ExitOnFailure(hr, "Failed to add message queue permissions");
    if (S_FALSE == hr) ExitFunction();

    hr = S_OK;

LExit:
    // clean up
    ReleaseStr(pwzCustomActionData);

    // uninitialize
    MqiUninitialize();

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
예제 #10
0
/********************************************************************
 MessageQueuingRollbackUninstall - CUSTOM ACTION ENTRY POINT

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

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;

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

    hr = MqiInitialize();
    ExitOnFailure(hr, "Failed to initialize");

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

    // delete message queues
    hr = MqiRollbackDeleteMessageQueues(&pwzData);
    ExitOnFailure(hr, "Failed to delete message queues");

    // remove message queue permissions
    hr = MqiRollbackRemoveMessageQueuePermissions(&pwzData);
    ExitOnFailure(hr, "Failed to remove message queue permissions");

    hr = S_OK;

LExit:
    // clean up
    ReleaseStr(pwzCustomActionData);

    // uninitialize
    MqiUninitialize();

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
예제 #11
0
파일: wcalog.cpp 프로젝트: 925coder/wix3
/********************************************************************
 IsVerboseLogging() - internal helper function to detect if doing
                      verbose logging.  Checks:
                      1. LOGVERBOSE property.
                      2. MsiLogging property contains 'v'
                      3. Policy from registry.
                      
                      Requires database access.
********************************************************************/
BOOL WIXAPI IsVerboseLogging()
{
    static int iVerbose = -1;
    LPWSTR pwzMsiLogging = NULL;

    if (0 > iVerbose)
    {
        iVerbose = WcaIsPropertySet("LOGVERBOSE");
        if (0 == iVerbose) 
        {
            // if the property wasn't set, check the MsiLogging property (MSI 4.0+)
            HRESULT hr = WcaGetProperty(L"MsiLogging", &pwzMsiLogging);
            ExitOnFailure(hr, "failed to get MsiLogging property");
            int cchMsiLogging = lstrlenW(pwzMsiLogging);
            if (0 < cchMsiLogging)
            {
                for (int i = 0; i < cchMsiLogging; i++)
                {
                    if (L'v' == pwzMsiLogging[i] || L'V' == pwzMsiLogging[i])
                    {
                        iVerbose = 1;
                        break;
                    }
                }
            }

            // last chance: Check the registry to see if the logging policy was turned on
            if (0 == iVerbose && IsVerboseLoggingPolicy()) 
            {
               iVerbose = 1;
            }
        }
    }

LExit:
    ReleaseStr(pwzMsiLogging);
    Assert(iVerbose >= 0);
    return (BOOL)iVerbose;
}
예제 #12
0
파일: qtexecca.cpp 프로젝트: bleissem/wix3
DWORD GetTimeout(LPCWSTR wzPropertyName)
{
    DWORD dwTimeout = ONEMINUTE;
    HRESULT hr = S_OK;

    LPWSTR pwzData = NULL;

    if (WcaIsUnicodePropertySet(wzPropertyName))
    {
        hr = WcaGetProperty(wzPropertyName, &pwzData);
        ExitOnFailure(hr, "Failed to get %ls", wzPropertyName);

        if ((dwTimeout = (DWORD)_wtoi(pwzData)) == 0)
        {
            dwTimeout = ONEMINUTE;
        }
    }

LExit:
    ReleaseStr(pwzData);

    return dwTimeout;

}
예제 #13
0
/********************************************************************
WcaGetFormattedProperty - gets a formatted string property value from
the active install

********************************************************************/
extern "C" HRESULT WIXAPI WcaGetFormattedProperty(
    __in_z LPCWSTR wzProperty,
    __out LPWSTR* ppwzData
    )
{
    if (!wzProperty || !*wzProperty || !ppwzData)
    {
        return E_INVALIDARG;
    }

    HRESULT hr = S_OK;
    LPWSTR pwzPropertyValue = NULL;

    hr = WcaGetProperty(wzProperty, &pwzPropertyValue);
    ExitOnFailure1(hr, "failed to get %ls", wzProperty);

    hr = WcaGetFormattedString(pwzPropertyValue, ppwzData);
    ExitOnFailure2(hr, "failed to get formatted value for property: '%ls' with value: '%ls'", wzProperty, pwzPropertyValue);

LExit:
    ReleaseStr(pwzPropertyValue);

    return hr;
}
예제 #14
0
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);
}
/******************************************************************
 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;
}
UINT __stdcall ExecAddinRegistration(MSIHANDLE hInstall)
{
    // AssertSz(FALSE, "debug ExecAddinRegistration");

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

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

	LPWSTR pwzAllUsers = NULL;

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

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

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

    pwz = pwzCustomActionData;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

LExit:
    RegUninitialize();

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

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

	return WcaFinalize(SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE);
}
예제 #17
0
/******************************************************************
RollbackServiceConfig - entry point for ServiceConfig rollback
                        Custom Action.

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

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwz = NULL;

    LPWSTR pwzScriptKey = NULL;
    WCA_CASCRIPT_HANDLE hRollbackScript = NULL;

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

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

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

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

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

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

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

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

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

    pwz = pwzCustomActionData;

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

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

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

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

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

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

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

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

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

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

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

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

    WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE);

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

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
예제 #18
0
/******************************************************************
 WixCreateInternetShortcuts - entry point for Internet shortcuts
    custom action
*******************************************************************/
extern "C" UINT __stdcall WixCreateInternetShortcuts(
    __in MSIHANDLE hInstall
)
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

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

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

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

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

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

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

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

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

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

    er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er;
    return WcaFinalize(er);
}
예제 #19
0
static HRESULT ExecuteCertificateOperation(
    __in MSIHANDLE hInstall,
    __in SCA_ACTION saAction,
    __in DWORD dwStoreLocation
    )
{
    //AssertSz(FALSE, "Debug ExecuteCertificateOperation() here.");
    Assert(saAction & SCA_ACTION_INSTALL || saAction & SCA_ACTION_UNINSTALL);

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

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

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

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

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

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

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

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

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

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

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

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

    ReleaseMem(pbData);
    ReleaseStr(pwzFilePath);
    ReleaseStr(pwzPFXPassword);
    ReleaseStr(pwzStore);
    ReleaseStr(pwzName);
    ReleaseStr(pwzCaData);
    return hr;
}
예제 #20
0
파일: XmlConfig.cpp 프로젝트: BMurri/wix3
/******************************************************************
 ExecXmlConfigRollback - entry point for XmlConfig rollback Custom Action

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

    int iIs64Bit;
    BOOL fIs64Bit = FALSE;

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

    FILETIME ft;

    HANDLE hFile = INVALID_HANDLE_VALUE;

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


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

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

    pwz = pwzCustomActionData;

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

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

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

    fIs64Bit = (BOOL)iIs64Bit;

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

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

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

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

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

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

    Assert(cbData == cbDataWritten);

    ReleaseFile(hFile);

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

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

    ReleaseFile(hFile);

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

    ReleaseMem(pbData);

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
예제 #21
0
파일: XmlConfig.cpp 프로젝트: BMurri/wix3
/******************************************************************
 ExecXmlConfig - entry point for XmlConfig Custom Action

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

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

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

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

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

    FILETIME ft;

    int id = IDRETRY;

    eXmlAction xa;
    eXmlPreserveDate xd;

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

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

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

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

    pwz = pwzCustomActionData;

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

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

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

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

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

        // Open the file
        ReleaseNullObject(pixd);

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

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

            fIsFSRedirectDisabled = TRUE;
        }

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

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

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

                    cAdditionalChanges--;
                }
                continue;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    cAdditionalChanges--;
                }

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

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


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

            int iSaveAttempt = 0;

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

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

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

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

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

    ReleaseObject(pixeNew);
    ReleaseObject(pixdNew);

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

    XmlUninitialize();

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

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

	HCERTSTORE hCertStore = NULL;

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

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

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

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

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

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

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

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

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

	ReleaseMem(pbData);
	ReleaseStr(pwzFilePath);
	ReleaseStr(pwzPFXPassword);
	ReleaseStr(pwzStore);
	ReleaseStr(pwzName);
	ReleaseStr(pwzCaData);
	return hr;
}
예제 #23
0
/********************************************************************
 ComPlusInstallExecuteCommit - CUSTOM ACTION ENTRY POINT

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

	LPWSTR pwzData = NULL;
	LPWSTR pwzRollbackFileName = NULL;

	HANDLE hRollbackFile = INVALID_HANDLE_VALUE;

	BOOL fInitializedCom = FALSE;

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

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

	CpiInitialize();

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

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

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

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

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

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

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

	hr = S_OK;

LExit:
	// clean up
	ReleaseStr(pwzData);

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

	// unitialize
	CpiFinalize();

	if (fInitializedCom)
		::CoUninitialize();

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
예제 #24
0
/******************************************************************
 CaExecSecureObjects - entry point for SecureObjects Custom Action
				   called as Type 1025 CustomAction (deferred binary DLL)

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

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

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

	PMSIHANDLE hActionRec = ::MsiCreateRecord(1);

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

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

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

	pwz = pwzData;

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

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

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

		//
		// create the appropriate SID
		//

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

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

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

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

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

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

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

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

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

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

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

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

		objectType = SE_UNKNOWN_OBJECT_TYPE;
	}

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

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

	if (FAILED(hr))
		er = ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
예제 #25
0
/********************************************************************
 ComPlusRollbackUninstallExecute - CUSTOM ACTION ENTRY POINT

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

	LPWSTR pwzData = NULL;
	LPWSTR pwzRollbackFileName = NULL;

	HANDLE hRollbackFile = INVALID_HANDLE_VALUE;

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

	BOOL fInitializedCom = FALSE;

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

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

	CpiInitialize();

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

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

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

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

	::CloseHandle(hRollbackFile);
	hRollbackFile = INVALID_HANDLE_VALUE;

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

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

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

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

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

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

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

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

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

	hr = S_OK;

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

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

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

	// unitialize
	CpiFinalize();

	if (fInitializedCom)
		::CoUninitialize();

	er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
예제 #26
0
/********************************************************************
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);
}
예제 #27
0
/********************************************************************
 Print - Function that sends the data from richedit control to the printer

 NOTE: Any errors encountered are saved to the vhr variable
********************************************************************/
void Print(
    __in_opt HWND hRtfWnd
    )
{
    HRESULT hr = S_OK;
    FORMATRANGE fRange;
    RECT rcPage;
    RECT rcPrintablePage;
    GETTEXTLENGTHEX gTxex;
    HDC hPrinterDC = vpPrintDlg->hDC;
    int nHorizRes = ::GetDeviceCaps(hPrinterDC, HORZRES);
    int nVertRes = ::GetDeviceCaps(hPrinterDC, VERTRES);
    int nLogPixelsX = ::GetDeviceCaps(hPrinterDC, LOGPIXELSX);
    //int nLogPixelsY = ::GetDeviceCaps(hPrinterDC, LOGPIXELSY);
    LONG_PTR lTextLength = 0; // Length of document.
    LONG_PTR lTextPrinted = 0; // Amount of document printed.
    DOCINFOW dInfo;
    LPDEVNAMES pDevnames;
    LPWSTR sczProductName = NULL;
    BOOL fStartedDoc = FALSE;
    BOOL fPrintedSomething = FALSE;

    // Ensure the printer DC is in MM_TEXT mode.
    if (0 == ::SetMapMode(hPrinterDC, MM_TEXT))
    {
        ExitWithLastError(hr, "failed to set map mode");
    }

    // Rendering to the same DC we are measuring.
    ::ZeroMemory(&fRange, sizeof(fRange));
    fRange.hdc = fRange.hdcTarget = hPrinterDC;

    // Set up the page.
    rcPage.left = rcPage.top = 0;
    rcPage.right = MulDiv(nHorizRes, ONE_INCH, nLogPixelsX);
    rcPage.bottom = MulDiv(nVertRes, ONE_INCH, nLogPixelsX);

    // Set up 1" margins all around.
    rcPrintablePage.left = rcPage.left + ONE_INCH;  
    rcPrintablePage.top = rcPage.top + ONE_INCH;
    rcPrintablePage.right = rcPage.right - ONE_INCH;
    rcPrintablePage.bottom = rcPage.bottom - ONE_INCH;

    // Set up the print job (standard printing stuff here).
    ::ZeroMemory(&dInfo, sizeof(dInfo));
    dInfo.cbSize = sizeof(DOCINFO);
    hr = WcaGetProperty(L"ProductName", &sczProductName);
    if (FAILED(hr))
    {
        // If we fail to get the product name, don't fail, just leave it blank;
        dInfo.lpszDocName = L"";
        hr = S_OK;
    }
    else
    {
        dInfo.lpszDocName = sczProductName;
    }

    pDevnames = (LPDEVNAMES)::GlobalLock(vpPrintDlg->hDevNames);
    ExitOnNullWithLastError(pDevnames, hr, "failed to get global lock");

    dInfo.lpszOutput  = (LPWSTR)pDevnames + pDevnames->wOutputOffset;

    if (0 == ::GlobalUnlock(pDevnames))
    {
        ExitWithLastError(hr, "failed to release global lock");
    }

    // Start the document.
    if (0 >= ::StartDocW(hPrinterDC, &dInfo))
    {
        ExitWithLastError(hr, "failed to start print document");
    }

    fStartedDoc = TRUE;

    ::ZeroMemory(&gTxex, sizeof(gTxex));
    gTxex.flags = GTL_NUMCHARS | GTL_PRECISE;
    lTextLength = ::SendMessageW(hRtfWnd, EM_GETTEXTLENGTHEX, (LONG_PTR)&gTxex, 0);

    while (lTextPrinted < lTextLength)
    {
        // Start the page.
        if (0 >= ::StartPage(hPrinterDC))
        {
            ExitWithLastError(hr, "failed to start print page");
        }

        // Always reset to the full printable page and start where the
        // last text left off (or zero at the beginning).
        fRange.rc = rcPrintablePage;
        fRange.rcPage = rcPage;
        fRange.chrg.cpMin = (LONG)lTextPrinted;
        fRange.chrg.cpMax = -1;

        // Print as much text as can fit on a page. The return value is
        // the index of the first character on the next page. Using TRUE
        // for the wParam parameter causes the text to be printed.
        lTextPrinted = ::SendMessageW(hRtfWnd, EM_FORMATRANGE, TRUE, (LPARAM)&fRange);
        fPrintedSomething = TRUE;

        // If text wasn't printed (i.e. we didn't move past the point we started) then
        // something must have gone wrong.
        if (lTextPrinted <= fRange.chrg.cpMin)
        {
            hr = E_FAIL;
            ExitOnFailure(hr, "failed to print some text");
        }

        // Print last page.
        if (0 >= ::EndPage(hPrinterDC))
        {
            ExitWithLastError(hr, "failed to end print page");
        }
    }

LExit:
    // Tell the control to release cached information, if we actually tried to
    // print something.
    if (fPrintedSomething)
    {
        ::SendMessageW(hRtfWnd, EM_FORMATRANGE, 0, (LPARAM)NULL);
    }

    if (fStartedDoc)
    {
        ::EndDoc(hPrinterDC);
    }

    ReleaseStr(sczProductName);

    vhr = hr;
}
예제 #28
0
/******************************************************************
 CaExecServiceConfig - entry point for ServiceConfig Custom Action
				   called as Type 1025 CustomAction (deferred binary DLL)

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

	LPWSTR pwzData = NULL;
	LPWSTR pwz = NULL;

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

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

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

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

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

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

	pwz = pwzData;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	if (FAILED(hr))
		uiResult = ERROR_INSTALL_FAILURE;
	return WcaFinalize(uiResult);
}
예제 #29
0
파일: firewall.cpp 프로젝트: BobSilent/wix3
/******************************************************************
 ExecFirewallExceptions - deferred custom action entry point to 
   register and remove firewall exceptions.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
}
예제 #30
0
/*
  Checks if database directory or service are modified by user
  For example, service may point to different mysqld.exe that it was originally
  installed, or some different service might use this database directory. This 
  would normally mean user has done an upgrade of the database and in this case 
  uninstall should neither delete service nor database directory.

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

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

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

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

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

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

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

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

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

LExit:
  if(scm)
    CloseServiceHandle(scm);

  ReleaseStr(servicename);
  ReleaseStr(datadir);
  ReleaseStr(bindir);
  return WcaFinalize(er); 
}