Beispiel #1
0
/////////////////////////////////////////////////////////////////////
// 
// Function:    LogMessage
//
// Description: This function writes to the MSI log file and displays
//              the SetupError dialog box as appropriate.
//
/////////////////////////////////////////////////////////////////////
UINT BOINCCABase::LogMessage(
    const UINT    uiInstallMessageType,    // message type to send to Windows Installer
    const UINT    uiPushButtonStyle,       // push button sstyle to use in message box
    const UINT    uiIconStyle,             // icon style to use in message box
    const UINT    uiErrorNumber,           // number of error in Error table
    const UINT    uiErrorCode,             // the return value from an api
    const tstring strMessage               // message
    )
{
    UINT        uiReturnValue = 0;

    switch(uiInstallMessageType)
    {

    // Send informational message to the log file
    case INSTALLMESSAGE_INFO:

        MsiRecordSetString (m_phLogInfoRec, 2, strMessage.c_str());
        MsiRecordSetInteger(m_phLogInfoRec, 3, uiErrorCode);

        // returns IDOK if successful
        uiReturnValue = MsiProcessMessage(
            m_hMSIHandle, 
            INSTALLMESSAGE(uiInstallMessageType),
            m_phLogInfoRec
            );
        break;

    // Display a dialog and send error message to log file
    case INSTALLMESSAGE_ERROR:
    case INSTALLMESSAGE_WARNING:
    case INSTALLMESSAGE_USER:

        PMSIHANDLE phLogErrorRec = MsiCreateRecord(2);

        MsiRecordSetString (phLogErrorRec, 0, _T("[1]"));
        MsiRecordSetString (phLogErrorRec, 1, strMessage.c_str());

        // Return value to indicate which button is 
        // pushed on message box
        uiReturnValue = MsiProcessMessage(
            m_hMSIHandle,
            INSTALLMESSAGE(uiInstallMessageType|uiPushButtonStyle|uiIconStyle),
            phLogErrorRec
            );
        break;

    }
    return uiReturnValue;
}
UINT Blip(
	MSIHANDLE hModule) // Handle of MSI being installed. [in]
{
	// Set up variables.
	PMSIHANDLE hRecord = ::MsiCreateRecord(4);
    HANDLE_OK(hRecord)

	UINT uiAnswer = ::MsiRecordSetInteger(hRecord, 1, 2);
	MSI_OK(uiAnswer)
	
	uiAnswer = ::MsiRecordSetInteger(hRecord, 2, 0);
	MSI_OK(uiAnswer)

	uiAnswer = ::MsiRecordSetInteger(hRecord, 3, 0);
	MSI_OK(uiAnswer)

	uiAnswer = ::MsiRecordSetInteger(hRecord, 4, 0);
	MSI_OK(uiAnswer)

	// Send the message
	uiAnswer = ::MsiProcessMessage(hModule, INSTALLMESSAGE(INSTALLMESSAGE_PROGRESS), hRecord);

	// Corrects return value for use with MSI_OK.
	switch (uiAnswer) {
	case IDOK:
	case 0: // Means no action was taken...
		return ERROR_SUCCESS;
	case IDCANCEL:
		return ERROR_INSTALL_USEREXIT;
	default:
		return ERROR_INSTALL_FAILURE;
	}
}
Beispiel #3
0
int MsiMessageBox(MSIHANDLE hInstall, TCHAR* szString, DWORD dwDlgFlags)
{
  // I am not aware of anyway to programmatically set the dialog title through this code.
  // I think you may just have to author the Error Dialog in your .msi to use the text that you want.
  // chances are you will want to use [ProgramName] because the Error Dialog can get called from the MSI
  // it self, if it encounters an error, and it would be weird if you hard-coded the title bar to 
  // "Desktop Shortcut?" or something like that.
  PMSIHANDLE newHandle = ::MsiCreateRecord(2);
  MsiRecordSetString(newHandle, 0, szString);
  return (MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_USER + dwDlgFlags), newHandle));
}
Beispiel #4
0
static void logStringW(MSIHANDLE hInstall, LPCWSTR pwszString, ...)
{
    PMSIHANDLE newHandle = MsiCreateRecord(2);

    WCHAR szBuffer[1024];
    va_list va;
    va_start(va, pwszString);
    _vsnwprintf(szBuffer, RT_ELEMENTS(szBuffer), pwszString, va);
    va_end(va);

    MsiRecordSetStringW(newHandle, 0, szBuffer);
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), newHandle);
    MsiCloseHandle(newHandle);
}
Beispiel #5
0
void LogString(MSIHANDLE hInstall, TCHAR* szString)
{
  // if you are curious what the PMSIHANDLE is, look it up in the msi.chm.  It is actually a good idea to use it
  // rather than MSIHANDLE.  Basically it will free itself when it goes out of scope.  In the past I helped
  // track a bug down to the fact that they weren't using it...
  PMSIHANDLE newHandle = ::MsiCreateRecord(2);
  TCHAR szTemp[MAX_PATH * 2];
  wsprintf(szTemp, L"-- MSI_LOGGING --   %s", szString); 
  MsiRecordSetString(newHandle, 0, szTemp);
  MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), newHandle);
  // if you get one of those:  cannot convert parameter 2 from 'enum tagINSTALLMESSAGE' to 'enum tagMSIMESSAGE'
  // errors on the line above, then chances are you:
  //    1) havent installed the latest MSI SDK (now apart of the Platform SDK)
  // or 2) havent added the \include\ and \lib\ directories to the Visual Studio path (tools | options, directory tab).
}
Beispiel #6
0
static void logString(MSIHANDLE hInstall, LPCSTR szString, ...)
{
    PMSIHANDLE newHandle = MsiCreateRecord(2);

    char szBuffer[1024];
    va_list va;
    va_start(va, szString);
    _vsnprintf(szBuffer, sizeof(szBuffer), szString, va);
    va_end(va);

    MsiRecordSetStringA(newHandle, 0, szBuffer);
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), newHandle);
    MsiCloseHandle(newHandle);

#if 0/*def DEBUG - wrong? What does '%s' expect, wchar or char? */
    _tprintf(_T("Debug: %s\n"), szBuffer);
#endif
}
//////////////////////////////////////////////////////////////////////////////
// RemoveUserAccount
//
//     Attempts to remove a user account on the local machine according
//       to the "instructions" provided in the CustomActionData property
//
//     As a deferred custom action, you do not have access to the database.
//       The only source of information comes from a property that an immediate
//       custom action can set to provide the information you need.  This
//       property is written into the script
//
                                                           UINT __stdcall RemoveUserAccount(MSIHANDLE hInstall)
{
    // determine mode in which we are called
    BOOL bRollback = MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK); // true for rollback, else regular deferred version (for uninstall)

    BOOL fSuccess = FALSE;

    // id's for error and warning messages
    const int iRemoveError = 25003;
    const int iRemoveWarning = 25004;

    // Grab the CustomActionData property
    DWORD cchCAData = 0;

    if (ERROR_MORE_DATA == MsiGetPropertyW(hInstall, IPROPNAME_CUSTOMACTIONDATA, L"", &cchCAData))
    {
        WCHAR* wszCAData = new WCHAR[++cchCAData]; // add 1 for null-terminator which is not included in size on return
        if (wszCAData)
        {
            if (ERROR_SUCCESS == MsiGetPropertyW(hInstall, IPROPNAME_CUSTOMACTIONDATA, wszCAData, &cchCAData))
            {
                // send ActionData message (template in ActionText table)
                // send ActionData message (template in ActionText table)
                PMSIHANDLE hRec = MsiCreateRecord(1);
                if (!hRec
                        || ERROR_SUCCESS != MsiRecordSetStringW(hRec, 1, wszCAData))
                {
                    delete [] wszCAData;
                    return ERROR_INSTALL_FAILURE;
                }

                int iRet = MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONDATA, hRec);
                if (IDCANCEL == iRet || IDABORT == iRet)
                {
                    delete [] wszCAData;
                    return ERROR_INSTALL_USEREXIT;
                }

                //
                // Call the NetUserDel function,
                //
                NET_API_STATUS nStatus = NetUserDel(NULL /*local machine*/, wszCAData /*user name*/);

                if (NERR_Success != nStatus)
                {
                    PMSIHANDLE hRecErr = MsiCreateRecord(3);
                    if ( !hRecErr
                            || ERROR_SUCCESS != MsiRecordSetStringW(hRecErr, 2, wszCAData))
                    {
                        delete [] wszCAData;
                        return ERROR_INSTALL_FAILURE;
                    }

                    // In rollback mode, NERR_UserNotFound means cancel button depressed in middle of deferred CA trying to create this account
                    if (bRollback && NERR_UserNotFound == nStatus)
                    {
                        fSuccess = TRUE;
                    }
                    else if (NERR_UserNotFound == nStatus)
                    {
                        // treat this as a warning, but success since we are attempting to delete and it is not present
                        if (ERROR_SUCCESS != MsiRecordSetInteger(hRecErr, 1, iRemoveWarning))
                        {
                            delete [] wszCAData;
                            return ERROR_INSTALL_FAILURE;
                        }

                        // just pop up an OK button
                        // OPTIONALLY, could specify multiple buttons and cancel
                        // install based on user selection by handling the return value
                        // from MsiProcessMessage, but here we are ignoring the MsiProcessMessage return
                        MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING|MB_ICONWARNING|MB_OK), hRecErr);
                        fSuccess = TRUE;
                    }
                    else
                    {
                        if (ERROR_SUCCESS == MsiRecordSetInteger(hRecErr, 1, iRemoveError)
                                && ERROR_SUCCESS == MsiRecordSetInteger(hRecErr, 3, nStatus))
                        {
                            // returning failure anyway, so ignoring MsiProcessMessage return
                            MsiProcessMessage(hInstall, INSTALLMESSAGE_ERROR, hRecErr);
                        }
                    }
                }
                else // NERR_Success
                {
                    fSuccess = TRUE;
                }
            }

            delete [] wszCAData;
        }
    }

    return fSuccess ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
}