diff options
Diffstat (limited to 'src/burn/engine')
-rw-r--r-- | src/burn/engine/apply.cpp | 8 | ||||
-rw-r--r-- | src/burn/engine/apply.h | 5 | ||||
-rw-r--r-- | src/burn/engine/bundlepackageengine.cpp | 28 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 17 | ||||
-rw-r--r-- | src/burn/engine/engine.mc | 7 | ||||
-rw-r--r-- | src/burn/engine/exeengine.cpp | 132 | ||||
-rw-r--r-- | src/burn/engine/exeengine.h | 9 | ||||
-rw-r--r-- | src/burn/engine/msuengine.cpp | 32 | ||||
-rw-r--r-- | src/burn/engine/userexperience.cpp | 30 | ||||
-rw-r--r-- | src/burn/engine/userexperience.h | 6 |
10 files changed, 181 insertions, 93 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index 3ad22e9b..73b5b396 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp | |||
@@ -3326,6 +3326,14 @@ static int GenericExecuteMessageHandler( | |||
3326 | } | 3326 | } |
3327 | break; | 3327 | break; |
3328 | 3328 | ||
3329 | case GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL: | ||
3330 | { | ||
3331 | BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION action = BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION_ABANDON; | ||
3332 | UserExperienceOnExecuteProcessCancel(pContext->pUX, pContext->wzExecutingPackageId, pMessage->processCancel.dwProcessId, &action); // ignore return value. | ||
3333 | nResult = BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION_WAIT == action ? IDRETRY : IDIGNORE; | ||
3334 | } | ||
3335 | break; | ||
3336 | |||
3329 | case GENERIC_EXECUTE_MESSAGE_ERROR: | 3337 | case GENERIC_EXECUTE_MESSAGE_ERROR: |
3330 | UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE, pContext->wzExecutingPackageId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwUIHint, 0, NULL, &nResult); // ignore return value. | 3338 | UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE, pContext->wzExecutingPackageId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwUIHint, 0, NULL, &nResult); // ignore return value. |
3331 | break; | 3339 | break; |
diff --git a/src/burn/engine/apply.h b/src/burn/engine/apply.h index 1717a71a..47f0ece6 100644 --- a/src/burn/engine/apply.h +++ b/src/burn/engine/apply.h | |||
@@ -13,6 +13,7 @@ enum GENERIC_EXECUTE_MESSAGE_TYPE | |||
13 | GENERIC_EXECUTE_MESSAGE_ERROR, | 13 | GENERIC_EXECUTE_MESSAGE_ERROR, |
14 | GENERIC_EXECUTE_MESSAGE_PROGRESS, | 14 | GENERIC_EXECUTE_MESSAGE_PROGRESS, |
15 | GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE, | 15 | GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE, |
16 | GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL, | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA | 19 | typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA |
@@ -43,6 +44,10 @@ typedef struct _GENERIC_EXECUTE_MESSAGE | |||
43 | DWORD cFiles; | 44 | DWORD cFiles; |
44 | LPCWSTR* rgwzFiles; | 45 | LPCWSTR* rgwzFiles; |
45 | } filesInUse; | 46 | } filesInUse; |
47 | struct | ||
48 | { | ||
49 | DWORD dwProcessId; | ||
50 | } processCancel; | ||
46 | }; | 51 | }; |
47 | } GENERIC_EXECUTE_MESSAGE; | 52 | } GENERIC_EXECUTE_MESSAGE; |
48 | 53 | ||
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp index 88a00f5e..0bee054f 100644 --- a/src/burn/engine/bundlepackageengine.cpp +++ b/src/burn/engine/bundlepackageengine.cpp | |||
@@ -251,7 +251,6 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( | |||
251 | ) | 251 | ) |
252 | { | 252 | { |
253 | HRESULT hr = S_OK; | 253 | HRESULT hr = S_OK; |
254 | int nResult = IDNOACTION; | ||
255 | LPCWSTR wzArguments = NULL; | 254 | LPCWSTR wzArguments = NULL; |
256 | LPWSTR sczArguments = NULL; | 255 | LPWSTR sczArguments = NULL; |
257 | LPWSTR sczArgumentsFormatted = NULL; | 256 | LPWSTR sczArgumentsFormatted = NULL; |
@@ -420,31 +419,10 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( | |||
420 | hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); | 419 | hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); |
421 | ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); | 420 | ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); |
422 | } | 421 | } |
423 | else // create and wait for the executable process while sending fake progress to allow cancel. | 422 | else |
424 | { | 423 | { |
425 | // Make the cache location of the executable the current directory to help those executables | 424 | hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); |
426 | // that expect stuff to be relative to them. | 425 | ExitOnFailure(hr, "Failed to run BUNDLE process"); |
427 | si.cb = sizeof(si); | ||
428 | if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, sczCachedDirectory, &si, &pi)) | ||
429 | { | ||
430 | ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath); | ||
431 | } | ||
432 | |||
433 | do | ||
434 | { | ||
435 | message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; | ||
436 | message.dwUIHint = MB_OKCANCEL; | ||
437 | message.progress.dwPercentage = 50; | ||
438 | nResult = pfnGenericMessageHandler(&message, pvContext); | ||
439 | hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); | ||
440 | ExitOnRootFailure(hr, "Bootstrapper application aborted during BUNDLE progress."); | ||
441 | |||
442 | hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode); | ||
443 | if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) | ||
444 | { | ||
445 | ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath); | ||
446 | } | ||
447 | } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); | ||
448 | } | 426 | } |
449 | 427 | ||
450 | hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, dwExitCode, pRestart); | 428 | hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, dwExitCode, pRestart); |
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 636d67ce..3c2872f1 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp | |||
@@ -43,6 +43,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE | |||
43 | BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE, | 43 | BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE, |
44 | BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS, | 44 | BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS, |
45 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, | 45 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, |
46 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL, | ||
46 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, | 47 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, |
47 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, | 48 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, |
48 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE, | 49 | BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE, |
@@ -1812,7 +1813,14 @@ static HRESULT ProcessGenericExecuteMessages( | |||
1812 | 1813 | ||
1813 | // read message parameters | 1814 | // read message parameters |
1814 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.progress.dwPercentage); | 1815 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.progress.dwPercentage); |
1815 | ExitOnFailure(hr, "Failed to progress."); | 1816 | ExitOnFailure(hr, "Failed to read progress."); |
1817 | break; | ||
1818 | |||
1819 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL: | ||
1820 | message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL; | ||
1821 | |||
1822 | hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.processCancel.dwProcessId); | ||
1823 | ExitOnFailure(hr, "Failed to read processId."); | ||
1816 | break; | 1824 | break; |
1817 | 1825 | ||
1818 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: | 1826 | case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: |
@@ -3450,6 +3458,13 @@ static int GenericExecuteMessageHandler( | |||
3450 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS; | 3458 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS; |
3451 | break; | 3459 | break; |
3452 | 3460 | ||
3461 | case GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL: | ||
3462 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->processCancel.dwProcessId); | ||
3463 | ExitOnFailure(hr, "Failed to write progress percentage to message buffer."); | ||
3464 | |||
3465 | dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL; | ||
3466 | break; | ||
3467 | |||
3453 | case GENERIC_EXECUTE_MESSAGE_ERROR: | 3468 | case GENERIC_EXECUTE_MESSAGE_ERROR: |
3454 | // serialize message data | 3469 | // serialize message data |
3455 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); | 3470 | hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); |
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index 53e6b256..9e139661 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc | |||
@@ -933,6 +933,13 @@ Language=English | |||
933 | Could not create system restore point, error: 0x%1!x!. Continuing... | 933 | Could not create system restore point, error: 0x%1!x!. Continuing... |
934 | . | 934 | . |
935 | 935 | ||
936 | MessageId=364 | ||
937 | Severity=Success | ||
938 | SymbolicName=MSG_EXECUTE_PROCESS_DELAYED_CANCEL_REQUESTED | ||
939 | Language=English | ||
940 | Bootstrapper application requested delayed cancel during package process progress, id: %1!ls!. Waiting... | ||
941 | . | ||
942 | |||
936 | MessageId=370 | 943 | MessageId=370 |
937 | Severity=Success | 944 | Severity=Success |
938 | SymbolicName=MSG_SESSION_BEGIN | 945 | SymbolicName=MSG_SESSION_BEGIN |
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index c984f5a7..4c3c6fb0 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp | |||
@@ -317,7 +317,6 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
317 | ) | 317 | ) |
318 | { | 318 | { |
319 | HRESULT hr = S_OK; | 319 | HRESULT hr = S_OK; |
320 | int nResult = IDNOACTION; | ||
321 | LPCWSTR wzArguments = NULL; | 320 | LPCWSTR wzArguments = NULL; |
322 | LPWSTR sczArguments = NULL; | 321 | LPWSTR sczArguments = NULL; |
323 | LPWSTR sczArgumentsFormatted = NULL; | 322 | LPWSTR sczArgumentsFormatted = NULL; |
@@ -327,10 +326,7 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
327 | LPWSTR sczCommand = NULL; | 326 | LPWSTR sczCommand = NULL; |
328 | LPWSTR sczCommandObfuscated = NULL; | 327 | LPWSTR sczCommandObfuscated = NULL; |
329 | HANDLE hExecutableFile = INVALID_HANDLE_VALUE; | 328 | HANDLE hExecutableFile = INVALID_HANDLE_VALUE; |
330 | STARTUPINFOW si = { }; | ||
331 | PROCESS_INFORMATION pi = { }; | ||
332 | DWORD dwExitCode = 0; | 329 | DWORD dwExitCode = 0; |
333 | GENERIC_EXECUTE_MESSAGE message = { }; | ||
334 | BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; | 330 | BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; |
335 | BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; | 331 | BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; |
336 | 332 | ||
@@ -442,37 +438,10 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
442 | hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); | 438 | hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); |
443 | ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); | 439 | ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); |
444 | } | 440 | } |
445 | else // create and wait for the executable process while sending fake progress to allow cancel. | 441 | else |
446 | { | 442 | { |
447 | // Make the cache location of the executable the current directory to help those executables | 443 | hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczExecutablePath, sczCommand, sczCachedDirectory, &dwExitCode); |
448 | // that expect stuff to be relative to them. | 444 | ExitOnFailure(hr, "Failed to run EXE process"); |
449 | si.cb = sizeof(si); | ||
450 | if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, sczCachedDirectory, &si, &pi)) | ||
451 | { | ||
452 | ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath); | ||
453 | } | ||
454 | |||
455 | if (pPackage->Exe.fFireAndForget) | ||
456 | { | ||
457 | ::WaitForInputIdle(pi.hProcess, 5000); | ||
458 | ExitFunction(); | ||
459 | } | ||
460 | |||
461 | do | ||
462 | { | ||
463 | message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; | ||
464 | message.dwUIHint = MB_OKCANCEL; | ||
465 | message.progress.dwPercentage = 50; | ||
466 | nResult = pfnGenericMessageHandler(&message, pvContext); | ||
467 | hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); | ||
468 | ExitOnRootFailure(hr, "Bootstrapper application aborted during EXE progress."); | ||
469 | |||
470 | hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode); | ||
471 | if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) | ||
472 | { | ||
473 | ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath); | ||
474 | } | ||
475 | } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); | ||
476 | } | 445 | } |
477 | 446 | ||
478 | hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart); | 447 | hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart); |
@@ -487,8 +456,6 @@ LExit: | |||
487 | StrSecureZeroFreeString(sczCommand); | 456 | StrSecureZeroFreeString(sczCommand); |
488 | ReleaseStr(sczCommandObfuscated); | 457 | ReleaseStr(sczCommandObfuscated); |
489 | 458 | ||
490 | ReleaseHandle(pi.hThread); | ||
491 | ReleaseHandle(pi.hProcess); | ||
492 | ReleaseFileHandle(hExecutableFile); | 459 | ReleaseFileHandle(hExecutableFile); |
493 | 460 | ||
494 | // Best effort to clear the execute package cache folder and action variables. | 461 | // Best effort to clear the execute package cache folder and action variables. |
@@ -498,6 +465,99 @@ LExit: | |||
498 | return hr; | 465 | return hr; |
499 | } | 466 | } |
500 | 467 | ||
468 | extern "C" HRESULT ExeEngineRunProcess( | ||
469 | __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, | ||
470 | __in LPVOID pvContext, | ||
471 | __in BURN_PACKAGE* pPackage, | ||
472 | __in_z LPCWSTR wzExecutablePath, | ||
473 | __in_z LPWSTR wzCommand, | ||
474 | __in_z_opt LPCWSTR wzCachedDirectory, | ||
475 | __inout DWORD* pdwExitCode | ||
476 | ) | ||
477 | { | ||
478 | HRESULT hr = S_OK; | ||
479 | STARTUPINFOW si = { }; | ||
480 | PROCESS_INFORMATION pi = { }; | ||
481 | GENERIC_EXECUTE_MESSAGE message = { }; | ||
482 | int nResult = IDNOACTION; | ||
483 | DWORD dwProcessId = 0; | ||
484 | BOOL fDelayedCancel = FALSE; | ||
485 | BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget; | ||
486 | BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type; | ||
487 | |||
488 | // Make the cache location of the executable the current directory to help those executables | ||
489 | // that expect stuff to be relative to them. | ||
490 | si.cb = sizeof(si); | ||
491 | if (!::CreateProcessW(wzExecutablePath, wzCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) | ||
492 | { | ||
493 | ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath); | ||
494 | } | ||
495 | |||
496 | if (fFireAndForget) | ||
497 | { | ||
498 | ::WaitForInputIdle(pi.hProcess, 5000); | ||
499 | ExitFunction(); | ||
500 | } | ||
501 | |||
502 | dwProcessId = ::GetProcessId(pi.hProcess); | ||
503 | |||
504 | // Wait for the executable process while sending fake progress to allow cancel. | ||
505 | do | ||
506 | { | ||
507 | message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; | ||
508 | message.dwUIHint = MB_OKCANCEL; | ||
509 | message.progress.dwPercentage = 50; | ||
510 | nResult = pfnGenericMessageHandler(&message, pvContext); | ||
511 | |||
512 | if (IDCANCEL == nResult) | ||
513 | { | ||
514 | memset(&message, 0, sizeof(message)); | ||
515 | message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL; | ||
516 | message.dwUIHint = MB_ABORTRETRYIGNORE; | ||
517 | message.processCancel.dwProcessId = dwProcessId; | ||
518 | nResult = pfnGenericMessageHandler(&message, pvContext); | ||
519 | |||
520 | if (IDIGNORE == nResult) // abandon | ||
521 | { | ||
522 | nResult = IDCANCEL; | ||
523 | fDelayedCancel = FALSE; | ||
524 | } | ||
525 | //else if (IDABORT == nResult) // kill | ||
526 | else // wait | ||
527 | { | ||
528 | if (!fDelayedCancel) | ||
529 | { | ||
530 | fDelayedCancel = TRUE; | ||
531 | |||
532 | LogId(REPORT_STANDARD, MSG_EXECUTE_PROCESS_DELAYED_CANCEL_REQUESTED, pPackage->sczId); | ||
533 | } | ||
534 | |||
535 | nResult = IDNOACTION; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); | ||
540 | ExitOnRootFailure(hr, "Bootstrapper application aborted during package process progress."); | ||
541 | |||
542 | hr = ProcWaitForCompletion(pi.hProcess, 500, pdwExitCode); | ||
543 | if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) | ||
544 | { | ||
545 | ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", wzExecutablePath); | ||
546 | } | ||
547 | } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); | ||
548 | |||
549 | if (fDelayedCancel) | ||
550 | { | ||
551 | ExitWithRootFailure(hr, HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT), "Bootstrapper application cancelled during package process progress, exit code: 0x%x", *pdwExitCode); | ||
552 | } | ||
553 | |||
554 | LExit: | ||
555 | ReleaseHandle(pi.hThread); | ||
556 | ReleaseHandle(pi.hProcess); | ||
557 | |||
558 | return hr; | ||
559 | } | ||
560 | |||
501 | extern "C" void ExeEngineUpdateInstallRegistrationState( | 561 | extern "C" void ExeEngineUpdateInstallRegistrationState( |
502 | __in BURN_EXECUTE_ACTION* pAction, | 562 | __in BURN_EXECUTE_ACTION* pAction, |
503 | __in HRESULT hrExecute | 563 | __in HRESULT hrExecute |
diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h index 743621b7..636988f1 100644 --- a/src/burn/engine/exeengine.h +++ b/src/burn/engine/exeengine.h | |||
@@ -42,6 +42,15 @@ HRESULT ExeEngineExecutePackage( | |||
42 | __in LPVOID pvContext, | 42 | __in LPVOID pvContext, |
43 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart | 43 | __out BOOTSTRAPPER_APPLY_RESTART* pRestart |
44 | ); | 44 | ); |
45 | HRESULT ExeEngineRunProcess( | ||
46 | __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, | ||
47 | __in LPVOID pvContext, | ||
48 | __in BURN_PACKAGE* pPackage, | ||
49 | __in_z LPCWSTR wzExecutablePath, | ||
50 | __in_z LPWSTR wzCommand, | ||
51 | __in_z_opt LPCWSTR wzCachedDirectory, | ||
52 | __inout DWORD* pdwExitCode | ||
53 | ); | ||
45 | void ExeEngineUpdateInstallRegistrationState( | 54 | void ExeEngineUpdateInstallRegistrationState( |
46 | __in BURN_EXECUTE_ACTION* pAction, | 55 | __in BURN_EXECUTE_ACTION* pAction, |
47 | __in HRESULT hrExecute | 56 | __in HRESULT hrExecute |
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp index 091bbe62..2f1fb61c 100644 --- a/src/burn/engine/msuengine.cpp +++ b/src/burn/engine/msuengine.cpp | |||
@@ -264,7 +264,6 @@ extern "C" HRESULT MsuEngineExecutePackage( | |||
264 | ) | 264 | ) |
265 | { | 265 | { |
266 | HRESULT hr = S_OK; | 266 | HRESULT hr = S_OK; |
267 | int nResult = IDNOACTION; | ||
268 | LPWSTR sczCachedDirectory = NULL; | 267 | LPWSTR sczCachedDirectory = NULL; |
269 | LPWSTR sczMsuPath = NULL; | 268 | LPWSTR sczMsuPath = NULL; |
270 | LPWSTR sczWindowsPath = NULL; | 269 | LPWSTR sczWindowsPath = NULL; |
@@ -350,35 +349,8 @@ extern "C" HRESULT MsuEngineExecutePackage( | |||
350 | hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled); | 349 | hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled); |
351 | ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package."); | 350 | ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package."); |
352 | 351 | ||
353 | // create process | 352 | hr = ExeEngineRunProcess(pfnGenericMessageHandler, pvContext, pPackage, sczWusaPath, sczCommand, NULL, &dwExitCode); |
354 | si.cb = sizeof(si); | 353 | ExitOnFailure(hr, "Failed to run MSU process"); |
355 | if (!::CreateProcessW(sczWusaPath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) | ||
356 | { | ||
357 | ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczWusaPath); | ||
358 | } | ||
359 | |||
360 | do | ||
361 | { | ||
362 | message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; | ||
363 | message.dwUIHint = MB_OKCANCEL; | ||
364 | message.progress.dwPercentage = 50; | ||
365 | nResult = pfnGenericMessageHandler(&message, pvContext); | ||
366 | hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); | ||
367 | ExitOnRootFailure(hr, "Bootstrapper application aborted during MSU progress."); | ||
368 | |||
369 | // wait for process to terminate | ||
370 | hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode); | ||
371 | if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) | ||
372 | { | ||
373 | ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", sczWusaPath); | ||
374 | } | ||
375 | } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); | ||
376 | |||
377 | // get process exit code | ||
378 | if (!::GetExitCodeProcess(pi.hProcess, &dwExitCode)) | ||
379 | { | ||
380 | ExitWithLastError(hr, "Failed to get process exit code."); | ||
381 | } | ||
382 | 354 | ||
383 | // We'll normalize the restart required error code from wusa.exe just in case. Most likely | 355 | // We'll normalize the restart required error code from wusa.exe just in case. Most likely |
384 | // that on reboot we'll actually get WU_S_REBOOT_REQUIRED. | 356 | // that on reboot we'll actually get WU_S_REBOOT_REQUIRED. |
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 81ce8bb9..06f87363 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp | |||
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad( | |||
104 | args.pCommand = pCommand; | 104 | args.pCommand = pCommand; |
105 | args.pfnBootstrapperEngineProc = EngineForApplicationProc; | 105 | args.pfnBootstrapperEngineProc = EngineForApplicationProc; |
106 | args.pvBootstrapperEngineProcContext = pEngineContext; | 106 | args.pvBootstrapperEngineProcContext = pEngineContext; |
107 | args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 14, 0); | 107 | args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 17, 0); |
108 | 108 | ||
109 | results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); | 109 | results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); |
110 | 110 | ||
@@ -1701,6 +1701,34 @@ LExit: | |||
1701 | return hr; | 1701 | return hr; |
1702 | } | 1702 | } |
1703 | 1703 | ||
1704 | BAAPI UserExperienceOnExecuteProcessCancel( | ||
1705 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
1706 | __in_z LPCWSTR wzPackageId, | ||
1707 | __in DWORD dwProcessId, | ||
1708 | __inout BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION* pAction | ||
1709 | ) | ||
1710 | { | ||
1711 | HRESULT hr = S_OK; | ||
1712 | BA_ONEXECUTEPROCESSCANCEL_ARGS args = { }; | ||
1713 | BA_ONEXECUTEPROCESSCANCEL_RESULTS results = { }; | ||
1714 | |||
1715 | args.cbSize = sizeof(args); | ||
1716 | args.wzPackageId = wzPackageId; | ||
1717 | args.dwProcessId = dwProcessId; | ||
1718 | args.recommendation = *pAction; | ||
1719 | |||
1720 | results.cbSize = sizeof(results); | ||
1721 | results.action = *pAction; | ||
1722 | |||
1723 | hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL, &args, &results); | ||
1724 | ExitOnFailure(hr, "BA OnExecuteProcessCancel failed."); | ||
1725 | |||
1726 | *pAction = results.action; | ||
1727 | |||
1728 | LExit: | ||
1729 | return hr; | ||
1730 | } | ||
1731 | |||
1704 | EXTERN_C BAAPI UserExperienceOnExecuteProgress( | 1732 | EXTERN_C BAAPI UserExperienceOnExecuteProgress( |
1705 | __in BURN_USER_EXPERIENCE* pUserExperience, | 1733 | __in BURN_USER_EXPERIENCE* pUserExperience, |
1706 | __in_z LPCWSTR wzPackageId, | 1734 | __in_z LPCWSTR wzPackageId, |
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index 2f18acdd..de558ad5 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h | |||
@@ -398,6 +398,12 @@ BAAPI UserExperienceOnExecutePatchTarget( | |||
398 | __in_z LPCWSTR wzPackageId, | 398 | __in_z LPCWSTR wzPackageId, |
399 | __in_z LPCWSTR wzTargetProductCode | 399 | __in_z LPCWSTR wzTargetProductCode |
400 | ); | 400 | ); |
401 | BAAPI UserExperienceOnExecuteProcessCancel( | ||
402 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
403 | __in_z LPCWSTR wzPackageId, | ||
404 | __in DWORD dwProcessId, | ||
405 | __inout BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION* pAction | ||
406 | ); | ||
401 | BAAPI UserExperienceOnExecuteProgress( | 407 | BAAPI UserExperienceOnExecuteProgress( |
402 | __in BURN_USER_EXPERIENCE* pUserExperience, | 408 | __in BURN_USER_EXPERIENCE* pUserExperience, |
403 | __in_z LPCWSTR wzPackageId, | 409 | __in_z LPCWSTR wzPackageId, |