aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-11-15 19:54:20 -0600
committerSean Hall <r.sean.hall@gmail.com>2020-11-17 19:06:00 -0600
commit0d873d28c2dd18444afa08b748e91f495ed1cf5c (patch)
treec82e70b9ac047b316f976e6078bf19ff19cc7d95
parentd6aceb1277606fe1f1688d40ee0895d0b89c6705 (diff)
downloadwix-0d873d28c2dd18444afa08b748e91f495ed1cf5c.tar.gz
wix-0d873d28c2dd18444afa08b748e91f495ed1cf5c.tar.bz2
wix-0d873d28c2dd18444afa08b748e91f495ed1cf5c.zip
Add plan tests.
-rw-r--r--src/engine/container.cpp36
-rw-r--r--src/engine/container.h5
-rw-r--r--src/engine/core.cpp4
-rw-r--r--src/engine/logging.cpp21
-rw-r--r--src/engine/logging.h4
-rw-r--r--src/engine/manifest.cpp49
-rw-r--r--src/engine/manifest.h5
-rw-r--r--src/engine/msiengine.cpp5
-rw-r--r--src/engine/msiengine.h6
-rw-r--r--src/engine/plan.cpp34
-rw-r--r--src/engine/plan.h3
-rw-r--r--src/test/BurnUnitTest/BurnUnitTest.vcxproj1
-rw-r--r--src/test/BurnUnitTest/BurnUnitTest.vcxproj.filters3
-rw-r--r--src/test/BurnUnitTest/PlanTest.cpp982
-rw-r--r--src/test/BurnUnitTest/precomp.h1
15 files changed, 1125 insertions, 34 deletions
diff --git a/src/engine/container.cpp b/src/engine/container.cpp
index ada9025b..55a16afb 100644
--- a/src/engine/container.cpp
+++ b/src/engine/container.cpp
@@ -17,7 +17,6 @@ static HRESULT GetAttachedContainerInfo(
17// function definitions 17// function definitions
18 18
19extern "C" HRESULT ContainersParseFromXml( 19extern "C" HRESULT ContainersParseFromXml(
20 __in BURN_SECTION* pSection,
21 __in BURN_CONTAINERS* pContainers, 20 __in BURN_CONTAINERS* pContainers,
22 __in IXMLDOMNode* pixnBundle 21 __in IXMLDOMNode* pixnBundle
23 ) 22 )
@@ -128,14 +127,6 @@ extern "C" HRESULT ContainersParseFromXml(
128 ExitOnFailure(hr, "Failed to get @Hash."); 127 ExitOnFailure(hr, "Failed to get @Hash.");
129 } 128 }
130 129
131 // If the container is attached, make sure the information in the section matches what the
132 // manifest contained and get the offset to the container.
133 if (pContainer->fAttached)
134 {
135 hr = SectionGetAttachedContainerInfo(pSection, pContainer->dwAttachedIndex, pContainer->type, &pContainer->qwAttachedOffset, &pContainer->qwFileSize, &pContainer->fActuallyAttached);
136 ExitOnFailure(hr, "Failed to get attached container information.");
137 }
138
139 // prepare next iteration 130 // prepare next iteration
140 ReleaseNullObject(pixnNode); 131 ReleaseNullObject(pixnNode);
141 } 132 }
@@ -150,6 +141,33 @@ LExit:
150 return hr; 141 return hr;
151} 142}
152 143
144extern "C" HRESULT ContainersInitialize(
145 __in BURN_CONTAINERS* pContainers,
146 __in BURN_SECTION* pSection
147 )
148{
149 HRESULT hr = S_OK;
150
151 if (pContainers->rgContainers)
152 {
153 for (DWORD i = 0; i < pContainers->cContainers; ++i)
154 {
155 BURN_CONTAINER* pContainer = &pContainers->rgContainers[i];
156
157 // If the container is attached, make sure the information in the section matches what the
158 // manifest contained and get the offset to the container.
159 if (pContainer->fAttached)
160 {
161 hr = SectionGetAttachedContainerInfo(pSection, pContainer->dwAttachedIndex, pContainer->type, &pContainer->qwAttachedOffset, &pContainer->qwFileSize, &pContainer->fActuallyAttached);
162 ExitOnFailure(hr, "Failed to get attached container information.");
163 }
164 }
165 }
166
167LExit:
168 return hr;
169}
170
153extern "C" void ContainersUninitialize( 171extern "C" void ContainersUninitialize(
154 __in BURN_CONTAINERS* pContainers 172 __in BURN_CONTAINERS* pContainers
155 ) 173 )
diff --git a/src/engine/container.h b/src/engine/container.h
index 2ca3d7ad..bbd9fa72 100644
--- a/src/engine/container.h
+++ b/src/engine/container.h
@@ -135,10 +135,13 @@ typedef struct _BURN_CONTAINER_CONTEXT
135// functions 135// functions
136 136
137HRESULT ContainersParseFromXml( 137HRESULT ContainersParseFromXml(
138 __in BURN_SECTION* pSection,
139 __in BURN_CONTAINERS* pContainers, 138 __in BURN_CONTAINERS* pContainers,
140 __in IXMLDOMNode* pixnBundle 139 __in IXMLDOMNode* pixnBundle
141 ); 140 );
141HRESULT ContainersInitialize(
142 __in BURN_CONTAINERS* pContainers,
143 __in BURN_SECTION* pSection
144 );
142void ContainersUninitialize( 145void ContainersUninitialize(
143 __in BURN_CONTAINERS* pContainers 146 __in BURN_CONTAINERS* pContainers
144 ); 147 );
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index c34024fd..aeae6bea 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -96,6 +96,9 @@ extern "C" HRESULT CoreInitialize(
96 hr = ManifestLoadXmlFromBuffer(pbBuffer, cbBuffer, pEngineState); 96 hr = ManifestLoadXmlFromBuffer(pbBuffer, cbBuffer, pEngineState);
97 ExitOnFailure(hr, "Failed to load manifest."); 97 ExitOnFailure(hr, "Failed to load manifest.");
98 98
99 hr = ContainersInitialize(&pEngineState->containers, &pEngineState->section);
100 ExitOnFailure(hr, "Failed to intialize containers.");
101
99 // Parse command line. 102 // Parse command line.
100 hr = ParseCommandLine(pEngineState->argc, pEngineState->argv, &pEngineState->command, &pEngineState->companionConnection, &pEngineState->embeddedConnection, &pEngineState->variables, &pEngineState->mode, &pEngineState->automaticUpdates, &pEngineState->fDisableSystemRestore, &sczSourceProcessPath, &sczOriginalSource, &pEngineState->fDisableUnelevate, &pEngineState->log.dwAttributes, &pEngineState->log.sczPath, &pEngineState->registration.sczActiveParent, &pEngineState->sczIgnoreDependencies, &pEngineState->registration.sczAncestors, &sczSanitizedCommandLine); 103 hr = ParseCommandLine(pEngineState->argc, pEngineState->argv, &pEngineState->command, &pEngineState->companionConnection, &pEngineState->embeddedConnection, &pEngineState->variables, &pEngineState->mode, &pEngineState->automaticUpdates, &pEngineState->fDisableSystemRestore, &sczSourceProcessPath, &sczOriginalSource, &pEngineState->fDisableUnelevate, &pEngineState->log.dwAttributes, &pEngineState->log.sczPath, &pEngineState->registration.sczActiveParent, &pEngineState->sczIgnoreDependencies, &pEngineState->registration.sczAncestors, &sczSanitizedCommandLine);
101 ExitOnFailure(hr, "Failed to parse command line."); 104 ExitOnFailure(hr, "Failed to parse command line.");
@@ -411,6 +414,7 @@ extern "C" HRESULT CorePlan(
411 pEngineState->plan.action = action; 414 pEngineState->plan.action = action;
412 pEngineState->plan.wzBundleId = pEngineState->registration.sczId; 415 pEngineState->plan.wzBundleId = pEngineState->registration.sczId;
413 pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId; 416 pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId;
417 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback;
414 418
415 hr = PlanSetVariables(action, &pEngineState->variables); 419 hr = PlanSetVariables(action, &pEngineState->variables);
416 ExitOnFailure(hr, "Failed to update action."); 420 ExitOnFailure(hr, "Failed to update action.");
diff --git a/src/engine/logging.cpp b/src/engine/logging.cpp
index e69303f0..512b562c 100644
--- a/src/engine/logging.cpp
+++ b/src/engine/logging.cpp
@@ -468,6 +468,27 @@ extern "C" LPCSTR LoggingMsiInstallContext(
468 } 468 }
469} 469}
470 470
471extern "C" LPCWSTR LoggingBurnMsiPropertyToString(
472 __in BURN_MSI_PROPERTY burnMsiProperty
473 )
474{
475 switch (burnMsiProperty)
476 {
477 case BURN_MSI_PROPERTY_INSTALL:
478 return BURNMSIINSTALL_PROPERTY_NAME;
479 case BURN_MSI_PROPERTY_MODIFY:
480 return BURNMSIMODIFY_PROPERTY_NAME;
481 case BURN_MSI_PROPERTY_NONE:
482 return L"(none)";
483 case BURN_MSI_PROPERTY_REPAIR:
484 return BURNMSIREPAIR_PROPERTY_NAME;
485 case BURN_MSI_PROPERTY_UNINSTALL:
486 return BURNMSIUNINSTALL_PROPERTY_NAME;
487 default:
488 return L"Invalid";
489 }
490}
491
471extern "C" LPCSTR LoggingPerMachineToString( 492extern "C" LPCSTR LoggingPerMachineToString(
472 __in BOOL fPerMachine 493 __in BOOL fPerMachine
473 ) 494 )
diff --git a/src/engine/logging.h b/src/engine/logging.h
index 22dd54d9..381a295b 100644
--- a/src/engine/logging.h
+++ b/src/engine/logging.h
@@ -101,6 +101,10 @@ LPCSTR LoggingMsiInstallContext(
101 __in MSIINSTALLCONTEXT context 101 __in MSIINSTALLCONTEXT context
102 ); 102 );
103 103
104LPCWSTR LoggingBurnMsiPropertyToString(
105 __in BURN_MSI_PROPERTY burnMsiProperty
106 );
107
104LPCSTR LoggingPerMachineToString( 108LPCSTR LoggingPerMachineToString(
105 __in BOOL fPerMachine 109 __in BOOL fPerMachine
106 ); 110 );
diff --git a/src/engine/manifest.cpp b/src/engine/manifest.cpp
index 8783b15e..270b6b74 100644
--- a/src/engine/manifest.cpp
+++ b/src/engine/manifest.cpp
@@ -3,8 +3,33 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6static HRESULT ParseFromXml(
7 __in IXMLDOMDocument* pixdDocument,
8 __in BURN_ENGINE_STATE* pEngineState
9 );
10
6// function definitions 11// function definitions
7 12
13extern "C" HRESULT ManifestLoadXml(
14 __in LPCWSTR wzDocument,
15 __in BURN_ENGINE_STATE* pEngineState
16 )
17{
18 HRESULT hr = S_OK;
19 IXMLDOMDocument* pixdDocument = NULL;
20
21 // load xml document
22 hr = XmlLoadDocument(wzDocument, &pixdDocument);
23 ExitOnFailure(hr, "Failed to load manifest as XML document.");
24
25 hr = ParseFromXml(pixdDocument, pEngineState);
26
27LExit:
28 ReleaseObject(pixdDocument);
29
30 return hr;
31}
32
8extern "C" HRESULT ManifestLoadXmlFromBuffer( 33extern "C" HRESULT ManifestLoadXmlFromBuffer(
9 __in_bcount(cbBuffer) BYTE* pbBuffer, 34 __in_bcount(cbBuffer) BYTE* pbBuffer,
10 __in SIZE_T cbBuffer, 35 __in SIZE_T cbBuffer,
@@ -13,14 +38,29 @@ extern "C" HRESULT ManifestLoadXmlFromBuffer(
13{ 38{
14 HRESULT hr = S_OK; 39 HRESULT hr = S_OK;
15 IXMLDOMDocument* pixdDocument = NULL; 40 IXMLDOMDocument* pixdDocument = NULL;
16 IXMLDOMElement* pixeBundle = NULL;
17 IXMLDOMNode* pixnLog = NULL;
18 IXMLDOMNode* pixnChain = NULL;
19 41
20 // load xml document 42 // load xml document
21 hr = XmlLoadDocumentFromBuffer(pbBuffer, cbBuffer, &pixdDocument); 43 hr = XmlLoadDocumentFromBuffer(pbBuffer, cbBuffer, &pixdDocument);
22 ExitOnFailure(hr, "Failed to load manifest as XML document."); 44 ExitOnFailure(hr, "Failed to load manifest as XML document.");
23 45
46 hr = ParseFromXml(pixdDocument, pEngineState);
47
48LExit:
49 ReleaseObject(pixdDocument);
50
51 return hr;
52}
53
54static HRESULT ParseFromXml(
55 __in IXMLDOMDocument* pixdDocument,
56 __in BURN_ENGINE_STATE* pEngineState
57 )
58{
59 HRESULT hr = S_OK;
60 IXMLDOMElement* pixeBundle = NULL;
61 IXMLDOMNode* pixnLog = NULL;
62 IXMLDOMNode* pixnChain = NULL;
63
24 // get bundle element 64 // get bundle element
25 hr = pixdDocument->get_documentElement(&pixeBundle); 65 hr = pixdDocument->get_documentElement(&pixeBundle);
26 ExitOnFailure(hr, "Failed to get bundle element."); 66 ExitOnFailure(hr, "Failed to get bundle element.");
@@ -105,7 +145,7 @@ extern "C" HRESULT ManifestLoadXmlFromBuffer(
105 ExitOnFailure(hr, "Failed to parse update."); 145 ExitOnFailure(hr, "Failed to parse update.");
106 146
107 // parse containers 147 // parse containers
108 hr = ContainersParseFromXml(&pEngineState->section, &pEngineState->containers, pixeBundle); 148 hr = ContainersParseFromXml(&pEngineState->containers, pixeBundle);
109 ExitOnFailure(hr, "Failed to parse containers."); 149 ExitOnFailure(hr, "Failed to parse containers.");
110 150
111 // parse payloads 151 // parse payloads
@@ -124,6 +164,5 @@ LExit:
124 ReleaseObject(pixnChain); 164 ReleaseObject(pixnChain);
125 ReleaseObject(pixnLog); 165 ReleaseObject(pixnLog);
126 ReleaseObject(pixeBundle); 166 ReleaseObject(pixeBundle);
127 ReleaseObject(pixdDocument);
128 return hr; 167 return hr;
129} 168}
diff --git a/src/engine/manifest.h b/src/engine/manifest.h
index 6e535d60..223181d9 100644
--- a/src/engine/manifest.h
+++ b/src/engine/manifest.h
@@ -11,6 +11,11 @@ extern "C" {
11 11
12// function declarations 12// function declarations
13 13
14HRESULT ManifestLoadXml(
15 __in LPCWSTR wzDocument,
16 __in BURN_ENGINE_STATE* pEngineState
17 );
18
14HRESULT ManifestLoadXmlFromBuffer( 19HRESULT ManifestLoadXmlFromBuffer(
15 __in_bcount(cbBuffer) BYTE* pbBuffer, 20 __in_bcount(cbBuffer) BYTE* pbBuffer,
16 __in SIZE_T cbBuffer, 21 __in SIZE_T cbBuffer,
diff --git a/src/engine/msiengine.cpp b/src/engine/msiengine.cpp
index 066734d0..c20e2ef8 100644
--- a/src/engine/msiengine.cpp
+++ b/src/engine/msiengine.cpp
@@ -4,10 +4,7 @@
4 4
5 5
6// constants 6// constants
7#define BURNMSIINSTALL_PROPERTY_NAME L"BURNMSIINSTALL" 7
8#define BURNMSIMODIFY_PROPERTY_NAME L"BURNMSIMODIFY"
9#define BURNMSIREPAIR_PROPERTY_NAME L"BURNMSIREPAIR"
10#define BURNMSIUNINSTALL_PROPERTY_NAME L"BURNMSIUNINSTALL"
11 8
12// structs 9// structs
13 10
diff --git a/src/engine/msiengine.h b/src/engine/msiengine.h
index 04c375c2..64bddcf0 100644
--- a/src/engine/msiengine.h
+++ b/src/engine/msiengine.h
@@ -1,6 +1,12 @@
1#pragma once 1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. 2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3 3
4// constants
5#define BURNMSIINSTALL_PROPERTY_NAME L"BURNMSIINSTALL"
6#define BURNMSIMODIFY_PROPERTY_NAME L"BURNMSIMODIFY"
7#define BURNMSIREPAIR_PROPERTY_NAME L"BURNMSIREPAIR"
8#define BURNMSIUNINSTALL_PROPERTY_NAME L"BURNMSIUNINSTALL"
9
4 10
5#if defined(__cplusplus) 11#if defined(__cplusplus)
6extern "C" { 12extern "C" {
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index 3c0e1c50..e2a3437d 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -74,7 +74,9 @@ static BOOL AlreadyPlannedCachePackage(
74 __in_z LPCWSTR wzPackageId, 74 __in_z LPCWSTR wzPackageId,
75 __out HANDLE* phSyncpointEvent 75 __out HANDLE* phSyncpointEvent
76 ); 76 );
77static DWORD GetNextCheckpointId(); 77static DWORD GetNextCheckpointId(
78 __in BURN_PLAN* pPlan
79 );
78static HRESULT AppendCacheAction( 80static HRESULT AppendCacheAction(
79 __in BURN_PLAN* pPlan, 81 __in BURN_PLAN* pPlan,
80 __out BURN_CACHE_ACTION** ppCacheAction 82 __out BURN_CACHE_ACTION** ppCacheAction
@@ -1621,7 +1623,7 @@ extern "C" HRESULT PlanExecuteCheckpoint(
1621{ 1623{
1622 HRESULT hr = S_OK; 1624 HRESULT hr = S_OK;
1623 BURN_EXECUTE_ACTION* pAction = NULL; 1625 BURN_EXECUTE_ACTION* pAction = NULL;
1624 DWORD dwCheckpointId = GetNextCheckpointId(); 1626 DWORD dwCheckpointId = GetNextCheckpointId(pPlan);
1625 1627
1626 // execute checkpoint 1628 // execute checkpoint
1627 hr = PlanAppendExecuteAction(pPlan, &pAction); 1629 hr = PlanAppendExecuteAction(pPlan, &pAction);
@@ -1808,7 +1810,7 @@ extern "C" HRESULT PlanRollbackBoundaryComplete(
1808 DWORD dwCheckpointId = 0; 1810 DWORD dwCheckpointId = 0;
1809 1811
1810 // Add checkpoints. 1812 // Add checkpoints.
1811 dwCheckpointId = GetNextCheckpointId(); 1813 dwCheckpointId = GetNextCheckpointId(pPlan);
1812 1814
1813 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction); 1815 hr = PlanAppendExecuteAction(pPlan, &pExecuteAction);
1814 ExitOnFailure(hr, "Failed to append execute action."); 1816 ExitOnFailure(hr, "Failed to append execute action.");
@@ -2095,7 +2097,7 @@ static HRESULT AddCachePackageHelper(
2095 // Cache checkpoints happen before the package is cached because downloading packages' 2097 // Cache checkpoints happen before the package is cached because downloading packages'
2096 // payloads will not roll themselves back the way installation packages rollback on 2098 // payloads will not roll themselves back the way installation packages rollback on
2097 // failure automatically. 2099 // failure automatically.
2098 dwCheckpoint = GetNextCheckpointId(); 2100 dwCheckpoint = GetNextCheckpointId(pPlan);
2099 2101
2100 hr = AppendCacheAction(pPlan, &pCacheAction); 2102 hr = AppendCacheAction(pPlan, &pCacheAction);
2101 ExitOnFailure(hr, "Failed to append package start action."); 2103 ExitOnFailure(hr, "Failed to append package start action.");
@@ -2234,10 +2236,11 @@ static BOOL AlreadyPlannedCachePackage(
2234 return fPlanned; 2236 return fPlanned;
2235} 2237}
2236 2238
2237static DWORD GetNextCheckpointId() 2239static DWORD GetNextCheckpointId(
2240 __in BURN_PLAN* pPlan
2241 )
2238{ 2242{
2239 static DWORD dwCounter = 0; 2243 return ++pPlan->dwNextCheckpointId;
2240 return ++dwCounter;
2241} 2244}
2242 2245
2243static HRESULT AppendCacheAction( 2246static HRESULT AppendCacheAction(
@@ -3039,11 +3042,11 @@ static void CacheActionLog(
3039 break; 3042 break;
3040 3043
3041 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 3044 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
3042 LogStringLine(REPORT_STANDARD, "%ls action[%u]: SIGNAL_SYNCPOINT event handle: 0x%x, skip until retried: %hs", wzBase, iAction, pAction->syncpoint.hEvent, LoggingBoolToString(pAction->fSkipUntilRetried)); 3045 LogStringLine(REPORT_STANDARD, "%ls action[%u]: SIGNAL_SYNCPOINT event handle: 0x%p, skip until retried: %hs", wzBase, iAction, pAction->syncpoint.hEvent, LoggingBoolToString(pAction->fSkipUntilRetried));
3043 break; 3046 break;
3044 3047
3045 case BURN_CACHE_ACTION_TYPE_TRANSACTION_BOUNDARY: 3048 case BURN_CACHE_ACTION_TYPE_TRANSACTION_BOUNDARY:
3046 LogStringLine(REPORT_STANDARD, "%ls action[%u]: TRANSACTION_BOUNDARY id: %ls, event handle: 0x%x, 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"); 3049 LogStringLine(REPORT_STANDARD, "%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");
3047 break; 3050 break;
3048 3051
3049 default: 3052 default:
@@ -3066,11 +3069,11 @@ static void ExecuteActionLog(
3066 break; 3069 break;
3067 3070
3068 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER: 3071 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER:
3069 LogStringLine(REPORT_STANDARD, "%ls action[%u]: PACKAGE_PROVIDER package id: %ls, action: %u", wzBase, iAction, pAction->packageProvider.pPackage->sczId, pAction->packageProvider.action); 3072 LogStringLine(REPORT_STANDARD, "%ls action[%u]: PACKAGE_PROVIDER package id: %ls, action: %hs", wzBase, iAction, pAction->packageProvider.pPackage->sczId, LoggingDependencyActionToString(pAction->packageProvider.action));
3070 break; 3073 break;
3071 3074
3072 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY: 3075 case BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY:
3073 LogStringLine(REPORT_STANDARD, "%ls action[%u]: PACKAGE_DEPENDENCY package id: %ls, bundle provider key: %ls, action: %u", wzBase, iAction, pAction->packageDependency.pPackage->sczId, pAction->packageDependency.sczBundleProviderKey, pAction->packageDependency.action); 3076 LogStringLine(REPORT_STANDARD, "%ls action[%u]: PACKAGE_DEPENDENCY package id: %ls, bundle provider key: %ls, action: %hs", wzBase, iAction, pAction->packageDependency.pPackage->sczId, pAction->packageDependency.sczBundleProviderKey, LoggingDependencyActionToString(pAction->packageDependency.action));
3074 break; 3077 break;
3075 3078
3076 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 3079 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
@@ -3078,15 +3081,15 @@ static void ExecuteActionLog(
3078 break; 3081 break;
3079 3082
3080 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 3083 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
3081 LogStringLine(REPORT_STANDARD, "%ls action[%u]: MSI_PACKAGE package id: %ls, action: %hs, action msi property: %u, ui level: %u, disable externaluihandler: %ls, log path: %ls, logging attrib: %u", wzBase, iAction, pAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pAction->msiPackage.action), pAction->msiPackage.actionMsiProperty, pAction->msiPackage.uiLevel, pAction->msiPackage.fDisableExternalUiHandler ? L"yes" : L"no", pAction->msiPackage.sczLogPath, pAction->msiPackage.dwLoggingAttributes); 3084 LogStringLine(REPORT_STANDARD, "%ls action[%u]: MSI_PACKAGE package id: %ls, action: %hs, action msi property: %ls, ui level: %u, disable externaluihandler: %ls, log path: %ls, logging attrib: %u", wzBase, iAction, pAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pAction->msiPackage.action), LoggingBurnMsiPropertyToString(pAction->msiPackage.actionMsiProperty), pAction->msiPackage.uiLevel, pAction->msiPackage.fDisableExternalUiHandler ? L"yes" : L"no", pAction->msiPackage.sczLogPath, pAction->msiPackage.dwLoggingAttributes);
3082 for (DWORD j = 0; j < pAction->msiPackage.cPatches; ++j) 3085 for (DWORD j = 0; j < pAction->msiPackage.cPatches; ++j)
3083 { 3086 {
3084 LogStringLine(REPORT_STANDARD, " Patch[%u]: order: %u, msp package id: %ls", j, pAction->msiPackage.rgOrderedPatches->dwOrder, pAction->msiPackage.rgOrderedPatches[j].dwOrder, pAction->msiPackage.rgOrderedPatches[j].pPackage->sczId); 3087 LogStringLine(REPORT_STANDARD, " Patch[%u]: order: %u, msp package id: %ls", j, pAction->msiPackage.rgOrderedPatches[j].dwOrder, pAction->msiPackage.rgOrderedPatches[j].pPackage->sczId);
3085 } 3088 }
3086 break; 3089 break;
3087 3090
3088 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: 3091 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
3089 LogStringLine(REPORT_STANDARD, "%ls action[%u]: MSP_TARGET package id: %ls, action: %hs, target product code: %ls, target per-machine: %ls, action msi property: %u, ui level: %u, disable externaluihandler: %ls, log path: %ls", wzBase, iAction, pAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pAction->mspTarget.action), pAction->mspTarget.sczTargetProductCode, pAction->mspTarget.fPerMachineTarget ? L"yes" : L"no", pAction->mspTarget.actionMsiProperty, pAction->mspTarget.uiLevel, pAction->mspTarget.fDisableExternalUiHandler ? L"yes" : L"no", pAction->mspTarget.sczLogPath); 3092 LogStringLine(REPORT_STANDARD, "%ls action[%u]: MSP_TARGET package id: %ls, action: %hs, target product code: %ls, target per-machine: %ls, action msi property: %ls, ui level: %u, disable externaluihandler: %ls, log path: %ls", wzBase, iAction, pAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pAction->mspTarget.action), pAction->mspTarget.sczTargetProductCode, pAction->mspTarget.fPerMachineTarget ? L"yes" : L"no", LoggingBurnMsiPropertyToString(pAction->mspTarget.actionMsiProperty), pAction->mspTarget.uiLevel, pAction->mspTarget.fDisableExternalUiHandler ? L"yes" : L"no", pAction->mspTarget.sczLogPath);
3090 for (DWORD j = 0; j < pAction->mspTarget.cOrderedPatches; ++j) 3093 for (DWORD j = 0; j < pAction->mspTarget.cOrderedPatches; ++j)
3091 { 3094 {
3092 LogStringLine(REPORT_STANDARD, " Patch[%u]: order: %u, msp package id: %ls", j, pAction->mspTarget.rgOrderedPatches[j].dwOrder, pAction->mspTarget.rgOrderedPatches[j].pPackage->sczId); 3095 LogStringLine(REPORT_STANDARD, " Patch[%u]: order: %u, msp package id: %ls", j, pAction->mspTarget.rgOrderedPatches[j].dwOrder, pAction->mspTarget.rgOrderedPatches[j].pPackage->sczId);
@@ -3106,7 +3109,7 @@ static void ExecuteActionLog(
3106 break; 3109 break;
3107 3110
3108 case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT: 3111 case BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT:
3109 LogStringLine(REPORT_STANDARD, "%ls action[%u]: WAIT_SYNCPOINT event handle: 0x%x", wzBase, iAction, pAction->syncpoint.hEvent); 3112 LogStringLine(REPORT_STANDARD, "%ls action[%u]: WAIT_SYNCPOINT event handle: 0x%p", wzBase, iAction, pAction->syncpoint.hEvent);
3110 break; 3113 break;
3111 3114
3112 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE: 3115 case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE:
@@ -3131,6 +3134,7 @@ extern "C" void PlanDump(
3131 3134
3132 LogStringLine(REPORT_STANDARD, "Plan action: %hs", LoggingBurnActionToString(pPlan->action)); 3135 LogStringLine(REPORT_STANDARD, "Plan action: %hs", LoggingBurnActionToString(pPlan->action));
3133 LogStringLine(REPORT_STANDARD, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine)); 3136 LogStringLine(REPORT_STANDARD, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine));
3137 LogStringLine(REPORT_STANDARD, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback));
3134 LogStringLine(REPORT_STANDARD, " keep registration by default: %hs", LoggingTrueFalseToString(pPlan->fKeepRegistrationDefault)); 3138 LogStringLine(REPORT_STANDARD, " keep registration by default: %hs", LoggingTrueFalseToString(pPlan->fKeepRegistrationDefault));
3135 LogStringLine(REPORT_STANDARD, " estimated size: %llu", pPlan->qwEstimatedSize); 3139 LogStringLine(REPORT_STANDARD, " estimated size: %llu", pPlan->qwEstimatedSize);
3136 3140
diff --git a/src/engine/plan.h b/src/engine/plan.h
index 4fd3380e..5fddd72f 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -325,6 +325,7 @@ typedef struct _BURN_PLAN
325 DWORD dwRegistrationOperations; 325 DWORD dwRegistrationOperations;
326 BOOL fKeepRegistrationDefault; 326 BOOL fKeepRegistrationDefault;
327 BOOL fDisallowRemoval; 327 BOOL fDisallowRemoval;
328 BOOL fDisableRollback;
328 329
329 DWORD64 qwCacheSizeTotal; 330 DWORD64 qwCacheSizeTotal;
330 331
@@ -366,6 +367,8 @@ typedef struct _BURN_PLAN
366 BURN_CACHE_PAYLOAD_PROGRESS* rgPayloadProgress; 367 BURN_CACHE_PAYLOAD_PROGRESS* rgPayloadProgress;
367 DWORD cPayloadProgress; 368 DWORD cPayloadProgress;
368 STRINGDICT_HANDLE shPayloadProgress; 369 STRINGDICT_HANDLE shPayloadProgress;
370
371 DWORD dwNextCheckpointId;
369} BURN_PLAN; 372} BURN_PLAN;
370 373
371 374
diff --git a/src/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/test/BurnUnitTest/BurnUnitTest.vcxproj
index dde01be1..71f3ea09 100644
--- a/src/test/BurnUnitTest/BurnUnitTest.vcxproj
+++ b/src/test/BurnUnitTest/BurnUnitTest.vcxproj
@@ -36,6 +36,7 @@
36 <ClCompile Include="ElevationTest.cpp" /> 36 <ClCompile Include="ElevationTest.cpp" />
37 <ClCompile Include="ManifestHelpers.cpp" /> 37 <ClCompile Include="ManifestHelpers.cpp" />
38 <ClCompile Include="ManifestTest.cpp" /> 38 <ClCompile Include="ManifestTest.cpp" />
39 <ClCompile Include="PlanTest.cpp" />
39 <ClCompile Include="precomp.cpp"> 40 <ClCompile Include="precomp.cpp">
40 <PrecompiledHeader>Create</PrecompiledHeader> 41 <PrecompiledHeader>Create</PrecompiledHeader>
41 <!-- Warnings from referencing netstandard dlls --> 42 <!-- Warnings from referencing netstandard dlls -->
diff --git a/src/test/BurnUnitTest/BurnUnitTest.vcxproj.filters b/src/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
index 14261ba0..f9461f53 100644
--- a/src/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
+++ b/src/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
@@ -30,6 +30,9 @@
30 <ClCompile Include="ManifestTest.cpp"> 30 <ClCompile Include="ManifestTest.cpp">
31 <Filter>Source Files</Filter> 31 <Filter>Source Files</Filter>
32 </ClCompile> 32 </ClCompile>
33 <ClCompile Include="PlanTest.cpp">
34 <Filter>Source Files</Filter>
35 </ClCompile>
33 <ClCompile Include="precomp.cpp"> 36 <ClCompile Include="precomp.cpp">
34 <Filter>Source Files</Filter> 37 <Filter>Source Files</Filter>
35 </ClCompile> 38 </ClCompile>
diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp
new file mode 100644
index 00000000..86bc646b
--- /dev/null
+++ b/src/test/BurnUnitTest/PlanTest.cpp
@@ -0,0 +1,982 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5static HRESULT WINAPI PlanTestBAProc(
6 __in BOOTSTRAPPER_APPLICATION_MESSAGE message,
7 __in const LPVOID pvArgs,
8 __inout LPVOID pvResults,
9 __in_opt LPVOID pvContext
10 );
11
12static LPCWSTR wzMsiTransactionManifest =
13 L"<Bundle>"
14 L" <Log PathVariable='WixBundleLog' Prefix='~manual_BundleA' Extension='log' />"
15 L" <RelatedBundle Id='{90ED10D5-B187-4470-B498-05D80DAB729A}' Action='Upgrade' />"
16 L" <Variable Id='TestName' Value='MsiTransaction' Type='string' Hidden='no' Persisted='no' />"
17 L" <Variable Id='WixBundleName' Hidden='no' Persisted='yes' />"
18 L" <Variable Id='WixBundleOriginalSource' Hidden='no' Persisted='yes' />"
19 L" <Variable Id='WixBundleOriginalSourceFolder' Hidden='no' Persisted='yes' />"
20 L" <Variable Id='WixBundleLastUsedSource' Hidden='no' Persisted='yes' />"
21 L" <UX>"
22 L" <Payload Id='WixStandardBootstrapperApplication.RtfLicense' FilePath='wixstdba.dll' FileSize='1312768' Hash='B331BC5C819F019981D2524C48CC370DE2BFE9F8' Packaging='embedded' SourcePath='u0' />"
23 L" <Payload Id='payF3wjO.aj6M8ftq9wrfYB1N4aw4g' FilePath='thm.xml' FileSize='8048' Hash='A712A9E1427A4EE1D0B68343A54019A3FC9967CB' Packaging='embedded' SourcePath='u1' />"
24 L" <Payload Id='payViPRdlZD7MPIBgwmX2Hv5C6oKt4' FilePath='thm.wxl' FileSize='3926' Hash='B88FAB9B6C2B52FBE017F91B0915781C6B76058E' Packaging='embedded' SourcePath='u2' />"
25 L" <Payload Id='payjqSD44latbvJnf4vAQuVMUST73A' FilePath='logo.png' FileSize='852' Hash='239F10674BF6022854C1F1BF7C91955BDE34D3E4' Packaging='embedded' SourcePath='u3' />"
26 L" <Payload Id='pay60yHh1x6HODo4M_38Pud7jhl2Ig' FilePath='license.rtf' FileSize='4908' Hash='383034848F8CC4F3C8E795CC0F4D716A285E9465' Packaging='embedded' SourcePath='u4' />"
27 L" <Payload Id='uxTxMXPVMXwQrPTMIGa5WGt93w0Ns' FilePath='BootstrapperApplicationData.xml' FileSize='6870' Hash='5302818DB5BD565463715D3C7099FE5123474476' Packaging='embedded' SourcePath='u5' />"
28 L" </UX>"
29 L" <Container Id='WixAttachedContainer' FileSize='9198' Hash='D932DEBC15B7EC41B3EB64DD075A1C7148C2BD6D' FilePath='BundleA.exe' AttachedIndex='1' Attached='yes' Primary='yes' />"
30 L" <Payload Id='PackageA' FilePath='~manual_PackageA.msi' FileSize='32768' Hash='4011C700186B4C162B2A50D981C895108AD67EBB' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />"
31 L" <Payload Id='PackageB' FilePath='~manual_PackageB.msi' FileSize='32768' Hash='0DA2766C6B5D2253A37675D89E6F15A70EDD18EB' Packaging='embedded' SourcePath='a1' Container='WixAttachedContainer' />"
32 L" <Payload Id='PackageC' FilePath='~manual_PackageC.msi' FileSize='32768' Hash='B5E1B37DCF08B7D88F2EB45D063513BDE052E5E4' Packaging='embedded' SourcePath='a2' Container='WixAttachedContainer' />"
33 L" <Payload Id='cab1QmlL013Hqv_44W64R0cvnHn_2c' FilePath='cab1.cab' FileSize='973' Hash='7A51FCEDBCD0A697A94F0C47A89BDD5EFCC0CB4B' Packaging='embedded' SourcePath='a3' Container='WixAttachedContainer' />"
34 L" <Payload Id='cabQH1Sgh7w2K8tLIftUaaWVhMWt0s' FilePath='cab1.cab' FileSize='985' Hash='32EFE9983CB1FF0905A3725B901D0BBD5334E616' Packaging='embedded' SourcePath='a4' Container='WixAttachedContainer' />"
35 L" <Payload Id='cabRT8kdm93olnEAQB2GSO3u0400VI' FilePath='cab1.cab' FileSize='971' Hash='1D20203378E2AEC4AD728F7849A5CC7F6E7D094D' Packaging='embedded' SourcePath='a5' Container='WixAttachedContainer' />"
36 L" <RollbackBoundary Id='WixDefaultBoundary' Vital='yes' Transaction='no' />"
37 L" <RollbackBoundary Id='rbaOCA08D8ky7uBOK71_6FWz1K3TuQ' Vital='yes' Transaction='yes' />"
38 L" <Registration Id='{c096190a-8bf3-4342-a1d2-94ea9cb853d6}' ExecutableName='BundleA.exe' PerMachine='yes' Tag='' Version='1.0.0.0' ProviderKey='{c096190a-8bf3-4342-a1d2-94ea9cb853d6}'>"
39 L" <Arp Register='yes' DisplayName='~manual - Bundle A' DisplayVersion='1.0.0.0' />"
40 L" </Registration>"
41 L" <Chain>"
42 L" <MsiPackage Id='PackageA' Cache='yes' CacheId='{196E43EA-EF92-4FF8-B9AC-A0FD0D225BB4}v1.0.0.0' InstallSize='1634' Size='33741' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_PackageA' RollbackLogPathVariable='WixBundleRollbackLog_PackageA' ProductCode='{196E43EA-EF92-4FF8-B9AC-A0FD0D225BB4}' Language='1033' Version='1.0.0.0' UpgradeCode='{5B6AB1CF-5DD5-4BB1-851A-9C7E789BCDC7}'>"
43 L" <MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />"
44 L" <MsiProperty Id='MSIFASTINSTALL' Value='7' />"
45 L" <Provides Key='{196E43EA-EF92-4FF8-B9AC-A0FD0D225BB4}' DisplayName='~manual - A' />"
46 L" <RelatedPackage Id='{5B6AB1CF-5DD5-4BB1-851A-9C7E789BCDC7}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'>"
47 L" <Language Id='1033' />"
48 L" </RelatedPackage>"
49 L" <RelatedPackage Id='{5B6AB1CF-5DD5-4BB1-851A-9C7E789BCDC7}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'>"
50 L" <Language Id='1033' />"
51 L" </RelatedPackage>"
52 L" <PayloadRef Id='PackageA' />"
53 L" <PayloadRef Id='cab1QmlL013Hqv_44W64R0cvnHn_2c' />"
54 L" </MsiPackage>"
55 L" <MsiPackage Id='PackageB' Cache='yes' CacheId='{388E4963-13AD-4EE7-B907-AA8888F50E54}v1.0.0.0' InstallSize='1665' Size='33753' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='rbaOCA08D8ky7uBOK71_6FWz1K3TuQ' LogPathVariable='WixBundleLog_PackageB' RollbackLogPathVariable='WixBundleRollbackLog_PackageB' ProductCode='{388E4963-13AD-4EE7-B907-AA8888F50E54}' Language='1033' Version='1.0.0.0' UpgradeCode='{04ABCDBB-2C66-4338-9B1D-DE2AC9B0D1C2}'>"
56 L" <MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />"
57 L" <MsiProperty Id='MSIFASTINSTALL' Value='7' />"
58 L" <Provides Key='{388E4963-13AD-4EE7-B907-AA8888F50E54}' DisplayName='~manual - B' />"
59 L" <RelatedPackage Id='{04ABCDBB-2C66-4338-9B1D-DE2AC9B0D1C2}' MaxVersion='1.0.0.0' MaxInclusive='yes' OnlyDetect='no' LangInclusive='yes'>"
60 L" <Language Id='1033' />"
61 L" </RelatedPackage>"
62 L" <RelatedPackage Id='{04ABCDBB-2C66-4338-9B1D-DE2AC9B0D1C2}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'>"
63 L" <Language Id='1033' />"
64 L" </RelatedPackage>"
65 L" <PayloadRef Id='PackageB' />"
66 L" <PayloadRef Id='cabQH1Sgh7w2K8tLIftUaaWVhMWt0s' />"
67 L" </MsiPackage>"
68 L" <MsiPackage Id='PackageC' Cache='yes' CacheId='{BE27CF2B-9E5F-4500-BAE3-5E0E522FB962}v1.0.0.0' InstallSize='1634' Size='33739' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryBackward='rbaOCA08D8ky7uBOK71_6FWz1K3TuQ' LogPathVariable='WixBundleLog_PackageC' RollbackLogPathVariable='WixBundleRollbackLog_PackageC' ProductCode='{BE27CF2B-9E5F-4500-BAE3-5E0E522FB962}' Language='1033' Version='1.0.0.0' UpgradeCode='{3F8C1522-741D-499E-9137-7E192405E01A}'>"
69 L" <MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />"
70 L" <MsiProperty Id='MSIFASTINSTALL' Value='7' />"
71 L" <Provides Key='{BE27CF2B-9E5F-4500-BAE3-5E0E522FB962}' DisplayName='~manual - C' />"
72 L" <RelatedPackage Id='{3F8C1522-741D-499E-9137-7E192405E01A}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'>"
73 L" <Language Id='1033' />"
74 L" </RelatedPackage>"
75 L" <RelatedPackage Id='{3F8C1522-741D-499E-9137-7E192405E01A}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'>"
76 L" <Language Id='1033' />"
77 L" </RelatedPackage>"
78 L" <PayloadRef Id='PackageC' />"
79 L" <PayloadRef Id='cabRT8kdm93olnEAQB2GSO3u0400VI' />"
80 L" </MsiPackage>"
81 L" </Chain>"
82 L"</Bundle>";
83
84static LPCWSTR wzSingleMsiManifest =
85 L"<Bundle>"
86 L" <Log PathVariable='WixBundleLog' Prefix='~manual_BundleB' Extension='log' />"
87 L" <RelatedBundle Id='{CAAD4202-2097-4065-82BB-83F9F3FF61CE}' Action='Upgrade' />"
88 L" <Variable Id='TestName' Value='SingleMsi' Type='string' Hidden='no' Persisted='no' />"
89 L" <Variable Id='WixBundleName' Hidden='no' Persisted='yes' />"
90 L" <Variable Id='WixBundleOriginalSource' Hidden='no' Persisted='yes' />"
91 L" <Variable Id='WixBundleOriginalSourceFolder' Hidden='no' Persisted='yes' />"
92 L" <Variable Id='WixBundleLastUsedSource' Hidden='no' Persisted='yes' />"
93 L" <UX>"
94 L" <Payload Id='WixStandardBootstrapperApplication.RtfLicense' FilePath='wixstdba.dll' FileSize='1312768' Hash='B331BC5C819F019981D2524C48CC370DE2BFE9F8' Packaging='embedded' SourcePath='u0' />"
95 L" <Payload Id='payF3wjO.aj6M8ftq9wrfYB1N4aw4g' FilePath='thm.xml' FileSize='8048' Hash='A712A9E1427A4EE1D0B68343A54019A3FC9967CB' Packaging='embedded' SourcePath='u1' />"
96 L" <Payload Id='payViPRdlZD7MPIBgwmX2Hv5C6oKt4' FilePath='thm.wxl' FileSize='3926' Hash='B88FAB9B6C2B52FBE017F91B0915781C6B76058E' Packaging='embedded' SourcePath='u2' />"
97 L" <Payload Id='payjqSD44latbvJnf4vAQuVMUST73A' FilePath='logo.png' FileSize='852' Hash='239F10674BF6022854C1F1BF7C91955BDE34D3E4' Packaging='embedded' SourcePath='u3' />"
98 L" <Payload Id='pay60yHh1x6HODo4M_38Pud7jhl2Ig' FilePath='license.rtf' FileSize='4908' Hash='383034848F8CC4F3C8E795CC0F4D716A285E9465' Packaging='embedded' SourcePath='u4' />"
99 L" <Payload Id='uxTxMXPVMXwQrPTMIGa5WGt93w0Ns' FilePath='BootstrapperApplicationData.xml' FileSize='3854' Hash='2807D2AB42585125D18B7DCE49DB6454A1AFC367' Packaging='embedded' SourcePath='u5' />"
100 L" </UX>"
101 L" <Container Id='WixAttachedContainer' FileSize='6486' Hash='944E8702BD8DCDB1E41C47033115B690CED42033' FilePath='BundleC.exe' AttachedIndex='1' Attached='yes' Primary='yes' />"
102 L" <Payload Id='PackageE' FilePath='~manual_PackageE.msi' FileSize='32768' Hash='EB5B931CFCD724391A014A93A9B41037AEE57EC5' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />"
103 L" <Payload Id='cabkAPka1fWa1PyiVdoVPuoB6Qvs3k' FilePath='cab1.cab' FileSize='973' Hash='A0D42DE329CFCF0AF60D5FFA902C7E53DD5F3B4F' Packaging='embedded' SourcePath='a1' Container='WixAttachedContainer' />"
104 L" <RollbackBoundary Id='WixDefaultBoundary' Vital='yes' Transaction='no' />"
105 L" <Registration Id='{4a04385a-0081-44ba-acd1-9e4e95cfc97f}' ExecutableName='BundleC.exe' PerMachine='yes' Tag='' Version='1.0.0.0' ProviderKey='{4a04385a-0081-44ba-acd1-9e4e95cfc97f}'>"
106 L" <Arp Register='yes' DisplayName='~manual - Bundle B' DisplayVersion='1.0.0.0' />"
107 L" </Registration>"
108 L" <Chain>"
109 L" <MsiPackage Id='PackageE' Cache='yes' CacheId='{284F56B6-B6C7-404A-B9B5-78F63BF79494}v1.0.0.0' InstallSize='1640' Size='33741' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_PackageE' RollbackLogPathVariable='WixBundleRollbackLog_PackageE' ProductCode='{284F56B6-B6C7-404A-B9B5-78F63BF79494}' Language='1033' Version='1.0.0.0' UpgradeCode='{04ABCDBB-2C66-4338-9B1D-DE2AC9B0D1C2}'>"
110 L" <MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />"
111 L" <MsiProperty Id='MSIFASTINSTALL' Value='7' />"
112 L" <Provides Key='{284F56B6-B6C7-404A-B9B5-78F63BF79494}' DisplayName='~manual - E' />"
113 L" <RelatedPackage Id='{04ABCDBB-2C66-4338-9B1D-DE2AC9B0D1C2}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'>"
114 L" <Language Id='1033' />"
115 L" </RelatedPackage>"
116 L" <RelatedPackage Id='{04ABCDBB-2C66-4338-9B1D-DE2AC9B0D1C2}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'>"
117 L" <Language Id='1033' />"
118 L" </RelatedPackage>"
119 L" <PayloadRef Id='PackageE' />"
120 L" <PayloadRef Id='cabkAPka1fWa1PyiVdoVPuoB6Qvs3k' />"
121 L" </MsiPackage>"
122 L" </Chain>"
123 L"</Bundle>";
124
125namespace Microsoft
126{
127namespace Tools
128{
129namespace WindowsInstallerXml
130{
131namespace Test
132{
133namespace Bootstrapper
134{
135 using namespace System;
136 using namespace Xunit;
137
138 public ref class PlanTest : BurnUnitTest
139 {
140 public:
141 PlanTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture)
142 {
143 }
144
145 [Fact]
146 void MsiTransactionInstallTest()
147 {
148 HRESULT hr = S_OK;
149 BURN_ENGINE_STATE engineState = { };
150 BURN_ENGINE_STATE* pEngineState = &engineState;
151 BURN_PLAN* pPlan = &engineState.plan;
152
153 InitializeEngineStateForCorePlan(wzMsiTransactionManifest, pEngineState);
154 DetectPackagesAsAbsent(pEngineState);
155 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"1.0.0.0");
156
157 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
158 NativeAssert::Succeeded(hr, "CorePlan failed");
159
160 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
161 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
162 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
163 Assert::Equal<BOOL>(FALSE, pPlan->fKeepRegistrationDefault);
164
165 BOOL fRollback = FALSE;
166 DWORD dwIndex = 0;
167 DWORD dwPackageStart = 0;
168 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
169 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageA", 6, 2, 33741, FALSE);
170 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE);
171 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 6);
172 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"PackageA", TRUE, FALSE, dwPackageStart);
173 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageA", L"cab1QmlL013Hqv_44W64R0cvnHn_2c", TRUE, FALSE, dwPackageStart);
174 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
175 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
176 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 8);
177 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageB", 14, 2, 33753, FALSE);
178 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE);
179 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2);
180 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageB", L"PackageB", TRUE, FALSE, dwPackageStart);
181 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageB", L"cabQH1Sgh7w2K8tLIftUaaWVhMWt0s", TRUE, FALSE, dwPackageStart);
182 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageB", FALSE);
183 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
184 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
185 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageC", 22, 2, 33739, FALSE);
186 ValidateCacheAcquireContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", TRUE);
187 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, dwPackageStart, 2);
188 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageC", L"PackageC", TRUE, FALSE, dwPackageStart);
189 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageC", L"cabRT8kdm93olnEAQB2GSO3u0400VI", TRUE, FALSE, dwPackageStart);
190 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageC", FALSE);
191 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
192 Assert::Equal(24ul, pPlan->cCacheActions);
193
194 fRollback = TRUE;
195 dwIndex = 0;
196 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
197 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE);
198 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 8);
199 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageB", FALSE);
200 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
201 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageC", FALSE);
202 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
203
204 Assert::Equal(106166ull, pPlan->qwEstimatedSize);
205 Assert::Equal(101233ull, pPlan->qwCacheSizeTotal);
206
207 fRollback = FALSE;
208 dwIndex = 0;
209 DWORD dwExecuteCheckpointId = 2;
210 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
211 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[7].syncpoint.hEvent);
212 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
213 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
214 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
215 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
216 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
217 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
218 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
219 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
220 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
221 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
222 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
223 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[15].syncpoint.hEvent);
224 dwExecuteCheckpointId = 9;
225 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
226 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
227 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER);
228 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
229 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
230 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
231 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
232 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
233 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent);
234 dwExecuteCheckpointId = 15;
235 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
236 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
237 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER);
238 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
239 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
240 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
241 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
242 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
243 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
244 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[23].syncpoint.hEvent);
245 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
246 Assert::Equal(34ul, pPlan->cExecuteActions);
247
248 fRollback = TRUE;
249 dwIndex = 0;
250 dwExecuteCheckpointId = 2;
251 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
252 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
253 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
254 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
255 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
256 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
257 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
258 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
259 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
260 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
261 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
262 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
263 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
264 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
265 dwExecuteCheckpointId = 9;
266 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
267 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER);
268 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
269 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
270 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
271 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
272 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
273 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
274 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageC");
275 dwExecuteCheckpointId = 15;
276 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
277 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER);
278 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
279 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
280 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
281 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
282 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
283 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
284 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
285 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
286 Assert::Equal(33ul, pPlan->cRollbackActions);
287
288 Assert::Equal(4ul, pPlan->cExecutePackagesTotal);
289 Assert::Equal(7ul, pPlan->cOverallProgressTicksTotal);
290
291 dwIndex = 0;
292 Assert::Equal(dwIndex, pPlan->cCleanActions);
293
294 UINT uIndex = 0;
295 ValidatePlannedProvider(pPlan, uIndex++, L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", NULL);
296 Assert::Equal(uIndex, pPlan->cPlannedProviders);
297 }
298
299 [Fact]
300 void MsiTransactionUninstallTest()
301 {
302 HRESULT hr = S_OK;
303 BURN_ENGINE_STATE engineState = { };
304 BURN_ENGINE_STATE* pEngineState = &engineState;
305 BURN_PLAN* pPlan = &engineState.plan;
306
307 InitializeEngineStateForCorePlan(wzMsiTransactionManifest, pEngineState);
308 DetectPackagesAsPresentAndCached(pEngineState);
309
310 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL);
311 NativeAssert::Succeeded(hr, "CorePlan failed");
312
313 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
314 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
315 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
316 Assert::Equal<BOOL>(TRUE, pPlan->fKeepRegistrationDefault);
317
318 BOOL fRollback = FALSE;
319 DWORD dwIndex = 0;
320 Assert::Equal(dwIndex, pPlan->cCacheActions);
321
322 fRollback = TRUE;
323 dwIndex = 0;
324 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
325
326 Assert::Equal(0ull, pPlan->qwEstimatedSize);
327 Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
328
329 fRollback = FALSE;
330 dwIndex = 0;
331 DWORD dwExecuteCheckpointId = 1;
332 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
333 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
334 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
335 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
336 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_UNREGISTER);
337 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
338 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
339 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
340 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
341 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
342 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
343 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_UNREGISTER);
344 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
345 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
346 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
347 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
348 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
349 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
350 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_UNREGISTER);
351 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
352 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
353 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
354 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
355 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
356 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
357 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
358 Assert::Equal(dwIndex, pPlan->cExecuteActions);
359
360 fRollback = TRUE;
361 dwIndex = 0;
362 dwExecuteCheckpointId = 1;
363 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ", TRUE, TRUE);
364 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageC", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
365 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
366 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageC", BURN_DEPENDENCY_ACTION_REGISTER);
367 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
368 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageC", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
369 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
370 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
371 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageB", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
372 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
373 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageB", BURN_DEPENDENCY_ACTION_REGISTER);
374 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
375 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageB", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
376 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
377 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
378 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
379 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
380 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", BURN_DEPENDENCY_ACTION_REGISTER);
381 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
382 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
383 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
384 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
385 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
386 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
387 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
388 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
389 Assert::Equal(dwIndex, pPlan->cRollbackActions);
390
391 Assert::Equal(3ul, pPlan->cExecutePackagesTotal);
392 Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal);
393
394 dwIndex = 0;
395 ValidateCleanAction(pPlan, dwIndex++, L"PackageC");
396 ValidateCleanAction(pPlan, dwIndex++, L"PackageB");
397 ValidateCleanAction(pPlan, dwIndex++, L"PackageA");
398 Assert::Equal(dwIndex, pPlan->cCleanActions);
399
400 UINT uIndex = 0;
401 ValidatePlannedProvider(pPlan, uIndex++, L"{c096190a-8bf3-4342-a1d2-94ea9cb853d6}", NULL);
402 ValidatePlannedProvider(pPlan, uIndex++, L"{BE27CF2B-9E5F-4500-BAE3-5E0E522FB962}", NULL);
403 ValidatePlannedProvider(pPlan, uIndex++, L"{388E4963-13AD-4EE7-B907-AA8888F50E54}", NULL);
404 ValidatePlannedProvider(pPlan, uIndex++, L"{196E43EA-EF92-4FF8-B9AC-A0FD0D225BB4}", NULL);
405 Assert::Equal(uIndex, pPlan->cPlannedProviders);
406 }
407
408 [Fact]
409 void SingleMsiInstallTest()
410 {
411 HRESULT hr = S_OK;
412 BURN_ENGINE_STATE engineState = { };
413 BURN_ENGINE_STATE* pEngineState = &engineState;
414 BURN_PLAN* pPlan = &engineState.plan;
415
416 InitializeEngineStateForCorePlan(wzSingleMsiManifest, pEngineState);
417 DetectAttachedContainerAsAttached(pEngineState);
418 DetectPackagesAsAbsent(pEngineState);
419 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0");
420
421 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_INSTALL);
422 NativeAssert::Succeeded(hr, "CorePlan failed");
423
424 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_INSTALL, pPlan->action);
425 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
426 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
427 Assert::Equal<BOOL>(FALSE, pPlan->fKeepRegistrationDefault);
428
429 BOOL fRollback = FALSE;
430 DWORD dwIndex = 0;
431 DWORD dwPackageStart = 0;
432 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
433 dwPackageStart = ValidateCachePackageStart(pPlan, fRollback, dwIndex++, L"PackageE", 5, 2, 33741, FALSE);
434 ValidateCacheExtractContainer(pPlan, fRollback, dwIndex++, L"WixAttachedContainer", FALSE, BURN_PLAN_INVALID_ACTION_INDEX, 2);
435 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageE", L"PackageE", TRUE, FALSE, dwPackageStart);
436 ValidateCacheCachePayload(pPlan, fRollback, dwIndex++, L"PackageE", L"cabkAPka1fWa1PyiVdoVPuoB6Qvs3k", TRUE, FALSE, dwPackageStart);
437 ValidateCachePackageStop(pPlan, fRollback, dwIndex++, L"PackageE", FALSE);
438 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, FALSE);
439 Assert::Equal(dwIndex, pPlan->cCacheActions);
440
441 fRollback = TRUE;
442 dwIndex = 0;
443 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
444 ValidateCacheRollbackPackage(pPlan, fRollback, dwIndex++, L"PackageE", FALSE);
445 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
446
447 Assert::Equal(35381ull, pPlan->qwEstimatedSize);
448 Assert::Equal(33741ull, pPlan->qwCacheSizeTotal);
449
450 fRollback = FALSE;
451 dwIndex = 0;
452 DWORD dwExecuteCheckpointId = 2;
453 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
454 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent);
455 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
456 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
457 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageE", BURN_DEPENDENCY_ACTION_REGISTER);
458 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
459 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageE", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
460 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
461 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
462 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageE", L"{4a04385a-0081-44ba-acd1-9e4e95cfc97f}", BURN_DEPENDENCY_ACTION_REGISTER);
463 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
464 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
465 ValidateExecuteWaitSyncpoint(pPlan, fRollback, dwIndex++, pPlan->rgCacheActions[6].syncpoint.hEvent);
466 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
467 Assert::Equal(dwIndex, pPlan->cExecuteActions);
468
469 fRollback = TRUE;
470 dwIndex = 0;
471 dwExecuteCheckpointId = 2;
472 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
473 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
474 ValidateExecuteUncachePackage(pPlan, fRollback, dwIndex++, L"PackageE");
475 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
476 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageE", BURN_DEPENDENCY_ACTION_UNREGISTER);
477 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
478 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageE", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
479 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
480 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageE", L"{4a04385a-0081-44ba-acd1-9e4e95cfc97f}", BURN_DEPENDENCY_ACTION_UNREGISTER);
481 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
482 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
483 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
484 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
485 Assert::Equal(dwIndex, pPlan->cRollbackActions);
486
487 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
488 Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal);
489
490 dwIndex = 0;
491 Assert::Equal(dwIndex, pPlan->cCleanActions);
492
493 UINT uIndex = 0;
494 ValidatePlannedProvider(pPlan, uIndex++, L"{4a04385a-0081-44ba-acd1-9e4e95cfc97f}", NULL);
495 Assert::Equal(uIndex, pPlan->cPlannedProviders);
496 }
497
498 [Fact]
499 void SingleMsiUninstallTest()
500 {
501 HRESULT hr = S_OK;
502 BURN_ENGINE_STATE engineState = { };
503 BURN_ENGINE_STATE* pEngineState = &engineState;
504 BURN_PLAN* pPlan = &engineState.plan;
505
506 InitializeEngineStateForCorePlan(wzSingleMsiManifest, pEngineState);
507 DetectPackagesAsPresentAndCached(pEngineState);
508
509 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL);
510 NativeAssert::Succeeded(hr, "CorePlan failed");
511
512 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
513 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
514 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
515 Assert::Equal<BOOL>(TRUE, pPlan->fKeepRegistrationDefault);
516
517 BOOL fRollback = FALSE;
518 DWORD dwIndex = 0;
519 Assert::Equal(dwIndex, pPlan->cCacheActions);
520
521 fRollback = TRUE;
522 dwIndex = 0;
523 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
524
525 Assert::Equal(0ull, pPlan->qwEstimatedSize);
526 Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
527
528 fRollback = FALSE;
529 dwIndex = 0;
530 DWORD dwExecuteCheckpointId = 1;
531 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
532 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
533 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageE", L"{4a04385a-0081-44ba-acd1-9e4e95cfc97f}", BURN_DEPENDENCY_ACTION_UNREGISTER);
534 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
535 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageE", BURN_DEPENDENCY_ACTION_UNREGISTER);
536 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
537 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageE", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
538 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, FALSE);
539 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
540 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
541 Assert::Equal(dwIndex, pPlan->cExecuteActions);
542
543 fRollback = TRUE;
544 dwIndex = 0;
545 dwExecuteCheckpointId = 1;
546 ValidateExecuteRollbackBoundary(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
547 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageE", L"{4a04385a-0081-44ba-acd1-9e4e95cfc97f}", BURN_DEPENDENCY_ACTION_REGISTER);
548 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
549 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageE", BURN_DEPENDENCY_ACTION_REGISTER);
550 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
551 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageE", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, 0);
552 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
553 ValidateExecuteRegistration(pPlan, fRollback, dwIndex++, TRUE);
554 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
555 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
556 Assert::Equal(dwIndex, pPlan->cRollbackActions);
557
558 Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
559 Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal);
560
561 dwIndex = 0;
562 ValidateCleanAction(pPlan, dwIndex++, L"PackageE");
563 Assert::Equal(dwIndex, pPlan->cCleanActions);
564
565 UINT uIndex = 0;
566 ValidatePlannedProvider(pPlan, uIndex++, L"{4a04385a-0081-44ba-acd1-9e4e95cfc97f}", NULL);
567 ValidatePlannedProvider(pPlan, uIndex++, L"{284F56B6-B6C7-404A-B9B5-78F63BF79494}", NULL);
568 Assert::Equal(uIndex, pPlan->cPlannedProviders);
569 }
570
571 private:
572 // This doesn't initialize everything, just enough for CorePlan to work.
573 void InitializeEngineStateForCorePlan(LPCWSTR wzManifest, BURN_ENGINE_STATE* pEngineState)
574 {
575 HRESULT hr = S_OK;
576
577 ::InitializeCriticalSection(&pEngineState->csActive);
578 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
579
580 hr = VariableInitialize(&pEngineState->variables);
581 NativeAssert::Succeeded(hr, "Failed to initialize variables.");
582
583 hr = ManifestLoadXml(wzManifest, pEngineState);
584 NativeAssert::Succeeded(hr, "Failed to load manifest.");
585
586 pEngineState->userExperience.pfnBAProc = PlanTestBAProc;
587 }
588
589 void DetectAttachedContainerAsAttached(BURN_ENGINE_STATE* pEngineState)
590 {
591 for (DWORD i = 0; i < pEngineState->containers.cContainers; ++i)
592 {
593 BURN_CONTAINER* pContainer = pEngineState->containers.rgContainers + i;
594 if (pContainer->fAttached)
595 {
596 pContainer->fActuallyAttached = TRUE;
597 }
598 }
599 }
600
601 void DetectPackagesAsAbsent(BURN_ENGINE_STATE* pEngineState)
602 {
603 DetectReset(&pEngineState->registration, &pEngineState->packages);
604 PlanReset(&pEngineState->plan, &pEngineState->packages);
605
606 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
607 {
608 BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
609 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
610 }
611 }
612
613 void DetectPackagesAsPresentAndCached(BURN_ENGINE_STATE* pEngineState)
614 {
615 DetectReset(&pEngineState->registration, &pEngineState->packages);
616 PlanReset(&pEngineState->plan, &pEngineState->packages);
617
618 pEngineState->registration.fInstalled = TRUE;
619
620 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
621 {
622 BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
623 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
624 pPackage->cache = BURN_CACHE_STATE_COMPLETE;
625
626 for (DWORD j = 0; j < pPackage->cPayloads; ++j)
627 {
628 pPackage->rgPayloads[j].fCached = TRUE;
629 }
630 }
631 }
632
633 HRESULT DetectUpgradeBundle(
634 __in BURN_ENGINE_STATE* pEngineState,
635 __in LPCWSTR wzId,
636 __in LPCWSTR wzVersion
637 )
638 {
639 HRESULT hr = S_OK;
640 BURN_RELATED_BUNDLES* pRelatedBundles = &pEngineState->registration.relatedBundles;
641 BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
642
643 hr = StrAllocString(&dependencyProvider.sczKey, wzId, 0);
644 ExitOnFailure(hr, "Failed to copy provider key");
645
646 dependencyProvider.fImported = TRUE;
647
648 hr = StrAllocString(&dependencyProvider.sczVersion, wzVersion, 0);
649 ExitOnFailure(hr, "Failed to copy version");
650
651 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pRelatedBundles->rgRelatedBundles), pRelatedBundles->cRelatedBundles + 1, sizeof(BURN_RELATED_BUNDLE), 5);
652 ExitOnFailure(hr, "Failed to ensure there is space for related bundles.");
653
654 BURN_RELATED_BUNDLE* pRelatedBundle = pRelatedBundles->rgRelatedBundles + pRelatedBundles->cRelatedBundles;
655
656 hr = VerParseVersion(wzVersion, 0, FALSE, &pRelatedBundle->pVersion);
657 ExitOnFailure(hr, "Failed to parse pseudo bundle version: %ls", wzVersion);
658
659 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
660
661 hr = PseudoBundleInitialize(0, &pRelatedBundle->package, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, NULL, NULL, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0);
662 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
663
664 ++pRelatedBundles->cRelatedBundles;
665
666 LExit:
667 return hr;
668 }
669
670 void ValidateCacheAcquireContainer(
671 __in BURN_PLAN* pPlan,
672 __in BOOL fRollback,
673 __in DWORD dwIndex,
674 __in LPCWSTR wzContainerId,
675 __in BOOL fSkipUntilRetried
676 )
677 {
678 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
679 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ACQUIRE_CONTAINER, pAction->type);
680 NativeAssert::StringEqual(wzContainerId, pAction->extractContainer.pContainer->sczId);
681 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
682 }
683
684 BURN_CACHE_ACTION* ValidateCacheActionExists(BURN_PLAN* pPlan, BOOL fRollback, DWORD dwIndex)
685 {
686 Assert::InRange(dwIndex + 1ul, 1ul, (fRollback ? pPlan->cRollbackCacheActions : pPlan->cCacheActions));
687 return (fRollback ? pPlan->rgRollbackCacheActions : pPlan->rgCacheActions) + dwIndex;
688 }
689
690 void ValidateCacheCachePayload(
691 __in BURN_PLAN* pPlan,
692 __in BOOL fRollback,
693 __in DWORD dwIndex,
694 __in LPCWSTR wzPackageId,
695 __in LPCWSTR wzPayloadId,
696 __in BOOL fMove,
697 __in BOOL fSkipUntilRetried,
698 __in DWORD iTryAgainAction
699 )
700 {
701 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
702 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_CACHE_PAYLOAD, pAction->type);
703 NativeAssert::StringEqual(wzPackageId, pAction->cachePayload.pPackage->sczId);
704 NativeAssert::StringEqual(wzPayloadId, pAction->cachePayload.pPayload->sczKey);
705 Assert::Equal<BOOL>(fMove, pAction->cachePayload.fMove);
706 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
707 Assert::Equal(iTryAgainAction, pAction->cachePayload.iTryAgainAction);
708 }
709
710 void ValidateCacheCheckpoint(
711 __in BURN_PLAN* pPlan,
712 __in BOOL fRollback,
713 __in DWORD dwIndex,
714 __in DWORD dwId
715 )
716 {
717 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
718 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_CHECKPOINT, pAction->type);
719 Assert::Equal(dwId, pAction->checkpoint.dwId);
720 }
721
722 void ValidateCacheExtractContainer(
723 __in BURN_PLAN* pPlan,
724 __in BOOL fRollback,
725 __in DWORD dwIndex,
726 __in LPCWSTR wzContainerId,
727 __in BOOL fSkipUntilRetried,
728 __in DWORD iSkipUntilAcquiredByAction,
729 __in DWORD cPayloads
730 )
731 {
732 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
733 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_EXTRACT_CONTAINER, pAction->type);
734 NativeAssert::StringEqual(wzContainerId, pAction->extractContainer.pContainer->sczId);
735 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
736 Assert::Equal(iSkipUntilAcquiredByAction, pAction->extractContainer.iSkipUntilAcquiredByAction);
737 Assert::Equal(cPayloads, pAction->extractContainer.cPayloads);
738 }
739
740 DWORD ValidateCachePackageStart(
741 __in BURN_PLAN* pPlan,
742 __in BOOL fRollback,
743 __in DWORD dwIndex,
744 __in LPCWSTR wzPackageId,
745 __in DWORD iPackageCompleteAction,
746 __in DWORD cCachePayloads,
747 __in DWORD64 qwCachePayloadSizeTotal,
748 __in BOOL fSkipUntilRetried
749 )
750 {
751 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
752 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE_START, pAction->type);
753 NativeAssert::StringEqual(wzPackageId, pAction->packageStart.pPackage->sczId);
754 Assert::Equal(iPackageCompleteAction, pAction->packageStart.iPackageCompleteAction);
755 Assert::Equal(cCachePayloads, pAction->packageStart.cCachePayloads);
756 Assert::Equal(qwCachePayloadSizeTotal, pAction->packageStart.qwCachePayloadSizeTotal);
757 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
758 return dwIndex + 1;
759 }
760
761 void ValidateCachePackageStop(
762 __in BURN_PLAN* pPlan,
763 __in BOOL fRollback,
764 __in DWORD dwIndex,
765 __in LPCWSTR wzPackageId,
766 __in BOOL fSkipUntilRetried
767 )
768 {
769 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
770 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE_STOP, pAction->type);
771 NativeAssert::StringEqual(wzPackageId, pAction->packageStop.pPackage->sczId);
772 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
773 }
774
775 void ValidateCacheRollbackPackage(
776 __in BURN_PLAN* pPlan,
777 __in BOOL fRollback,
778 __in DWORD dwIndex,
779 __in LPCWSTR wzPackageId,
780 __in BOOL fSkipUntilRetried
781 )
782 {
783 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
784 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE, pAction->type);
785 NativeAssert::StringEqual(wzPackageId, pAction->rollbackPackage.pPackage->sczId);
786 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
787 }
788
789 void ValidateCacheSignalSyncpoint(
790 __in BURN_PLAN* pPlan,
791 __in BOOL fRollback,
792 __in DWORD dwIndex,
793 __in BOOL fSkipUntilRetried
794 )
795 {
796 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
797 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT, pAction->type);
798 Assert::NotEqual((DWORD_PTR)NULL, (DWORD_PTR)pAction->syncpoint.hEvent);
799 Assert::Equal<BOOL>(fSkipUntilRetried, pAction->fSkipUntilRetried);
800 }
801
802 void ValidateCleanAction(
803 __in BURN_PLAN* pPlan,
804 __in DWORD dwIndex,
805 __in LPCWSTR wzPackageId
806 )
807 {
808 Assert::InRange(dwIndex + 1ul, 1ul, pPlan->cCleanActions);
809
810 BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + dwIndex;
811 Assert::NotEqual((DWORD_PTR)0, (DWORD_PTR)pCleanAction->pPackage);
812 NativeAssert::StringEqual(wzPackageId, pCleanAction->pPackage->sczId);
813 }
814
815 BURN_EXECUTE_ACTION* ValidateExecuteActionExists(BURN_PLAN* pPlan, BOOL fRollback, DWORD dwIndex)
816 {
817 Assert::InRange(dwIndex + 1ul, 1ul, (fRollback ? pPlan->cRollbackActions : pPlan->cExecuteActions));
818 return (fRollback ? pPlan->rgRollbackActions : pPlan->rgExecuteActions) + dwIndex;
819 }
820
821 void ValidateExecuteCheckpoint(
822 __in BURN_PLAN* pPlan,
823 __in BOOL fRollback,
824 __in DWORD dwIndex,
825 __in DWORD dwId
826 )
827 {
828 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
829 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_CHECKPOINT, pAction->type);
830 Assert::Equal(dwId, pAction->checkpoint.dwId);
831 }
832
833 void ValidateExecuteExePackage(
834 __in BURN_PLAN* pPlan,
835 __in BOOL fRollback,
836 __in DWORD dwIndex,
837 __in LPCWSTR wzPackageId,
838 __in BOOTSTRAPPER_ACTION_STATE action,
839 __in LPCWSTR wzIgnoreDependencies
840 )
841 {
842 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
843 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
844 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
845 Assert::Equal<DWORD>(action, pAction->exePackage.action);
846 NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
847 }
848
849 void ValidateExecuteMsiPackage(
850 __in BURN_PLAN* pPlan,
851 __in BOOL fRollback,
852 __in DWORD dwIndex,
853 __in LPCWSTR wzPackageId,
854 __in BOOTSTRAPPER_ACTION_STATE action,
855 __in BURN_MSI_PROPERTY actionMsiProperty,
856 __in DWORD uiLevel,
857 __in BOOL fDisableExternalUiHandler,
858 __in DWORD dwLoggingAttributes
859 )
860 {
861 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
862 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, pAction->type);
863 NativeAssert::StringEqual(wzPackageId, pAction->msiPackage.pPackage->sczId);
864 Assert::Equal<DWORD>(action, pAction->msiPackage.action);
865 Assert::Equal<DWORD>(actionMsiProperty, pAction->msiPackage.actionMsiProperty);
866 Assert::Equal<DWORD>(uiLevel, pAction->msiPackage.uiLevel);
867 Assert::Equal<BOOL>(fDisableExternalUiHandler, pAction->msiPackage.fDisableExternalUiHandler);
868 NativeAssert::NotNull(pAction->msiPackage.sczLogPath);
869 Assert::Equal<DWORD>(dwLoggingAttributes, pAction->msiPackage.dwLoggingAttributes);
870 }
871
872 void ValidateExecutePackageDependency(
873 __in BURN_PLAN* pPlan,
874 __in BOOL fRollback,
875 __in DWORD dwIndex,
876 __in LPCWSTR wzPackageId,
877 __in LPCWSTR wzBundleProviderKey,
878 __in BURN_DEPENDENCY_ACTION action
879 )
880 {
881 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
882 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY, pAction->type);
883 NativeAssert::StringEqual(wzPackageId, pAction->packageDependency.pPackage->sczId);
884 NativeAssert::StringEqual(wzBundleProviderKey, pAction->packageDependency.sczBundleProviderKey);
885 Assert::Equal<DWORD>(action, pAction->packageDependency.action);
886 }
887
888 void ValidateExecutePackageProvider(
889 __in BURN_PLAN* pPlan,
890 __in BOOL fRollback,
891 __in DWORD dwIndex,
892 __in LPCWSTR wzPackageId,
893 __in BURN_DEPENDENCY_ACTION action
894 )
895 {
896 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
897 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER, pAction->type);
898 NativeAssert::StringEqual(wzPackageId, pAction->packageProvider.pPackage->sczId);
899 Assert::Equal<DWORD>(action, pAction->packageProvider.action);
900 }
901
902 void ValidateExecuteRegistration(
903 __in BURN_PLAN* pPlan,
904 __in BOOL fRollback,
905 __in DWORD dwIndex,
906 __in BOOL fKeep
907 )
908 {
909 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
910 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_REGISTRATION, pAction->type);
911 Assert::Equal<BOOL>(fKeep, pAction->registration.fKeep);
912 }
913
914 void ValidateExecuteRollbackBoundary(
915 __in BURN_PLAN* pPlan,
916 __in BOOL fRollback,
917 __in DWORD dwIndex,
918 __in LPCWSTR wzId,
919 __in BOOL fVital,
920 __in BOOL fTransaction
921 )
922 {
923 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
924 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_ROLLBACK_BOUNDARY, pAction->type);
925 NativeAssert::StringEqual(wzId, pAction->rollbackBoundary.pRollbackBoundary->sczId);
926 Assert::Equal<BOOL>(fVital, pAction->rollbackBoundary.pRollbackBoundary->fVital);
927 Assert::Equal<BOOL>(fTransaction, pAction->rollbackBoundary.pRollbackBoundary->fTransaction);
928 }
929
930 void ValidateExecuteUncachePackage(
931 __in BURN_PLAN* pPlan,
932 __in BOOL fRollback,
933 __in DWORD dwIndex,
934 __in LPCWSTR wzPackageId
935 )
936 {
937 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
938 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE, pAction->type);
939 NativeAssert::StringEqual(wzPackageId, pAction->uncachePackage.pPackage->sczId);
940 }
941
942 void ValidateExecuteWaitSyncpoint(
943 __in BURN_PLAN* pPlan,
944 __in BOOL fRollback,
945 __in DWORD dwIndex,
946 __in HANDLE hEvent
947 )
948 {
949 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
950 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_WAIT_SYNCPOINT, pAction->type);
951 Assert::Equal((DWORD_PTR)hEvent, (DWORD_PTR)pAction->syncpoint.hEvent);
952 }
953
954 void ValidatePlannedProvider(
955 __in BURN_PLAN* pPlan,
956 __in UINT uIndex,
957 __in LPCWSTR wzKey,
958 __in LPCWSTR wzName
959 )
960 {
961 Assert::InRange(uIndex + 1u, 1u, pPlan->cPlannedProviders);
962
963 DEPENDENCY* pProvider = pPlan->rgPlannedProviders + uIndex;
964 NativeAssert::StringEqual(wzKey, pProvider->sczKey);
965 NativeAssert::StringEqual(wzName, pProvider->sczName);
966 }
967 };
968}
969}
970}
971}
972}
973
974static HRESULT WINAPI PlanTestBAProc(
975 __in BOOTSTRAPPER_APPLICATION_MESSAGE /*message*/,
976 __in const LPVOID /*pvArgs*/,
977 __inout LPVOID /*pvResults*/,
978 __in_opt LPVOID /*pvContext*/
979 )
980{
981 return S_OK;
982}
diff --git a/src/test/BurnUnitTest/precomp.h b/src/test/BurnUnitTest/precomp.h
index fea30156..ddbdf9c6 100644
--- a/src/test/BurnUnitTest/precomp.h
+++ b/src/test/BurnUnitTest/precomp.h
@@ -69,6 +69,7 @@
69#include "manifest.h" 69#include "manifest.h"
70#include "splashscreen.h" 70#include "splashscreen.h"
71#include "bitsengine.h" 71#include "bitsengine.h"
72#include "detect.h"
72 73
73#pragma managed 74#pragma managed
74#include <vcclr.h> 75#include <vcclr.h>