aboutsummaryrefslogtreecommitdiff
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
parentc88806b89293f5bb92c42e90230e48be6b79b7f4 (diff)
downloadwix-90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd.tar.gz
wix-90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd.tar.bz2
wix-90cdf39e6e6b7d676ca33bee031fa2b865bb5fbd.zip
Don't plan payloads.
Contributes to #3640 and #5253
-rw-r--r--src/engine/apply.cpp758
-rw-r--r--src/engine/cache.cpp15
-rw-r--r--src/engine/cache.h1
-rw-r--r--src/engine/container.cpp12
-rw-r--r--src/engine/container.h7
-rw-r--r--src/engine/core.cpp26
-rw-r--r--src/engine/core.h2
-rw-r--r--src/engine/detect.cpp5
-rw-r--r--src/engine/engine.mc4
-rw-r--r--src/engine/exeengine.cpp32
-rw-r--r--src/engine/manifest.cpp2
-rw-r--r--src/engine/msiengine.cpp47
-rw-r--r--src/engine/mspengine.cpp3
-rw-r--r--src/engine/msuengine.cpp12
-rw-r--r--src/engine/package.cpp14
-rw-r--r--src/engine/package.h9
-rw-r--r--src/engine/payload.cpp41
-rw-r--r--src/engine/payload.h12
-rw-r--r--src/engine/plan.cpp893
-rw-r--r--src/engine/plan.h106
-rw-r--r--src/engine/pseudobundle.cpp75
-rw-r--r--src/engine/relatedbundle.cpp9
-rw-r--r--src/engine/userexperience.cpp2
-rw-r--r--src/test/BurnUnitTest/PlanTest.cpp211
24 files changed, 718 insertions, 1580 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;
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp
index 46c2650a..6ddbfb50 100644
--- a/src/engine/cache.cpp
+++ b/src/engine/cache.cpp
@@ -391,6 +391,7 @@ LExit:
391 391
392extern "C" HRESULT CacheFindLocalSource( 392extern "C" HRESULT CacheFindLocalSource(
393 __in_z LPCWSTR wzSourcePath, 393 __in_z LPCWSTR wzSourcePath,
394 __in_z LPCWSTR wzDestinationPath,
394 __in BURN_VARIABLES* pVariables, 395 __in BURN_VARIABLES* pVariables,
395 __out BOOL* pfFound, 396 __out BOOL* pfFound,
396 __out_z LPWSTR* psczSourceFullPath 397 __out_z LPWSTR* psczSourceFullPath
@@ -403,7 +404,7 @@ extern "C" HRESULT CacheFindLocalSource(
403 LPWSTR sczLastSourceFolder = NULL; 404 LPWSTR sczLastSourceFolder = NULL;
404 LPWSTR sczLayoutPath = NULL; 405 LPWSTR sczLayoutPath = NULL;
405 LPWSTR sczLayoutFolder = NULL; 406 LPWSTR sczLayoutFolder = NULL;
406 LPCWSTR rgwzSearchPaths[3] = { }; 407 LPCWSTR rgwzSearchPaths[4] = { };
407 DWORD cSearchPaths = 0; 408 DWORD cSearchPaths = 0;
408 409
409 // If the source path provided is a full path, obviously that is where we should be looking. 410 // If the source path provided is a full path, obviously that is where we should be looking.
@@ -414,8 +415,12 @@ extern "C" HRESULT CacheFindLocalSource(
414 } 415 }
415 else 416 else
416 { 417 {
418 // Use the destination path first.
419 rgwzSearchPaths[0] = wzDestinationPath;
420 cSearchPaths = 1;
421
417 // If we're not running from cache or we couldn't get the last source, use 422 // If we're not running from cache or we couldn't get the last source, use
418 // the source path location first. In the case where we are in the bundle's 423 // the source path location. In the case where we are in the bundle's
419 // package cache and couldn't find a last used source we unfortunately will 424 // package cache and couldn't find a last used source we unfortunately will
420 // be picking the package cache path which isn't likely to have what we are 425 // be picking the package cache path which isn't likely to have what we are
421 // looking for. 426 // looking for.
@@ -428,8 +433,8 @@ extern "C" HRESULT CacheFindLocalSource(
428 hr = PathConcat(sczSourceProcessFolder, wzSourcePath, &sczCurrentPath); 433 hr = PathConcat(sczSourceProcessFolder, wzSourcePath, &sczCurrentPath);
429 ExitOnFailure(hr, "Failed to combine last source with source."); 434 ExitOnFailure(hr, "Failed to combine last source with source.");
430 435
431 rgwzSearchPaths[0] = sczCurrentPath; 436 rgwzSearchPaths[cSearchPaths] = sczCurrentPath;
432 cSearchPaths = 1; 437 ++cSearchPaths;
433 } 438 }
434 439
435 // If we have a last used source and it does not duplicate the existing search path, 440 // If we have a last used source and it does not duplicate the existing search path,
@@ -439,7 +444,7 @@ extern "C" HRESULT CacheFindLocalSource(
439 hr = PathConcat(sczLastSourceFolder, wzSourcePath, &sczLastSourcePath); 444 hr = PathConcat(sczLastSourceFolder, wzSourcePath, &sczLastSourcePath);
440 ExitOnFailure(hr, "Failed to combine last source with source."); 445 ExitOnFailure(hr, "Failed to combine last source with source.");
441 446
442 if (0 == cSearchPaths || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, rgwzSearchPaths[0], -1, sczLastSourcePath, -1)) 447 if (1 == cSearchPaths || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, rgwzSearchPaths[1], -1, sczLastSourcePath, -1))
443 { 448 {
444 rgwzSearchPaths[cSearchPaths] = sczLastSourcePath; 449 rgwzSearchPaths[cSearchPaths] = sczLastSourcePath;
445 ++cSearchPaths; 450 ++cSearchPaths;
diff --git a/src/engine/cache.h b/src/engine/cache.h
index a00c50b7..52b111e9 100644
--- a/src/engine/cache.h
+++ b/src/engine/cache.h
@@ -54,6 +54,7 @@ HRESULT CacheGetResumePath(
54 ); 54 );
55HRESULT CacheFindLocalSource( 55HRESULT CacheFindLocalSource(
56 __in_z LPCWSTR wzSourcePath, 56 __in_z LPCWSTR wzSourcePath,
57 __in_z LPCWSTR wzDestinationPath,
57 __in BURN_VARIABLES* pVariables, 58 __in BURN_VARIABLES* pVariables,
58 __out BOOL* pfFound, 59 __out BOOL* pfFound,
59 __out_z LPWSTR* psczSourceFullPath 60 __out_z LPWSTR* psczSourceFullPath
diff --git a/src/engine/container.cpp b/src/engine/container.cpp
index 55a16afb..2db2412c 100644
--- a/src/engine/container.cpp
+++ b/src/engine/container.cpp
@@ -3,17 +3,6 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6// internal function declarations
7
8static HRESULT GetAttachedContainerInfo(
9 __in HANDLE hFile,
10 __in DWORD iContainerIndex,
11 __out DWORD* pdwFormat,
12 __out DWORD64* pqwOffset,
13 __out DWORD64* pqwSize
14 );
15
16
17// function definitions 6// function definitions
18 7
19extern "C" HRESULT ContainersParseFromXml( 8extern "C" HRESULT ContainersParseFromXml(
@@ -186,6 +175,7 @@ extern "C" void ContainersUninitialize(
186 ReleaseStr(pContainer->downloadSource.sczUrl); 175 ReleaseStr(pContainer->downloadSource.sczUrl);
187 ReleaseStr(pContainer->downloadSource.sczUser); 176 ReleaseStr(pContainer->downloadSource.sczUser);
188 ReleaseStr(pContainer->downloadSource.sczPassword); 177 ReleaseStr(pContainer->downloadSource.sczPassword);
178 ReleaseStr(pContainer->sczUnverifiedPath);
189 } 179 }
190 MemFree(pContainers->rgContainers); 180 MemFree(pContainers->rgContainers);
191 } 181 }
diff --git a/src/engine/container.h b/src/engine/container.h
index bbd9fa72..d38016cc 100644
--- a/src/engine/container.h
+++ b/src/engine/container.h
@@ -65,7 +65,6 @@ typedef struct _BURN_CONTAINER
65 DWORD64 qwFileSize; 65 DWORD64 qwFileSize;
66 LPWSTR sczHash; 66 LPWSTR sczHash;
67 LPWSTR sczFilePath; // relative path to container. 67 LPWSTR sczFilePath; // relative path to container.
68 LPWSTR sczSourcePath;
69 DOWNLOAD_SOURCE downloadSource; 68 DOWNLOAD_SOURCE downloadSource;
70 69
71 BYTE* pbHash; 70 BYTE* pbHash;
@@ -73,8 +72,10 @@ typedef struct _BURN_CONTAINER
73 DWORD64 qwAttachedOffset; 72 DWORD64 qwAttachedOffset;
74 BOOL fActuallyAttached; // indicates whether an attached container is attached or missing. 73 BOOL fActuallyAttached; // indicates whether an attached container is attached or missing.
75 74
76 //LPWSTR* rgsczPayloads; 75 // mutable members
77 //DWORD cPayloads; 76 BOOL fPlanned;
77 LPWSTR sczSourcePath;
78 LPWSTR sczUnverifiedPath;
78} BURN_CONTAINER; 79} BURN_CONTAINER;
79 80
80typedef struct _BURN_CONTAINERS 81typedef struct _BURN_CONTAINERS
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index 42759d3f..98aa943e 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -287,7 +287,7 @@ extern "C" HRESULT CoreDetect(
287 pEngineState->fDetected = FALSE; 287 pEngineState->fDetected = FALSE;
288 pEngineState->fPlanned = FALSE; 288 pEngineState->fPlanned = FALSE;
289 DetectReset(&pEngineState->registration, &pEngineState->packages); 289 DetectReset(&pEngineState->registration, &pEngineState->packages);
290 PlanReset(&pEngineState->plan, &pEngineState->packages); 290 PlanReset(&pEngineState->plan, &pEngineState->containers, &pEngineState->packages, &pEngineState->layoutPayloads);
291 291
292 // Detect if bundle installed state has changed since start up. This 292 // Detect if bundle installed state has changed since start up. This
293 // only happens if Apply() changed the state of bundle (installed or 293 // only happens if Apply() changed the state of bundle (installed or
@@ -438,7 +438,6 @@ extern "C" HRESULT CorePlan(
438{ 438{
439 HRESULT hr = S_OK; 439 HRESULT hr = S_OK;
440 BOOL fPlanBegan = FALSE; 440 BOOL fPlanBegan = FALSE;
441 LPWSTR sczLayoutDirectory = NULL;
442 BURN_PACKAGE* pUpgradeBundlePackage = NULL; 441 BURN_PACKAGE* pUpgradeBundlePackage = NULL;
443 BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL; 442 BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL;
444 BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies. 443 BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies.
@@ -460,11 +459,12 @@ extern "C" HRESULT CorePlan(
460 459
461 // Always reset the plan. 460 // Always reset the plan.
462 pEngineState->fPlanned = FALSE; 461 pEngineState->fPlanned = FALSE;
463 PlanReset(&pEngineState->plan, &pEngineState->packages); 462 PlanReset(&pEngineState->plan, &pEngineState->containers, &pEngineState->packages, &pEngineState->layoutPayloads);
464 463
465 // Remember the overall action state in the plan since it shapes the changes 464 // Remember the overall action state in the plan since it shapes the changes
466 // we make everywhere. 465 // we make everywhere.
467 pEngineState->plan.action = action; 466 pEngineState->plan.action = action;
467 pEngineState->plan.pPayloads = &pEngineState->payloads;
468 pEngineState->plan.wzBundleId = pEngineState->registration.sczId; 468 pEngineState->plan.wzBundleId = pEngineState->registration.sczId;
469 pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId; 469 pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId;
470 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback; 470 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback;
@@ -484,11 +484,11 @@ extern "C" HRESULT CorePlan(
484 Assert(!pEngineState->plan.fPerMachine); 484 Assert(!pEngineState->plan.fPerMachine);
485 485
486 // Plan the bundle's layout. 486 // Plan the bundle's layout.
487 hr = PlanLayoutBundle(&pEngineState->plan, pEngineState->registration.sczExecutableName, pEngineState->section.qwBundleSize, &pEngineState->variables, &pEngineState->payloads, &sczLayoutDirectory); 487 hr = PlanLayoutBundle(&pEngineState->plan, pEngineState->registration.sczExecutableName, pEngineState->section.qwBundleSize, &pEngineState->variables, &pEngineState->layoutPayloads);
488 ExitOnFailure(hr, "Failed to plan the layout of the bundle."); 488 ExitOnFailure(hr, "Failed to plan the layout of the bundle.");
489 489
490 // Plan the packages' layout. 490 // Plan the packages' layout.
491 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, sczLayoutDirectory); 491 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
492 ExitOnFailure(hr, "Failed to plan packages."); 492 ExitOnFailure(hr, "Failed to plan packages.");
493 } 493 }
494 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) 494 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action)
@@ -532,7 +532,7 @@ extern "C" HRESULT CorePlan(
532 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); 532 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
533 ExitOnFailure(hr, "Failed to plan related bundles."); 533 ExitOnFailure(hr, "Failed to plan related bundles.");
534 534
535 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL); 535 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
536 ExitOnFailure(hr, "Failed to plan packages."); 536 ExitOnFailure(hr, "Failed to plan packages.");
537 537
538 // Schedule the update of related bundles last. 538 // Schedule the update of related bundles last.
@@ -562,7 +562,6 @@ LExit:
562 } 562 }
563 563
564 LogId(REPORT_STANDARD, MSG_PLAN_COMPLETE, hr); 564 LogId(REPORT_STANDARD, MSG_PLAN_COMPLETE, hr);
565 ReleaseStr(sczLayoutDirectory);
566 565
567 return hr; 566 return hr;
568} 567}
@@ -1679,23 +1678,22 @@ static HRESULT DetectPackagePayloadsCached(
1679 // If the cached directory exists, we have something. 1678 // If the cached directory exists, we have something.
1680 if (DirExists(sczCachePath, NULL)) 1679 if (DirExists(sczCachePath, NULL))
1681 { 1680 {
1682 // Check all payloads to see if they exist. 1681 // Check all payloads to see if any exist.
1683 for (DWORD i = 0; i < pPackage->cPayloads; ++i) 1682 for (DWORD i = 0; i < pPackage->payloads.cPayloads; ++i)
1684 { 1683 {
1685 BURN_PACKAGE_PAYLOAD* pPackagePayload = pPackage->rgPayloads + i; 1684 BURN_PAYLOAD* pPayload = pPackage->payloads.rgpPayloads[i];
1686 1685
1687 hr = PathConcat(sczCachePath, pPackagePayload->pPayload->sczFilePath, &sczPayloadCachePath); 1686 hr = PathConcat(sczCachePath, pPayload->sczFilePath, &sczPayloadCachePath);
1688 ExitOnFailure(hr, "Failed to concat payload cache path."); 1687 ExitOnFailure(hr, "Failed to concat payload cache path.");
1689 1688
1690 if (FileExistsEx(sczPayloadCachePath, NULL)) 1689 if (FileExistsEx(sczPayloadCachePath, NULL))
1691 { 1690 {
1692 // TODO: We shouldn't track whether the payload was cached since all we did was check whether the file exists.
1693 pPackagePayload->fCached = TRUE;
1694 fCached = TRUE; 1691 fCached = TRUE;
1692 break;
1695 } 1693 }
1696 else 1694 else
1697 { 1695 {
1698 LogId(REPORT_STANDARD, MSG_DETECT_PACKAGE_NOT_FULLY_CACHED, pPackage->sczId, pPackagePayload->pPayload->sczKey); 1696 LogId(REPORT_STANDARD, MSG_DETECT_PACKAGE_NOT_FULLY_CACHED, pPackage->sczId, pPayload->sczKey);
1699 } 1697 }
1700 } 1698 }
1701 } 1699 }
diff --git a/src/engine/core.h b/src/engine/core.h
index b4e0e0d3..e96440bb 100644
--- a/src/engine/core.h
+++ b/src/engine/core.h
@@ -112,6 +112,8 @@ typedef struct _BURN_ENGINE_STATE
112 112
113 BURN_LOGGING log; 113 BURN_LOGGING log;
114 114
115 BURN_PAYLOAD_GROUP layoutPayloads;
116
115 BURN_PLAN plan; 117 BURN_PLAN plan;
116 118
117 BURN_MODE mode; 119 BURN_MODE mode;
diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp
index 844816ba..dc35e747 100644
--- a/src/engine/detect.cpp
+++ b/src/engine/detect.cpp
@@ -68,11 +68,6 @@ extern "C" void DetectReset(
68 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 68 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
69 69
70 pPackage->fCached = FALSE; 70 pPackage->fCached = FALSE;
71 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload)
72 {
73 BURN_PACKAGE_PAYLOAD* pPayload = pPackage->rgPayloads + iPayload;
74 pPayload->fCached = FALSE;
75 }
76 71
77 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 72 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
78 { 73 {
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index 71c27cad..c8b46806 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -552,7 +552,7 @@ MessageId=314
552Severity=Error 552Severity=Error
553SymbolicName=MSG_FAILED_CACHE_PAYLOAD 553SymbolicName=MSG_FAILED_CACHE_PAYLOAD
554Language=English 554Language=English
555Failed to cache payload: %2!ls! from working path: %3!ls!, error: %1!ls!. 555Failed to cache payload: %2!ls! from working path: %4!ls!, error: %1!ls!.
556. 556.
557 557
558MessageId=315 558MessageId=315
@@ -574,7 +574,7 @@ MessageId=317
574Severity=Error 574Severity=Error
575SymbolicName=MSG_FAILED_LAYOUT_PAYLOAD 575SymbolicName=MSG_FAILED_LAYOUT_PAYLOAD
576Language=English 576Language=English
577Failed to layout payload: %2!ls! to layout directory: %3!ls!, error: %1!ls!. 577Failed to layout payload: %2!ls! from working path: %4!ls! to layout directory: %3!ls!, error: %1!ls!.
578. 578.
579 579
580MessageId=318 580MessageId=318
diff --git a/src/engine/exeengine.cpp b/src/engine/exeengine.cpp
index 46905fc3..9b1b6973 100644
--- a/src/engine/exeengine.cpp
+++ b/src/engine/exeengine.cpp
@@ -372,31 +372,33 @@ extern "C" HRESULT ExeEngineExecutePackage(
372 PROCESS_INFORMATION pi = { }; 372 PROCESS_INFORMATION pi = { };
373 DWORD dwExitCode = 0; 373 DWORD dwExitCode = 0;
374 GENERIC_EXECUTE_MESSAGE message = { }; 374 GENERIC_EXECUTE_MESSAGE message = { };
375 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage;
376 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0];
375 377
376 // get cached executable path 378 // get cached executable path
377 hr = CacheGetCompletedPath(pExecuteAction->exePackage.pPackage->fPerMachine, pExecuteAction->exePackage.pPackage->sczCacheId, &sczCachedDirectory); 379 hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
378 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pExecuteAction->exePackage.pPackage->sczId); 380 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
379 381
380 // Best effort to set the execute package cache folder and action variables. 382 // Best effort to set the execute package cache folder and action variables.
381 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 383 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
382 VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, pExecuteAction->exePackage.action, TRUE); 384 VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, pExecuteAction->exePackage.action, TRUE);
383 385
384 hr = PathConcat(sczCachedDirectory, pExecuteAction->exePackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczExecutablePath); 386 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
385 ExitOnFailure(hr, "Failed to build executable path."); 387 ExitOnFailure(hr, "Failed to build executable path.");
386 388
387 // pick arguments 389 // pick arguments
388 switch (pExecuteAction->exePackage.action) 390 switch (pExecuteAction->exePackage.action)
389 { 391 {
390 case BOOTSTRAPPER_ACTION_STATE_INSTALL: 392 case BOOTSTRAPPER_ACTION_STATE_INSTALL:
391 wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczInstallArguments; 393 wzArguments = pPackage->Exe.sczInstallArguments;
392 break; 394 break;
393 395
394 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: 396 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
395 wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczUninstallArguments; 397 wzArguments = pPackage->Exe.sczUninstallArguments;
396 break; 398 break;
397 399
398 case BOOTSTRAPPER_ACTION_STATE_REPAIR: 400 case BOOTSTRAPPER_ACTION_STATE_REPAIR:
399 wzArguments = pExecuteAction->exePackage.pPackage->Exe.sczRepairArguments; 401 wzArguments = pPackage->Exe.sczRepairArguments;
400 break; 402 break;
401 403
402 default: 404 default:
@@ -408,9 +410,9 @@ extern "C" HRESULT ExeEngineExecutePackage(
408 hr = StrAllocString(&sczArguments, wzArguments && *wzArguments ? wzArguments : L"", 0); 410 hr = StrAllocString(&sczArguments, wzArguments && *wzArguments ? wzArguments : L"", 0);
409 ExitOnFailure(hr, "Failed to copy package arguments."); 411 ExitOnFailure(hr, "Failed to copy package arguments.");
410 412
411 for (DWORD i = 0; i < pExecuteAction->exePackage.pPackage->Exe.cCommandLineArguments; ++i) 413 for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i)
412 { 414 {
413 BURN_EXE_COMMAND_LINE_ARGUMENT* commandLineArgument = &pExecuteAction->exePackage.pPackage->Exe.rgCommandLineArguments[i]; 415 BURN_EXE_COMMAND_LINE_ARGUMENT* commandLineArgument = &pPackage->Exe.rgCommandLineArguments[i];
414 BOOL fCondition = FALSE; 416 BOOL fCondition = FALSE;
415 417
416 hr = ConditionEvaluate(pVariables, commandLineArgument->sczCondition, &fCondition); 418 hr = ConditionEvaluate(pVariables, commandLineArgument->sczCondition, &fCondition);
@@ -468,10 +470,10 @@ extern "C" HRESULT ExeEngineExecutePackage(
468 } 470 }
469 ExitOnFailure(hr, "Failed to create obfuscated executable command."); 471 ExitOnFailure(hr, "Failed to create obfuscated executable command.");
470 472
471 if (pExecuteAction->exePackage.pPackage->Exe.fSupportsAncestors) 473 if (pPackage->Exe.fSupportsAncestors)
472 { 474 {
473 // Add the list of dependencies to ignore, if any, to the burn command line. 475 // Add the list of dependencies to ignore, if any, to the burn command line.
474 if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol) 476 if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
475 { 477 {
476 hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); 478 hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
477 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); 479 ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
@@ -491,21 +493,21 @@ extern "C" HRESULT ExeEngineExecutePackage(
491 } 493 }
492 } 494 }
493 495
494 if (BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol) 496 if (BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
495 { 497 {
496 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated); 498 hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated);
497 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); 499 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
498 } 500 }
499 501
500 // Log before we add the secret pipe name and client token for embedded processes. 502 // Log before we add the secret pipe name and client token for embedded processes.
501 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->exePackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); 503 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
502 504
503 if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pExecuteAction->exePackage.pPackage->Exe.protocol) 505 if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
504 { 506 {
505 hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 507 hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
506 ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); 508 ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
507 } 509 }
508 else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pExecuteAction->exePackage.pPackage->Exe.protocol) 510 else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
509 { 511 {
510 hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 512 hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
511 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); 513 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
@@ -543,7 +545,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
543 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); 545 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
544 } 546 }
545 547
546 hr = HandleExitCode(pExecuteAction->exePackage.pPackage, dwExitCode, pRestart); 548 hr = HandleExitCode(pPackage, dwExitCode, pRestart);
547 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); 549 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
548 550
549LExit: 551LExit:
diff --git a/src/engine/manifest.cpp b/src/engine/manifest.cpp
index fa454348..b1740083 100644
--- a/src/engine/manifest.cpp
+++ b/src/engine/manifest.cpp
@@ -145,7 +145,7 @@ static HRESULT ParseFromXml(
145 ExitOnFailure(hr, "Failed to parse containers."); 145 ExitOnFailure(hr, "Failed to parse containers.");
146 146
147 // parse payloads 147 // parse payloads
148 hr = PayloadsParseFromXml(&pEngineState->payloads, &pEngineState->containers, pixeBundle); 148 hr = PayloadsParseFromXml(&pEngineState->payloads, &pEngineState->containers, &pEngineState->layoutPayloads, pixeBundle);
149 ExitOnFailure(hr, "Failed to parse payloads."); 149 ExitOnFailure(hr, "Failed to parse payloads.");
150 150
151 // parse packages 151 // parse packages
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index 35ca5c62..b081b9ca 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -1099,6 +1099,8 @@ extern "C" HRESULT MsiEngineExecutePackage(
1099 LPWSTR sczMsiPath = NULL; 1099 LPWSTR sczMsiPath = NULL;
1100 LPWSTR sczProperties = NULL; 1100 LPWSTR sczProperties = NULL;
1101 LPWSTR sczObfuscatedProperties = NULL; 1101 LPWSTR sczObfuscatedProperties = NULL;
1102 BURN_PACKAGE* pPackage = pExecuteAction->msiPackage.pPackage;
1103 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0];
1102 1104
1103 // During rollback, if the package is already in the rollback state we expect don't 1105 // During rollback, if the package is already in the rollback state we expect don't
1104 // touch it again. 1106 // touch it again.
@@ -1106,10 +1108,10 @@ extern "C" HRESULT MsiEngineExecutePackage(
1106 { 1108 {
1107 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->msiPackage.action) 1109 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->msiPackage.action)
1108 { 1110 {
1109 hr = WiuGetProductInfoEx(pExecuteAction->msiPackage.pPackage->Msi.sczProductCode, NULL, pExecuteAction->msiPackage.pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion); 1111 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion);
1110 if (FAILED(hr)) // package not present. 1112 if (FAILED(hr)) // package not present.
1111 { 1113 {
1112 LogId(REPORT_STANDARD, MSG_ROLLBACK_PACKAGE_SKIPPED, pExecuteAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), LoggingPackageStateToString(BOOTSTRAPPER_PACKAGE_STATE_ABSENT)); 1114 LogId(REPORT_STANDARD, MSG_ROLLBACK_PACKAGE_SKIPPED, pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), LoggingPackageStateToString(BOOTSTRAPPER_PACKAGE_STATE_ABSENT));
1113 1115
1114 hr = S_OK; 1116 hr = S_OK;
1115 ExitFunction(); 1117 ExitFunction();
@@ -1117,10 +1119,10 @@ extern "C" HRESULT MsiEngineExecutePackage(
1117 } 1119 }
1118 else if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->msiPackage.action) 1120 else if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->msiPackage.action)
1119 { 1121 {
1120 hr = WiuGetProductInfoEx(pExecuteAction->msiPackage.pPackage->Msi.sczProductCode, NULL, pExecuteAction->msiPackage.pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion); 1122 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion);
1121 if (SUCCEEDED(hr)) // package present. 1123 if (SUCCEEDED(hr)) // package present.
1122 { 1124 {
1123 LogId(REPORT_STANDARD, MSG_ROLLBACK_PACKAGE_SKIPPED, pExecuteAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), LoggingPackageStateToString(BOOTSTRAPPER_PACKAGE_STATE_PRESENT)); 1125 LogId(REPORT_STANDARD, MSG_ROLLBACK_PACKAGE_SKIPPED, pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), LoggingPackageStateToString(BOOTSTRAPPER_PACKAGE_STATE_PRESENT));
1124 1126
1125 hr = S_OK; 1127 hr = S_OK;
1126 ExitFunction(); 1128 ExitFunction();
@@ -1141,13 +1143,13 @@ extern "C" HRESULT MsiEngineExecutePackage(
1141 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL != pExecuteAction->msiPackage.action) 1143 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL != pExecuteAction->msiPackage.action)
1142 { 1144 {
1143 // get cached MSI path 1145 // get cached MSI path
1144 hr = CacheGetCompletedPath(pExecuteAction->msiPackage.pPackage->fPerMachine, pExecuteAction->msiPackage.pPackage->sczCacheId, &sczCachedDirectory); 1146 hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
1145 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pExecuteAction->msiPackage.pPackage->sczId); 1147 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
1146 1148
1147 // Best effort to set the execute package cache folder variable. 1149 // Best effort to set the execute package cache folder variable.
1148 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 1150 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
1149 1151
1150 hr = PathConcat(sczCachedDirectory, pExecuteAction->msiPackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczMsiPath); 1152 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczMsiPath);
1151 ExitOnFailure(hr, "Failed to build MSI path."); 1153 ExitOnFailure(hr, "Failed to build MSI path.");
1152 } 1154 }
1153 1155
@@ -1169,28 +1171,28 @@ extern "C" HRESULT MsiEngineExecutePackage(
1169 if (pExecuteAction->msiPackage.sczLogPath && *pExecuteAction->msiPackage.sczLogPath) 1171 if (pExecuteAction->msiPackage.sczLogPath && *pExecuteAction->msiPackage.sczLogPath)
1170 { 1172 {
1171 hr = WiuEnableLog(dwLogMode, pExecuteAction->msiPackage.sczLogPath, 0); 1173 hr = WiuEnableLog(dwLogMode, pExecuteAction->msiPackage.sczLogPath, 0);
1172 ExitOnFailure(hr, "Failed to enable logging for package: %ls to: %ls", pExecuteAction->msiPackage.pPackage->sczId, pExecuteAction->msiPackage.sczLogPath); 1174 ExitOnFailure(hr, "Failed to enable logging for package: %ls to: %ls", pPackage->sczId, pExecuteAction->msiPackage.sczLogPath);
1173 } 1175 }
1174 1176
1175 // set up properties 1177 // set up properties
1176 hr = MsiEngineConcatProperties(pExecuteAction->msiPackage.pPackage->Msi.rgProperties, pExecuteAction->msiPackage.pPackage->Msi.cProperties, pVariables, fRollback, &sczProperties, FALSE); 1178 hr = MsiEngineConcatProperties(pPackage->Msi.rgProperties, pPackage->Msi.cProperties, pVariables, fRollback, &sczProperties, FALSE);
1177 ExitOnFailure(hr, "Failed to add properties to argument string."); 1179 ExitOnFailure(hr, "Failed to add properties to argument string.");
1178 1180
1179 hr = MsiEngineConcatProperties(pExecuteAction->msiPackage.pPackage->Msi.rgProperties, pExecuteAction->msiPackage.pPackage->Msi.cProperties, pVariables, fRollback, &sczObfuscatedProperties, TRUE); 1181 hr = MsiEngineConcatProperties(pPackage->Msi.rgProperties, pPackage->Msi.cProperties, pVariables, fRollback, &sczObfuscatedProperties, TRUE);
1180 ExitOnFailure(hr, "Failed to add obfuscated properties to argument string."); 1182 ExitOnFailure(hr, "Failed to add obfuscated properties to argument string.");
1181 1183
1182 // add feature action properties 1184 // add feature action properties
1183 hr = ConcatFeatureActionProperties(pExecuteAction->msiPackage.pPackage, pExecuteAction->msiPackage.rgFeatures, &sczProperties); 1185 hr = ConcatFeatureActionProperties(pPackage, pExecuteAction->msiPackage.rgFeatures, &sczProperties);
1184 ExitOnFailure(hr, "Failed to add feature action properties to argument string."); 1186 ExitOnFailure(hr, "Failed to add feature action properties to argument string.");
1185 1187
1186 hr = ConcatFeatureActionProperties(pExecuteAction->msiPackage.pPackage, pExecuteAction->msiPackage.rgFeatures, &sczObfuscatedProperties); 1188 hr = ConcatFeatureActionProperties(pPackage, pExecuteAction->msiPackage.rgFeatures, &sczObfuscatedProperties);
1187 ExitOnFailure(hr, "Failed to add feature action properties to obfuscated argument string."); 1189 ExitOnFailure(hr, "Failed to add feature action properties to obfuscated argument string.");
1188 1190
1189 // add slipstream patch properties 1191 // add slipstream patch properties
1190 hr = ConcatPatchProperty(pExecuteAction->msiPackage.pPackage, fRollback, &sczProperties); 1192 hr = ConcatPatchProperty(pPackage, fRollback, &sczProperties);
1191 ExitOnFailure(hr, "Failed to add patch properties to argument string."); 1193 ExitOnFailure(hr, "Failed to add patch properties to argument string.");
1192 1194
1193 hr = ConcatPatchProperty(pExecuteAction->msiPackage.pPackage, fRollback, &sczObfuscatedProperties); 1195 hr = ConcatPatchProperty(pPackage, fRollback, &sczObfuscatedProperties);
1194 ExitOnFailure(hr, "Failed to add patch properties to obfuscated argument string."); 1196 ExitOnFailure(hr, "Failed to add patch properties to obfuscated argument string.");
1195 1197
1196 hr = MsiEngineConcatActionProperty(pExecuteAction->msiPackage.actionMsiProperty, &sczProperties); 1198 hr = MsiEngineConcatActionProperty(pExecuteAction->msiPackage.actionMsiProperty, &sczProperties);
@@ -1199,7 +1201,7 @@ extern "C" HRESULT MsiEngineExecutePackage(
1199 hr = MsiEngineConcatActionProperty(pExecuteAction->msiPackage.actionMsiProperty, &sczObfuscatedProperties); 1201 hr = MsiEngineConcatActionProperty(pExecuteAction->msiPackage.actionMsiProperty, &sczObfuscatedProperties);
1200 ExitOnFailure(hr, "Failed to add action property to obfuscated argument string."); 1202 ExitOnFailure(hr, "Failed to add action property to obfuscated argument string.");
1201 1203
1202 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), sczMsiPath, sczObfuscatedProperties ? sczObfuscatedProperties : L""); 1204 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), sczMsiPath, sczObfuscatedProperties ? sczObfuscatedProperties : L"");
1203 1205
1204 // 1206 //
1205 // Do the actual action. 1207 // Do the actual action.
@@ -1213,13 +1215,13 @@ extern "C" HRESULT MsiEngineExecutePackage(
1213 hr = WiuInstallProduct(sczMsiPath, sczProperties, &restart); 1215 hr = WiuInstallProduct(sczMsiPath, sczProperties, &restart);
1214 ExitOnFailure(hr, "Failed to install MSI package."); 1216 ExitOnFailure(hr, "Failed to install MSI package.");
1215 1217
1216 RegisterSourceDirectory(pExecuteAction->msiPackage.pPackage, sczMsiPath); 1218 RegisterSourceDirectory(pPackage, sczMsiPath);
1217 break; 1219 break;
1218 1220
1219 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE: 1221 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE:
1220 // If feature selection is not enabled, then reinstall the existing features to ensure they get 1222 // If feature selection is not enabled, then reinstall the existing features to ensure they get
1221 // updated. 1223 // updated.
1222 if (0 == pExecuteAction->msiPackage.pPackage->Msi.cFeatures) 1224 if (0 == pPackage->Msi.cFeatures)
1223 { 1225 {
1224 hr = StrAllocConcatSecure(&sczProperties, L" REINSTALL=ALL", 0); 1226 hr = StrAllocConcatSecure(&sczProperties, L" REINSTALL=ALL", 0);
1225 ExitOnFailure(hr, "Failed to add reinstall all property on minor upgrade."); 1227 ExitOnFailure(hr, "Failed to add reinstall all property on minor upgrade.");
@@ -1231,7 +1233,7 @@ extern "C" HRESULT MsiEngineExecutePackage(
1231 hr = WiuInstallProduct(sczMsiPath, sczProperties, &restart); 1233 hr = WiuInstallProduct(sczMsiPath, sczProperties, &restart);
1232 ExitOnFailure(hr, "Failed to perform minor upgrade of MSI package."); 1234 ExitOnFailure(hr, "Failed to perform minor upgrade of MSI package.");
1233 1235
1234 RegisterSourceDirectory(pExecuteAction->msiPackage.pPackage, sczMsiPath); 1236 RegisterSourceDirectory(pPackage, sczMsiPath);
1235 break; 1237 break;
1236 1238
1237 case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough; 1239 case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough;
@@ -1239,7 +1241,7 @@ extern "C" HRESULT MsiEngineExecutePackage(
1239 case BOOTSTRAPPER_ACTION_STATE_REPAIR: 1241 case BOOTSTRAPPER_ACTION_STATE_REPAIR:
1240 { 1242 {
1241 LPCWSTR wzReinstallAll = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action || 1243 LPCWSTR wzReinstallAll = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action ||
1242 pExecuteAction->msiPackage.pPackage->Msi.cFeatures) ? L"" : L" REINSTALL=ALL"; 1244 pPackage->Msi.cFeatures) ? L"" : L" REINSTALL=ALL";
1243 LPCWSTR wzReinstallMode = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action || BOOTSTRAPPER_ACTION_STATE_MEND == pExecuteAction->msiPackage.action) ? L"o" : L"e"; 1245 LPCWSTR wzReinstallMode = (BOOTSTRAPPER_ACTION_STATE_MODIFY == pExecuteAction->msiPackage.action || BOOTSTRAPPER_ACTION_STATE_MEND == pExecuteAction->msiPackage.action) ? L"o" : L"e";
1244 1246
1245 hr = StrAllocFormattedSecure(&sczProperties, L"%ls%ls REINSTALLMODE=\"cmus%ls\" REBOOT=ReallySuppress", sczProperties ? sczProperties : L"", wzReinstallAll, wzReinstallMode); 1247 hr = StrAllocFormattedSecure(&sczProperties, L"%ls%ls REINSTALLMODE=\"cmus%ls\" REBOOT=ReallySuppress", sczProperties ? sczProperties : L"", wzReinstallAll, wzReinstallMode);
@@ -1262,10 +1264,10 @@ extern "C" HRESULT MsiEngineExecutePackage(
1262 hr = StrAllocFormattedSecure(&sczProperties, L"%ls %ls=ALL", sczProperties, DEPENDENCY_IGNOREDEPENDENCIES); 1264 hr = StrAllocFormattedSecure(&sczProperties, L"%ls %ls=ALL", sczProperties, DEPENDENCY_IGNOREDEPENDENCIES);
1263 ExitOnFailure(hr, "Failed to add the list of dependencies to ignore to the properties."); 1265 ExitOnFailure(hr, "Failed to add the list of dependencies to ignore to the properties.");
1264 1266
1265 hr = WiuConfigureProductEx(pExecuteAction->msiPackage.pPackage->Msi.sczProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, sczProperties, &restart); 1267 hr = WiuConfigureProductEx(pPackage->Msi.sczProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, sczProperties, &restart);
1266 if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr) 1268 if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr)
1267 { 1269 {
1268 LogId(REPORT_STANDARD, MSG_ATTEMPTED_UNINSTALL_ABSENT_PACKAGE, pExecuteAction->msiPackage.pPackage->sczId); 1270 LogId(REPORT_STANDARD, MSG_ATTEMPTED_UNINSTALL_ABSENT_PACKAGE, pPackage->sczId);
1269 hr = S_OK; 1271 hr = S_OK;
1270 } 1272 }
1271 ExitOnFailure(hr, "Failed to uninstall MSI package."); 1273 ExitOnFailure(hr, "Failed to uninstall MSI package.");
@@ -1979,6 +1981,7 @@ static HRESULT ConcatPatchProperty(
1979 { 1981 {
1980 BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + i; 1982 BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pPackage->Msi.rgSlipstreamMsps + i;
1981 BURN_PACKAGE* pMspPackage = pSlipstreamMsp->pMspPackage; 1983 BURN_PACKAGE* pMspPackage = pSlipstreamMsp->pMspPackage;
1984 BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgpPayloads[0];
1982 BOOTSTRAPPER_ACTION_STATE patchExecuteAction = fRollback ? pSlipstreamMsp->rollback : pSlipstreamMsp->execute; 1985 BOOTSTRAPPER_ACTION_STATE patchExecuteAction = fRollback ? pSlipstreamMsp->rollback : pSlipstreamMsp->execute;
1983 1986
1984 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < patchExecuteAction) 1987 if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < patchExecuteAction)
@@ -1986,7 +1989,7 @@ static HRESULT ConcatPatchProperty(
1986 hr = CacheGetCompletedPath(pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory); 1989 hr = CacheGetCompletedPath(pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory);
1987 ExitOnFailure(hr, "Failed to get cached path for MSP package: %ls", pMspPackage->sczId); 1990 ExitOnFailure(hr, "Failed to get cached path for MSP package: %ls", pMspPackage->sczId);
1988 1991
1989 hr = PathConcat(sczCachedDirectory, pMspPackage->rgPayloads[0].pPayload->sczFilePath, &sczMspPath); 1992 hr = PathConcat(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath);
1990 ExitOnFailure(hr, "Failed to build MSP path."); 1993 ExitOnFailure(hr, "Failed to build MSP path.");
1991 1994
1992 if (!sczPatches) 1995 if (!sczPatches)
diff --git a/src/engine/mspengine.cpp b/src/engine/mspengine.cpp
index 5ccb6718..6addfa90 100644
--- a/src/engine/mspengine.cpp
+++ b/src/engine/mspengine.cpp
@@ -581,6 +581,7 @@ extern "C" HRESULT MspEngineExecutePackage(
581 { 581 {
582 LPCWSTR wzAppend = NULL; 582 LPCWSTR wzAppend = NULL;
583 BURN_PACKAGE* pMspPackage = pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage; 583 BURN_PACKAGE* pMspPackage = pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage;
584 BURN_PAYLOAD* pMspPackagePayload = pMspPackage->payloads.rgpPayloads[0];
584 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Invalid package type added to ordered patches."); 585 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Invalid package type added to ordered patches.");
585 586
586 if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->mspTarget.action) 587 if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->mspTarget.action)
@@ -592,7 +593,7 @@ extern "C" HRESULT MspEngineExecutePackage(
592 // Best effort to set the execute package cache folder variable. 593 // Best effort to set the execute package cache folder variable.
593 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 594 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
594 595
595 hr = PathConcat(sczCachedDirectory, pMspPackage->rgPayloads[0].pPayload->sczFilePath, &sczMspPath); 596 hr = PathConcat(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath);
596 ExitOnFailure(hr, "Failed to build MSP path."); 597 ExitOnFailure(hr, "Failed to build MSP path.");
597 598
598 wzAppend = sczMspPath; 599 wzAppend = sczMspPath;
diff --git a/src/engine/msuengine.cpp b/src/engine/msuengine.cpp
index 59f9a656..02ceb0c6 100644
--- a/src/engine/msuengine.cpp
+++ b/src/engine/msuengine.cpp
@@ -264,6 +264,8 @@ extern "C" HRESULT MsuEngineExecutePackage(
264 GENERIC_EXECUTE_MESSAGE message = { }; 264 GENERIC_EXECUTE_MESSAGE message = { };
265 DWORD dwExitCode = 0; 265 DWORD dwExitCode = 0;
266 BOOL fUseSysNativePath = FALSE; 266 BOOL fUseSysNativePath = FALSE;
267 BURN_PACKAGE* pPackage = pExecuteAction->msuPackage.pPackage;
268 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgpPayloads[0];
267 269
268#if !defined(_WIN64) 270#if !defined(_WIN64)
269 hr = ProcWow64(::GetCurrentProcess(), &fUseSysNativePath); 271 hr = ProcWow64(::GetCurrentProcess(), &fUseSysNativePath);
@@ -295,13 +297,13 @@ extern "C" HRESULT MsuEngineExecutePackage(
295 { 297 {
296 case BOOTSTRAPPER_ACTION_STATE_INSTALL: 298 case BOOTSTRAPPER_ACTION_STATE_INSTALL:
297 // get cached MSU path 299 // get cached MSU path
298 hr = CacheGetCompletedPath(TRUE, pExecuteAction->msuPackage.pPackage->sczCacheId, &sczCachedDirectory); 300 hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCachedDirectory);
299 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pExecuteAction->msuPackage.pPackage->sczId); 301 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
300 302
301 // Best effort to set the execute package cache folder variable. 303 // Best effort to set the execute package cache folder variable.
302 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 304 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
303 305
304 hr = PathConcat(sczCachedDirectory, pExecuteAction->msuPackage.pPackage->rgPayloads[0].pPayload->sczFilePath, &sczMsuPath); 306 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczMsuPath);
305 ExitOnFailure(hr, "Failed to build MSU path."); 307 ExitOnFailure(hr, "Failed to build MSU path.");
306 308
307 // format command 309 // format command
@@ -311,7 +313,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
311 313
312 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: 314 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
313 // format command 315 // format command
314 hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pExecuteAction->msuPackage.pPackage->Msu.sczKB); 316 hr = StrAllocFormatted(&sczCommand, L"\"%ls\" /uninstall /kb:%ls /quiet /norestart", sczWusaPath, pPackage->Msu.sczKB);
315 ExitOnFailure(hr, "Failed to format MSU uninstall command."); 317 ExitOnFailure(hr, "Failed to format MSU uninstall command.");
316 break; 318 break;
317 319
@@ -329,7 +331,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
329 ExitOnFailure(hr, "Failed to append log path to MSU command-line."); 331 ExitOnFailure(hr, "Failed to append log path to MSU command-line.");
330 } 332 }
331 333
332 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pExecuteAction->msuPackage.pPackage->sczId, LoggingActionStateToString(pExecuteAction->msuPackage.action), sczMsuPath ? sczMsuPath : pExecuteAction->msuPackage.pPackage->Msu.sczKB, sczCommand); 334 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->msuPackage.action), sczMsuPath ? sczMsuPath : pPackage->Msu.sczKB, sczCommand);
333 335
334 hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled); 336 hr = EnsureWUServiceEnabled(fStopWusaService, &schWu, &fWuWasDisabled);
335 ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package."); 337 ExitOnFailure(hr, "Failed to ensure WU service was enabled to install MSU package.");
diff --git a/src/engine/package.cpp b/src/engine/package.cpp
index 6ff59fe4..ecf1488b 100644
--- a/src/engine/package.cpp
+++ b/src/engine/package.cpp
@@ -349,7 +349,7 @@ extern "C" void PackageUninitialize(
349 MemFree(pPackage->rgDependencyProviders); 349 MemFree(pPackage->rgDependencyProviders);
350 } 350 }
351 351
352 ReleaseMem(pPackage->rgPayloads); 352 ReleaseMem(pPackage->payloads.rgpPayloads);
353 353
354 switch (pPackage->type) 354 switch (pPackage->type)
355 { 355 {
@@ -567,16 +567,14 @@ static HRESULT ParsePayloadRefsFromXml(
567 } 567 }
568 568
569 // allocate memory for payload pointers 569 // allocate memory for payload pointers
570 pPackage->rgPayloads = (BURN_PACKAGE_PAYLOAD*)MemAlloc(sizeof(BURN_PACKAGE_PAYLOAD) * cNodes, TRUE); 570 pPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*) * cNodes, TRUE);
571 ExitOnNull(pPackage->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for package payloads."); 571 ExitOnNull(pPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for package payloads.");
572 572
573 pPackage->cPayloads = cNodes; 573 pPackage->payloads.cPayloads = cNodes;
574 574
575 // parse package elements 575 // parse package elements
576 for (DWORD i = 0; i < cNodes; ++i) 576 for (DWORD i = 0; i < cNodes; ++i)
577 { 577 {
578 BURN_PACKAGE_PAYLOAD* pPackagePayload = &pPackage->rgPayloads[i];
579
580 hr = XmlNextElement(pixnNodes, &pixnNode, NULL); 578 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
581 ExitOnFailure(hr, "Failed to get next node."); 579 ExitOnFailure(hr, "Failed to get next node.");
582 580
@@ -585,9 +583,11 @@ static HRESULT ParsePayloadRefsFromXml(
585 ExitOnFailure(hr, "Failed to get Id attribute."); 583 ExitOnFailure(hr, "Failed to get Id attribute.");
586 584
587 // find payload 585 // find payload
588 hr = PayloadFindById(pPayloads, sczId, &pPackagePayload->pPayload); 586 hr = PayloadFindById(pPayloads, sczId, &pPackage->payloads.rgpPayloads[i]);
589 ExitOnFailure(hr, "Failed to find payload."); 587 ExitOnFailure(hr, "Failed to find payload.");
590 588
589 pPackage->payloads.qwTotalSize += pPackage->payloads.rgpPayloads[i]->qwFileSize;
590
591 // prepare next iteration 591 // prepare next iteration
592 ReleaseNullObject(pixnNode); 592 ReleaseNullObject(pixnNode);
593 } 593 }
diff --git a/src/engine/package.h b/src/engine/package.h
index 262262ab..34a3af26 100644
--- a/src/engine/package.h
+++ b/src/engine/package.h
@@ -184,12 +184,6 @@ typedef struct _BURN_SLIPSTREAM_MSP
184 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. 184 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
185} BURN_SLIPSTREAM_MSP; 185} BURN_SLIPSTREAM_MSP;
186 186
187typedef struct _BURN_PACKAGE_PAYLOAD
188{
189 BURN_PAYLOAD* pPayload;
190 BOOL fCached;
191} BURN_PACKAGE_PAYLOAD;
192
193typedef struct _BURN_DEPENDENCY_PROVIDER 187typedef struct _BURN_DEPENDENCY_PROVIDER
194{ 188{
195 LPWSTR sczKey; 189 LPWSTR sczKey;
@@ -260,8 +254,7 @@ typedef struct _BURN_PACKAGE
260 BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState;// only valid after Plan. 254 BURN_PACKAGE_REGISTRATION_STATE expectedInstallRegistrationState;// only valid after Plan.
261 BURN_PACKAGE_REGISTRATION_STATE transactionRegistrationState; // only valid during Apply inside an MSI transaction. 255 BURN_PACKAGE_REGISTRATION_STATE transactionRegistrationState; // only valid during Apply inside an MSI transaction.
262 256
263 BURN_PACKAGE_PAYLOAD* rgPayloads; 257 BURN_PAYLOAD_GROUP payloads;
264 DWORD cPayloads;
265 258
266 BURN_DEPENDENCY_PROVIDER* rgDependencyProviders; 259 BURN_DEPENDENCY_PROVIDER* rgDependencyProviders;
267 DWORD cDependencyProviders; 260 DWORD cDependencyProviders;
diff --git a/src/engine/payload.cpp b/src/engine/payload.cpp
index 67eebe10..2be39b23 100644
--- a/src/engine/payload.cpp
+++ b/src/engine/payload.cpp
@@ -18,6 +18,7 @@ static HRESULT FindEmbeddedBySourcePath(
18extern "C" HRESULT PayloadsParseFromXml( 18extern "C" HRESULT PayloadsParseFromXml(
19 __in BURN_PAYLOADS* pPayloads, 19 __in BURN_PAYLOADS* pPayloads,
20 __in_opt BURN_CONTAINERS* pContainers, 20 __in_opt BURN_CONTAINERS* pContainers,
21 __in_opt BURN_PAYLOAD_GROUP* pLayoutPayloads,
21 __in IXMLDOMNode* pixnBundle 22 __in IXMLDOMNode* pixnBundle
22 ) 23 )
23{ 24{
@@ -136,6 +137,17 @@ extern "C" HRESULT PayloadsParseFromXml(
136 hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash); 137 hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash);
137 ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash."); 138 ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash.");
138 139
140 if (pPayload->fLayoutOnly && pLayoutPayloads)
141 {
142 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgpPayloads), pLayoutPayloads->cPayloads + 1, sizeof(BURN_PAYLOAD*), 5);
143 ExitOnNull(pPayloads->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for layout payloads.");
144
145 pLayoutPayloads->rgpPayloads[pLayoutPayloads->cPayloads] = pPayload;
146 ++pLayoutPayloads->cPayloads;
147
148 pLayoutPayloads->qwTotalSize += pPayload->qwFileSize;
149 }
150
139 // prepare next iteration 151 // prepare next iteration
140 ReleaseNullObject(pixnNode); 152 ReleaseNullObject(pixnNode);
141 } 153 }
@@ -150,6 +162,24 @@ LExit:
150 return hr; 162 return hr;
151} 163}
152 164
165extern "C" void PayloadUninitialize(
166 __in BURN_PAYLOAD* pPayload
167 )
168{
169 if (pPayload)
170 {
171 ReleaseStr(pPayload->sczKey);
172 ReleaseStr(pPayload->sczFilePath);
173 ReleaseMem(pPayload->pbHash);
174 ReleaseStr(pPayload->sczSourcePath);
175 ReleaseStr(pPayload->sczLocalFilePath);
176 ReleaseStr(pPayload->downloadSource.sczUrl);
177 ReleaseStr(pPayload->downloadSource.sczUser);
178 ReleaseStr(pPayload->downloadSource.sczPassword);
179 ReleaseStr(pPayload->sczUnverifiedPath);
180 }
181}
182
153extern "C" void PayloadsUninitialize( 183extern "C" void PayloadsUninitialize(
154 __in BURN_PAYLOADS* pPayloads 184 __in BURN_PAYLOADS* pPayloads
155 ) 185 )
@@ -158,16 +188,7 @@ extern "C" void PayloadsUninitialize(
158 { 188 {
159 for (DWORD i = 0; i < pPayloads->cPayloads; ++i) 189 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
160 { 190 {
161 BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; 191 PayloadUninitialize(pPayloads->rgPayloads + i);
162
163 ReleaseStr(pPayload->sczKey);
164 ReleaseStr(pPayload->sczFilePath);
165 ReleaseMem(pPayload->pbHash);
166 ReleaseStr(pPayload->sczSourcePath);
167 ReleaseStr(pPayload->sczLocalFilePath);
168 ReleaseStr(pPayload->downloadSource.sczUrl);
169 ReleaseStr(pPayload->downloadSource.sczUser);
170 ReleaseStr(pPayload->downloadSource.sczPassword);
171 } 192 }
172 MemFree(pPayloads->rgPayloads); 193 MemFree(pPayloads->rgPayloads);
173 } 194 }
diff --git a/src/engine/payload.h b/src/engine/payload.h
index e8639d64..ba555766 100644
--- a/src/engine/payload.h
+++ b/src/engine/payload.h
@@ -45,6 +45,8 @@ typedef struct _BURN_PAYLOAD
45 // mutable members 45 // mutable members
46 BURN_PAYLOAD_STATE state; 46 BURN_PAYLOAD_STATE state;
47 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy 47 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy
48
49 LPWSTR sczUnverifiedPath;
48} BURN_PAYLOAD; 50} BURN_PAYLOAD;
49 51
50typedef struct _BURN_PAYLOADS 52typedef struct _BURN_PAYLOADS
@@ -53,14 +55,24 @@ typedef struct _BURN_PAYLOADS
53 DWORD cPayloads; 55 DWORD cPayloads;
54} BURN_PAYLOADS; 56} BURN_PAYLOADS;
55 57
58typedef struct _BURN_PAYLOAD_GROUP
59{
60 BURN_PAYLOAD** rgpPayloads;
61 DWORD cPayloads;
62 DWORD64 qwTotalSize;
63} BURN_PAYLOAD_GROUP;
56 64
57// functions 65// functions
58 66
59HRESULT PayloadsParseFromXml( 67HRESULT PayloadsParseFromXml(
60 __in BURN_PAYLOADS* pPayloads, 68 __in BURN_PAYLOADS* pPayloads,
61 __in_opt BURN_CONTAINERS* pContainers, 69 __in_opt BURN_CONTAINERS* pContainers,
70 __in_opt BURN_PAYLOAD_GROUP* pLayoutPayloads,
62 __in IXMLDOMNode* pixnBundle 71 __in IXMLDOMNode* pixnBundle
63 ); 72 );
73void PayloadUninitialize(
74 __in BURN_PAYLOAD* pPayload
75 );
64void PayloadsUninitialize( 76void PayloadsUninitialize(
65 __in BURN_PAYLOADS* pPayloads 77 __in BURN_PAYLOADS* pPayloads
66 ); 78 );
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index 187b1f15..ce577da5 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -15,6 +15,15 @@ static void UninitializeRegistrationAction(
15static void UninitializeCacheAction( 15static void UninitializeCacheAction(
16 __in BURN_CACHE_ACTION* pCacheAction 16 __in BURN_CACHE_ACTION* pCacheAction
17 ); 17 );
18static void ResetPlannedContainerState(
19 __in BURN_CONTAINER* pContainer
20 );
21static void ResetPlannedPayloadsState(
22 __in BURN_PAYLOADS* pPayloads
23 );
24static void ResetPlannedPayloadGroupState(
25 __in BURN_PAYLOAD_GROUP* pPayloadGroup
26 );
18static void ResetPlannedPackageState( 27static void ResetPlannedPackageState(
19 __in BURN_PACKAGE* pPackage 28 __in BURN_PACKAGE* pPackage
20 ); 29 );
@@ -30,8 +39,7 @@ static HRESULT PlanPackagesHelper(
30 __in BURN_LOGGING* pLog, 39 __in BURN_LOGGING* pLog,
31 __in BURN_VARIABLES* pVariables, 40 __in BURN_VARIABLES* pVariables,
32 __in BOOTSTRAPPER_DISPLAY display, 41 __in BOOTSTRAPPER_DISPLAY display,
33 __in BOOTSTRAPPER_RELATION_TYPE relationType, 42 __in BOOTSTRAPPER_RELATION_TYPE relationType
34 __in_z_opt LPCWSTR wzLayoutDirectory
35 ); 43 );
36static HRESULT InitializePackage( 44static HRESULT InitializePackage(
37 __in BURN_PLAN* pPlan, 45 __in BURN_PLAN* pPlan,
@@ -48,7 +56,6 @@ static HRESULT ProcessPackage(
48 __in BURN_LOGGING* pLog, 56 __in BURN_LOGGING* pLog,
49 __in BURN_VARIABLES* pVariables, 57 __in BURN_VARIABLES* pVariables,
50 __in BOOTSTRAPPER_DISPLAY display, 58 __in BOOTSTRAPPER_DISPLAY display,
51 __in_z_opt LPCWSTR wzLayoutDirectory,
52 __inout HANDLE* phSyncpointEvent, 59 __inout HANDLE* phSyncpointEvent,
53 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 60 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
54 ); 61 );
@@ -99,54 +106,9 @@ static HRESULT AppendRollbackCacheAction(
99 __in BURN_PLAN* pPlan, 106 __in BURN_PLAN* pPlan,
100 __out BURN_CACHE_ACTION** ppCacheAction 107 __out BURN_CACHE_ACTION** ppCacheAction
101 ); 108 );
102static HRESULT AppendLayoutContainerAction( 109static HRESULT ProcessPayloadGroup(
103 __in BURN_PLAN* pPlan,
104 __in_opt BURN_PACKAGE* pPackage,
105 __in DWORD iPackageStartAction,
106 __in BURN_CONTAINER* pContainer,
107 __in BOOL fContainerCached,
108 __in_z LPCWSTR wzLayoutDirectory
109 );
110static HRESULT AppendCacheOrLayoutPayloadAction(
111 __in BURN_PLAN* pPlan,
112 __in_opt BURN_PACKAGE* pPackage,
113 __in DWORD iPackageStartAction,
114 __in BURN_PAYLOAD* pPayload,
115 __in BOOL fPayloadCached,
116 __in_z_opt LPCWSTR wzLayoutDirectory
117 );
118static BOOL FindContainerCacheAction(
119 __in BURN_CACHE_ACTION_TYPE type,
120 __in BURN_PLAN* pPlan,
121 __in BURN_CONTAINER* pContainer,
122 __in DWORD iSearchStart,
123 __in DWORD iSearchEnd,
124 __out_opt BURN_CACHE_ACTION** ppCacheAction,
125 __out_opt DWORD* piCacheAction
126 );
127static HRESULT CreateContainerAcquireAndExtractAction(
128 __in BURN_PLAN* pPlan, 110 __in BURN_PLAN* pPlan,
129 __in BURN_CONTAINER* pContainer, 111 __in BURN_PAYLOAD_GROUP* pPayloadGroup
130 __in DWORD iPackageStartAction,
131 __in BOOL fPayloadCached,
132 __out BURN_CACHE_ACTION** ppContainerExtractAction,
133 __out DWORD* piContainerTryAgainAction
134 );
135static HRESULT AddAcquireContainer(
136 __in BURN_PLAN* pPlan,
137 __in BURN_CONTAINER* pContainer,
138 __out_opt BURN_CACHE_ACTION** ppCacheAction,
139 __out_opt DWORD* piCacheAction
140 );
141static HRESULT AddExtractPayload(
142 __in BURN_CACHE_ACTION* pCacheAction,
143 __in_opt BURN_PACKAGE* pPackage,
144 __in BURN_PAYLOAD* pPayload,
145 __in_z LPCWSTR wzPayloadWorkingPath
146 );
147static BURN_CACHE_ACTION* ProcessSharedPayload(
148 __in BURN_PLAN* pPlan,
149 __in BURN_PAYLOAD* pPayload
150 ); 112 );
151static void RemoveUnnecessaryActions( 113static void RemoveUnnecessaryActions(
152 __in BOOL fExecute, 114 __in BOOL fExecute,
@@ -175,24 +137,17 @@ static BOOL NeedsCache(
175 __in BURN_PACKAGE* pPackage, 137 __in BURN_PACKAGE* pPackage,
176 __in BOOL fExecute 138 __in BOOL fExecute
177 ); 139 );
178static HRESULT CreateContainerProgress(
179 __in BURN_PLAN* pPlan,
180 __in BURN_CONTAINER* pContainer,
181 __out BURN_CACHE_CONTAINER_PROGRESS** ppContainerProgress
182 );
183static HRESULT CreatePayloadProgress(
184 __in BURN_PLAN* pPlan,
185 __in BURN_PAYLOAD* pPayload,
186 __out BURN_CACHE_PAYLOAD_PROGRESS** ppPayloadProgress
187 );
188 140
189// function definitions 141// function definitions
190 142
191extern "C" void PlanReset( 143extern "C" void PlanReset(
192 __in BURN_PLAN* pPlan, 144 __in BURN_PLAN* pPlan,
193 __in BURN_PACKAGES* pPackages 145 __in BURN_CONTAINERS* pContainers,
146 __in BURN_PACKAGES* pPackages,
147 __in BURN_PAYLOAD_GROUP* pLayoutPayloads
194 ) 148 )
195{ 149{
150 ReleaseNullStr(pPlan->sczLayoutDirectory);
196 PackageUninitialize(&pPlan->forwardCompatibleBundle); 151 PackageUninitialize(&pPlan->forwardCompatibleBundle);
197 152
198 if (pPlan->rgRegistrationActions) 153 if (pPlan->rgRegistrationActions)
@@ -271,8 +226,21 @@ extern "C" void PlanReset(
271 ReleaseDict(pPlan->shPayloadProgress); 226 ReleaseDict(pPlan->shPayloadProgress);
272 } 227 }
273 228
229 if (pPlan->pPayloads)
230 {
231 ResetPlannedPayloadsState(pPlan->pPayloads);
232 }
233
274 memset(pPlan, 0, sizeof(BURN_PLAN)); 234 memset(pPlan, 0, sizeof(BURN_PLAN));
275 235
236 if (pContainers->rgContainers)
237 {
238 for (DWORD i = 0; i < pContainers->cContainers; ++i)
239 {
240 ResetPlannedContainerState(&pContainers->rgContainers[i]);
241 }
242 }
243
276 // Reset the planned actions for each package. 244 // Reset the planned actions for each package.
277 if (pPackages->rgPackages) 245 if (pPackages->rgPackages)
278 { 246 {
@@ -282,6 +250,8 @@ extern "C" void PlanReset(
282 } 250 }
283 } 251 }
284 252
253 ResetPlannedPayloadGroupState(pLayoutPayloads);
254
285 // Reset the planned state for each rollback boundary. 255 // Reset the planned state for each rollback boundary.
286 if (pPackages->rgRollbackBoundaries) 256 if (pPackages->rgRollbackBoundaries)
287 { 257 {
@@ -417,34 +387,35 @@ extern "C" HRESULT PlanLayoutBundle(
417 __in_z LPCWSTR wzExecutableName, 387 __in_z LPCWSTR wzExecutableName,
418 __in DWORD64 qwBundleSize, 388 __in DWORD64 qwBundleSize,
419 __in BURN_VARIABLES* pVariables, 389 __in BURN_VARIABLES* pVariables,
420 __in BURN_PAYLOADS* pPayloads, 390 __in BURN_PAYLOAD_GROUP* pLayoutPayloads
421 __out_z LPWSTR* psczLayoutDirectory
422 ) 391 )
423{ 392{
424 HRESULT hr = S_OK; 393 HRESULT hr = S_OK;
425 BURN_CACHE_ACTION* pCacheAction = NULL; 394 BURN_CACHE_ACTION* pCacheAction = NULL;
426 LPWSTR sczExecutablePath = NULL; 395 LPWSTR sczExecutablePath = NULL;
427 LPWSTR sczLayoutDirectory = NULL;
428 396
429 // Get the layout directory. 397 // Get the layout directory.
430 hr = VariableGetString(pVariables, BURN_BUNDLE_LAYOUT_DIRECTORY, &sczLayoutDirectory); 398 hr = VariableGetString(pVariables, BURN_BUNDLE_LAYOUT_DIRECTORY, &pPlan->sczLayoutDirectory);
431 if (E_NOTFOUND == hr) // if not set, use the current directory as the layout directory. 399 if (E_NOTFOUND == hr) // if not set, use the current directory as the layout directory.
432 { 400 {
433 hr = VariableGetString(pVariables, BURN_BUNDLE_SOURCE_PROCESS_FOLDER, &sczLayoutDirectory); 401 hr = VariableGetString(pVariables, BURN_BUNDLE_SOURCE_PROCESS_FOLDER, &pPlan->sczLayoutDirectory);
434 if (E_NOTFOUND == hr) // if not set, use the current directory as the layout directory. 402 if (E_NOTFOUND == hr) // if not set, use the current directory as the layout directory.
435 { 403 {
436 hr = PathForCurrentProcess(&sczExecutablePath, NULL); 404 hr = PathForCurrentProcess(&sczExecutablePath, NULL);
437 ExitOnFailure(hr, "Failed to get path for current executing process as layout directory."); 405 ExitOnFailure(hr, "Failed to get path for current executing process as layout directory.");
438 406
439 hr = PathGetDirectory(sczExecutablePath, &sczLayoutDirectory); 407 hr = PathGetDirectory(sczExecutablePath, &pPlan->sczLayoutDirectory);
440 ExitOnFailure(hr, "Failed to get executing process as layout directory."); 408 ExitOnFailure(hr, "Failed to get executing process as layout directory.");
441 } 409 }
442 } 410 }
443 ExitOnFailure(hr, "Failed to get bundle layout directory property."); 411 ExitOnFailure(hr, "Failed to get bundle layout directory property.");
444 412
445 hr = PathBackslashTerminate(&sczLayoutDirectory); 413 hr = PathBackslashTerminate(&pPlan->sczLayoutDirectory);
446 ExitOnFailure(hr, "Failed to ensure layout directory is backslash terminated."); 414 ExitOnFailure(hr, "Failed to ensure layout directory is backslash terminated.");
447 415
416 hr = ProcessPayloadGroup(pPlan, pLayoutPayloads);
417 ExitOnFailure(hr, "Failed to process payload group for bundle.");
418
448 // Plan the layout of the bundle engine itself. 419 // Plan the layout of the bundle engine itself.
449 hr = AppendCacheAction(pPlan, &pCacheAction); 420 hr = AppendCacheAction(pPlan, &pCacheAction);
450 ExitOnFailure(hr, "Failed to append bundle start action."); 421 ExitOnFailure(hr, "Failed to append bundle start action.");
@@ -454,36 +425,17 @@ extern "C" HRESULT PlanLayoutBundle(
454 hr = StrAllocString(&pCacheAction->bundleLayout.sczExecutableName, wzExecutableName, 0); 425 hr = StrAllocString(&pCacheAction->bundleLayout.sczExecutableName, wzExecutableName, 0);
455 ExitOnFailure(hr, "Failed to to copy executable name for bundle."); 426 ExitOnFailure(hr, "Failed to to copy executable name for bundle.");
456 427
457 hr = StrAllocString(&pCacheAction->bundleLayout.sczLayoutDirectory, sczLayoutDirectory, 0);
458 ExitOnFailure(hr, "Failed to to copy layout directory for bundle.");
459
460 hr = CacheCalculateBundleLayoutWorkingPath(pPlan->wzBundleId, &pCacheAction->bundleLayout.sczUnverifiedPath); 428 hr = CacheCalculateBundleLayoutWorkingPath(pPlan->wzBundleId, &pCacheAction->bundleLayout.sczUnverifiedPath);
461 ExitOnFailure(hr, "Failed to calculate bundle layout working path."); 429 ExitOnFailure(hr, "Failed to calculate bundle layout working path.");
462 430
463 pCacheAction->bundleLayout.qwBundleSize = qwBundleSize; 431 pCacheAction->bundleLayout.qwBundleSize = qwBundleSize;
432 pCacheAction->bundleLayout.pPayloadGroup = pLayoutPayloads;
464 433
465 pPlan->qwCacheSizeTotal += qwBundleSize; 434 pPlan->qwCacheSizeTotal += 2 * qwBundleSize;
466 435
467 ++pPlan->cOverallProgressTicksTotal; 436 ++pPlan->cOverallProgressTicksTotal;
468 437
469 // Plan the layout of layout-only payloads.
470 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
471 {
472 BURN_PAYLOAD* pPayload = pPayloads->rgPayloads + i;
473 if (pPayload->fLayoutOnly)
474 {
475 // TODO: determine if a payload already exists in the layout and pass appropriate value fPayloadCached
476 // (instead of always FALSE).
477 hr = AppendCacheOrLayoutPayloadAction(pPlan, NULL, BURN_PLAN_INVALID_ACTION_INDEX, pPayload, FALSE, sczLayoutDirectory);
478 ExitOnFailure(hr, "Failed to plan layout payload.");
479 }
480 }
481
482 *psczLayoutDirectory = sczLayoutDirectory;
483 sczLayoutDirectory = NULL;
484
485LExit: 438LExit:
486 ReleaseStr(sczLayoutDirectory);
487 ReleaseStr(sczExecutablePath); 439 ReleaseStr(sczExecutablePath);
488 440
489 return hr; 441 return hr;
@@ -562,13 +514,12 @@ extern "C" HRESULT PlanPackages(
562 __in BURN_LOGGING* pLog, 514 __in BURN_LOGGING* pLog,
563 __in BURN_VARIABLES* pVariables, 515 __in BURN_VARIABLES* pVariables,
564 __in BOOTSTRAPPER_DISPLAY display, 516 __in BOOTSTRAPPER_DISPLAY display,
565 __in BOOTSTRAPPER_RELATION_TYPE relationType, 517 __in BOOTSTRAPPER_RELATION_TYPE relationType
566 __in_z_opt LPCWSTR wzLayoutDirectory
567 ) 518 )
568{ 519{
569 HRESULT hr = S_OK; 520 HRESULT hr = S_OK;
570 521
571 hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, wzLayoutDirectory); 522 hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, TRUE, pUX, pPlan, pLog, pVariables, display, relationType);
572 523
573 return hr; 524 return hr;
574} 525}
@@ -782,7 +733,7 @@ extern "C" HRESULT PlanPassThroughBundle(
782 // Plan passthrough package. 733 // Plan passthrough package.
783 // Passthrough packages are never cleaned up by the calling bundle (they delete themselves when appropriate) 734 // Passthrough packages are never cleaned up by the calling bundle (they delete themselves when appropriate)
784 // so we don't need to plan clean up. 735 // so we don't need to plan clean up.
785 hr = PlanPackagesHelper(pPackage, 1, FALSE, pUX, pPlan, pLog, pVariables, display, relationType, NULL); 736 hr = PlanPackagesHelper(pPackage, 1, FALSE, pUX, pPlan, pLog, pVariables, display, relationType);
786 ExitOnFailure(hr, "Failed to process passthrough package."); 737 ExitOnFailure(hr, "Failed to process passthrough package.");
787 738
788LExit: 739LExit:
@@ -802,7 +753,7 @@ extern "C" HRESULT PlanUpdateBundle(
802 HRESULT hr = S_OK; 753 HRESULT hr = S_OK;
803 754
804 // Plan update package. 755 // Plan update package.
805 hr = PlanPackagesHelper(pPackage, 1, TRUE, pUX, pPlan, pLog, pVariables, display, relationType, NULL); 756 hr = PlanPackagesHelper(pPackage, 1, TRUE, pUX, pPlan, pLog, pVariables, display, relationType);
806 ExitOnFailure(hr, "Failed to process update package."); 757 ExitOnFailure(hr, "Failed to process update package.");
807 758
808LExit: 759LExit:
@@ -818,8 +769,7 @@ static HRESULT PlanPackagesHelper(
818 __in BURN_LOGGING* pLog, 769 __in BURN_LOGGING* pLog,
819 __in BURN_VARIABLES* pVariables, 770 __in BURN_VARIABLES* pVariables,
820 __in BOOTSTRAPPER_DISPLAY display, 771 __in BOOTSTRAPPER_DISPLAY display,
821 __in BOOTSTRAPPER_RELATION_TYPE relationType, 772 __in BOOTSTRAPPER_RELATION_TYPE relationType
822 __in_z_opt LPCWSTR wzLayoutDirectory
823 ) 773 )
824{ 774{
825 HRESULT hr = S_OK; 775 HRESULT hr = S_OK;
@@ -856,7 +806,7 @@ static HRESULT PlanPackagesHelper(
856 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 806 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
857 BURN_PACKAGE* pPackage = rgPackages + iPackage; 807 BURN_PACKAGE* pPackage = rgPackages + iPackage;
858 808
859 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, wzLayoutDirectory, &hSyncpointEvent, &pRollbackBoundary); 809 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &hSyncpointEvent, &pRollbackBoundary);
860 ExitOnFailure(hr, "Failed to process package."); 810 ExitOnFailure(hr, "Failed to process package.");
861 } 811 }
862 812
@@ -962,7 +912,6 @@ static HRESULT ProcessPackage(
962 __in BURN_LOGGING* pLog, 912 __in BURN_LOGGING* pLog,
963 __in BURN_VARIABLES* pVariables, 913 __in BURN_VARIABLES* pVariables,
964 __in BOOTSTRAPPER_DISPLAY display, 914 __in BOOTSTRAPPER_DISPLAY display,
965 __in_z_opt LPCWSTR wzLayoutDirectory,
966 __inout HANDLE* phSyncpointEvent, 915 __inout HANDLE* phSyncpointEvent,
967 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 916 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
968 ) 917 )
@@ -976,7 +925,7 @@ static HRESULT ProcessPackage(
976 925
977 if (BOOTSTRAPPER_ACTION_LAYOUT == pPlan->action) 926 if (BOOTSTRAPPER_ACTION_LAYOUT == pPlan->action)
978 { 927 {
979 hr = PlanLayoutPackage(pPlan, pPackage, wzLayoutDirectory); 928 hr = PlanLayoutPackage(pPlan, pPackage);
980 ExitOnFailure(hr, "Failed to plan layout package."); 929 ExitOnFailure(hr, "Failed to plan layout package.");
981 } 930 }
982 else 931 else
@@ -1035,59 +984,69 @@ LExit:
1035 return hr; 984 return hr;
1036} 985}
1037 986
1038extern "C" HRESULT PlanLayoutPackage( 987extern "C" HRESULT PlanLayoutContainer(
1039 __in BURN_PLAN* pPlan, 988 __in BURN_PLAN* pPlan,
1040 __in BURN_PACKAGE* pPackage, 989 __in BURN_CONTAINER* pContainer
1041 __in_z_opt LPCWSTR wzLayoutDirectory
1042 ) 990 )
1043{ 991{
1044 HRESULT hr = S_OK; 992 HRESULT hr = S_OK;
1045 BURN_CACHE_ACTION* pCacheAction = NULL; 993 BURN_CACHE_ACTION* pCacheAction = NULL;
1046 DWORD iPackageStartAction = 0;
1047 994
1048 hr = AppendCacheAction(pPlan, &pCacheAction); 995 Assert(!pContainer->fPlanned);
1049 ExitOnFailure(hr, "Failed to append package start action."); 996 pContainer->fPlanned = TRUE;
1050 997
1051 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE_START; 998 if (pPlan->sczLayoutDirectory)
1052 pCacheAction->packageStart.pPackage = pPackage; 999 {
1000 if (!pContainer->fAttached)
1001 {
1002 hr = AppendCacheAction(pPlan, &pCacheAction);
1003 ExitOnFailure(hr, "Failed to append package start action.");
1053 1004
1054 // Remember the index for the package start action (which is now the last in the cache 1005 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CONTAINER;
1055 // actions array) because the array may be resized later and move around in memory. 1006 pCacheAction->container.pContainer = pContainer;
1056 iPackageStartAction = pPlan->cCacheActions - 1;
1057 1007
1058 // If any of the package payloads are not cached, add them to the plan. 1008 pPlan->qwCacheSizeTotal += 2 * pContainer->qwFileSize;
1059 for (DWORD i = 0; i < pPackage->cPayloads; ++i) 1009 }
1010 }
1011 else
1060 { 1012 {
1061 BURN_PACKAGE_PAYLOAD* pPackagePayload = &pPackage->rgPayloads[i]; 1013 pPlan->qwCacheSizeTotal += 2 * pContainer->qwFileSize;
1014 }
1062 1015
1063 // If doing layout and the package is in a container. 1016 if (!pContainer->sczUnverifiedPath)
1064 if (wzLayoutDirectory && pPackagePayload->pPayload->pContainer) 1017 {
1018 if (pContainer->fActuallyAttached)
1065 { 1019 {
1066 // TODO: determine if a container already exists in the layout and pass appropriate value fPayloadCached (instead of always FALSE). 1020 hr = PathForCurrentProcess(&pContainer->sczUnverifiedPath, NULL);
1067 hr = AppendLayoutContainerAction(pPlan, pPackage, iPackageStartAction, pPackagePayload->pPayload->pContainer, FALSE, wzLayoutDirectory); 1021 ExitOnFailure(hr, "Failed to get path for executing module as attached container working path.");
1068 ExitOnFailure(hr, "Failed to append layout container action.");
1069 } 1022 }
1070 else 1023 else
1071 { 1024 {
1072 // TODO: determine if a payload already exists in the layout and pass appropriate value fPayloadCached (instead of always FALSE). 1025 hr = CacheCalculateContainerWorkingPath(pPlan->wzBundleId, pContainer, &pContainer->sczUnverifiedPath);
1073 hr = AppendCacheOrLayoutPayloadAction(pPlan, pPackage, iPackageStartAction, pPackagePayload->pPayload, FALSE, wzLayoutDirectory); 1026 ExitOnFailure(hr, "Failed to calculate unverified path for container.");
1074 ExitOnFailure(hr, "Failed to append cache/layout payload action.");
1075 } 1027 }
1076
1077 Assert(BURN_CACHE_ACTION_TYPE_PACKAGE_START == pPlan->rgCacheActions[iPackageStartAction].type);
1078 ++pPlan->rgCacheActions[iPackageStartAction].packageStart.cCachePayloads;
1079 pPlan->rgCacheActions[iPackageStartAction].packageStart.qwCachePayloadSizeTotal += pPackagePayload->pPayload->qwFileSize;
1080 } 1028 }
1081 1029
1082 // Create package stop action. 1030LExit:
1083 hr = AppendCacheAction(pPlan, &pCacheAction); 1031 return hr;
1084 ExitOnFailure(hr, "Failed to append cache action."); 1032}
1085 1033
1086 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE_STOP; 1034extern "C" HRESULT PlanLayoutPackage(
1087 pCacheAction->packageStop.pPackage = pPackage; 1035 __in BURN_PLAN* pPlan,
1036 __in BURN_PACKAGE* pPackage
1037 )
1038{
1039 HRESULT hr = S_OK;
1040 BURN_CACHE_ACTION* pCacheAction = NULL;
1041
1042 hr = ProcessPayloadGroup(pPlan, &pPackage->payloads);
1043 ExitOnFailure(hr, "Failed to process payload group for package: %ls.", pPackage->sczId);
1088 1044
1089 // Update the start action with the location of the complete action. 1045 hr = AppendCacheAction(pPlan, &pCacheAction);
1090 pPlan->rgCacheActions[iPackageStartAction].packageStart.iPackageCompleteAction = pPlan->cCacheActions - 1; 1046 ExitOnFailure(hr, "Failed to append package start action.");
1047
1048 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE;
1049 pCacheAction->package.pPackage = pPackage;
1091 1050
1092 ++pPlan->cOverallProgressTicksTotal; 1051 ++pPlan->cOverallProgressTicksTotal;
1093 1052
@@ -1854,29 +1813,37 @@ static void UninitializeCacheAction(
1854 1813
1855 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE: 1814 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
1856 ReleaseStr(pCacheAction->bundleLayout.sczExecutableName); 1815 ReleaseStr(pCacheAction->bundleLayout.sczExecutableName);
1857 ReleaseStr(pCacheAction->bundleLayout.sczLayoutDirectory);
1858 ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath); 1816 ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath);
1859 break; 1817 break;
1818 }
1819}
1860 1820
1861 case BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER: 1821static void ResetPlannedContainerState(
1862 ReleaseStr(pCacheAction->resolveContainer.sczUnverifiedPath); 1822 __in BURN_CONTAINER* pContainer
1863 break; 1823 )
1864 1824{
1865 case BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER: 1825 pContainer->fPlanned = FALSE;
1866 ReleaseStr(pCacheAction->extractContainer.sczContainerUnverifiedPath); 1826}
1867 ReleaseMem(pCacheAction->extractContainer.rgPayloads);
1868 break;
1869 1827
1870 case BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD: 1828static void ResetPlannedPayloadsState(
1871 ReleaseStr(pCacheAction->resolvePayload.sczUnverifiedPath); 1829 __in BURN_PAYLOADS* pPayloads
1872 break; 1830 )
1831{
1832 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
1833 {
1834 BURN_PAYLOAD* pPayload = pPayloads->rgPayloads + i;
1873 1835
1874 case BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD: 1836 pPayload->state = BURN_PAYLOAD_STATE_NONE;
1875 ReleaseStr(pCacheAction->cachePayload.sczUnverifiedPath); 1837 ReleaseNullStr(pPayload->sczLocalFilePath);
1876 break;
1877 } 1838 }
1878} 1839}
1879 1840
1841static void ResetPlannedPayloadGroupState(
1842 __in BURN_PAYLOAD_GROUP* /*pPayloadGroup*/
1843 )
1844{
1845}
1846
1880static void ResetPlannedPackageState( 1847static void ResetPlannedPackageState(
1881 __in BURN_PACKAGE* pPackage 1848 __in BURN_PACKAGE* pPackage
1882 ) 1849 )
@@ -1931,6 +1898,8 @@ static void ResetPlannedPackageState(
1931 pTargetProduct->rollbackSkip = BURN_PATCH_SKIP_STATE_NONE; 1898 pTargetProduct->rollbackSkip = BURN_PATCH_SKIP_STATE_NONE;
1932 } 1899 }
1933 } 1900 }
1901
1902 ResetPlannedPayloadGroupState(&pPackage->payloads);
1934} 1903}
1935 1904
1936static void ResetPlannedRollbackBoundaryState( 1905static void ResetPlannedRollbackBoundaryState(
@@ -2091,7 +2060,6 @@ static HRESULT AddCachePackageHelper(
2091 HRESULT hr = S_OK; 2060 HRESULT hr = S_OK;
2092 BURN_CACHE_ACTION* pCacheAction = NULL; 2061 BURN_CACHE_ACTION* pCacheAction = NULL;
2093 DWORD dwCheckpoint = 0; 2062 DWORD dwCheckpoint = 0;
2094 DWORD iPackageStartAction = 0;
2095 2063
2096 BOOL fPlanned = AlreadyPlannedCachePackage(pPlan, pPackage->sczId, phSyncpointEvent); 2064 BOOL fPlanned = AlreadyPlannedCachePackage(pPlan, pPackage->sczId, phSyncpointEvent);
2097 if (fPlanned) 2065 if (fPlanned)
@@ -2105,7 +2073,7 @@ static HRESULT AddCachePackageHelper(
2105 dwCheckpoint = GetNextCheckpointId(pPlan); 2073 dwCheckpoint = GetNextCheckpointId(pPlan);
2106 2074
2107 hr = AppendCacheAction(pPlan, &pCacheAction); 2075 hr = AppendCacheAction(pPlan, &pCacheAction);
2108 ExitOnFailure(hr, "Failed to append package start action."); 2076 ExitOnFailure(hr, "Failed to append checkpoint before package start action.");
2109 2077
2110 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CHECKPOINT; 2078 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CHECKPOINT;
2111 pCacheAction->checkpoint.dwId = dwCheckpoint; 2079 pCacheAction->checkpoint.dwId = dwCheckpoint;
@@ -2123,50 +2091,8 @@ static HRESULT AddCachePackageHelper(
2123 pCacheAction->checkpoint.dwId = dwCheckpoint; 2091 pCacheAction->checkpoint.dwId = dwCheckpoint;
2124 } 2092 }
2125 2093
2126 // Plan the package start. 2094 hr = PlanLayoutPackage(pPlan, pPackage);
2127 hr = AppendCacheAction(pPlan, &pCacheAction); 2095 ExitOnFailure(hr, "Failed to plan cache for package.");
2128 ExitOnFailure(hr, "Failed to append package start action.");
2129
2130 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE_START;
2131 pCacheAction->packageStart.pPackage = pPackage;
2132
2133 // Remember the index for the package start action (which is now the last in the cache
2134 // actions array) because we have to update this action after processing all the payloads
2135 // and the array may be resized later which would move a pointer around in memory.
2136 iPackageStartAction = pPlan->cCacheActions - 1;
2137
2138 if (fPlanCacheRollback)
2139 {
2140 // Create a package cache rollback action.
2141 hr = AppendRollbackCacheAction(pPlan, &pCacheAction);
2142 ExitOnFailure(hr, "Failed to append rollback cache action.");
2143
2144 pCacheAction->type = BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE;
2145 pCacheAction->rollbackPackage.pPackage = pPackage;
2146 }
2147
2148 // Add all the payload cache operations to the plan for this package.
2149 for (DWORD i = 0; i < pPackage->cPayloads; ++i)
2150 {
2151 BURN_PACKAGE_PAYLOAD* pPackagePayload = &pPackage->rgPayloads[i];
2152
2153 hr = AppendCacheOrLayoutPayloadAction(pPlan, pPackage, iPackageStartAction, pPackagePayload->pPayload, pPackagePayload->fCached, NULL);
2154 ExitOnFailure(hr, "Failed to append payload cache action.");
2155
2156 Assert(BURN_CACHE_ACTION_TYPE_PACKAGE_START == pPlan->rgCacheActions[iPackageStartAction].type);
2157 ++pPlan->rgCacheActions[iPackageStartAction].packageStart.cCachePayloads;
2158 pPlan->rgCacheActions[iPackageStartAction].packageStart.qwCachePayloadSizeTotal += pPackagePayload->pPayload->qwFileSize;
2159 }
2160
2161 // Create package stop action.
2162 hr = AppendCacheAction(pPlan, &pCacheAction);
2163 ExitOnFailure(hr, "Failed to append cache action.");
2164
2165 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE_STOP;
2166 pCacheAction->packageStop.pPackage = pPackage;
2167
2168 // Update the start action with the location of the complete action.
2169 pPlan->rgCacheActions[iPackageStartAction].packageStart.iPackageCompleteAction = pPlan->cCacheActions - 1;
2170 2096
2171 // Create syncpoint action. 2097 // Create syncpoint action.
2172 hr = AppendCacheAction(pPlan, &pCacheAction); 2098 hr = AppendCacheAction(pPlan, &pCacheAction);
@@ -2178,8 +2104,6 @@ static HRESULT AddCachePackageHelper(
2178 2104
2179 *phSyncpointEvent = pCacheAction->syncpoint.hEvent; 2105 *phSyncpointEvent = pCacheAction->syncpoint.hEvent;
2180 2106
2181 ++pPlan->cOverallProgressTicksTotal;
2182
2183 pPackage->fPlannedCache = TRUE; 2107 pPackage->fPlannedCache = TRUE;
2184 if (pPackage->fCanAffectRegistration) 2108 if (pPackage->fCanAffectRegistration)
2185 { 2109 {
@@ -2225,9 +2149,9 @@ static BOOL AlreadyPlannedCachePackage(
2225 { 2149 {
2226 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + iCacheAction; 2150 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + iCacheAction;
2227 2151
2228 if (BURN_CACHE_ACTION_TYPE_PACKAGE_STOP == pCacheAction->type) 2152 if (BURN_CACHE_ACTION_TYPE_PACKAGE == pCacheAction->type)
2229 { 2153 {
2230 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pCacheAction->packageStop.pPackage->sczId, -1, wzPackageId, -1)) 2154 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pCacheAction->package.pPackage->sczId, -1, wzPackageId, -1))
2231 { 2155 {
2232 if (iCacheAction + 1 < pPlan->cCacheActions && BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT == pPlan->rgCacheActions[iCacheAction + 1].type) 2156 if (iCacheAction + 1 < pPlan->cCacheActions && BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT == pPlan->rgCacheActions[iCacheAction + 1].type)
2233 { 2157 {
@@ -2284,460 +2208,39 @@ LExit:
2284 return hr; 2208 return hr;
2285} 2209}
2286 2210
2287static HRESULT AppendLayoutContainerAction( 2211static HRESULT ProcessPayloadGroup(
2288 __in BURN_PLAN* pPlan,
2289 __in_opt BURN_PACKAGE* pPackage,
2290 __in DWORD iPackageStartAction,
2291 __in BURN_CONTAINER* pContainer,
2292 __in BOOL fContainerCached,
2293 __in_z LPCWSTR wzLayoutDirectory
2294 )
2295{
2296 HRESULT hr = S_OK;
2297 BURN_CACHE_ACTION* pAcquireAction = NULL;
2298 DWORD iAcquireAction = BURN_PLAN_INVALID_ACTION_INDEX;
2299 LPWSTR sczContainerWorkingPath = NULL;
2300 BURN_CACHE_ACTION* pCacheAction = NULL;
2301 BURN_CACHE_CONTAINER_PROGRESS* pContainerProgress = NULL;
2302
2303 // No need to do anything if the container is already cached or is attached to the bundle (since the
2304 // bundle itself will already have a layout action).
2305 if (fContainerCached || pContainer->fAttached)
2306 {
2307 ExitFunction();
2308 }
2309
2310 // Ensure the container is being acquired. If it is, then some earlier package already planned the layout of this container so
2311 // don't do it again. Otherwise, plan away!
2312 if (!FindContainerCacheAction(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, pPlan, pContainer, 0, iPackageStartAction, NULL, NULL))
2313 {
2314 hr = AddAcquireContainer(pPlan, pContainer, &pAcquireAction, &iAcquireAction);
2315 ExitOnFailure(hr, "Failed to append acquire container action for layout to plan.");
2316
2317 Assert(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER == pAcquireAction->type);
2318
2319 // Create the layout container action.
2320 hr = StrAllocString(&sczContainerWorkingPath, pAcquireAction->resolveContainer.sczUnverifiedPath, 0);
2321 ExitOnFailure(hr, "Failed to copy container working path for layout.");
2322
2323 hr = AppendCacheAction(pPlan, &pCacheAction);
2324 ExitOnFailure(hr, "Failed to append cache action to cache payload.");
2325
2326 hr = CreateContainerProgress(pPlan, pContainer, &pContainerProgress);
2327 ExitOnFailure(hr, "Failed to create container progress.");
2328
2329 hr = StrAllocString(&pCacheAction->layoutContainer.sczLayoutDirectory, wzLayoutDirectory, 0);
2330 ExitOnFailure(hr, "Failed to copy layout directory into plan.");
2331
2332 pCacheAction->type = BURN_CACHE_ACTION_TYPE_LAYOUT_CONTAINER;
2333 pCacheAction->layoutContainer.pPackage = pPackage;
2334 pCacheAction->layoutContainer.pContainer = pContainer;
2335 pCacheAction->layoutContainer.iProgress = pContainerProgress->iIndex;
2336 pCacheAction->layoutContainer.fMove = TRUE;
2337 pCacheAction->layoutContainer.iTryAgainAction = iAcquireAction;
2338 pCacheAction->layoutContainer.sczUnverifiedPath = sczContainerWorkingPath;
2339 sczContainerWorkingPath = NULL;
2340 }
2341
2342LExit:
2343 ReleaseNullStr(sczContainerWorkingPath);
2344
2345 return hr;
2346}
2347
2348static HRESULT AppendCacheOrLayoutPayloadAction(
2349 __in BURN_PLAN* pPlan, 2212 __in BURN_PLAN* pPlan,
2350 __in_opt BURN_PACKAGE* pPackage, 2213 __in BURN_PAYLOAD_GROUP* pPayloadGroup
2351 __in DWORD iPackageStartAction,
2352 __in BURN_PAYLOAD* pPayload,
2353 __in BOOL fPayloadCached,
2354 __in_z_opt LPCWSTR wzLayoutDirectory
2355 ) 2214 )
2356{ 2215{
2357 HRESULT hr = S_OK; 2216 HRESULT hr = S_OK;
2358 LPWSTR sczPayloadWorkingPath = NULL;
2359 BURN_CACHE_ACTION* pCacheAction = NULL;
2360 DWORD iTryAgainAction = BURN_PLAN_INVALID_ACTION_INDEX;
2361 BURN_CACHE_PAYLOAD_PROGRESS* pPayloadProgress = NULL;
2362
2363 hr = CacheCalculatePayloadWorkingPath(pPlan->wzBundleId, pPayload, &sczPayloadWorkingPath);
2364 ExitOnFailure(hr, "Failed to calculate unverified path for payload.");
2365
2366 // If the payload is in a container, ensure the container is being acquired
2367 // then add this payload to the list of payloads to extract already in the plan.
2368 if (pPayload->pContainer)
2369 {
2370 BURN_CACHE_ACTION* pPreviousPackageExtractAction = NULL;
2371 BURN_CACHE_ACTION* pThisPackageExtractAction = NULL;
2372
2373 // If the payload is not already cached, then add it to the first extract container action in the plan. Extracting
2374 // all the needed payloads from the container in a single pass is the most efficient way to extract files from
2375 // containers. If there is not an extract container action before our package, that is okay because we'll create
2376 // an extract container action for our package in a second anyway.
2377 if (!fPayloadCached)
2378 {
2379 if (FindContainerCacheAction(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER, pPlan, pPayload->pContainer, 0, iPackageStartAction, &pPreviousPackageExtractAction, NULL))
2380 {
2381 hr = AddExtractPayload(pPreviousPackageExtractAction, pPackage, pPayload, sczPayloadWorkingPath);
2382 ExitOnFailure(hr, "Failed to add extract payload action to previous package.");
2383 }
2384 }
2385
2386 // If there is already an extract container action after our package start action then try to find an acquire action
2387 // that is matched with it. If there is an acquire action then that is our "try again" action, otherwise we'll use the existing
2388 // extract action as the "try again" action.
2389 if (FindContainerCacheAction(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER, pPlan, pPayload->pContainer, iPackageStartAction, BURN_PLAN_INVALID_ACTION_INDEX, &pThisPackageExtractAction, &iTryAgainAction))
2390 {
2391 DWORD iAcquireAction = BURN_PLAN_INVALID_ACTION_INDEX;
2392 if (FindContainerCacheAction(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, pPlan, pPayload->pContainer, iPackageStartAction, iTryAgainAction, NULL, &iAcquireAction))
2393 {
2394 iTryAgainAction = iAcquireAction;
2395 }
2396 }
2397 else // did not find an extract container action for our package.
2398 {
2399 // Ensure there is an extract action (and maybe an acquire action) for every package that has payloads. The
2400 // acquire and extract action will be skipped if the payload is already cached or was added to a previous
2401 // package's extract action above.
2402 //
2403 // These actions always exist (even when they are likely to be skipped) so that "try again" will not
2404 // jump so far back in the plan that you end up extracting payloads for other packages. With these actions
2405 // "try again" will only retry the extraction for payloads in this package.
2406 hr = CreateContainerAcquireAndExtractAction(pPlan, pPayload->pContainer, iPackageStartAction, pPreviousPackageExtractAction ? TRUE : fPayloadCached, &pThisPackageExtractAction, &iTryAgainAction);
2407 ExitOnFailure(hr, "Failed to create container extract action.");
2408 }
2409 ExitOnFailure(hr, "Failed while searching for package's container extract action.");
2410
2411 // We *always* add the payload to this package's extract action even though the extract action
2412 // is probably being skipped until retry if there was a previous package extract action.
2413 hr = AddExtractPayload(pThisPackageExtractAction, pPackage, pPayload, sczPayloadWorkingPath);
2414 ExitOnFailure(hr, "Failed to add extract payload to current package.");
2415 }
2416 else // add a payload acquire action to the plan.
2417 {
2418 // Try to find an existing acquire action for this payload. If one is not found,
2419 // we'll create it. At the same time we will change any cache/layout payload actions
2420 // that would "MOVE" the file to "COPY" so that our new cache/layout action below
2421 // can do the move.
2422 pCacheAction = ProcessSharedPayload(pPlan, pPayload);
2423 if (!pCacheAction)
2424 {
2425 hr = AppendCacheAction(pPlan, &pCacheAction);
2426 ExitOnFailure(hr, "Failed to append cache action to acquire payload.");
2427
2428 pCacheAction->type = BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD;
2429 pCacheAction->fSkipUntilRetried = fPayloadCached;
2430 pCacheAction->resolvePayload.pPackage = pPackage;
2431 pCacheAction->resolvePayload.pPayload = pPayload;
2432 hr = StrAllocString(&pCacheAction->resolvePayload.sczUnverifiedPath, sczPayloadWorkingPath, 0);
2433 ExitOnFailure(hr, "Failed to copy unverified path for payload to acquire.");
2434 }
2435
2436 iTryAgainAction = static_cast<DWORD>(pCacheAction - pPlan->rgCacheActions);
2437 pCacheAction = NULL;
2438 }
2439 2217
2440 Assert(BURN_PLAN_INVALID_ACTION_INDEX != iTryAgainAction); 2218 for (DWORD i = 0; i < pPayloadGroup->cPayloads; ++i)
2441 Assert(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER == pPlan->rgCacheActions[iTryAgainAction].type ||
2442 BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER == pPlan->rgCacheActions[iTryAgainAction].type ||
2443 BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD == pPlan->rgCacheActions[iTryAgainAction].type);
2444
2445 hr = AppendCacheAction(pPlan, &pCacheAction);
2446 ExitOnFailure(hr, "Failed to append cache action to cache payload.");
2447
2448 hr = CreatePayloadProgress(pPlan, pPayload, &pPayloadProgress);
2449 ExitOnFailure(hr, "Failed to create payload progress.");
2450
2451 if (!wzLayoutDirectory)
2452 { 2219 {
2453 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD; 2220 BURN_PAYLOAD* pPayload = pPayloadGroup->rgpPayloads[i];
2454 pCacheAction->cachePayload.pPackage = pPackage;
2455 pCacheAction->cachePayload.pPayload = pPayload;
2456 pCacheAction->cachePayload.iProgress = pPayloadProgress->iIndex;
2457 pCacheAction->cachePayload.fMove = TRUE;
2458 pCacheAction->cachePayload.iTryAgainAction = iTryAgainAction;
2459 pCacheAction->cachePayload.sczUnverifiedPath = sczPayloadWorkingPath;
2460 sczPayloadWorkingPath = NULL;
2461 }
2462 else
2463 {
2464 hr = StrAllocString(&pCacheAction->layoutPayload.sczLayoutDirectory, wzLayoutDirectory, 0);
2465 ExitOnFailure(hr, "Failed to copy layout directory into plan.");
2466
2467 pCacheAction->type = BURN_CACHE_ACTION_TYPE_LAYOUT_PAYLOAD;
2468 pCacheAction->layoutPayload.pPackage = pPackage;
2469 pCacheAction->layoutPayload.pPayload = pPayload;
2470 pCacheAction->layoutPayload.iProgress = pPayloadProgress->iIndex;
2471 pCacheAction->layoutPayload.fMove = TRUE;
2472 pCacheAction->layoutPayload.iTryAgainAction = iTryAgainAction;
2473 pCacheAction->layoutPayload.sczUnverifiedPath = sczPayloadWorkingPath;
2474 sczPayloadWorkingPath = NULL;
2475 }
2476
2477 pCacheAction = NULL;
2478
2479LExit:
2480 ReleaseStr(sczPayloadWorkingPath);
2481
2482 return hr;
2483}
2484
2485static BOOL FindContainerCacheAction(
2486 __in BURN_CACHE_ACTION_TYPE type,
2487 __in BURN_PLAN* pPlan,
2488 __in BURN_CONTAINER* pContainer,
2489 __in DWORD iSearchStart,
2490 __in DWORD iSearchEnd,
2491 __out_opt BURN_CACHE_ACTION** ppCacheAction,
2492 __out_opt DWORD* piCacheAction
2493 )
2494{
2495 BOOL fFound = FALSE; // assume we won't find what we are looking for.
2496
2497 Assert(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER == type || BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER == type);
2498
2499 iSearchStart = (BURN_PLAN_INVALID_ACTION_INDEX == iSearchStart) ? 0 : iSearchStart;
2500 iSearchEnd = (BURN_PLAN_INVALID_ACTION_INDEX == iSearchEnd) ? pPlan->cCacheActions : iSearchEnd;
2501 2221
2502 for (DWORD iSearch = iSearchStart; iSearch < iSearchEnd; ++iSearch) 2222 if (pPayload->pContainer && !pPayload->pContainer->fPlanned)
2503 {
2504 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + iSearch;
2505 if (pCacheAction->type == type &&
2506 ((BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER == pCacheAction->type && pCacheAction->resolveContainer.pContainer == pContainer) ||
2507 (BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER == pCacheAction->type && pCacheAction->extractContainer.pContainer == pContainer)))
2508 { 2223 {
2509 if (ppCacheAction) 2224 hr = PlanLayoutContainer(pPlan, pPayload->pContainer);
2510 { 2225 ExitOnFailure(hr, "Failed to plan container: %ls", pPayload->pContainer->sczId);
2511 *ppCacheAction = pCacheAction;
2512 }
2513
2514 if (piCacheAction)
2515 {
2516 *piCacheAction = iSearch;
2517 }
2518
2519 fFound = TRUE;
2520 break;
2521 } 2226 }
2522 }
2523
2524 return fFound;
2525}
2526 2227
2527static HRESULT CreateContainerAcquireAndExtractAction( 2228 if (!pPlan->sczLayoutDirectory || !pPayload->pContainer)
2528 __in BURN_PLAN* pPlan,
2529 __in BURN_CONTAINER* pContainer,
2530 __in DWORD iPackageStartAction,
2531 __in BOOL fPayloadCached,
2532 __out BURN_CACHE_ACTION** ppContainerExtractAction,
2533 __out DWORD* piContainerTryAgainAction
2534 )
2535{
2536 HRESULT hr = S_OK;
2537 DWORD iAcquireAction = BURN_PLAN_INVALID_ACTION_INDEX;
2538 BURN_CACHE_ACTION* pContainerExtractAction = NULL;
2539 DWORD iExtractAction = BURN_PLAN_INVALID_ACTION_INDEX;
2540 DWORD iTryAgainAction = BURN_PLAN_INVALID_ACTION_INDEX;
2541 LPWSTR sczContainerWorkingPath = NULL;
2542
2543 // If the container is actually attached to the executable then we will not need an acquire
2544 // container action.
2545 if (!pContainer->fActuallyAttached)
2546 {
2547 BURN_CACHE_ACTION* pAcquireContainerAction = NULL;
2548
2549 // If there is no plan to acquire the container then add acquire action since we
2550 // can't extract stuff out of a container until we acquire the container.
2551 if (!FindContainerCacheAction(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, pPlan, pContainer, iPackageStartAction, BURN_PLAN_INVALID_ACTION_INDEX, &pAcquireContainerAction, &iAcquireAction))
2552 { 2229 {
2553 hr = AddAcquireContainer(pPlan, pContainer, &pAcquireContainerAction, &iAcquireAction); 2230 pPlan->qwCacheSizeTotal += 2 * pPayload->qwFileSize;
2554 ExitOnFailure(hr, "Failed to append acquire container action to plan.");
2555
2556 pAcquireContainerAction->fSkipUntilRetried = TRUE; // we'll start by assuming the acquire is not necessary and the fPayloadCached below will set us straight if wrong.
2557 } 2231 }
2558 2232
2559 Assert(BURN_PLAN_INVALID_ACTION_INDEX != iAcquireAction); 2233 if (!pPayload->sczUnverifiedPath)
2560 Assert(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER == pAcquireContainerAction->type);
2561 Assert(pContainer == pAcquireContainerAction->resolveContainer.pContainer);
2562 }
2563
2564 Assert((pContainer->fActuallyAttached && BURN_PLAN_INVALID_ACTION_INDEX == iAcquireAction) ||
2565 (!pContainer->fActuallyAttached && BURN_PLAN_INVALID_ACTION_INDEX != iAcquireAction));
2566
2567 // If we do not find an action for extracting payloads from this container, create it now.
2568 if (!FindContainerCacheAction(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER, pPlan, pContainer, (BURN_PLAN_INVALID_ACTION_INDEX == iAcquireAction) ? iPackageStartAction : iAcquireAction, BURN_PLAN_INVALID_ACTION_INDEX, &pContainerExtractAction, &iExtractAction))
2569 {
2570 // Attached containers that are actually attached use the executable path for their working path.
2571 if (pContainer->fActuallyAttached)
2572 { 2234 {
2573 Assert(BURN_PLAN_INVALID_ACTION_INDEX == iAcquireAction); 2235 hr = CacheCalculatePayloadWorkingPath(pPlan->wzBundleId, pPayload, &pPayload->sczUnverifiedPath);
2574 2236 ExitOnFailure(hr, "Failed to calculate unverified path for payload.");
2575 hr = PathForCurrentProcess(&sczContainerWorkingPath, NULL);
2576 ExitOnFailure(hr, "Failed to get path for executing module as attached container working path.");
2577 } 2237 }
2578 else // use the acquired working path as the location of the container.
2579 {
2580 Assert(BURN_PLAN_INVALID_ACTION_INDEX != iAcquireAction);
2581
2582 hr = StrAllocString(&sczContainerWorkingPath, pPlan->rgCacheActions[iAcquireAction].resolveContainer.sczUnverifiedPath, 0);
2583 ExitOnFailure(hr, "Failed to copy container unverified path for cache action to extract container.");
2584 }
2585
2586 hr = AppendCacheAction(pPlan, &pContainerExtractAction);
2587 ExitOnFailure(hr, "Failed to append cache action to extract payloads from container.");
2588
2589 iExtractAction = pPlan->cCacheActions - 1;
2590
2591 pContainerExtractAction->type = BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER;
2592 pContainerExtractAction->fSkipUntilRetried = pContainer->fActuallyAttached; // assume we can skip the extract engine when the container is already attached and the fPayloadCached below will set us straight if wrong.
2593 pContainerExtractAction->extractContainer.pContainer = pContainer;
2594 pContainerExtractAction->extractContainer.iSkipUntilAcquiredByAction = iAcquireAction;
2595 pContainerExtractAction->extractContainer.sczContainerUnverifiedPath = sczContainerWorkingPath;
2596 sczContainerWorkingPath = NULL;
2597 }
2598
2599 Assert(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER == pContainerExtractAction->type);
2600 Assert(BURN_PLAN_INVALID_ACTION_INDEX != iExtractAction);
2601
2602 // If there is an acquire action, that is our try again action. Otherwise, we'll use the extract action.
2603 iTryAgainAction = (BURN_PLAN_INVALID_ACTION_INDEX != iAcquireAction) ? iAcquireAction : iExtractAction;
2604
2605 // If the try again action thinks it can be skipped but the payload is not cached,
2606 // ensure the action will not be skipped.
2607 BURN_CACHE_ACTION* pTryAgainAction = pPlan->rgCacheActions + iTryAgainAction;
2608 Assert((BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER == pTryAgainAction->type && pContainer == pTryAgainAction->resolveContainer.pContainer) ||
2609 (BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER == pTryAgainAction->type && pContainer == pTryAgainAction->extractContainer.pContainer));
2610 if (pTryAgainAction->fSkipUntilRetried && !fPayloadCached)
2611 {
2612 pTryAgainAction->fSkipUntilRetried = FALSE;
2613 }
2614
2615 *ppContainerExtractAction = pContainerExtractAction;
2616 *piContainerTryAgainAction = iTryAgainAction;
2617
2618LExit:
2619 ReleaseStr(sczContainerWorkingPath);
2620
2621 return hr;
2622}
2623
2624static HRESULT AddAcquireContainer(
2625 __in BURN_PLAN* pPlan,
2626 __in BURN_CONTAINER* pContainer,
2627 __out_opt BURN_CACHE_ACTION** ppCacheAction,
2628 __out_opt DWORD* piCacheAction
2629 )
2630{
2631 HRESULT hr = S_OK;
2632 LPWSTR sczContainerWorkingPath = NULL;
2633 BURN_CACHE_ACTION* pAcquireContainerAction = NULL;
2634 BURN_CACHE_CONTAINER_PROGRESS* pContainerProgress = NULL;
2635
2636 hr = CacheCalculateContainerWorkingPath(pPlan->wzBundleId, pContainer, &sczContainerWorkingPath);
2637 ExitOnFailure(hr, "Failed to calculate unverified path for container.");
2638
2639 hr = AppendCacheAction(pPlan, &pAcquireContainerAction);
2640 ExitOnFailure(hr, "Failed to append acquire container action to plan.");
2641
2642 hr = CreateContainerProgress(pPlan, pContainer, &pContainerProgress);
2643 ExitOnFailure(hr, "Failed to create container progress.");
2644
2645 pAcquireContainerAction->type = BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER;
2646 pAcquireContainerAction->resolveContainer.pContainer = pContainer;
2647 pAcquireContainerAction->resolveContainer.iProgress = pContainerProgress->iIndex;
2648 pAcquireContainerAction->resolveContainer.sczUnverifiedPath = sczContainerWorkingPath;
2649 sczContainerWorkingPath = NULL;
2650
2651 if (ppCacheAction)
2652 {
2653 *ppCacheAction = pAcquireContainerAction;
2654 }
2655
2656 if (piCacheAction)
2657 {
2658 *piCacheAction = pPlan->cCacheActions - 1;
2659 } 2238 }
2660 2239
2661LExit: 2240LExit:
2662 ReleaseStr(sczContainerWorkingPath);
2663
2664 return hr;
2665}
2666
2667static HRESULT AddExtractPayload(
2668 __in BURN_CACHE_ACTION* pCacheAction,
2669 __in_opt BURN_PACKAGE* pPackage,
2670 __in BURN_PAYLOAD* pPayload,
2671 __in_z LPCWSTR wzPayloadWorkingPath
2672 )
2673{
2674 HRESULT hr = S_OK;
2675
2676 Assert(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER == pCacheAction->type);
2677
2678 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pCacheAction->extractContainer.rgPayloads), pCacheAction->extractContainer.cPayloads + 1, sizeof(BURN_EXTRACT_PAYLOAD), 5);
2679 ExitOnFailure(hr, "Failed to grow list of payloads to extract from container.");
2680
2681 BURN_EXTRACT_PAYLOAD* pExtractPayload = pCacheAction->extractContainer.rgPayloads + pCacheAction->extractContainer.cPayloads;
2682 pExtractPayload->pPackage = pPackage;
2683 pExtractPayload->pPayload = pPayload;
2684 hr = StrAllocString(&pExtractPayload->sczUnverifiedPath, wzPayloadWorkingPath, 0);
2685 ExitOnFailure(hr, "Failed to copy unverified path for payload to extract.");
2686 ++pCacheAction->extractContainer.cPayloads;
2687
2688LExit:
2689 return hr; 2241 return hr;
2690} 2242}
2691 2243
2692static BURN_CACHE_ACTION* ProcessSharedPayload(
2693 __in BURN_PLAN* pPlan,
2694 __in BURN_PAYLOAD* pPayload
2695 )
2696{
2697 BURN_CACHE_ACTION* pAcquireAction = NULL;
2698#ifdef DEBUG
2699 DWORD cMove = 0;
2700#endif
2701
2702 for (DWORD i = 0; i < pPlan->cCacheActions; ++i)
2703 {
2704 BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + i;
2705
2706 if (BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD == pCacheAction->type &&
2707 pCacheAction->resolvePayload.pPayload == pPayload)
2708 {
2709 AssertSz(!pAcquireAction, "There should be at most one acquire cache action per payload.");
2710 pAcquireAction = pCacheAction;
2711 }
2712 else if (BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD == pCacheAction->type &&
2713 pCacheAction->cachePayload.pPayload == pPayload &&
2714 pCacheAction->cachePayload.fMove)
2715 {
2716 // Since we found a shared payload, change its operation from MOVE to COPY.
2717 pCacheAction->cachePayload.fMove = FALSE;
2718
2719 AssertSz(1 == ++cMove, "Shared payload should be moved once and only once.");
2720#ifndef DEBUG
2721 break;
2722#endif
2723 }
2724 else if (BURN_CACHE_ACTION_TYPE_LAYOUT_PAYLOAD == pCacheAction->type &&
2725 pCacheAction->layoutPayload.pPayload == pPayload &&
2726 pCacheAction->layoutPayload.fMove)
2727 {
2728 // Since we found a shared payload, change its operation from MOVE to COPY if necessary
2729 pCacheAction->layoutPayload.fMove = FALSE;
2730
2731 AssertSz(1 == ++cMove, "Shared payload should be moved once and only once.");
2732#ifndef DEBUG
2733 break;
2734#endif
2735 }
2736 }
2737
2738 return pAcquireAction;
2739}
2740
2741static void RemoveUnnecessaryActions( 2244static void RemoveUnnecessaryActions(
2742 __in BOOL fExecute, 2245 __in BOOL fExecute,
2743 __in BURN_EXECUTE_ACTION* rgActions, 2246 __in BURN_EXECUTE_ACTION* rgActions,
@@ -2984,86 +2487,6 @@ static BOOL NeedsCache(
2984 } 2487 }
2985} 2488}
2986 2489
2987static HRESULT CreateContainerProgress(
2988 __in BURN_PLAN* pPlan,
2989 __in BURN_CONTAINER* pContainer,
2990 __out BURN_CACHE_CONTAINER_PROGRESS** ppContainerProgress
2991 )
2992{
2993 HRESULT hr = S_OK;
2994 BURN_CACHE_CONTAINER_PROGRESS* pContainerProgress = NULL;
2995
2996 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPlan->rgContainerProgress), pPlan->cContainerProgress + 1, sizeof(BURN_CACHE_CONTAINER_PROGRESS), 5);
2997 ExitOnFailure(hr, "Failed to grow container progress list.");
2998
2999 if (!pPlan->shContainerProgress)
3000 {
3001 hr = DictCreateWithEmbeddedKey(&pPlan->shContainerProgress, 5, reinterpret_cast<void **>(&pPlan->rgContainerProgress), offsetof(BURN_CACHE_CONTAINER_PROGRESS, wzId), DICT_FLAG_NONE);
3002 ExitOnFailure(hr, "Failed to create container progress dictionary.");
3003 }
3004
3005 hr = DictGetValue(pPlan->shContainerProgress, pContainer->sczId, reinterpret_cast<void **>(&pContainerProgress));
3006 if (E_NOTFOUND == hr)
3007 {
3008 pContainerProgress = &pPlan->rgContainerProgress[pPlan->cContainerProgress];
3009 pContainerProgress->iIndex = pPlan->cContainerProgress;
3010 pContainerProgress->pContainer = pContainer;
3011 pContainerProgress->wzId = pContainer->sczId;
3012
3013 hr = DictAddValue(pPlan->shContainerProgress, pContainerProgress);
3014 ExitOnFailure(hr, "Failed to add \"%ls\" to the container progress dictionary.", pContainerProgress->wzId);
3015
3016 ++pPlan->cContainerProgress;
3017 pPlan->qwCacheSizeTotal += pContainer->qwFileSize;
3018 }
3019 ExitOnFailure(hr, "Failed to retrieve \"%ls\" from the container progress dictionary.", pContainer->sczId);
3020
3021 *ppContainerProgress = pContainerProgress;
3022
3023LExit:
3024 return hr;
3025}
3026
3027static HRESULT CreatePayloadProgress(
3028 __in BURN_PLAN* pPlan,
3029 __in BURN_PAYLOAD* pPayload,
3030 __out BURN_CACHE_PAYLOAD_PROGRESS** ppPayloadProgress
3031 )
3032{
3033 HRESULT hr = S_OK;
3034 BURN_CACHE_PAYLOAD_PROGRESS* pPayloadProgress = NULL;
3035
3036 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPlan->rgPayloadProgress), pPlan->cPayloadProgress + 1, sizeof(BURN_CACHE_PAYLOAD_PROGRESS), 5);
3037 ExitOnFailure(hr, "Failed to grow payload progress list.");
3038
3039 if (!pPlan->shPayloadProgress)
3040 {
3041 hr = DictCreateWithEmbeddedKey(&pPlan->shPayloadProgress, 5, reinterpret_cast<void **>(&pPlan->rgPayloadProgress), offsetof(BURN_CACHE_PAYLOAD_PROGRESS, wzId), DICT_FLAG_NONE);
3042 ExitOnFailure(hr, "Failed to create payload progress dictionary.");
3043 }
3044
3045 hr = DictGetValue(pPlan->shPayloadProgress, pPayload->sczKey, reinterpret_cast<void **>(&pPayloadProgress));
3046 if (E_NOTFOUND == hr)
3047 {
3048 pPayloadProgress = &pPlan->rgPayloadProgress[pPlan->cPayloadProgress];
3049 pPayloadProgress->iIndex = pPlan->cPayloadProgress;
3050 pPayloadProgress->pPayload = pPayload;
3051 pPayloadProgress->wzId = pPayload->sczKey;
3052
3053 hr = DictAddValue(pPlan->shPayloadProgress, pPayloadProgress);
3054 ExitOnFailure(hr, "Failed to add \"%ls\" to the payload progress dictionary.", pPayloadProgress->wzId);
3055
3056 ++pPlan->cPayloadProgress;
3057 pPlan->qwCacheSizeTotal += pPayload->qwFileSize;
3058 }
3059 ExitOnFailure(hr, "Failed to retrieve \"%ls\" from the payload progress dictionary.", pPayload->sczKey);
3060
3061 *ppPayloadProgress = pPayloadProgress;
3062
3063LExit:
3064 return hr;
3065}
3066
3067static void CacheActionLog( 2490static void CacheActionLog(
3068 __in DWORD iAction, 2491 __in DWORD iAction,
3069 __in BURN_CACHE_ACTION* pAction, 2492 __in BURN_CACHE_ACTION* pAction,
@@ -3073,60 +2496,28 @@ static void CacheActionLog(
3073 LPCWSTR wzBase = fRollback ? L" Rollback cache" : L" Cache"; 2496 LPCWSTR wzBase = fRollback ? L" Rollback cache" : L" Cache";
3074 switch (pAction->type) 2497 switch (pAction->type)
3075 { 2498 {
3076 case BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER:
3077 LogStringLine(PlanDumpLevel, "%ls action[%u]: ACQUIRE_CONTAINER id: %ls, source path: %ls, working path: %ls, skip until retried: %hs", wzBase, iAction, pAction->resolveContainer.pContainer->sczId, pAction->resolveContainer.pContainer->sczSourcePath, pAction->resolveContainer.sczUnverifiedPath, LoggingBoolToString(pAction->fSkipUntilRetried));
3078 break;
3079
3080 case BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD:
3081 LogStringLine(PlanDumpLevel, "%ls action[%u]: ACQUIRE_PAYLOAD package id: %ls, payload id: %ls, source path: %ls, working path: %ls, skip until retried: %hs", wzBase, iAction, pAction->resolvePayload.pPackage ? pAction->resolvePayload.pPackage->sczId : L"", pAction->resolvePayload.pPayload->sczKey, pAction->resolvePayload.pPayload->sczSourcePath, pAction->resolvePayload.sczUnverifiedPath, LoggingBoolToString(pAction->fSkipUntilRetried));
3082 break;
3083
3084 case BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD:
3085 LogStringLine(PlanDumpLevel, "%ls action[%u]: CACHE_PAYLOAD package id: %ls, payload id: %ls, working path: %ls, operation: %ls, skip until retried: %hs, retry action: %u", wzBase, iAction, pAction->cachePayload.pPackage->sczId, pAction->cachePayload.pPayload->sczKey, pAction->cachePayload.sczUnverifiedPath, pAction->cachePayload.fMove ? L"move" : L"copy", LoggingBoolToString(pAction->fSkipUntilRetried), pAction->cachePayload.iTryAgainAction);
3086 break;
3087
3088 case BURN_CACHE_ACTION_TYPE_CHECKPOINT: 2499 case BURN_CACHE_ACTION_TYPE_CHECKPOINT:
3089 LogStringLine(PlanDumpLevel, "%ls action[%u]: CHECKPOINT id: %u", wzBase, iAction, pAction->checkpoint.dwId); 2500 LogStringLine(PlanDumpLevel, "%ls action[%u]: CHECKPOINT id: %u", wzBase, iAction, pAction->checkpoint.dwId);
3090 break; 2501 break;
3091 2502
3092 case BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER:
3093 LogStringLine(PlanDumpLevel, "%ls action[%u]: EXTRACT_CONTAINER id: %ls, working path: %ls, skip until retried: %hs, skip until acquired by action: %u", wzBase, iAction, pAction->extractContainer.pContainer->sczId, pAction->extractContainer.sczContainerUnverifiedPath, LoggingBoolToString(pAction->fSkipUntilRetried), pAction->extractContainer.iSkipUntilAcquiredByAction);
3094 for (DWORD j = 0; j < pAction->extractContainer.cPayloads; j++)
3095 {
3096 LogStringLine(PlanDumpLevel, " extract package id: %ls, payload id: %ls, working path: %ls", pAction->extractContainer.rgPayloads[j].pPackage->sczId, pAction->extractContainer.rgPayloads[j].pPayload->sczKey, pAction->extractContainer.rgPayloads[j].sczUnverifiedPath);
3097 }
3098 break;
3099
3100 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE: 2503 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
3101 LogStringLine(PlanDumpLevel, "%ls action[%u]: LAYOUT_BUNDLE working path: %ls, layout directory: %ls, exe name: %ls, skip until retried: %hs", wzBase, iAction, pAction->bundleLayout.sczUnverifiedPath, pAction->bundleLayout.sczLayoutDirectory, pAction->bundleLayout.sczExecutableName, LoggingBoolToString(pAction->fSkipUntilRetried)); 2504 LogStringLine(PlanDumpLevel, "%ls action[%u]: LAYOUT_BUNDLE working path: %ls, exe name: %ls", wzBase, iAction, pAction->bundleLayout.sczUnverifiedPath, pAction->bundleLayout.sczExecutableName);
3102 break;
3103
3104 case BURN_CACHE_ACTION_TYPE_LAYOUT_CONTAINER:
3105 LogStringLine(PlanDumpLevel, "%ls action[%u]: LAYOUT_CONTAINER package id: %ls, container id: %ls, working path: %ls, layout directory: %ls, operation: %ls, skip until retried: %hs, retry action: %u", wzBase, iAction, pAction->layoutContainer.pPackage ? pAction->layoutContainer.pPackage->sczId : L"", pAction->layoutContainer.pContainer->sczId, pAction->layoutContainer.sczUnverifiedPath, pAction->layoutContainer.sczLayoutDirectory, pAction->layoutContainer.fMove ? L"move" : L"copy", LoggingBoolToString(pAction->fSkipUntilRetried), pAction->layoutContainer.iTryAgainAction);
3106 break;
3107
3108 case BURN_CACHE_ACTION_TYPE_LAYOUT_PAYLOAD:
3109 LogStringLine(PlanDumpLevel, "%ls action[%u]: LAYOUT_PAYLOAD package id: %ls, payload id: %ls, working path: %ls, layout directory: %ls, operation: %ls, skip until retried: %hs, retry action: %u", wzBase, iAction, pAction->layoutPayload.pPackage ? pAction->layoutPayload.pPackage->sczId : L"", pAction->layoutPayload.pPayload->sczKey, pAction->layoutPayload.sczUnverifiedPath, pAction->layoutPayload.sczLayoutDirectory, pAction->layoutPayload.fMove ? L"move" : L"copy", LoggingBoolToString(pAction->fSkipUntilRetried), pAction->layoutPayload.iTryAgainAction);
3110 break; 2505 break;
3111 2506
3112 case BURN_CACHE_ACTION_TYPE_PACKAGE_START: 2507 case BURN_CACHE_ACTION_TYPE_CONTAINER:
3113 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE_START id: %ls, plan index for skip: %u, payloads to cache: %u, bytes to cache: %llu, skip until retried: %hs", wzBase, iAction, pAction->packageStart.pPackage->sczId, pAction->packageStart.iPackageCompleteAction, pAction->packageStart.cCachePayloads, pAction->packageStart.qwCachePayloadSizeTotal, LoggingBoolToString(pAction->fSkipUntilRetried)); 2508 LogStringLine(PlanDumpLevel, "%ls action[%u]: CONTAINER container id: %ls, working path: %ls", wzBase, iAction, pAction->container.pContainer->sczId, pAction->container.pContainer->sczUnverifiedPath);
3114 break; 2509 break;
3115 2510
3116 case BURN_CACHE_ACTION_TYPE_PACKAGE_STOP: 2511 case BURN_CACHE_ACTION_TYPE_PACKAGE:
3117 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE_STOP id: %ls, skip until retried: %hs", wzBase, iAction, pAction->packageStop.pPackage->sczId, LoggingBoolToString(pAction->fSkipUntilRetried)); 2512 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE id: %ls", wzBase, iAction, pAction->package.pPackage->sczId);
3118 break; 2513 break;
3119 2514
3120 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE: 2515 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE:
3121 LogStringLine(PlanDumpLevel, "%ls action[%u]: ROLLBACK_PACKAGE id: %ls, skip until retried: %hs", wzBase, iAction, pAction->rollbackPackage.pPackage->sczId, LoggingBoolToString(pAction->fSkipUntilRetried)); 2516 LogStringLine(PlanDumpLevel, "%ls action[%u]: ROLLBACK_PACKAGE id: %ls", wzBase, iAction, pAction->rollbackPackage.pPackage->sczId);
3122 break; 2517 break;
3123 2518
3124 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 2519 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
3125 LogStringLine(PlanDumpLevel, "%ls action[%u]: SIGNAL_SYNCPOINT event handle: 0x%p, skip until retried: %hs", wzBase, iAction, pAction->syncpoint.hEvent, LoggingBoolToString(pAction->fSkipUntilRetried)); 2520 LogStringLine(PlanDumpLevel, "%ls action[%u]: SIGNAL_SYNCPOINT event handle: 0x%p", wzBase, iAction, pAction->syncpoint.hEvent);
3126 break;
3127
3128 case BURN_CACHE_ACTION_TYPE_TRANSACTION_BOUNDARY:
3129 LogStringLine(PlanDumpLevel, "%ls action[%u]: TRANSACTION_BOUNDARY id: %ls, event handle: 0x%p, vital: %ls, transaction: %ls", wzBase, iAction, pAction->rollbackBoundary.pRollbackBoundary->sczId, pAction->rollbackBoundary.hEvent, pAction->rollbackBoundary.pRollbackBoundary->fVital ? L"yes" : L"no", pAction->rollbackBoundary.pRollbackBoundary->fTransaction ? L"yes" : L"no");
3130 break; 2521 break;
3131 2522
3132 default: 2523 default:
@@ -3222,6 +2613,10 @@ extern "C" void PlanDump(
3222 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine)); 2613 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine));
3223 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback)); 2614 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback));
3224 LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize); 2615 LogStringLine(PlanDumpLevel, " estimated size: %llu", pPlan->qwEstimatedSize);
2616 if (pPlan->sczLayoutDirectory)
2617 {
2618 LogStringLine(PlanDumpLevel, " layout directory: %ls", pPlan->sczLayoutDirectory);
2619 }
3225 2620
3226 LogStringLine(PlanDumpLevel, "Plan cache size: %llu", pPlan->qwCacheSizeTotal); 2621 LogStringLine(PlanDumpLevel, "Plan cache size: %llu", pPlan->qwCacheSizeTotal);
3227 for (DWORD i = 0; i < pPlan->cCacheActions; ++i) 2622 for (DWORD i = 0; i < pPlan->cCacheActions; ++i)
diff --git a/src/engine/plan.h b/src/engine/plan.h
index 0024b0aa..4ba2df6a 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -38,17 +38,10 @@ enum BURN_CACHE_ACTION_TYPE
38 BURN_CACHE_ACTION_TYPE_NONE, 38 BURN_CACHE_ACTION_TYPE_NONE,
39 BURN_CACHE_ACTION_TYPE_CHECKPOINT, 39 BURN_CACHE_ACTION_TYPE_CHECKPOINT,
40 BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE, 40 BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE,
41 BURN_CACHE_ACTION_TYPE_PACKAGE_START, 41 BURN_CACHE_ACTION_TYPE_PACKAGE,
42 BURN_CACHE_ACTION_TYPE_PACKAGE_STOP,
43 BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE, 42 BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE,
44 BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT, 43 BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT,
45 BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, 44 BURN_CACHE_ACTION_TYPE_CONTAINER,
46 BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER,
47 BURN_CACHE_ACTION_TYPE_LAYOUT_CONTAINER,
48 BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD,
49 BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD,
50 BURN_CACHE_ACTION_TYPE_LAYOUT_PAYLOAD,
51 BURN_CACHE_ACTION_TYPE_TRANSACTION_BOUNDARY,
52}; 45};
53 46
54enum BURN_EXECUTE_ACTION_TYPE 47enum BURN_EXECUTE_ACTION_TYPE
@@ -78,13 +71,6 @@ enum BURN_CLEAN_ACTION_TYPE
78 71
79// structs 72// structs
80 73
81typedef struct _BURN_EXTRACT_PAYLOAD
82{
83 BURN_PACKAGE* pPackage;
84 BURN_PAYLOAD* pPayload;
85 LPWSTR sczUnverifiedPath;
86} BURN_EXTRACT_PAYLOAD;
87
88typedef struct _BURN_DEPENDENT_REGISTRATION_ACTION 74typedef struct _BURN_DEPENDENT_REGISTRATION_ACTION
89{ 75{
90 BURN_DEPENDENT_REGISTRATION_ACTION_TYPE type; 76 BURN_DEPENDENT_REGISTRATION_ACTION_TYPE type;
@@ -111,7 +97,6 @@ typedef struct _BURN_CACHE_PAYLOAD_PROGRESS
111typedef struct _BURN_CACHE_ACTION 97typedef struct _BURN_CACHE_ACTION
112{ 98{
113 BURN_CACHE_ACTION_TYPE type; 99 BURN_CACHE_ACTION_TYPE type;
114 BOOL fSkipUntilRetried;
115 union 100 union
116 { 101 {
117 struct 102 struct
@@ -121,21 +106,14 @@ typedef struct _BURN_CACHE_ACTION
121 struct 106 struct
122 { 107 {
123 LPWSTR sczExecutableName; 108 LPWSTR sczExecutableName;
124 LPWSTR sczLayoutDirectory;
125 LPWSTR sczUnverifiedPath; 109 LPWSTR sczUnverifiedPath;
126 DWORD64 qwBundleSize; 110 DWORD64 qwBundleSize;
111 BURN_PAYLOAD_GROUP* pPayloadGroup;
127 } bundleLayout; 112 } bundleLayout;
128 struct 113 struct
129 { 114 {
130 BURN_PACKAGE* pPackage; 115 BURN_PACKAGE* pPackage;
131 DWORD cCachePayloads; 116 } package;
132 DWORD64 qwCachePayloadSizeTotal;
133 DWORD iPackageCompleteAction;
134 } packageStart;
135 struct
136 {
137 BURN_PACKAGE* pPackage;
138 } packageStop;
139 struct 117 struct
140 { 118 {
141 BURN_PACKAGE* pPackage; 119 BURN_PACKAGE* pPackage;
@@ -147,62 +125,7 @@ typedef struct _BURN_CACHE_ACTION
147 struct 125 struct
148 { 126 {
149 BURN_CONTAINER* pContainer; 127 BURN_CONTAINER* pContainer;
150 DWORD iProgress; 128 } container;
151 LPWSTR sczUnverifiedPath;
152 } resolveContainer;
153 struct
154 {
155 BURN_CONTAINER* pContainer;
156 DWORD iSkipUntilAcquiredByAction;
157 LPWSTR sczContainerUnverifiedPath;
158
159 BURN_EXTRACT_PAYLOAD* rgPayloads;
160 DWORD cPayloads;
161 } extractContainer;
162 struct
163 {
164 BURN_PACKAGE* pPackage;
165 BURN_CONTAINER* pContainer;
166 DWORD iProgress;
167 DWORD iTryAgainAction;
168 DWORD cTryAgainAttempts;
169 LPWSTR sczLayoutDirectory;
170 LPWSTR sczUnverifiedPath;
171 BOOL fMove;
172 } layoutContainer;
173 struct
174 {
175 BURN_PACKAGE* pPackage;
176 BURN_PAYLOAD* pPayload;
177 DWORD iProgress;
178 LPWSTR sczUnverifiedPath;
179 } resolvePayload;
180 struct
181 {
182 BURN_PACKAGE* pPackage;
183 BURN_PAYLOAD* pPayload;
184 DWORD iProgress;
185 DWORD iTryAgainAction;
186 DWORD cTryAgainAttempts;
187 LPWSTR sczUnverifiedPath;
188 BOOL fMove;
189 } cachePayload;
190 struct
191 {
192 BURN_PACKAGE* pPackage;
193 BURN_PAYLOAD* pPayload;
194 DWORD iProgress;
195 DWORD iTryAgainAction;
196 DWORD cTryAgainAttempts;
197 LPWSTR sczLayoutDirectory;
198 LPWSTR sczUnverifiedPath;
199 BOOL fMove;
200 } layoutPayload;
201 struct
202 {
203 BURN_ROLLBACK_BOUNDARY* pRollbackBoundary;
204 HANDLE hEvent;
205 } rollbackBoundary;
206 }; 129 };
207} BURN_CACHE_ACTION; 130} BURN_CACHE_ACTION;
208 131
@@ -306,6 +229,7 @@ typedef struct _BURN_CLEAN_ACTION
306typedef struct _BURN_PLAN 229typedef struct _BURN_PLAN
307{ 230{
308 BOOTSTRAPPER_ACTION action; 231 BOOTSTRAPPER_ACTION action;
232 BURN_PAYLOADS* pPayloads; // points directly into parent the ENGINE_STATE.
309 LPWSTR wzBundleId; // points directly into parent the ENGINE_STATE. 233 LPWSTR wzBundleId; // points directly into parent the ENGINE_STATE.
310 LPWSTR wzBundleProviderKey; // points directly into parent the ENGINE_STATE. 234 LPWSTR wzBundleProviderKey; // points directly into parent the ENGINE_STATE.
311 BOOL fPerMachine; 235 BOOL fPerMachine;
@@ -315,6 +239,7 @@ typedef struct _BURN_PLAN
315 BOOL fDisableRollback; 239 BOOL fDisableRollback;
316 BOOL fAffectedMachineState; 240 BOOL fAffectedMachineState;
317 BOOL fIgnoreAllDependents; 241 BOOL fIgnoreAllDependents;
242 LPWSTR sczLayoutDirectory;
318 243
319 DWORD64 qwCacheSizeTotal; 244 DWORD64 qwCacheSizeTotal;
320 245
@@ -369,7 +294,9 @@ typedef struct _BURN_PLAN
369 294
370void PlanReset( 295void PlanReset(
371 __in BURN_PLAN* pPlan, 296 __in BURN_PLAN* pPlan,
372 __in BURN_PACKAGES* pPackages 297 __in BURN_CONTAINERS* pContainers,
298 __in BURN_PACKAGES* pPackages,
299 __in BURN_PAYLOAD_GROUP* pLayoutPayloads
373 ); 300 );
374void PlanUninitializeExecuteAction( 301void PlanUninitializeExecuteAction(
375 __in BURN_EXECUTE_ACTION* pExecuteAction 302 __in BURN_EXECUTE_ACTION* pExecuteAction
@@ -393,8 +320,7 @@ HRESULT PlanLayoutBundle(
393 __in_z LPCWSTR wzExecutableName, 320 __in_z LPCWSTR wzExecutableName,
394 __in DWORD64 qwBundleSize, 321 __in DWORD64 qwBundleSize,
395 __in BURN_VARIABLES* pVariables, 322 __in BURN_VARIABLES* pVariables,
396 __in BURN_PAYLOADS* pPayloads, 323 __in BURN_PAYLOAD_GROUP* pLayoutPayloads
397 __out_z LPWSTR* psczLayoutDirectory
398 ); 324 );
399HRESULT PlanForwardCompatibleBundles( 325HRESULT PlanForwardCompatibleBundles(
400 __in BURN_USER_EXPERIENCE* pUX, 326 __in BURN_USER_EXPERIENCE* pUX,
@@ -410,8 +336,7 @@ HRESULT PlanPackages(
410 __in BURN_LOGGING* pLog, 336 __in BURN_LOGGING* pLog,
411 __in BURN_VARIABLES* pVariables, 337 __in BURN_VARIABLES* pVariables,
412 __in BOOTSTRAPPER_DISPLAY display, 338 __in BOOTSTRAPPER_DISPLAY display,
413 __in BOOTSTRAPPER_RELATION_TYPE relationType, 339 __in BOOTSTRAPPER_RELATION_TYPE relationType
414 __in_z_opt LPCWSTR wzLayoutDirectory
415 ); 340 );
416HRESULT PlanRegistration( 341HRESULT PlanRegistration(
417 __in BURN_PLAN* pPlan, 342 __in BURN_PLAN* pPlan,
@@ -438,10 +363,13 @@ HRESULT PlanUpdateBundle(
438 __in BOOTSTRAPPER_DISPLAY display, 363 __in BOOTSTRAPPER_DISPLAY display,
439 __in BOOTSTRAPPER_RELATION_TYPE relationType 364 __in BOOTSTRAPPER_RELATION_TYPE relationType
440 ); 365 );
366HRESULT PlanLayoutContainer(
367 __in BURN_PLAN* pPlan,
368 __in BURN_CONTAINER* pContainer
369 );
441HRESULT PlanLayoutPackage( 370HRESULT PlanLayoutPackage(
442 __in BURN_PLAN* pPlan, 371 __in BURN_PLAN* pPlan,
443 __in BURN_PACKAGE* pPackage, 372 __in BURN_PACKAGE* pPackage
444 __in_z_opt LPCWSTR wzLayoutDirectory
445 ); 373 );
446HRESULT PlanExecutePackage( 374HRESULT PlanExecutePackage(
447 __in BOOL fPerMachine, 375 __in BOOL fPerMachine,
diff --git a/src/engine/pseudobundle.cpp b/src/engine/pseudobundle.cpp
index 73fbb019..db25096b 100644
--- a/src/engine/pseudobundle.cpp
+++ b/src/engine/pseudobundle.cpp
@@ -26,6 +26,7 @@ extern "C" HRESULT PseudoBundleInitialize(
26{ 26{
27 HRESULT hr = S_OK; 27 HRESULT hr = S_OK;
28 LPWSTR sczRelationTypeCommandLineSwitch = NULL; 28 LPWSTR sczRelationTypeCommandLineSwitch = NULL;
29 BURN_PAYLOAD* pPayload = NULL;
29 30
30 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType); 31 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
31 if (wzRelationTypeCommandLine) 32 if (wzRelationTypeCommandLine)
@@ -34,41 +35,40 @@ extern "C" HRESULT PseudoBundleInitialize(
34 } 35 }
35 36
36 // Initialize the single payload, and fill out all the necessary fields 37 // Initialize the single payload, and fill out all the necessary fields
37 pPackage->rgPayloads = (BURN_PACKAGE_PAYLOAD *)MemAlloc(sizeof(BURN_PACKAGE_PAYLOAD), TRUE); 38 pPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*), TRUE);
38 ExitOnNull(pPackage->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of related bundle struct"); 39 ExitOnNull(pPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of related bundle struct");
39 pPackage->cPayloads = 1; 40 pPackage->payloads.cPayloads = 1;
40 41
41 pPackage->rgPayloads->pPayload = (BURN_PAYLOAD *)MemAlloc(sizeof(BURN_PAYLOAD), TRUE); 42 pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE);
42 ExitOnNull(pPackage->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct"); 43 ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct");
43 pPackage->rgPayloads->pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; 44 pPackage->payloads.rgpPayloads[0] = pPayload;
44 pPackage->rgPayloads->pPayload->qwFileSize = qwSize; 45 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
46 pPayload->qwFileSize = qwSize;
45 47
46 hr = StrAllocString(&pPackage->rgPayloads->pPayload->sczKey, wzId, 0); 48 hr = StrAllocString(&pPayload->sczKey, wzId, 0);
47 ExitOnFailure(hr, "Failed to copy key for pseudo bundle payload."); 49 ExitOnFailure(hr, "Failed to copy key for pseudo bundle payload.");
48 50
49 hr = StrAllocString(&pPackage->rgPayloads->pPayload->sczFilePath, wzFilePath, 0); 51 hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0);
50 ExitOnFailure(hr, "Failed to copy filename for pseudo bundle."); 52 ExitOnFailure(hr, "Failed to copy filename for pseudo bundle.");
51 53
52 hr = StrAllocString(&pPackage->rgPayloads->pPayload->sczSourcePath, wzLocalSource, 0); 54 hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0);
53 ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle."); 55 ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle.");
54 56
55 if (wzDownloadSource && *wzDownloadSource) 57 if (wzDownloadSource && *wzDownloadSource)
56 { 58 {
57 hr = StrAllocString(&pPackage->rgPayloads->pPayload->downloadSource.sczUrl, wzDownloadSource, 0); 59 hr = StrAllocString(&pPayload->downloadSource.sczUrl, wzDownloadSource, 0);
58 ExitOnFailure(hr, "Failed to copy download source for pseudo bundle."); 60 ExitOnFailure(hr, "Failed to copy download source for pseudo bundle.");
59 } 61 }
60 62
61 if (pbHash) 63 if (pbHash)
62 { 64 {
63 pPackage->rgPayloads->pPayload->pbHash = static_cast<BYTE*>(MemAlloc(cbHash, FALSE)); 65 pPayload->pbHash = static_cast<BYTE*>(MemAlloc(cbHash, FALSE));
64 ExitOnNull(pPackage->rgPayloads->pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for pseudo bundle payload hash."); 66 ExitOnNull(pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for pseudo bundle payload hash.");
65 67
66 pPackage->rgPayloads->pPayload->cbHash = cbHash; 68 pPayload->cbHash = cbHash;
67 memcpy_s(pPackage->rgPayloads->pPayload->pbHash, pPackage->rgPayloads->pPayload->cbHash, pbHash, cbHash); 69 memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
68 } 70 }
69 71
70 pPackage->rgPayloads->fCached = fCached;
71
72 pPackage->Exe.fPseudoBundle = TRUE; 72 pPackage->Exe.fPseudoBundle = TRUE;
73 73
74 pPackage->type = BURN_PACKAGE_TYPE_EXE; 74 pPackage->type = BURN_PACKAGE_TYPE_EXE;
@@ -171,44 +171,13 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
171 LPWSTR sczArguments = NULL; 171 LPWSTR sczArguments = NULL;
172 172
173 // Initialize the payloads, and copy the necessary fields. 173 // Initialize the payloads, and copy the necessary fields.
174 pPassthroughPackage->rgPayloads = (BURN_PACKAGE_PAYLOAD *)MemAlloc(sizeof(BURN_PACKAGE_PAYLOAD) * pPackage->cPayloads, TRUE); 174 pPassthroughPackage->payloads.rgpPayloads = (BURN_PAYLOAD**)MemAlloc(sizeof(BURN_PAYLOAD*) * pPackage->payloads.cPayloads, TRUE);
175 ExitOnNull(pPassthroughPackage->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle."); 175 ExitOnNull(pPassthroughPackage->payloads.rgpPayloads, hr, E_OUTOFMEMORY, "Failed to allocate space for burn package payload inside of passthrough bundle.");
176 pPassthroughPackage->cPayloads = pPackage->cPayloads; 176 pPassthroughPackage->payloads.cPayloads = pPackage->payloads.cPayloads;
177 177
178 for (DWORD iPayload = 0; iPayload < pPackage->cPayloads; ++iPayload) 178 for (DWORD iPayload = 0; iPayload < pPackage->payloads.cPayloads; ++iPayload)
179 { 179 {
180 BURN_PACKAGE_PAYLOAD* pPayload = pPackage->rgPayloads + iPayload; 180 pPassthroughPackage->payloads.rgpPayloads[iPayload] = pPackage->payloads.rgpPayloads[iPayload];
181
182 pPassthroughPackage->rgPayloads[iPayload].pPayload = (BURN_PAYLOAD *)MemAlloc(sizeof(BURN_PAYLOAD), TRUE);
183 ExitOnNull(pPassthroughPackage->rgPayloads[iPayload].pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of related bundle struct");
184 pPassthroughPackage->rgPayloads[iPayload].pPayload->packaging = pPayload->pPayload->packaging;
185 pPassthroughPackage->rgPayloads[iPayload].pPayload->qwFileSize = pPayload->pPayload->qwFileSize;
186
187 hr = StrAllocString(&pPassthroughPackage->rgPayloads[iPayload].pPayload->sczKey, pPayload->pPayload->sczKey, 0);
188 ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle payload.");
189
190 hr = StrAllocString(&pPassthroughPackage->rgPayloads[iPayload].pPayload->sczFilePath, pPayload->pPayload->sczFilePath, 0);
191 ExitOnFailure(hr, "Failed to copy filename for passthrough pseudo bundle.");
192
193 hr = StrAllocString(&pPassthroughPackage->rgPayloads[iPayload].pPayload->sczSourcePath, pPayload->pPayload->sczSourcePath, 0);
194 ExitOnFailure(hr, "Failed to copy local source path for passthrough pseudo bundle.");
195
196 if (pPayload->pPayload->downloadSource.sczUrl)
197 {
198 hr = StrAllocString(&pPassthroughPackage->rgPayloads[iPayload].pPayload->downloadSource.sczUrl, pPayload->pPayload->downloadSource.sczUrl, 0);
199 ExitOnFailure(hr, "Failed to copy download source for passthrough pseudo bundle.");
200 }
201
202 if (pPayload->pPayload->pbHash)
203 {
204 pPassthroughPackage->rgPayloads[iPayload].pPayload->pbHash = static_cast<BYTE*>(MemAlloc(pPayload->pPayload->cbHash, FALSE));
205 ExitOnNull(pPassthroughPackage->rgPayloads[iPayload].pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for pseudo bundle payload hash.");
206
207 pPassthroughPackage->rgPayloads[iPayload].pPayload->cbHash = pPayload->pPayload->cbHash;
208 memcpy_s(pPassthroughPackage->rgPayloads[iPayload].pPayload->pbHash, pPassthroughPackage->rgPayloads[iPayload].pPayload->cbHash, pPayload->pPayload->pbHash, pPayload->pPayload->cbHash);
209 }
210
211 pPassthroughPackage->rgPayloads[iPayload].fCached = pPayload->fCached;
212 } 181 }
213 182
214 pPassthroughPackage->Exe.fPseudoBundle = TRUE; 183 pPassthroughPackage->Exe.fPseudoBundle = TRUE;
diff --git a/src/engine/relatedbundle.cpp b/src/engine/relatedbundle.cpp
index 6953c678..a79be020 100644
--- a/src/engine/relatedbundle.cpp
+++ b/src/engine/relatedbundle.cpp
@@ -80,7 +80,14 @@ extern "C" void RelatedBundlesUninitialize(
80 { 80 {
81 for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) 81 for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i)
82 { 82 {
83 PackageUninitialize(&pRelatedBundles->rgRelatedBundles[i].package); 83 BURN_PACKAGE* pPackage = &pRelatedBundles->rgRelatedBundles[i].package;
84
85 for (DWORD j = 0; j < pPackage->payloads.cPayloads; ++j)
86 {
87 PayloadUninitialize(pPackage->payloads.rgpPayloads[j]);
88 }
89
90 PackageUninitialize(pPackage);
84 ReleaseStr(pRelatedBundles->rgRelatedBundles[i].sczTag); 91 ReleaseStr(pRelatedBundles->rgRelatedBundles[i].sczTag);
85 } 92 }
86 93
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp
index c1641675..b6bd65dc 100644
--- a/src/engine/userexperience.cpp
+++ b/src/engine/userexperience.cpp
@@ -62,7 +62,7 @@ extern "C" HRESULT UserExperienceParseFromXml(
62 } 62 }
63 63
64 // parse payloads 64 // parse payloads
65 hr = PayloadsParseFromXml(&pUserExperience->payloads, NULL, pixnUserExperienceNode); 65 hr = PayloadsParseFromXml(&pUserExperience->payloads, NULL, NULL, pixnUserExperienceNode);
66 ExitOnFailure(hr, "Failed to parse user experience payloads."); 66 ExitOnFailure(hr, "Failed to parse user experience payloads.");
67 67
68 // make sure we have at least one payload 68 // make sure we have at least one payload
diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp
index 2ebbca74..aa9deaf6 100644
--- a/src/test/BurnUnitTest/PlanTest.cpp
+++ b/src/test/BurnUnitTest/PlanTest.cpp
@@ -54,47 +54,30 @@ namespace Bootstrapper
54 54
55 BOOL fRollback = FALSE; 55 BOOL fRollback = FALSE;
56 DWORD dwIndex = 0; 56 DWORD dwIndex = 0;
57 DWORD dwPackageStart = 0;
58 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 57 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
59 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 6, 2, 33743, FALSE); 58 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
60 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE); 59 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
61 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 6);
62 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
63 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart);
64 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
65 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
66 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9); 60 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
67 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", 14, 2, 33743, FALSE); 61 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
68 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE); 62 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
69 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2);
70 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageB", L"PackageB", TRUE, FALSE, dwPackageStart);
71 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageB", L"cablKtJUKxAbhSMIBwQU6vJ_CDsIkE", TRUE, FALSE, dwPackageStart);
72 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageB", FALSE);
73 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
74 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14); 63 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
75 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageC", 22, 2, 33743, FALSE); 64 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageC");
76 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE); 65 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
77 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2); 66 Assert::Equal(dwIndex, pPlan->cCacheActions);
78 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageC", L"PackageC", TRUE, FALSE, dwPackageStart);
79 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageC", L"cab3wekki1le1R8RPDV2B8_g8jcjZc", TRUE, FALSE, dwPackageStart);
80 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageC", FALSE);
81 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
82 Assert::Equal(24ul, pPlan->cCacheActions);
83 67
84 fRollback = TRUE; 68 fRollback = TRUE;
85 dwIndex = 0; 69 dwIndex = 0;
86 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 70 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
87 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
88 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 71 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
89 72
90 Assert::Equal(107082ull, pPlan->qwEstimatedSize); 73 Assert::Equal(107082ull, pPlan->qwEstimatedSize);
91 Assert::Equal(101229ull, pPlan->qwCacheSizeTotal); 74 Assert::Equal(202458ull, pPlan->qwCacheSizeTotal);
92 75
93 fRollback = FALSE; 76 fRollback = FALSE;
94 dwIndex = 0; 77 dwIndex = 0;
95 DWORD dwExecuteCheckpointId = 2; 78 DWORD dwExecuteCheckpointId = 2;
96 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 79 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
97 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[7].syncpoint.hEvent); 80 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
98 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 81 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
99 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 82 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
100 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 83 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
@@ -107,7 +90,7 @@ namespace Bootstrapper
107 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE); 90 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
108 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 91 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
109 ValidateExecuteBeginMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); 92 ValidateExecuteBeginMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
110 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[15].syncpoint.hEvent); 93 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[5].syncpoint.hEvent);
111 dwExecuteCheckpointId += 1; // cache checkpoints 94 dwExecuteCheckpointId += 1; // cache checkpoints
112 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 95 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
113 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 96 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -116,7 +99,7 @@ namespace Bootstrapper
116 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 99 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
117 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER); 100 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", BURN_DEPENDENCY_ACTION_REGISTER);
118 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 101 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
119 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent); 102 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[8].syncpoint.hEvent);
120 dwExecuteCheckpointId += 1; // cache checkpoints 103 dwExecuteCheckpointId += 1; // cache checkpoints
121 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 104 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
122 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 105 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -314,30 +297,24 @@ namespace Bootstrapper
314 297
315 BOOL fRollback = FALSE; 298 BOOL fRollback = FALSE;
316 DWORD dwIndex = 0; 299 DWORD dwIndex = 0;
317 DWORD dwPackageStart = 0;
318 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 300 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
319 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); 301 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
320 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); 302 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
321 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
322 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart);
323 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
324 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
325 Assert::Equal(dwIndex, pPlan->cCacheActions); 303 Assert::Equal(dwIndex, pPlan->cCacheActions);
326 304
327 fRollback = TRUE; 305 fRollback = TRUE;
328 dwIndex = 0; 306 dwIndex = 0;
329 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 307 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
330 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
331 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 308 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
332 309
333 Assert::Equal(35694ull, pPlan->qwEstimatedSize); 310 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
334 Assert::Equal(33743ull, pPlan->qwCacheSizeTotal); 311 Assert::Equal(67486ull, pPlan->qwCacheSizeTotal);
335 312
336 fRollback = FALSE; 313 fRollback = FALSE;
337 dwIndex = 0; 314 dwIndex = 0;
338 DWORD dwExecuteCheckpointId = 2; 315 DWORD dwExecuteCheckpointId = 2;
339 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 316 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
340 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent); 317 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
341 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 318 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
342 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 319 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
343 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 320 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
@@ -401,14 +378,9 @@ namespace Bootstrapper
401 378
402 BOOL fRollback = FALSE; 379 BOOL fRollback = FALSE;
403 DWORD dwIndex = 0; 380 DWORD dwIndex = 0;
404 DWORD dwPackageStart = 0;
405 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 381 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
406 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); 382 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
407 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); 383 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
408 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
409 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart);
410 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
411 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
412 Assert::Equal(dwIndex, pPlan->cCacheActions); 384 Assert::Equal(dwIndex, pPlan->cCacheActions);
413 385
414 fRollback = TRUE; 386 fRollback = TRUE;
@@ -416,13 +388,13 @@ namespace Bootstrapper
416 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 388 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
417 389
418 Assert::Equal(33743ull, pPlan->qwEstimatedSize); 390 Assert::Equal(33743ull, pPlan->qwEstimatedSize);
419 Assert::Equal(33743ull, pPlan->qwCacheSizeTotal); 391 Assert::Equal(67486ull, pPlan->qwCacheSizeTotal);
420 392
421 fRollback = FALSE; 393 fRollback = FALSE;
422 dwIndex = 0; 394 dwIndex = 0;
423 DWORD dwExecuteCheckpointId = 2; 395 DWORD dwExecuteCheckpointId = 2;
424 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 396 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
425 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent); 397 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
426 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 398 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
427 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 399 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
428 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 400 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -475,30 +447,24 @@ namespace Bootstrapper
475 447
476 BOOL fRollback = FALSE; 448 BOOL fRollback = FALSE;
477 DWORD dwIndex = 0; 449 DWORD dwIndex = 0;
478 DWORD dwPackageStart = 0;
479 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 450 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
480 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 5, 2, 33743, FALSE); 451 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
481 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2); 452 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
482 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
483 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab9Ins_fTP3wNwq5Gxo41ch5VUPaQ", TRUE, FALSE, dwPackageStart);
484 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
485 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
486 Assert::Equal(dwIndex, pPlan->cCacheActions); 453 Assert::Equal(dwIndex, pPlan->cCacheActions);
487 454
488 fRollback = TRUE; 455 fRollback = TRUE;
489 dwIndex = 0; 456 dwIndex = 0;
490 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 457 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
491 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
492 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 458 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
493 459
494 Assert::Equal(35694ull, pPlan->qwEstimatedSize); 460 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
495 Assert::Equal(33743ull, pPlan->qwCacheSizeTotal); 461 Assert::Equal(67486ull, pPlan->qwCacheSizeTotal);
496 462
497 fRollback = FALSE; 463 fRollback = FALSE;
498 dwIndex = 0; 464 dwIndex = 0;
499 DWORD dwExecuteCheckpointId = 2; 465 DWORD dwExecuteCheckpointId = 2;
500 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 466 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
501 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent); 467 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
502 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 468 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
503 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 469 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
504 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 470 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
@@ -759,36 +725,28 @@ namespace Bootstrapper
759 725
760 BOOL fRollback = FALSE; 726 BOOL fRollback = FALSE;
761 DWORD dwIndex = 0; 727 DWORD dwIndex = 0;
762 DWORD dwPackageStart = 0;
763 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 728 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
764 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PatchA", 4, 1, 20480, FALSE); 729 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
765 ValidateCacheAcquirePayload(pPlan, fRollback, dwIndex++, L"PatchA", L"PatchA", FALSE); 730 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
766 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PatchA", L"PatchA", TRUE, FALSE, dwPackageStart);
767 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PatchA", FALSE);
768 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
769 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2); 731 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2);
770 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 10, 1, 32768, FALSE); 732 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
771 ValidateCacheAcquirePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", FALSE); 733 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
772 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
773 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
774 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
775 Assert::Equal(dwIndex, pPlan->cCacheActions); 734 Assert::Equal(dwIndex, pPlan->cCacheActions);
776 735
777 fRollback = TRUE; 736 fRollback = TRUE;
778 dwIndex = 0; 737 dwIndex = 0;
779 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2); 738 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2);
780 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
781 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 739 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
782 740
783 Assert::Equal(3055111ull, pPlan->qwEstimatedSize); 741 Assert::Equal(3055111ull, pPlan->qwEstimatedSize);
784 Assert::Equal(53248ull, pPlan->qwCacheSizeTotal); 742 Assert::Equal(106496ull, pPlan->qwCacheSizeTotal);
785 743
786 fRollback = FALSE; 744 fRollback = FALSE;
787 dwIndex = 0; 745 dwIndex = 0;
788 DWORD dwExecuteCheckpointId = 3; 746 DWORD dwExecuteCheckpointId = 3;
789 BURN_EXECUTE_ACTION* pExecuteAction = NULL; 747 BURN_EXECUTE_ACTION* pExecuteAction = NULL;
790 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 748 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
791 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[11].syncpoint.hEvent); 749 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[5].syncpoint.hEvent);
792 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 750 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
793 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 751 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
794 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER); 752 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
@@ -797,7 +755,7 @@ namespace Bootstrapper
797 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 755 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
798 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER); 756 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", BURN_DEPENDENCY_ACTION_REGISTER);
799 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 757 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
800 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[5].syncpoint.hEvent); 758 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[2].syncpoint.hEvent);
801 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 759 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
802 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 760 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
803 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_REGISTER); 761 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", BURN_DEPENDENCY_ACTION_REGISTER);
@@ -983,7 +941,7 @@ namespace Bootstrapper
983 BURN_REGISTRATION* pRegistration = &pEngineState->registration; 941 BURN_REGISTRATION* pRegistration = &pEngineState->registration;
984 942
985 DetectReset(pRegistration, &pEngineState->packages); 943 DetectReset(pRegistration, &pEngineState->packages);
986 PlanReset(&pEngineState->plan, &pEngineState->packages); 944 PlanReset(&pEngineState->plan, &pEngineState->containers, &pEngineState->packages, &pEngineState->layoutPayloads);
987 945
988 hr = DepDependencyArrayAlloc(&pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, pRegistration->sczProviderKey, NULL); 946 hr = DepDependencyArrayAlloc(&pRegistration->rgIgnoredDependencies, &pRegistration->cIgnoredDependencies, pRegistration->sczProviderKey, NULL);
989 NativeAssert::Succeeded(hr, "Failed to add the bundle provider key to the list of dependencies to ignore."); 947 NativeAssert::Succeeded(hr, "Failed to add the bundle provider key to the list of dependencies to ignore.");
@@ -1047,11 +1005,6 @@ namespace Bootstrapper
1047 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 1005 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1048 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 1006 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1049 } 1007 }
1050
1051 for (DWORD i = 0; i < pPackage->cPayloads; ++i)
1052 {
1053 pPackage->rgPayloads[i].fCached = TRUE;
1054 }
1055 } 1008 }
1056 1009
1057 void DetectPackageDependent(BURN_PACKAGE* pPackage, LPCWSTR wzId) 1010 void DetectPackageDependent(BURN_PACKAGE* pPackage, LPCWSTR wzId)
@@ -1186,34 +1139,16 @@ namespace Bootstrapper
1186 } 1139 }
1187 } 1140 }
1188 1141
1189 void ValidateCacheAcquireContainer( 1142 void ValidateCacheContainer(
1190 __in BURN_PLAN* pPlan,
1191 __in BOOL fRollback,
1192 __in DWORD dwIndex,
1193 __in LPCWSTR wzContainerId,
1194 __in BOOL fSkipUntilRetried
1195 )
1196 {
1197 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1198 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, pAction->type);
1199 NativeAssert::StringEqual(wzContainerId, pAction->resolveContainer.pContainer->sczId);
1200 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1201 }
1202
1203 void ValidateCacheAcquirePayload(
1204 __in BURN_PLAN* pPlan, 1143 __in BURN_PLAN* pPlan,
1205 __in BOOL fRollback, 1144 __in BOOL fRollback,
1206 __in DWORD dwIndex, 1145 __in DWORD dwIndex,
1207 __in LPCWSTR wzPackageId, 1146 __in LPCWSTR wzContainerId
1208 __in LPCWSTR wzPayloadId,
1209 __in BOOL fSkipUntilRetried
1210 ) 1147 )
1211 { 1148 {
1212 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); 1149 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1213 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ACQUIRE_PAYLOAD, pAction->type); 1150 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_CONTAINER, pAction->type);
1214 NativeAssert::StringEqual(wzPackageId, pAction->resolvePayload.pPackage->sczId); 1151 NativeAssert::StringEqual(wzContainerId, pAction->container.pContainer->sczId);
1215 NativeAssert::StringEqual(wzPayloadId, pAction->resolvePayload.pPayload->sczKey);
1216 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1217 } 1152 }
1218 1153
1219 BURN_CACHE_ACTION* ValidateCacheActionExists(BURN_PLAN* pPlan, BOOL fRollback, DWORD dwIndex) 1154 BURN_CACHE_ACTION* ValidateCacheActionExists(BURN_PLAN* pPlan, BOOL fRollback, DWORD dwIndex)
@@ -1222,26 +1157,6 @@ namespace Bootstrapper
1222 return (fRollback ? pPlan->rgRollbackCacheActions : pPlan->rgCacheActions) + dwIndex; 1157 return (fRollback ? pPlan->rgRollbackCacheActions : pPlan->rgCacheActions) + dwIndex;
1223 } 1158 }
1224 1159
1225 void ValidateCacheCachePayload(
1226 __in BURN_PLAN* pPlan,
1227 __in BOOL fRollback,
1228 __in DWORD dwIndex,
1229 __in LPCWSTR wzPackageId,
1230 __in LPCWSTR wzPayloadId,
1231 __in BOOL fMove,
1232 __in BOOL fSkipUntilRetried,
1233 __in DWORD iTryAgainAction
1234 )
1235 {
1236 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1237 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD, pAction->type);
1238 NativeAssert::StringEqual(wzPackageId, pAction->cachePayload.pPackage->sczId);
1239 NativeAssert::StringEqual(wzPayloadId, pAction->cachePayload.pPayload->sczKey);
1240 Assert::Equal<BOOL>(fMove, pAction->cachePayload.fMove);
1241 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1242 Assert::Equal(iTryAgainAction, pAction->cachePayload.iTryAgainAction);
1243 }
1244
1245 void ValidateCacheCheckpoint( 1160 void ValidateCacheCheckpoint(
1246 __in BURN_PLAN* pPlan, 1161 __in BURN_PLAN* pPlan,
1247 __in BOOL fRollback, 1162 __in BOOL fRollback,
@@ -1254,84 +1169,40 @@ namespace Bootstrapper
1254 Assert::Equal(dwId, pAction->checkpoint.dwId); 1169 Assert::Equal(dwId, pAction->checkpoint.dwId);
1255 } 1170 }
1256 1171
1257 void ValidateCacheExtractContainer( 1172 DWORD ValidateCachePackage(
1258 __in BURN_PLAN* pPlan,
1259 __in BOOL fRollback,
1260 __in DWORD dwIndex,
1261 __in LPCWSTR wzContainerId,
1262 __in BOOL fSkipUntilRetried,
1263 __in DWORD iSkipUntilAcquiredByAction,
1264 __in DWORD cPayloads
1265 )
1266 {
1267 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1268 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER, pAction->type);
1269 NativeAssert::StringEqual(wzContainerId, pAction->extractContainer.pContainer->sczId);
1270 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1271 Assert::Equal(iSkipUntilAcquiredByAction, pAction->extractContainer.iSkipUntilAcquiredByAction);
1272 Assert::Equal(cPayloads, pAction->extractContainer.cPayloads);
1273 }
1274
1275 DWORD ValidateCachePackageStart(
1276 __in BURN_PLAN* pPlan, 1173 __in BURN_PLAN* pPlan,
1277 __in BOOL fRollback, 1174 __in BOOL fRollback,
1278 __in DWORD dwIndex, 1175 __in DWORD dwIndex,
1279 __in LPCWSTR wzPackageId, 1176 __in LPCWSTR wzPackageId
1280 __in DWORD iPackageCompleteAction,
1281 __in DWORD cCachePayloads,
1282 __in DWORD64 qwCachePayloadSizeTotal,
1283 __in BOOL fSkipUntilRetried
1284 ) 1177 )
1285 { 1178 {
1286 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); 1179 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1287 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE_START, pAction->type); 1180 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE, pAction->type);
1288 NativeAssert::StringEqual(wzPackageId, pAction->packageStart.pPackage->sczId); 1181 NativeAssert::StringEqual(wzPackageId, pAction->package.pPackage->sczId);
1289 Assert::Equal(iPackageCompleteAction, pAction->packageStart.iPackageCompleteAction);
1290 Assert::Equal(cCachePayloads, pAction->packageStart.cCachePayloads);
1291 Assert::Equal(qwCachePayloadSizeTotal, pAction->packageStart.qwCachePayloadSizeTotal);
1292 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1293 return dwIndex + 1; 1182 return dwIndex + 1;
1294 } 1183 }
1295 1184
1296 void ValidateCachePackageStop(
1297 __in BURN_PLAN* pPlan,
1298 __in BOOL fRollback,
1299 __in DWORD dwIndex,
1300 __in LPCWSTR wzPackageId,
1301 __in BOOL fSkipUntilRetried
1302 )
1303 {
1304 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1305 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE_STOP, pAction->type);
1306 NativeAssert::StringEqual(wzPackageId, pAction->packageStop.pPackage->sczId);
1307 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1308 }
1309
1310 void ValidateCacheRollbackPackage( 1185 void ValidateCacheRollbackPackage(
1311 __in BURN_PLAN* pPlan, 1186 __in BURN_PLAN* pPlan,
1312 __in BOOL fRollback, 1187 __in BOOL fRollback,
1313 __in DWORD dwIndex, 1188 __in DWORD dwIndex,
1314 __in LPCWSTR wzPackageId, 1189 __in LPCWSTR wzPackageId
1315 __in BOOL fSkipUntilRetried
1316 ) 1190 )
1317 { 1191 {
1318 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); 1192 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1319 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE, pAction->type); 1193 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE, pAction->type);
1320 NativeAssert::StringEqual(wzPackageId, pAction->rollbackPackage.pPackage->sczId); 1194 NativeAssert::StringEqual(wzPackageId, pAction->rollbackPackage.pPackage->sczId);
1321 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1322 } 1195 }
1323 1196
1324 void ValidateCacheSignalSyncpoint( 1197 void ValidateCacheSignalSyncpoint(
1325 __in BURN_PLAN* pPlan, 1198 __in BURN_PLAN* pPlan,
1326 __in BOOL fRollback, 1199 __in BOOL fRollback,
1327 __in DWORD dwIndex, 1200 __in DWORD dwIndex
1328 __in BOOL fSkipUntilRetried
1329 ) 1201 )
1330 { 1202 {
1331 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); 1203 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
1332 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT, pAction->type); 1204 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT, pAction->type);
1333 Assert::NotEqual((DWORD_PTR)NULL, (DWORD_PTR)pAction->syncpoint.hEvent); 1205 Assert::NotEqual((DWORD_PTR)NULL, (DWORD_PTR)pAction->syncpoint.hEvent);
1334 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
1335 } 1206 }
1336 1207
1337 void ValidateCleanAction( 1208 void ValidateCleanAction(