コード例 #1
0
ファイル: pipe.cpp プロジェクト: firegiant/wix4
/*******************************************************************
 PipeCreateNameAndSecret - 

*******************************************************************/
extern "C" HRESULT PipeCreateNameAndSecret(
    __out_z LPWSTR *psczConnectionName,
    __out_z LPWSTR *psczSecret
    )
{
    HRESULT hr = S_OK;
    WCHAR wzGuid[GUID_STRING_LENGTH];
    LPWSTR sczConnectionName = NULL;
    LPWSTR sczSecret = NULL;

    // Create the unique pipe name.
    hr = GuidFixedCreate(wzGuid);
    ExitOnRootFailure(hr, "Failed to create pipe guid.");

    hr = StrAllocFormatted(&sczConnectionName, L"BurnPipe.%s", wzGuid);
    ExitOnFailure(hr, "Failed to allocate pipe name.");

    // Create the unique client secret.
    hr = GuidFixedCreate(wzGuid);
    ExitOnRootFailure(hr, "Failed to create pipe secret.");

    hr = StrAllocString(&sczSecret, wzGuid, 0);
    ExitOnFailure(hr, "Failed to allocate pipe secret.");

    *psczConnectionName = sczConnectionName;
    sczConnectionName = NULL;
    *psczSecret = sczSecret;
    sczSecret = NULL;

LExit:
    ReleaseStr(sczSecret);
    ReleaseStr(sczConnectionName);

    return hr;
}
コード例 #2
0
ファイル: pipe.cpp プロジェクト: firegiant/wix3
/*******************************************************************
 PipeCreateNameAndSecret - 

*******************************************************************/
extern "C" HRESULT PipeCreateNameAndSecret(
    __out_z LPWSTR *psczConnectionName,
    __out_z LPWSTR *psczSecret
    )
{
    HRESULT hr = S_OK;
    RPC_STATUS rs = RPC_S_OK;
    UUID guid = { };
    WCHAR wzGuid[39];
    LPWSTR sczConnectionName = NULL;
    LPWSTR sczSecret = NULL;

    // Create the unique pipe name.
    rs = ::UuidCreate(&guid);
    hr = HRESULT_FROM_RPC(rs);
    ExitOnFailure(hr, "Failed to create pipe guid.");

    if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
    {
        hr = E_OUTOFMEMORY;
        ExitOnRootFailure(hr, "Failed to convert pipe guid into string.");
    }

    hr = StrAllocFormatted(&sczConnectionName, L"BurnPipe.%s", wzGuid);
    ExitOnFailure(hr, "Failed to allocate pipe name.");

    // Create the unique client secret.
    rs = ::UuidCreate(&guid);
    hr = HRESULT_FROM_RPC(rs);
    ExitOnRootFailure(hr, "Failed to create pipe guid.");

    if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
    {
        hr = E_OUTOFMEMORY;
        ExitOnRootFailure(hr, "Failed to convert pipe guid into string.");
    }

    hr = StrAllocString(&sczSecret, wzGuid, 0);
    ExitOnFailure(hr, "Failed to allocate pipe secret.");

    *psczConnectionName = sczConnectionName;
    sczConnectionName = NULL;
    *psczSecret = sczSecret;
    sczSecret = NULL;

LExit:
    ReleaseStr(sczSecret);
    ReleaseStr(sczConnectionName);

    return hr;
}
コード例 #3
0
ファイル: balutil.cpp プロジェクト: BMurri/wix3
DAPIV_(HRESULT) BalLog(
    __in BOOTSTRAPPER_LOG_LEVEL level,
    __in_z __format_string LPCSTR szFormat,
    ...
    )
{
    HRESULT hr = S_OK;
    va_list args;
    LPSTR sczFormattedAnsi = NULL;
    LPWSTR sczMessage = NULL;

    if (!vpEngine)
    {
        hr = E_POINTER;
        ExitOnRootFailure(hr, "BalInitialize() must be called first.");
    }

    va_start(args, szFormat);
    hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args);
    va_end(args);
    ExitOnFailure(hr, "Failed to format log string.");

    hr = StrAllocStringAnsi(&sczMessage, sczFormattedAnsi, 0, CP_UTF8);
    ExitOnFailure(hr, "Failed to convert log string to Unicode.");

    hr = vpEngine->Log(level, sczMessage);

LExit:
    ReleaseStr(sczMessage);
    ReleaseStr(sczFormattedAnsi);
    return hr;
}
コード例 #4
0
ファイル: balutil.cpp プロジェクト: BMurri/wix3
DAPIV_(HRESULT) BalLogError(
    __in HRESULT hrError,
    __in_z __format_string LPCSTR szFormat,
    ...
    )
{
    HRESULT hr = S_OK;
    va_list args;
    LPSTR sczFormattedAnsi = NULL;
    LPWSTR sczMessage = NULL;

    if (!vpEngine)
    {
        hr = E_POINTER;
        ExitOnRootFailure(hr, "BalInitialize() must be called first.");
    }

    va_start(args, szFormat);
    hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args);
    va_end(args);
    ExitOnFailure(hr, "Failed to format error log string.");

    hr = StrAllocFormatted(&sczMessage, L"Error 0x%08x: %S", hrError, sczFormattedAnsi);
    ExitOnFailure(hr, "Failed to prepend error number to error log string.");

    hr = vpEngine->Log(BOOTSTRAPPER_LOG_LEVEL_ERROR, sczMessage);

LExit:
    ReleaseStr(sczMessage);
    ReleaseStr(sczFormattedAnsi);
    return hr;
}
コード例 #5
0
ファイル: balutil.cpp プロジェクト: BMurri/wix3
// The contents of psczOut may be sensitive, should keep encrypted and SecureZeroFree.
DAPI_(HRESULT) BalFormatString(
    __in_z LPCWSTR wzFormat,
    __inout LPWSTR* psczOut
    )
{
    HRESULT hr = S_OK;
    DWORD cch = 0;

    if (!vpEngine)
    {
        hr = E_POINTER;
        ExitOnRootFailure(hr, "BalInitialize() must be called first.");
    }

    if (*psczOut)
    {
        hr = StrMaxLength(*psczOut, reinterpret_cast<DWORD_PTR*>(&cch));
        ExitOnFailure(hr, "Failed to determine length of value.");
    }

    hr = vpEngine->FormatString(wzFormat, *psczOut, &cch);
    if (E_MOREDATA == hr)
    {
        ++cch;

        hr = StrAllocSecure(psczOut, cch);
        ExitOnFailure(hr, "Failed to allocate value.");

        hr = vpEngine->FormatString(wzFormat, *psczOut, &cch);
    }

LExit:
    return hr;
}
コード例 #6
0
ファイル: dutil.cpp プロジェクト: 925coder/wix3
/*******************************************************************
 LoadSystemLibraryWithPath - Fully qualifies the path to a module in
                             the Windows system directory and loads it
                             and returns the path

 Returns
   E_MODNOTFOUND - The module could not be found.
   * - Another error occured.
********************************************************************/
extern "C" HRESULT DAPI LoadSystemLibraryWithPath(
    __in_z LPCWSTR wzModuleName,
    __out HMODULE *phModule,
    __deref_out_z_opt LPWSTR* psczPath
    )
{
    HRESULT hr = S_OK;
    DWORD cch = 0;
    WCHAR wzPath[MAX_PATH] = { };

    cch = ::GetSystemDirectoryW(wzPath, MAX_PATH);
    ExitOnNullWithLastError(cch, hr, "Failed to get the Windows system directory.");

    if (L'\\' != wzPath[cch - 1])
    {
        hr = ::StringCchCatNW(wzPath, MAX_PATH, L"\\", 1);
        ExitOnRootFailure(hr, "Failed to terminate the string with a backslash.");
    }

    hr = ::StringCchCatW(wzPath, MAX_PATH, wzModuleName);
    ExitOnRootFailure1(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName);

    *phModule = ::LoadLibraryW(wzPath);
    ExitOnNullWithLastError1(*phModule, hr, "Failed to load the library %ls.", wzModuleName);

    if (psczPath)
    {
        hr = StrAllocString(psczPath, wzPath, MAX_PATH);
        ExitOnFailure(hr, "Failed to copy the path to library.");
    }

LExit:
    return hr;
}
コード例 #7
0
ファイル: jsonutil.cpp プロジェクト: AnalogJ/Wix3.6Toolset
static HRESULT DoEnd(
    __in JSON_WRITER* pWriter,
    __in JSON_TOKEN tokenEnd,
    __in_z LPCWSTR wzEndString
    )
{
    HRESULT hr = S_OK;

    ::EnterCriticalSection(&pWriter->cs);

    if (!pWriter->rgTokenStack || 0 == pWriter->cTokens)
    {
        hr = E_UNEXPECTED;
        ExitOnRootFailure(hr, "Failure to pop token because the stack is empty.");
    }
    else
    {
        JSON_TOKEN token = pWriter->rgTokenStack[pWriter->cTokens - 1];
        if ((JSON_TOKEN_ARRAY_END == tokenEnd && JSON_TOKEN_ARRAY_START != token && JSON_TOKEN_ARRAY_VALUE != token) ||
            (JSON_TOKEN_OBJECT_END == tokenEnd && JSON_TOKEN_OBJECT_START != token && JSON_TOKEN_OBJECT_VALUE != token))
        {
            hr = E_UNEXPECTED;
            ExitOnRootFailure1(hr, "Failure to pop token because the stack did not match the expected token: %d", tokenEnd);
        }
    }

    hr = StrAllocConcat(&pWriter->sczJson, wzEndString, 0);
    ExitOnFailure(hr, "Failed to end JSON array or object.");

    --pWriter->cTokens;

LExit:
    ::LeaveCriticalSection(&pWriter->cs);
    return hr;
}
コード例 #8
0
ファイル: handle.cpp プロジェクト: firegiant/wix4
HRESULT HandleEnsureSummaryDataTable(
    __in CFGDB_STRUCT *pcdb
    )
{
    HRESULT hr = S_OK;
    BOOL fInSceTransaction = FALSE;
    BOOL fEmpty = FALSE;
    SCE_ROW_HANDLE sceRow = NULL;

    hr = SceGetFirstRow(pcdb->psceDb, SUMMARY_DATA_TABLE, &sceRow);
    if (E_NOTFOUND == hr)
    {
        fEmpty = TRUE;
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failed to get first row of summary data table");

    if (fEmpty)
    {
        hr = GuidCreate(&pcdb->sczGuid);
        ExitOnRootFailure(hr, "Failed to generate guid string");

        hr = SceBeginTransaction(pcdb->psceDb);
        ExitOnFailure(hr, "Failed to begin transaction");
        fInSceTransaction = TRUE;

        hr = ScePrepareInsert(pcdb->psceDb, SUMMARY_DATA_TABLE, &sceRow);
        ExitOnFailure(hr, "Failed to prepare for insert");

        hr = SceSetColumnString(sceRow, SUMMARY_GUID, pcdb->sczGuid);
        ExitOnFailure(hr, "Failed to set column string of summary data table guid");

        hr = SceFinishUpdate(sceRow);
        ExitOnFailure(hr, "Failed to finish insert into summary data table");

        hr = SceCommitTransaction(pcdb->psceDb);
        ExitOnFailure(hr, "Failed to commit transaction");
        fInSceTransaction = FALSE;

        ExitFunction1(hr = S_OK);
    }
    ExitOnFailure(hr, "Failed to move to first row in SummaryData table");

    hr = SceGetColumnString(sceRow, SUMMARY_GUID, &pcdb->sczGuid);
    ExitOnFailure(hr, "Failed to get GUID from summary data table");

LExit:
    ReleaseSceRow(sceRow);
    if (fInSceTransaction)
    {
        SceRollbackTransaction(pcdb->psceDb);
    }
    if (FAILED(hr))
    {
        ReleaseNullStr(pcdb->sczGuid);
    }

    return hr;
}
コード例 #9
0
ファイル: wuautil.cpp プロジェクト: lukaswinzenried/WixCustBa
extern "C" HRESULT DAPI WuaRestartRequired(
    __out BOOL* pfRestartRequired
    )
{
    HRESULT hr = S_OK;
    ISystemInformation* pSystemInformation = NULL;
    VARIANT_BOOL bRestartRequired;

    hr = ::CoCreateInstance(__uuidof(SystemInformation), NULL, CLSCTX_INPROC_SERVER, __uuidof(ISystemInformation), reinterpret_cast<LPVOID*>(&pSystemInformation));
    ExitOnRootFailure(hr, "Failed to get WUA system information interface.");

    hr = pSystemInformation->get_RebootRequired(&bRestartRequired);
    ExitOnRootFailure(hr, "Failed to determine if restart is required from WUA.");

    *pfRestartRequired = (VARIANT_FALSE != bRestartRequired);

LExit:
    ReleaseObject(pSystemInformation);

    return hr;
}
コード例 #10
0
ファイル: engine.cpp プロジェクト: Alyoshak/wix3
static HRESULT Restart()
{
    HRESULT hr = S_OK;
    HANDLE hProcessToken = NULL;
    TOKEN_PRIVILEGES priv = { };
    DWORD dwRetries = 0;

    if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcessToken))
    {
        ExitWithLastError(hr, "Failed to get process token.");
    }

    priv.PrivilegeCount = 1;
    priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!::LookupPrivilegeValueW(NULL, L"SeShutdownPrivilege", &priv.Privileges[0].Luid))
    {
        ExitWithLastError(hr, "Failed to get shutdown privilege LUID.");
    }

    if (!::AdjustTokenPrivileges(hProcessToken, FALSE, &priv, sizeof(TOKEN_PRIVILEGES), NULL, 0))
    {
        ExitWithLastError(hr, "Failed to adjust token to add shutdown privileges.");
    }

    do
    {
        hr = S_OK;

        // Wait a second to let the companion process (assuming we did an elevated install) to get to the
        // point where it too is thinking about restarting the computer. Only one will schedule the restart
        // but both will have their log files closed and otherwise be ready to exit.
        //
        // On retry, we'll also wait a second to let the OS try to get to a place where the restart can
        // be initiated.
        ::Sleep(1000);

        if (!vpfnInitiateSystemShutdownExW(NULL, NULL, 0, FALSE, TRUE, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_INSTALLATION | SHTDN_REASON_FLAG_PLANNED))
        {
            hr = HRESULT_FROM_WIN32(::GetLastError());
        }
    } while (dwRetries++ < RESTART_RETRIES && (HRESULT_FROM_WIN32(ERROR_MACHINE_LOCKED) == hr || HRESULT_FROM_WIN32(ERROR_NOT_READY) == hr));
    ExitOnRootFailure(hr, "Failed to schedule restart.");

LExit:
    ReleaseHandle(hProcessToken);
    return hr;
}
コード例 #11
0
ファイル: jsonutil.cpp プロジェクト: AnalogJ/Wix3.6Toolset
static HRESULT DoKey(
    __in JSON_WRITER* pWriter,
    __in_z LPCWSTR wzKey
    )
{
    HRESULT hr = S_OK;
    JSON_TOKEN token = JSON_TOKEN_NONE;
    BOOL fNeedComma = FALSE;

    ::EnterCriticalSection(&pWriter->cs);

    hr = EnsureTokenStack(pWriter);
    ExitOnFailure(hr, "Failed to ensure token stack for key.");

    token = pWriter->rgTokenStack[pWriter->cTokens - 1];
    switch (token)
    {
    case JSON_TOKEN_OBJECT_START:
        token = JSON_TOKEN_OBJECT_KEY;
        break;

    case JSON_TOKEN_OBJECT_VALUE:
        token = JSON_TOKEN_OBJECT_KEY;
        fNeedComma = TRUE;
        break;

    default: // everything else is not allowed.
        hr = E_UNEXPECTED;
        break;
    }
    ExitOnRootFailure(hr, "Cannot add key to JSON serializer now.");

    if (fNeedComma)
    {
        hr = StrAllocConcat(&pWriter->sczJson, L",", 0);
        ExitOnFailure(hr, "Failed to add comma for key to JSON.");
    }

    hr = StrAllocConcat(&pWriter->sczJson, wzKey, 0);
    ExitOnFailure(hr, "Failed to add key to JSON.");

    pWriter->rgTokenStack[pWriter->cTokens - 1] = token;

LExit:
    ::LeaveCriticalSection(&pWriter->cs);
    return hr;
}
コード例 #12
0
ファイル: balutil.cpp プロジェクト: BMurri/wix3
// The contents of pllValue may be sensitive, if variable is hidden should keep value encrypted and SecureZeroMemory.
DAPI_(HRESULT) BalGetNumericVariable(
    __in_z LPCWSTR wzVariable,
    __out LONGLONG* pllValue
    )
{
    HRESULT hr = S_OK;

    if (!vpEngine)
    {
        hr = E_POINTER;
        ExitOnRootFailure(hr, "BalInitialize() must be called first.");
    }

    hr = vpEngine->GetVariableNumeric(wzVariable, pllValue);

LExit:
    return hr;
}
コード例 #13
0
ファイル: balutil.cpp プロジェクト: BMurri/wix3
DAPI_(BOOL) BalStringVariableExists(
    __in_z LPCWSTR wzVariable
    )
{
    HRESULT hr = S_OK;
    DWORD cch = 0;

    if (!vpEngine)
    {
        hr = E_POINTER;
        ExitOnRootFailure(hr, "BalInitialize() must be called first.");
    }

    hr = vpEngine->GetVariableString(wzVariable, NULL, &cch);

LExit:
    return E_MOREDATA == hr; // string exists only if there are more than zero characters in the variable.
}
コード例 #14
0
ファイル: thmviewer.cpp プロジェクト: 925coder/wix3
//
// ProcessCommandLine - process the provided command line arguments.
//
static HRESULT ProcessCommandLine(
    __in_z_opt LPCWSTR wzCommandLine,
    __out_z LPWSTR* psczThemeFile
    )
{
    HRESULT hr = S_OK;
    int argc = 0;
    LPWSTR* argv = NULL;

    if (wzCommandLine && *wzCommandLine)
    {
        argv = ::CommandLineToArgvW(wzCommandLine, &argc);
        ExitOnNullWithLastError(argv, hr, "Failed to get command line.");

        for (int i = 0; i < argc; ++i)
        {
            if (argv[i][0] == L'-' || argv[i][0] == L'/')
            {
                if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1))
                {
                    if (i + 1 >= argc)
                    {
                        ExitOnRootFailure(hr = E_INVALIDARG, "Must specify a language.");
                    }

                    ++i;
                }
            }
            else
            {
                hr = StrAllocString(psczThemeFile, argv[i], 0);
                ExitOnFailure(hr, "Failed to copy path to theme file.");
            }
        }
    }

LExit:
    if (argv)
    {
        ::LocalFree(argv);
    }

    return hr;
}
コード例 #15
0
ファイル: detect.cpp プロジェクト: 925coder/wix3
extern "C" HRESULT DetectUpdate(
    __in_z LPCWSTR wzBundleId,
    __in BURN_USER_EXPERIENCE* pUX,
    __in BURN_UPDATE* pUpdate
    )
{
    HRESULT hr = S_OK;
    int nResult = IDNOACTION;
    BOOL fBeginCalled = FALSE;

    // If no update source was specified, skip update detection.
    if (!pUpdate->sczUpdateSource || !*pUpdate->sczUpdateSource)
    {
        ExitFunction();
    }

    fBeginCalled = TRUE;

    nResult = pUX->pUserExperience->OnDetectUpdateBegin(pUpdate->sczUpdateSource, IDNOACTION);
    hr = UserExperienceInterpretResult(pUX, MB_OKCANCEL, nResult);
    ExitOnRootFailure(hr, "UX aborted detect update begin.");

    if (IDNOACTION == nResult)
    {
        //pUpdate->fUpdateAvailable = FALSE;
    }
    else if (IDOK == nResult)
    {
        hr = DetectAtomFeedUpdate(wzBundleId, pUX, pUpdate);
        ExitOnFailure(hr, "Failed to detect atom feed update.");
    }

LExit:
    if (fBeginCalled)
    {
        pUX->pUserExperience->OnDetectUpdateComplete(hr, pUpdate->fUpdateAvailable ? pUpdate->sczUpdateSource : NULL);
    }

    return hr;
}
コード例 #16
0
ファイル: jsonutil.cpp プロジェクト: AnalogJ/Wix3.6Toolset
static HRESULT DoStart(
    __in JSON_WRITER* pWriter,
    __in JSON_TOKEN tokenStart,
    __in_z LPCWSTR wzStartString
    )
{
    Assert(JSON_TOKEN_ARRAY_START == tokenStart || JSON_TOKEN_OBJECT_START == tokenStart);

    HRESULT hr = S_OK;
    JSON_TOKEN token = JSON_TOKEN_NONE;
    BOOL fNeedComma = FALSE;
    BOOL fPushToken = TRUE;

    ::EnterCriticalSection(&pWriter->cs);

    hr = EnsureTokenStack(pWriter);
    ExitOnFailure(hr, "Failed to ensure token stack for start.");

    token = pWriter->rgTokenStack[pWriter->cTokens - 1];
    switch (token)
    {
    case JSON_TOKEN_NONE:
        token = tokenStart;
        fPushToken = FALSE;
        break;

    case JSON_TOKEN_ARRAY_START: // array start changes to array value.
        token = JSON_TOKEN_ARRAY_VALUE;
        break;

    case JSON_TOKEN_ARRAY_VALUE:
    case JSON_TOKEN_ARRAY_END:
    case JSON_TOKEN_OBJECT_END:
        fNeedComma = TRUE;
        break;

    default: // everything else is not allowed.
        hr = E_UNEXPECTED;
        break;
    }
    ExitOnRootFailure(hr, "Cannot start array or object to JSON serializer now.");

    if (fNeedComma)
    {
        hr = StrAllocConcat(&pWriter->sczJson, L",", 0);
        ExitOnFailure(hr, "Failed to add comma for start array or object to JSON.");
    }

    hr = StrAllocConcat(&pWriter->sczJson, wzStartString, 0);
    ExitOnFailure(hr, "Failed to start JSON array or object.");

    pWriter->rgTokenStack[pWriter->cTokens - 1] = token;
    if (fPushToken)
    {
        pWriter->rgTokenStack[pWriter->cTokens] = tokenStart;
        ++pWriter->cTokens;
    }

LExit:
    ::LeaveCriticalSection(&pWriter->cs);
    return hr;
}
コード例 #17
0
extern "C" HRESULT NetFxRunChainer(
    __in LPCWSTR wzExecutablePath,
    __in LPCWSTR wzArguments,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out DWORD* pdwExitCode
)
{
    HRESULT hr = S_OK;
    DWORD er = 0;
    UUID guid = { };
    WCHAR wzGuid[39];
    RPC_STATUS rs = RPC_S_OK;
    LPWSTR sczEventName = NULL;
    LPWSTR sczSectionName = NULL;
    LPWSTR sczCommand = NULL;
    NetFxChainer* pNetfxChainer = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    HRESULT hrInternalError = 0;

    // Create the unique name suffix.
    rs = ::UuidCreate(&guid);
    hr = HRESULT_FROM_RPC(rs);
    ExitOnFailure(hr, "Failed to create netfx chainer guid.");

    if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
    {
        hr = E_OUTOFMEMORY;
        ExitOnRootFailure(hr, "Failed to convert netfx chainer guid into string.");
    }

    hr = StrAllocFormatted(&sczSectionName, L"NetFxSection.%ls", wzGuid);
    ExitOnFailure(hr, "Failed to allocate section name.");

    hr = StrAllocFormatted(&sczEventName, L"NetFxEvent.%ls", wzGuid);
    ExitOnFailure(hr, "Failed to allocate event name.");

    hr = CreateNetFxChainer(sczSectionName, sczEventName, &pNetfxChainer);
    ExitOnFailure(hr, "Failed to create netfx chainer.");

    hr = StrAllocFormatted(&sczCommand, L"%ls /pipe %ls", wzArguments, sczSectionName);
    ExitOnFailure(hr, "Failed to allocate netfx chainer arguments.");

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

    HANDLE handles[2] = { pi.hProcess, pNetfxChainer->hEventChaineeSend };

    for (;;)
    {
        er = ::WaitForMultipleObjects(2, handles, FALSE, 100);
        if (WAIT_OBJECT_0 == er)
        {
            // Process has exited
            *pdwExitCode = NetFxGetResult(pNetfxChainer, &hrInternalError);
            if (E_PENDING == *pdwExitCode)
            {
                if (!::GetExitCodeProcess(pi.hProcess, pdwExitCode))
                {
                    ExitWithLastError(hr, "Failed to get netfx return code.");
                }
            }
            else if (FAILED(hrInternalError))
            {
                // push internal error message
                OnNetFxError(pNetfxChainer, hrInternalError, pfnGenericMessageHandler, pvContext);
                ExitOnFailure(hr, "Failed to send internal error message from netfx chainer.");
            }

            break;
        }
        else if (WAIT_OBJECT_0 + 1 == er)
        {
            // Chainee has notified us of a change.
            hr = ProcessNetFxMessage(pNetfxChainer, pfnGenericMessageHandler, pvContext);
            ExitOnFailure(hr, "Failed to process netfx chainer message.");
        }
        else if (WAIT_FAILED == er)
        {
            ExitWithLastError(hr, "Failed to wait for netfx chainer process to complete");
        }
    }

LExit:
    ReleaseStr(sczSectionName);
    ReleaseStr(sczEventName);
    ReleaseStr(sczCommand);
    DestroyNetFxChainer(pNetfxChainer);
    ReleaseHandle(pi.hThread);
    ReleaseHandle(pi.hProcess);

    return hr;
}
コード例 #18
0
ファイル: pipe.cpp プロジェクト: firegiant/wix3
/*******************************************************************
 PipeWaitForChildConnect - 

*******************************************************************/
extern "C" HRESULT PipeWaitForChildConnect(
    __in BURN_PIPE_CONNECTION* pConnection
    )
{
    HRESULT hr = S_OK;
    HANDLE hPipes[2] = { pConnection->hPipe, pConnection->hCachePipe};
    LPCWSTR wzSecret = pConnection->sczSecret;
    DWORD cbSecret = lstrlenW(wzSecret) * sizeof(WCHAR);
    DWORD dwCurrentProcessId = ::GetCurrentProcessId();
    DWORD dwAck = 0;
    DWORD cb = 0;

    for (DWORD i = 0; i < countof(hPipes) && INVALID_HANDLE_VALUE != hPipes[i]; ++i)
    {
        HANDLE hPipe = hPipes[i];
        DWORD dwPipeState = PIPE_READMODE_BYTE | PIPE_NOWAIT;

        // Temporarily make the pipe non-blocking so we will not get stuck in ::ConnectNamedPipe() forever
        // if the child decides not to show up.
        if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL))
        {
            ExitWithLastError(hr, "Failed to set pipe to non-blocking.");
        }

        // Loop for a while waiting for a connection from child process.
        DWORD cRetry = 0;
        do
        {
            if (!::ConnectNamedPipe(hPipe, NULL))
            {
                DWORD er = ::GetLastError();
                if (ERROR_PIPE_CONNECTED == er)
                {
                    hr = S_OK;
                    break;
                }
                else if (ERROR_PIPE_LISTENING == er)
                {
                    if (cRetry < PIPE_RETRY_FOR_CONNECTION)
                    {
                        hr = HRESULT_FROM_WIN32(er);
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
                        break;
                    }

                    ++cRetry;
                    ::Sleep(PIPE_WAIT_FOR_CONNECTION);
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(er);
                    break;
                }
            }
        } while (HRESULT_FROM_WIN32(ERROR_PIPE_LISTENING) == hr);
        ExitOnRootFailure(hr, "Failed to wait for child to connect to pipe.");

        // Put the pipe back in blocking mode.
        dwPipeState = PIPE_READMODE_BYTE | PIPE_WAIT;
        if (!::SetNamedPipeHandleState(hPipe, &dwPipeState, NULL, NULL))
        {
            ExitWithLastError(hr, "Failed to reset pipe to blocking.");
        }

        // Prove we are the one that created the elevated process by passing the secret.
        if (!::WriteFile(hPipe, &cbSecret, sizeof(cbSecret), &cb, NULL))
        {
            ExitWithLastError(hr, "Failed to write secret length to pipe.");
        }

        if (!::WriteFile(hPipe, wzSecret, cbSecret, &cb, NULL))
        {
            ExitWithLastError(hr, "Failed to write secret to pipe.");
        }

        if (!::WriteFile(hPipe, &dwCurrentProcessId, sizeof(dwCurrentProcessId), &cb, NULL))
        {
            ExitWithLastError(hr, "Failed to write our process id to pipe.");
        }

        // Wait until the elevated process responds that it is ready to go.
        if (!::ReadFile(hPipe, &dwAck, sizeof(dwAck), &cb, NULL))
        {
            ExitWithLastError(hr, "Failed to read ACK from pipe.");
        }

        // The ACK should match out expected child process id.
        //if (pConnection->dwProcessId != dwAck)
        //{
        //    hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
        //    ExitOnRootFailure1(hr, "Incorrect ACK from elevated pipe: %u", dwAck);
        //}
    }

LExit:
    return hr;
}
コード例 #19
0
ファイル: detect.cpp プロジェクト: 925coder/wix3
static HRESULT DetectAtomFeedUpdate(
    __in_z LPCWSTR wzBundleId,
    __in BURN_USER_EXPERIENCE* pUX,
    __in BURN_UPDATE* pUpdate
    )
{
    Assert(pUpdate && pUpdate->sczUpdateSource && *pUpdate->sczUpdateSource);
#ifdef DEBUG
    LogLine(REPORT_STANDARD, "DetectAtomFeedUpdate() - update location: %ls", pUpdate->sczUpdateSource);
#endif


    HRESULT hr = S_OK;
    int nResult = IDNOACTION;
    LPWSTR sczUpdateFeedTempFile = NULL;

    ATOM_FEED* pAtomFeed = NULL;
    APPLICATION_UPDATE_CHAIN* pApupChain = NULL;

    hr = AtomInitialize();
    ExitOnFailure(hr, "Failed to initialize Atom.");

    hr = DownloadUpdateFeed(wzBundleId, pUX, pUpdate, &sczUpdateFeedTempFile);
    ExitOnFailure(hr, "Failed to download update feed.");

    hr = AtomParseFromFile(sczUpdateFeedTempFile, &pAtomFeed);
    ExitOnFailure1(hr, "Failed to parse update atom feed: %ls.", sczUpdateFeedTempFile);

    hr = ApupAllocChainFromAtom(pAtomFeed, &pApupChain);
    ExitOnFailure(hr, "Failed to allocate update chain from atom feed.");

    if (0 < pApupChain->cEntries)
    {
        for (DWORD i = 0; i < pApupChain->cEntries; ++i)
        {
            APPLICATION_UPDATE_ENTRY* pAppUpdateEntry = &pApupChain->rgEntries[i];

            nResult = pUX->pUserExperience->OnDetectUpdate(pAppUpdateEntry->rgEnclosures ? pAppUpdateEntry->rgEnclosures->wzUrl : NULL, 
                pAppUpdateEntry->rgEnclosures ? pAppUpdateEntry->rgEnclosures->dw64Size : 0, 
                pAppUpdateEntry->dw64Version, pAppUpdateEntry->wzTitle,
                pAppUpdateEntry->wzSummary, pAppUpdateEntry->wzContentType, pAppUpdateEntry->wzContent, IDNOACTION);

            switch (nResult)
            {
                case IDNOACTION:
                    hr = S_OK;
                    continue;
                case IDOK:   
                    pUpdate->fUpdateAvailable = TRUE;
                    hr = S_OK;
                    break;
                case IDCANCEL:
                    hr = S_FALSE;
                    break;
                default:
                    ExitOnRootFailure(hr = E_INVALIDDATA, "UX aborted detect update begin.");
            }
            break;
        }
    }

LExit:
    if (sczUpdateFeedTempFile && *sczUpdateFeedTempFile)
    {
        FileEnsureDelete(sczUpdateFeedTempFile);
    }

    ApupFreeChain(pApupChain);
    AtomFreeFeed(pAtomFeed);
    ReleaseStr(sczUpdateFeedTempFile);
    AtomUninitialize();

    return hr;
}
コード例 #20
0
ファイル: pipe.cpp プロジェクト: firegiant/wix3
/*******************************************************************
 PipePumpMessages - 

*******************************************************************/
extern "C" HRESULT PipePumpMessages(
    __in HANDLE hPipe,
    __in_opt PFN_PIPE_MESSAGE_CALLBACK pfnCallback,
    __in_opt LPVOID pvContext,
    __in BURN_PIPE_RESULT* pResult
    )
{
    HRESULT hr = S_OK;
    BURN_PIPE_MESSAGE msg = { };
    SIZE_T iData = 0;
    LPSTR sczMessage = NULL;
    DWORD dwResult = 0;

    // Pump messages from child process.
    while (S_OK == (hr = GetPipeMessage(hPipe, &msg)))
    {
        switch (msg.dwMessage)
        {
        case BURN_PIPE_MESSAGE_TYPE_LOG:
            iData = 0;

            hr = BuffReadStringAnsi((BYTE*)msg.pvData, msg.cbData, &iData, &sczMessage);
            ExitOnFailure(hr, "Failed to read log message.");

            hr = LogStringWorkRaw(sczMessage);
            ExitOnFailure1(hr, "Failed to write log message:'%hs'.", sczMessage);

            dwResult = static_cast<DWORD>(hr);
            break;

        case BURN_PIPE_MESSAGE_TYPE_COMPLETE:
            if (!msg.pvData || sizeof(DWORD) != msg.cbData)
            {
                hr = E_INVALIDARG;
                ExitOnRootFailure(hr, "No status returned to PipePumpMessages()");
            }

            pResult->dwResult = *static_cast<DWORD*>(msg.pvData);
            ExitFunction1(hr = S_OK); // exit loop.

        case BURN_PIPE_MESSAGE_TYPE_TERMINATE:
            iData = 0;

            hr = BuffReadNumber(static_cast<BYTE*>(msg.pvData), msg.cbData, &iData, &pResult->dwResult);
            ExitOnFailure(hr, "Failed to read returned result to PipePumpMessages()");

            if (sizeof(DWORD) * 2 == msg.cbData)
            {
                hr = BuffReadNumber(static_cast<BYTE*>(msg.pvData), msg.cbData, &iData, (DWORD*)&pResult->fRestart);
                ExitOnFailure(hr, "Failed to read returned restart to PipePumpMessages()");
            }

            ExitFunction1(hr = S_OK); // exit loop.

        default:
            if (pfnCallback)
            {
                hr = pfnCallback(&msg, pvContext, &dwResult);
            }
            else
            {
                hr = E_INVALIDARG;
            }
            ExitOnFailure1(hr, "Failed to process message: %u", msg.dwMessage);
            break;
        }

        // post result
        hr = WritePipeMessage(hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_COMPLETE), &dwResult, sizeof(dwResult));
        ExitOnFailure(hr, "Failed to post result to child process.");

        FreePipeMessage(&msg);
    }
    ExitOnFailure(hr, "Failed to get message over pipe");

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

LExit:
    ReleaseStr(sczMessage);
    FreePipeMessage(&msg);

    return hr;
}
コード例 #21
0
ファイル: exeengine.cpp プロジェクト: 925coder/wix3
extern "C" HRESULT ExeEngineExecutePackage(
    __in BURN_EXECUTE_ACTION* pExecuteAction,
    __in BURN_VARIABLES* pVariables,
    __in BOOL fRollback,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out BOOTSTRAPPER_APPLY_RESTART* pRestart
    )
{
    HRESULT hr = S_OK;
    WCHAR wzCurrentDirectory[MAX_PATH] = { };
    BOOL fChangedCurrentDirectory = FALSE;
    int nResult = IDNOACTION;
    LPCWSTR wzArguments = NULL;
    LPWSTR sczArgumentsFormatted = NULL;
    LPWSTR sczArgumentsObfuscated = NULL;
    LPWSTR sczCachedDirectory = NULL;
    LPWSTR sczExecutablePath = NULL;
    LPWSTR sczCommand = NULL;
    LPWSTR sczCommandObfuscated = NULL;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    DWORD dwExitCode = 0;
    GENERIC_EXECUTE_MESSAGE message = { };

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

    // Best effort to set the execute package cache folder variable.
    VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE);

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

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

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

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

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

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

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

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

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

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

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

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

        // Add the list of ancestors, if any, to the burn command line.
        if (pExecuteAction->exePackage.sczAncestors)
        {
            hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
            ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");

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

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

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

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

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

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

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

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

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

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

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

    // Best effort to clear the execute package cache folder variable.
    VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, NULL, TRUE);

    return hr;
}
コード例 #22
0
ファイル: msuengine.cpp プロジェクト: AnalogJ/Wix3.6Toolset
extern "C" HRESULT MsuEngineExecutePackage(
    __in BURN_EXECUTE_ACTION* pExecuteAction,
    __in BOOL fRollback,
    __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
    __in LPVOID pvContext,
    __out BOOTSTRAPPER_APPLY_RESTART* pRestart
    )
{
    HRESULT hr = S_OK;
    int nResult = IDNOACTION;
    LPWSTR sczCachedDirectory = NULL;
    LPWSTR sczMsuPath = NULL;
    LPWSTR sczSystemPath = NULL;
    LPWSTR sczWusaPath = NULL;
    LPWSTR sczCommand = NULL;
    SC_HANDLE schWu = NULL;
    BOOL fWuWasDisabled = FALSE;
    STARTUPINFOW si = { };
    PROCESS_INFORMATION pi = { };
    GENERIC_EXECUTE_MESSAGE message = { };
    DWORD dwExitCode = 0;
    BOOL fDoDependency = FALSE;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    default:
        hr = E_UNEXPECTED;
        break;
    }

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

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

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

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

    return hr;
}
コード例 #23
0
ファイル: engine.cpp プロジェクト: Alyoshak/wix3
static HRESULT RunApplication(
    __in BURN_ENGINE_STATE* pEngineState,
    __out BOOL* pfReloadApp
    )
{
    HRESULT hr = S_OK;
    DWORD dwThreadId = 0;
    IBootstrapperEngine* pEngineForApplication = NULL;
    BOOL fStartupCalled = FALSE;
    BOOL fRet = FALSE;
    MSG msg = { };

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

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

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

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

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

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

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

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

    ReleaseObject(pEngineForApplication);

    return hr;
}
コード例 #24
0
ファイル: detect.cpp プロジェクト: 925coder/wix3
extern "C" HRESULT DetectForwardCompatibleBundle(
    __in BURN_USER_EXPERIENCE* pUX,
    __in BOOTSTRAPPER_COMMAND* pCommand,
    __in BURN_REGISTRATION* pRegistration
    )
{
    HRESULT hr = S_OK;
    int nRecommendation = IDNOACTION;

    if (pRegistration->sczDetectedProviderKeyBundleId &&
        CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRegistration->sczId, -1))
    {
        // Only change the recommendation if an parent was provided.
        if (pRegistration->sczActiveParent && *pRegistration->sczActiveParent)
        {
            // On install, recommend running the forward compatible bundle because there is an active parent. This
            // will essentially register the parent with the forward compatible bundle.
            if (BOOTSTRAPPER_ACTION_INSTALL == pCommand->action)
            {
                nRecommendation = IDOK;
            }
            else if (BOOTSTRAPPER_ACTION_UNINSTALL == pCommand->action ||
                     BOOTSTRAPPER_ACTION_MODIFY == pCommand->action ||
                     BOOTSTRAPPER_ACTION_REPAIR == pCommand->action)
            {
                // When modifying the bundle, only recommend running the forward compatible bundle if the parent
                // is already registered as a dependent of the provider key.
                if (DependencyDependentExists(pRegistration, pRegistration->sczActiveParent))
                {
                    nRecommendation = IDOK;
                }
            }
        }

        for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle)
        {
            BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;

            if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType &&
                pRegistration->qwVersion <= pRelatedBundle->qwVersion &&
                CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1))
            {
                int nResult = pUX->pUserExperience->OnDetectForwardCompatibleBundle(pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->qwVersion, nRecommendation);
                hr = UserExperienceInterpretResult(pUX, MB_OKCANCEL, nResult);
                ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle.");

                if (IDOK == nResult)
                {
                    hr = PseudoBundleInitializePassthrough(&pRegistration->forwardCompatibleBundle, pCommand, NULL, pRegistration->sczActiveParent, pRegistration->sczAncestors, &pRelatedBundle->package);
                    ExitOnFailure(hr, "Failed to initialize update bundle.");

                    pRegistration->fEnabledForwardCompatibleBundle = TRUE;
                }

                LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), LoggingVersionToString(pRelatedBundle->qwVersion), LoggingBoolToString(pRegistration->fEnabledForwardCompatibleBundle));
                break;
            }
        }
    }

LExit:
    return hr;
}
コード例 #25
0
ファイル: mspengine.cpp プロジェクト: firegiant/wix4
//
// PlanCalculate - calculates the execute and rollback state for the requested package state.
//
extern "C" HRESULT MspEnginePlanCalculatePackage(
    __in BURN_PACKAGE* pPackage,
    __in BURN_USER_EXPERIENCE* pUserExperience,
    __out BOOL* pfBARequestedCache
    )
{
    HRESULT hr = S_OK;
    BOOL fBARequestedCache = FALSE;

    for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
    {
        BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;

        BOOTSTRAPPER_REQUEST_STATE requested = pPackage->requested;
        BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
        BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;

        int nResult = pUserExperience->pUserExperience->OnPlanTargetMsiPackage(pPackage->sczId, pTargetProduct->wzTargetProductCode, &requested);
        hr = UserExperienceInterpretResult(pUserExperience, MB_OKCANCEL, nResult);
        ExitOnRootFailure(hr, "UX aborted plan target MSI package.");

        // Calculate the execute action.
        switch (pTargetProduct->patchPackageState)
        {
        case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
            switch (requested)
            {
            case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
                execute = BOOTSTRAPPER_ACTION_STATE_REPAIR;
                break;

            case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_CACHE:
                execute = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
                break;

            case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
                execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
                break;

            default:
                execute = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
            break;

        case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
            switch (requested)
            {
            case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
                execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
                break;

            case BOOTSTRAPPER_REQUEST_STATE_CACHE:
                execute = BOOTSTRAPPER_ACTION_STATE_NONE;
                fBARequestedCache = TRUE;
                break;

            default:
                execute = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
            break;
        }

        // Calculate the rollback action if there is an execute action.
        if (BOOTSTRAPPER_ACTION_STATE_NONE != execute)
        {
            switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState)
            {
            case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
                switch (requested)
                {
                case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
                case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
                    rollback = BOOTSTRAPPER_ACTION_STATE_INSTALL;
                    break;

                default:
                    rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                    break;
                }
                break;

            case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: __fallthrough;
            case BOOTSTRAPPER_PACKAGE_STATE_CACHED:
                switch (requested)
                {
                case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
                case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
                    rollback = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
                    break;

                default:
                    rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                    break;
                }
                break;

            default:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
        }

        pTargetProduct->execute = execute;
        pTargetProduct->rollback = rollback;

        // The highest aggregate action state found will be returned.
        if (pPackage->execute < execute)
        {
            pPackage->execute = execute;
        }

        if (pPackage->rollback < rollback)
        {
            pPackage->rollback = rollback;
        }
    }

    if (pfBARequestedCache)
    {
        *pfBARequestedCache = fBARequestedCache;
    }

LExit:

    return hr;
}
コード例 #26
0
ファイル: mspengine.cpp プロジェクト: firegiant/wix4
extern "C" HRESULT MspEngineDetectPackage(
    __in BURN_PACKAGE* pPackage,
    __in BURN_USER_EXPERIENCE* pUserExperience
    )
{
    HRESULT hr = S_OK;
    int nResult = IDOK;
    LPWSTR sczState = NULL;

    if (0 == pPackage->Msp.cTargetProductCodes)
    {
        pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
    }
    else
    {
        // Start the package state at the the highest state then loop through all the
        // target product codes and end up setting the current state to the lowest
        // package state applied to the the target product codes.
        pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;

        for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
        {
            BURN_MSPTARGETPRODUCT* pTargetProduct = pPackage->Msp.rgTargetProducts + i;

            hr = WiuGetPatchInfoEx(pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode, NULL, pTargetProduct->context, INSTALLPROPERTY_PATCHSTATE, &sczState);
            if (SUCCEEDED(hr))
            {
                switch (*sczState)
                {
                case '1':
                    pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
                    break;

                case '2':
                    pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_SUPERSEDED;
                    break;

                case '4':
                    pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE;
                    break;

                default:
                    pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
                    break;
                }
            }
            else if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PATCH) == hr)
            {
                pTargetProduct->patchPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
                hr = S_OK;
            }
            ExitOnFailure(hr, "Failed to get patch information for patch code: %ls, target product code: %ls", pPackage->Msp.sczPatchCode, pTargetProduct->wzTargetProductCode);

            if (pPackage->currentState > pTargetProduct->patchPackageState)
            {
                pPackage->currentState = pTargetProduct->patchPackageState;
            }

            nResult = pUserExperience->pUserExperience->OnDetectTargetMsiPackage(pPackage->sczId, pTargetProduct->wzTargetProductCode, pTargetProduct->patchPackageState);
            hr = UserExperienceInterpretResult(pUserExperience, MB_OKCANCEL, nResult);
            ExitOnRootFailure(hr, "UX aborted detect target MSI package.");
        }
    }

LExit:
    ReleaseStr(sczState);

    return hr;
}
コード例 #27
0
ファイル: detect.cpp プロジェクト: 925coder/wix3
extern "C" HRESULT DetectReportRelatedBundles(
    __in BURN_USER_EXPERIENCE* pUX,
    __in BURN_REGISTRATION* pRegistration,
    __in BOOTSTRAPPER_RELATION_TYPE relationType,
    __in BOOTSTRAPPER_ACTION action
    )
{
    HRESULT hr = S_OK;

    for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle)
    {
        const BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
        BOOTSTRAPPER_RELATED_OPERATION operation = BOOTSTRAPPER_RELATED_OPERATION_NONE;

        switch (pRelatedBundle->relationType)
        {
        case BOOTSTRAPPER_RELATION_UPGRADE:
            if (BOOTSTRAPPER_RELATION_UPGRADE != relationType && BOOTSTRAPPER_ACTION_UNINSTALL < action)
            {
                if (pRegistration->qwVersion > pRelatedBundle->qwVersion)
                {
                    operation = BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE;
                }
                else if (pRegistration->qwVersion < pRelatedBundle->qwVersion)
                {
                    operation = BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE;
                }
            }
            break;

        case BOOTSTRAPPER_RELATION_PATCH: __fallthrough;
        case BOOTSTRAPPER_RELATION_ADDON:
            if (BOOTSTRAPPER_ACTION_UNINSTALL == action)
            {
                operation = BOOTSTRAPPER_RELATED_OPERATION_REMOVE;
            }
            else if (BOOTSTRAPPER_ACTION_INSTALL == action || BOOTSTRAPPER_ACTION_MODIFY == action)
            {
                operation = BOOTSTRAPPER_RELATED_OPERATION_INSTALL;
            }
            else if (BOOTSTRAPPER_ACTION_REPAIR == action)
            {
                operation = BOOTSTRAPPER_RELATED_OPERATION_REPAIR;
            }
            break;

        case BOOTSTRAPPER_RELATION_DETECT: __fallthrough;
        case BOOTSTRAPPER_RELATION_DEPENDENT:
            break;

        default:
            hr = E_FAIL;
            ExitOnRootFailure1(hr, "Unexpected relation type encountered: %d", pRelatedBundle->relationType);
            break;
        }

        LogId(REPORT_STANDARD, MSG_DETECTED_RELATED_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), LoggingVersionToString(pRelatedBundle->qwVersion), LoggingRelatedOperationToString(operation));

        int nResult = pUX->pUserExperience->OnDetectRelatedBundle(pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->qwVersion, operation);
        hr = UserExperienceInterpretResult(pUX, MB_OKCANCEL, nResult);
        ExitOnRootFailure(hr, "BA aborted detect related bundle.");
    }

LExit:
    return hr;
}
コード例 #28
0
ファイル: exeengine.cpp プロジェクト: 925coder/wix3
//
// PlanCalculate - calculates the execute and rollback state for the requested package state.
//
extern "C" HRESULT ExeEnginePlanCalculatePackage(
    __in BURN_PACKAGE* pPackage
    )
{
    HRESULT hr = S_OK;
    //BOOL fCondition = FALSE;
    //BOOTSTRAPPER_PACKAGE_STATE expected = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN;
    BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
    BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;

    //// evaluate rollback install condition
    //if (pPackage->sczRollbackInstallCondition)
    //{
    //    hr = ConditionEvaluate(pVariables, pPackage->sczRollbackInstallCondition, &fCondition);
    //    ExitOnFailure(hr, "Failed to evaluate rollback install condition.");

    //    expected = fCondition ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
    //}

    // execute action
    switch (pPackage->currentState)
    {
    case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
        switch (pPackage->requested)
        {
        case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
            execute = pPackage->Exe.fPseudoBundle ? BOOTSTRAPPER_ACTION_STATE_INSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
            break;
        case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
            execute = pPackage->Exe.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE;
            break;
        case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
            execute = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
            break;
        case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
            execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
            break;
        default:
            execute = BOOTSTRAPPER_ACTION_STATE_NONE;
        }
        break;

    case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
        switch (pPackage->requested)
        {
        case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
        case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
            execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
            break;
        case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
        case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
            execute = BOOTSTRAPPER_ACTION_STATE_NONE;
            break;
        default:
            execute = BOOTSTRAPPER_ACTION_STATE_NONE;
        }
        break;

    default:
        hr = E_INVALIDARG;
        ExitOnRootFailure1(hr, "Invalid package current state: %d.", pPackage->currentState);
    }

    // Calculate the rollback action if there is an execute action.
    if (BOOTSTRAPPER_ACTION_STATE_NONE != execute)
    {
        switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState)
        {
        case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
            switch (pPackage->requested)
            {
            case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
                rollback = BOOTSTRAPPER_ACTION_STATE_INSTALL;
                break;
            default:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
            break;

        case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
            switch (pPackage->requested)
            {
            case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
                rollback = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            default:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
            break;

        default:
            hr = E_INVALIDARG;
            ExitOnRootFailure(hr, "Invalid package expected state.");
        }
    }

    // return values
    pPackage->execute = execute;
    pPackage->rollback = rollback;

LExit:
    return hr;
}
コード例 #29
0
ファイル: pipe.cpp プロジェクト: firegiant/wix4
/*******************************************************************
 PipeChildConnect - Called from the child process to connect back
                    to the pipe provided by the parent process.

*******************************************************************/
extern "C" HRESULT PipeChildConnect(
    __in BURN_PIPE_CONNECTION* pConnection,
    __in BOOL fConnectCachePipe
    )
{
    Assert(pConnection->sczName);
    Assert(pConnection->sczSecret);
    Assert(!pConnection->hProcess);
    Assert(INVALID_HANDLE_VALUE == pConnection->hPipe);
    Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe);

    HRESULT hr = S_OK;
    LPWSTR sczPipeName = NULL;

    // Try to connect to the parent.
    hr = StrAllocFormatted(&sczPipeName, PIPE_NAME_FORMAT_STRING, pConnection->sczName);
    ExitOnFailure(hr, "Failed to allocate name of parent pipe.");

    hr = E_UNEXPECTED;
    for (DWORD cRetry = 0; FAILED(hr) && cRetry < PIPE_RETRY_FOR_CONNECTION; ++cRetry)
    {
        pConnection->hPipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (INVALID_HANDLE_VALUE == pConnection->hPipe)
        {
            hr = HRESULT_FROM_WIN32(::GetLastError());
            if (E_FILENOTFOUND == hr) // if the pipe isn't created, call it a timeout waiting on the parent.
            {
                hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
            }

            ::Sleep(PIPE_WAIT_FOR_CONNECTION);
        }
        else // we have a connection, go with it.
        {
            hr = S_OK;
        }
    }
    ExitOnRootFailure(hr, "Failed to open parent pipe: %ls", sczPipeName)

    // Verify the parent and notify it that the child connected.
    hr = ChildPipeConnected(pConnection->hPipe, pConnection->sczSecret, &pConnection->dwProcessId);
    ExitOnFailure(hr, "Failed to verify parent pipe: %ls", sczPipeName);

    if (fConnectCachePipe)
    {
        // Connect to the parent for the cache pipe.
        hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName);
        ExitOnFailure(hr, "Failed to allocate name of parent cache pipe.");

        pConnection->hCachePipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (INVALID_HANDLE_VALUE == pConnection->hCachePipe)
        {
            ExitWithLastError(hr, "Failed to open parent pipe: %ls", sczPipeName)
        }

        // Verify the parent and notify it that the child connected.
        hr = ChildPipeConnected(pConnection->hCachePipe, pConnection->sczSecret, &pConnection->dwProcessId);
        ExitOnFailure(hr, "Failed to verify parent pipe: %ls", sczPipeName);
    }

    pConnection->hProcess = ::OpenProcess(SYNCHRONIZE, FALSE, pConnection->dwProcessId);
    ExitOnNullWithLastError(pConnection->hProcess, hr, "Failed to open companion process with PID: %u", pConnection->dwProcessId);

LExit:
    ReleaseStr(sczPipeName);

    return hr;
}
コード例 #30
0
ファイル: msuengine.cpp プロジェクト: AnalogJ/Wix3.6Toolset
//
// PlanCalculate - calculates the execute and rollback state for the requested package state.
//
extern "C" HRESULT MsuEnginePlanCalculatePackage(
    __in BURN_PACKAGE* pPackage
    )
{
    HRESULT hr = S_OK;
    BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
    BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;

    BOOL fAllowUninstall = FALSE;
    OS_VERSION osVersion = OS_VERSION_UNKNOWN;
    DWORD dwServicePack = 0;

    // We can only uninstall MSU packages if they have a KB and we are on Win7 or newer.
    OsGetVersion(&osVersion, &dwServicePack);
    fAllowUninstall = pPackage->fUninstallable && (pPackage->Msu.sczKB && *pPackage->Msu.sczKB) && OS_VERSION_WIN7 <= osVersion;

    // execute action
    switch (pPackage->currentState)
    {
    case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
        switch (pPackage->requested)
        {
        case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
        case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
            execute = BOOTSTRAPPER_ACTION_STATE_NONE;
            break;

        case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
            execute = fAllowUninstall ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
            break;

        default:
            execute = BOOTSTRAPPER_ACTION_STATE_NONE;
        }
        break;

    case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
        switch (pPackage->requested)
        {
        case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
        case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
            execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
            break;

        default:
            execute = BOOTSTRAPPER_ACTION_STATE_NONE;
        }
        break;

    default:
        hr = E_INVALIDARG;
        ExitOnRootFailure(hr, "Invalid package state.");
    }

    // Calculate the rollback action if there is an execute action.
    if (BOOTSTRAPPER_ACTION_STATE_NONE != execute)
    {
        switch (BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN != pPackage->expected ? pPackage->expected : pPackage->currentState)
        {
        case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
            switch (pPackage->requested)
            {
            case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
                rollback = BOOTSTRAPPER_ACTION_STATE_INSTALL;
                break;

            default:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
            break;

        case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
            switch (pPackage->requested)
            {
            case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
            case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
                rollback = fAllowUninstall ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
                break;

            default:
                rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
                break;
            }
            break;

        default:
            hr = E_INVALIDARG;
            ExitOnRootFailure(hr, "Invalid package expected state.");
        }
    }

    // return values
    pPackage->execute = execute;
    pPackage->rollback = rollback;

LExit:
    return hr;
}