aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2025-02-11 05:21:34 -0800
committerRob Mensching <rob@firegiant.com>2025-02-11 15:49:33 -0800
commitf2e9af96142439ebfdbc1e884335bb8874f8a427 (patch)
treef3ffd15660a7041d1f70d793e2b2200ccbe42af5 /src/burn
parent81fb512834c65b0a8f99c3a266879c476e382875 (diff)
downloadwix-f2e9af96142439ebfdbc1e884335bb8874f8a427.tar.gz
wix-f2e9af96142439ebfdbc1e884335bb8874f8a427.tar.bz2
wix-f2e9af96142439ebfdbc1e884335bb8874f8a427.zip
Harden Burn's BootstrapperApplication and elevated engine extraction
Fixes 8914
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/bootstrapperapplication.cpp8
-rw-r--r--src/burn/engine/cache.cpp86
-rw-r--r--src/burn/engine/cache.h7
-rw-r--r--src/burn/engine/container.cpp18
-rw-r--r--src/burn/engine/container.h5
-rw-r--r--src/burn/engine/core.cpp14
-rw-r--r--src/burn/engine/core.h1
-rw-r--r--src/burn/engine/elevation.cpp4
-rw-r--r--src/burn/engine/engine.cpp3
-rw-r--r--src/burn/engine/payload.cpp14
-rw-r--r--src/burn/engine/payload.h1
-rw-r--r--src/burn/engine/plan.cpp1
-rw-r--r--src/burn/test/BurnUnitTest/ElevationTest.cpp2
-rw-r--r--src/burn/test/BurnUnitTest/ExitCodeTest.cpp2
14 files changed, 122 insertions, 44 deletions
diff --git a/src/burn/engine/bootstrapperapplication.cpp b/src/burn/engine/bootstrapperapplication.cpp
index 947b3720..dc3bd5da 100644
--- a/src/burn/engine/bootstrapperapplication.cpp
+++ b/src/burn/engine/bootstrapperapplication.cpp
@@ -306,6 +306,14 @@ EXTERN_C HRESULT BootstrapperApplicationRemove(
306{ 306{
307 HRESULT hr = S_OK; 307 HRESULT hr = S_OK;
308 308
309 // Release any open file handles so we can try to recursively delete the temp folder.
310 for (DWORD i = 0; i < pUserExperience->payloads.cPayloads; ++i)
311 {
312 BURN_PAYLOAD* pPayload = pUserExperience->payloads.rgPayloads + i;
313
314 ReleaseFileHandle(pPayload->hLocalFile);
315 }
316
309 // Remove temporary UX directory 317 // Remove temporary UX directory
310 if (pUserExperience->sczTempDirectory) 318 if (pUserExperience->sczTempDirectory)
311 { 319 {
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index 5a8388c4..16db4a81 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -112,13 +112,15 @@ static HRESULT CopyEngineToWorkingFolder(
112 __in_z LPCWSTR wzWorkingFolderName, 112 __in_z LPCWSTR wzWorkingFolderName,
113 __in_z LPCWSTR wzExecutableName, 113 __in_z LPCWSTR wzExecutableName,
114 __in BURN_SECTION* pSection, 114 __in BURN_SECTION* pSection,
115 __deref_out_z_opt LPWSTR* psczEngineWorkingPath 115 __out_z LPWSTR* psczEngineWorkingPath,
116 __out HANDLE* phEngineWorkingFile
116 ); 117 );
117static HRESULT CopyEngineWithSignatureFixup( 118static HRESULT CopyEngineWithSignatureFixup(
118 __in HANDLE hEngineFile, 119 __in HANDLE hEngineFile,
119 __in_z LPCWSTR wzEnginePath, 120 __in_z LPCWSTR wzEnginePath,
120 __in_z LPCWSTR wzTargetPath, 121 __in_z LPCWSTR wzTargetPath,
121 __in BURN_SECTION* pSection 122 __in BURN_SECTION* pSection,
123 __out HANDLE* phEngineFile
122 ); 124 );
123static HRESULT RemoveBundleOrPackage( 125static HRESULT RemoveBundleOrPackage(
124 __in BURN_CACHE* pCache, 126 __in BURN_CACHE* pCache,
@@ -915,33 +917,59 @@ extern "C" HRESULT CacheBundleToWorkingDirectory(
915 __in BOOL fElevated, 917 __in BOOL fElevated,
916 __in BURN_CACHE* pCache, 918 __in BURN_CACHE* pCache,
917 __in_z LPCWSTR wzExecutableName, 919 __in_z LPCWSTR wzExecutableName,
918 __in BURN_SECTION* pSection, 920 __in BURN_SECTION* pSection
919 __deref_out_z_opt LPWSTR* psczEngineWorkingPath
920 ) 921 )
921{ 922{
922 Assert(pCache->fInitializedCache); 923 Assert(pCache->fInitializedCache);
923 924
924 HRESULT hr = S_OK; 925 HRESULT hr = S_OK;
925 LPWSTR sczSourcePath = NULL; 926 LPWSTR sczSourcePath = NULL;
927 LPWSTR sczEngineWorkingPath = NULL;
928 HANDLE hEngineWorkingFile = INVALID_HANDLE_VALUE;
929
930 // If we already cached the engine, bail.
931 if (pCache->sczBundleEngineWorkingPath && INVALID_HANDLE_VALUE != pCache->hBundleEngineWorkingFile)
932 {
933 ExitFunction();
934 }
926 935
927 // Initialize the source. 936 // Initialize the source.
928 hr = PathForCurrentProcess(&sczSourcePath, NULL); 937 hr = PathForCurrentProcess(&sczSourcePath, NULL);
929 ExitOnFailure(hr, "Failed to get current process path."); 938 ExitOnFailure(hr, "Failed to get current process path.");
930 939
931 // If the bundle is running out of the package cache then we don't need to copy it to 940 // If the bundle is running out of the package cache then we don't need to copy it to
932 // the working folder since we feel safe in the package cache and will run from there. 941 // the working folder (and we don't need to lock the file either) since we feel safe
942 // in the package cache and will run from there.
933 if (CacheBundleRunningFromCache(pCache)) 943 if (CacheBundleRunningFromCache(pCache))
934 { 944 {
935 hr = StrAllocString(psczEngineWorkingPath, sczSourcePath, 0); 945 hr = StrAllocString(&sczEngineWorkingPath, sczSourcePath, 0);
936 ExitOnFailure(hr, "Failed to use current process path as target path."); 946 ExitOnFailure(hr, "Failed to copy current process path as bundle engine working path.");
937 } 947 }
938 else // otherwise, carry on putting the bundle in the working folder. 948 else // otherwise, carry on putting the bundle in the working folder and lock it.
939 { 949 {
940 hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, psczEngineWorkingPath); 950 hr = CopyEngineToWorkingFolder(fElevated, pCache, sczSourcePath, BUNDLE_WORKING_FOLDER_NAME, wzExecutableName, pSection, &sczEngineWorkingPath, &hEngineWorkingFile);
941 ExitOnFailure(hr, "Failed to copy engine to working folder."); 951 ExitOnFailure(hr, "Failed to copy engine to working folder.");
942 } 952
953 // Close the engine file handle (if we opened it) then reopen it read-only as quickly as possible to lock it.
954 ReleaseFileHandle(hEngineWorkingFile);
955
956 hr = FileCreateWithRetry(sczEngineWorkingPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 30, 100, &hEngineWorkingFile);
957 ExitOnFailure(hr, "Failed to lock bundle engine file: %ls", sczEngineWorkingPath);
958 }
959
960 // Clean out any previous values (there shouldn't be any).
961 ReleaseNullStr(pCache->sczBundleEngineWorkingPath);
962 ReleaseFileHandle(pCache->hBundleEngineWorkingFile);
963
964 pCache->sczBundleEngineWorkingPath = sczEngineWorkingPath;
965 sczEngineWorkingPath = NULL;
966
967 pCache->hBundleEngineWorkingFile = hEngineWorkingFile;
968 hEngineWorkingFile = INVALID_HANDLE_VALUE;
943 969
944LExit: 970LExit:
971 ReleaseFileHandle(hEngineWorkingFile);
972 ReleaseStr(sczEngineWorkingPath);
945 ReleaseStr(sczSourcePath); 973 ReleaseStr(sczSourcePath);
946 974
947 return hr; 975 return hr;
@@ -1206,9 +1234,14 @@ extern "C" HRESULT CacheRemoveBaseWorkingFolder(
1206 1234
1207 if (pCache->fInitializedBaseWorkingFolder) 1235 if (pCache->fInitializedBaseWorkingFolder)
1208 { 1236 {
1237 // Release the engine file handle if it is open to ensure the working folder can be deleted.
1238 ReleaseFileHandle(pCache->hBundleEngineWorkingFile);
1239
1209 // Try to clean out everything in the working folder. 1240 // Try to clean out everything in the working folder.
1210 hr = DirEnsureDeleteEx(pCache->sczBaseWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE); 1241 hr = DirEnsureDeleteEx(pCache->sczBaseWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE);
1211 TraceError(hr, "Could not delete bundle engine working folder."); 1242 TraceError(hr, "Could not delete bundle engine working folder.");
1243
1244 pCache->fInitializedBaseWorkingFolder = FALSE;
1212 } 1245 }
1213 1246
1214 return hr; 1247 return hr;
@@ -1396,6 +1429,8 @@ extern "C" void CacheUninitialize(
1396 ReleaseStr(pCache->sczBaseWorkingFolder); 1429 ReleaseStr(pCache->sczBaseWorkingFolder);
1397 ReleaseStr(pCache->sczAcquisitionFolder); 1430 ReleaseStr(pCache->sczAcquisitionFolder);
1398 ReleaseStr(pCache->sczSourceProcessFolder); 1431 ReleaseStr(pCache->sczSourceProcessFolder);
1432 ReleaseStr(pCache->sczBundleEngineWorkingPath)
1433 ReleaseFileHandle(pCache->hBundleEngineWorkingFile)
1399 1434
1400 memset(pCache, 0, sizeof(BURN_CACHE)); 1435 memset(pCache, 0, sizeof(BURN_CACHE));
1401} 1436}
@@ -2094,16 +2129,15 @@ static HRESULT CopyEngineToWorkingFolder(
2094 __in_z LPCWSTR wzWorkingFolderName, 2129 __in_z LPCWSTR wzWorkingFolderName,
2095 __in_z LPCWSTR wzExecutableName, 2130 __in_z LPCWSTR wzExecutableName,
2096 __in BURN_SECTION* pSection, 2131 __in BURN_SECTION* pSection,
2097 __deref_out_z_opt LPWSTR* psczEngineWorkingPath 2132 __out_z LPWSTR* psczEngineWorkingPath,
2133 __out HANDLE* phEngineWorkingFile
2098 ) 2134 )
2099{ 2135{
2100 HRESULT hr = S_OK; 2136 HRESULT hr = S_OK;
2101 LPWSTR sczWorkingFolder = NULL; 2137 LPWSTR sczWorkingFolder = NULL;
2102 LPWSTR sczTargetDirectory = NULL; 2138 LPWSTR sczTargetDirectory = NULL;
2103 LPWSTR sczTargetPath = NULL; 2139 LPWSTR sczTargetPath = NULL;
2104 LPWSTR sczSourceDirectory = NULL; 2140 HANDLE hTargetFile = INVALID_HANDLE_VALUE;
2105 LPWSTR sczPayloadSourcePath = NULL;
2106 LPWSTR sczPayloadTargetPath = NULL;
2107 2141
2108 hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder); 2142 hr = CacheEnsureBaseWorkingFolder(fElevated, pCache, &sczWorkingFolder);
2109 ExitOnFailure(hr, "Failed to create working path to copy engine."); 2143 ExitOnFailure(hr, "Failed to create working path to copy engine.");
@@ -2118,19 +2152,17 @@ static HRESULT CopyEngineToWorkingFolder(
2118 ExitOnFailure(hr, "Failed to combine working path with engine file name."); 2152 ExitOnFailure(hr, "Failed to combine working path with engine file name.");
2119 2153
2120 // Copy the engine without any attached containers to the working path. 2154 // Copy the engine without any attached containers to the working path.
2121 hr = CopyEngineWithSignatureFixup(pSection->hEngineFile, wzSourcePath, sczTargetPath, pSection); 2155 hr = CopyEngineWithSignatureFixup(pSection->hEngineFile, wzSourcePath, sczTargetPath, pSection, &hTargetFile);
2122 ExitOnFailure(hr, "Failed to copy engine: '%ls' to working path: %ls", wzSourcePath, sczTargetPath); 2156 ExitOnFailure(hr, "Failed to copy engine: '%ls' to working path: %ls", wzSourcePath, sczTargetPath);
2123 2157
2124 if (psczEngineWorkingPath) 2158 *psczEngineWorkingPath = sczTargetPath;
2125 { 2159 sczTargetPath = NULL;
2126 hr = StrAllocString(psczEngineWorkingPath, sczTargetPath, 0); 2160
2127 ExitOnFailure(hr, "Failed to copy target path for engine working path."); 2161 *phEngineWorkingFile = hTargetFile;
2128 } 2162 hTargetFile = INVALID_HANDLE_VALUE;
2129 2163
2130LExit: 2164LExit:
2131 ReleaseStr(sczPayloadTargetPath); 2165 ReleaseFileHandle(hTargetFile);
2132 ReleaseStr(sczPayloadSourcePath);
2133 ReleaseStr(sczSourceDirectory);
2134 ReleaseStr(sczTargetPath); 2166 ReleaseStr(sczTargetPath);
2135 ReleaseStr(sczTargetDirectory); 2167 ReleaseStr(sczTargetDirectory);
2136 ReleaseStr(sczWorkingFolder); 2168 ReleaseStr(sczWorkingFolder);
@@ -2143,7 +2175,8 @@ static HRESULT CopyEngineWithSignatureFixup(
2143 __in HANDLE hEngineFile, 2175 __in HANDLE hEngineFile,
2144 __in_z LPCWSTR wzEnginePath, 2176 __in_z LPCWSTR wzEnginePath,
2145 __in_z LPCWSTR wzTargetPath, 2177 __in_z LPCWSTR wzTargetPath,
2146 __in BURN_SECTION* pSection 2178 __in BURN_SECTION* pSection,
2179 __out HANDLE* phEngineFile
2147 ) 2180 )
2148{ 2181{
2149 HRESULT hr = S_OK; 2182 HRESULT hr = S_OK;
@@ -2151,7 +2184,7 @@ static HRESULT CopyEngineWithSignatureFixup(
2151 LARGE_INTEGER li = { }; 2184 LARGE_INTEGER li = { };
2152 DWORD dwZeroOriginals[3] = { }; 2185 DWORD dwZeroOriginals[3] = { };
2153 2186
2154 hTarget = ::CreateFileW(wzTargetPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 2187 hTarget = ::CreateFileW(wzTargetPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2155 if (INVALID_HANDLE_VALUE == hTarget) 2188 if (INVALID_HANDLE_VALUE == hTarget)
2156 { 2189 {
2157 ExitWithLastError(hr, "Failed to create engine file at path: %ls", wzTargetPath); 2190 ExitWithLastError(hr, "Failed to create engine file at path: %ls", wzTargetPath);
@@ -2200,6 +2233,9 @@ static HRESULT CopyEngineWithSignatureFixup(
2200 ExitOnFailure(hr, "Failed to zero out original data offset."); 2233 ExitOnFailure(hr, "Failed to zero out original data offset.");
2201 } 2234 }
2202 2235
2236 *phEngineFile = hTarget;
2237 hTarget = INVALID_HANDLE_VALUE;
2238
2203LExit: 2239LExit:
2204 ReleaseFileHandle(hTarget); 2240 ReleaseFileHandle(hTarget);
2205 2241
diff --git a/src/burn/engine/cache.h b/src/burn/engine/cache.h
index cce35df0..c2e6e157 100644
--- a/src/burn/engine/cache.h
+++ b/src/burn/engine/cache.h
@@ -49,6 +49,10 @@ typedef struct _BURN_CACHE
49 // Only valid after CacheEnsureBaseWorkingFolder 49 // Only valid after CacheEnsureBaseWorkingFolder
50 BOOL fInitializedBaseWorkingFolder; 50 BOOL fInitializedBaseWorkingFolder;
51 LPWSTR sczBaseWorkingFolder; 51 LPWSTR sczBaseWorkingFolder;
52
53 // Only valid after CacheBundleToWorkingDirectory
54 LPWSTR sczBundleEngineWorkingPath;
55 HANDLE hBundleEngineWorkingFile;
52} BURN_CACHE; 56} BURN_CACHE;
53 57
54typedef struct _BURN_CACHE_MESSAGE 58typedef struct _BURN_CACHE_MESSAGE
@@ -175,8 +179,7 @@ HRESULT CacheBundleToWorkingDirectory(
175 __in BOOL fElvated, 179 __in BOOL fElvated,
176 __in BURN_CACHE* pCache, 180 __in BURN_CACHE* pCache,
177 __in_z LPCWSTR wzExecutableName, 181 __in_z LPCWSTR wzExecutableName,
178 __in BURN_SECTION* pSection, 182 __in BURN_SECTION* pSection
179 __deref_out_z_opt LPWSTR* psczEngineWorkingPath
180 ); 183 );
181HRESULT CacheLayoutBundle( 184HRESULT CacheLayoutBundle(
182 __in_z LPCWSTR wzExecutableName, 185 __in_z LPCWSTR wzExecutableName,
diff --git a/src/burn/engine/container.cpp b/src/burn/engine/container.cpp
index e6b91532..fad010cf 100644
--- a/src/burn/engine/container.cpp
+++ b/src/burn/engine/container.cpp
@@ -326,6 +326,24 @@ extern "C" HRESULT ContainerStreamToBuffer(
326 return hr; 326 return hr;
327} 327}
328 328
329extern "C" HRESULT ContainerStreamToHandle(
330 __in BURN_CONTAINER_CONTEXT* pContext,
331 __in HANDLE hFile
332 )
333{
334 HRESULT hr = S_OK;
335
336 switch (pContext->type)
337 {
338 case BURN_CONTAINER_TYPE_CABINET:
339 hr = CabExtractStreamToHandle(pContext, hFile);
340 break;
341 }
342
343//LExit:
344 return hr;
345}
346
329extern "C" HRESULT ContainerSkipStream( 347extern "C" HRESULT ContainerSkipStream(
330 __in BURN_CONTAINER_CONTEXT* pContext 348 __in BURN_CONTAINER_CONTEXT* pContext
331 ) 349 )
diff --git a/src/burn/engine/container.h b/src/burn/engine/container.h
index a38afa90..5306e7db 100644
--- a/src/burn/engine/container.h
+++ b/src/burn/engine/container.h
@@ -48,6 +48,7 @@ enum BURN_CAB_OPERATION
48 BURN_CAB_OPERATION_NEXT_STREAM, 48 BURN_CAB_OPERATION_NEXT_STREAM,
49 BURN_CAB_OPERATION_STREAM_TO_FILE, 49 BURN_CAB_OPERATION_STREAM_TO_FILE,
50 BURN_CAB_OPERATION_STREAM_TO_BUFFER, 50 BURN_CAB_OPERATION_STREAM_TO_BUFFER,
51 BURN_CAB_OPERATION_STREAM_TO_HANDLE,
51 BURN_CAB_OPERATION_SKIP_STREAM, 52 BURN_CAB_OPERATION_SKIP_STREAM,
52 BURN_CAB_OPERATION_CLOSE, 53 BURN_CAB_OPERATION_CLOSE,
53}; 54};
@@ -184,6 +185,10 @@ HRESULT ContainerStreamToBuffer(
184 __out BYTE** ppbBuffer, 185 __out BYTE** ppbBuffer,
185 __out SIZE_T* pcbBuffer 186 __out SIZE_T* pcbBuffer
186 ); 187 );
188HRESULT ContainerStreamToHandle(
189 __in BURN_CONTAINER_CONTEXT* pContext,
190 __in HANDLE hFile
191 );
187HRESULT ContainerSkipStream( 192HRESULT ContainerSkipStream(
188 __in BURN_CONTAINER_CONTEXT* pContext 193 __in BURN_CONTAINER_CONTEXT* pContext
189 ); 194 );
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 3fe9b586..b20f7f0c 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -586,11 +586,8 @@ extern "C" HRESULT CoreElevate(
586 while (INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe) 586 while (INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe)
587 { 587 {
588 // If the elevated companion pipe isn't created yet, let's make that happen. 588 // If the elevated companion pipe isn't created yet, let's make that happen.
589 if (!pEngineState->sczBundleEngineWorkingPath) 589 hr = CacheBundleToWorkingDirectory(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section);
590 { 590 ExitOnFailure(hr, "Failed to cache engine to working directory.");
591 hr = CacheBundleToWorkingDirectory(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath);
592 ExitOnFailure(hr, "Failed to cache engine to working directory.");
593 }
594 591
595 hr = ElevationElevate(pEngineState, reason, hwndParent); 592 hr = ElevationElevate(pEngineState, reason, hwndParent);
596 if (E_SUSPECTED_AV_INTERFERENCE == hr && 1 > cAVRetryAttempts) 593 if (E_SUSPECTED_AV_INTERFERENCE == hr && 1 > cAVRetryAttempts)
@@ -695,11 +692,8 @@ extern "C" HRESULT CoreApply(
695 ::InitializeCriticalSection(&applyContext.csApply); 692 ::InitializeCriticalSection(&applyContext.csApply);
696 693
697 // Ensure the engine is cached to the working path. 694 // Ensure the engine is cached to the working path.
698 if (!pEngineState->sczBundleEngineWorkingPath) 695 hr = CacheBundleToWorkingDirectory(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section);
699 { 696 ExitOnFailure(hr, "Failed to cache engine to working directory.");
700 hr = CacheBundleToWorkingDirectory(pEngineState->internalCommand.fInitiallyElevated, &pEngineState->cache, pEngineState->registration.sczExecutableName, &pEngineState->section, &pEngineState->sczBundleEngineWorkingPath);
701 ExitOnFailure(hr, "Failed to cache engine to working directory.");
702 }
703 697
704 // Elevate. 698 // Elevate.
705 if (pEngineState->plan.fPerMachine) 699 if (pEngineState->plan.fPerMachine)
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 787100b7..c5d0a370 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -172,7 +172,6 @@ typedef struct _BURN_ENGINE_STATE
172 BURN_REDIRECTED_LOGGING_CONTEXT elevatedLoggingContext; 172 BURN_REDIRECTED_LOGGING_CONTEXT elevatedLoggingContext;
173 HANDLE hUnelevatedLoggingThread; 173 HANDLE hUnelevatedLoggingThread;
174 174
175 LPWSTR sczBundleEngineWorkingPath;
176 BURN_PIPE_CONNECTION companionConnection; 175 BURN_PIPE_CONNECTION companionConnection;
177 BURN_PIPE_CONNECTION embeddedConnection; 176 BURN_PIPE_CONNECTION embeddedConnection;
178 177
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 85d5a543..90e9db01 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -1677,8 +1677,8 @@ static HRESULT LaunchElevatedProcess(
1677 1677
1678 // Since ShellExecuteEx doesn't support passing inherited handles, don't bother with CoreAppendFileHandleSelfToCommandLine. 1678 // Since ShellExecuteEx doesn't support passing inherited handles, don't bother with CoreAppendFileHandleSelfToCommandLine.
1679 // We could fallback to using ::DuplicateHandle to inject the file handle later if necessary. 1679 // We could fallback to using ::DuplicateHandle to inject the file handle later if necessary.
1680 hr = ShelExec(pEngineState->sczBundleEngineWorkingPath, sczParameters, L"runas", NULL, SW_SHOWNA, hwndParent, &hProcess); 1680 hr = ShelExec(pEngineState->cache.sczBundleEngineWorkingPath, sczParameters, L"runas", NULL, SW_SHOWNA, hwndParent, &hProcess);
1681 ExitOnFailure(hr, "Failed to launch elevated child process: %ls", pEngineState->sczBundleEngineWorkingPath); 1681 ExitOnFailure(hr, "Failed to launch elevated child process: %ls", pEngineState->cache.sczBundleEngineWorkingPath);
1682 1682
1683 pConnection->dwProcessId = ::GetProcessId(hProcess); 1683 pConnection->dwProcessId = ::GetProcessId(hProcess);
1684 pConnection->hProcess = hProcess; 1684 pConnection->hProcess = hProcess;
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index 5fec289d..2232358d 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -364,6 +364,8 @@ static HRESULT InitializeEngineState(
364 HANDLE hSectionFile = hEngineFile; 364 HANDLE hSectionFile = hEngineFile;
365 HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE; 365 HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE;
366 366
367 pEngineState->cache.hBundleEngineWorkingFile = INVALID_HANDLE_VALUE;
368
367 pEngineState->hUnelevatedLoggingThread = INVALID_HANDLE_VALUE; 369 pEngineState->hUnelevatedLoggingThread = INVALID_HANDLE_VALUE;
368 pEngineState->elevatedLoggingContext.hPipe = INVALID_HANDLE_VALUE; 370 pEngineState->elevatedLoggingContext.hPipe = INVALID_HANDLE_VALUE;
369 pEngineState->elevatedLoggingContext.hThread = INVALID_HANDLE_VALUE; 371 pEngineState->elevatedLoggingContext.hThread = INVALID_HANDLE_VALUE;
@@ -413,7 +415,6 @@ static void UninitializeEngineState(
413 415
414 BurnPipeConnectionUninitialize(&pEngineState->embeddedConnection); 416 BurnPipeConnectionUninitialize(&pEngineState->embeddedConnection);
415 BurnPipeConnectionUninitialize(&pEngineState->companionConnection); 417 BurnPipeConnectionUninitialize(&pEngineState->companionConnection);
416 ReleaseStr(pEngineState->sczBundleEngineWorkingPath)
417 418
418 ReleaseHandle(pEngineState->hMessageWindowThread); 419 ReleaseHandle(pEngineState->hMessageWindowThread);
419 420
diff --git a/src/burn/engine/payload.cpp b/src/burn/engine/payload.cpp
index 1d8328e3..270da6aa 100644
--- a/src/burn/engine/payload.cpp
+++ b/src/burn/engine/payload.cpp
@@ -239,6 +239,7 @@ extern "C" void PayloadUninitialize(
239 ReleaseMem(pPayload->pbCertificateRootThumbprint); 239 ReleaseMem(pPayload->pbCertificateRootThumbprint);
240 ReleaseMem(pPayload->pbCertificateRootPublicKeyIdentifier); 240 ReleaseMem(pPayload->pbCertificateRootPublicKeyIdentifier);
241 ReleaseStr(pPayload->sczSourcePath); 241 ReleaseStr(pPayload->sczSourcePath);
242 ReleaseFileHandle(pPayload->hLocalFile);
242 ReleaseStr(pPayload->sczLocalFilePath); 243 ReleaseStr(pPayload->sczLocalFilePath);
243 ReleaseStr(pPayload->sczFailedLocalAcquisitionPath); 244 ReleaseStr(pPayload->sczFailedLocalAcquisitionPath);
244 ReleaseStr(pPayload->downloadSource.sczUrl); 245 ReleaseStr(pPayload->downloadSource.sczUrl);
@@ -278,6 +279,7 @@ extern "C" HRESULT PayloadExtractUXContainer(
278 LPWSTR sczStreamName = NULL; 279 LPWSTR sczStreamName = NULL;
279 LPWSTR sczDirectory = NULL; 280 LPWSTR sczDirectory = NULL;
280 BURN_PAYLOAD* pPayload = NULL; 281 BURN_PAYLOAD* pPayload = NULL;
282 HANDLE hTargetFile = INVALID_HANDLE_VALUE;
281 283
282 // extract all payloads 284 // extract all payloads
283 for (;;) 285 for (;;)
@@ -306,9 +308,18 @@ extern "C" HRESULT PayloadExtractUXContainer(
306 hr = DirEnsureExists(sczDirectory, NULL); 308 hr = DirEnsureExists(sczDirectory, NULL);
307 ExitOnFailure(hr, "Failed to ensure directory exists"); 309 ExitOnFailure(hr, "Failed to ensure directory exists");
308 310
309 hr = ContainerStreamToFile(pContainerContext, pPayload->sczLocalFilePath); 311 hTargetFile = ::CreateFileW(pPayload->sczLocalFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
312 ExitOnInvalidHandleWithLastError(hTargetFile, hr, "Failed to create file: %ls", pPayload->sczLocalFilePath);
313
314 hr = ContainerStreamToHandle(pContainerContext, hTargetFile);
310 ExitOnFailure(hr, "Failed to extract file."); 315 ExitOnFailure(hr, "Failed to extract file.");
311 316
317 // Reopen the payload for read-only access to prevent the file from being removed or tampered with while the BA is running.
318 ReleaseFileHandle(hTargetFile);
319
320 hr = FileCreateWithRetry(pPayload->sczLocalFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 30, 100, &pPayload->hLocalFile);
321 ExitOnFailure(hr, "Failed to open file: %ls", pPayload->sczLocalFilePath);
322
312 // flag that the payload has been acquired 323 // flag that the payload has been acquired
313 pPayload->state = BURN_PAYLOAD_STATE_ACQUIRED; 324 pPayload->state = BURN_PAYLOAD_STATE_ACQUIRED;
314 } 325 }
@@ -326,6 +337,7 @@ extern "C" HRESULT PayloadExtractUXContainer(
326 } 337 }
327 338
328LExit: 339LExit:
340 ReleaseFileHandle(hTargetFile);
329 ReleaseStr(sczStreamName); 341 ReleaseStr(sczStreamName);
330 ReleaseStr(sczDirectory); 342 ReleaseStr(sczDirectory);
331 343
diff --git a/src/burn/engine/payload.h b/src/burn/engine/payload.h
index 351fd058..4c21ae54 100644
--- a/src/burn/engine/payload.h
+++ b/src/burn/engine/payload.h
@@ -57,6 +57,7 @@ typedef struct _BURN_PAYLOAD
57 // mutable members 57 // mutable members
58 BURN_PAYLOAD_STATE state; 58 BURN_PAYLOAD_STATE state;
59 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy 59 LPWSTR sczLocalFilePath; // location of extracted or downloaded copy
60 HANDLE hLocalFile;
60 61
61 LPWSTR sczUnverifiedPath; 62 LPWSTR sczUnverifiedPath;
62 DWORD cRemainingInstances; 63 DWORD cRemainingInstances;
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 47b1c621..7994dd32 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -2117,6 +2117,7 @@ static void ResetPlannedPayloadsState(
2117 pPayload->cRemainingInstances = 0; 2117 pPayload->cRemainingInstances = 0;
2118 pPayload->state = BURN_PAYLOAD_STATE_NONE; 2118 pPayload->state = BURN_PAYLOAD_STATE_NONE;
2119 pPayload->fFailedVerificationFromAcquisition = FALSE; 2119 pPayload->fFailedVerificationFromAcquisition = FALSE;
2120 ReleaseFileHandle(pPayload->hLocalFile);
2120 ReleaseNullStr(pPayload->sczLocalFilePath); 2121 ReleaseNullStr(pPayload->sczLocalFilePath);
2121 ReleaseNullStr(pPayload->sczFailedLocalAcquisitionPath); 2122 ReleaseNullStr(pPayload->sczFailedLocalAcquisitionPath);
2122 } 2123 }
diff --git a/src/burn/test/BurnUnitTest/ElevationTest.cpp b/src/burn/test/BurnUnitTest/ElevationTest.cpp
index f9ae2579..81e9f93e 100644
--- a/src/burn/test/BurnUnitTest/ElevationTest.cpp
+++ b/src/burn/test/BurnUnitTest/ElevationTest.cpp
@@ -55,7 +55,7 @@ namespace Bootstrapper
55 BURN_PIPE_CONNECTION* pConnection = &engineState.companionConnection; 55 BURN_PIPE_CONNECTION* pConnection = &engineState.companionConnection;
56 DWORD dwResult = S_OK; 56 DWORD dwResult = S_OK;
57 57
58 engineState.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe"; 58 engineState.cache.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe";
59 59
60 try 60 try
61 { 61 {
diff --git a/src/burn/test/BurnUnitTest/ExitCodeTest.cpp b/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
index c742543b..9b66f4c0 100644
--- a/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
+++ b/src/burn/test/BurnUnitTest/ExitCodeTest.cpp
@@ -105,7 +105,7 @@ static void LoadEngineState(
105 { (DWORD)HRESULT_FROM_WIN32(ERROR_FAIL_REBOOT_INITIATED), HRESULT_FROM_WIN32(ERROR_FAIL_REBOOT_INITIATED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" }, 105 { (DWORD)HRESULT_FROM_WIN32(ERROR_FAIL_REBOOT_INITIATED), HRESULT_FROM_WIN32(ERROR_FAIL_REBOOT_INITIATED), BOOTSTRAPPER_APPLY_RESTART_NONE, L"Custom" },
106 }; 106 };
107 107
108 engineState.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe"; 108 engineState.cache.sczBundleEngineWorkingPath = L"tests\\ignore\\this\\path\\to\\burn.exe";
109 109
110 try 110 try
111 { 111 {