From 6d7a275edafb3ae0f3cff94d66503a82dafb71f7 Mon Sep 17 00:00:00 2001
From: Sean Hall <r.sean.hall@gmail.com>
Date: Tue, 3 Aug 2021 15:41:18 -0500
Subject: Replace static cache internals with a struct.

Initialize them explicitly to make it clearer when that happens.
---
 src/burn/engine/apply.cpp                       |  34 +-
 src/burn/engine/approvedexe.cpp                 |   3 +-
 src/burn/engine/approvedexe.h                   |   6 +
 src/burn/engine/cache.cpp                       | 505 ++++++++++++------------
 src/burn/engine/cache.h                         |  57 ++-
 src/burn/engine/core.cpp                        |  23 +-
 src/burn/engine/core.h                          |   2 +
 src/burn/engine/elevation.cpp                   |  74 ++--
 src/burn/engine/elevation.h                     |   1 +
 src/burn/engine/engine.cpp                      |  18 +-
 src/burn/engine/exeengine.cpp                   |   3 +-
 src/burn/engine/exeengine.h                     |   1 +
 src/burn/engine/manifest.cpp                    |   2 +-
 src/burn/engine/msiengine.cpp                   |  11 +-
 src/burn/engine/msiengine.h                     |   1 +
 src/burn/engine/mspengine.cpp                   |   3 +-
 src/burn/engine/mspengine.h                     |   1 +
 src/burn/engine/msuengine.cpp                   |   3 +-
 src/burn/engine/msuengine.h                     |   1 +
 src/burn/engine/plan.cpp                        |   8 +-
 src/burn/engine/plan.h                          |   3 +-
 src/burn/engine/precomp.h                       |   2 +-
 src/burn/engine/registration.cpp                |  17 +-
 src/burn/engine/registration.h                  |   3 +
 src/burn/engine/uithread.cpp                    |  12 +-
 src/burn/engine/userexperience.cpp              |   4 +-
 src/burn/engine/userexperience.h                |   4 +-
 src/burn/test/BurnUnitTest/CacheTest.cpp        |   7 +-
 src/burn/test/BurnUnitTest/ManifestTest.cpp     |   3 +
 src/burn/test/BurnUnitTest/PlanTest.cpp         |   6 +
 src/burn/test/BurnUnitTest/RegistrationTest.cpp |  78 ++--
 src/burn/test/BurnUnitTest/precomp.h            |   2 +-
 32 files changed, 526 insertions(+), 372 deletions(-)

diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index c126d63c..002158b6 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -26,6 +26,7 @@ enum BURN_CACHE_PROGRESS_TYPE
 
 typedef struct _BURN_CACHE_CONTEXT
 {
+    BURN_CACHE* pCache;
     BURN_USER_EXPERIENCE* pUX;
     BURN_VARIABLES* pVariables;
     BURN_PAYLOADS* pPayloads;
@@ -55,6 +56,7 @@ typedef struct _BURN_CACHE_PROGRESS_CONTEXT
 
 typedef struct _BURN_EXECUTE_CONTEXT
 {
+    BURN_CACHE* pCache;
     BURN_USER_EXPERIENCE* pUX;
     BURN_APPLY_CONTEXT* pApplyContext;
     BOOL fRollback;
@@ -269,6 +271,7 @@ static void ResetTransactionRegistrationState(
     __in BOOL fCommit
     );
 static HRESULT CleanPackage(
+    __in BURN_CACHE* pCache,
     __in HANDLE hElevatedPipe,
     __in BURN_PACKAGE* pPackage
     );
@@ -401,7 +404,7 @@ extern "C" HRESULT ApplyRegister(
     }
     else // need to complete registration on the machine.
     {
-        hr = CacheCalculateBundleWorkingPath(pEngineState->registration.sczId, pEngineState->registration.sczExecutableName, &sczEngineWorkingPath);
+        hr = CacheCalculateBundleWorkingPath(pEngineState->plan.pCache, pEngineState->registration.sczExecutableName, &sczEngineWorkingPath);
         ExitOnFailure(hr, "Failed to calculate working path for engine.");
 
         // begin new session
@@ -412,7 +415,7 @@ extern "C" HRESULT ApplyRegister(
         }
         else
         {
-            hr = RegistrationSessionBegin(sczEngineWorkingPath, &pEngineState->registration, &pEngineState->variables, pEngineState->plan.dwRegistrationOperations, pEngineState->plan.dependencyRegistrationAction, pEngineState->plan.qwEstimatedSize, registrationType);
+            hr = RegistrationSessionBegin(sczEngineWorkingPath, &pEngineState->registration, &pEngineState->cache, &pEngineState->variables, pEngineState->plan.dwRegistrationOperations, pEngineState->plan.dependencyRegistrationAction, pEngineState->plan.qwEstimatedSize, registrationType);
             ExitOnFailure(hr, "Failed to begin registration session.");
         }
     }
@@ -501,7 +504,7 @@ extern "C" HRESULT ApplyUnregister(
     }
     else
     {
-        hr = RegistrationSessionEnd(&pEngineState->registration, &pEngineState->variables, &pEngineState->packages, resumeMode, restart, pEngineState->plan.dependencyRegistrationAction, registrationType);
+        hr = RegistrationSessionEnd(&pEngineState->registration, &pEngineState->cache, &pEngineState->variables, &pEngineState->packages, resumeMode, restart, pEngineState->plan.dependencyRegistrationAction, registrationType);
         ExitOnFailure(hr, "Failed to end session in per-user process.");
     }
 
@@ -531,6 +534,7 @@ extern "C" HRESULT ApplyCache(
     ExitOnRootFailure(hr, "BA aborted cache.");
 
     cacheContext.hSourceEngineFile = hSourceEngineFile;
+    cacheContext.pCache = pPlan->pCache;
     cacheContext.pPayloads = pPlan->pPayloads;
     cacheContext.pUX = pUX;
     cacheContext.pVariables = pVariables;
@@ -568,7 +572,7 @@ extern "C" HRESULT ApplyCache(
             {
                 if (!pPackage->fPerMachine || INVALID_HANDLE_VALUE == cacheContext.hPipe)
                 {
-                    hr = CachePreparePackage(pPackage);
+                    hr = CachePreparePackage(pPlan->pCache, pPackage);
 
                     cacheContext.hPipe = INVALID_HANDLE_VALUE;
                 }
@@ -616,7 +620,7 @@ LExit:
         ElevationCacheCleanup(hPipe);
     }
 
-    CacheCleanup(FALSE, pPlan->wzBundleId);
+    CacheCleanup(FALSE, pPlan->pCache);
 
     for (DWORD i = 0; i < cacheContext.cSearchPathsMax; ++i)
     {
@@ -653,6 +657,7 @@ extern "C" HRESULT ApplyExecute(
     BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL;
     BOOL fSeekNextRollbackBoundary = FALSE;
 
+    context.pCache = pEngineState->plan.pCache;
     context.pUX = &pEngineState->userExperience;
     context.pApplyContext = pApplyContext;
     context.cExecutePackagesTotal = pEngineState->plan.cExecutePackagesTotal;
@@ -762,7 +767,7 @@ extern "C" void ApplyClean(
         BURN_CLEAN_ACTION* pCleanAction = pPlan->rgCleanActions + i;
         BURN_PACKAGE* pPackage = pCleanAction->pPackage;
 
-        hr = CleanPackage(hPipe, pPackage);
+        hr = CleanPackage(pPlan->pCache, hPipe, pPackage);
     }
 }
 
@@ -1479,7 +1484,7 @@ static HRESULT AcquireContainerOrPayload(
             dwChosenSearchPath = 0;
             dwDestinationSearchPath = 0;
 
-            hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths, &dwChosenSearchPath, &dwDestinationSearchPath);
+            hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pCache, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths, &dwChosenSearchPath, &dwDestinationSearchPath);
             ExitOnFailure(hr, "Failed to search local source.");
 
             if (wzPayloadContainerId)
@@ -1710,7 +1715,7 @@ static HRESULT LayoutOrCacheContainerOrPayload(
             }
             else // complete the payload.
             {
-                hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
+                hr = CacheCompletePayload(pContext->pCache, pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
             }
         }
 
@@ -2174,7 +2179,7 @@ static void DoRollbackCache(
                 {
                     if (dwLastCheckpoint <= dwCheckpoint) // only rollback when it was attempted to be cached.
                     {
-                        hr = CleanPackage(hPipe, pPackage);
+                        hr = CleanPackage(pPlan->pCache, hPipe, pPackage);
                     }
                 }
                 else if (pPackage->fCanAffectRegistration)
@@ -2401,7 +2406,7 @@ static HRESULT DoRollbackActions(
             case BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE:
                 if (!pRollbackAction->uncachePackage.pPackage->fCached) // only rollback when it wasn't already cached.
                 {
-                    hr = CleanPackage(pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage);
+                    hr = CleanPackage(pEngineState->plan.pCache, pEngineState->companionConnection.hPipe, pRollbackAction->uncachePackage.pPackage);
                     IgnoreRollbackError(hr, "Failed to uncache package for rollback.");
                 }
                 else if (pRollbackAction->uncachePackage.pPackage->fCanAffectRegistration)
@@ -2477,7 +2482,7 @@ static HRESULT ExecuteExePackage(
     }
     else
     {
-        hrExecute = ExeEngineExecutePackage(pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
+        hrExecute = ExeEngineExecutePackage(pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
         ExitOnFailure(hrExecute, "Failed to configure per-user EXE package.");
     }
 
@@ -2548,7 +2553,7 @@ static HRESULT ExecuteMsiPackage(
     }
     else
     {
-        hrExecute = MsiEngineExecutePackage(pEngineState->userExperience.hwndApply, pExecuteAction, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart);
+        hrExecute = MsiEngineExecutePackage(pEngineState->userExperience.hwndApply, pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart);
         ExitOnFailure(hrExecute, "Failed to configure per-user MSI package.");
     }
 
@@ -2621,7 +2626,7 @@ static HRESULT ExecuteMspPackage(
     }
     else
     {
-        hrExecute = MspEngineExecutePackage(pEngineState->userExperience.hwndApply, pExecuteAction, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart);
+        hrExecute = MspEngineExecutePackage(pEngineState->userExperience.hwndApply, pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, MsiExecuteMessageHandler, pContext, pRestart);
         ExitOnFailure(hrExecute, "Failed to configure per-user MSP package.");
     }
 
@@ -2983,6 +2988,7 @@ static void ResetTransactionRegistrationState(
 }
 
 static HRESULT CleanPackage(
+    __in BURN_CACHE* pCache,
     __in HANDLE hElevatedPipe,
     __in BURN_PACKAGE* pPackage
     )
@@ -2995,7 +3001,7 @@ static HRESULT CleanPackage(
     }
     else
     {
-        hr = CacheRemovePackage(FALSE, pPackage->sczId, pPackage->sczCacheId);
+        hr = CacheRemovePackage(pCache, FALSE, pPackage->sczId, pPackage->sczCacheId);
     }
 
     if (pPackage->fCanAffectRegistration)
diff --git a/src/burn/engine/approvedexe.cpp b/src/burn/engine/approvedexe.cpp
index e3d51a47..b9efd624 100644
--- a/src/burn/engine/approvedexe.cpp
+++ b/src/burn/engine/approvedexe.cpp
@@ -211,6 +211,7 @@ LExit:
 }
 
 extern "C" HRESULT ApprovedExesVerifySecureLocation(
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe
     )
@@ -245,7 +246,7 @@ extern "C" HRESULT ApprovedExesVerifySecureLocation(
 
     // The problem with using a Variable for the root package cache folder is that it might not have been secured yet.
     // Getting it through CacheGetPerMachineRootCompletedPath makes sure it has been secured.
-    hr = CacheGetPerMachineRootCompletedPath(&scz, &sczSecondary);
+    hr = CacheGetPerMachineRootCompletedPath(pCache, &scz, &sczSecondary);
     ExitOnFailure(hr, "Failed to get the root package cache folder.");
 
     // If the package cache is redirected, hr is S_FALSE.
diff --git a/src/burn/engine/approvedexe.h b/src/burn/engine/approvedexe.h
index 23f3b1bb..076d86c4 100644
--- a/src/burn/engine/approvedexe.h
+++ b/src/burn/engine/approvedexe.h
@@ -6,6 +6,11 @@
 extern "C" {
 #endif
 
+// forward declare
+
+typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT;
+typedef struct _BURN_CACHE BURN_CACHE;
+typedef struct _BURN_ENGINE_COMMAND BURN_ENGINE_COMMAND;
 
 // structs
 
@@ -57,6 +62,7 @@ HRESULT ApprovedExesLaunch(
     __out DWORD* pdwProcessId
     );
 HRESULT ApprovedExesVerifySecureLocation(
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe
     );
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index a35b83bc..54328091 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -9,40 +9,37 @@ static const LPCWSTR PACKAGE_CACHE_FOLDER_NAME = L"Package Cache";
 static const DWORD FILE_OPERATION_RETRY_COUNT = 3;
 static const DWORD FILE_OPERATION_RETRY_WAIT = 2000;
 
-static BOOL vfInitializedCache = FALSE;
-static BOOL vfRunningFromCache = FALSE;
-static LPWSTR vsczSourceProcessFolder = NULL;
-static LPWSTR vsczWorkingFolder = NULL;
-static LPWSTR vsczDefaultUserPackageCache = NULL;
-static LPWSTR vsczDefaultMachinePackageCache = NULL;
-static LPWSTR vsczCurrentMachinePackageCache = NULL;
-
 static HRESULT CacheVerifyPayloadSignature(
     __in BURN_PAYLOAD* pPayload,
     __in_z LPCWSTR wzUnverifiedPayloadPath,
     __in HANDLE hFile
     );
 static HRESULT CalculateWorkingFolder(
-    __in_z LPCWSTR wzBundleId,
-    __deref_out_z LPWSTR* psczWorkingFolder
+    __in BURN_CACHE* pCache,
+    __in BURN_ENGINE_COMMAND* pInternalCommand
     );
 static HRESULT GetLastUsedSourceFolder(
     __in BURN_VARIABLES* pVariables,
     __out_z LPWSTR* psczLastSource
     );
-static HRESULT SecurePerMachineCacheRoot();
+static HRESULT SecurePerMachineCacheRoot(
+    __in BURN_CACHE* pCache
+    );
 static HRESULT CreateCompletedPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in LPCWSTR wzCacheId,
     __in LPCWSTR wzFilePath,
     __out_z LPWSTR* psczCachePath
     );
 static HRESULT CreateUnverifiedPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzPayloadId,
     __out_z LPWSTR* psczUnverifiedPayloadPath
     );
 static HRESULT GetRootPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in BOOL fAllowRedirect,
     __deref_out_z LPWSTR* psczRootPath
@@ -101,6 +98,7 @@ static HRESULT SecurePath(
     __in LPCWSTR wzPath
     );
 static HRESULT CopyEngineToWorkingFolder(
+    __in BURN_CACHE* pCache,
     __in_z LPCWSTR wzSourcePath,
     __in_z LPCWSTR wzWorkingFolderName,
     __in_z LPCWSTR wzExecutableName,
@@ -114,6 +112,7 @@ static HRESULT CopyEngineWithSignatureFixup(
     __in BURN_SECTION* pSection
     );
 static HRESULT RemoveBundleOrPackage(
+    __in BURN_CACHE* pCache,
     __in BOOL fBundle,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzBundleOrPackageId,
@@ -158,11 +157,79 @@ static HRESULT SendCacheCompleteMessage(
 
 
 extern "C" HRESULT CacheInitialize(
+    __in BURN_CACHE* pCache,
+    __in BURN_ENGINE_COMMAND* pInternalCommand
+    )
+{
+    Assert(!pCache->fInitializedCache);
+
+    HRESULT hr = S_OK;
+    LPWSTR sczAppData = NULL;
+    int nCompare = 0;
+
+    // Cache paths are initialized once so they cannot be changed while the engine is caching payloads.
+    // Always construct the default machine package cache path so we can determine if we're redirected.
+    hr = PathGetKnownFolder(CSIDL_COMMON_APPDATA, &sczAppData);
+    ExitOnFailure(hr, "Failed to find local %hs appdata directory.", "per-machine");
+
+    hr = PathConcat(sczAppData, PACKAGE_CACHE_FOLDER_NAME, &pCache->sczDefaultMachinePackageCache);
+    ExitOnFailure(hr, "Failed to construct %hs package cache directory name.", "per-machine");
+
+    hr = PathBackslashTerminate(&pCache->sczDefaultMachinePackageCache);
+    ExitOnFailure(hr, "Failed to backslash terminate default %hs package cache directory name.", "per-machine");
+
+
+    // The machine package cache can be redirected through policy.
+    hr = PolcReadString(POLICY_BURN_REGISTRY_PATH, L"PackageCache", NULL, &pCache->sczCurrentMachinePackageCache);
+    ExitOnFailure(hr, "Failed to read PackageCache policy directory.");
+
+    if (pCache->sczCurrentMachinePackageCache)
+    {
+        hr = PathBackslashTerminate(&pCache->sczCurrentMachinePackageCache);
+        ExitOnFailure(hr, "Failed to backslash terminate redirected per-machine package cache directory name.");
+    }
+    else
+    {
+        hr = StrAllocString(&pCache->sczCurrentMachinePackageCache, pCache->sczDefaultMachinePackageCache, 0);
+        ExitOnFailure(hr, "Failed to copy default package cache directory to current package cache directory.");
+    }
+
+    hr = PathCompare(pCache->sczDefaultMachinePackageCache, pCache->sczCurrentMachinePackageCache, &nCompare);
+    ExitOnFailure(hr, "Failed to compare default and current package cache directories.");
+
+    pCache->fCustomMachinePackageCache = CSTR_EQUAL != nCompare;
+
+
+    hr = PathGetKnownFolder(CSIDL_LOCAL_APPDATA, &sczAppData);
+    ExitOnFailure(hr, "Failed to find local %hs appdata directory.", "per-user");
+
+    hr = PathConcat(sczAppData, PACKAGE_CACHE_FOLDER_NAME, &pCache->sczDefaultUserPackageCache);
+    ExitOnFailure(hr, "Failed to construct %hs package cache directory name.", "per-user");
+
+    hr = PathBackslashTerminate(&pCache->sczDefaultUserPackageCache);
+    ExitOnFailure(hr, "Failed to backslash terminate default %hs package cache directory name.", "per-user");
+
+
+    hr = CalculateWorkingFolder(pCache, pInternalCommand);
+
+    pCache->fInitializedCache = TRUE;
+
+LExit:
+    ReleaseStr(sczAppData);
+
+    return hr;
+}
+
+
+extern "C" HRESULT CacheInitializeSources(
+    __in BURN_CACHE* pCache,
     __in BURN_REGISTRATION* pRegistration,
     __in BURN_VARIABLES* pVariables,
-    __in_z_opt LPCWSTR wzSourceProcessPath
+    __in BURN_ENGINE_COMMAND* pInternalCommand
     )
 {
+    Assert(!pCache->fInitializedCacheSources);
+
     HRESULT hr = S_OK;
     LPWSTR sczCurrentPath = NULL;
     LPWSTR sczCompletedFolder = NULL;
@@ -170,66 +237,64 @@ extern "C" HRESULT CacheInitialize(
     LPWSTR sczOriginalSource = NULL;
     LPWSTR sczOriginalSourceFolder = NULL;
     int nCompare = 0;
+    LPCWSTR wzSourceProcessPath = pInternalCommand->sczSourceProcessPath;
 
-    if (!vfInitializedCache)
-    {
-        hr = PathForCurrentProcess(&sczCurrentPath, NULL);
-        ExitOnFailure(hr, "Failed to get current process path.");
+    hr = PathForCurrentProcess(&sczCurrentPath, NULL);
+    ExitOnFailure(hr, "Failed to get current process path.");
 
-        // Determine if we are running from the package cache or not.
-        hr = CacheGetCompletedPath(pRegistration->fPerMachine, pRegistration->sczId, &sczCompletedFolder);
-        ExitOnFailure(hr, "Failed to get completed path for bundle.");
+    // Determine if we are running from the package cache or not.
+    hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczId, &sczCompletedFolder);
+    ExitOnFailure(hr, "Failed to get completed path for bundle.");
 
-        hr = PathConcat(sczCompletedFolder, pRegistration->sczExecutableName, &sczCompletedPath);
-        ExitOnFailure(hr, "Failed to combine working path with engine file name.");
+    hr = PathConcat(sczCompletedFolder, pRegistration->sczExecutableName, &sczCompletedPath);
+    ExitOnFailure(hr, "Failed to combine working path with engine file name.");
 
-        hr = PathCompare(sczCurrentPath, sczCompletedPath, &nCompare);
-        ExitOnFailure(hr, "Failed to compare current path for bundle: %ls", sczCurrentPath);
+    hr = PathCompare(sczCurrentPath, sczCompletedPath, &nCompare);
+    ExitOnFailure(hr, "Failed to compare current path for bundle: %ls", sczCurrentPath);
 
-        vfRunningFromCache = (CSTR_EQUAL == nCompare);
+    pCache->fRunningFromCache = (CSTR_EQUAL == nCompare);
 
-        // If a source process path was not provided (e.g. we are not being
-        // run in a clean room) then use the current process path as the
-        // source process path.
-        if (!wzSourceProcessPath)
-        {
-            wzSourceProcessPath = sczCurrentPath;
-        }
+    // If a source process path was not provided (e.g. we are not being
+    // run in a clean room) then use the current process path as the
+    // source process path.
+    if (!wzSourceProcessPath)
+    {
+        wzSourceProcessPath = sczCurrentPath;
+    }
 
-        hr = PathGetDirectory(wzSourceProcessPath, &vsczSourceProcessFolder);
-        ExitOnFailure(hr, "Failed to initialize cache source folder.");
+    hr = PathGetDirectory(wzSourceProcessPath, &pCache->sczSourceProcessFolder);
+    ExitOnFailure(hr, "Failed to initialize cache source folder.");
 
-        // If we're not running from the cache, ensure the original source is set.
-        if (!vfRunningFromCache)
+    // If we're not running from the cache, ensure the original source is set.
+    if (!pCache->fRunningFromCache)
+    {
+        // If the original source has not been set already then set it where the bundle is
+        // running from right now. This value will be persisted and we'll use it when launched
+        // from the clean room or package cache since none of our packages will be relative to
+        // those locations.
+        hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, &sczOriginalSource);
+        if (E_NOTFOUND == hr)
         {
-            // If the original source has not been set already then set it where the bundle is
-            // running from right now. This value will be persisted and we'll use it when launched
-            // from the clean room or package cache since none of our packages will be relative to
-            // those locations.
-            hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, &sczOriginalSource);
-            if (E_NOTFOUND == hr)
-            {
-                hr = VariableSetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, wzSourceProcessPath, FALSE, FALSE);
-                ExitOnFailure(hr, "Failed to set original source variable.");
+            hr = VariableSetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, wzSourceProcessPath, FALSE, FALSE);
+            ExitOnFailure(hr, "Failed to set original source variable.");
 
-                hr = StrAllocString(&sczOriginalSource, wzSourceProcessPath, 0);
-                ExitOnFailure(hr, "Failed to copy current path to original source.");
-            }
+            hr = StrAllocString(&sczOriginalSource, wzSourceProcessPath, 0);
+            ExitOnFailure(hr, "Failed to copy current path to original source.");
+        }
 
-            hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, &sczOriginalSourceFolder);
-            if (E_NOTFOUND == hr)
-            {
-                hr = PathGetDirectory(sczOriginalSource, &sczOriginalSourceFolder);
-                ExitOnFailure(hr, "Failed to get directory from original source path.");
+        hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, &sczOriginalSourceFolder);
+        if (E_NOTFOUND == hr)
+        {
+            hr = PathGetDirectory(sczOriginalSource, &sczOriginalSourceFolder);
+            ExitOnFailure(hr, "Failed to get directory from original source path.");
 
-                hr = VariableSetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, sczOriginalSourceFolder, FALSE, FALSE);
-                ExitOnFailure(hr, "Failed to set original source directory variable.");
-            }
+            hr = VariableSetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, sczOriginalSourceFolder, FALSE, FALSE);
+            ExitOnFailure(hr, "Failed to set original source directory variable.");
         }
-
-        vfInitializedCache = TRUE;
     }
 
+    pCache->fInitializedCacheSources = TRUE;
+
 LExit:
     ReleaseStr(sczCurrentPath);
     ReleaseStr(sczCompletedFolder);
@@ -241,99 +306,85 @@ LExit:
 }
 
 extern "C" HRESULT CacheEnsureWorkingFolder(
-    __in_z_opt LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __deref_out_z_opt LPWSTR* psczWorkingFolder
     )
 {
-    HRESULT hr = S_OK;
-    LPWSTR sczWorkingFolder = NULL;
+    Assert(pCache->fInitializedCache);
 
-    hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder);
-    ExitOnFailure(hr, "Failed to calculate working folder to ensure it exists.");
+    HRESULT hr = S_OK;
 
-    hr = DirEnsureExists(sczWorkingFolder, NULL);
+    hr = DirEnsureExists(pCache->sczWorkingFolder, NULL);
     ExitOnFailure(hr, "Failed create working folder.");
 
     // Best effort to ensure our working folder is not encrypted.
-    ::DecryptFileW(sczWorkingFolder, 0);
+    ::DecryptFileW(pCache->sczWorkingFolder, 0);
 
     if (psczWorkingFolder)
     {
-        hr = StrAllocString(psczWorkingFolder, sczWorkingFolder, 0);
+        hr = StrAllocString(psczWorkingFolder, pCache->sczWorkingFolder, 0);
         ExitOnFailure(hr, "Failed to copy working folder.");
     }
 
 LExit:
-    ReleaseStr(sczWorkingFolder);
-
     return hr;
 }
 
 extern "C" HRESULT CacheCalculateBundleWorkingPath(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in LPCWSTR wzExecutableName,
     __deref_out_z LPWSTR* psczWorkingPath
     )
 {
-    Assert(vfInitializedCache);
+    Assert(pCache->fInitializedCache);
 
     HRESULT hr = S_OK;
-    LPWSTR sczWorkingFolder = NULL;
 
     // If the bundle is running out of the package cache then we use that as the
     // working folder since we feel safe in the package cache.
-    if (vfRunningFromCache)
+    if (CacheBundleRunningFromCache(pCache))
     {
         hr = PathForCurrentProcess(psczWorkingPath, NULL);
         ExitOnFailure(hr, "Failed to get current process path.");
     }
     else // Otherwise, use the real working folder.
     {
-        hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder);
-        ExitOnFailure(hr, "Failed to get working folder for bundle.");
-
-        hr = StrAllocFormatted(psczWorkingPath, L"%ls%ls\\%ls", sczWorkingFolder, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName);
+        hr = StrAllocFormatted(psczWorkingPath, L"%ls%ls\\%ls", pCache->sczWorkingFolder, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName);
         ExitOnFailure(hr, "Failed to calculate the bundle working path.");
     }
 
 LExit:
-    ReleaseStr(sczWorkingFolder);
-
     return hr;
 }
 
 extern "C" HRESULT CacheCalculateBundleLayoutWorkingPath(
+    __in BURN_CACHE* pCache,
     __in_z LPCWSTR wzBundleId,
     __deref_out_z LPWSTR* psczWorkingPath
     )
 {
-    HRESULT hr = S_OK;
-    LPWSTR sczWorkingFolder = NULL;
+    Assert(pCache->fInitializedCache);
 
-    hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath);
-    ExitOnFailure(hr, "Failed to get working folder for bundle layout.");
+    HRESULT hr = S_OK;
 
-    hr = StrAllocConcat(psczWorkingPath, wzBundleId, 0);
+    hr = PathConcat(pCache->sczWorkingFolder, wzBundleId, psczWorkingPath);
     ExitOnFailure(hr, "Failed to append bundle id for bundle layout working path.");
 
 LExit:
-    ReleaseStr(sczWorkingFolder);
-
     return hr;
 }
 
 extern "C" HRESULT CacheCalculatePayloadWorkingPath(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in BURN_PAYLOAD* pPayload,
     __deref_out_z LPWSTR* psczWorkingPath
     )
 {
-    HRESULT hr = S_OK;
+    Assert(pCache->fInitializedCache);
 
-    hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath);
-    ExitOnFailure(hr, "Failed to get working folder for payload.");
+    HRESULT hr = S_OK;
 
-    hr = StrAllocConcat(psczWorkingPath, pPayload->sczKey, 0);
+    hr = PathConcat(pCache->sczWorkingFolder, pPayload->sczKey, psczWorkingPath);
     ExitOnFailure(hr, "Failed to append Id as payload unverified path.");
 
 LExit:
@@ -341,17 +392,16 @@ LExit:
 }
 
 extern "C" HRESULT CacheCalculateContainerWorkingPath(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in BURN_CONTAINER* pContainer,
     __deref_out_z LPWSTR* psczWorkingPath
     )
 {
-    HRESULT hr = S_OK;
+    Assert(pCache->fInitializedCache);
 
-    hr = CalculateWorkingFolder(wzBundleId, psczWorkingPath);
-    ExitOnFailure(hr, "Failed to get working folder for container.");
+    HRESULT hr = S_OK;
 
-    hr = StrAllocConcat(psczWorkingPath, pContainer->sczHash, 0);
+    hr = PathConcat(pCache->sczWorkingFolder, pContainer->sczHash, psczWorkingPath);
     ExitOnFailure(hr, "Failed to append hash as container unverified path.");
 
 LExit:
@@ -359,6 +409,7 @@ LExit:
 }
 
 extern "C" HRESULT CacheGetPerMachineRootCompletedPath(
+    __in BURN_CACHE* pCache,
     __out_z LPWSTR* psczCurrentRootCompletedPath,
     __out_z LPWSTR* psczDefaultRootCompletedPath
     )
@@ -368,15 +419,15 @@ extern "C" HRESULT CacheGetPerMachineRootCompletedPath(
     *psczCurrentRootCompletedPath = NULL;
     *psczDefaultRootCompletedPath = NULL;
 
-    hr = SecurePerMachineCacheRoot();
+    hr = SecurePerMachineCacheRoot(pCache);
     ExitOnFailure(hr, "Failed to secure per-machine cache root.");
 
-    hr = GetRootPath(TRUE, TRUE, psczCurrentRootCompletedPath);
+    hr = GetRootPath(pCache, TRUE, TRUE, psczCurrentRootCompletedPath);
     ExitOnFailure(hr, "Failed to get per-machine cache root.");
 
     if (S_FALSE == hr)
     {
-        hr = GetRootPath(TRUE, FALSE, psczDefaultRootCompletedPath);
+        hr = GetRootPath(pCache, TRUE, FALSE, psczDefaultRootCompletedPath);
         ExitOnFailure(hr, "Failed to get default per-machine cache root.");
 
         hr = S_FALSE;
@@ -387,6 +438,7 @@ LExit:
 }
 
 extern "C" HRESULT CacheGetCompletedPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzCacheId,
     __deref_out_z LPWSTR* psczCompletedPath
@@ -398,7 +450,7 @@ extern "C" HRESULT CacheGetCompletedPath(
     LPWSTR sczCurrentCompletedPath = NULL;
     LPWSTR sczDefaultCompletedPath = NULL;
 
-    hr = GetRootPath(fPerMachine, TRUE, &sczRootPath);
+    hr = GetRootPath(pCache, fPerMachine, TRUE, &sczRootPath);
     ExitOnFailure(hr, "Failed to get %hs package cache root directory.", fPerMachine ? "per-machine" : "per-user");
 
     // GetRootPath returns S_FALSE if the package cache is redirected elsewhere.
@@ -414,7 +466,7 @@ extern "C" HRESULT CacheGetCompletedPath(
     // If neither package cache directory exists return the (possibly) redirected package cache directory.
     if (fRedirected && !DirExists(sczCurrentCompletedPath, NULL))
     {
-        hr = GetRootPath(fPerMachine, FALSE, &sczRootPath);
+        hr = GetRootPath(pCache, fPerMachine, FALSE, &sczRootPath);
         ExitOnFailure(hr, "Failed to get old %hs package cache root directory.", fPerMachine ? "per-machine" : "per-user");
 
         hr = PathConcat(sczRootPath, wzCacheId, &sczDefaultCompletedPath);
@@ -462,6 +514,7 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
     __in_z LPCWSTR wzSourcePath,
     __in_z LPCWSTR wzDestinationPath,
     __in_z_opt LPCWSTR wzLayoutDirectory,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __inout LPWSTR** prgSearchPaths,
     __out DWORD* pcSearchPaths,
@@ -469,6 +522,8 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
     __out DWORD* pdwDestinationSearchPath
     )
 {
+    AssertSz(pCache->fInitializedCacheSources, "Cache sources weren't initialized");
+
     HRESULT hr = S_OK;
     LPWSTR sczCurrentPath = NULL;
     LPWSTR sczLastSourceFolder = NULL;
@@ -481,11 +536,9 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
     DWORD dwLikelySearchPath = 0;
     DWORD dwDestinationSearchPath = 0;
 
-    AssertSz(vfInitializedCache, "Cache wasn't initialized");
-
     hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder);
-    fPreferSourcePathLocation = !vfRunningFromCache || FAILED(hr);
-    fTryLastFolder = SUCCEEDED(hr) && sczLastSourceFolder && *sczLastSourceFolder && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, vsczSourceProcessFolder, -1, sczLastSourceFolder, -1);
+    fPreferSourcePathLocation = !pCache->fRunningFromCache || FAILED(hr);
+    fTryLastFolder = SUCCEEDED(hr) && sczLastSourceFolder && *sczLastSourceFolder && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pCache->sczSourceProcessFolder, -1, sczLastSourceFolder, -1);
     fTryRelativePath = CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzSourcePath, -1, wzRelativePath, -1);
     fSourceIsAbsolute = PathIsAbsolute(wzSourcePath);
 
@@ -528,7 +581,7 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
         hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
         ExitOnFailure(hr, "Failed to ensure size for search paths array.");
 
-        hr = PathConcat(vsczSourceProcessFolder, wzSourcePath, &sczCurrentPath);
+        hr = PathConcat(pCache->sczSourceProcessFolder, wzSourcePath, &sczCurrentPath);
         ExitOnFailure(hr, "Failed to combine source process folder with source.");
 
         // If we're not running from cache or we couldn't get the last source,
@@ -580,7 +633,7 @@ extern "C" HRESULT CacheGetLocalSourcePaths(
         hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
         ExitOnFailure(hr, "Failed to ensure size for search paths array.");
 
-        hr = PathConcat(vsczSourceProcessFolder, wzRelativePath, &sczCurrentPath);
+        hr = PathConcat(pCache->sczSourceProcessFolder, wzRelativePath, &sczCurrentPath);
         ExitOnFailure(hr, "Failed to combine source process folder with relative.");
 
         if (fPreferSourcePathLocation)
@@ -761,12 +814,17 @@ extern "C" void CacheSendErrorCallback(
     }
 }
 
-extern "C" BOOL CacheBundleRunningFromCache()
+extern "C" BOOL CacheBundleRunningFromCache(
+    __in BURN_CACHE* pCache
+    )
 {
-    return vfRunningFromCache;
+    AssertSz(pCache->fInitializedCacheSources, "Cache sources weren't initialized");
+
+    return pCache->fRunningFromCache;
 }
 
-HRESULT CachePreparePackage(
+extern "C" HRESULT CachePreparePackage(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGE* pPackage
     )
 {
@@ -774,13 +832,14 @@ HRESULT CachePreparePackage(
 
     if (!pPackage->sczCacheFolder)
     {
-        hr = CreateCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, NULL, &pPackage->sczCacheFolder);
+        hr = CreateCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, NULL, &pPackage->sczCacheFolder);
     }
 
     return hr;
 }
 
 extern "C" HRESULT CacheBundleToCleanRoom(
+    __in BURN_CACHE* pCache,
     __in BURN_SECTION* pSection,
     __deref_out_z_opt LPWSTR* psczCleanRoomBundlePath
     )
@@ -794,7 +853,7 @@ extern "C" HRESULT CacheBundleToCleanRoom(
 
     wzExecutableName = PathFile(sczSourcePath);
 
-    hr = CopyEngineToWorkingFolder(sczSourcePath, BUNDLE_CLEAN_ROOM_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczCleanRoomBundlePath);
+    hr = CopyEngineToWorkingFolder(pCache, sczSourcePath, BUNDLE_CLEAN_ROOM_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczCleanRoomBundlePath);
     ExitOnFailure(hr, "Failed to cache bundle to clean room.");
 
 LExit:
@@ -804,13 +863,13 @@ LExit:
 }
 
 extern "C" HRESULT CacheBundleToWorkingDirectory(
-    __in_z LPCWSTR /*wzBundleId*/,
+    __in BURN_CACHE* pCache,
     __in_z LPCWSTR wzExecutableName,
     __in BURN_SECTION* pSection,
     __deref_out_z_opt LPWSTR* psczEngineWorkingPath
     )
 {
-    Assert(vfInitializedCache);
+    Assert(pCache->fInitializedCache);
 
     HRESULT hr = S_OK;
     LPWSTR sczSourcePath = NULL;
@@ -821,14 +880,14 @@ extern "C" HRESULT CacheBundleToWorkingDirectory(
 
     // If the bundle is running out of the package cache then we don't need to copy it to
     // the working folder since we feel safe in the package cache and will run from there.
-    if (vfRunningFromCache)
+    if (CacheBundleRunningFromCache(pCache))
     {
         hr = StrAllocString(psczEngineWorkingPath, sczSourcePath, 0);
         ExitOnFailure(hr, "Failed to use current process path as target path.");
     }
     else // otherwise, carry on putting the bundle in the working folder.
     {
-        hr = CopyEngineToWorkingFolder(sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath);
+        hr = CopyEngineToWorkingFolder(pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath);
         ExitOnFailure(hr, "Failed to copy engine to working folder.");
     }
 
@@ -866,6 +925,7 @@ LExit:
 }
 
 extern "C" HRESULT CacheCompleteBundle(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzExecutableName,
     __in_z LPCWSTR wzBundleId,
@@ -882,7 +942,7 @@ extern "C" HRESULT CacheCompleteBundle(
     LPWSTR sczSourceDirectory = NULL;
     LPWSTR sczPayloadSourcePath = NULL;
 
-    hr = CreateCompletedPath(fPerMachine, wzBundleId, NULL, &sczTargetDirectory);
+    hr = CreateCompletedPath(pCache, fPerMachine, wzBundleId, NULL, &sczTargetDirectory);
     ExitOnFailure(hr, "Failed to create completed cache path for bundle.");
 
     hr = PathConcat(sczTargetDirectory, wzExecutableName, &sczTargetPath);
@@ -976,6 +1036,7 @@ LExit:
 }
 
 extern "C" HRESULT CacheCompletePayload(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in BURN_PAYLOAD* pPayload,
     __in_z LPCWSTR wzCacheId,
@@ -990,7 +1051,7 @@ extern "C" HRESULT CacheCompletePayload(
     LPWSTR sczCachedPath = NULL;
     LPWSTR sczUnverifiedPayloadPath = NULL;
 
-    hr = CreateCompletedPath(fPerMachine, wzCacheId, pPayload->sczFilePath, &sczCachedPath);
+    hr = CreateCompletedPath(pCache, fPerMachine, wzCacheId, pPayload->sczFilePath, &sczCachedPath);
     ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", wzCacheId);
 
     // If the cached file matches what we expected, we're good.
@@ -1000,7 +1061,7 @@ extern "C" HRESULT CacheCompletePayload(
         ExitFunction();
     }
 
-    hr = CreateUnverifiedPath(fPerMachine, pPayload->sczKey, &sczUnverifiedPayloadPath);
+    hr = CreateUnverifiedPath(pCache, fPerMachine, pPayload->sczKey, &sczUnverifiedPayloadPath);
     ExitOnFailure(hr, "Failed to create unverified path.");
 
     // If the working path exists, let's get it into the unverified path so we can reset the ACLs and verify the file.
@@ -1091,36 +1152,30 @@ LExit:
 }
 
 extern "C" HRESULT CacheRemoveWorkingFolder(
-    __in_z_opt LPCWSTR wzBundleId
+    __in BURN_CACHE* pCache
     )
 {
     HRESULT hr = S_OK;
-    LPWSTR sczWorkingFolder = NULL;
 
-    if (vfInitializedCache)
+    if (pCache->fInitializedCacheSources)
     {
-        hr = CalculateWorkingFolder(wzBundleId, &sczWorkingFolder);
-        ExitOnFailure(hr, "Failed to calculate the working folder to remove it.");
-
         // Try to clean out everything in the working folder.
-        hr = DirEnsureDeleteEx(sczWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE);
+        hr = DirEnsureDeleteEx(pCache->sczWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE);
         TraceError(hr, "Could not delete bundle engine working folder.");
     }
 
-LExit:
-    ReleaseStr(sczWorkingFolder);
-
     return hr;
 }
 
 extern "C" HRESULT CacheRemoveBundle(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzBundleId
     )
 {
     HRESULT hr = S_OK;
 
-    hr = RemoveBundleOrPackage(TRUE, fPerMachine, wzBundleId, wzBundleId);
+    hr = RemoveBundleOrPackage(pCache, TRUE, fPerMachine, wzBundleId, wzBundleId);
     ExitOnFailure(hr, "Failed to remove bundle id: %ls.", wzBundleId);
 
 LExit:
@@ -1128,6 +1183,7 @@ LExit:
 }
 
 extern "C" HRESULT CacheRemovePackage(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzPackageId,
     __in_z LPCWSTR wzCacheId
@@ -1135,7 +1191,7 @@ extern "C" HRESULT CacheRemovePackage(
 {
     HRESULT hr = S_OK;
 
-    hr = RemoveBundleOrPackage(FALSE, fPerMachine, wzPackageId, wzCacheId);
+    hr = RemoveBundleOrPackage(pCache, FALSE, fPerMachine, wzPackageId, wzCacheId);
     ExitOnFailure(hr, "Failed to remove package id: %ls.", wzPackageId);
 
 LExit:
@@ -1194,9 +1250,11 @@ LExit:
 
 extern "C" void CacheCleanup(
     __in BOOL fPerMachine,
-    __in_z LPCWSTR wzBundleId
+    __in BURN_CACHE* pCache
     )
 {
+    Assert(pCache->fInitializedCache);
+
     HRESULT hr = S_OK;
     LPWSTR sczFolder = NULL;
     LPWSTR sczFiles = NULL;
@@ -1205,7 +1263,7 @@ extern "C" void CacheCleanup(
     WIN32_FIND_DATAW wfd = { };
     size_t cchFileName = 0;
 
-    hr = CacheGetCompletedPath(fPerMachine, UNVERIFIED_CACHE_FOLDER_NAME, &sczFolder);
+    hr = CacheGetCompletedPath(pCache, fPerMachine, UNVERIFIED_CACHE_FOLDER_NAME, &sczFolder);
     if (SUCCEEDED(hr))
     {
         hr = DirEnsureDeleteEx(sczFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE);
@@ -1213,10 +1271,9 @@ extern "C" void CacheCleanup(
 
     if (!fPerMachine)
     {
-        hr = CalculateWorkingFolder(wzBundleId, &sczFolder);
-        if (SUCCEEDED(hr))
+        if (pCache->sczWorkingFolder)
         {
-            hr = PathConcat(sczFolder, L"*.*", &sczFiles);
+            hr = PathConcat(pCache->sczWorkingFolder, L"*.*", &sczFiles);
             if (SUCCEEDED(hr))
             {
                 hFind = ::FindFirstFileW(sczFiles, &wfd);
@@ -1238,7 +1295,7 @@ extern "C" void CacheCleanup(
                             continue;
                         }
 
-                        hr = PathConcatCch(sczFolder, 0, wfd.cFileName, cchFileName, &sczDelete);
+                        hr = PathConcatCch(pCache->sczWorkingFolder, 0, wfd.cFileName, cchFileName, &sczDelete);
                         if (SUCCEEDED(hr))
                         {
                             hr = FileEnsureDelete(sczDelete);
@@ -1259,63 +1316,61 @@ extern "C" void CacheCleanup(
     ReleaseStr(sczFolder);
 }
 
-extern "C" void CacheUninitialize()
+extern "C" void CacheUninitialize(
+    __in BURN_CACHE* pCache
+    )
 {
-    ReleaseNullStr(vsczCurrentMachinePackageCache);
-    ReleaseNullStr(vsczDefaultMachinePackageCache);
-    ReleaseNullStr(vsczDefaultUserPackageCache);
-    ReleaseNullStr(vsczWorkingFolder);
-    ReleaseNullStr(vsczSourceProcessFolder);
-
-    vfRunningFromCache = FALSE;
-    vfInitializedCache = FALSE;
+    ReleaseNullStr(pCache->sczCurrentMachinePackageCache);
+    ReleaseNullStr(pCache->sczDefaultMachinePackageCache);
+    ReleaseNullStr(pCache->sczDefaultUserPackageCache);
+    ReleaseNullStr(pCache->sczWorkingFolder);
+    ReleaseNullStr(pCache->sczSourceProcessFolder);
+
+    pCache->fRunningFromCache = FALSE;
+    pCache->fInitializedCache = FALSE;
+    pCache->fInitializedCacheSources = FALSE;
+    pCache->fPerMachineCacheRootVerified = FALSE;
+    pCache->fOriginalPerMachineCacheRootVerified = FALSE;
+    pCache->fUnverifiedCacheFolderCreated = FALSE;
+    pCache->fCustomMachinePackageCache = FALSE;
 }
 
 // Internal functions.
 
 static HRESULT CalculateWorkingFolder(
-    __in_z_opt LPCWSTR /*wzBundleId*/,
-    __deref_out_z LPWSTR* psczWorkingFolder
+    __in BURN_CACHE* pCache,
+    __in BURN_ENGINE_COMMAND* pInternalCommand
     )
 {
     HRESULT hr = S_OK;
     RPC_STATUS rs = RPC_S_OK;
-    BOOL fElevated = FALSE;
     LPWSTR sczTempPath = NULL;
     UUID guid = {};
     WCHAR wzGuid[39];
 
-    if (!vsczWorkingFolder)
+    if (pInternalCommand->fInitiallyElevated)
     {
-        ProcElevated(::GetCurrentProcess(), &fElevated);
-
-        if (fElevated)
-        {
-            hr = PathGetSystemTempPath(&sczTempPath);
-            ExitOnFailure(hr, "Failed to get system temp folder path for working folder.");
-        }
-        else
-        {
-            hr = PathGetTempPath(&sczTempPath);
-            ExitOnFailure(hr, "Failed to get temp folder path for working folder.");
-        }
-
-        rs = ::UuidCreate(&guid);
-        hr = HRESULT_FROM_RPC(rs);
-        ExitOnFailure(hr, "Failed to create working folder guid.");
+        hr = PathGetSystemTempPath(&sczTempPath);
+        ExitOnFailure(hr, "Failed to get system temp folder path for working folder.");
+    }
+    else
+    {
+        hr = PathGetTempPath(&sczTempPath);
+        ExitOnFailure(hr, "Failed to get temp folder path for working folder.");
+    }
 
-        if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
-        {
-            hr = E_OUTOFMEMORY;
-            ExitOnRootFailure(hr, "Failed to convert working folder guid into string.");
-        }
+    rs = ::UuidCreate(&guid);
+    hr = HRESULT_FROM_RPC(rs);
+    ExitOnFailure(hr, "Failed to create working folder guid.");
 
-        hr = StrAllocFormatted(&vsczWorkingFolder, L"%ls%ls\\", sczTempPath, wzGuid);
-        ExitOnFailure(hr, "Failed to append bundle id on to temp path for working folder.");
+    if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
+    {
+        hr = E_OUTOFMEMORY;
+        ExitOnRootFailure(hr, "Failed to convert working folder guid into string.");
     }
 
-    hr = StrAllocString(psczWorkingFolder, vsczWorkingFolder, 0);
-    ExitOnFailure(hr, "Failed to copy working folder path.");
+    hr = StrAllocFormatted(&pCache->sczWorkingFolder, L"%ls%ls\\", sczTempPath, wzGuid);
+    ExitOnFailure(hr, "Failed to append random guid on to temp path for working folder.");
 
 LExit:
     ReleaseStr(sczTempPath);
@@ -1324,78 +1379,33 @@ LExit:
 }
 
 static HRESULT GetRootPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in BOOL fAllowRedirect,
     __deref_out_z LPWSTR* psczRootPath
     )
 {
+    Assert(pCache->fInitializedCache);
+
     HRESULT hr = S_OK;
-    LPWSTR sczAppData = NULL;
-    int nCompare = 0;
 
-    // Cache paths are initialized once so they cannot be changed while the engine is caching payloads.
     if (fPerMachine)
     {
-        // Always construct the default machine package cache path so we can determine if we're redirected.
-        if (!vsczDefaultMachinePackageCache)
-        {
-            hr = PathGetKnownFolder(CSIDL_COMMON_APPDATA, &sczAppData);
-            ExitOnFailure(hr, "Failed to find local %hs appdata directory.", "per-machine");
-
-            hr = PathConcat(sczAppData, PACKAGE_CACHE_FOLDER_NAME, &vsczDefaultMachinePackageCache);
-            ExitOnFailure(hr, "Failed to construct %hs package cache directory name.", "per-machine");
-
-            hr = PathBackslashTerminate(&vsczDefaultMachinePackageCache);
-            ExitOnFailure(hr, "Failed to backslash terminate default %hs package cache directory name.", "per-machine");
-        }
+        BOOL fRedirect = fAllowRedirect && pCache->fCustomMachinePackageCache;
 
-        if (!vsczCurrentMachinePackageCache)
-        {
-            hr = PolcReadString(POLICY_BURN_REGISTRY_PATH, L"PackageCache", NULL, &vsczCurrentMachinePackageCache);
-            ExitOnFailure(hr, "Failed to read PackageCache policy directory.");
-
-            if (vsczCurrentMachinePackageCache)
-            {
-                hr = PathBackslashTerminate(&vsczCurrentMachinePackageCache);
-                ExitOnFailure(hr, "Failed to backslash terminate redirected per-machine package cache directory name.");
-            }
-            else
-            {
-                hr = StrAllocString(&vsczCurrentMachinePackageCache, vsczDefaultMachinePackageCache, 0);
-                ExitOnFailure(hr, "Failed to copy default package cache directory to current package cache directory.");
-            }
-        }
-
-        hr = StrAllocString(psczRootPath, fAllowRedirect ? vsczCurrentMachinePackageCache : vsczDefaultMachinePackageCache, 0);
+        hr = StrAllocString(psczRootPath, fRedirect ? pCache->sczCurrentMachinePackageCache : pCache->sczDefaultMachinePackageCache, 0);
         ExitOnFailure(hr, "Failed to copy %hs package cache root directory.", "per-machine");
 
-        hr = PathCompare(vsczDefaultMachinePackageCache, *psczRootPath, &nCompare);
-        ExitOnFailure(hr, "Failed to compare default and current package cache directories.");
-
         // Return S_FALSE if the current location is not the default location (redirected).
-        hr = CSTR_EQUAL == nCompare ? S_OK : S_FALSE;
+        hr = fRedirect ? S_FALSE : S_OK;
     }
     else
     {
-        if (!vsczDefaultUserPackageCache)
-        {
-            hr = PathGetKnownFolder(CSIDL_LOCAL_APPDATA, &sczAppData);
-            ExitOnFailure(hr, "Failed to find local %hs appdata directory.", "per-user");
-
-            hr = PathConcat(sczAppData, PACKAGE_CACHE_FOLDER_NAME, &vsczDefaultUserPackageCache);
-            ExitOnFailure(hr, "Failed to construct %hs package cache directory name.", "per-user");
-
-            hr = PathBackslashTerminate(&vsczDefaultUserPackageCache);
-            ExitOnFailure(hr, "Failed to backslash terminate default %hs package cache directory name.", "per-user");
-        }
-
-        hr = StrAllocString(psczRootPath, vsczDefaultUserPackageCache, 0);
+        hr = StrAllocString(psczRootPath, pCache->sczDefaultUserPackageCache, 0);
         ExitOnFailure(hr, "Failed to copy %hs package cache root directory.", "per-user");
     }
 
 LExit:
-    ReleaseStr(sczAppData);
-
     return hr;
 }
 
@@ -1416,20 +1426,19 @@ static HRESULT GetLastUsedSourceFolder(
     return hr;
 }
 
-static HRESULT SecurePerMachineCacheRoot()
+static HRESULT SecurePerMachineCacheRoot(
+    __in BURN_CACHE* pCache
+    )
 {
-    static BOOL fPerMachineCacheRootVerified = FALSE;
-    static BOOL fOriginalPerMachineCacheRootVerified = FALSE;
-
     HRESULT hr = S_OK;
     BOOL fRedirected = FALSE;
     LPWSTR sczCacheDirectory = NULL;
 
-    if (!fPerMachineCacheRootVerified)
+    if (!pCache->fPerMachineCacheRootVerified)
     {
         // If we are doing a permachine install but have not yet verified that the root cache folder
         // was created with the correct ACLs yet, do that now.
-        hr = GetRootPath(TRUE, TRUE, &sczCacheDirectory);
+        hr = GetRootPath(pCache, TRUE, TRUE, &sczCacheDirectory);
         ExitOnFailure(hr, "Failed to get cache directory.");
 
         fRedirected = S_FALSE == hr;
@@ -1440,19 +1449,19 @@ static HRESULT SecurePerMachineCacheRoot()
         hr = SecurePath(sczCacheDirectory);
         ExitOnFailure(hr, "Failed to secure cache directory: %ls", sczCacheDirectory);
 
-        fPerMachineCacheRootVerified = TRUE;
+        pCache->fPerMachineCacheRootVerified = TRUE;
 
         if (!fRedirected)
         {
-            fOriginalPerMachineCacheRootVerified = TRUE;
+            pCache->fOriginalPerMachineCacheRootVerified = TRUE;
         }
     }
 
-    if (!fOriginalPerMachineCacheRootVerified)
+    if (!pCache->fOriginalPerMachineCacheRootVerified)
     {
         // If we are doing a permachine install but have not yet verified that the original root cache folder
         // was created with the correct ACLs yet, do that now.
-        hr = GetRootPath(TRUE, FALSE, &sczCacheDirectory);
+        hr = GetRootPath(pCache, TRUE, FALSE, &sczCacheDirectory);
         ExitOnFailure(hr, "Failed to get original cache directory.");
 
         hr = DirEnsureExists(sczCacheDirectory, NULL);
@@ -1461,7 +1470,7 @@ static HRESULT SecurePerMachineCacheRoot()
         hr = SecurePath(sczCacheDirectory);
         ExitOnFailure(hr, "Failed to secure original cache directory: %ls", sczCacheDirectory);
 
-        fOriginalPerMachineCacheRootVerified = TRUE;
+        pCache->fOriginalPerMachineCacheRootVerified = TRUE;
     }
 
 LExit:
@@ -1471,6 +1480,7 @@ LExit:
 }
 
 static HRESULT CreateCompletedPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in LPCWSTR wzId,
     __in LPCWSTR wzFilePath,
@@ -1483,12 +1493,12 @@ static HRESULT CreateCompletedPath(
 
     if (fPerMachine)
     {
-        hr = SecurePerMachineCacheRoot();
+        hr = SecurePerMachineCacheRoot(pCache);
         ExitOnFailure(hr, "Failed to secure per-machine cache root.");
     }
 
     // Get the cache completed path.
-    hr = CacheGetCompletedPath(fPerMachine, wzId, &sczCacheDirectory);
+    hr = CacheGetCompletedPath(pCache, fPerMachine, wzId, &sczCacheDirectory);
     ExitOnFailure(hr, "Failed to get cache directory.");
 
     // Ensure it exists.
@@ -1523,25 +1533,26 @@ LExit:
 }
 
 static HRESULT CreateUnverifiedPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzPayloadId,
     __out_z LPWSTR* psczUnverifiedPayloadPath
     )
 {
-    static BOOL fUnverifiedCacheFolderCreated = FALSE;
-
     HRESULT hr = S_OK;
     LPWSTR sczUnverifiedCacheFolder = NULL;
 
-    hr = CacheGetCompletedPath(fPerMachine, UNVERIFIED_CACHE_FOLDER_NAME, &sczUnverifiedCacheFolder);
+    hr = CacheGetCompletedPath(pCache, fPerMachine, UNVERIFIED_CACHE_FOLDER_NAME, &sczUnverifiedCacheFolder);
     ExitOnFailure(hr, "Failed to get cache directory.");
 
-    if (!fUnverifiedCacheFolderCreated)
+    if (!pCache->fUnverifiedCacheFolderCreated)
     {
         hr = DirEnsureExists(sczUnverifiedCacheFolder, NULL);
         ExitOnFailure(hr, "Failed to create unverified cache directory: %ls", sczUnverifiedCacheFolder);
 
         ResetPathPermissions(fPerMachine, sczUnverifiedCacheFolder);
+
+        pCache->fUnverifiedCacheFolderCreated = TRUE;
     }
 
     hr = PathConcat(sczUnverifiedCacheFolder, wzPayloadId, psczUnverifiedPayloadPath);
@@ -1946,6 +1957,7 @@ LExit:
 
 
 static HRESULT CopyEngineToWorkingFolder(
+    __in BURN_CACHE* pCache,
     __in_z LPCWSTR wzSourcePath,
     __in_z LPCWSTR wzWorkingFolderName,
     __in_z LPCWSTR wzExecutableName,
@@ -1961,7 +1973,7 @@ static HRESULT CopyEngineToWorkingFolder(
     LPWSTR sczPayloadSourcePath = NULL;
     LPWSTR sczPayloadTargetPath = NULL;
 
-    hr = CacheEnsureWorkingFolder(NULL, &sczWorkingFolder);
+    hr = CacheEnsureWorkingFolder(pCache, &sczWorkingFolder);
     ExitOnFailure(hr, "Failed to create working path to copy engine.");
 
     hr = PathConcat(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory);
@@ -2064,6 +2076,7 @@ LExit:
 
 
 static HRESULT RemoveBundleOrPackage(
+    __in BURN_CACHE* pCache,
     __in BOOL fBundle,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzBundleOrPackageId,
@@ -2074,7 +2087,7 @@ static HRESULT RemoveBundleOrPackage(
     LPWSTR sczRootCacheDirectory = NULL;
     LPWSTR sczDirectory = NULL;
 
-    hr = CacheGetCompletedPath(fPerMachine, wzCacheId, &sczDirectory);
+    hr = CacheGetCompletedPath(pCache, fPerMachine, wzCacheId, &sczDirectory);
     ExitOnFailure(hr, "Failed to calculate cache path.");
 
     LogId(REPORT_STANDARD, fBundle ? MSG_UNCACHE_BUNDLE : MSG_UNCACHE_PACKAGE, wzBundleOrPackageId, sczDirectory);
@@ -2103,14 +2116,14 @@ static HRESULT RemoveBundleOrPackage(
     else
     {
         // Try to remove root package cache in the off chance it is now empty.
-        hr = GetRootPath(fPerMachine, TRUE, &sczRootCacheDirectory);
+        hr = GetRootPath(pCache, fPerMachine, TRUE, &sczRootCacheDirectory);
         ExitOnFailure(hr, "Failed to get %hs package cache root directory.", fPerMachine ? "per-machine" : "per-user");
         DirEnsureDeleteEx(sczRootCacheDirectory, DIR_DELETE_SCHEDULE);
 
         // GetRootPath returns S_FALSE if the package cache is redirected elsewhere.
         if (S_FALSE == hr)
         {
-            hr = GetRootPath(fPerMachine, FALSE, &sczRootCacheDirectory);
+            hr = GetRootPath(pCache, fPerMachine, FALSE, &sczRootCacheDirectory);
             ExitOnFailure(hr, "Failed to get old %hs package cache root directory.", fPerMachine ? "per-machine" : "per-user");
             DirEnsureDeleteEx(sczRootCacheDirectory, DIR_DELETE_SCHEDULE);
         }
diff --git a/src/burn/engine/cache.h b/src/burn/engine/cache.h
index dfb4f69f..69d82639 100644
--- a/src/burn/engine/cache.h
+++ b/src/burn/engine/cache.h
@@ -24,6 +24,24 @@ enum BURN_CACHE_STEP
     BURN_CACHE_STEP_FINALIZE,
 };
 
+typedef struct _BURN_CACHE
+{
+    BOOL fInitializedCache;
+    BOOL fPerMachineCacheRootVerified;
+    BOOL fOriginalPerMachineCacheRootVerified;
+    BOOL fUnverifiedCacheFolderCreated;
+    BOOL fCustomMachinePackageCache;
+    LPWSTR sczDefaultUserPackageCache;
+    LPWSTR sczDefaultMachinePackageCache;
+    LPWSTR sczCurrentMachinePackageCache;
+
+    // Only valid after CacheInitializeSources
+    BOOL fInitializedCacheSources;
+    BOOL fRunningFromCache;
+    LPWSTR sczSourceProcessFolder;
+    LPWSTR sczWorkingFolder;
+} BURN_CACHE;
+
 typedef struct _BURN_CACHE_MESSAGE
 {
     BURN_CACHE_MESSAGE_TYPE type;
@@ -53,38 +71,46 @@ typedef HRESULT(CALLBACK* PFN_BURNCACHEMESSAGEHANDLER)(
 // functions
 
 HRESULT CacheInitialize(
+    __in BURN_CACHE* pCache,
+    __in BURN_ENGINE_COMMAND* pInternalCommand
+    );
+HRESULT CacheInitializeSources(
+    __in BURN_CACHE* pCache,
     __in BURN_REGISTRATION* pRegistration,
     __in BURN_VARIABLES* pVariables,
-    __in_z_opt LPCWSTR wzSourceProcessPath
+    __in BURN_ENGINE_COMMAND* pInternalCommand
     );
 HRESULT CacheEnsureWorkingFolder(
-    __in_z_opt LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __deref_out_z_opt LPWSTR* psczWorkingFolder
     );
 HRESULT CacheCalculateBundleWorkingPath(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in LPCWSTR wzExecutableName,
     __deref_out_z LPWSTR* psczWorkingPath
     );
 HRESULT CacheCalculateBundleLayoutWorkingPath(
+    __in BURN_CACHE* pCache,
     __in_z LPCWSTR wzBundleId,
     __deref_out_z LPWSTR* psczWorkingPath
     );
 HRESULT CacheCalculatePayloadWorkingPath(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in BURN_PAYLOAD* pPayload,
     __deref_out_z LPWSTR* psczWorkingPath
     );
 HRESULT CacheCalculateContainerWorkingPath(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in BURN_CONTAINER* pContainer,
     __deref_out_z LPWSTR* psczWorkingPath
     );
 HRESULT CacheGetPerMachineRootCompletedPath(
+    __in BURN_CACHE* pCache,
     __out_z LPWSTR* psczCurrentRootCompletedPath,
     __out_z LPWSTR* psczDefaultRootCompletedPath
     );
 HRESULT CacheGetCompletedPath(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzCacheId,
     __deref_out_z LPWSTR* psczCompletedPath
@@ -98,6 +124,7 @@ HRESULT CacheGetLocalSourcePaths(
     __in_z LPCWSTR wzSourcePath,
     __in_z LPCWSTR wzDestinationPath,
     __in_z_opt LPCWSTR wzLayoutDirectory,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __inout LPWSTR** prgSearchPaths,
     __out DWORD* pcSearchPaths,
@@ -121,16 +148,20 @@ void CacheSendErrorCallback(
     __in_z_opt LPCWSTR wzError,
     __out_opt BOOL* pfRetry
     );
-BOOL CacheBundleRunningFromCache();
+BOOL CacheBundleRunningFromCache(
+    __in BURN_CACHE* pCache
+    );
 HRESULT CachePreparePackage(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGE* pPackage
     );
 HRESULT CacheBundleToCleanRoom(
+    __in BURN_CACHE* pCache,
     __in BURN_SECTION* pSection,
     __deref_out_z_opt LPWSTR* psczCleanRoomBundlePath
     );
 HRESULT CacheBundleToWorkingDirectory(
-    __in_z LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __in_z LPCWSTR wzExecutableName,
     __in BURN_SECTION* pSection,
     __deref_out_z_opt LPWSTR* psczEngineWorkingPath
@@ -145,6 +176,7 @@ HRESULT CacheLayoutBundle(
     __in LPVOID pContext
     );
 HRESULT CacheCompleteBundle(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzExecutableName,
     __in_z LPCWSTR wzBundleId,
@@ -172,6 +204,7 @@ HRESULT CacheLayoutPayload(
     __in LPVOID pContext
     );
 HRESULT CacheCompletePayload(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in BURN_PAYLOAD* pPayload,
     __in_z LPCWSTR wzCacheId,
@@ -196,22 +229,26 @@ HRESULT CacheVerifyPayload(
     __in LPVOID pContext
     );
 HRESULT CacheRemoveWorkingFolder(
-    __in_z_opt LPCWSTR wzBundleId
+    __in BURN_CACHE* pCache
     );
 HRESULT CacheRemoveBundle(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzPackageId
     );
 HRESULT CacheRemovePackage(
+    __in BURN_CACHE* pCache,
     __in BOOL fPerMachine,
     __in_z LPCWSTR wzPackageId,
     __in_z LPCWSTR wzCacheId
     );
 void CacheCleanup(
     __in BOOL fPerMachine,
-    __in_z LPCWSTR wzBundleId
+    __in BURN_CACHE* pCache
+    );
+void CacheUninitialize(
+    __in BURN_CACHE* pCache
     );
-void CacheUninitialize();
 
 #ifdef __cplusplus
 }
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 0468d406..8985ab27 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -32,6 +32,7 @@ static HRESULT DetectPackage(
     __in BURN_PACKAGE* pPackage
     );
 static HRESULT DetectPackagePayloadsCached(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGE* pPackage
     );
 static DWORD WINAPI CacheThreadProc(
@@ -65,7 +66,6 @@ extern "C" HRESULT CoreInitialize(
     BYTE* pbBuffer = NULL;
     SIZE_T cbBuffer = 0;
     BURN_CONTAINER_CONTEXT containerContext = { };
-    BOOL fElevated = FALSE;
     LPWSTR sczSourceProcessFolder = NULL;
 
     // Initialize variables.
@@ -105,10 +105,7 @@ extern "C" HRESULT CoreInitialize(
     hr = CoreInitializeConstants(pEngineState);
     ExitOnFailure(hr, "Failed to initialize contants.");
 
-    // Retain whether bundle was initially run elevated.
-    ProcElevated(::GetCurrentProcess(), &fElevated);
-
-    hr = VariableSetNumeric(&pEngineState->variables, BURN_BUNDLE_ELEVATED, fElevated, TRUE);
+    hr = VariableSetNumeric(&pEngineState->variables, BURN_BUNDLE_ELEVATED, pEngineState->internalCommand.fInitiallyElevated, TRUE);
     ExitOnFailure(hr, "Failed to overwrite the %ls built-in variable.", BURN_BUNDLE_ELEVATED);
 
     hr = VariableSetNumeric(&pEngineState->variables, BURN_BUNDLE_UILEVEL, pEngineState->command.display, TRUE);
@@ -136,8 +133,8 @@ extern "C" HRESULT CoreInitialize(
 
     if (BURN_MODE_UNTRUSTED == pEngineState->mode || BURN_MODE_NORMAL == pEngineState->mode || BURN_MODE_EMBEDDED == pEngineState->mode)
     {
-        hr = CacheInitialize(&pEngineState->registration, &pEngineState->variables, pEngineState->internalCommand.sczSourceProcessPath);
-        ExitOnFailure(hr, "Failed to initialize internal cache functionality.");
+        hr = CacheInitializeSources(&pEngineState->cache, &pEngineState->registration, &pEngineState->variables, &pEngineState->internalCommand);
+        ExitOnFailure(hr, "Failed to initialize internal cache source functionality.");
     }
 
     // If we're not elevated then we'll be loading the bootstrapper application, so extract
@@ -145,7 +142,7 @@ extern "C" HRESULT CoreInitialize(
     if (BURN_MODE_NORMAL == pEngineState->mode || BURN_MODE_EMBEDDED == pEngineState->mode)
     {
         // Extract all UX payloads to working folder.
-        hr = UserExperienceEnsureWorkingFolder(pEngineState->registration.sczId, &pEngineState->userExperience.sczTempDirectory);
+        hr = UserExperienceEnsureWorkingFolder(&pEngineState->cache, &pEngineState->userExperience.sczTempDirectory);
         ExitOnFailure(hr, "Failed to get unique temporary folder for bootstrapper application.");
 
         hr = PayloadExtractUXContainer(&pEngineState->userExperience.payloads, &containerContext, pEngineState->userExperience.sczTempDirectory);
@@ -455,6 +452,7 @@ extern "C" HRESULT CorePlan(
     // Remember the overall action state in the plan since it shapes the changes
     // we make everywhere.
     pEngineState->plan.action = action;
+    pEngineState->plan.pCache = &pEngineState->cache;
     pEngineState->plan.pPayloads = &pEngineState->payloads;
     pEngineState->plan.wzBundleId = pEngineState->registration.sczId;
     pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId;
@@ -571,7 +569,7 @@ extern "C" HRESULT CoreElevate(
         // If the elevated companion pipe isn't created yet, let's make that happen.
         if (!pEngineState->sczBundleEngineWorkingPath)
         {
-            hr = CacheBundleToWorkingDirectory(pEngineState->registration.sczId, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath);
+            hr = CacheBundleToWorkingDirectory(&pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath);
             ExitOnFailure(hr, "Failed to cache engine to working directory.");
         }
 
@@ -673,7 +671,7 @@ extern "C" HRESULT CoreApply(
     // Ensure the engine is cached to the working path.
     if (!pEngineState->sczBundleEngineWorkingPath)
     {
-        hr = CacheBundleToWorkingDirectory(pEngineState->registration.sczId, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath);
+        hr = CacheBundleToWorkingDirectory(&pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath);
         ExitOnFailure(hr, "Failed to cache engine to working directory.");
     }
 
@@ -1740,7 +1738,7 @@ static HRESULT DetectPackage(
     ExitOnRootFailure(hr, "BA aborted detect package begin.");
 
     // Detect the cache state of the package.
-    hr = DetectPackagePayloadsCached(pPackage);
+    hr = DetectPackagePayloadsCached(&pEngineState->cache, pPackage);
     ExitOnFailure(hr, "Failed to detect if payloads are all cached for package: %ls", pPackage->sczId);
 
     // Use the correct engine to detect the package.
@@ -1782,6 +1780,7 @@ LExit:
 }
 
 static HRESULT DetectPackagePayloadsCached(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGE* pPackage
     )
 {
@@ -1792,7 +1791,7 @@ static HRESULT DetectPackagePayloadsCached(
 
     if (pPackage->sczCacheId && *pPackage->sczCacheId)
     {
-        hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachePath);
+        hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachePath);
         ExitOnFailure(hr, "Failed to get completed cache path.");
 
         // If the cached directory exists, we have something.
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 3fa1f04a..9bb06147 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -80,6 +80,7 @@ enum BURN_AU_PAUSE_ACTION
 
 typedef struct _BURN_ENGINE_COMMAND
 {
+    BOOL fInitiallyElevated;
     LPWSTR sczSourceProcessPath;
     LPWSTR sczOriginalSource;
 } BURN_ENGINE_COMMAND;
@@ -109,6 +110,7 @@ typedef struct _BURN_ENGINE_STATE
     BURN_PACKAGES packages;
     BURN_UPDATE update;
     BURN_APPROVED_EXES approvedExes;
+    BURN_CACHE cache;
     BURN_EXTENSIONS extensions;
 
     HWND hMessageWindow;
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index db2a82a6..a0ad6685 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -88,6 +88,7 @@ typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT
     HANDLE* phLock;
     BOOL* pfDisabledAutomaticUpdates;
     BURN_APPROVED_EXES* pApprovedExes;
+    BURN_CACHE* pCache;
     BURN_CONTAINERS* pContainers;
     BURN_PACKAGES* pPackages;
     BURN_PAYLOADS* pPayloads;
@@ -164,6 +165,7 @@ static HRESULT OnApplyUninitialize(
     __in HANDLE* phLock
     );
 static HRESULT OnSessionBegin(
+    __in BURN_CACHE* pCache,
     __in BURN_REGISTRATION* pRegistration,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -176,6 +178,7 @@ static HRESULT OnSessionResume(
     __in SIZE_T cbData
     );
 static HRESULT OnSessionEnd(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_REGISTRATION* pRegistration,
     __in BURN_VARIABLES* pVariables,
@@ -188,12 +191,14 @@ static HRESULT OnSaveState(
     __in SIZE_T cbData
     );
 static HRESULT OnCachePreparePackage(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BYTE* pbData,
     __in SIZE_T cbData
     );
 static HRESULT OnCacheCompletePayload(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_PAYLOADS* pPayloads,
     __in BYTE* pbData,
@@ -207,7 +212,7 @@ static HRESULT OnCacheVerifyPayload(
     __in SIZE_T cbData
     );
 static void OnCacheCleanup(
-    __in_z LPCWSTR wzBundleId
+    __in BURN_CACHE* pCache
     );
 static HRESULT OnProcessDependentRegistration(
     __in const BURN_REGISTRATION* pRegistration,
@@ -216,6 +221,7 @@ static HRESULT OnProcessDependentRegistration(
     );
 static HRESULT OnExecuteExePackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_RELATED_BUNDLES* pRelatedBundles,
     __in BURN_VARIABLES* pVariables,
@@ -224,6 +230,7 @@ static HRESULT OnExecuteExePackage(
     );
 static HRESULT OnExecuteMsiPackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -231,6 +238,7 @@ static HRESULT OnExecuteMsiPackage(
     );
 static HRESULT OnExecuteMspPackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -238,6 +246,7 @@ static HRESULT OnExecuteMspPackage(
     );
 static HRESULT OnExecuteMsuPackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -279,6 +288,7 @@ static int MsiExecuteMessageHandler(
     __in_opt LPVOID pvContext
     );
 static HRESULT OnCleanPackage(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BYTE* pbData,
     __in SIZE_T cbData
@@ -286,6 +296,7 @@ static HRESULT OnCleanPackage(
 static HRESULT OnLaunchApprovedExe(
     __in HANDLE hPipe,
     __in BURN_APPROVED_EXES* pApprovedExes,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
     __in SIZE_T cbData
@@ -1284,6 +1295,7 @@ extern "C" HRESULT ElevationChildPumpMessages(
     __in HANDLE hPipe,
     __in HANDLE hCachePipe,
     __in BURN_APPROVED_EXES* pApprovedExes,
+    __in BURN_CACHE* pCache,
     __in BURN_CONTAINERS* pContainers,
     __in BURN_PACKAGES* pPackages,
     __in BURN_PAYLOADS* pPayloads,
@@ -1304,6 +1316,7 @@ extern "C" HRESULT ElevationChildPumpMessages(
 
     cacheContext.dwLoggingTlsId = dwLoggingTlsId;
     cacheContext.hPipe = hCachePipe;
+    cacheContext.pCache = pCache;
     cacheContext.pContainers = pContainers;
     cacheContext.pPackages = pPackages;
     cacheContext.pPayloads = pPayloads;
@@ -1316,6 +1329,7 @@ extern "C" HRESULT ElevationChildPumpMessages(
     context.phLock = phLock;
     context.pfDisabledAutomaticUpdates = pfDisabledAutomaticUpdates;
     context.pApprovedExes = pApprovedExes;
+    context.pCache = pCache;
     context.pContainers = pContainers;
     context.pPackages = pPackages;
     context.pPayloads = pPayloads;
@@ -1826,7 +1840,7 @@ static HRESULT ProcessElevatedChildMessage(
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN:
-        hrResult = OnSessionBegin(pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnSessionBegin(pContext->pCache, pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_SESSION_RESUME:
@@ -1834,7 +1848,7 @@ static HRESULT ProcessElevatedChildMessage(
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_SESSION_END:
-        hrResult = OnSessionEnd(pContext->pPackages, pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnSessionEnd(pContext->pCache, pContext->pPackages, pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE:
@@ -1846,19 +1860,19 @@ static HRESULT ProcessElevatedChildMessage(
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE:
-        hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pPackages, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE:
-        hrResult = OnExecuteMsiPackage(pContext->hPipe, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnExecuteMsiPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE:
-        hrResult = OnExecuteMspPackage(pContext->hPipe, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnExecuteMspPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE:
-        hrResult = OnExecuteMsuPackage(pContext->hPipe, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnExecuteMsuPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER:
@@ -1870,11 +1884,11 @@ static HRESULT ProcessElevatedChildMessage(
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE:
-        hrResult = OnCleanPackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnCleanPackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE:
-        hrResult = OnLaunchApprovedExe(pContext->hPipe, pContext->pApprovedExes, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnLaunchApprovedExe(pContext->hPipe, pContext->pApprovedExes, pContext->pCache, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     default:
@@ -1901,11 +1915,11 @@ static HRESULT ProcessElevatedChildCacheMessage(
     switch (pMsg->dwMessage)
     {
     case BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE:
-        hrResult = OnCachePreparePackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnCachePreparePackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD:
-        hrResult = OnCacheCompletePayload(pContext->hPipe, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnCacheCompletePayload(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD:
@@ -1913,12 +1927,12 @@ static HRESULT ProcessElevatedChildCacheMessage(
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP:
-        OnCacheCleanup(pContext->pRegistration->sczId);
+        OnCacheCleanup(pContext->pCache);
         hrResult = S_OK;
         break;
 
     case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE:
-        hrResult = OnCleanPackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
+        hrResult = OnCleanPackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
         break;
 
     default:
@@ -2080,6 +2094,7 @@ static HRESULT OnApplyUninitialize(
 }
 
 static HRESULT OnSessionBegin(
+    __in BURN_CACHE* pCache,
     __in BURN_REGISTRATION* pRegistration,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -2120,7 +2135,7 @@ static HRESULT OnSessionBegin(
     ExitOnFailure(hr, "Failed to read variables.");
 
     // Begin session in per-machine process.
-    hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pVariables, dwRegistrationOperations, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
+    hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pCache, pVariables, dwRegistrationOperations, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
     ExitOnFailure(hr, "Failed to begin registration session.");
 
 LExit:
@@ -2162,6 +2177,7 @@ LExit:
 }
 
 static HRESULT OnSessionEnd(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_REGISTRATION* pRegistration,
     __in BURN_VARIABLES* pVariables,
@@ -2190,7 +2206,7 @@ static HRESULT OnSessionEnd(
     ExitOnFailure(hr, "Failed to read dependency registration action.");
 
     // suspend session in per-machine process
-    hr = RegistrationSessionEnd(pRegistration, pVariables, pPackages, (BURN_RESUME_MODE)dwResumeMode, (BOOTSTRAPPER_APPLY_RESTART)dwRestart, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
+    hr = RegistrationSessionEnd(pRegistration, pCache, pVariables, pPackages, (BURN_RESUME_MODE)dwResumeMode, (BOOTSTRAPPER_APPLY_RESTART)dwRestart, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
     ExitOnFailure(hr, "Failed to suspend registration session.");
 
 LExit:
@@ -2214,6 +2230,7 @@ LExit:
 }
 
 static HRESULT OnCachePreparePackage(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BYTE* pbData,
     __in SIZE_T cbData
@@ -2239,7 +2256,7 @@ static HRESULT OnCachePreparePackage(
         ExitOnRootFailure(hr, "Invalid data passed to cache prepare package.");
     }
 
-    hr = CachePreparePackage(pPackage);
+    hr = CachePreparePackage(pCache, pPackage);
     ExitOnFailure(hr, "Failed to prepare cache package.");
 
 LExit:
@@ -2250,6 +2267,7 @@ LExit:
 
 static HRESULT OnCacheCompletePayload(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_PAYLOADS* pPayloads,
     __in BYTE* pbData,
@@ -2291,7 +2309,7 @@ static HRESULT OnCacheCompletePayload(
 
     if (pPackage && pPayload) // complete payload.
     {
-        hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
+        hr = CacheCompletePayload(pCache, pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
         ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey);
     }
     else
@@ -2364,10 +2382,10 @@ LExit:
 }
 
 static void OnCacheCleanup(
-    __in_z LPCWSTR wzBundleId
+    __in BURN_CACHE* pCache
     )
 {
-    CacheCleanup(TRUE, wzBundleId);
+    CacheCleanup(TRUE, pCache);
 }
 
 static HRESULT OnProcessDependentRegistration(
@@ -2405,6 +2423,7 @@ LExit:
 
 static HRESULT OnExecuteExePackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_RELATED_BUNDLES* pRelatedBundles,
     __in BURN_VARIABLES* pVariables,
@@ -2464,7 +2483,7 @@ static HRESULT OnExecuteExePackage(
     }
 
     // Execute EXE package.
-    hr = ExeEngineExecutePackage(&executeAction, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
+    hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
     ExitOnFailure(hr, "Failed to execute EXE package.");
 
 LExit:
@@ -2490,6 +2509,7 @@ LExit:
 
 static HRESULT OnExecuteMsiPackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -2563,7 +2583,7 @@ static HRESULT OnExecuteMsiPackage(
     ExitOnFailure(hr, "Failed to read variables.");
 
     // Execute MSI package.
-    hr = MsiEngineExecutePackage(hwndParent, &executeAction, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &msiRestart);
+    hr = MsiEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &msiRestart);
     ExitOnFailure(hr, "Failed to execute MSI package.");
 
 LExit:
@@ -2587,6 +2607,7 @@ LExit:
 
 static HRESULT OnExecuteMspPackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -2658,7 +2679,7 @@ static HRESULT OnExecuteMspPackage(
     ExitOnFailure(hr, "Failed to read rollback flag.");
 
     // Execute MSP package.
-    hr = MspEngineExecutePackage(hwndParent, &executeAction, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &restart);
+    hr = MspEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, &restart);
     ExitOnFailure(hr, "Failed to execute MSP package.");
 
 LExit:
@@ -2682,6 +2703,7 @@ LExit:
 
 static HRESULT OnExecuteMsuPackage(
     __in HANDLE hPipe,
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
@@ -2718,7 +2740,7 @@ static HRESULT OnExecuteMsuPackage(
     ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
 
     // execute MSU package
-    hr = MsuEngineExecutePackage(&executeAction, pVariables, static_cast<BOOL>(dwRollback), static_cast<BOOL>(dwStopWusaService), GenericExecuteMessageHandler, hPipe, &restart);
+    hr = MsuEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), static_cast<BOOL>(dwStopWusaService), GenericExecuteMessageHandler, hPipe, &restart);
     ExitOnFailure(hr, "Failed to execute MSU package.");
 
 LExit:
@@ -3051,6 +3073,7 @@ LExit:
 }
 
 static HRESULT OnCleanPackage(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGES* pPackages,
     __in BYTE* pbData,
     __in SIZE_T cbData
@@ -3069,7 +3092,7 @@ static HRESULT OnCleanPackage(
     ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
 
     // Remove the package from the cache.
-    hr = CacheRemovePackage(TRUE, pPackage->sczId, pPackage->sczCacheId);
+    hr = CacheRemovePackage(pCache, TRUE, pPackage->sczId, pPackage->sczCacheId);
     ExitOnFailure(hr, "Failed to remove from cache package: %ls", pPackage->sczId);
 
 LExit:
@@ -3080,6 +3103,7 @@ LExit:
 static HRESULT OnLaunchApprovedExe(
     __in HANDLE hPipe,
     __in BURN_APPROVED_EXES* pApprovedExes,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BYTE* pbData,
     __in SIZE_T cbData
@@ -3124,7 +3148,7 @@ static HRESULT OnLaunchApprovedExe(
     hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath);
     ExitOnFailure(hr, "Failed to read the value for the approved exe path.");
 
-    hr = ApprovedExesVerifySecureLocation(pVariables, pLaunchApprovedExe);
+    hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe);
     ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath);
     if (S_FALSE == hr)
     {
diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h
index 00dca8dc..fb2e9cb4 100644
--- a/src/burn/engine/elevation.h
+++ b/src/burn/engine/elevation.h
@@ -151,6 +151,7 @@ HRESULT ElevationChildPumpMessages(
     __in HANDLE hPipe,
     __in HANDLE hCachePipe,
     __in BURN_APPROVED_EXES* pApprovedExes,
+    __in BURN_CACHE* pCache,
     __in BURN_CONTAINERS* pContainers,
     __in BURN_PACKAGES* pPackages,
     __in BURN_PAYLOADS* pPayloads,
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index e6cb1708..0c2c8dc5 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -244,8 +244,8 @@ LExit:
 
     UserExperienceRemove(&engineState.userExperience);
 
-    CacheRemoveWorkingFolder(engineState.registration.sczId);
-    CacheUninitialize();
+    CacheRemoveWorkingFolder(&engineState.cache);
+    CacheUninitialize(&engineState.cache);
 
     // If this is a related bundle (but not an update) suppress restart and return the standard restart error code.
     if (fRestart && BOOTSTRAPPER_RELATION_NONE != engineState.command.relationType && BOOTSTRAPPER_RELATION_UPDATE != engineState.command.relationType)
@@ -334,6 +334,9 @@ static HRESULT InitializeEngineState(
     PipeConnectionInitialize(&pEngineState->companionConnection);
     PipeConnectionInitialize(&pEngineState->embeddedConnection);
 
+    // Retain whether bundle was initially run elevated.
+    ProcElevated(::GetCurrentProcess(), &pEngineState->internalCommand.fInitiallyElevated);
+
     // Parse command line.
     hr = CoreParseCommandLine(pEngineState->argc, pEngineState->argv, &pEngineState->command, &pEngineState->companionConnection, &pEngineState->embeddedConnection, &pEngineState->mode, &pEngineState->automaticUpdates, &pEngineState->fDisableSystemRestore, &pEngineState->internalCommand.sczSourceProcessPath, &pEngineState->internalCommand.sczOriginalSource, &hSectionFile, &hSourceEngineFile, &pEngineState->fDisableUnelevate, &pEngineState->log.dwAttributes, &pEngineState->log.sczPath, &pEngineState->registration.sczActiveParent, &pEngineState->sczIgnoreDependencies, &pEngineState->registration.sczAncestors, &pEngineState->fInvalidCommandLine, &pEngineState->cUnknownArgs, &pEngineState->rgUnknownArgs);
     ExitOnFailure(hr, "Fatal error while parsing command line.");
@@ -341,6 +344,9 @@ static HRESULT InitializeEngineState(
     hr = SectionInitialize(&pEngineState->section, hSectionFile, hSourceEngineFile);
     ExitOnFailure(hr, "Failed to initialize engine section.");
 
+    hr = CacheInitialize(&pEngineState->cache, &pEngineState->internalCommand);
+    ExitOnFailure(hr, "Failed to initialize internal cache functionality.");
+
 LExit:
     return hr;
 }
@@ -421,8 +427,6 @@ static HRESULT RunUntrusted(
     hr = PathForCurrentProcess(&sczCurrentProcessPath, NULL);
     ExitOnFailure(hr, "Failed to get path for current process.");
 
-    BOOL fRunningFromCache = CacheBundleRunningFromCache();
-
     // If we're running from the package cache, we're in a secure
     // folder (DLLs cannot be inserted here for hijacking purposes)
     // so just launch the current process's path as the clean room
@@ -431,13 +435,13 @@ static HRESULT RunUntrusted(
     // a secure folder) but it makes the code that only wants to run
     // in clean room more complicated if we don't launch an explicit
     // clean room process.
-    if (fRunningFromCache)
+    if (CacheBundleRunningFromCache(&pEngineState->cache))
     {
         wzCleanRoomBundlePath = sczCurrentProcessPath;
     }
     else
     {
-        hr = CacheBundleToCleanRoom(&pEngineState->section, &sczCachedCleanRoomBundlePath);
+        hr = CacheBundleToCleanRoom(&pEngineState->cache, &pEngineState->section, &sczCachedCleanRoomBundlePath);
         ExitOnFailure(hr, "Failed to cache to clean room.");
 
         wzCleanRoomBundlePath = sczCachedCleanRoomBundlePath;
@@ -658,7 +662,7 @@ static HRESULT RunElevated(
     SrpInitialize(TRUE);
 
     // Pump messages from parent process.
-    hr = ElevationChildPumpMessages(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe, pEngineState->companionConnection.hCachePipe, &pEngineState->approvedExes, &pEngineState->containers, &pEngineState->packages, &pEngineState->payloads, &pEngineState->variables, &pEngineState->registration, &pEngineState->userExperience, &hLock, &fDisabledAutomaticUpdates, &pEngineState->userExperience.dwExitCode, &pEngineState->fRestart);
+    hr = ElevationChildPumpMessages(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe, pEngineState->companionConnection.hCachePipe, &pEngineState->approvedExes, &pEngineState->cache, &pEngineState->containers, &pEngineState->packages, &pEngineState->payloads, &pEngineState->variables, &pEngineState->registration, &pEngineState->userExperience, &hLock, &fDisabledAutomaticUpdates, &pEngineState->userExperience.dwExitCode, &pEngineState->fRestart);
     LogRedirect(NULL, NULL); // reset logging so the next failure gets written to "log buffer" for the failure log.
     ExitOnFailure(hr, "Failed to pump messages from parent process.");
 
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index d8ffbdb0..9eea4960 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -342,6 +342,7 @@ LExit:
 
 extern "C" HRESULT ExeEngineExecutePackage(
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
@@ -368,7 +369,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
     BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
 
     // get cached executable path
-    hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
+    hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
     ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
 
     // Best effort to set the execute package cache folder and action variables.
diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h
index 4fec2dd9..877968cd 100644
--- a/src/burn/engine/exeengine.h
+++ b/src/burn/engine/exeengine.h
@@ -32,6 +32,7 @@ HRESULT ExeEnginePlanAddPackage(
     );
 HRESULT ExeEngineExecutePackage(
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in PFN_GENERICMESSAGEHANDLER pfnGenericExecuteProgress,
diff --git a/src/burn/engine/manifest.cpp b/src/burn/engine/manifest.cpp
index b1740083..1ef8e610 100644
--- a/src/burn/engine/manifest.cpp
+++ b/src/burn/engine/manifest.cpp
@@ -133,7 +133,7 @@ static HRESULT ParseFromXml(
     ExitOnFailure(hr, "Failed to parse searches.");
 
     // parse registration
-    hr = RegistrationParseFromXml(&pEngineState->registration, pixeBundle);
+    hr = RegistrationParseFromXml(&pEngineState->registration, &pEngineState->cache, pixeBundle);
     ExitOnFailure(hr, "Failed to parse registration.");
 
     // parse update
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index 4ff129fd..c80fd79f 100644
--- a/src/burn/engine/msiengine.cpp
+++ b/src/burn/engine/msiengine.cpp
@@ -41,6 +41,7 @@ static HRESULT ConcatFeatureActionProperties(
     __inout_z LPWSTR* psczArguments
     );
 static HRESULT ConcatPatchProperty(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGE* pPackage,
     __in BOOL fRollback,
     __inout_z LPWSTR* psczArguments
@@ -1059,6 +1060,7 @@ LExit:
 extern "C" HRESULT MsiEngineExecutePackage(
     __in_opt HWND hwndParent,
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler,
@@ -1119,7 +1121,7 @@ extern "C" HRESULT MsiEngineExecutePackage(
     if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL != pExecuteAction->msiPackage.action)
     {
         // get cached MSI path
-        hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
+        hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
         ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
 
         // Best effort to set the execute package cache folder variable.
@@ -1165,10 +1167,10 @@ extern "C" HRESULT MsiEngineExecutePackage(
     ExitOnFailure(hr, "Failed to add feature action properties to obfuscated argument string.");
 
     // add slipstream patch properties
-    hr = ConcatPatchProperty(pPackage, fRollback, &sczProperties);
+    hr = ConcatPatchProperty(pCache, pPackage, fRollback, &sczProperties);
     ExitOnFailure(hr, "Failed to add patch properties to argument string.");
 
-    hr = ConcatPatchProperty(pPackage, fRollback, &sczObfuscatedProperties);
+    hr = ConcatPatchProperty(pCache, pPackage, fRollback, &sczObfuscatedProperties);
     ExitOnFailure(hr, "Failed to add patch properties to obfuscated argument string.");
 
     hr = MsiEngineConcatActionProperty(pExecuteAction->msiPackage.actionMsiProperty, &sczProperties);
@@ -1940,6 +1942,7 @@ LExit:
 }
 
 static HRESULT ConcatPatchProperty(
+    __in BURN_CACHE* pCache,
     __in BURN_PACKAGE* pPackage,
     __in BOOL fRollback,
     __inout_z LPWSTR* psczArguments
@@ -1962,7 +1965,7 @@ static HRESULT ConcatPatchProperty(
 
             if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL < patchExecuteAction)
             {
-                hr = CacheGetCompletedPath(pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory);
+                hr = CacheGetCompletedPath(pCache, pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory);
                 ExitOnFailure(hr, "Failed to get cached path for MSP package: %ls", pMspPackage->sczId);
 
                 hr = PathConcat(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath);
diff --git a/src/burn/engine/msiengine.h b/src/burn/engine/msiengine.h
index e4155a62..87f47f7c 100644
--- a/src/burn/engine/msiengine.h
+++ b/src/burn/engine/msiengine.h
@@ -63,6 +63,7 @@ HRESULT MsiEngineRollbackTransaction(
 HRESULT MsiEngineExecutePackage(
     __in_opt HWND hwndParent,
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler,
diff --git a/src/burn/engine/mspengine.cpp b/src/burn/engine/mspengine.cpp
index d547b130..3d7b5517 100644
--- a/src/burn/engine/mspengine.cpp
+++ b/src/burn/engine/mspengine.cpp
@@ -544,6 +544,7 @@ LExit:
 extern "C" HRESULT MspEngineExecutePackage(
     __in_opt HWND hwndParent,
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler,
@@ -574,7 +575,7 @@ extern "C" HRESULT MspEngineExecutePackage(
 
         if (BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->mspTarget.action)
         {
-            hr = CacheGetCompletedPath(pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory);
+            hr = CacheGetCompletedPath(pCache, pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory);
             ExitOnFailure(hr, "Failed to get cached path for MSP package: %ls", pMspPackage->sczId);
 
             // TODO: Figure out if this makes sense -- the variable is set to the last patch's path only
diff --git a/src/burn/engine/mspengine.h b/src/burn/engine/mspengine.h
index a8835d7b..d17d731d 100644
--- a/src/burn/engine/mspengine.h
+++ b/src/burn/engine/mspengine.h
@@ -62,6 +62,7 @@ HRESULT MspEnginePlanAddPackage(
 HRESULT MspEngineExecutePackage(
     __in_opt HWND hwndParent,
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler,
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp
index d6722bbf..1ce2dd11 100644
--- a/src/burn/engine/msuengine.cpp
+++ b/src/burn/engine/msuengine.cpp
@@ -233,6 +233,7 @@ LExit:
 
 extern "C" HRESULT MsuEngineExecutePackage(
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in BOOL fStopWusaService,
@@ -289,7 +290,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
     {
     case BOOTSTRAPPER_ACTION_STATE_INSTALL:
         // get cached MSU path
-        hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCachedDirectory);
+        hr = CacheGetCompletedPath(pCache, TRUE, pPackage->sczCacheId, &sczCachedDirectory);
         ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
 
         // Best effort to set the execute package cache folder variable.
diff --git a/src/burn/engine/msuengine.h b/src/burn/engine/msuengine.h
index 23dd5301..0d2563e2 100644
--- a/src/burn/engine/msuengine.h
+++ b/src/burn/engine/msuengine.h
@@ -31,6 +31,7 @@ HRESULT MsuEnginePlanAddPackage(
     );
 HRESULT MsuEngineExecutePackage(
     __in BURN_EXECUTE_ACTION* pExecuteAction,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BOOL fRollback,
     __in BOOL fStopWusaService,
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 3d6fc65f..79b7c98f 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -409,7 +409,7 @@ extern "C" HRESULT PlanLayoutBundle(
     hr = StrAllocString(&pCacheAction->bundleLayout.sczExecutableName, wzExecutableName, 0);
     ExitOnFailure(hr, "Failed to to copy executable name for bundle.");
 
-    hr = CacheCalculateBundleLayoutWorkingPath(pPlan->wzBundleId, &pCacheAction->bundleLayout.sczUnverifiedPath);
+    hr = CacheCalculateBundleLayoutWorkingPath(pPlan->pCache, pPlan->wzBundleId, &pCacheAction->bundleLayout.sczUnverifiedPath);
     ExitOnFailure(hr, "Failed to calculate bundle layout working path.");
 
     pCacheAction->bundleLayout.qwBundleSize = qwBundleSize;
@@ -526,7 +526,7 @@ extern "C" HRESULT PlanRegistration(
     pPlan->fIgnoreAllDependents = pRegistration->fIgnoreAllDependents;
 
     // Ensure the bundle is cached if not running from the cache.
-    if (!CacheBundleRunningFromCache())
+    if (!CacheBundleRunningFromCache(pPlan->pCache))
     {
         pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
     }
@@ -1021,7 +1021,7 @@ extern "C" HRESULT PlanLayoutContainer(
         }
         else
         {
-            hr = CacheCalculateContainerWorkingPath(pPlan->wzBundleId, pContainer, &pContainer->sczUnverifiedPath);
+            hr = CacheCalculateContainerWorkingPath(pPlan->pCache, pContainer, &pContainer->sczUnverifiedPath);
             ExitOnFailure(hr, "Failed to calculate unverified path for container.");
         }
     }
@@ -2235,7 +2235,7 @@ static HRESULT ProcessPayloadGroup(
 
         if (!pPayload->sczUnverifiedPath)
         {
-            hr = CacheCalculatePayloadWorkingPath(pPlan->wzBundleId, pPayload, &pPayload->sczUnverifiedPath);
+            hr = CacheCalculatePayloadWorkingPath(pPlan->pCache, pPayload, &pPayload->sczUnverifiedPath);
             ExitOnFailure(hr, "Failed to calculate unverified path for payload.");
         }
     }
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 6db464e1..28fc1639 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -229,7 +229,8 @@ typedef struct _BURN_CLEAN_ACTION
 typedef struct _BURN_PLAN
 {
     BOOTSTRAPPER_ACTION action;
-    BURN_PAYLOADS* pPayloads;   // points directly into parent the ENGINE_STATE.
+    BURN_CACHE* pCache;
+    BURN_PAYLOADS* pPayloads;
     LPWSTR wzBundleId;          // points directly into parent the ENGINE_STATE.
     LPWSTR wzBundleProviderKey; // points directly into parent the ENGINE_STATE.
     BOOL fPerMachine;
diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h
index c1822381..647a3b33 100644
--- a/src/burn/engine/precomp.h
+++ b/src/burn/engine/precomp.h
@@ -82,8 +82,8 @@
 #include "plan.h"
 #include "logging.h"
 #include "pipe.h"
-#include "core.h"
 #include "cache.h"
+#include "core.h"
 #include "apply.h"
 #include "exeengine.h"
 #include "msiengine.h"
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index 0a8fb602..d1c32b3e 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -42,7 +42,8 @@ static HRESULT ParseSoftwareTagsFromXml(
     __out DWORD* pcSoftwareTags
     );
 static HRESULT SetPaths(
-    __in BURN_REGISTRATION* pRegistration
+    __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache
     );
 static HRESULT GetBundleManufacturer(
     __in BURN_REGISTRATION* pRegistration,
@@ -120,6 +121,7 @@ static BOOL IsRegistryRebootPending();
 *******************************************************************/
 extern "C" HRESULT RegistrationParseFromXml(
     __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache,
     __in IXMLDOMNode* pixnBundle
     )
 {
@@ -335,7 +337,7 @@ extern "C" HRESULT RegistrationParseFromXml(
         ExitOnFailure(hr, "Failed to get @Classification.");
     }
 
-    hr = SetPaths(pRegistration);
+    hr = SetPaths(pRegistration, pCache);
     ExitOnFailure(hr, "Failed to set registration paths.");
 
 LExit:
@@ -614,6 +616,7 @@ LExit:
 extern "C" HRESULT RegistrationSessionBegin(
     __in_z LPCWSTR wzEngineWorkingPath,
     __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in DWORD dwRegistrationOptions,
     __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
@@ -633,7 +636,7 @@ extern "C" HRESULT RegistrationSessionBegin(
     // Cache bundle executable.
     if (dwRegistrationOptions & BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE)
     {
-        hr = CacheCompleteBundle(pRegistration->fPerMachine, pRegistration->sczExecutableName, pRegistration->sczId, wzEngineWorkingPath
+        hr = CacheCompleteBundle(pCache, pRegistration->fPerMachine, pRegistration->sczExecutableName, pRegistration->sczId, wzEngineWorkingPath
 #ifdef DEBUG
                         , pRegistration->sczCacheExecutablePath
 #endif
@@ -900,6 +903,7 @@ LExit:
  *******************************************************************/
 extern "C" HRESULT RegistrationSessionEnd(
     __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BURN_PACKAGES* pPackages,
     __in BURN_RESUME_MODE resumeMode,
@@ -964,7 +968,7 @@ extern "C" HRESULT RegistrationSessionEnd(
             ExitOnFailure(hr, "Failed to delete registration key: %ls", pRegistration->sczRegistrationKey);
         }
 
-        CacheRemoveBundle(pRegistration->fPerMachine, pRegistration->sczId);
+        CacheRemoveBundle(pCache, pRegistration->fPerMachine, pRegistration->sczId);
     }
     else // the mode needs to be updated so open the registration key.
     {
@@ -1213,7 +1217,8 @@ LExit:
 }
 
 static HRESULT SetPaths(
-    __in BURN_REGISTRATION* pRegistration
+    __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache
     )
 {
     HRESULT hr = S_OK;
@@ -1227,7 +1232,7 @@ static HRESULT SetPaths(
     ExitOnFailure(hr, "Failed to build uninstall registry key path.");
 
     // build cache directory
-    hr = CacheGetCompletedPath(pRegistration->fPerMachine, pRegistration->sczId, &sczCacheDirectory);
+    hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczId, &sczCacheDirectory);
     ExitOnFailure(hr, "Failed to build cache directory.");
 
     // build cached executable path
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h
index 936e5966..aa5bf842 100644
--- a/src/burn/engine/registration.h
+++ b/src/burn/engine/registration.h
@@ -166,6 +166,7 @@ typedef struct _BURN_REGISTRATION
 
 HRESULT RegistrationParseFromXml(
     __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache,
     __in IXMLDOMNode* pixnBundle
     );
 void RegistrationUninitialize(
@@ -188,6 +189,7 @@ HRESULT RegistrationDetectRelatedBundles(
 HRESULT RegistrationSessionBegin(
     __in_z LPCWSTR wzEngineWorkingPath,
     __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in DWORD dwRegistrationOptions,
     __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
@@ -201,6 +203,7 @@ HRESULT RegistrationSessionResume(
     );
 HRESULT RegistrationSessionEnd(
     __in BURN_REGISTRATION* pRegistration,
+    __in BURN_CACHE* pCache,
     __in BURN_VARIABLES* pVariables,
     __in BURN_PACKAGES* pPackages,
     __in BURN_RESUME_MODE resumeMode,
diff --git a/src/burn/engine/uithread.cpp b/src/burn/engine/uithread.cpp
index 433cb171..986342b2 100644
--- a/src/burn/engine/uithread.cpp
+++ b/src/burn/engine/uithread.cpp
@@ -16,7 +16,7 @@ struct UITHREAD_CONTEXT
 
 struct UITHREAD_INFO
 {
-    BOOL fElevated;
+    BOOL fElevatedEngine;
     BURN_USER_EXPERIENCE* pUserExperience;
 };
 
@@ -105,10 +105,10 @@ static DWORD WINAPI ThreadProc(
     MSG msg = { };
 
     BURN_ENGINE_STATE* pEngineState = pContext->pEngineState;
-    BOOL fElevated = BURN_MODE_ELEVATED == pContext->pEngineState->mode;
+    BOOL fElevatedEngine = BURN_MODE_ELEVATED == pContext->pEngineState->mode;
 
     // If elevated, set up the thread local storage to store the correct pipe to communicate logging.
-    if (fElevated)
+    if (fElevatedEngine)
     {
         Assert(TLS_OUT_OF_INDEXES != pEngineState->dwElevatedLoggingTlsId);
 
@@ -130,7 +130,7 @@ static DWORD WINAPI ThreadProc(
 
     fRegistered = TRUE;
 
-    info.fElevated = fElevated;
+    info.fElevatedEngine = fElevatedEngine;
     info.pUserExperience = &pEngineState->userExperience;
 
     // Create the window to handle reboots without activating it.
@@ -199,7 +199,7 @@ static LRESULT CALLBACK WndProc(
 
         // Always block shutdown in the elevated process, but ask the BA in the non-elevated.
         UITHREAD_INFO* pInfo = reinterpret_cast<UITHREAD_INFO*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
-        if (!pInfo->fElevated)
+        if (!pInfo->fElevatedEngine)
         {
             // TODO: instead of recommending canceling all non-critical shutdowns, maybe we should only recommend cancel
             //       when the engine is doing work?
@@ -209,7 +209,7 @@ static LRESULT CALLBACK WndProc(
         }
 
         fRet = !fCancel;
-        LogId(REPORT_STANDARD, MSG_SYSTEM_SHUTDOWN, LoggingBoolToString(fCritical), LoggingBoolToString(pInfo->fElevated), LoggingBoolToString(fRet));
+        LogId(REPORT_STANDARD, MSG_SYSTEM_SHUTDOWN, LoggingBoolToString(fCritical), LoggingBoolToString(pInfo->fElevatedEngine), LoggingBoolToString(fRet));
         return fRet;
         }
 
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index 88655774..69ec6347 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -161,14 +161,14 @@ extern "C" HRESULT UserExperienceUnload(
 }
 
 extern "C" HRESULT UserExperienceEnsureWorkingFolder(
-    __in LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __deref_out_z LPWSTR* psczUserExperienceWorkingFolder
     )
 {
     HRESULT hr = S_OK;
     LPWSTR sczWorkingFolder = NULL;
 
-    hr = CacheEnsureWorkingFolder(wzBundleId, &sczWorkingFolder);
+    hr = CacheEnsureWorkingFolder(pCache, &sczWorkingFolder);
     ExitOnFailure(hr, "Failed to create working folder.");
 
     hr = StrAllocFormatted(psczUserExperienceWorkingFolder, L"%ls%ls\\", sczWorkingFolder, L".ba");
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index 584bef14..aaf69083 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -15,8 +15,6 @@ const DWORD MB_RETRYTRYAGAIN = 0xF;
 
 // structs
 
-typedef struct _BOOTSTRAPPER_ENGINE_CONTEXT BOOTSTRAPPER_ENGINE_CONTEXT; // forward declare
-
 typedef struct _BURN_USER_EXPERIENCE
 {
     BURN_PAYLOADS payloads;
@@ -66,7 +64,7 @@ HRESULT UserExperienceUnload(
     __in BURN_USER_EXPERIENCE* pUserExperience
     );
 HRESULT UserExperienceEnsureWorkingFolder(
-    __in LPCWSTR wzBundleId,
+    __in BURN_CACHE* pCache,
     __deref_out_z LPWSTR* psczUserExperienceWorkingFolder
     );
 HRESULT UserExperienceRemove(
diff --git a/src/burn/test/BurnUnitTest/CacheTest.cpp b/src/burn/test/BurnUnitTest/CacheTest.cpp
index e9ad555b..6979ec1a 100644
--- a/src/burn/test/BurnUnitTest/CacheTest.cpp
+++ b/src/burn/test/BurnUnitTest/CacheTest.cpp
@@ -48,6 +48,8 @@ namespace Bootstrapper
         void CacheSignatureTest()
         {
             HRESULT hr = S_OK;
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             BURN_PACKAGE package = { };
             BURN_PAYLOAD payload = { };
             LPWSTR sczPayloadPath = NULL;
@@ -74,7 +76,10 @@ namespace Bootstrapper
                 payload.qwFileSize = 27;
                 payload.verification = BURN_PAYLOAD_VERIFICATION_HASH;
 
-                hr = CacheCompletePayload(package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE, CacheTestEventRoutine, CacheTestProgressRoutine, &context);
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
+                hr = CacheCompletePayload(&cache, package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE, CacheTestEventRoutine, CacheTestProgressRoutine, &context);
                 Assert::Equal(S_OK, hr);
             }
             finally
diff --git a/src/burn/test/BurnUnitTest/ManifestTest.cpp b/src/burn/test/BurnUnitTest/ManifestTest.cpp
index 345ddfd9..6973c772 100644
--- a/src/burn/test/BurnUnitTest/ManifestTest.cpp
+++ b/src/burn/test/BurnUnitTest/ManifestTest.cpp
@@ -40,6 +40,9 @@ namespace Bootstrapper
                     "    <CommandLine Variables='upperCase' />"
                     "</Bundle>";
 
+                hr = CacheInitialize(&engineState.cache, &engineState.internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&engineState.variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 7909d747..2e3b1092 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -925,6 +925,9 @@ namespace Bootstrapper
 
             ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
 
+            hr = CacheInitialize(&pEngineState->cache, &pEngineState->internalCommand);
+            NativeAssert::Succeeded(hr, "Failed to initialize cache.");
+
             hr = VariableInitialize(&pEngineState->variables);
             NativeAssert::Succeeded(hr, "Failed to initialize variables.");
 
@@ -948,6 +951,9 @@ namespace Bootstrapper
             hr = CoreInitializeConstants(pEngineState);
             NativeAssert::Succeeded(hr, "Failed to initialize core constants");
 
+            hr = CacheInitializeSources(&pEngineState->cache, &pEngineState->registration, &pEngineState->variables, &pEngineState->internalCommand);
+            NativeAssert::Succeeded(hr, "Failed to initialize cache sources.");
+
             pEngineState->userExperience.pfnBAProc = PlanTestBAProc;
         }
 
diff --git a/src/burn/test/BurnUnitTest/RegistrationTest.cpp b/src/burn/test/BurnUnitTest/RegistrationTest.cpp
index b1c911f7..7c0dde5a 100644
--- a/src/burn/test/BurnUnitTest/RegistrationTest.cpp
+++ b/src/burn/test/BurnUnitTest/RegistrationTest.cpp
@@ -75,6 +75,8 @@ namespace Bootstrapper
             BURN_REGISTRATION registration = { };
             BURN_LOGGING logging = { };
             BURN_PACKAGES packages = { };
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID));
 
             try
@@ -99,13 +101,16 @@ namespace Bootstrapper
                 // load XML document
                 LoadBundleXmlHelper(wzDocument, &pixeBundle);
 
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
                 hr = UserExperienceParseFromXml(&userExperience, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse UX from XML.");
 
-                hr = RegistrationParseFromXml(&registration, pixeBundle);
+                hr = RegistrationParseFromXml(&registration, &cache, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse registration from XML.");
 
                 hr = PlanSetResumeCommand(&registration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging);
@@ -115,7 +120,7 @@ namespace Bootstrapper
                 TestThrowOnFailure(hr, L"Failed to get current process path.");
 
                 // write registration
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was created
@@ -126,7 +131,7 @@ namespace Bootstrapper
                 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)(Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr)));
 
                 // end session
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // verify that registration was removed
@@ -165,6 +170,8 @@ namespace Bootstrapper
             BURN_REGISTRATION registration = { };
             BURN_LOGGING logging = { };
             BURN_PACKAGES packages = { };
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID));
             try
             {
@@ -188,13 +195,16 @@ namespace Bootstrapper
                 // load XML document
                 LoadBundleXmlHelper(wzDocument, &pixeBundle);
 
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
                 hr = UserExperienceParseFromXml(&userExperience, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse UX from XML.");
 
-                hr = RegistrationParseFromXml(&registration, pixeBundle);
+                hr = RegistrationParseFromXml(&registration, &cache, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse registration from XML.");
 
                 hr = PlanSetResumeCommand(&registration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging);
@@ -208,7 +218,7 @@ namespace Bootstrapper
                 //
 
                 // write registration
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was created
@@ -217,7 +227,7 @@ namespace Bootstrapper
                 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr));
 
                 // complete registration
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // verify that registration was updated
@@ -230,7 +240,7 @@ namespace Bootstrapper
                 //
 
                 // write registration
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was updated
@@ -239,7 +249,7 @@ namespace Bootstrapper
                 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr));
 
                 // delete registration
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // verify that registration was removed
@@ -277,6 +287,8 @@ namespace Bootstrapper
             BURN_REGISTRATION registration = { };
             BURN_LOGGING logging = { };
             BURN_PACKAGES packages = { };
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID));
             try
             {
@@ -300,13 +312,16 @@ namespace Bootstrapper
                 // load XML document
                 LoadBundleXmlHelper(wzDocument, &pixeBundle);
 
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
                 hr = UserExperienceParseFromXml(&userExperience, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse UX from XML.");
 
-                hr = RegistrationParseFromXml(&registration, pixeBundle);
+                hr = RegistrationParseFromXml(&registration, &cache, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse registration from XML.");
 
                 hr = PlanSetResumeCommand(&registration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging);
@@ -320,7 +335,7 @@ namespace Bootstrapper
                 //
 
                 // write registration
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was created
@@ -328,7 +343,7 @@ namespace Bootstrapper
                 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr));
 
                 // complete registration
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_FULL);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_FULL);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // verify that registration variables were updated
@@ -349,7 +364,7 @@ namespace Bootstrapper
                 //
 
                 // delete registration
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // verify that registration was removed
@@ -387,6 +402,8 @@ namespace Bootstrapper
             BURN_REGISTRATION registration = { };
             BURN_LOGGING logging = { };
             BURN_PACKAGES packages = { };
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             String^ cacheDirectory = Path::Combine(Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), gcnew String(L"Package Cache")), gcnew String(TEST_BUNDLE_ID));
             try
             {
@@ -412,13 +429,16 @@ namespace Bootstrapper
                 // load XML document
                 LoadBundleXmlHelper(wzDocument, &pixeBundle);
 
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
                 hr = UserExperienceParseFromXml(&userExperience, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse UX from XML.");
 
-                hr = RegistrationParseFromXml(&registration, pixeBundle);
+                hr = RegistrationParseFromXml(&registration, &cache, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse registration from XML.");
 
                 hr = PlanSetResumeCommand(&registration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging);
@@ -432,7 +452,7 @@ namespace Bootstrapper
                 //
 
                 // write registration
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was created
@@ -440,7 +460,7 @@ namespace Bootstrapper
                 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr));
 
                 // finish registration
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_FULL);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_FULL);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was updated
@@ -465,7 +485,7 @@ namespace Bootstrapper
                 //
 
                 // write registration
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 // verify that registration was updated
@@ -473,7 +493,7 @@ namespace Bootstrapper
                 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr));
 
                 // delete registration
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // verify that registration was removed
@@ -514,6 +534,8 @@ namespace Bootstrapper
             BURN_REGISTRATION registration = { };
             BURN_LOGGING logging = { };
             BURN_PACKAGES packages = { };
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             BYTE* pbBuffer = NULL;
             SIZE_T cbBuffer = 0;
             
@@ -546,6 +568,9 @@ namespace Bootstrapper
                 // load XML document
                 LoadBundleXmlHelper(wzDocument, &pixeBundle);
 
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
@@ -555,7 +580,7 @@ namespace Bootstrapper
                 hr = UserExperienceParseFromXml(&userExperience, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse UX from XML.");
 
-                hr = RegistrationParseFromXml(&registration, pixeBundle);
+                hr = RegistrationParseFromXml(&registration, &cache, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse registration from XML.");
 
                 hr = PlanSetResumeCommand(&registration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging);
@@ -565,7 +590,7 @@ namespace Bootstrapper
                 TestThrowOnFailure(hr, L"Failed to get current process path.");
 
                 // begin session
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 VariableSetNumericHelper(&variables, L"MyBurnVariable1", 42);
@@ -608,7 +633,7 @@ namespace Bootstrapper
                 NativeAssert::StringEqual(L"42", sczValue);
 
                 // end session
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
             }
             finally
@@ -643,6 +668,8 @@ namespace Bootstrapper
             BURN_REGISTRATION registration = { };
             BURN_LOGGING logging = { };
             BURN_PACKAGES packages = { };
+            BURN_CACHE cache = { };
+            BURN_ENGINE_COMMAND internalCommand = { };
             BOOTSTRAPPER_RESUME_TYPE resumeType = BOOTSTRAPPER_RESUME_TYPE_NONE;
             BYTE* pbBuffer = NULL;
             SIZE_T cbBuffer = 0;
@@ -674,6 +701,9 @@ namespace Bootstrapper
                 // load XML document
                 LoadBundleXmlHelper(wzDocument, &pixeBundle);
 
+                hr = CacheInitialize(&cache, &internalCommand);
+                TestThrowOnFailure(hr, L"Failed initialize cache.");
+
                 hr = VariableInitialize(&variables);
                 TestThrowOnFailure(hr, L"Failed to initialize variables.");
 
@@ -683,7 +713,7 @@ namespace Bootstrapper
                 hr = UserExperienceParseFromXml(&userExperience, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse UX from XML.");
 
-                hr = RegistrationParseFromXml(&registration, pixeBundle);
+                hr = RegistrationParseFromXml(&registration, &cache, pixeBundle);
                 TestThrowOnFailure(hr, L"Failed to parse registration from XML.");
 
                 hr = PlanSetResumeCommand(&registration, BOOTSTRAPPER_ACTION_INSTALL, &command, &logging);
@@ -699,7 +729,7 @@ namespace Bootstrapper
                 Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_NONE, (int)resumeType);
 
                 // begin session
-                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &cache, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to register bundle.");
 
                 VariableSetNumericHelper(&variables, L"MyBurnVariable1", 42);
@@ -738,7 +768,7 @@ namespace Bootstrapper
                 Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED, (int)resumeType);
 
                 // suspend session
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_SUSPEND, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_SUSPEND, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
                 TestThrowOnFailure(hr, L"Failed to suspend session.");
 
                 // verify that run key was removed
@@ -765,7 +795,7 @@ namespace Bootstrapper
                 Assert::NotEqual((Object^)nullptr, Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(TEST_BUNDLE_ID), nullptr));
 
                 // end session
-                hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
+                hr = RegistrationSessionEnd(&registration, &cache, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
                 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
 
                 // read resume type after session
diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h
index 78c44d39..a77dfe32 100644
--- a/src/burn/test/BurnUnitTest/precomp.h
+++ b/src/burn/test/BurnUnitTest/precomp.h
@@ -56,8 +56,8 @@
 #include "plan.h"
 #include "pipe.h"
 #include "logging.h"
-#include "core.h"
 #include "cache.h"
+#include "core.h"
 #include "apply.h"
 #include "exeengine.h"
 #include "msiengine.h"
-- 
cgit v1.2.3-55-g6feb