aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-05-26 17:34:48 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-05-31 13:20:44 -0500
commit90982fbf1c887a3ed3454f9ab3ab8dfbd57a1383 (patch)
tree7d87b21f0879de446f5db7053d349f32b4882cbe /src
parenta070d8c7b57d6c9a54106abeb359a6c868b6d7ae (diff)
downloadwix-90982fbf1c887a3ed3454f9ab3ab8dfbd57a1383.tar.gz
wix-90982fbf1c887a3ed3454f9ab3ab8dfbd57a1383.tar.bz2
wix-90982fbf1c887a3ed3454f9ab3ab8dfbd57a1383.zip
Add PathConcatRelativeToBase and use it in Burn.
Fixes 6707
Diffstat (limited to 'src')
-rw-r--r--src/burn/engine/apply.cpp2
-rw-r--r--src/burn/engine/bundlepackageengine.cpp34
-rw-r--r--src/burn/engine/cache.cpp32
-rw-r--r--src/burn/engine/core.cpp2
-rw-r--r--src/burn/engine/exeengine.cpp28
-rw-r--r--src/burn/engine/msiengine.cpp4
-rw-r--r--src/burn/engine/mspengine.cpp2
-rw-r--r--src/burn/engine/msuengine.cpp2
-rw-r--r--src/burn/engine/payload.cpp2
-rw-r--r--src/burn/engine/registration.cpp6
-rw-r--r--src/ext/Bal/dnchost/dnchost.cpp2
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/pathutil.h11
-rw-r--r--src/libs/dutil/WixToolset.DUtil/path2utl.cpp40
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp107
14 files changed, 233 insertions, 41 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index 41cb6ad4..f9b33333 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -1371,7 +1371,7 @@ static HRESULT LayoutBundle(
1371 ExitOnFailure(hr, "Failed to get path to bundle to layout."); 1371 ExitOnFailure(hr, "Failed to get path to bundle to layout.");
1372 } 1372 }
1373 1373
1374 hr = PathConcat(pContext->wzLayoutDirectory, wzExecutableName, &sczDestinationPath); 1374 hr = PathConcatRelativeToBase(pContext->wzLayoutDirectory, wzExecutableName, &sczDestinationPath);
1375 ExitOnFailure(hr, "Failed to concat layout path for bundle."); 1375 ExitOnFailure(hr, "Failed to concat layout path for bundle.");
1376 1376
1377 // If the destination path is the currently running bundle, bail. 1377 // If the destination path is the currently running bundle, bail.
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index 00cf9454..97861436 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -23,6 +23,7 @@ static HRESULT ExecuteBundle(
23 __in BOOTSTRAPPER_ACTION_STATE action, 23 __in BOOTSTRAPPER_ACTION_STATE action,
24 __in BOOTSTRAPPER_RELATION_TYPE relationType, 24 __in BOOTSTRAPPER_RELATION_TYPE relationType,
25 __in BURN_PACKAGE* pPackage, 25 __in BURN_PACKAGE* pPackage,
26 __in BOOL fPseudoPackage,
26 __in_z_opt LPCWSTR wzParent, 27 __in_z_opt LPCWSTR wzParent,
27 __in_z_opt LPCWSTR wzIgnoreDependencies, 28 __in_z_opt LPCWSTR wzIgnoreDependencies,
28 __in_z_opt LPCWSTR wzAncestors, 29 __in_z_opt LPCWSTR wzAncestors,
@@ -614,7 +615,7 @@ extern "C" HRESULT BundlePackageEngineExecutePackage(
614 BOOTSTRAPPER_RELATION_TYPE relationType = BOOTSTRAPPER_RELATION_CHAIN_PACKAGE; 615 BOOTSTRAPPER_RELATION_TYPE relationType = BOOTSTRAPPER_RELATION_CHAIN_PACKAGE;
615 BURN_PACKAGE* pPackage = pExecuteAction->bundlePackage.pPackage; 616 BURN_PACKAGE* pPackage = pExecuteAction->bundlePackage.pPackage;
616 617
617 return ExecuteBundle(pCache, pVariables, fRollback, pfnGenericMessageHandler, pvContext, action, relationType, pPackage, wzParent, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart); 618 return ExecuteBundle(pCache, pVariables, fRollback, pfnGenericMessageHandler, pvContext, action, relationType, pPackage, FALSE, wzParent, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart);
618} 619}
619 620
620extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( 621extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
@@ -636,7 +637,7 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
636 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pRelatedBundle->planRelationType); 637 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType(pRelatedBundle->planRelationType);
637 BURN_PACKAGE* pPackage = &pRelatedBundle->package; 638 BURN_PACKAGE* pPackage = &pRelatedBundle->package;
638 639
639 return ExecuteBundle(pCache, pVariables, fRollback, pfnGenericMessageHandler, pvContext, action, relationType, pPackage, wzParent, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart); 640 return ExecuteBundle(pCache, pVariables, fRollback, pfnGenericMessageHandler, pvContext, action, relationType, pPackage, TRUE, wzParent, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart);
640} 641}
641 642
642extern "C" void BundlePackageEngineUpdateInstallRegistrationState( 643extern "C" void BundlePackageEngineUpdateInstallRegistrationState(
@@ -733,6 +734,7 @@ static HRESULT ExecuteBundle(
733 __in BOOTSTRAPPER_ACTION_STATE action, 734 __in BOOTSTRAPPER_ACTION_STATE action,
734 __in BOOTSTRAPPER_RELATION_TYPE relationType, 735 __in BOOTSTRAPPER_RELATION_TYPE relationType,
735 __in BURN_PACKAGE* pPackage, 736 __in BURN_PACKAGE* pPackage,
737 __in BOOL fPseudoPackage,
736 __in_z_opt LPCWSTR wzParent, 738 __in_z_opt LPCWSTR wzParent,
737 __in_z_opt LPCWSTR wzIgnoreDependencies, 739 __in_z_opt LPCWSTR wzIgnoreDependencies,
738 __in_z_opt LPCWSTR wzAncestors, 740 __in_z_opt LPCWSTR wzAncestors,
@@ -759,17 +761,33 @@ static HRESULT ExecuteBundle(
759 LPCWSTR wzOperationCommandLine = NULL; 761 LPCWSTR wzOperationCommandLine = NULL;
760 BOOL fRunEmbedded = pPackage->Bundle.fSupportsBurnProtocol; 762 BOOL fRunEmbedded = pPackage->Bundle.fSupportsBurnProtocol;
761 763
762 // get cached executable path 764 if (fPseudoPackage)
763 hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory); 765 {
764 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId); 766 if (!PathIsFullyQualified(pPackagePayload->sczFilePath, NULL))
767 {
768 ExitWithRootFailure(hr, E_INVALIDSTATE, "Related bundles must have a fully qualified target path.");
769 }
770
771 hr = StrAllocString(&sczExecutablePath, pPackagePayload->sczFilePath, 0);
772 ExitOnFailure(hr, "Failed to build executable path.");
773
774 hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory);
775 ExitOnFailure(hr, "Failed to get cached path for related bundle: %ls", pPackage->sczId);
776 }
777 else
778 {
779 // get cached executable path
780 hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
781 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
782
783 hr = PathConcatRelativeToBase(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
784 ExitOnFailure(hr, "Failed to build executable path.");
785 }
765 786
766 // Best effort to set the execute package cache folder and action variables. 787 // Best effort to set the execute package cache folder and action variables.
767 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 788 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
768 VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, action, TRUE); 789 VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, action, TRUE);
769 790
770 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
771 ExitOnFailure(hr, "Failed to build executable path.");
772
773 // pick arguments 791 // pick arguments
774 switch (action) 792 switch (action)
775 { 793 {
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index 2b7d6ede..04b2f0ca 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -251,7 +251,7 @@ extern "C" HRESULT CacheInitializeSources(
251 hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczId, &sczCompletedFolder); 251 hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczId, &sczCompletedFolder);
252 ExitOnFailure(hr, "Failed to get completed path for bundle."); 252 ExitOnFailure(hr, "Failed to get completed path for bundle.");
253 253
254 hr = PathConcat(sczCompletedFolder, pRegistration->sczExecutableName, &sczCompletedPath); 254 hr = PathConcatRelativeToBase(sczCompletedFolder, pRegistration->sczExecutableName, &sczCompletedPath);
255 ExitOnFailure(hr, "Failed to combine working path with engine file name."); 255 ExitOnFailure(hr, "Failed to combine working path with engine file name.");
256 256
257 hr = PathCompare(sczCurrentPath, sczCompletedPath, &nCompare); 257 hr = PathCompare(sczCurrentPath, sczCompletedPath, &nCompare);
@@ -390,7 +390,7 @@ extern "C" HRESULT CacheCalculateBundleLayoutWorkingPath(
390 390
391 HRESULT hr = S_OK; 391 HRESULT hr = S_OK;
392 392
393 hr = PathConcat(pCache->sczAcquisitionFolder, wzBundleId, psczWorkingPath); 393 hr = PathConcatRelativeToBase(pCache->sczAcquisitionFolder, wzBundleId, psczWorkingPath);
394 ExitOnFailure(hr, "Failed to append bundle id for bundle layout working path."); 394 ExitOnFailure(hr, "Failed to append bundle id for bundle layout working path.");
395 395
396LExit: 396LExit:
@@ -407,7 +407,7 @@ extern "C" HRESULT CacheCalculatePayloadWorkingPath(
407 407
408 HRESULT hr = S_OK; 408 HRESULT hr = S_OK;
409 409
410 hr = PathConcat(pCache->sczAcquisitionFolder, pPayload->sczKey, psczWorkingPath); 410 hr = PathConcatRelativeToBase(pCache->sczAcquisitionFolder, pPayload->sczKey, psczWorkingPath);
411 ExitOnFailure(hr, "Failed to append Id as payload unverified path."); 411 ExitOnFailure(hr, "Failed to append Id as payload unverified path.");
412 412
413LExit: 413LExit:
@@ -424,7 +424,7 @@ extern "C" HRESULT CacheCalculateContainerWorkingPath(
424 424
425 HRESULT hr = S_OK; 425 HRESULT hr = S_OK;
426 426
427 hr = PathConcat(pCache->sczAcquisitionFolder, pContainer->sczHash, psczWorkingPath); 427 hr = PathConcatRelativeToBase(pCache->sczAcquisitionFolder, pContainer->sczHash, psczWorkingPath);
428 ExitOnFailure(hr, "Failed to append hash as container unverified path."); 428 ExitOnFailure(hr, "Failed to append hash as container unverified path.");
429 429
430LExit: 430LExit:
@@ -479,7 +479,7 @@ extern "C" HRESULT CacheGetCompletedPath(
479 // GetRootPath returns S_FALSE if the package cache is redirected elsewhere. 479 // GetRootPath returns S_FALSE if the package cache is redirected elsewhere.
480 fRedirected = S_FALSE == hr; 480 fRedirected = S_FALSE == hr;
481 481
482 hr = PathConcat(sczRootPath, wzCacheId, &sczCurrentCompletedPath); 482 hr = PathConcatRelativeToBase(sczRootPath, wzCacheId, &sczCurrentCompletedPath);
483 ExitOnFailure(hr, "Failed to construct cache path."); 483 ExitOnFailure(hr, "Failed to construct cache path.");
484 484
485 hr = PathBackslashTerminate(&sczCurrentCompletedPath); 485 hr = PathBackslashTerminate(&sczCurrentCompletedPath);
@@ -492,7 +492,7 @@ extern "C" HRESULT CacheGetCompletedPath(
492 hr = GetRootPath(pCache, fPerMachine, FALSE, &sczRootPath); 492 hr = GetRootPath(pCache, fPerMachine, FALSE, &sczRootPath);
493 ExitOnFailure(hr, "Failed to get old %hs package cache root directory.", fPerMachine ? "per-machine" : "per-user"); 493 ExitOnFailure(hr, "Failed to get old %hs package cache root directory.", fPerMachine ? "per-machine" : "per-user");
494 494
495 hr = PathConcat(sczRootPath, wzCacheId, &sczDefaultCompletedPath); 495 hr = PathConcatRelativeToBase(sczRootPath, wzCacheId, &sczDefaultCompletedPath);
496 ExitOnFailure(hr, "Failed to construct cache path."); 496 ExitOnFailure(hr, "Failed to construct cache path.");
497 497
498 hr = PathBackslashTerminate(&sczDefaultCompletedPath); 498 hr = PathBackslashTerminate(&sczDefaultCompletedPath);
@@ -933,7 +933,7 @@ extern "C" HRESULT CacheLayoutBundle(
933 HRESULT hr = S_OK; 933 HRESULT hr = S_OK;
934 LPWSTR sczTargetPath = NULL; 934 LPWSTR sczTargetPath = NULL;
935 935
936 hr = PathConcat(wzLayoutDirectory, wzExecutableName, &sczTargetPath); 936 hr = PathConcatRelativeToBase(wzLayoutDirectory, wzExecutableName, &sczTargetPath);
937 ExitOnFailure(hr, "Failed to combine completed path with engine file name for layout."); 937 ExitOnFailure(hr, "Failed to combine completed path with engine file name for layout.");
938 938
939 LogStringLine(REPORT_STANDARD, "Layout bundle from: '%ls' to: '%ls'", wzSourceBundlePath, sczTargetPath); 939 LogStringLine(REPORT_STANDARD, "Layout bundle from: '%ls' to: '%ls'", wzSourceBundlePath, sczTargetPath);
@@ -968,7 +968,7 @@ extern "C" HRESULT CacheCompleteBundle(
968 hr = CreateCompletedPath(pCache, fPerMachine, wzBundleId, NULL, &sczTargetDirectory); 968 hr = CreateCompletedPath(pCache, fPerMachine, wzBundleId, NULL, &sczTargetDirectory);
969 ExitOnFailure(hr, "Failed to create completed cache path for bundle."); 969 ExitOnFailure(hr, "Failed to create completed cache path for bundle.");
970 970
971 hr = PathConcat(sczTargetDirectory, wzExecutableName, &sczTargetPath); 971 hr = PathConcatRelativeToBase(sczTargetDirectory, wzExecutableName, &sczTargetPath);
972 ExitOnFailure(hr, "Failed to combine completed path with engine file name."); 972 ExitOnFailure(hr, "Failed to combine completed path with engine file name.");
973 973
974 // We can't just use wzExecutablePath because we needed to call CreateCompletedPath to ensure that the destination was secured. 974 // We can't just use wzExecutablePath because we needed to call CreateCompletedPath to ensure that the destination was secured.
@@ -1021,7 +1021,7 @@ extern "C" HRESULT CacheLayoutContainer(
1021 HRESULT hr = S_OK; 1021 HRESULT hr = S_OK;
1022 LPWSTR sczCachedPath = NULL; 1022 LPWSTR sczCachedPath = NULL;
1023 1023
1024 hr = PathConcat(wzLayoutDirectory, pContainer->sczFilePath, &sczCachedPath); 1024 hr = PathConcatRelativeToBase(wzLayoutDirectory, pContainer->sczFilePath, &sczCachedPath);
1025 ExitOnFailure(hr, "Failed to concat complete cached path."); 1025 ExitOnFailure(hr, "Failed to concat complete cached path.");
1026 1026
1027 hr = VerifyThenTransferContainer(pContainer, sczCachedPath, wzUnverifiedContainerPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext); 1027 hr = VerifyThenTransferContainer(pContainer, sczCachedPath, wzUnverifiedContainerPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext);
@@ -1046,7 +1046,7 @@ extern "C" HRESULT CacheLayoutPayload(
1046 HRESULT hr = S_OK; 1046 HRESULT hr = S_OK;
1047 LPWSTR sczCachedPath = NULL; 1047 LPWSTR sczCachedPath = NULL;
1048 1048
1049 hr = PathConcat(wzLayoutDirectory, pPayload->sczFilePath, &sczCachedPath); 1049 hr = PathConcatRelativeToBase(wzLayoutDirectory, pPayload->sczFilePath, &sczCachedPath);
1050 ExitOnFailure(hr, "Failed to concat complete cached path."); 1050 ExitOnFailure(hr, "Failed to concat complete cached path.");
1051 1051
1052 hr = VerifyThenTransferPayload(pPayload, sczCachedPath, wzUnverifiedPayloadPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext); 1052 hr = VerifyThenTransferPayload(pPayload, sczCachedPath, wzUnverifiedPayloadPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext);
@@ -1141,7 +1141,7 @@ extern "C" HRESULT CacheVerifyContainer(
1141 HRESULT hr = S_OK; 1141 HRESULT hr = S_OK;
1142 LPWSTR sczCachedPath = NULL; 1142 LPWSTR sczCachedPath = NULL;
1143 1143
1144 hr = PathConcat(wzCachedDirectory, pContainer->sczFilePath, &sczCachedPath); 1144 hr = PathConcatRelativeToBase(wzCachedDirectory, pContainer->sczFilePath, &sczCachedPath);
1145 ExitOnFailure(hr, "Failed to concat complete cached path."); 1145 ExitOnFailure(hr, "Failed to concat complete cached path.");
1146 1146
1147 hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext); 1147 hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext);
@@ -1163,7 +1163,7 @@ extern "C" HRESULT CacheVerifyPayload(
1163 HRESULT hr = S_OK; 1163 HRESULT hr = S_OK;
1164 LPWSTR sczCachedPath = NULL; 1164 LPWSTR sczCachedPath = NULL;
1165 1165
1166 hr = PathConcat(wzCachedDirectory, pPayload->sczFilePath, &sczCachedPath); 1166 hr = PathConcatRelativeToBase(wzCachedDirectory, pPayload->sczFilePath, &sczCachedPath);
1167 ExitOnFailure(hr, "Failed to concat complete cached path."); 1167 ExitOnFailure(hr, "Failed to concat complete cached path.");
1168 1168
1169 hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext); 1169 hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext);
@@ -1596,7 +1596,7 @@ static HRESULT CreateCompletedPath(
1596 else 1596 else
1597 { 1597 {
1598 // Get the cache completed file path. 1598 // Get the cache completed file path.
1599 hr = PathConcat(sczCacheDirectory, wzFilePath, &sczCacheFile); 1599 hr = PathConcatRelativeToBase(sczCacheDirectory, wzFilePath, &sczCacheFile);
1600 ExitOnFailure(hr, "Failed to construct cache file."); 1600 ExitOnFailure(hr, "Failed to construct cache file.");
1601 1601
1602 // Don't reset permissions here. The payload's package must reset its cache folder when it starts caching. 1602 // Don't reset permissions here. The payload's package must reset its cache folder when it starts caching.
@@ -1634,7 +1634,7 @@ static HRESULT CreateUnverifiedPath(
1634 pCache->fUnverifiedCacheFolderCreated = TRUE; 1634 pCache->fUnverifiedCacheFolderCreated = TRUE;
1635 } 1635 }
1636 1636
1637 hr = PathConcat(sczUnverifiedCacheFolder, wzPayloadId, psczUnverifiedPayloadPath); 1637 hr = PathConcatRelativeToBase(sczUnverifiedCacheFolder, wzPayloadId, psczUnverifiedPayloadPath);
1638 ExitOnFailure(hr, "Failed to concat payload id to unverified folder path."); 1638 ExitOnFailure(hr, "Failed to concat payload id to unverified folder path.");
1639 1639
1640LExit: 1640LExit:
@@ -2055,13 +2055,13 @@ static HRESULT CopyEngineToWorkingFolder(
2055 hr = CacheEnsureBaseWorkingFolder(pCache, &sczWorkingFolder); 2055 hr = CacheEnsureBaseWorkingFolder(pCache, &sczWorkingFolder);
2056 ExitOnFailure(hr, "Failed to create working path to copy engine."); 2056 ExitOnFailure(hr, "Failed to create working path to copy engine.");
2057 2057
2058 hr = PathConcat(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory); 2058 hr = PathConcatRelativeToBase(sczWorkingFolder, wzWorkingFolderName, &sczTargetDirectory);
2059 ExitOnFailure(hr, "Failed to calculate the bundle working folder target name."); 2059 ExitOnFailure(hr, "Failed to calculate the bundle working folder target name.");
2060 2060
2061 hr = DirEnsureExists(sczTargetDirectory, NULL); 2061 hr = DirEnsureExists(sczTargetDirectory, NULL);
2062 ExitOnFailure(hr, "Failed create bundle working folder."); 2062 ExitOnFailure(hr, "Failed create bundle working folder.");
2063 2063
2064 hr = PathConcat(sczTargetDirectory, wzExecutableName, &sczTargetPath); 2064 hr = PathConcatRelativeToBase(sczTargetDirectory, wzExecutableName, &sczTargetPath);
2065 ExitOnFailure(hr, "Failed to combine working path with engine file name."); 2065 ExitOnFailure(hr, "Failed to combine working path with engine file name.");
2066 2066
2067 // Copy the engine without any attached containers to the working path. 2067 // Copy the engine without any attached containers to the working path.
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 19b739f9..4255fa6b 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -2217,7 +2217,7 @@ static HRESULT DetectPackagePayloadsCached(
2217 { 2217 {
2218 BURN_PAYLOAD* pPayload = pPackage->payloads.rgItems[i].pPayload; 2218 BURN_PAYLOAD* pPayload = pPackage->payloads.rgItems[i].pPayload;
2219 2219
2220 hr = PathConcat(sczCachePath, pPayload->sczFilePath, &sczPayloadCachePath); 2220 hr = PathConcatRelativeToBase(sczCachePath, pPayload->sczFilePath, &sczPayloadCachePath);
2221 ExitOnFailure(hr, "Failed to concat payload cache path."); 2221 ExitOnFailure(hr, "Failed to concat payload cache path.");
2222 2222
2223 if (FileExistsEx(sczPayloadCachePath, NULL)) 2223 if (FileExistsEx(sczPayloadCachePath, NULL))
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index a287d171..c3757e92 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -361,17 +361,33 @@ extern "C" HRESULT ExeEngineExecutePackage(
361 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; 361 BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage;
362 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; 362 BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
363 363
364 // get cached executable path 364 if (pPackage->Exe.fPseudoPackage && BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE != pPackagePayload->verification)
365 hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory); 365 {
366 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId); 366 if (!PathIsFullyQualified(pPackagePayload->sczFilePath, NULL))
367 {
368 ExitWithRootFailure(hr, E_INVALIDSTATE, "Pseudo ExePackages must have a fully qualified target path.");
369 }
370
371 hr = StrAllocString(&sczExecutablePath, pPackagePayload->sczFilePath, 0);
372 ExitOnFailure(hr, "Failed to build executable path.");
373
374 hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory);
375 ExitOnFailure(hr, "Failed to get cached path for pseudo-package: %ls", pPackage->sczId);
376 }
377 else
378 {
379 // get cached executable path
380 hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
381 ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
382
383 hr = PathConcatRelativeToBase(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
384 ExitOnFailure(hr, "Failed to build executable path.");
385 }
367 386
368 // Best effort to set the execute package cache folder and action variables. 387 // Best effort to set the execute package cache folder and action variables.
369 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 388 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
370 VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, pExecuteAction->exePackage.action, TRUE); 389 VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, pExecuteAction->exePackage.action, TRUE);
371 390
372 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
373 ExitOnFailure(hr, "Failed to build executable path.");
374
375 // pick arguments 391 // pick arguments
376 switch (pExecuteAction->exePackage.action) 392 switch (pExecuteAction->exePackage.action)
377 { 393 {
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index d892b2bc..bfd5710f 100644
--- a/src/burn/engine/msiengine.cpp
+++ b/src/burn/engine/msiengine.cpp
@@ -1236,7 +1236,7 @@ extern "C" HRESULT MsiEngineExecutePackage(
1236 // Best effort to set the execute package cache folder variable. 1236 // Best effort to set the execute package cache folder variable.
1237 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 1237 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
1238 1238
1239 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczMsiPath); 1239 hr = PathConcatRelativeToBase(sczCachedDirectory, pPackagePayload->sczFilePath, &sczMsiPath);
1240 ExitOnFailure(hr, "Failed to build MSI path."); 1240 ExitOnFailure(hr, "Failed to build MSI path.");
1241 } 1241 }
1242 1242
@@ -2195,7 +2195,7 @@ static HRESULT ConcatPatchProperty(
2195 hr = CacheGetCompletedPath(pCache, pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory); 2195 hr = CacheGetCompletedPath(pCache, pMspPackage->fPerMachine, pMspPackage->sczCacheId, &sczCachedDirectory);
2196 ExitOnFailure(hr, "Failed to get cached path for MSP package: %ls", pMspPackage->sczId); 2196 ExitOnFailure(hr, "Failed to get cached path for MSP package: %ls", pMspPackage->sczId);
2197 2197
2198 hr = PathConcat(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath); 2198 hr = PathConcatRelativeToBase(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath);
2199 ExitOnFailure(hr, "Failed to build MSP path."); 2199 ExitOnFailure(hr, "Failed to build MSP path.");
2200 2200
2201 if (!sczPatches) 2201 if (!sczPatches)
diff --git a/src/burn/engine/mspengine.cpp b/src/burn/engine/mspengine.cpp
index 7403e78c..02e2afe4 100644
--- a/src/burn/engine/mspengine.cpp
+++ b/src/burn/engine/mspengine.cpp
@@ -613,7 +613,7 @@ extern "C" HRESULT MspEngineExecutePackage(
613 // Best effort to set the execute package cache folder variable. 613 // Best effort to set the execute package cache folder variable.
614 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 614 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
615 615
616 hr = PathConcat(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath); 616 hr = PathConcatRelativeToBase(sczCachedDirectory, pMspPackagePayload->sczFilePath, &sczMspPath);
617 ExitOnFailure(hr, "Failed to build MSP path."); 617 ExitOnFailure(hr, "Failed to build MSP path.");
618 618
619 wzAppend = sczMspPath; 619 wzAppend = sczMspPath;
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp
index de8e8c38..d78943ac 100644
--- a/src/burn/engine/msuengine.cpp
+++ b/src/burn/engine/msuengine.cpp
@@ -320,7 +320,7 @@ extern "C" HRESULT MsuEngineExecutePackage(
320 // Best effort to set the execute package cache folder variable. 320 // Best effort to set the execute package cache folder variable.
321 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); 321 VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
322 322
323 hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczMsuPath); 323 hr = PathConcatRelativeToBase(sczCachedDirectory, pPackagePayload->sczFilePath, &sczMsuPath);
324 ExitOnFailure(hr, "Failed to build MSU path."); 324 ExitOnFailure(hr, "Failed to build MSU path.");
325 325
326 // format command 326 // format command
diff --git a/src/burn/engine/payload.cpp b/src/burn/engine/payload.cpp
index 6acfcd73..f57f1310 100644
--- a/src/burn/engine/payload.cpp
+++ b/src/burn/engine/payload.cpp
@@ -294,7 +294,7 @@ extern "C" HRESULT PayloadExtractUXContainer(
294 ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName); 294 ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName);
295 295
296 // make file path 296 // make file path
297 hr = PathConcat(wzTargetDir, pPayload->sczFilePath, &pPayload->sczLocalFilePath); 297 hr = PathConcatRelativeToBase(wzTargetDir, pPayload->sczFilePath, &pPayload->sczLocalFilePath);
298 ExitOnFailure(hr, "Failed to concat file paths."); 298 ExitOnFailure(hr, "Failed to concat file paths.");
299 299
300 // extract file 300 // extract file
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index e83e0811..2b3dc4d4 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -1149,7 +1149,7 @@ static HRESULT SetPaths(
1149 ExitOnFailure(hr, "Failed to build cache directory."); 1149 ExitOnFailure(hr, "Failed to build cache directory.");
1150 1150
1151 // build cached executable path 1151 // build cached executable path
1152 hr = PathConcat(sczCacheDirectory, pRegistration->sczExecutableName, &pRegistration->sczCacheExecutablePath); 1152 hr = PathConcatRelativeToBase(sczCacheDirectory, pRegistration->sczExecutableName, &pRegistration->sczCacheExecutablePath);
1153 ExitOnFailure(hr, "Failed to build cached executable path."); 1153 ExitOnFailure(hr, "Failed to build cached executable path.");
1154 1154
1155 // build state file path 1155 // build state file path
@@ -1367,7 +1367,7 @@ static HRESULT WriteSoftwareTags(
1367 hr = PathConcat(sczRootFolder, SWIDTAG_FOLDER, &sczTagFolder); 1367 hr = PathConcat(sczRootFolder, SWIDTAG_FOLDER, &sczTagFolder);
1368 ExitOnFailure(hr, "Failed to allocate regid folder path."); 1368 ExitOnFailure(hr, "Failed to allocate regid folder path.");
1369 1369
1370 hr = PathConcat(sczTagFolder, pSoftwareTag->sczFilename, &sczPath); 1370 hr = PathConcatRelativeToBase(sczTagFolder, pSoftwareTag->sczFilename, &sczPath);
1371 ExitOnFailure(hr, "Failed to allocate regid file path."); 1371 ExitOnFailure(hr, "Failed to allocate regid file path.");
1372 1372
1373 hr = DirEnsureExists(sczTagFolder, NULL); 1373 hr = DirEnsureExists(sczTagFolder, NULL);
@@ -1405,7 +1405,7 @@ static HRESULT RemoveSoftwareTags(
1405 hr = PathConcat(sczRootFolder, SWIDTAG_FOLDER, &sczTagFolder); 1405 hr = PathConcat(sczRootFolder, SWIDTAG_FOLDER, &sczTagFolder);
1406 ExitOnFailure(hr, "Failed to allocate regid folder path."); 1406 ExitOnFailure(hr, "Failed to allocate regid folder path.");
1407 1407
1408 hr = PathConcat(sczTagFolder, pSoftwareTag->sczFilename, &sczPath); 1408 hr = PathConcatRelativeToBase(sczTagFolder, pSoftwareTag->sczFilename, &sczPath);
1409 ExitOnFailure(hr, "Failed to allocate regid file path."); 1409 ExitOnFailure(hr, "Failed to allocate regid file path.");
1410 1410
1411 // Best effort to delete the software tag file and the regid folder. 1411 // Best effort to delete the software tag file and the regid folder.
diff --git a/src/ext/Bal/dnchost/dnchost.cpp b/src/ext/Bal/dnchost/dnchost.cpp
index 36970f83..cdf204fb 100644
--- a/src/ext/Bal/dnchost/dnchost.cpp
+++ b/src/ext/Bal/dnchost/dnchost.cpp
@@ -199,7 +199,7 @@ static HRESULT LoadDncConfiguration(
199 hr = XmlGetAttributeEx(pixnHost, L"FilePath", &sczPayloadName); 199 hr = XmlGetAttributeEx(pixnHost, L"FilePath", &sczPayloadName);
200 BalExitOnRequiredXmlQueryFailure(hr, "Failed to get WixBalBAFactoryAssembly/@FilePath."); 200 BalExitOnRequiredXmlQueryFailure(hr, "Failed to get WixBalBAFactoryAssembly/@FilePath.");
201 201
202 hr = PathConcat(pArgs->pCommand->wzBootstrapperWorkingFolder, sczPayloadName, &pState->sczBaFactoryAssemblyPath); 202 hr = PathConcatRelativeToBase(pArgs->pCommand->wzBootstrapperWorkingFolder, sczPayloadName, &pState->sczBaFactoryAssemblyPath);
203 BalExitOnFailure(hr, "Failed to create BaFactoryAssemblyPath."); 203 BalExitOnFailure(hr, "Failed to create BaFactoryAssemblyPath.");
204 204
205 LPCWSTR wzFileName = PathFile(pState->sczBaFactoryAssemblyPath); 205 LPCWSTR wzFileName = PathFile(pState->sczBaFactoryAssemblyPath);
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
index fc6bb3bb..941793f8 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
@@ -237,6 +237,17 @@ DAPI_(HRESULT) PathConcatCch(
237 ); 237 );
238 238
239/******************************************************************* 239/*******************************************************************
240 PathConcatRelativeToBase - canonicalizes a relative path before
241 concatenating it to the base path to ensure the resulting path
242 is inside the base path.
243*******************************************************************/
244DAPI_(HRESULT) PathConcatRelativeToBase(
245 __in LPCWSTR wzBase,
246 __in_opt LPCWSTR wzRelative,
247 __deref_out_z LPWSTR* psczCombined
248 );
249
250/*******************************************************************
240 PathCompare - compares the fully expanded path of the two paths using 251 PathCompare - compares the fully expanded path of the two paths using
241 ::CompareStringW(). 252 ::CompareStringW().
242*******************************************************************/ 253*******************************************************************/
diff --git a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
index 45157d0b..61c1803a 100644
--- a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
@@ -131,6 +131,46 @@ LExit:
131 return hr; 131 return hr;
132} 132}
133 133
134DAPI_(HRESULT) PathConcatRelativeToBase(
135 __in LPCWSTR wzBase,
136 __in_opt LPCWSTR wzRelative,
137 __deref_out_z LPWSTR* psczCombined
138 )
139{
140 HRESULT hr = S_OK;
141 LPWSTR sczCanonicalizedRelative = NULL;
142
143 if (!wzBase || !*wzBase)
144 {
145 PathExitWithRootFailure(hr, E_INVALIDARG, "wzBase is required.");
146 }
147
148 if (PathIsRooted(wzRelative))
149 {
150 PathExitWithRootFailure(hr, E_INVALIDARG, "wzRelative cannot be rooted.");
151 }
152
153 hr = StrAllocString(psczCombined, wzBase, 0);
154 PathExitOnFailure(hr, "Failed to copy base to output.");
155
156 if (wzRelative && *wzRelative)
157 {
158 hr = PathBackslashTerminate(psczCombined);
159 PathExitOnFailure(hr, "Failed to backslashify.");
160
161 hr = PathCanonicalizeForComparison(wzRelative, 0, &sczCanonicalizedRelative);
162 PathExitOnFailure(hr, "Failed to canonicalize wzRelative.");
163
164 hr = StrAllocConcat(psczCombined, sczCanonicalizedRelative, 0);
165 PathExitOnFailure(hr, "Failed to append relative to output.");
166 }
167
168LExit:
169 ReleaseStr(sczCanonicalizedRelative);
170
171 return hr;
172}
173
134DAPI_(HRESULT) PathDirectoryContainsPath( 174DAPI_(HRESULT) PathDirectoryContainsPath(
135 __in_z LPCWSTR wzDirectory, 175 __in_z LPCWSTR wzDirectory,
136 __in_z LPCWSTR wzPath 176 __in_z LPCWSTR wzPath
diff --git a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
index 04d0b447..52698b98 100644
--- a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
+++ b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp
@@ -221,6 +221,113 @@ namespace DutilTests
221 } 221 }
222 222
223 [Fact] 223 [Fact]
224 void PathConcatTest()
225 {
226 HRESULT hr = S_OK;
227 LPWSTR sczPath = NULL;
228 LPCWSTR rgwzPaths[54] =
229 {
230 L"a", NULL, L"a",
231 L"a", L"", L"a",
232 L"C:\\", L"a", L"C:\\a",
233 L"\\a", L"b", L"\\a\\b",
234 L"a", L"b", L"a\\b",
235 L"C:\\", L"..\\a", L"C:\\..\\a",
236 L"C:\\a", L"..\\b", L"C:\\a\\..\\b",
237 L"\\\\server\\share", L"..\\a", L"\\\\server\\share\\..\\a",
238 L"\\\\server\\share\\a", L"..\\b", L"\\\\server\\share\\a\\..\\b",
239 NULL, L"b", L"b",
240 L"", L"b", L"b",
241 L"a", L"\\b", L"\\b",
242 L"a", L"b:", L"b:",
243 L"a", L"b:\\", L"b:\\",
244 L"a", L"\\\\?\\b", L"\\\\?\\b",
245 L"a", L"\\\\?\\UNC\\b", L"\\\\?\\UNC\\b",
246 L"a", L"\\b", L"\\b",
247 L"a", L"\\\\", L"\\\\",
248 };
249
250 try
251 {
252 for (DWORD i = 0; i < countof(rgwzPaths); i += 3)
253 {
254 hr = PathConcat(rgwzPaths[i], rgwzPaths[i + 1], &sczPath);
255 NativeAssert::Succeeded(hr, "PathConcat: {0}, {1}", rgwzPaths[i], rgwzPaths[i + 1]);
256 NativeAssert::StringEqual(rgwzPaths[i + 2], sczPath);
257 }
258 }
259 finally
260 {
261 ReleaseStr(sczPath);
262 }
263 }
264
265 [Fact]
266 void PathConcatRelativeToBaseTest()
267 {
268 HRESULT hr = S_OK;
269 LPWSTR sczPath = NULL;
270 LPCWSTR rgwzPaths[27] =
271 {
272 L"a", NULL, L"a",
273 L"a", L"", L"a",
274 L"C:\\", L"a", L"C:\\a",
275 L"\\a", L"b", L"\\a\\b",
276 L"a", L"b", L"a\\b",
277 L"C:\\", L"..\\a", L"C:\\a",
278 L"C:\\a", L"..\\b", L"C:\\a\\b",
279 L"\\\\server\\share", L"..\\a", L"\\\\server\\share\\a",
280 L"\\\\server\\share\\a", L"..\\b", L"\\\\server\\share\\a\\b",
281 };
282
283 try
284 {
285 for (DWORD i = 0; i < countof(rgwzPaths); i += 3)
286 {
287 hr = PathConcatRelativeToBase(rgwzPaths[i], rgwzPaths[i + 1], &sczPath);
288 NativeAssert::Succeeded(hr, "PathConcatRelativeToBase: {0}, {1}", rgwzPaths[i], rgwzPaths[i + 1]);
289 NativeAssert::StringEqual(rgwzPaths[i + 2], sczPath);
290 }
291 }
292 finally
293 {
294 ReleaseStr(sczPath);
295 }
296 }
297
298 [Fact]
299 void PathConcatRelativeToBaseFailureTest()
300 {
301 HRESULT hr = S_OK;
302 LPWSTR sczPath = NULL;
303 LPCWSTR rgwzPaths[18] =
304 {
305 NULL, L"b",
306 L"", L"b",
307 L"a", L"\\b",
308 L"a", L"b:",
309 L"a", L"b:\\",
310 L"a", L"\\\\?\\b",
311 L"a", L"\\\\?\\UNC\\b",
312 L"a", L"\\b",
313 L"a", L"\\\\",
314 };
315
316 try
317 {
318 for (DWORD i = 0; i < countof(rgwzPaths); i += 2)
319 {
320 hr = PathConcatRelativeToBase(rgwzPaths[i], rgwzPaths[i + 1], &sczPath);
321 NativeAssert::SpecificReturnCode(hr, E_INVALIDARG, "PathConcatRelativeToBase: {0}, {1}", rgwzPaths[i], rgwzPaths[i + 1]);
322 }
323 }
324 finally
325 {
326 ReleaseStr(sczPath);
327 }
328 }
329
330 [Fact]
224 void PathDirectoryContainsPathTest() 331 void PathDirectoryContainsPathTest()
225 { 332 {
226 HRESULT hr = S_OK; 333 HRESULT hr = S_OK;