diff options
author | Rob Mensching <rob@firegiant.com> | 2025-02-11 05:21:34 -0800 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2025-02-11 15:49:33 -0800 |
commit | f2e9af96142439ebfdbc1e884335bb8874f8a427 (patch) | |
tree | f3ffd15660a7041d1f70d793e2b2200ccbe42af5 /src/burn | |
parent | 81fb512834c65b0a8f99c3a266879c476e382875 (diff) | |
download | wix-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.cpp | 8 | ||||
-rw-r--r-- | src/burn/engine/cache.cpp | 86 | ||||
-rw-r--r-- | src/burn/engine/cache.h | 7 | ||||
-rw-r--r-- | src/burn/engine/container.cpp | 18 | ||||
-rw-r--r-- | src/burn/engine/container.h | 5 | ||||
-rw-r--r-- | src/burn/engine/core.cpp | 14 | ||||
-rw-r--r-- | src/burn/engine/core.h | 1 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 4 | ||||
-rw-r--r-- | src/burn/engine/engine.cpp | 3 | ||||
-rw-r--r-- | src/burn/engine/payload.cpp | 14 | ||||
-rw-r--r-- | src/burn/engine/payload.h | 1 | ||||
-rw-r--r-- | src/burn/engine/plan.cpp | 1 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/ElevationTest.cpp | 2 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/ExitCodeTest.cpp | 2 |
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 | ); |
117 | static HRESULT CopyEngineWithSignatureFixup( | 118 | static 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 | ); |
123 | static HRESULT RemoveBundleOrPackage( | 125 | static 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 | ||
944 | LExit: | 970 | LExit: |
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 | ||
2130 | LExit: | 2164 | LExit: |
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 | |||
2203 | LExit: | 2239 | LExit: |
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 | ||
54 | typedef struct _BURN_CACHE_MESSAGE | 58 | typedef 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 | ); |
181 | HRESULT CacheLayoutBundle( | 184 | HRESULT 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 | ||
329 | extern "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 | |||
329 | extern "C" HRESULT ContainerSkipStream( | 347 | extern "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 | ); |
188 | HRESULT ContainerStreamToHandle( | ||
189 | __in BURN_CONTAINER_CONTEXT* pContext, | ||
190 | __in HANDLE hFile | ||
191 | ); | ||
187 | HRESULT ContainerSkipStream( | 192 | HRESULT 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 | ||
328 | LExit: | 339 | LExit: |
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 | { |