aboutsummaryrefslogtreecommitdiff
path: root/src/engine/apply.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-04-16 10:09:26 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-04-19 23:12:55 -0500
commit90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd (patch)
tree901feb035d5ea9a13f306582cedd6668b539953f /src/engine/apply.cpp
parentc88806b89293f5bb92c42e90230e48be6b79b7f4 (diff)
downloadwix-90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd.tar.gz
wix-90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd.tar.bz2
wix-90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd.zip
Don't plan payloads.
Contributes to #3640 and #5253
Diffstat (limited to 'src/engine/apply.cpp')
-rw-r--r--src/engine/apply.cpp758
1 files changed, 350 insertions, 408 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index b79bf934..7e03ebf9 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -13,18 +13,28 @@ const DWORD BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS = 2;
13 13
14// structs 14// structs
15 15
16struct BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT 16typedef struct _BURN_CACHE_CONTEXT
17{ 17{
18 BURN_USER_EXPERIENCE* pUX; 18 BURN_USER_EXPERIENCE* pUX;
19 BURN_VARIABLES* pVariables;
20 BURN_PAYLOADS* pPayloads;
21 HANDLE hPipe;
22 HANDLE hSourceEngineFile;
23 DWORD64 qwTotalCacheSize;
24 DWORD64 qwSuccessfulCacheProgress;
25 LPCWSTR wzLayoutDirectory;
26} BURN_CACHE_CONTEXT;
27
28typedef struct _BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT
29{
30 BURN_CACHE_CONTEXT* pCacheContext;
19 BURN_CONTAINER* pContainer; 31 BURN_CONTAINER* pContainer;
20 BURN_PACKAGE* pPackage; 32 BURN_PACKAGE* pPackage;
21 BURN_PAYLOAD* pPayload; 33 BURN_PAYLOAD* pPayload;
22 DWORD64 qwCacheProgress;
23 DWORD64 qwTotalCacheSize;
24 34
25 BOOL fCancel; 35 BOOL fCancel;
26 BOOL fError; 36 BOOL fError;
27}; 37} BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT;
28 38
29typedef struct _BURN_EXECUTE_CONTEXT 39typedef struct _BURN_EXECUTE_CONTEXT
30{ 40{
@@ -56,50 +66,49 @@ static HRESULT ExecuteDependentRegistrationActions(
56 __in_ecount(cActions) const BURN_DEPENDENT_REGISTRATION_ACTION* rgActions, 66 __in_ecount(cActions) const BURN_DEPENDENT_REGISTRATION_ACTION* rgActions,
57 __in DWORD cActions 67 __in DWORD cActions
58 ); 68 );
59static HRESULT ExtractContainer( 69static HRESULT ApplyCachePackage(
60 __in HANDLE hSourceEngineFile, 70 __in BURN_CACHE_CONTEXT* pContext,
61 __in BURN_CONTAINER* pContainer, 71 __in BURN_PACKAGE* pPackage
62 __in_z LPCWSTR wzContainerPath,
63 __in_ecount(cExtractPayloads) BURN_EXTRACT_PAYLOAD* rgExtractPayloads,
64 __in DWORD cExtractPayloads
65 ); 72 );
66static void UpdateCacheSuccessProgress( 73static HRESULT ApplyExtractContainer(
67 __in BURN_PLAN* pPlan, 74 __in BURN_CACHE_CONTEXT* pContext,
68 __in BURN_CACHE_ACTION* pCacheAction, 75 __in BURN_CONTAINER* pContainer
69 __inout DWORD64* pqwSuccessfulCachedProgress 76 );
77static HRESULT ApplyLayoutBundle(
78 __in BURN_CACHE_CONTEXT* pContext,
79 __in BURN_PAYLOAD_GROUP* pPayloads,
80 __in_z LPCWSTR wzExecutableName,
81 __in_z LPCWSTR wzUnverifiedPath
82 );
83static HRESULT ApplyLayoutContainer(
84 __in BURN_CACHE_CONTEXT* pContext,
85 __in BURN_CONTAINER* pContainer
86 );
87static HRESULT ApplyProcessPayload(
88 __in BURN_CACHE_CONTEXT* pContext,
89 __in_opt BURN_PACKAGE* pPackage,
90 __in BURN_PAYLOAD* pPayload
91 );
92static HRESULT ExtractContainer(
93 __in BURN_CACHE_CONTEXT* pContext,
94 __in BURN_CONTAINER* pContainer
70 ); 95 );
71static HRESULT LayoutBundle( 96static HRESULT LayoutBundle(
72 __in HANDLE hSourceEngineFile, 97 __in BURN_CACHE_CONTEXT* pContext,
73 __in BURN_USER_EXPERIENCE* pUX,
74 __in BURN_VARIABLES* pVariables,
75 __in HANDLE hPipe,
76 __in_z LPCWSTR wzExecutableName, 98 __in_z LPCWSTR wzExecutableName,
77 __in_z LPCWSTR wzLayoutDirectory, 99 __in_z LPCWSTR wzUnverifiedPath
78 __in_z LPCWSTR wzUnverifiedPath,
79 __in DWORD64 qwSuccessfulCacheProgress,
80 __in DWORD64 qwTotalCacheSize
81 ); 100 );
82static HRESULT AcquireContainerOrPayload( 101static HRESULT AcquireContainerOrPayload(
83 __in BURN_USER_EXPERIENCE* pUX, 102 __in BURN_CACHE_CONTEXT* pContext,
84 __in BURN_VARIABLES* pVariables,
85 __in_opt BURN_CONTAINER* pContainer, 103 __in_opt BURN_CONTAINER* pContainer,
86 __in_opt BURN_PACKAGE* pPackage, 104 __in_opt BURN_PACKAGE* pPackage,
87 __in_opt BURN_PAYLOAD* pPayload, 105 __in_opt BURN_PAYLOAD* pPayload
88 __in LPCWSTR wzDestinationPath,
89 __in DWORD64 qwSuccessfulCacheProgress,
90 __in DWORD64 qwTotalCacheSize
91 ); 106 );
92static HRESULT LayoutOrCacheContainerOrPayload( 107static HRESULT LayoutOrCacheContainerOrPayload(
93 __in BURN_USER_EXPERIENCE* pUX, 108 __in BURN_CACHE_CONTEXT* pContext,
94 __in HANDLE hPipe,
95 __in_opt BURN_CONTAINER* pContainer, 109 __in_opt BURN_CONTAINER* pContainer,
96 __in_opt BURN_PACKAGE* pPackage, 110 __in_opt BURN_PACKAGE* pPackage,
97 __in_opt BURN_PAYLOAD* pPayload, 111 __in_opt BURN_PAYLOAD* pPayload,
98 __in BOOL fAlreadyProvidedProgress,
99 __in DWORD64 qwSuccessfullyCacheProgress,
100 __in DWORD64 qwTotalCacheSize,
101 __in_z_opt LPCWSTR wzLayoutDirectory,
102 __in_z LPCWSTR wzUnverifiedPath,
103 __in BOOL fMove, 112 __in BOOL fMove,
104 __in DWORD cTryAgainAttempts, 113 __in DWORD cTryAgainAttempts,
105 __out BOOL* pfRetry 114 __out BOOL* pfRetry
@@ -461,268 +470,83 @@ extern "C" HRESULT ApplyCache(
461{ 470{
462 HRESULT hr = S_OK; 471 HRESULT hr = S_OK;
463 DWORD dwCheckpoint = 0; 472 DWORD dwCheckpoint = 0;
464 BOOL fRetry = FALSE; 473 BURN_CACHE_CONTEXT cacheContext = { };
465 DWORD iRetryAction = BURN_PLAN_INVALID_ACTION_INDEX; 474 BURN_PACKAGE* pPackage = NULL;
466 BURN_PACKAGE* pStartedPackage = NULL;
467 DWORD64 qwSuccessfulCachedProgress = 0;
468
469 // Allow us to retry and skip packages.
470 DWORD iPackageStartAction = BURN_PLAN_INVALID_ACTION_INDEX;
471 DWORD iPackageCompleteAction = BURN_PLAN_INVALID_ACTION_INDEX;
472 475
473 *pfRollback = FALSE; 476 *pfRollback = FALSE;
474 477
475 hr = UserExperienceOnCacheBegin(pUX); 478 hr = UserExperienceOnCacheBegin(pUX);
476 ExitOnRootFailure(hr, "BA aborted cache."); 479 ExitOnRootFailure(hr, "BA aborted cache.");
477 480
478 do 481 cacheContext.hSourceEngineFile = hSourceEngineFile;
479 { 482 cacheContext.pPayloads = pPlan->pPayloads;
480 hr = S_OK; 483 cacheContext.pUX = pUX;
481 fRetry = FALSE; 484 cacheContext.pVariables = pVariables;
485 cacheContext.qwTotalCacheSize = pPlan->qwCacheSizeTotal;
486 cacheContext.wzLayoutDirectory = pPlan->sczLayoutDirectory;
482 487
483 // Allow us to retry just a container or payload. 488 for (DWORD i = 0; i < pPlan->cCacheActions; ++i)
484 LPCWSTR wzRetryId = NULL; 489 {
485 DWORD iRetryContainerOrPayloadAction = BURN_PLAN_INVALID_ACTION_INDEX; 490 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + i;
486 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE; 491 cacheContext.hPipe = hPipe;
492 pPackage = NULL;
487 493
488 // cache actions 494 switch (pCacheAction->type)
489 for (DWORD i = (BURN_PLAN_INVALID_ACTION_INDEX == iRetryAction) ? 0 : iRetryAction; SUCCEEDED(hr) && i < pPlan->cCacheActions; ++i)
490 { 495 {
491 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + i; 496 case BURN_CACHE_ACTION_TYPE_CHECKPOINT:
492 BOOL fRetryContainerOrPayload = FALSE; 497 dwCheckpoint = pCacheAction->checkpoint.dwId;
493 cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE; 498 break;
494
495 if (pCacheAction->fSkipUntilRetried)
496 {
497 // If this action was retried, let's make sure it will not be skipped any longer.
498 if (iRetryAction == i)
499 {
500 pCacheAction->fSkipUntilRetried = FALSE;
501 }
502 else // skip the action.
503 {
504 continue;
505 }
506 }
507
508 switch (pCacheAction->type)
509 {
510 case BURN_CACHE_ACTION_TYPE_CHECKPOINT:
511 dwCheckpoint = pCacheAction->checkpoint.dwId;
512 break;
513
514 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
515 hr = LayoutBundle(hSourceEngineFile, pUX, pVariables, hPipe, pCacheAction->bundleLayout.sczExecutableName, pCacheAction->bundleLayout.sczLayoutDirectory, pCacheAction->bundleLayout.sczUnverifiedPath, qwSuccessfulCachedProgress, pPlan->qwCacheSizeTotal);
516 if (SUCCEEDED(hr))
517 {
518 UpdateCacheSuccessProgress(pPlan, pCacheAction, &qwSuccessfulCachedProgress);
519 ++(*pcOverallProgressTicks);
520
521 hr = ReportOverallProgressTicks(pUX, FALSE, pPlan->cOverallProgressTicksTotal, *pcOverallProgressTicks);
522 if (FAILED(hr))
523 {
524 LogErrorId(hr, MSG_USER_CANCELED, L"layout bundle", NULL, NULL);
525 }
526 }
527 break;
528
529 case BURN_CACHE_ACTION_TYPE_PACKAGE_START:
530 iPackageStartAction = i; // if we retry this package, we'll start here in the plan.
531 iPackageCompleteAction = pCacheAction->packageStart.iPackageCompleteAction; // if we ignore this package, we'll start after the complete action in the plan.
532 pStartedPackage = pCacheAction->packageStart.pPackage;
533
534 hr = UserExperienceOnCachePackageBegin(pUX, pStartedPackage->sczId, pCacheAction->packageStart.cCachePayloads, pCacheAction->packageStart.qwCachePayloadSizeTotal);
535 if (FAILED(hr))
536 {
537 LogErrorId(hr, MSG_USER_CANCELED, L"begin cache package", pStartedPackage->sczId, NULL);
538 }
539 break;
540
541 case BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER:
542 hr = AcquireContainerOrPayload(pUX, pVariables, pCacheAction->resolveContainer.pContainer, NULL, NULL, pCacheAction->resolveContainer.sczUnverifiedPath, qwSuccessfulCachedProgress, pPlan->qwCacheSizeTotal);
543 if (SUCCEEDED(hr))
544 {
545 UpdateCacheSuccessProgress(pPlan, pCacheAction, &qwSuccessfulCachedProgress);
546 }
547 else
548 {
549 LogErrorId(hr, MSG_FAILED_ACQUIRE_CONTAINER, pCacheAction->resolveContainer.pContainer->sczId, pCacheAction->resolveContainer.sczUnverifiedPath, NULL);
550 }
551 break;
552
553 case BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER:
554 // If this action is to be skipped until the acquire action is not skipped and the other
555 // action is still being skipped then skip this action.
556 if (BURN_PLAN_INVALID_ACTION_INDEX != pCacheAction->extractContainer.iSkipUntilAcquiredByAction && pPlan->rgCacheActions[pCacheAction->extractContainer.iSkipUntilAcquiredByAction].fSkipUntilRetried)
557 {
558 break;
559 }
560
561 hr = ExtractContainer(hSourceEngineFile, pCacheAction->extractContainer.pContainer, pCacheAction->extractContainer.sczContainerUnverifiedPath, pCacheAction->extractContainer.rgPayloads, pCacheAction->extractContainer.cPayloads);
562 if (FAILED(hr))
563 {
564 LogErrorId(hr, MSG_FAILED_EXTRACT_CONTAINER, pCacheAction->extractContainer.pContainer->sczId, pCacheAction->extractContainer.sczContainerUnverifiedPath, NULL);
565 }
566 break;
567
568 case BURN_CACHE_ACTION_TYPE_LAYOUT_CONTAINER:
569 hr = LayoutOrCacheContainerOrPayload(pUX, hPipe, pCacheAction->layoutContainer.pContainer, pCacheAction->layoutContainer.pPackage, NULL, pPlan->rgContainerProgress[pCacheAction->layoutContainer.iProgress].fCachedDuringApply, qwSuccessfulCachedProgress, pPlan->qwCacheSizeTotal, pCacheAction->layoutContainer.sczLayoutDirectory, pCacheAction->layoutContainer.sczUnverifiedPath, pCacheAction->layoutContainer.fMove, pCacheAction->layoutContainer.cTryAgainAttempts, &fRetryContainerOrPayload);
570 if (SUCCEEDED(hr))
571 {
572 UpdateCacheSuccessProgress(pPlan, pCacheAction, &qwSuccessfulCachedProgress);
573 }
574 else
575 {
576 LogErrorId(hr, MSG_FAILED_LAYOUT_CONTAINER, pCacheAction->layoutContainer.pContainer->sczId, pCacheAction->layoutContainer.sczLayoutDirectory, pCacheAction->layoutContainer.sczUnverifiedPath);
577
578 if (fRetryContainerOrPayload)
579 {
580 wzRetryId = pCacheAction->layoutContainer.pContainer->sczId;
581 iRetryContainerOrPayloadAction = pCacheAction->layoutContainer.iTryAgainAction;
582
583 ++pCacheAction->layoutContainer.cTryAgainAttempts;
584 }
585 }
586 break;
587
588 case BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD:
589 hr = AcquireContainerOrPayload(pUX, pVariables, NULL, pCacheAction->resolvePayload.pPackage, pCacheAction->resolvePayload.pPayload, pCacheAction->resolvePayload.sczUnverifiedPath, qwSuccessfulCachedProgress, pPlan->qwCacheSizeTotal);
590 if (SUCCEEDED(hr))
591 {
592 UpdateCacheSuccessProgress(pPlan, pCacheAction, &qwSuccessfulCachedProgress);
593 }
594 else
595 {
596 LogErrorId(hr, MSG_FAILED_ACQUIRE_PAYLOAD, pCacheAction->resolvePayload.pPayload->sczKey, pCacheAction->resolvePayload.sczUnverifiedPath, NULL);
597 }
598 break;
599
600 case BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD:
601 hr = LayoutOrCacheContainerOrPayload(pUX, pCacheAction->cachePayload.pPackage->fPerMachine ? hPipe : INVALID_HANDLE_VALUE, NULL, pCacheAction->cachePayload.pPackage, pCacheAction->cachePayload.pPayload, pPlan->rgPayloadProgress[pCacheAction->cachePayload.iProgress].fCachedDuringApply, qwSuccessfulCachedProgress, pPlan->qwCacheSizeTotal, NULL, pCacheAction->cachePayload.sczUnverifiedPath, pCacheAction->cachePayload.fMove, pCacheAction->cachePayload.cTryAgainAttempts, &fRetryContainerOrPayload);
602 if (SUCCEEDED(hr))
603 {
604 UpdateCacheSuccessProgress(pPlan, pCacheAction, &qwSuccessfulCachedProgress);
605 }
606 else
607 {
608 LogErrorId(hr, MSG_FAILED_CACHE_PAYLOAD, pCacheAction->cachePayload.pPayload->sczKey, pCacheAction->cachePayload.sczUnverifiedPath, NULL);
609
610 if (fRetryContainerOrPayload)
611 {
612 wzRetryId = pCacheAction->cachePayload.pPayload->sczKey;
613 iRetryContainerOrPayloadAction = pCacheAction->cachePayload.iTryAgainAction;
614
615 ++pCacheAction->cachePayload.cTryAgainAttempts;
616 }
617 }
618 break;
619
620 case BURN_CACHE_ACTION_TYPE_LAYOUT_PAYLOAD:
621 hr = LayoutOrCacheContainerOrPayload(pUX, hPipe, NULL, pCacheAction->layoutPayload.pPackage, pCacheAction->layoutPayload.pPayload, pPlan->rgPayloadProgress[pCacheAction->layoutPayload.iProgress].fCachedDuringApply, qwSuccessfulCachedProgress, pPlan->qwCacheSizeTotal, pCacheAction->layoutPayload.sczLayoutDirectory, pCacheAction->layoutPayload.sczUnverifiedPath, pCacheAction->layoutPayload.fMove, pCacheAction->layoutPayload.cTryAgainAttempts, &fRetryContainerOrPayload);
622 if (SUCCEEDED(hr))
623 {
624 UpdateCacheSuccessProgress(pPlan, pCacheAction, &qwSuccessfulCachedProgress);
625 }
626 else
627 {
628 LogErrorId(hr, MSG_FAILED_LAYOUT_PAYLOAD, pCacheAction->layoutPayload.pPayload->sczKey, pCacheAction->layoutPayload.sczLayoutDirectory, pCacheAction->layoutPayload.sczUnverifiedPath);
629
630 if (fRetryContainerOrPayload)
631 {
632 wzRetryId = pCacheAction->layoutPayload.pPayload->sczKey;
633 iRetryContainerOrPayloadAction = pCacheAction->layoutPayload.iTryAgainAction;
634
635 ++pCacheAction->layoutPayload.cTryAgainAttempts;
636 }
637 }
638 break;
639
640 case BURN_CACHE_ACTION_TYPE_PACKAGE_STOP:
641 AssertSz(pStartedPackage == pCacheAction->packageStop.pPackage, "Expected package started cached to be the same as the package checkpointed.");
642 499
643 hr = ReportOverallProgressTicks(pUX, FALSE, pPlan->cOverallProgressTicksTotal, *pcOverallProgressTicks + 1); 500 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
644 if (FAILED(hr)) 501 hr = ApplyLayoutBundle(&cacheContext, pCacheAction->bundleLayout.pPayloadGroup, pCacheAction->bundleLayout.sczExecutableName, pCacheAction->bundleLayout.sczUnverifiedPath);
645 { 502 ExitOnFailure(hr, "Failed cache action: %ls", L"layout bundle");
646 LogErrorId(hr, MSG_USER_CANCELED, L"end cache package", NULL, NULL);
647 }
648 else
649 {
650 ++(*pcOverallProgressTicks);
651 503
652 UserExperienceOnCachePackageComplete(pUX, pStartedPackage->sczId, hr, &cachePackageCompleteAction); 504 ++(*pcOverallProgressTicks);
653 505
654 pStartedPackage->hrCacheResult = hr; 506 hr = ReportOverallProgressTicks(pUX, FALSE, pPlan->cOverallProgressTicksTotal, *pcOverallProgressTicks);
507 LogExitOnFailure(hr, MSG_USER_CANCELED, "Cancel during cache: %ls", L"layout bundle");
655 508
656 iPackageStartAction = BURN_PLAN_INVALID_ACTION_INDEX; 509 break;
657 iPackageCompleteAction = BURN_PLAN_INVALID_ACTION_INDEX;
658 pStartedPackage = NULL;
659 }
660 break;
661 510
662 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 511 case BURN_CACHE_ACTION_TYPE_PACKAGE:
663 if (!::SetEvent(pCacheAction->syncpoint.hEvent)) 512 pPackage = pCacheAction->package.pPackage;
664 {
665 ExitWithLastError(hr, "Failed to set syncpoint event.");
666 }
667 break;
668 513
669 default: 514 if (!pPackage->fPerMachine && !cacheContext.wzLayoutDirectory)
670 AssertSz(FALSE, "Unknown cache action."); 515 {
671 break; 516 cacheContext.hPipe = INVALID_HANDLE_VALUE;
672 } 517 }
673 }
674
675 if (BURN_PLAN_INVALID_ACTION_INDEX != iRetryContainerOrPayloadAction)
676 {
677 Assert(wzRetryId);
678 518
679 LogErrorId(hr, MSG_APPLY_RETRYING_PAYLOAD, wzRetryId, NULL, NULL); 519 hr = ApplyCachePackage(&cacheContext, pPackage);
520 ExitOnFailure(hr, "Failed cache action: %ls", L"cache package");
680 521
681 iRetryAction = iRetryContainerOrPayloadAction; 522 ++(*pcOverallProgressTicks);
682 fRetry = TRUE;
683 }
684 else if (pStartedPackage)
685 {
686 Assert(BURN_PLAN_INVALID_ACTION_INDEX != iPackageStartAction);
687 Assert(BURN_PLAN_INVALID_ACTION_INDEX != iPackageCompleteAction);
688 523
689 cachePackageCompleteAction = SUCCEEDED(hr) || pStartedPackage->fVital ? BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE : BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE; 524 hr = ReportOverallProgressTicks(pUX, FALSE, pPlan->cOverallProgressTicksTotal, *pcOverallProgressTicks);
690 UserExperienceOnCachePackageComplete(pUX, pStartedPackage->sczId, hr, &cachePackageCompleteAction); 525 LogExitOnFailure(hr, MSG_USER_CANCELED, "Cancel during cache: %ls", L"cache package");
691 if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY == cachePackageCompleteAction)
692 {
693 LogErrorId(hr, MSG_APPLY_RETRYING_PACKAGE, pStartedPackage->sczId, NULL, NULL);
694 526
695 iRetryAction = iPackageStartAction; 527 break;
696 fRetry = TRUE;
697 }
698 else if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE == cachePackageCompleteAction && !pStartedPackage->fVital) // ignore non-vital download failures.
699 {
700 LogId(REPORT_STANDARD, MSG_APPLY_CONTINUING_NONVITAL_PACKAGE, pStartedPackage->sczId, hr);
701 528
702 ++(*pcOverallProgressTicks); // add progress even though we didn't fully cache the package. 529 case BURN_CACHE_ACTION_TYPE_CONTAINER:
530 Assert(pPlan->sczLayoutDirectory);
531 hr = ApplyLayoutContainer(&cacheContext, pCacheAction->container.pContainer);
532 ExitOnFailure(hr, "Failed cache action: %ls", L"layout container");
533
534 break;
703 535
704 iRetryAction = iPackageCompleteAction + 1; 536 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
705 fRetry = TRUE; 537 if (!::SetEvent(pCacheAction->syncpoint.hEvent))
538 {
539 ExitWithLastError(hr, "Failed to set syncpoint event.");
706 } 540 }
541 break;
707 542
708 pStartedPackage->hrCacheResult = hr; 543 default:
709 544 AssertSz(FALSE, "Unknown cache action.");
710 iPackageStartAction = BURN_PLAN_INVALID_ACTION_INDEX; 545 break;
711 iPackageCompleteAction = BURN_PLAN_INVALID_ACTION_INDEX;
712 pStartedPackage = NULL;
713 }
714 else
715 {
716 Assert(BURN_PLAN_INVALID_ACTION_INDEX == iPackageStartAction);
717 Assert(BURN_PLAN_INVALID_ACTION_INDEX == iPackageCompleteAction);
718 } 546 }
719 } while (fRetry); 547 }
720 548
721LExit: 549LExit:
722 Assert(NULL == pStartedPackage);
723 Assert(BURN_PLAN_INVALID_ACTION_INDEX == iPackageStartAction);
724 Assert(BURN_PLAN_INVALID_ACTION_INDEX == iPackageCompleteAction);
725
726 if (FAILED(hr)) 550 if (FAILED(hr))
727 { 551 {
728 DoRollbackCache(pUX, pPlan, hPipe, dwCheckpoint); 552 DoRollbackCache(pUX, pPlan, hPipe, dwCheckpoint);
@@ -936,12 +760,216 @@ LExit:
936 return hr; 760 return hr;
937} 761}
938 762
763static HRESULT ApplyCachePackage(
764 __in BURN_CACHE_CONTEXT* pContext,
765 __in BURN_PACKAGE* pPackage
766 )
767{
768 HRESULT hr = S_OK;
769 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE;
770
771 for (;;)
772 {
773 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cPayloads, pPackage->payloads.qwTotalSize);
774 LogExitOnFailure(hr, MSG_USER_CANCELED, "Cancel during cache: %ls: %ls", L"begin cache package", pPackage->sczId);
775
776 for (DWORD i = 0; i < pPackage->payloads.cPayloads; ++i)
777 {
778 BURN_PAYLOAD* pPayload = pPackage->payloads.rgpPayloads[i];
779
780 hr = ApplyProcessPayload(pContext, pPackage, pPayload);
781 if (FAILED(hr))
782 {
783 break;
784 }
785 }
786
787 pPackage->hrCacheResult = hr;
788 cachePackageCompleteAction = SUCCEEDED(hr) || pPackage->fVital ? BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE : BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE;
789 UserExperienceOnCachePackageComplete(pContext->pUX, pPackage->sczId, hr, &cachePackageCompleteAction);
790
791 if (SUCCEEDED(hr))
792 {
793 break;
794 }
795
796 if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY == cachePackageCompleteAction)
797 {
798 // TODO: the progress needs to account for the payloads (potentially) being recached.
799 LogErrorId(hr, MSG_APPLY_RETRYING_PACKAGE, pPackage->sczId, NULL, NULL);
800
801 continue;
802 }
803 else if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE == cachePackageCompleteAction && !pPackage->fVital) // ignore non-vital download failures.
804 {
805 LogId(REPORT_STANDARD, MSG_APPLY_CONTINUING_NONVITAL_PACKAGE, pPackage->sczId, hr);
806 hr = S_OK;
807 }
808
809 break;
810 }
811
812LExit:
813 return hr;
814}
815
816static HRESULT ApplyExtractContainer(
817 __in BURN_CACHE_CONTEXT* pContext,
818 __in BURN_CONTAINER* pContainer
819 )
820{
821 HRESULT hr = S_OK;
822
823 if (!pContainer->fActuallyAttached)
824 {
825 hr = AcquireContainerOrPayload(pContext, pContainer, NULL, NULL);
826 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
827 }
828
829 pContext->qwSuccessfulCacheProgress += pContainer->qwFileSize;
830
831 hr = ExtractContainer(pContext, pContainer);
832 LogExitOnFailure(hr, MSG_FAILED_EXTRACT_CONTAINER, "Failed to extract payloads from container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
833
834 pContext->qwSuccessfulCacheProgress += pContainer->qwFileSize;
835
836LExit:
837 return hr;
838}
839
840static HRESULT ApplyLayoutBundle(
841 __in BURN_CACHE_CONTEXT* pContext,
842 __in BURN_PAYLOAD_GROUP* pPayloads,
843 __in_z LPCWSTR wzExecutableName,
844 __in_z LPCWSTR wzUnverifiedPath
845 )
846{
847 HRESULT hr = S_OK;
848
849 hr = LayoutBundle(pContext, wzExecutableName, wzUnverifiedPath);
850 ExitOnFailure(hr, "Failed to layout bundle.");
851
852 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
853 {
854 BURN_PAYLOAD* pPayload = pPayloads->rgpPayloads[i];
855
856 hr = ApplyProcessPayload(pContext, NULL, pPayload);
857 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayload->sczKey);
858 }
859
860LExit:
861 return hr;
862}
863
864static HRESULT ApplyLayoutContainer(
865 __in BURN_CACHE_CONTEXT* pContext,
866 __in BURN_CONTAINER* pContainer
867 )
868{
869 HRESULT hr = S_OK;
870 DWORD cTryAgainAttempts = 0;
871 BOOL fRetry = FALSE;
872
873 Assert(!pContainer->fAttached);
874
875 for (;;)
876 {
877 fRetry = FALSE;
878
879 hr = AcquireContainerOrPayload(pContext, pContainer, NULL, NULL);
880 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
881
882 pContext->qwSuccessfulCacheProgress += pContainer->qwFileSize;
883
884 hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, TRUE, cTryAgainAttempts, &fRetry);
885 if (SUCCEEDED(hr))
886 {
887 pContext->qwSuccessfulCacheProgress += pContainer->qwFileSize;
888 break;
889 }
890 else
891 {
892 LogErrorId(hr, MSG_FAILED_LAYOUT_CONTAINER, pContainer->sczId, pContext->wzLayoutDirectory, pContainer->sczUnverifiedPath);
893
894 if (!fRetry)
895 {
896 ExitFunction();
897 }
898
899 ++cTryAgainAttempts;
900 pContext->qwSuccessfulCacheProgress -= pContainer->qwFileSize;
901 LogErrorId(hr, MSG_APPLY_RETRYING_PAYLOAD, pContainer->sczId, NULL, NULL);
902 }
903 }
904
905LExit:
906 return hr;
907}
908
909static HRESULT ApplyProcessPayload(
910 __in BURN_CACHE_CONTEXT* pContext,
911 __in_opt BURN_PACKAGE* pPackage,
912 __in BURN_PAYLOAD* pPayload
913 )
914{
915 HRESULT hr = S_OK;
916 DWORD cTryAgainAttempts = 0;
917 BOOL fRetry = FALSE;
918
919 Assert(pContext->pPayloads || pContext->wzLayoutDirectory);
920
921 for (;;)
922 {
923 fRetry = FALSE;
924
925 if (pPayload->pContainer)
926 {
927 if (pContext->wzLayoutDirectory)
928 {
929 ExitFunction();
930 }
931
932 // TODO: only extract container if payload isn't already cached and isn't already extracted
933 hr = ApplyExtractContainer(pContext, pPayload->pContainer);
934 ExitOnFailure(hr, "Failed to extract container for payload: %ls", pPayload->sczKey);
935 }
936 else
937 {
938 hr = AcquireContainerOrPayload(pContext, NULL, pPackage, pPayload);
939 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath);
940 }
941
942 pContext->qwSuccessfulCacheProgress += pPayload->qwFileSize;
943
944 // TODO: set fMove to TRUE appropriately
945 hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayload, FALSE, cTryAgainAttempts, &fRetry);
946 if (SUCCEEDED(hr))
947 {
948 pContext->qwSuccessfulCacheProgress += pPayload->qwFileSize;
949 break;
950 }
951 else
952 {
953 LogErrorId(hr, pContext->wzLayoutDirectory ? MSG_FAILED_LAYOUT_PAYLOAD : MSG_FAILED_CACHE_PAYLOAD, pPayload->sczKey, pContext->wzLayoutDirectory, pPayload->sczUnverifiedPath);
954
955 if (!fRetry)
956 {
957 ExitFunction();
958 }
959
960 ++cTryAgainAttempts;
961 pContext->qwSuccessfulCacheProgress -= pPayload->qwFileSize;
962 LogErrorId(hr, MSG_APPLY_RETRYING_PAYLOAD, pPayload->sczKey, NULL, NULL);
963 }
964 }
965
966LExit:
967 return hr;
968}
969
939static HRESULT ExtractContainer( 970static HRESULT ExtractContainer(
940 __in HANDLE hSourceEngineFile, 971 __in BURN_CACHE_CONTEXT* pContext,
941 __in BURN_CONTAINER* pContainer, 972 __in BURN_CONTAINER* pContainer
942 __in_z LPCWSTR wzContainerPath,
943 __in_ecount(cExtractPayloads) BURN_EXTRACT_PAYLOAD* rgExtractPayloads,
944 __in DWORD cExtractPayloads
945 ) 973 )
946{ 974{
947 HRESULT hr = S_OK; 975 HRESULT hr = S_OK;
@@ -952,20 +980,20 @@ static HRESULT ExtractContainer(
952 // If the container is actually attached, then it was planned to be acquired through hSourceEngineFile. 980 // If the container is actually attached, then it was planned to be acquired through hSourceEngineFile.
953 if (pContainer->fActuallyAttached) 981 if (pContainer->fActuallyAttached)
954 { 982 {
955 hContainerHandle = hSourceEngineFile; 983 hContainerHandle = pContext->hSourceEngineFile;
956 } 984 }
957 985
958 hr = ContainerOpen(&context, pContainer, hContainerHandle, wzContainerPath); 986 hr = ContainerOpen(&context, pContainer, hContainerHandle, pContainer->sczUnverifiedPath);
959 ExitOnFailure(hr, "Failed to open container: %ls.", pContainer->sczId); 987 ExitOnFailure(hr, "Failed to open container: %ls.", pContainer->sczId);
960 988
961 while (S_OK == (hr = ContainerNextStream(&context, &sczExtractPayloadId))) 989 while (S_OK == (hr = ContainerNextStream(&context, &sczExtractPayloadId)))
962 { 990 {
963 BOOL fExtracted = FALSE; 991 BOOL fExtracted = FALSE;
964 992
965 for (DWORD iExtract = 0; iExtract < cExtractPayloads; ++iExtract) 993 for (DWORD iExtract = 0; iExtract < pContext->pPayloads->cPayloads; ++iExtract)
966 { 994 {
967 BURN_EXTRACT_PAYLOAD* pExtract = rgExtractPayloads + iExtract; 995 BURN_PAYLOAD* pExtract = pContext->pPayloads->rgPayloads + iExtract;
968 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczExtractPayloadId, -1, pExtract->pPayload->sczSourcePath, -1)) 996 if (pExtract->sczUnverifiedPath && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczExtractPayloadId, -1, pExtract->sczSourcePath, -1))
969 { 997 {
970 // TODO: Send progress when extracting stream to file. 998 // TODO: Send progress when extracting stream to file.
971 hr = ContainerStreamToFile(&context, pExtract->sczUnverifiedPath); 999 hr = ContainerStreamToFile(&context, pExtract->sczUnverifiedPath);
@@ -996,74 +1024,10 @@ LExit:
996 return hr; 1024 return hr;
997} 1025}
998 1026
999static void UpdateCacheSuccessProgress(
1000 __in BURN_PLAN* pPlan,
1001 __in BURN_CACHE_ACTION* pCacheAction,
1002 __inout DWORD64* pqwSuccessfulCachedProgress
1003 )
1004{
1005 switch (pCacheAction->type)
1006 {
1007 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
1008 *pqwSuccessfulCachedProgress += pCacheAction->bundleLayout.qwBundleSize;
1009 break;
1010
1011 case BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER:
1012 if (!pPlan->rgContainerProgress[pCacheAction->resolveContainer.iProgress].fCachedDuringApply)
1013 {
1014 pPlan->rgContainerProgress[pCacheAction->resolveContainer.iProgress].fCachedDuringApply = TRUE;
1015 *pqwSuccessfulCachedProgress += pCacheAction->resolveContainer.pContainer->qwFileSize;
1016 }
1017 break;
1018
1019 case BURN_CACHE_ACTION_TYPE_LAYOUT_CONTAINER:
1020 if (!pPlan->rgContainerProgress[pCacheAction->layoutContainer.iProgress].fCachedDuringApply)
1021 {
1022 pPlan->rgContainerProgress[pCacheAction->layoutContainer.iProgress].fCachedDuringApply = TRUE;
1023 *pqwSuccessfulCachedProgress += pCacheAction->layoutContainer.pContainer->qwFileSize;
1024 }
1025 break;
1026
1027 case BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD:
1028 if (!pPlan->rgPayloadProgress[pCacheAction->resolvePayload.iProgress].fCachedDuringApply)
1029 {
1030 pPlan->rgPayloadProgress[pCacheAction->resolvePayload.iProgress].fCachedDuringApply = TRUE;
1031 *pqwSuccessfulCachedProgress += pCacheAction->resolvePayload.pPayload->qwFileSize;
1032 }
1033 break;
1034
1035 case BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD:
1036 if (!pPlan->rgPayloadProgress[pCacheAction->cachePayload.iProgress].fCachedDuringApply)
1037 {
1038 pPlan->rgPayloadProgress[pCacheAction->cachePayload.iProgress].fCachedDuringApply = TRUE;
1039 *pqwSuccessfulCachedProgress += pCacheAction->cachePayload.pPayload->qwFileSize;
1040 }
1041 break;
1042
1043 case BURN_CACHE_ACTION_TYPE_LAYOUT_PAYLOAD:
1044 if (!pPlan->rgPayloadProgress[pCacheAction->layoutPayload.iProgress].fCachedDuringApply)
1045 {
1046 pPlan->rgPayloadProgress[pCacheAction->layoutPayload.iProgress].fCachedDuringApply = TRUE;
1047 *pqwSuccessfulCachedProgress += pCacheAction->layoutPayload.pPayload->qwFileSize;
1048 }
1049 break;
1050
1051 default:
1052 AssertSz(FALSE, "Unexpected cache action type.");
1053 break;
1054 }
1055}
1056
1057static HRESULT LayoutBundle( 1027static HRESULT LayoutBundle(
1058 __in HANDLE hSourceEngineFile, 1028 __in BURN_CACHE_CONTEXT* pContext,
1059 __in BURN_USER_EXPERIENCE* pUX,
1060 __in BURN_VARIABLES* pVariables,
1061 __in HANDLE hPipe,
1062 __in_z LPCWSTR wzExecutableName, 1029 __in_z LPCWSTR wzExecutableName,
1063 __in_z LPCWSTR wzLayoutDirectory, 1030 __in_z LPCWSTR wzUnverifiedPath
1064 __in_z LPCWSTR wzUnverifiedPath,
1065 __in DWORD64 qwSuccessfulCacheProgress,
1066 __in DWORD64 qwTotalCacheSize
1067 ) 1031 )
1068{ 1032{
1069 HRESULT hr = S_OK; 1033 HRESULT hr = S_OK;
@@ -1074,7 +1038,7 @@ static HRESULT LayoutBundle(
1074 BOOL fRetry = FALSE; 1038 BOOL fRetry = FALSE;
1075 BOOL fRetryAcquire = FALSE; 1039 BOOL fRetryAcquire = FALSE;
1076 1040
1077 hr = VariableGetString(pVariables, BURN_BUNDLE_SOURCE_PROCESS_PATH, &sczBundlePath); 1041 hr = VariableGetString(pContext->pVariables, BURN_BUNDLE_SOURCE_PROCESS_PATH, &sczBundlePath);
1078 if (FAILED(hr)) 1042 if (FAILED(hr))
1079 { 1043 {
1080 if (E_NOTFOUND != hr) 1044 if (E_NOTFOUND != hr)
@@ -1086,7 +1050,7 @@ static HRESULT LayoutBundle(
1086 ExitOnFailure(hr, "Failed to get path to bundle to layout."); 1050 ExitOnFailure(hr, "Failed to get path to bundle to layout.");
1087 } 1051 }
1088 1052
1089 hr = PathConcat(wzLayoutDirectory, wzExecutableName, &sczDestinationPath); 1053 hr = PathConcat(pContext->wzLayoutDirectory, wzExecutableName, &sczDestinationPath);
1090 ExitOnFailure(hr, "Failed to concat layout path for bundle."); 1054 ExitOnFailure(hr, "Failed to concat layout path for bundle.");
1091 1055
1092 // If the destination path is the currently running bundle, bail. 1056 // If the destination path is the currently running bundle, bail.
@@ -1098,9 +1062,7 @@ static HRESULT LayoutBundle(
1098 ExitFunction1(hr = S_OK); 1062 ExitFunction1(hr = S_OK);
1099 } 1063 }
1100 1064
1101 progress.pUX = pUX; 1065 progress.pCacheContext = pContext;
1102 progress.qwCacheProgress = qwSuccessfulCacheProgress;
1103 progress.qwTotalCacheSize = qwTotalCacheSize;
1104 1066
1105 do 1067 do
1106 { 1068 {
@@ -1112,13 +1074,13 @@ static HRESULT LayoutBundle(
1112 fRetryAcquire = FALSE; 1074 fRetryAcquire = FALSE;
1113 progress.fCancel = FALSE; 1075 progress.fCancel = FALSE;
1114 1076
1115 hr = UserExperienceOnCacheAcquireBegin(pUX, NULL, NULL, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczBundlePath); 1077 hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, NULL, NULL, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczBundlePath);
1116 ExitOnRootFailure(hr, "BA aborted cache acquire begin."); 1078 ExitOnRootFailure(hr, "BA aborted cache acquire begin.");
1117 1079
1118 hr = CopyPayload(&progress, hSourceEngineFile, sczBundlePath, wzUnverifiedPath); 1080 hr = CopyPayload(&progress, pContext->hSourceEngineFile, sczBundlePath, wzUnverifiedPath);
1119 // Error handling happens after sending complete message to BA. 1081 // Error handling happens after sending complete message to BA.
1120 1082
1121 UserExperienceOnCacheAcquireComplete(pUX, NULL, NULL, hr, &fRetryAcquire); 1083 UserExperienceOnCacheAcquireComplete(pContext->pUX, NULL, NULL, hr, &fRetryAcquire);
1122 if (fRetryAcquire) 1084 if (fRetryAcquire)
1123 { 1085 {
1124 continue; 1086 continue;
@@ -1130,20 +1092,20 @@ static HRESULT LayoutBundle(
1130 1092
1131 do 1093 do
1132 { 1094 {
1133 hr = UserExperienceOnCacheVerifyBegin(pUX, NULL, NULL); 1095 hr = UserExperienceOnCacheVerifyBegin(pContext->pUX, NULL, NULL);
1134 ExitOnRootFailure(hr, "BA aborted cache verify begin."); 1096 ExitOnRootFailure(hr, "BA aborted cache verify begin.");
1135 1097
1136 if (INVALID_HANDLE_VALUE != hPipe) 1098 if (INVALID_HANDLE_VALUE != pContext->hPipe)
1137 { 1099 {
1138 hr = ElevationLayoutBundle(hPipe, wzLayoutDirectory, wzUnverifiedPath); 1100 hr = ElevationLayoutBundle(pContext->hPipe, pContext->wzLayoutDirectory, wzUnverifiedPath);
1139 } 1101 }
1140 else 1102 else
1141 { 1103 {
1142 hr = CacheLayoutBundle(wzExecutableName, wzLayoutDirectory, wzUnverifiedPath); 1104 hr = CacheLayoutBundle(wzExecutableName, pContext->wzLayoutDirectory, wzUnverifiedPath);
1143 } 1105 }
1144 1106
1145 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE; 1107 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE;
1146 UserExperienceOnCacheVerifyComplete(pUX, NULL, NULL, hr, &action); 1108 UserExperienceOnCacheVerifyComplete(pContext->pUX, NULL, NULL, hr, &action);
1147 if (BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYVERIFICATION == action) 1109 if (BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYVERIFICATION == action)
1148 { 1110 {
1149 hr = S_FALSE; // retry verify. 1111 hr = S_FALSE; // retry verify.
@@ -1154,7 +1116,7 @@ static HRESULT LayoutBundle(
1154 } 1116 }
1155 } while (S_FALSE == hr); 1117 } while (S_FALSE == hr);
1156 } while (fRetry); 1118 } while (fRetry);
1157 LogExitOnFailure(hr, MSG_FAILED_LAYOUT_BUNDLE, "Failed to layout bundle: %ls to layout directory: %ls", sczBundlePath, wzLayoutDirectory); 1119 LogExitOnFailure(hr, MSG_FAILED_LAYOUT_BUNDLE, "Failed to layout bundle: %ls to layout directory: %ls", sczBundlePath, pContext->wzLayoutDirectory);
1158 1120
1159LExit: 1121LExit:
1160 ReleaseStr(sczDestinationPath); 1122 ReleaseStr(sczDestinationPath);
@@ -1164,14 +1126,10 @@ LExit:
1164} 1126}
1165 1127
1166static HRESULT AcquireContainerOrPayload( 1128static HRESULT AcquireContainerOrPayload(
1167 __in BURN_USER_EXPERIENCE* pUX, 1129 __in BURN_CACHE_CONTEXT* pContext,
1168 __in BURN_VARIABLES* pVariables,
1169 __in_opt BURN_CONTAINER* pContainer, 1130 __in_opt BURN_CONTAINER* pContainer,
1170 __in_opt BURN_PACKAGE* pPackage, 1131 __in_opt BURN_PACKAGE* pPackage,
1171 __in_opt BURN_PAYLOAD* pPayload, 1132 __in_opt BURN_PAYLOAD* pPayload
1172 __in LPCWSTR wzDestinationPath,
1173 __in DWORD64 qwSuccessfulCacheProgress,
1174 __in DWORD64 qwTotalCacheSize
1175 ) 1133 )
1176{ 1134{
1177 AssertSz(pContainer || pPayload, "Must provide a container or a payload."); 1135 AssertSz(pContainer || pPayload, "Must provide a container or a payload.");
@@ -1180,17 +1138,16 @@ static HRESULT AcquireContainerOrPayload(
1180 int nEquivalentPaths = 0; 1138 int nEquivalentPaths = 0;
1181 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL; 1139 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL;
1182 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL; 1140 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL;
1141 LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath;
1183 LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath; 1142 LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath;
1184 LPWSTR sczSourceFullPath = NULL; 1143 LPWSTR sczSourceFullPath = NULL;
1185 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; 1144 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1186 BOOL fRetry = FALSE; 1145 BOOL fRetry = FALSE;
1187 1146
1147 progress.pCacheContext = pContext;
1188 progress.pContainer = pContainer; 1148 progress.pContainer = pContainer;
1189 progress.pPackage = pPackage; 1149 progress.pPackage = pPackage;
1190 progress.pPayload = pPayload; 1150 progress.pPayload = pPayload;
1191 progress.pUX = pUX;
1192 progress.qwCacheProgress = qwSuccessfulCacheProgress;
1193 progress.qwTotalCacheSize = qwTotalCacheSize;
1194 1151
1195 do 1152 do
1196 { 1153 {
@@ -1204,7 +1161,7 @@ static HRESULT AcquireContainerOrPayload(
1204 fRetry = FALSE; 1161 fRetry = FALSE;
1205 progress.fCancel = FALSE; 1162 progress.fCancel = FALSE;
1206 1163
1207 hr = CacheFindLocalSource(wzSourcePath, pVariables, &fFoundLocal, &sczSourceFullPath); 1164 hr = CacheFindLocalSource(wzSourcePath, wzDestinationPath, pContext->pVariables, &fFoundLocal, &sczSourceFullPath);
1208 ExitOnFailure(hr, "Failed to search local source."); 1165 ExitOnFailure(hr, "Failed to search local source.");
1209 1166
1210 if (fFoundLocal) // the file exists locally, so copy it. 1167 if (fFoundLocal) // the file exists locally, so copy it.
@@ -1220,7 +1177,7 @@ static HRESULT AcquireContainerOrPayload(
1220 DWORD dwLogId = pContainer ? (wzPayloadId ? MSG_PROMPT_CONTAINER_PAYLOAD_SOURCE : MSG_PROMPT_CONTAINER_SOURCE) : pPackage ? MSG_PROMPT_PACKAGE_PAYLOAD_SOURCE : MSG_PROMPT_BUNDLE_PAYLOAD_SOURCE; 1177 DWORD dwLogId = pContainer ? (wzPayloadId ? MSG_PROMPT_CONTAINER_PAYLOAD_SOURCE : MSG_PROMPT_CONTAINER_SOURCE) : pPackage ? MSG_PROMPT_PACKAGE_PAYLOAD_SOURCE : MSG_PROMPT_BUNDLE_PAYLOAD_SOURCE;
1221 LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId ? wzPackageOrContainerId : L"", wzPayloadId ? wzPayloadId : L"", sczSourceFullPath); 1178 LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId ? wzPackageOrContainerId : L"", wzPayloadId ? wzPayloadId : L"", sczSourceFullPath);
1222 1179
1223 hr = PromptForSource(pUX, wzPackageOrContainerId, wzPayloadId, sczSourceFullPath, wzDownloadUrl, &fRetry, &fDownload); 1180 hr = PromptForSource(pContext->pUX, wzPackageOrContainerId, wzPayloadId, sczSourceFullPath, wzDownloadUrl, &fRetry, &fDownload);
1224 1181
1225 // If the BA requested download then ensure a download url is available (it may have been set 1182 // If the BA requested download then ensure a download url is available (it may have been set
1226 // during PromptForSource so we need to check again). 1183 // during PromptForSource so we need to check again).
@@ -1239,7 +1196,7 @@ static HRESULT AcquireContainerOrPayload(
1239 1196
1240 if (fCopy) 1197 if (fCopy)
1241 { 1198 {
1242 hr = UserExperienceOnCacheAcquireBegin(pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczSourceFullPath); 1199 hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczSourceFullPath);
1243 ExitOnRootFailure(hr, "BA aborted cache acquire begin."); 1200 ExitOnRootFailure(hr, "BA aborted cache acquire begin.");
1244 1201
1245 hr = CopyPayload(&progress, INVALID_HANDLE_VALUE, sczSourceFullPath, wzDestinationPath); 1202 hr = CopyPayload(&progress, INVALID_HANDLE_VALUE, sczSourceFullPath, wzDestinationPath);
@@ -1248,12 +1205,12 @@ static HRESULT AcquireContainerOrPayload(
1248 // We successfully copied from a source location, set that as the last used source. 1205 // We successfully copied from a source location, set that as the last used source.
1249 if (SUCCEEDED(hr)) 1206 if (SUCCEEDED(hr))
1250 { 1207 {
1251 CacheSetLastUsedSource(pVariables, sczSourceFullPath, wzRelativePath); 1208 CacheSetLastUsedSource(pContext->pVariables, sczSourceFullPath, wzRelativePath);
1252 } 1209 }
1253 } 1210 }
1254 else if (fDownload) 1211 else if (fDownload)
1255 { 1212 {
1256 hr = UserExperienceOnCacheAcquireBegin(pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD, wzDownloadUrl); 1213 hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD, wzDownloadUrl);
1257 ExitOnRootFailure(hr, "BA aborted cache download payload begin."); 1214 ExitOnRootFailure(hr, "BA aborted cache download payload begin.");
1258 1215
1259 hr = DownloadPayload(&progress, wzDestinationPath); 1216 hr = DownloadPayload(&progress, wzDestinationPath);
@@ -1262,7 +1219,7 @@ static HRESULT AcquireContainerOrPayload(
1262 1219
1263 if (fCopy || fDownload) 1220 if (fCopy || fDownload)
1264 { 1221 {
1265 UserExperienceOnCacheAcquireComplete(pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); 1222 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry);
1266 if (fRetry) 1223 if (fRetry)
1267 { 1224 {
1268 hr = S_OK; 1225 hr = S_OK;
@@ -1279,16 +1236,10 @@ LExit:
1279} 1236}
1280 1237
1281static HRESULT LayoutOrCacheContainerOrPayload( 1238static HRESULT LayoutOrCacheContainerOrPayload(
1282 __in BURN_USER_EXPERIENCE* pUX, 1239 __in BURN_CACHE_CONTEXT* pContext,
1283 __in HANDLE hPipe,
1284 __in_opt BURN_CONTAINER* pContainer, 1240 __in_opt BURN_CONTAINER* pContainer,
1285 __in_opt BURN_PACKAGE* pPackage, 1241 __in_opt BURN_PACKAGE* pPackage,
1286 __in_opt BURN_PAYLOAD* pPayload, 1242 __in_opt BURN_PAYLOAD* pPayload,
1287 __in BOOL fAlreadyProvidedProgress,
1288 __in DWORD64 qwSuccessfulCachedProgress,
1289 __in DWORD64 qwTotalCacheSize,
1290 __in_z_opt LPCWSTR wzLayoutDirectory,
1291 __in_z LPCWSTR wzUnverifiedPath,
1292 __in BOOL fMove, 1243 __in BOOL fMove,
1293 __in DWORD cTryAgainAttempts, 1244 __in DWORD cTryAgainAttempts,
1294 __out BOOL* pfRetry 1245 __out BOOL* pfRetry
@@ -1296,13 +1247,14 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1296{ 1247{
1297 HRESULT hr = S_OK; 1248 HRESULT hr = S_OK;
1298 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L""; 1249 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L"";
1250 LPCWSTR wzUnverifiedPath = pContainer ? pContainer->sczUnverifiedPath : pPayload->sczUnverifiedPath;
1299 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L""; 1251 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L"";
1300 LARGE_INTEGER liContainerOrPayloadSize = { }; 1252 LARGE_INTEGER liContainerOrPayloadSize = { };
1301 LARGE_INTEGER liZero = { }; 1253 LARGE_INTEGER liZero = { };
1302 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; 1254 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1303 BOOL fCanAffectRegistration = FALSE; 1255 BOOL fCanAffectRegistration = FALSE;
1304 1256
1305 if (!wzLayoutDirectory) 1257 if (!pContext->wzLayoutDirectory)
1306 { 1258 {
1307 Assert(!pContainer); 1259 Assert(!pContainer);
1308 Assert(pPackage); 1260 Assert(pPackage);
@@ -1312,41 +1264,31 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1312 1264
1313 liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize; 1265 liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize;
1314 1266
1267 progress.pCacheContext = pContext;
1315 progress.pContainer = pContainer; 1268 progress.pContainer = pContainer;
1316 progress.pPackage = pPackage; 1269 progress.pPackage = pPackage;
1317 progress.pPayload = pPayload; 1270 progress.pPayload = pPayload;
1318 progress.pUX = pUX;
1319 progress.qwTotalCacheSize = qwTotalCacheSize;
1320 if (fAlreadyProvidedProgress)
1321 {
1322 Assert(qwSuccessfulCachedProgress >= static_cast<DWORD64>(liContainerOrPayloadSize.QuadPart));
1323 progress.qwCacheProgress = qwSuccessfulCachedProgress - liContainerOrPayloadSize.QuadPart; // remove the payload size, since it was marked successful thus included in the successful size already.
1324 }
1325 else
1326 {
1327 progress.qwCacheProgress = qwSuccessfulCachedProgress;
1328 }
1329 1271
1330 *pfRetry = FALSE; 1272 *pfRetry = FALSE;
1331 1273
1332 do 1274 do
1333 { 1275 {
1334 hr = UserExperienceOnCacheVerifyBegin(pUX, wzPackageOrContainerId, wzPayloadId); 1276 hr = UserExperienceOnCacheVerifyBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId);
1335 ExitOnRootFailure(hr, "BA aborted cache verify begin."); 1277 ExitOnRootFailure(hr, "BA aborted cache verify begin.");
1336 1278
1337 if (INVALID_HANDLE_VALUE != hPipe) // pass the decision off to the elevated process. 1279 if (INVALID_HANDLE_VALUE != pContext->hPipe) // pass the decision off to the elevated process.
1338 { 1280 {
1339 hr = ElevationCacheOrLayoutContainerOrPayload(hPipe, pContainer, pPackage, pPayload, wzLayoutDirectory, wzUnverifiedPath, fMove); 1281 hr = ElevationCacheOrLayoutContainerOrPayload(pContext->hPipe, pContainer, pPackage, pPayload, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove);
1340 } 1282 }
1341 else if (wzLayoutDirectory) // layout the container or payload. 1283 else if (pContext->wzLayoutDirectory) // layout the container or payload.
1342 { 1284 {
1343 if (pContainer) 1285 if (pContainer)
1344 { 1286 {
1345 hr = CacheLayoutContainer(pContainer, wzLayoutDirectory, wzUnverifiedPath, fMove); 1287 hr = CacheLayoutContainer(pContainer, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove);
1346 } 1288 }
1347 else 1289 else
1348 { 1290 {
1349 hr = CacheLayoutPayload(pPayload, wzLayoutDirectory, wzUnverifiedPath, fMove); 1291 hr = CacheLayoutPayload(pPayload, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove);
1350 } 1292 }
1351 } 1293 }
1352 else // complete the payload. 1294 else // complete the payload.
@@ -1376,7 +1318,7 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1376 } 1318 }
1377 1319
1378 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = FAILED(hr) && cTryAgainAttempts < BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS ? BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYACQUISITION : BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE; 1320 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = FAILED(hr) && cTryAgainAttempts < BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS ? BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYACQUISITION : BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE;
1379 UserExperienceOnCacheVerifyComplete(pUX, wzPackageOrContainerId, wzPayloadId, hr, &action); 1321 UserExperienceOnCacheVerifyComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &action);
1380 if (BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYVERIFICATION == action) 1322 if (BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYVERIFICATION == action)
1381 { 1323 {
1382 hr = S_FALSE; // retry verify. 1324 hr = S_FALSE; // retry verify.
@@ -1541,7 +1483,7 @@ static HRESULT DownloadPayload(
1541 cacheCallback.pfnCancel = NULL; // TODO: set this 1483 cacheCallback.pfnCancel = NULL; // TODO: set this
1542 cacheCallback.pv = pProgress; 1484 cacheCallback.pv = pProgress;
1543 1485
1544 authenticationData.pUX = pProgress->pUX; 1486 authenticationData.pUX = pProgress->pCacheContext->pUX;
1545 authenticationData.wzPackageOrContainerId = wzPackageOrContainerId; 1487 authenticationData.wzPackageOrContainerId = wzPackageOrContainerId;
1546 authenticationData.wzPayloadId = wzPayloadId; 1488 authenticationData.wzPayloadId = wzPayloadId;
1547 authenticationCallback.pv = static_cast<LPVOID>(&authenticationData); 1489 authenticationCallback.pv = static_cast<LPVOID>(&authenticationData);
@@ -1630,15 +1572,15 @@ static DWORD CALLBACK CacheProgressRoutine(
1630 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress = static_cast<BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT*>(lpData); 1572 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress = static_cast<BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT*>(lpData);
1631 LPCWSTR wzPackageOrContainerId = pProgress->pContainer ? pProgress->pContainer->sczId : pProgress->pPackage ? pProgress->pPackage->sczId : NULL; 1573 LPCWSTR wzPackageOrContainerId = pProgress->pContainer ? pProgress->pContainer->sczId : pProgress->pPackage ? pProgress->pPackage->sczId : NULL;
1632 LPCWSTR wzPayloadId = pProgress->pPayload ? pProgress->pPayload->sczKey : NULL; 1574 LPCWSTR wzPayloadId = pProgress->pPayload ? pProgress->pPayload->sczKey : NULL;
1633 DWORD64 qwCacheProgress = pProgress->qwCacheProgress + TotalBytesTransferred.QuadPart; 1575 DWORD64 qwCacheProgress = pProgress->pCacheContext->qwSuccessfulCacheProgress + TotalBytesTransferred.QuadPart;
1634 if (qwCacheProgress > pProgress->qwTotalCacheSize) 1576 if (qwCacheProgress > pProgress->pCacheContext->qwTotalCacheSize)
1635 { 1577 {
1636 AssertSz(FALSE, "Apply has cached more than Plan envisioned."); 1578 //AssertSz(FALSE, "Apply has cached more than Plan envisioned.");
1637 qwCacheProgress = pProgress->qwTotalCacheSize; 1579 qwCacheProgress = pProgress->pCacheContext->qwTotalCacheSize;
1638 } 1580 }
1639 DWORD dwOverallPercentage = pProgress->qwTotalCacheSize ? static_cast<DWORD>(qwCacheProgress * 100 / pProgress->qwTotalCacheSize) : 0; 1581 DWORD dwOverallPercentage = pProgress->pCacheContext->qwTotalCacheSize ? static_cast<DWORD>(qwCacheProgress * 100 / pProgress->pCacheContext->qwTotalCacheSize) : 0;
1640 1582
1641 hr = UserExperienceOnCacheAcquireProgress(pProgress->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage); 1583 hr = UserExperienceOnCacheAcquireProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
1642 if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr) 1584 if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr)
1643 { 1585 {
1644 dwResult = PROGRESS_CANCEL; 1586 dwResult = PROGRESS_CANCEL;