diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/burn/engine/cache.cpp | 127 | ||||
-rw-r--r-- | src/burn/engine/cache.h | 7 | ||||
-rw-r--r-- | src/burn/engine/engine.cpp | 7 | ||||
-rw-r--r-- | src/burn/engine/engine.mc | 16 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/CacheTest.cpp | 95 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/precomp.h | 2 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/guidutil.cpp | 4 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | 9 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 38 | ||||
-rw-r--r-- | src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | 28 | ||||
-rw-r--r-- | src/test/burn/WixTestTools/BundleVerifier.cs | 12 | ||||
-rw-r--r-- | src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs | 68 |
12 files changed, 338 insertions, 75 deletions
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index b311a195..7fca8cc7 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp | |||
@@ -14,10 +14,10 @@ static HRESULT CacheVerifyPayloadSignature( | |||
14 | __in_z LPCWSTR wzUnverifiedPayloadPath, | 14 | __in_z LPCWSTR wzUnverifiedPayloadPath, |
15 | __in HANDLE hFile | 15 | __in HANDLE hFile |
16 | ); | 16 | ); |
17 | static HRESULT CalculateBaseWorkingFolder( | 17 | static HRESULT CalculatePotentialBaseWorkingFolders( |
18 | __in BURN_CACHE* pCache, | ||
18 | __in BURN_ENGINE_COMMAND* pInternalCommand, | 19 | __in BURN_ENGINE_COMMAND* pInternalCommand, |
19 | __in LPCWSTR wzAcquisitionFolder, | 20 | __in LPCWSTR wzAcquisitionFolder |
20 | __inout_z LPWSTR* psczBaseWorkingFolder | ||
21 | ); | 21 | ); |
22 | static HRESULT CalculateWorkingFolders( | 22 | static HRESULT CalculateWorkingFolders( |
23 | __in BURN_CACHE* pCache, | 23 | __in BURN_CACHE* pCache, |
@@ -321,8 +321,8 @@ extern "C" HRESULT CacheEnsureAcquisitionFolder( | |||
321 | hr = DirEnsureExists(pCache->sczAcquisitionFolder, NULL); | 321 | hr = DirEnsureExists(pCache->sczAcquisitionFolder, NULL); |
322 | ExitOnFailure(hr, "Failed create acquisition folder."); | 322 | ExitOnFailure(hr, "Failed create acquisition folder."); |
323 | 323 | ||
324 | // Best effort to ensure our working folder is not encrypted. | 324 | // Best effort to ensure our acquisition folder is not encrypted. |
325 | ::DecryptFileW(pCache->sczBaseWorkingFolder, 0); | 325 | ::DecryptFileW(pCache->sczAcquisitionFolder, 0); |
326 | 326 | ||
327 | LExit: | 327 | LExit: |
328 | return hr; | 328 | return hr; |
@@ -336,9 +336,30 @@ extern "C" HRESULT CacheEnsureBaseWorkingFolder( | |||
336 | Assert(pCache->fInitializedCache); | 336 | Assert(pCache->fInitializedCache); |
337 | 337 | ||
338 | HRESULT hr = S_OK; | 338 | HRESULT hr = S_OK; |
339 | LPWSTR sczPotential = NULL; | ||
340 | |||
341 | if (!pCache->fInitializedBaseWorkingFolder) | ||
342 | { | ||
343 | for (DWORD i = 0; i < pCache->cPotentialBaseWorkingFolders; ++i) | ||
344 | { | ||
345 | hr = PathConcatRelativeToBase(pCache->rgsczPotentialBaseWorkingFolders[i], pCache->wzGuid, &sczPotential); | ||
346 | ExitOnFailure(hr, "Failed to append random guid on to potential path for working folder."); | ||
347 | |||
348 | hr = DirEnsureExists(sczPotential, NULL); | ||
349 | if (SUCCEEDED(hr)) | ||
350 | { | ||
351 | pCache->sczBaseWorkingFolder = sczPotential; | ||
352 | sczPotential = NULL; | ||
353 | break; | ||
354 | } | ||
355 | |||
356 | LogErrorId(hr, MSG_INVALID_BASE_WORKING_FOLDER, sczPotential, NULL, NULL); | ||
357 | } | ||
339 | 358 | ||
340 | hr = DirEnsureExists(pCache->sczBaseWorkingFolder, NULL); | 359 | ExitOnNull(pCache->sczBaseWorkingFolder, hr, E_INVALIDSTATE, "No usable base working folder found."); |
341 | ExitOnFailure(hr, "Failed create working folder."); | 360 | |
361 | pCache->fInitializedBaseWorkingFolder = TRUE; | ||
362 | } | ||
342 | 363 | ||
343 | // Best effort to ensure our working folder is not encrypted. | 364 | // Best effort to ensure our working folder is not encrypted. |
344 | ::DecryptFileW(pCache->sczBaseWorkingFolder, 0); | 365 | ::DecryptFileW(pCache->sczBaseWorkingFolder, 0); |
@@ -350,6 +371,8 @@ extern "C" HRESULT CacheEnsureBaseWorkingFolder( | |||
350 | } | 371 | } |
351 | 372 | ||
352 | LExit: | 373 | LExit: |
374 | ReleaseStr(sczPotential); | ||
375 | |||
353 | return hr; | 376 | return hr; |
354 | } | 377 | } |
355 | 378 | ||
@@ -360,6 +383,7 @@ extern "C" HRESULT CacheCalculateBundleWorkingPath( | |||
360 | ) | 383 | ) |
361 | { | 384 | { |
362 | Assert(pCache->fInitializedCache); | 385 | Assert(pCache->fInitializedCache); |
386 | Assert(pCache->fInitializedBaseWorkingFolder); | ||
363 | 387 | ||
364 | HRESULT hr = S_OK; | 388 | HRESULT hr = S_OK; |
365 | 389 | ||
@@ -1180,7 +1204,7 @@ extern "C" HRESULT CacheRemoveBaseWorkingFolder( | |||
1180 | { | 1204 | { |
1181 | HRESULT hr = S_OK; | 1205 | HRESULT hr = S_OK; |
1182 | 1206 | ||
1183 | if (pCache->fInitializedCacheSources) | 1207 | if (pCache->fInitializedBaseWorkingFolder) |
1184 | { | 1208 | { |
1185 | // Try to clean out everything in the working folder. | 1209 | // Try to clean out everything in the working folder. |
1186 | hr = DirEnsureDeleteEx(pCache->sczBaseWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE); | 1210 | hr = DirEnsureDeleteEx(pCache->sczBaseWorkingFolder, DIR_DELETE_FILES | DIR_DELETE_RECURSE | DIR_DELETE_SCHEDULE); |
@@ -1343,70 +1367,78 @@ extern "C" void CacheUninitialize( | |||
1343 | __in BURN_CACHE* pCache | 1367 | __in BURN_CACHE* pCache |
1344 | ) | 1368 | ) |
1345 | { | 1369 | { |
1346 | ReleaseNullStr(pCache->sczCurrentMachinePackageCache); | 1370 | ReleaseStrArray(pCache->rgsczPotentialBaseWorkingFolders, pCache->cPotentialBaseWorkingFolders); |
1347 | ReleaseNullStr(pCache->sczDefaultMachinePackageCache); | 1371 | ReleaseStr(pCache->sczCurrentMachinePackageCache); |
1348 | ReleaseNullStr(pCache->sczDefaultUserPackageCache); | 1372 | ReleaseStr(pCache->sczDefaultMachinePackageCache); |
1349 | ReleaseNullStr(pCache->sczBaseWorkingFolder); | 1373 | ReleaseStr(pCache->sczDefaultUserPackageCache); |
1350 | ReleaseNullStr(pCache->sczAcquisitionFolder); | 1374 | ReleaseStr(pCache->sczBaseWorkingFolder); |
1351 | ReleaseNullStr(pCache->sczSourceProcessFolder); | 1375 | ReleaseStr(pCache->sczAcquisitionFolder); |
1352 | 1376 | ReleaseStr(pCache->sczSourceProcessFolder); | |
1353 | pCache->fRunningFromCache = FALSE; | 1377 | |
1354 | pCache->fInitializedCache = FALSE; | 1378 | memset(pCache, 0, sizeof(BURN_CACHE)); |
1355 | pCache->fInitializedCacheSources = FALSE; | ||
1356 | pCache->fPerMachineCacheRootVerified = FALSE; | ||
1357 | pCache->fOriginalPerMachineCacheRootVerified = FALSE; | ||
1358 | pCache->fUnverifiedCacheFolderCreated = FALSE; | ||
1359 | pCache->fCustomMachinePackageCache = FALSE; | ||
1360 | } | 1379 | } |
1361 | 1380 | ||
1362 | // Internal functions. | 1381 | // Internal functions. |
1363 | 1382 | ||
1364 | static HRESULT CalculateBaseWorkingFolder( | 1383 | static HRESULT CalculatePotentialBaseWorkingFolders( |
1384 | __in BURN_CACHE* pCache, | ||
1365 | __in BURN_ENGINE_COMMAND* pInternalCommand, | 1385 | __in BURN_ENGINE_COMMAND* pInternalCommand, |
1366 | __in LPCWSTR wzAcquisitionFolder, | 1386 | __in LPCWSTR wzAcquisitionFolder |
1367 | __inout_z LPWSTR* psczBaseWorkingFolder | ||
1368 | ) | 1387 | ) |
1369 | { | 1388 | { |
1389 | Assert(!pCache->rgsczPotentialBaseWorkingFolders && !pCache->cPotentialBaseWorkingFolders); | ||
1370 | HRESULT hr = S_OK; | 1390 | HRESULT hr = S_OK; |
1391 | LPWSTR sczTemp = NULL; | ||
1371 | 1392 | ||
1372 | ReleaseNullStr(*psczBaseWorkingFolder); | 1393 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pCache->rgsczPotentialBaseWorkingFolders), 6, sizeof(LPWSTR), 6); |
1394 | ExitOnFailure(hr, "Failed to initialize array."); | ||
1373 | 1395 | ||
1374 | // The value from the command line takes precedence. | 1396 | // The value from the command line takes precedence. |
1375 | if (pInternalCommand->sczEngineWorkingDirectory) | 1397 | if (pInternalCommand->sczEngineWorkingDirectory) |
1376 | { | 1398 | { |
1377 | hr = PathExpand(psczBaseWorkingFolder, pInternalCommand->sczEngineWorkingDirectory, PATH_EXPAND_FULLPATH); | 1399 | hr = PathExpand(&sczTemp, pInternalCommand->sczEngineWorkingDirectory, PATH_EXPAND_FULLPATH); |
1378 | ExitOnFailure(hr, "Failed to expand engine working directory from command-line: '%ls'", pInternalCommand->sczEngineWorkingDirectory); | 1400 | ExitOnFailure(hr, "Failed to expand engine working directory from command-line: '%ls'", pInternalCommand->sczEngineWorkingDirectory); |
1379 | 1401 | ||
1380 | ExitFunction(); | 1402 | pCache->rgsczPotentialBaseWorkingFolders[pCache->cPotentialBaseWorkingFolders] = sczTemp; |
1403 | sczTemp = NULL; | ||
1404 | ++pCache->cPotentialBaseWorkingFolders; | ||
1381 | } | 1405 | } |
1382 | 1406 | ||
1383 | // The base working folder can be specified through policy, | 1407 | // The base working folder can be specified through policy, |
1384 | // but only use it if elevated because it should be secured against non-admin users. | 1408 | // but only use it if elevated because it should be secured against non-admin users. |
1385 | if (pInternalCommand->fInitiallyElevated) | 1409 | if (pInternalCommand->fInitiallyElevated) |
1386 | { | 1410 | { |
1387 | hr = PolcReadString(POLICY_BURN_REGISTRY_PATH, L"EngineWorkingDirectory", NULL, psczBaseWorkingFolder); | 1411 | hr = PolcReadString(POLICY_BURN_REGISTRY_PATH, L"EngineWorkingDirectory", NULL, &sczTemp); |
1388 | ExitOnFailure(hr, "Failed to read EngineWorkingDirectory policy directory."); | 1412 | ExitOnFailure(hr, "Failed to read EngineWorkingDirectory policy directory."); |
1389 | 1413 | ||
1390 | if (*psczBaseWorkingFolder) | 1414 | if (sczTemp) |
1391 | { | 1415 | { |
1392 | // PolcReadString is supposed to automatically expand REG_EXPAND_SZ values. | 1416 | // PolcReadString is supposed to automatically expand REG_EXPAND_SZ values. |
1393 | ExitFunction(); | 1417 | pCache->rgsczPotentialBaseWorkingFolders[pCache->cPotentialBaseWorkingFolders] = sczTemp; |
1418 | sczTemp = NULL; | ||
1419 | ++pCache->cPotentialBaseWorkingFolders; | ||
1394 | } | 1420 | } |
1395 | } | 1421 | } |
1396 | 1422 | ||
1397 | // Default to the acquisition folder, but need to use system temp path for security reasons if running elevated. | 1423 | // Default to the acquisition folder, but need to use system temp path for security reasons if running elevated. |
1398 | if (pInternalCommand->fInitiallyElevated) | 1424 | if (pInternalCommand->fInitiallyElevated) |
1399 | { | 1425 | { |
1400 | hr = PathGetSystemTempPath(psczBaseWorkingFolder); | 1426 | hr = PathGetSystemTempPaths(&pCache->rgsczPotentialBaseWorkingFolders, &pCache->cPotentialBaseWorkingFolders); |
1401 | ExitOnFailure(hr, "Failed to get system temp folder path for base working folder."); | 1427 | ExitOnFailure(hr, "Failed to get system temp folder paths for base working folder."); |
1402 | } | 1428 | } |
1403 | else | 1429 | else |
1404 | { | 1430 | { |
1405 | hr = StrAllocString(psczBaseWorkingFolder, wzAcquisitionFolder, 0); | 1431 | hr = StrAllocString(&sczTemp, wzAcquisitionFolder, 0); |
1406 | ExitOnFailure(hr, "Failed to copy acquisition folder path for base working folder."); | 1432 | ExitOnFailure(hr, "Failed to copy acquisition folder path for base working folder."); |
1433 | |||
1434 | pCache->rgsczPotentialBaseWorkingFolders[pCache->cPotentialBaseWorkingFolders] = sczTemp; | ||
1435 | sczTemp = NULL; | ||
1436 | ++pCache->cPotentialBaseWorkingFolders; | ||
1407 | } | 1437 | } |
1408 | 1438 | ||
1409 | LExit: | 1439 | LExit: |
1440 | ReleaseStr(sczTemp); | ||
1441 | |||
1410 | return hr; | 1442 | return hr; |
1411 | } | 1443 | } |
1412 | 1444 | ||
@@ -1416,11 +1448,7 @@ static HRESULT CalculateWorkingFolders( | |||
1416 | ) | 1448 | ) |
1417 | { | 1449 | { |
1418 | HRESULT hr = S_OK; | 1450 | HRESULT hr = S_OK; |
1419 | RPC_STATUS rs = RPC_S_OK; | ||
1420 | LPWSTR sczBaseAcquisitionPath = NULL; | 1451 | LPWSTR sczBaseAcquisitionPath = NULL; |
1421 | LPWSTR sczTempPath = NULL; | ||
1422 | UUID guid = {}; | ||
1423 | WCHAR wzGuid[39]; | ||
1424 | 1452 | ||
1425 | hr = PathGetTempPath(&sczBaseAcquisitionPath); | 1453 | hr = PathGetTempPath(&sczBaseAcquisitionPath); |
1426 | ExitOnFailure(hr, "Failed to get temp folder path for acquisition folder base."); | 1454 | ExitOnFailure(hr, "Failed to get temp folder path for acquisition folder base."); |
@@ -1428,31 +1456,20 @@ static HRESULT CalculateWorkingFolders( | |||
1428 | hr = PathBackslashTerminate(&sczBaseAcquisitionPath); | 1456 | hr = PathBackslashTerminate(&sczBaseAcquisitionPath); |
1429 | ExitOnFailure(hr, "Failed to backslashify base engine working directory."); | 1457 | ExitOnFailure(hr, "Failed to backslashify base engine working directory."); |
1430 | 1458 | ||
1431 | hr = CalculateBaseWorkingFolder(pInternalCommand, sczBaseAcquisitionPath, &sczTempPath); | 1459 | hr = CalculatePotentialBaseWorkingFolders(pCache, pInternalCommand, sczBaseAcquisitionPath); |
1432 | ExitOnFailure(hr, "Failed to get base engine working directory."); | 1460 | ExitOnFailure(hr, "Failed to get potential base engine working directories."); |
1433 | |||
1434 | hr = PathBackslashTerminate(&sczTempPath); | ||
1435 | ExitOnFailure(hr, "Failed to backslashify base engine working directory."); | ||
1436 | 1461 | ||
1437 | rs = ::UuidCreate(&guid); | 1462 | hr = GuidFixedCreate(pCache->wzGuid); |
1438 | hr = HRESULT_FROM_RPC(rs); | ||
1439 | ExitOnFailure(hr, "Failed to create working folder guid."); | 1463 | ExitOnFailure(hr, "Failed to create working folder guid."); |
1440 | 1464 | ||
1441 | if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid))) | 1465 | pCache->wzGuid[GUID_STRING_LENGTH - 1] = L'\\'; |
1442 | { | 1466 | pCache->wzGuid[GUID_STRING_LENGTH] = L'\0'; |
1443 | hr = E_OUTOFMEMORY; | ||
1444 | ExitOnRootFailure(hr, "Failed to convert working folder guid into string."); | ||
1445 | } | ||
1446 | 1467 | ||
1447 | hr = StrAllocFormatted(&pCache->sczAcquisitionFolder, L"%ls%ls\\", sczBaseAcquisitionPath, wzGuid); | 1468 | hr = PathConcatRelativeToBase(sczBaseAcquisitionPath, pCache->wzGuid, &pCache->sczAcquisitionFolder); |
1448 | ExitOnFailure(hr, "Failed to append random guid on to temp path for acquisition folder."); | 1469 | ExitOnFailure(hr, "Failed to append random guid on to temp path for acquisition folder."); |
1449 | 1470 | ||
1450 | hr = StrAllocFormatted(&pCache->sczBaseWorkingFolder, L"%ls%ls\\", sczTempPath, wzGuid); | ||
1451 | ExitOnFailure(hr, "Failed to append random guid on to temp path for working folder."); | ||
1452 | |||
1453 | LExit: | 1471 | LExit: |
1454 | ReleaseStr(sczBaseAcquisitionPath); | 1472 | ReleaseStr(sczBaseAcquisitionPath); |
1455 | ReleaseStr(sczTempPath); | ||
1456 | 1473 | ||
1457 | return hr; | 1474 | return hr; |
1458 | } | 1475 | } |
diff --git a/src/burn/engine/cache.h b/src/burn/engine/cache.h index 8b038b99..9c698b4b 100644 --- a/src/burn/engine/cache.h +++ b/src/burn/engine/cache.h | |||
@@ -35,11 +35,18 @@ typedef struct _BURN_CACHE | |||
35 | LPWSTR sczDefaultMachinePackageCache; | 35 | LPWSTR sczDefaultMachinePackageCache; |
36 | LPWSTR sczCurrentMachinePackageCache; | 36 | LPWSTR sczCurrentMachinePackageCache; |
37 | 37 | ||
38 | WCHAR wzGuid[GUID_STRING_LENGTH + 1]; | ||
39 | LPWSTR* rgsczPotentialBaseWorkingFolders; | ||
40 | DWORD cPotentialBaseWorkingFolders; | ||
41 | |||
38 | // Only valid after CacheInitializeSources | 42 | // Only valid after CacheInitializeSources |
39 | BOOL fInitializedCacheSources; | 43 | BOOL fInitializedCacheSources; |
40 | BOOL fRunningFromCache; | 44 | BOOL fRunningFromCache; |
41 | LPWSTR sczSourceProcessFolder; | 45 | LPWSTR sczSourceProcessFolder; |
42 | LPWSTR sczAcquisitionFolder; | 46 | LPWSTR sczAcquisitionFolder; |
47 | |||
48 | // Only valid after CacheEnsureBaseWorkingFolder | ||
49 | BOOL fInitializedBaseWorkingFolder; | ||
43 | LPWSTR sczBaseWorkingFolder; | 50 | LPWSTR sczBaseWorkingFolder; |
44 | } BURN_CACHE; | 51 | } BURN_CACHE; |
45 | 52 | ||
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index a408ed4a..aca43438 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp | |||
@@ -97,6 +97,7 @@ extern "C" HRESULT EngineRun( | |||
97 | LPWSTR sczExePath = NULL; | 97 | LPWSTR sczExePath = NULL; |
98 | BOOL fRunUntrusted = FALSE; | 98 | BOOL fRunUntrusted = FALSE; |
99 | BOOL fRunNormal = FALSE; | 99 | BOOL fRunNormal = FALSE; |
100 | BOOL fRunRunOnce = FALSE; | ||
100 | BOOL fRestart = FALSE; | 101 | BOOL fRestart = FALSE; |
101 | 102 | ||
102 | BURN_ENGINE_STATE engineState = { }; | 103 | BURN_ENGINE_STATE engineState = { }; |
@@ -221,6 +222,8 @@ extern "C" HRESULT EngineRun( | |||
221 | break; | 222 | break; |
222 | 223 | ||
223 | case BURN_MODE_RUNONCE: | 224 | case BURN_MODE_RUNONCE: |
225 | fRunRunOnce = TRUE; | ||
226 | |||
224 | hr = RunRunOnce(&engineState, nCmdShow); | 227 | hr = RunRunOnce(&engineState, nCmdShow); |
225 | ExitOnFailure(hr, "Failed to run RunOnce mode."); | 228 | ExitOnFailure(hr, "Failed to run RunOnce mode."); |
226 | break; | 229 | break; |
@@ -303,6 +306,10 @@ LExit: | |||
303 | { | 306 | { |
304 | LogId(REPORT_STANDARD, MSG_EXITING_CLEAN_ROOM, FAILED(hr) ? (int)hr : *pdwExitCode); | 307 | LogId(REPORT_STANDARD, MSG_EXITING_CLEAN_ROOM, FAILED(hr) ? (int)hr : *pdwExitCode); |
305 | } | 308 | } |
309 | else if (fRunRunOnce) | ||
310 | { | ||
311 | LogId(REPORT_STANDARD, MSG_EXITING_RUN_ONCE, FAILED(hr) ? (int)hr : *pdwExitCode); | ||
312 | } | ||
306 | 313 | ||
307 | if (fLogInitialized) | 314 | if (fLogInitialized) |
308 | { | 315 | { |
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index 32473252..9a08fa3f 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc | |||
@@ -149,6 +149,20 @@ Language=English | |||
149 | Exit code: 0x%1!x! | 149 | Exit code: 0x%1!x! |
150 | . | 150 | . |
151 | 151 | ||
152 | MessageId=18 | ||
153 | Severity=Success | ||
154 | SymbolicName=MSG_EXITING_RUN_ONCE | ||
155 | Language=English | ||
156 | Exit code: 0x%1!x! | ||
157 | . | ||
158 | |||
159 | MessageId=19 | ||
160 | Severity=Warning | ||
161 | SymbolicName=MSG_INVALID_BASE_WORKING_FOLDER | ||
162 | Language=English | ||
163 | Failed to use folder as base working folder: %2!ls!, encountered error: %1!ls!. | ||
164 | . | ||
165 | |||
152 | MessageId=51 | 166 | MessageId=51 |
153 | Severity=Error | 167 | Severity=Error |
154 | SymbolicName=MSG_FAILED_PARSE_CONDITION | 168 | SymbolicName=MSG_FAILED_PARSE_CONDITION |
@@ -811,7 +825,7 @@ MessageId=346 | |||
811 | Severity=Warning | 825 | Severity=Warning |
812 | SymbolicName=MSG_CACHE_RETRYING_PACKAGE | 826 | SymbolicName=MSG_CACHE_RETRYING_PACKAGE |
813 | Language=English | 827 | Language=English |
814 | Application requested retry of caching package: %1!ls!, encountered error: 0x%2!x!. Retrying... | 828 | Application requested retry of caching package: %2!ls!, encountered error: %1!ls!. Retrying... |
815 | . | 829 | . |
816 | 830 | ||
817 | MessageId=347 | 831 | MessageId=347 |
diff --git a/src/burn/test/BurnUnitTest/CacheTest.cpp b/src/burn/test/BurnUnitTest/CacheTest.cpp index 6979ec1a..eb0b31ab 100644 --- a/src/burn/test/BurnUnitTest/CacheTest.cpp +++ b/src/burn/test/BurnUnitTest/CacheTest.cpp | |||
@@ -37,11 +37,100 @@ namespace Bootstrapper | |||
37 | using namespace System::IO; | 37 | using namespace System::IO; |
38 | using namespace Xunit; | 38 | using namespace Xunit; |
39 | 39 | ||
40 | public ref class CacheTest : BurnUnitTest | 40 | public ref class CacheTest : BurnUnitTest, IClassFixture<TestRegistryFixture^> |
41 | { | 41 | { |
42 | private: | ||
43 | TestRegistryFixture^ testRegistry; | ||
42 | public: | 44 | public: |
43 | CacheTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture) | 45 | CacheTest(BurnTestFixture^ fixture, TestRegistryFixture^ registryFixture) : BurnUnitTest(fixture) |
44 | { | 46 | { |
47 | this->testRegistry = registryFixture; | ||
48 | } | ||
49 | |||
50 | [Fact] | ||
51 | void CacheElevatedTempFallbacksTest() | ||
52 | { | ||
53 | HRESULT hr = S_OK; | ||
54 | BURN_CACHE cache = { }; | ||
55 | BURN_ENGINE_COMMAND internalCommand = { }; | ||
56 | HKEY hkSystemEnvironment = NULL; | ||
57 | HKEY hkBurnPolicy = NULL; | ||
58 | |||
59 | internalCommand.fInitiallyElevated = TRUE; | ||
60 | |||
61 | try | ||
62 | { | ||
63 | this->testRegistry->SetUp(); | ||
64 | |||
65 | // No registry keys, so should fallback to %windir%\TEMP. | ||
66 | hr = CacheInitialize(&cache, &internalCommand); | ||
67 | NativeAssert::Succeeded(hr, "Failed to initialize cache."); | ||
68 | Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders); | ||
69 | VerifyBaseWorkingFolder(L"%windir%\\TEMP\\", cache.rgsczPotentialBaseWorkingFolders[0]); | ||
70 | CacheUninitialize(&cache); | ||
71 | |||
72 | hr = RegCreate(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", GENERIC_WRITE, &hkSystemEnvironment); | ||
73 | NativeAssert::Succeeded(hr, "Failed to create system environment key."); | ||
74 | |||
75 | // Third fallback is system-level %TEMP%. | ||
76 | hr = RegWriteExpandString(hkSystemEnvironment, L"TEMP", L"A:\\TEST\\TEMP"); | ||
77 | NativeAssert::Succeeded(hr, "Failed to write TEMP system environment value."); | ||
78 | |||
79 | hr = CacheInitialize(&cache, &internalCommand); | ||
80 | NativeAssert::Succeeded(hr, "Failed to initialize cache."); | ||
81 | Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders); | ||
82 | VerifyBaseWorkingFolder(L"A:\\TEST\\TEMP\\", cache.rgsczPotentialBaseWorkingFolders[0]); | ||
83 | CacheUninitialize(&cache); | ||
84 | |||
85 | // Second fallback is system-level %TMP%. | ||
86 | hr = RegWriteExpandString(hkSystemEnvironment, L"TMP", L"B:\\TEST\\TMP\\"); | ||
87 | NativeAssert::Succeeded(hr, "Failed to write TEMP system environment value."); | ||
88 | |||
89 | hr = CacheInitialize(&cache, &internalCommand); | ||
90 | NativeAssert::Succeeded(hr, "Failed to initialize cache."); | ||
91 | Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders); | ||
92 | VerifyBaseWorkingFolder(L"B:\\TEST\\TMP\\", cache.rgsczPotentialBaseWorkingFolders[0]); | ||
93 | CacheUninitialize(&cache); | ||
94 | |||
95 | hr = RegCreate(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\WiX\\Burn", GENERIC_WRITE, &hkBurnPolicy); | ||
96 | NativeAssert::Succeeded(hr, "Failed to create Burn policy key."); | ||
97 | |||
98 | // Default source is Burn policy. | ||
99 | hr = RegWriteExpandString(hkBurnPolicy, L"EngineWorkingDirectory", L"D:\\TEST\\POLICY\\"); | ||
100 | NativeAssert::Succeeded(hr, "Failed to write EngineWorkingDirectory Burn policy value."); | ||
101 | |||
102 | hr = CacheInitialize(&cache, &internalCommand); | ||
103 | NativeAssert::Succeeded(hr, "Failed to initialize cache."); | ||
104 | Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders); | ||
105 | VerifyBaseWorkingFolder(L"D:\\TEST\\POLICY\\", cache.rgsczPotentialBaseWorkingFolders[0]); | ||
106 | CacheUninitialize(&cache); | ||
107 | |||
108 | // Command line parameter overrides everything else. | ||
109 | hr = StrAllocString(&internalCommand.sczEngineWorkingDirectory, L"E:\\TEST\\COMMANDLINE\\", 0); | ||
110 | NativeAssert::Succeeded(hr, "Failed to copy command line working directory."); | ||
111 | |||
112 | hr = CacheInitialize(&cache, &internalCommand); | ||
113 | NativeAssert::Succeeded(hr, "Failed to initialize cache."); | ||
114 | Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders); | ||
115 | VerifyBaseWorkingFolder(L"E:\\TEST\\COMMANDLINE\\", cache.rgsczPotentialBaseWorkingFolders[0]); | ||
116 | CacheUninitialize(&cache); | ||
117 | } | ||
118 | finally | ||
119 | { | ||
120 | ReleaseRegKey(hkBurnPolicy); | ||
121 | ReleaseRegKey(hkSystemEnvironment); | ||
122 | ReleaseStr(internalCommand.sczEngineWorkingDirectory); | ||
123 | |||
124 | CacheUninitialize(&cache); | ||
125 | |||
126 | this->testRegistry->TearDown(); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | void VerifyBaseWorkingFolder(LPCWSTR wzExpectedUnexpanded, LPCWSTR wzActual) | ||
131 | { | ||
132 | String^ expected = Environment::ExpandEnvironmentVariables(gcnew String(wzExpectedUnexpanded)); | ||
133 | WixAssert::StringEqual(expected, gcnew String(wzActual), true); | ||
45 | } | 134 | } |
46 | 135 | ||
47 | [Fact] | 136 | [Fact] |
@@ -93,6 +182,8 @@ namespace Bootstrapper | |||
93 | File::SetAttributes(filePath, FileAttributes::Normal); | 182 | File::SetAttributes(filePath, FileAttributes::Normal); |
94 | File::Delete(filePath); | 183 | File::Delete(filePath); |
95 | } | 184 | } |
185 | |||
186 | CacheUninitialize(&cache); | ||
96 | } | 187 | } |
97 | } | 188 | } |
98 | }; | 189 | }; |
diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h index 11e54284..92c8c4c0 100644 --- a/src/burn/test/BurnUnitTest/precomp.h +++ b/src/burn/test/BurnUnitTest/precomp.h | |||
@@ -19,9 +19,11 @@ | |||
19 | #include <buffutil.h> | 19 | #include <buffutil.h> |
20 | #include <dirutil.h> | 20 | #include <dirutil.h> |
21 | #include <fileutil.h> | 21 | #include <fileutil.h> |
22 | #include <guidutil.h> | ||
22 | #include <logutil.h> | 23 | #include <logutil.h> |
23 | #include <memutil.h> | 24 | #include <memutil.h> |
24 | #include <pathutil.h> | 25 | #include <pathutil.h> |
26 | #include <polcutil.h> | ||
25 | #include <regutil.h> | 27 | #include <regutil.h> |
26 | #include <resrutil.h> | 28 | #include <resrutil.h> |
27 | #include <shelutil.h> | 29 | #include <shelutil.h> |
diff --git a/src/libs/dutil/WixToolset.DUtil/guidutil.cpp b/src/libs/dutil/WixToolset.DUtil/guidutil.cpp index 204c9af2..946c256f 100644 --- a/src/libs/dutil/WixToolset.DUtil/guidutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/guidutil.cpp | |||
@@ -9,6 +9,7 @@ | |||
9 | #define GuidExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) | 9 | #define GuidExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) |
10 | #define GuidExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) | 10 | #define GuidExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) |
11 | #define GuidExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) | 11 | #define GuidExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) |
12 | #define GuidExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_GUIDUTIL, x, e, s, __VA_ARGS__) | ||
12 | #define GuidExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) | 13 | #define GuidExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_GUIDUTIL, x, s, __VA_ARGS__) |
13 | #define GuidExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_GUIDUTIL, p, x, e, s, __VA_ARGS__) | 14 | #define GuidExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_GUIDUTIL, p, x, e, s, __VA_ARGS__) |
14 | #define GuidExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_GUIDUTIL, p, x, s, __VA_ARGS__) | 15 | #define GuidExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_GUIDUTIL, p, x, s, __VA_ARGS__) |
@@ -29,8 +30,7 @@ extern "C" HRESULT DAPI GuidFixedCreate( | |||
29 | 30 | ||
30 | if (!::StringFromGUID2(guid, wzGuid, GUID_STRING_LENGTH)) | 31 | if (!::StringFromGUID2(guid, wzGuid, GUID_STRING_LENGTH)) |
31 | { | 32 | { |
32 | hr = E_OUTOFMEMORY; | 33 | GuidExitWithRootFailure(hr, E_OUTOFMEMORY, "Failed to convert guid into string."); |
33 | GuidExitOnRootFailure(hr, "Failed to convert guid into string."); | ||
34 | } | 34 | } |
35 | 35 | ||
36 | LExit: | 36 | LExit: |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h index 727318f2..875cfafb 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | |||
@@ -205,11 +205,12 @@ DAPI_(HRESULT) PathGetTempPath( | |||
205 | ); | 205 | ); |
206 | 206 | ||
207 | /******************************************************************* | 207 | /******************************************************************* |
208 | PathGetSystemTempPath - returns the path to the system temp folder | 208 | PathGetSystemTempPaths - returns the paths to system temp folders |
209 | that is backslash terminated. | 209 | that are backslash terminated with higher preference first. |
210 | *******************************************************************/ | 210 | *******************************************************************/ |
211 | DAPI_(HRESULT) PathGetSystemTempPath( | 211 | DAPI_(HRESULT) PathGetSystemTempPaths( |
212 | __out_z LPWSTR* psczSystemTempPath | 212 | __inout_z LPWSTR** prgsczSystemTempPaths, |
213 | __inout DWORD* pcSystemTempPaths | ||
213 | ); | 214 | ); |
214 | 215 | ||
215 | /******************************************************************* | 216 | /******************************************************************* |
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp index 1ac76626..dc33e656 100644 --- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp | |||
@@ -923,12 +923,14 @@ LExit: | |||
923 | } | 923 | } |
924 | 924 | ||
925 | 925 | ||
926 | DAPI_(HRESULT) PathGetSystemTempPath( | 926 | DAPI_(HRESULT) PathGetSystemTempPaths( |
927 | __out_z LPWSTR* psczSystemTempPath | 927 | __inout_z LPWSTR** prgsczSystemTempPaths, |
928 | __inout DWORD* pcSystemTempPaths | ||
928 | ) | 929 | ) |
929 | { | 930 | { |
930 | HRESULT hr = S_OK; | 931 | HRESULT hr = S_OK; |
931 | HKEY hKey = NULL; | 932 | HKEY hKey = NULL; |
933 | LPWSTR sczTemp = NULL; | ||
932 | WCHAR wzTempPath[MAX_PATH + 1] = { }; | 934 | WCHAR wzTempPath[MAX_PATH + 1] = { }; |
933 | DWORD cch = 0; | 935 | DWORD cch = 0; |
934 | 936 | ||
@@ -940,26 +942,36 @@ DAPI_(HRESULT) PathGetSystemTempPath( | |||
940 | 942 | ||
941 | // Follow documented precedence rules for TMP/TEMP from ::GetTempPath. | 943 | // Follow documented precedence rules for TMP/TEMP from ::GetTempPath. |
942 | // TODO: values will be expanded with the current environment variables instead of the system environment variables. | 944 | // TODO: values will be expanded with the current environment variables instead of the system environment variables. |
943 | hr = RegReadString(hKey, L"TMP", psczSystemTempPath); | 945 | hr = RegReadString(hKey, L"TMP", &sczTemp); |
944 | if (E_FILENOTFOUND != hr) | 946 | if (E_FILENOTFOUND != hr) |
945 | { | 947 | { |
946 | PathExitOnFailure(hr, "Failed to get system TMP value."); | 948 | PathExitOnFailure(hr, "Failed to get system TMP value."); |
947 | 949 | ||
948 | hr = PathBackslashTerminate(psczSystemTempPath); | 950 | hr = PathBackslashTerminate(&sczTemp); |
949 | PathExitOnFailure(hr, "Failed to backslash terminate system TMP value."); | 951 | PathExitOnFailure(hr, "Failed to backslash terminate system TMP value."); |
950 | 952 | ||
951 | ExitFunction(); | 953 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 3); |
954 | PathExitOnFailure(hr, "Failed to ensure array size for system TMP value."); | ||
955 | |||
956 | (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp; | ||
957 | sczTemp = NULL; | ||
958 | *pcSystemTempPaths += 1; | ||
952 | } | 959 | } |
953 | 960 | ||
954 | hr = RegReadString(hKey, L"TEMP", psczSystemTempPath); | 961 | hr = RegReadString(hKey, L"TEMP", &sczTemp); |
955 | if (E_FILENOTFOUND != hr) | 962 | if (E_FILENOTFOUND != hr) |
956 | { | 963 | { |
957 | PathExitOnFailure(hr, "Failed to get system TEMP value."); | 964 | PathExitOnFailure(hr, "Failed to get system TEMP value."); |
958 | 965 | ||
959 | hr = PathBackslashTerminate(psczSystemTempPath); | 966 | hr = PathBackslashTerminate(&sczTemp); |
960 | PathExitOnFailure(hr, "Failed to backslash terminate system TEMP value."); | 967 | PathExitOnFailure(hr, "Failed to backslash terminate system TEMP value."); |
961 | 968 | ||
962 | ExitFunction(); | 969 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 2); |
970 | PathExitOnFailure(hr, "Failed to ensure array size for system TEMP value."); | ||
971 | |||
972 | (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp; | ||
973 | sczTemp = NULL; | ||
974 | *pcSystemTempPaths += 1; | ||
963 | } | 975 | } |
964 | } | 976 | } |
965 | 977 | ||
@@ -973,11 +985,19 @@ DAPI_(HRESULT) PathGetSystemTempPath( | |||
973 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Windows directory path too long."); | 985 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Windows directory path too long."); |
974 | } | 986 | } |
975 | 987 | ||
976 | hr = PathConcat(wzTempPath, L"TEMP\\", psczSystemTempPath); | 988 | hr = PathConcat(wzTempPath, L"TEMP\\", &sczTemp); |
977 | PathExitOnFailure(hr, "Failed to concat Temp directory on Windows directory path."); | 989 | PathExitOnFailure(hr, "Failed to concat Temp directory on Windows directory path."); |
978 | 990 | ||
991 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 1); | ||
992 | PathExitOnFailure(hr, "Failed to ensure array size for Windows\\TEMP value."); | ||
993 | |||
994 | (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp; | ||
995 | sczTemp = NULL; | ||
996 | *pcSystemTempPaths += 1; | ||
997 | |||
979 | LExit: | 998 | LExit: |
980 | ReleaseRegKey(hKey); | 999 | ReleaseRegKey(hKey); |
1000 | ReleaseStr(sczTemp); | ||
981 | 1001 | ||
982 | return hr; | 1002 | return hr; |
983 | } | 1003 | } |
diff --git a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp index d1d304d3..e9ef1047 100644 --- a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp +++ b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | |||
@@ -800,6 +800,34 @@ namespace DutilTests | |||
800 | } | 800 | } |
801 | 801 | ||
802 | [Fact] | 802 | [Fact] |
803 | void PathGetSystemTempPathsTest() | ||
804 | { | ||
805 | HRESULT hr = S_OK; | ||
806 | LPWSTR* rgsczPaths = NULL; | ||
807 | DWORD cPaths = 0; | ||
808 | DWORD cPathsOriginal = 0; | ||
809 | |||
810 | try | ||
811 | { | ||
812 | hr = PathGetSystemTempPaths(&rgsczPaths, &cPaths); | ||
813 | NativeAssert::Succeeded(hr, "PathGetSystemTempPaths failed."); | ||
814 | |||
815 | Assert::InRange<DWORD>(cPaths, 1, 3); | ||
816 | WixAssert::StringEqual(Environment::ExpandEnvironmentVariables("%windir%\\temp\\"), gcnew String(rgsczPaths[cPaths - 1]), true); | ||
817 | |||
818 | cPathsOriginal = cPaths; | ||
819 | |||
820 | hr = PathGetSystemTempPaths(&rgsczPaths, &cPaths); | ||
821 | NativeAssert::Succeeded(hr, "PathGetSystemTempPaths failed."); | ||
822 | Assert::Equal(cPathsOriginal * 2, cPaths); | ||
823 | } | ||
824 | finally | ||
825 | { | ||
826 | ReleaseStrArray(rgsczPaths, cPaths); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | [Fact] | ||
803 | void PathNormalizeSlashesFixedTest() | 831 | void PathNormalizeSlashesFixedTest() |
804 | { | 832 | { |
805 | HRESULT hr = S_OK; | 833 | HRESULT hr = S_OK; |
diff --git a/src/test/burn/WixTestTools/BundleVerifier.cs b/src/test/burn/WixTestTools/BundleVerifier.cs index 594b19aa..103171cd 100644 --- a/src/test/burn/WixTestTools/BundleVerifier.cs +++ b/src/test/burn/WixTestTools/BundleVerifier.cs | |||
@@ -15,7 +15,8 @@ namespace WixTestTools | |||
15 | public partial class BundleInstaller | 15 | public partial class BundleInstaller |
16 | { | 16 | { |
17 | public const string DependencyRegistryRoot = "Software\\Classes\\Installer\\Dependencies"; | 17 | public const string DependencyRegistryRoot = "Software\\Classes\\Installer\\Dependencies"; |
18 | public const string FULL_BURN_POLICY_REGISTRY_PATH = "SOFTWARE\\WOW6432Node\\Policies\\WiX\\Burn"; | 18 | public const string FULL_BURN_POLICY_REGISTRY_PATH = "SOFTWARE\\Policies\\WiX\\Burn"; |
19 | public const string FULL_BURN_POLICY_REGISTRY_PATH_WOW6432NODE = "SOFTWARE\\WOW6432Node\\Policies\\WiX\\Burn"; | ||
19 | public const string PACKAGE_CACHE_FOLDER_NAME = "Package Cache"; | 20 | public const string PACKAGE_CACHE_FOLDER_NAME = "Package Cache"; |
20 | 21 | ||
21 | public string BundlePdb { get; } | 22 | public string BundlePdb { get; } |
@@ -35,12 +36,19 @@ namespace WixTestTools | |||
35 | return this.BundleSymbol; | 36 | return this.BundleSymbol; |
36 | } | 37 | } |
37 | 38 | ||
39 | public string GetFullBurnPolicyRegistryPath() | ||
40 | { | ||
41 | var bundleSymbol = this.GetBundleSymbol(); | ||
42 | var x64 = bundleSymbol.Platform != Platform.X86; | ||
43 | return x64 ? FULL_BURN_POLICY_REGISTRY_PATH : FULL_BURN_POLICY_REGISTRY_PATH_WOW6432NODE; | ||
44 | } | ||
45 | |||
38 | public string GetPackageCachePathForCacheId(string cacheId, bool perMachine) | 46 | public string GetPackageCachePathForCacheId(string cacheId, bool perMachine) |
39 | { | 47 | { |
40 | string cachePath; | 48 | string cachePath; |
41 | if (perMachine) | 49 | if (perMachine) |
42 | { | 50 | { |
43 | using var policyKey = Registry.LocalMachine.OpenSubKey(FULL_BURN_POLICY_REGISTRY_PATH); | 51 | using var policyKey = Registry.LocalMachine.OpenSubKey(this.GetFullBurnPolicyRegistryPath()); |
44 | var redirectedCachePath = policyKey?.GetValue("PackageCache") as string; | 52 | var redirectedCachePath = policyKey?.GetValue("PackageCache") as string; |
45 | cachePath = redirectedCachePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), PACKAGE_CACHE_FOLDER_NAME); | 53 | cachePath = redirectedCachePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), PACKAGE_CACHE_FOLDER_NAME); |
46 | } | 54 | } |
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs index 6c8250d9..f5a1cda8 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs | |||
@@ -5,6 +5,7 @@ namespace WixToolsetTest.BurnE2E | |||
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.IO; | 7 | using System.IO; |
8 | using Microsoft.Win32; | ||
8 | using WixBuildTools.TestSupport; | 9 | using WixBuildTools.TestSupport; |
9 | using WixTestTools; | 10 | using WixTestTools; |
10 | using WixToolset.Mba.Core; | 11 | using WixToolset.Mba.Core; |
@@ -201,5 +202,72 @@ namespace WixToolsetTest.BurnE2E | |||
201 | packageB.VerifyInstalled(true); | 202 | packageB.VerifyInstalled(true); |
202 | } | 203 | } |
203 | } | 204 | } |
205 | |||
206 | [RuntimeFact] | ||
207 | public void CanGetEngineWorkingDirectoryFromCommandLine() | ||
208 | { | ||
209 | var bundleA = this.CreateBundleInstaller("BundleA"); | ||
210 | var testBAController = this.CreateTestBAController(); | ||
211 | |||
212 | testBAController.SetImmediatelyQuit(); | ||
213 | |||
214 | using (var dfs = new DisposableFileSystem()) | ||
215 | { | ||
216 | var baseTempPath = dfs.GetFolder(true); | ||
217 | var logPath = bundleA.Install(0, $"-burn.engine.working.directory=\"{baseTempPath}\""); | ||
218 | LogVerifier.MessageInLogFileRegex(logPath, $"Burn x86 v4.*, Windows v.* \\(Build .*: Service Pack .*\\), path: {baseTempPath.Replace("\\", "\\\\")}\\\\.*\\\\.cr\\\\BundleA.exe"); | ||
219 | } | ||
220 | } | ||
221 | |||
222 | [RuntimeFact] | ||
223 | public void CanGetEngineWorkingDirectoryFromPolicy() | ||
224 | { | ||
225 | var deletePolicyKey = false; | ||
226 | string originalPolicyValue = null; | ||
227 | |||
228 | var bundleA = this.CreateBundleInstaller("BundleA"); | ||
229 | var testBAController = this.CreateTestBAController(); | ||
230 | var policyPath = bundleA.GetFullBurnPolicyRegistryPath(); | ||
231 | |||
232 | testBAController.SetImmediatelyQuit(); | ||
233 | |||
234 | try | ||
235 | { | ||
236 | using (var dfs = new DisposableFileSystem()) | ||
237 | { | ||
238 | var baseTempPath = dfs.GetFolder(true); | ||
239 | |||
240 | var policyKey = Registry.LocalMachine.OpenSubKey(policyPath, writable: true); | ||
241 | if (policyKey == null) | ||
242 | { | ||
243 | policyKey = Registry.LocalMachine.CreateSubKey(policyPath, writable: true); | ||
244 | deletePolicyKey = true; | ||
245 | } | ||
246 | |||
247 | using (policyKey) | ||
248 | { | ||
249 | originalPolicyValue = policyKey.GetValue("EngineWorkingDirectory") as string; | ||
250 | policyKey.SetValue("EngineWorkingDirectory", baseTempPath); | ||
251 | } | ||
252 | |||
253 | var logPath = bundleA.Install(); | ||
254 | LogVerifier.MessageInLogFileRegex(logPath, $"Burn x86 v4.*, Windows v.* \\(Build .*: Service Pack .*\\), path: {baseTempPath.Replace("\\", "\\\\")}\\\\.*\\\\.cr\\\\BundleA.exe"); | ||
255 | } | ||
256 | } | ||
257 | finally | ||
258 | { | ||
259 | if (deletePolicyKey) | ||
260 | { | ||
261 | Registry.LocalMachine.DeleteSubKeyTree(policyPath); | ||
262 | } | ||
263 | else if (originalPolicyValue != null) | ||
264 | { | ||
265 | using (var policyKey = Registry.LocalMachine.CreateSubKey(policyPath, writable: true)) | ||
266 | { | ||
267 | policyKey.SetValue("EngineWorkingDirectory", originalPolicyValue); | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | } | ||
204 | } | 272 | } |
205 | } | 273 | } |