Example #1
0
extern "C" HRESULT DisplayStart(
    __in HINSTANCE hInstance,
    __in HWND hWnd,
    __out HANDLE *phThread,
    __out DWORD* pdwThreadId
    )
{
    HRESULT hr = S_OK;
    HANDLE rgHandles[2] = { };
    DISPLAY_THREAD_CONTEXT context = { };

    rgHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL);
    ExitOnNullWithLastError(rgHandles[0], hr, "Failed to create load init event.");

    context.hWnd = hWnd;
    context.hInstance = hInstance;
    context.hInit = rgHandles[0];

    rgHandles[1] = ::CreateThread(NULL, 0, DisplayThreadProc, reinterpret_cast<LPVOID>(&context), 0, pdwThreadId);
    ExitOnNullWithLastError(rgHandles[1], hr, "Failed to create display thread.");

    ::WaitForMultipleObjects(countof(rgHandles), rgHandles, FALSE, INFINITE);

    *phThread = rgHandles[1];
    rgHandles[1] = NULL;

LExit:
    ReleaseHandle(rgHandles[1]);
    ReleaseHandle(rgHandles[0]);
    return hr;
}
Example #2
0
static HRESULT CreateMessageWindow(
    __out HWND* phWnd
    )
{
    HRESULT hr = S_OK;
    HANDLE rgWaitHandles[2] = { };
    UITHREAD_CONTEXT context = { };

    // Create event to signal after the UI thread / window is initialized.
    rgWaitHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL);
    ExitOnNullWithLastError(rgWaitHandles[0], hr, "Failed to create initialization event.");

    // Pass necessary information to create the window.
    context.hInitializedEvent = rgWaitHandles[0];
    context.hInstance = (HINSTANCE)g_hInstCADLL;

    // Create our separate UI thread.
    rgWaitHandles[1] = ::CreateThread(NULL, 0, ThreadProc, &context, 0, NULL);
    ExitOnNullWithLastError(rgWaitHandles[1], hr, "Failed to create the UI thread.");

    // Wait for either the thread to be initialized or the window to exit / fail prematurely.
    ::WaitForMultipleObjects(countof(rgWaitHandles), rgWaitHandles, FALSE, INFINITE);

    // Pass the window back to the caller.
    *phWnd = context.hWnd;

LExit:
    ReleaseHandle(rgWaitHandles[1]);
    ReleaseHandle(rgWaitHandles[0]);

    return hr;
}
Example #3
0
void CALLBACK my_InternetStatusCallback(HINTERNET hRequest, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
	LPINTERNET_ASYNC_RESULT	AsyncResult = (LPINTERNET_ASYNC_RESULT) lpvStatusInformation;
	INTERNET_STATUS_CALLBACK RealInetCallback;
	PHANDLE_CONTEXT Ctx;

	ENTER_HOOK();

	if (Ctx = FindHandle(hRequest))
	{
		switch (dwInternetStatus)
		{
		case INTERNET_STATUS_HANDLE_CLOSING:
			DelHandle(hRequest);
			break;
		case INTERNET_STATUS_REQUEST_COMPLETE:
			if (Ctx->Status == DOWNLOADING)
			{
				if (!AsyncResult->dwResult)
					Ctx->Status = ERROR_WHILE_LOADING;

				SetEvent(Ctx->AsyncEvent);

				ReleaseHandle(Ctx);
				LEAVE_HOOK();
				return;
			}	// if (Ctx->Status == DOWNLOADING)
			else
			{
				ULONG	HttpStatus, bSize = sizeof(ULONG);
				if (HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, &HttpStatus, &bSize, &bSize))
				{
					if (HttpStatus == 1)
					{
						__debugbreak();
					}
					
				}
				else
					bSize = GetLastError();
			}
			break;
		default:
			break;
		}	// switch (dwInternetStatus)
		
		if (RealInetCallback = Ctx->Callback)
		{
			ASSERT((LONG_PTR)Ctx->Callback > 0);	// User-mode address
			(RealInetCallback) (hRequest, dwContext, dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
		}

		ReleaseHandle(Ctx);
	}	// if (Ctx = FindHandle(hInternet))

	LEAVE_HOOK();
}
Example #4
0
//
//	Common routine for InternetReadFileExA and InternetReadFileExW hooks.
//
static BOOL CommonInternetReadFileEx(
	HINTERNET			hFile, 
	LPINTERNET_BUFFERS	lpBuffersOut, 
	DWORD				dwFlags, 
	DWORD_PTR			dwContext, 
	BOOL				IsUnicode
	)
{
	BOOL Ret = FALSE;
	PHANDLE_CONTEXT	Ctx;

	if (Ctx = IeGetContext(hFile))
	{
		do	// not a loop
		{
			GetPageContent(Ctx, hFile);

			lpBuffersOut->dwBufferTotal = lpBuffersOut->dwBufferLength;
			if (CoInvoke(Ctx->pStream, Read, lpBuffersOut->lpvBuffer, lpBuffersOut->dwBufferLength, &lpBuffersOut->dwBufferLength) == S_OK)
				Ret = TRUE;

		} while(FALSE);

		ReleaseHandle(Ctx);
	}
	else
	{
		if (IsUnicode)
			Ret = InternetReadFileExW(hFile, (LPINTERNET_BUFFERSW)lpBuffersOut, dwFlags, dwContext);
		else
			Ret = InternetReadFileExA(hFile, lpBuffersOut, dwFlags, dwContext);
	}

	return(Ret);
}
Example #5
0
/*******************************************************************
 PipeLaunchChildProcess - Called from the per-user process to create
                          the per-machine process and set up the
                          communication pipe.

*******************************************************************/
extern "C" HRESULT PipeLaunchChildProcess(
    __in_z LPCWSTR wzExecutablePath,
    __in BURN_PIPE_CONNECTION* pConnection,
    __in BOOL fElevate,
    __in_opt HWND hwndParent
    )
{
    HRESULT hr = S_OK;
    DWORD dwCurrentProcessId = ::GetCurrentProcessId();
    LPWSTR sczParameters = NULL;
    OS_VERSION osVersion = OS_VERSION_UNKNOWN;
    DWORD dwServicePack = 0;
    LPCWSTR wzVerb = NULL;
    HANDLE hProcess = NULL;

    hr = StrAllocFormatted(&sczParameters, L"-q -%ls %ls %ls %u", BURN_COMMANDLINE_SWITCH_ELEVATED, pConnection->sczName, pConnection->sczSecret, dwCurrentProcessId);
    ExitOnFailure(hr, "Failed to allocate parameters for elevated process.");

    OsGetVersion(&osVersion, &dwServicePack);
    wzVerb = (OS_VERSION_VISTA > osVersion) || !fElevate ? L"open" : L"runas";

    hr = ShelExec(wzExecutablePath, sczParameters, wzVerb, NULL, SW_HIDE, hwndParent, &hProcess);
    ExitOnFailure(hr, "Failed to launch elevated child process: %ls", wzExecutablePath);

    pConnection->dwProcessId = ::GetProcessId(hProcess);
    pConnection->hProcess = hProcess;
    hProcess = NULL;

LExit:
    ReleaseHandle(hProcess);
    ReleaseStr(sczParameters);

    return hr;
}
Example #6
0
BOOL WINAPI my_InternetQueryDataAvailable(HINTERNET hFile, LPDWORD lpdwNumberOfBytesAvailable, DWORD dwFlags, DWORD_PTR dwContext)
{
	BOOL Ret = FALSE;
	PHANDLE_CONTEXT Ctx;
	
	ENTER_HOOK();

	*lpdwNumberOfBytesAvailable = 0;

	if (Ctx = IeGetContext(hFile))
	{
		do	// not a loop
		{
			ULONG	Pos;
			ULONG	Length;

			GetPageContent(Ctx, hFile);
		
			Pos = StreamGetPos(Ctx->pStream);
			Length = StreamGetLength(Ctx->pStream);
			*lpdwNumberOfBytesAvailable = Length - Pos;

			Ret = TRUE;

		} while(FALSE);

		ReleaseHandle(Ctx);
	}
	else
		Ret = InternetQueryDataAvailable( hFile, lpdwNumberOfBytesAvailable, dwFlags, dwContext);

	LEAVE_HOOK();
	return(Ret);
}
Example #7
0
LONG PRIO_Poll(
	PRPollDesc *pds, 
	LONG		npds
	)
{
	LONG i, Count = 0;

	for(i=0; i<npds; i++)
	{
		if (pds[i].in_flags & PR_POLL_READ)
		{
			PHANDLE_CONTEXT Ctx;
			if (Ctx = FindHandle(pds[i].fd))
			{
				if (StreamGetLength(Ctx->pStream))
				{
					pds[Count].fd = pds[i].fd;
					pds[Count].in_flags = pds[i].in_flags;
					pds[Count].out_flags = PR_POLL_READ;
					Count += 1;
				}
				ReleaseHandle(Ctx);
			}	// if (Ctx = FindHandle(pds[i]->fd))
		}	// if (pds[i]->in_flags & PR_POLL_READ)
	}	// for(i=0; i<npds; i++)

	return(Count);
}
VOID TaskMgrSS::ReleaseHandles( TASKSETHANDLE *phSet,UINT uSet )
{
    for( UINT uIdx = 0; uIdx < uSet; ++uIdx )
    {
        ReleaseHandle( phSet[ uIdx ] );
    }
}
Example #9
0
static HRESULT RunRunOnce(
    __in const BURN_REGISTRATION* pRegistration,
    __in int nCmdShow
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczNewCommandLine = NULL;
    LPWSTR sczBurnPath = NULL;
    HANDLE hProcess = NULL;

    hr = RegistrationGetResumeCommandLine(pRegistration, &sczNewCommandLine);
    ExitOnFailure(hr, "Unable to get resume command line from the registry");

    // and re-launch
    hr = PathForCurrentProcess(&sczBurnPath, NULL);
    ExitOnFailure(hr, "Failed to get current process path.");

    hr = ProcExec(sczBurnPath, 0 < sczNewCommandLine ? sczNewCommandLine : L"", nCmdShow, &hProcess);
    ExitOnFailure(hr, "Failed to re-launch bundle process after RunOnce: %ls", sczBurnPath);

LExit:
    ReleaseHandle(hProcess);
    ReleaseStr(sczNewCommandLine);
    ReleaseStr(sczBurnPath);

    return hr;
}
static VOID DestroyNetFxChainer(
    __in NetFxChainer* pChainer
)
{
    if (pChainer)
    {
        ReleaseHandle(pChainer->hSection);
        ReleaseHandle(pChainer->hEventChaineeSend);
        ReleaseHandle(pChainer->hEventChainerSend);
        ReleaseHandle(pChainer->hMutex);

        if (pChainer->pData)
        {
            ::UnmapViewOfFile(pChainer->pData);
        }

        MemFree(pChainer);
    }
}
Example #11
0
HRESULT PipeLaunchParentProcess(
    __in_z LPCWSTR wzCommandLine,
    __in int nCmdShow,
    __in_z LPWSTR sczConnectionName,
    __in_z LPWSTR sczSecret,
    __in BOOL /*fDisableUnelevate*/
    )
{
    HRESULT hr = S_OK;
    DWORD dwProcessId = 0;
    LPWSTR sczBurnPath = NULL;
    LPWSTR sczParameters = NULL;
    HANDLE hProcess = NULL;

    dwProcessId = ::GetCurrentProcessId();

    hr = PathForCurrentProcess(&sczBurnPath, NULL);
    ExitOnFailure(hr, "Failed to get current process path.");

    hr = StrAllocFormatted(&sczParameters, L"-%ls %ls %ls %u %ls", BURN_COMMANDLINE_SWITCH_UNELEVATED, sczConnectionName, sczSecret, dwProcessId, wzCommandLine);
    ExitOnFailure(hr, "Failed to allocate parameters for unelevated process.");

#ifdef ENABLE_UNELEVATE
    if (fDisableUnelevate)
    {
        hr = ProcExec(sczBurnPath, sczParameters, nCmdShow, &hProcess);
        ExitOnFailure1(hr, "Failed to launch parent process with unelevate disabled: %ls", sczBurnPath);
    }
    else
    {
        // Try to launch unelevated and if that fails for any reason, try launch our process normally (even though that may make it elevated).
        hr = ProcExecuteAsInteractiveUser(sczBurnPath, sczParameters, &hProcess);
        if (FAILED(hr))
        {
            hr = ShelExecUnelevated(sczBurnPath, sczParameters, L"open", NULL, nCmdShow);
            if (FAILED(hr))
            {
                hr = ShelExec(sczBurnPath, sczParameters, L"open", NULL, nCmdShow, NULL, NULL);
                ExitOnFailure1(hr, "Failed to launch parent process: %ls", sczBurnPath);
            }
        }
    }
#else
    hr = ProcExec(sczBurnPath, sczParameters, nCmdShow, &hProcess);
    ExitOnFailure1(hr, "Failed to launch parent process with unelevate disabled: %ls", sczBurnPath);
#endif

LExit:
    ReleaseHandle(hProcess);
    ReleaseStr(sczParameters);
    ReleaseStr(sczBurnPath);

    return hr;
}
Example #12
0
/*******************************************************************
 PipeConnectionUninitialize - free data in a pipe connection.

*******************************************************************/
void PipeConnectionUninitialize(
    __in BURN_PIPE_CONNECTION* pConnection
    )
{
    ReleaseFileHandle(pConnection->hCachePipe);
    ReleaseFileHandle(pConnection->hPipe);
    ReleaseHandle(pConnection->hProcess);
    ReleaseStr(pConnection->sczSecret);
    ReleaseStr(pConnection->sczName);

    memset(pConnection, 0, sizeof(BURN_PIPE_CONNECTION));
    pConnection->hPipe = INVALID_HANDLE_VALUE;
    pConnection->hCachePipe = INVALID_HANDLE_VALUE;
}
Example #13
0
extern "C" HRESULT LoadStart(
    __in_z LPCWSTR wzThemePath,
    __in HWND hWnd,
    __out HANDLE* phThread
    )
{
    HRESULT hr = S_OK;
    HANDLE rgHandles[2] = { };
    LPWSTR sczThemePath = NULL;
    LOAD_THREAD_CONTEXT context = { };

    rgHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL);
    ExitOnNullWithLastError(rgHandles[0], hr, "Failed to create load init event.");

    hr = StrAllocString(&sczThemePath, wzThemePath, 0);
    ExitOnFailure(hr, "Failed to copy path to initial theme file.");

    context.hWnd = hWnd;
    context.sczThemePath = sczThemePath;
    context.hInit = rgHandles[0];

    rgHandles[1] = ::CreateThread(NULL, 0, LoadThreadProc, &context, 0, NULL);
    ExitOnNullWithLastError(rgHandles[1], hr, "Failed to create load thread.");

    ::WaitForMultipleObjects(countof(rgHandles), rgHandles, FALSE, INFINITE);

    *phThread = rgHandles[1];
    rgHandles[1] = NULL;
    sczThemePath = NULL;

LExit:
    ReleaseHandle(rgHandles[1]);
    ReleaseHandle(rgHandles[0]);
    ReleaseStr(sczThemePath);
    return hr;
}
VOID TaskMgrSS::CompleteTaskSet( TASKSETHANDLE hSet )
{
    TaskSet*             pSet = &mSets[ hSet ];

    UINT uCount = _InterlockedDecrement( (LONG*)&pSet->muCompletionCount );

    if( 0 == uCount )
    {
        pSet->mbCompleted = TRUE;
        pSet->mpFunc = 0;
        //
        //  The task set has completed.  We need to look at the successors
        //  and signal them that this dependency of theirs has completed.
        //
        pSet->mSuccessorsLock.aquire();

        for( UINT uSuccessor = 0; uSuccessor < MAX_SUCCESSORS; ++uSuccessor )
        {
            TaskSet* pSuccessor = pSet->Successors[ uSuccessor ];

            //
            //  A signaled successor must be removed from the Successors list 
            //  before the mSuccessorsLock can be released.
            //
            pSet->Successors[ uSuccessor ] = NULL;
            
            if( NULL != pSuccessor ) 
            {
                UINT uStart;

                uStart = _InterlockedDecrement( (LONG*)&pSuccessor->muStartCount );

                //
                //  If the start count is 0 the successor has had all its 
                //  dependencies satisified and can be scheduled.
                //
                if( 0 == uStart )
                {
                    mTaskScheduler.AddTaskSet( pSuccessor->mhTaskset, pSuccessor->muSize );
                }
            }
        }

        pSet->mSuccessorsLock.release();

        ReleaseHandle( hSet );
    }
}
Example #15
0
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;
}
Example #16
0
static HRESULT RunRunOnce(
    __in_z_opt LPCWSTR wzCommandLine,
    __in int nCmdShow
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczNewCommandLine = NULL;
    LPWSTR sczBurnPath = NULL;
    HANDLE hProcess = NULL;
    int argc = 0;
    LPWSTR* argv = NULL;

    // rebuild the command line without the runonce switch
    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'/') && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RUNONCE, -1)))
            {
                PathCommandLineAppend(&sczNewCommandLine, argv[i]);
            }
        }
    }

    // and re-launch
    hr = PathForCurrentProcess(&sczBurnPath, NULL);
    ExitOnFailure(hr, "Failed to get current process path.");

    hr = ProcExec(sczBurnPath, 0 < sczNewCommandLine ? sczNewCommandLine : L"", nCmdShow, &hProcess);
    ExitOnFailure1(hr, "Failed to re-launch bundle process after RunOnce: %ls", sczBurnPath);

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

    ReleaseHandle(hProcess);
    ReleaseStr(sczNewCommandLine);
    ReleaseStr(sczBurnPath);

    return hr;
}
Example #17
0
//
//	Performs handle check and returns handle-associated context.
//
static PHANDLE_CONTEXT IeGetContext(HANDLE	hRequest)
{
	PHANDLE_CONTEXT Ctx = NULL;

	if (Ctx = FindHandle(hRequest))
	{
		if (!(Ctx->Flags & (CF_SKIP | CF_CONTENT)))
		{
			Ctx->Flags |= CF_SKIP;

			// Checking content type
			if ((Ctx->Flags & CF_REPLACE) || IeCheckContentType(hRequest))
			{
				ULONG	bLen = 0;
				ASSERT(Ctx->Url == NULL);

				// Querying the URL
				InternetQueryOption(hRequest, INTERNET_OPTION_URL, NULL, &bLen);
				if ((bLen) && (Ctx->Url = hAlloc(bLen + sizeof(_TCHAR))))
				{
					if (InternetQueryOption(hRequest, INTERNET_OPTION_URL, Ctx->Url, &bLen))
					{
						Ctx->Url[bLen] = 0;
						Ctx->Flags |= CF_CONTENT;
						Ctx->Flags ^= CF_SKIP;
					}
					else
					{
						hFree(Ctx->Url);
						Ctx->Url = NULL;
					}
				}	// if ((bLen) && (Ctx->Url = hAlloc(bLen + sizeof(_TCHAR))))
			}	// if (IeCheckContentType(hFile))
		}	// if (!(Ctx->Flags & (CF_SKIP | CF_CONTENT)))

		if (Ctx->Flags & CF_SKIP)
		{
			ReleaseHandle(Ctx);
			Ctx = NULL;
		}
	}	// if (Ctx = FindHandle(hFile))

	return(Ctx);
}
Example #18
0
static void UninitializeEngineState(
    __in BURN_ENGINE_STATE* pEngineState
    )
{
    ReleaseStr(pEngineState->sczIgnoreDependencies);

    PipeConnectionUninitialize(&pEngineState->embeddedConnection);
    PipeConnectionUninitialize(&pEngineState->companionConnection);
    ReleaseStr(pEngineState->sczBundleEngineWorkingPath)

    ReleaseHandle(pEngineState->hMessageWindowThread);

    ::DeleteCriticalSection(&pEngineState->userExperience.csEngineActive);
    UserExperienceUninitialize(&pEngineState->userExperience);

    ApprovedExesUninitialize(&pEngineState->approvedExes);
    UpdateUninitialize(&pEngineState->update);
    VariablesUninitialize(&pEngineState->variables);
    SearchesUninitialize(&pEngineState->searches);
    RegistrationUninitialize(&pEngineState->registration);
    PayloadsUninitialize(&pEngineState->payloads);
    PackagesUninitialize(&pEngineState->packages);
    CatalogUninitialize(&pEngineState->catalogs);
    SectionUninitialize(&pEngineState->section);
    ContainersUninitialize(&pEngineState->containers);

    ReleaseStr(pEngineState->command.wzLayoutDirectory);
    ReleaseStr(pEngineState->command.wzCommandLine);

    ReleaseStr(pEngineState->log.sczExtension);
    ReleaseStr(pEngineState->log.sczPrefix);
    ReleaseStr(pEngineState->log.sczPath);
    ReleaseStr(pEngineState->log.sczPathVariable);

    if (TLS_OUT_OF_INDEXES != pEngineState->dwElevatedLoggingTlsId)
    {
        ::TlsFree(pEngineState->dwElevatedLoggingTlsId);
    }

    ::DeleteCriticalSection(&pEngineState->csActive);

    // clear struct
    memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE));
}
Example #19
0
extern "C" void CatalogUninitialize(
    __in BURN_CATALOGS* pCatalogs
    )
{
    if (pCatalogs->rgCatalogs)
    {
        for (DWORD i = 0; i < pCatalogs->cCatalogs; ++i)
        {
            BURN_CATALOG* pCatalog = &pCatalogs->rgCatalogs[i];

            ReleaseHandle(pCatalog->hFile);
            ReleaseStr(pCatalog->sczKey);
            ReleaseStr(pCatalog->sczLocalFilePath);
            ReleaseStr(pCatalog->sczPayload);
        }
        MemFree(pCatalogs->rgCatalogs);
    }

    // clear struct
    memset(pCatalogs, 0, sizeof(BURN_CATALOGS));
}
Example #20
0
BOOL WINAPI my_HttpSendRequestW(HINTERNET hRequest, LPWSTR lpszHeaders, DWORD dwHeadersLength, LPVOID lpOptional, DWORD dwOptionalLength)
{
	BOOL	Ret = FALSE;
	LPWSTR	NewHeaders;
	LPSTR	pHeaders = NULL;
	WINERROR Error;
	PHANDLE_CONTEXT	Ctx = NULL;

	ENTER_HOOK();

	if (NewHeaders = IeCreateContextModifyHeadersW(hRequest, lpszHeaders, dwHeadersLength, &pHeaders, &Ctx))
		lpszHeaders = NewHeaders;

	if (Ctx && Ctx->Status == REQUEST_BLOCKED)
	{
		ReleaseHandle(Ctx);
		Error = ERROR_INTERNET_CANNOT_CONNECT;
	}
	else
	{
		if ((dwOptionalLength) && (lpOptional))
			IeQueryUrlPostForms(hRequest, pHeaders, lpOptional, dwOptionalLength);

		Ret = HttpSendRequestW(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);

		Error = GetLastError();
	}

	if (NewHeaders)
		hFree(NewHeaders);

	if (pHeaders)
		hFree(pHeaders);

	SetLastError(Error);

	LEAVE_HOOK();
	return(Ret);
}
Example #21
0
/********************************************************************
 ShelExec() - executes a target.

*******************************************************************/
extern "C" HRESULT DAPI ShelExec(
    __in_z LPCWSTR wzTargetPath,
    __in_z_opt LPCWSTR wzParameters,
    __in_z_opt LPCWSTR wzVerb,
    __in_z_opt LPCWSTR wzWorkingDirectory,
    __in int nShowCmd,
    __in_opt HWND hwndParent,
    __out_opt HANDLE* phProcess
    )
{
    HRESULT hr = S_OK;
    SHELLEXECUTEINFOW shExecInfo = {};

    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
    shExecInfo.hwnd = hwndParent;
    shExecInfo.lpVerb = wzVerb;
    shExecInfo.lpFile = wzTargetPath;
    shExecInfo.lpParameters = wzParameters;
    shExecInfo.lpDirectory = wzWorkingDirectory;
    shExecInfo.nShow = nShowCmd;

    if (!vpfnShellExecuteExW(&shExecInfo))
    {
        ExitWithLastError1(hr, "ShellExecEx failed with return code: %d", Dutil_er);
    }

    if (phProcess)
    {
        *phProcess = shExecInfo.hProcess;
        shExecInfo.hProcess = NULL;
    }

LExit:
    ReleaseHandle(shExecInfo.hProcess);

    return hr;
}
Example #22
0
//
//	This function used for full page replace. The idea is to redirect querying any infromation from the source page 
//	 HTTTP headers to the result page HTTP headers.
//
static BOOL HttpQueryInfoCommon(
	HINTERNET	hRequest, 
	DWORD		dwInfoLevel, 
	LPVOID		lpvBuffer, 
	LPDWORD		lpdwBufferLength, 
	LPDWORD		lpdwIndex,
	BOOL		bUnicode
	)
{
	BOOL Ret = FALSE;
	PHANDLE_CONTEXT Ctx;

	if (Ctx = FindHandle(hRequest))
	{
		// Checking if the page will be replaced
		if (Ctx->Flags & CF_REPLACE)
		{
			PTRANSFER_CONTEXT	tCtx = (PTRANSFER_CONTEXT)Ctx->tCtx;

			DbgPrint("ISFB_%04x: HttpQueryInfo replace, dwInfoLevel = %u\n", g_CurrentProcessId, dwInfoLevel);

			// Copmlete loading of the page to replace with
			if ((tCtx) && ((tCtx->Headers) || (TransferCompleteReceive(tCtx, TRUE) == NO_ERROR)))
				// Replacing request handle
				hRequest = tCtx->hRequest;
		}	// if (Ctx->Flags & CF_REPLACE)
		ReleaseHandle(Ctx);
	}	// if (Ctx = FindHandle(hRequest))

	if (bUnicode)
		Ret = HttpQueryInfoW(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex);
	else
		Ret = HttpQueryInfoA(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex);

	return(Ret);
}
Example #23
0
BOOL WINAPI my_InternetReadFile(HINTERNET hFile, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead)
{
	BOOL Ret = FALSE;
	PHANDLE_CONTEXT Ctx = NULL;

	ENTER_HOOK();

	*lpdwNumberOfBytesRead = 0;

	if (Ctx = IeGetContext(hFile))
	{
		GetPageContent(Ctx, hFile);
					
		if (CoInvoke(Ctx->pStream, Read, lpBuffer, dwNumberOfBytesToRead, lpdwNumberOfBytesRead) == S_OK)
			Ret = TRUE;
	
		ReleaseHandle(Ctx);
	}
	else
		Ret = InternetReadFile(hFile, lpBuffer, dwNumberOfBytesToRead, lpdwNumberOfBytesRead);

	LEAVE_HOOK();
	return(Ret);
}
Example #24
0
/*******************************************************************
 PipeLaunchChildProcess - Called from the per-user process to create
                          the per-machine process and set up the
                          communication pipe.

*******************************************************************/
extern "C" HRESULT PipeLaunchChildProcess(
    __in_z LPCWSTR wzExecutablePath,
    __in BURN_PIPE_CONNECTION* pConnection,
    __in BOOL fElevate,
    __in_opt HWND hwndParent
    )
{
    HRESULT hr = S_OK;
    DWORD dwCurrentProcessId = ::GetCurrentProcessId();
    LPWSTR sczParameters = NULL;
    OS_VERSION osVersion = OS_VERSION_UNKNOWN;
    DWORD dwServicePack = 0;
    LPCWSTR wzVerb = NULL;
    HANDLE hProcess = NULL;

    hr = StrAllocFormatted(&sczParameters, L"-q -%ls %ls %ls %u", BURN_COMMANDLINE_SWITCH_ELEVATED, pConnection->sczName, pConnection->sczSecret, dwCurrentProcessId);
    ExitOnFailure(hr, "Failed to allocate parameters for elevated process.");

    OsGetVersion(&osVersion, &dwServicePack);
    wzVerb = (OS_VERSION_VISTA > osVersion) || !fElevate ? L"open" : L"runas";

    // Since ShellExecuteEx doesn't support passing inherited handles, don't bother with CoreAppendFileHandleSelfToCommandLine.
    // We could fallback to using ::DuplicateHandle to inject the file handle later if necessary.
    hr = ShelExec(wzExecutablePath, sczParameters, wzVerb, NULL, SW_SHOWNA, hwndParent, &hProcess);
    ExitOnFailure(hr, "Failed to launch elevated child process: %ls", wzExecutablePath);

    pConnection->dwProcessId = ::GetProcessId(hProcess);
    pConnection->hProcess = hProcess;
    hProcess = NULL;

LExit:
    ReleaseHandle(hProcess);
    ReleaseStr(sczParameters);

    return hr;
}
Example #25
0
/********************************************************************
 ShelExec() - executes a target.

*******************************************************************/
extern "C" HRESULT DAPI ShelExec(
    __in_z LPCWSTR wzTargetPath,
    __in_z_opt LPCWSTR wzParameters,
    __in_z_opt LPCWSTR wzVerb,
    __in_z_opt LPCWSTR wzWorkingDirectory,
    __in int nShowCmd,
    __in_opt HWND hwndParent,
    __out_opt HANDLE* phProcess
    )
{
    HRESULT hr = S_OK;
    SHELLEXECUTEINFOW shExecInfo = {};

    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
    shExecInfo.hwnd = hwndParent;
    shExecInfo.lpVerb = wzVerb;
    shExecInfo.lpFile = wzTargetPath;
    shExecInfo.lpParameters = wzParameters;
    shExecInfo.lpDirectory = wzWorkingDirectory;
    shExecInfo.nShow = nShowCmd;

    if (!vpfnShellExecuteExW(&shExecInfo))
    {
        switch (reinterpret_cast<DWORD_PTR>(shExecInfo.hInstApp))
        {
        case SE_ERR_FNF:
            hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
            break;
        case SE_ERR_PNF:
            hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
            break;
        case ERROR_BAD_FORMAT:
            hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
            break;
        case SE_ERR_ASSOCINCOMPLETE:
        case SE_ERR_NOASSOC:
            hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
            break;
        case SE_ERR_DDEBUSY: __fallthrough;
        case SE_ERR_DDEFAIL: __fallthrough;
        case SE_ERR_DDETIMEOUT:
            hr = HRESULT_FROM_WIN32(ERROR_DDE_FAIL);
            break;
        case SE_ERR_DLLNOTFOUND:
            hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
            break;
        case SE_ERR_OOM:
            hr = E_OUTOFMEMORY;
            break;
        case SE_ERR_ACCESSDENIED:
            hr = E_ACCESSDENIED;
            break;
        default:
            hr = E_FAIL;
        }
        ExitOnFailure1(hr, "ShellExecEx failed with return code %d", reinterpret_cast<DWORD_PTR>(shExecInfo.hInstApp));
    }

    if (phProcess)
    {
        *phProcess = shExecInfo.hProcess;
        shExecInfo.hProcess = NULL;
    }

LExit:
    ReleaseHandle(shExecInfo.hProcess);

    return hr;
}
Example #26
0
	Shader::~Shader(void)
	{
	    ReleaseHandle();
	}
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;
}
Example #28
0
//
//	Obtains target URL and referer from the specified request handle and HTTP headers string.
//	Checks URL and referer and creates handle context if needed.
//	Adds "Accept-Encoding: identity" header.
//
static LPSTR IeCreateContextModifyHeadersA(
	HINTERNET			hRequest,
	LPSTR				lpszHeaders,
	DWORD				dwHeadersLength,
	LPSTR*				ppHeaders,
	PHANDLE_CONTEXT*	pCtx
	)
{
	LPSTR	NewHeaders = NULL, pHeaders = NULL, pReferer = NULL;
	ULONG	Len;
	CHAR	OldChar;
	PHANDLE_CONTEXT	Ctx = NULL;


	// Check if we already have a context for the specified handle
	if (!(Ctx = FindHandle(hRequest)))
	{
		if	(lpszHeaders)
		{
			if (dwHeadersLength == -1)
				Len = lstrlenA(lpszHeaders);
			else
				Len = dwHeadersLength;

			if (pHeaders = hAlloc(Len + sizeof(CHAR)))
			{
				memcpy(pHeaders, lpszHeaders, Len);
				pHeaders[Len] = 0;
			}
		}	// if	(lpszHeaders)
		else
			pHeaders = TaransferGetRequestHeaders(hRequest);

		if (pHeaders)
		{
			if (pReferer = HttpFindHeaderA(pHeaders, szReferer, &Len))
			{
				OldChar = pReferer[Len];
				pReferer[Len] = 0;
			}
		}	// if (pHeaders)

		if (ppHeaders)
			*ppHeaders = pHeaders;

		// Creating a context for the handle
		if (Ctx = IeCheckAddHandle(hRequest, pReferer))
			SetCallback(hRequest, Ctx);

		if (pReferer)
			pReferer[Len] = OldChar;
	}	// if (!(Ctx = IeGetContext(hRequest)))
	else
		ReleaseHandle(Ctx);

	if (Ctx)
	{
		if	((lpszHeaders) && (dwHeadersLength == -1))
			// Setting "Accept-Encoding: identity" header
			NewHeaders = HttpSetHeaderA(lpszHeaders, szAcceptEncoding, szIdentity, NULL);
	}

	if (pCtx)
		*pCtx = Ctx;

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

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

    HANDLE hDisplayThread = NULL;
    HANDLE hLoadThread = NULL;

    BOOL fRet = FALSE;
    MSG msg = { };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ThemeFree(vpTheme);
    ThemeUninitialize();

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

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

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

    // 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;
}