@joebigelow / wix / commits / 681da11c

Add ability to disable file system redirection for File/DirectorySearch

Fixes 5476

Sean Hall committed Apr 27, 2022 at 16:54 UTC 681da11cfc9a266304b47b88843cb8a365015c63
8 files changed +179 -13
src/api/wix/WixToolset.Data/Symbols/WixFileSearchSymbol.cs
+17
@@ -54,6 +54,7 @@ namespace WixToolset.Data.Symbols
54 MaxSizeInclusive = 0x010,
55 MinDateInclusive = 0x020,
56 MaxDateInclusive = 0x040,
57 + DisableFileRedirection = 0x080,
58 }
59
60 public enum WixFileSearchType
@@ -246,5 +247,21 @@ namespace WixToolset.Data.Symbols
247 }
248 }
249 }
250 +
251 + public bool DisableFileRedirection
252 + {
253 + get { return this.Attributes.HasFlag(WixFileSearchAttributes.DisableFileRedirection); }
254 + set
255 + {
256 + if (value)
257 + {
258 + this.Attributes |= WixFileSearchAttributes.DisableFileRedirection;
259 + }
260 + else
261 + {
262 + this.Attributes &= ~WixFileSearchAttributes.DisableFileRedirection;
263 + }
264 + }
265 + }
266 }
267 }
src/burn/engine/search.cpp
+113 -1
@@ -139,6 +139,10 @@ extern "C" HRESULT SearchesParseFromXml(
139 hr = XmlGetAttributeEx(pixnNode, L"Path", &pSearch->FileSearch.sczPath);
140 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Path.");
141
142 + // @DisableFileRedirection
143 + hr = XmlGetYesNoAttribute(pixnNode, L"DisableFileRedirection", &pSearch->FileSearch.fDisableFileRedirection);
144 + ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get DisableFileRedirection attribute.");
145 +
146 // @Type
147 hr = XmlGetAttributeEx(pixnNode, L"Type", &scz);
148 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
@@ -557,6 +561,49 @@ extern "C" void SearchesUninitialize(
561
562 // internal function definitions
563
564 +#if !defined(_WIN64)
565 +
566 +typedef struct _BURN_FILE_SEARCH
567 +{
568 + BURN_SEARCH* pSearch;
569 + PROC_FILESYSTEMREDIRECTION pfsr;
570 +} BURN_FILE_SEARCH;
571 +
572 +static HRESULT FileSystemSearchStart(
573 + __in BURN_FILE_SEARCH* pFileSearch
574 + )
575 +{
576 + HRESULT hr = S_OK;
577 +
578 + if (pFileSearch->pSearch->FileSearch.fDisableFileRedirection)
579 + {
580 + hr = ProcDisableWowFileSystemRedirection(&pFileSearch->pfsr);
581 + if (hr == E_NOTIMPL)
582 + {
583 + hr = S_FALSE;
584 + }
585 + ExitOnFailure(hr, "Failed to disable file system redirection.");
586 + }
587 +
588 +LExit:
589 + return hr;
590 +}
591 +
592 +static void FileSystemSearchEnd(
593 + __in BURN_FILE_SEARCH* pFileSearch
594 + )
595 +{
596 + HRESULT hr = S_OK;
597 +
598 + hr = ProcRevertWowFileSystemRedirection(&pFileSearch->pfsr);
599 + ExitOnFailure(hr, "Failed to revert file system redirection.");
600 +
601 +LExit:
602 + return;
603 +}
604 +
605 +#endif
606 +
607 static HRESULT DirectorySearchExists(
608 __in BURN_SEARCH* pSearch,
609 __in BURN_VARIABLES* pVariables
@@ -566,6 +613,15 @@ static HRESULT DirectorySearchExists(
613 LPWSTR sczPath = NULL;
614 BOOL fExists = FALSE;
615
616 +#if !defined(_WIN64)
617 + BURN_FILE_SEARCH bfs = { };
618 +
619 + bfs.pSearch = pSearch;
620 +
621 + hr = FileSystemSearchStart(&bfs);
622 + ExitOnFailure(hr, "Failed to initialize file search.");
623 +#endif
624 +
625 // format path
626 hr = VariableFormatString(pVariables, pSearch->DirectorySearch.sczPath, &sczPath, NULL);
627 ExitOnFailure(hr, "Failed to format variable string.");
@@ -593,6 +649,10 @@ static HRESULT DirectorySearchExists(
649 ExitOnFailure(hr, "Failed to set variable.");
650
651 LExit:
652 +#if !defined(_WIN64)
653 + FileSystemSearchEnd(&bfs);
654 +#endif
655 +
656 StrSecureZeroFreeString(sczPath);
657
658 return hr;
@@ -606,6 +666,15 @@ static HRESULT DirectorySearchPath(
666 HRESULT hr = S_OK;
667 LPWSTR sczPath = NULL;
668
669 +#if !defined(_WIN64)
670 + BURN_FILE_SEARCH bfs = { };
671 +
672 + bfs.pSearch = pSearch;
673 +
674 + hr = FileSystemSearchStart(&bfs);
675 + ExitOnFailure(hr, "Failed to initialize file search.");
676 +#endif
677 +
678 // format path
679 hr = VariableFormatString(pVariables, pSearch->DirectorySearch.sczPath, &sczPath, NULL);
680 ExitOnFailure(hr, "Failed to format variable string.");
@@ -634,6 +703,10 @@ static HRESULT DirectorySearchPath(
703 ExitOnFailure(hr, "Failed while searching directory search: %ls, for path: %ls", pSearch->sczKey, sczPath);
704
705 LExit:
706 +#if !defined(_WIN64)
707 + FileSystemSearchEnd(&bfs);
708 +#endif
709 +
710 StrSecureZeroFreeString(sczPath);
711
712 return hr;
@@ -649,6 +722,15 @@ static HRESULT FileSearchExists(
722 LPWSTR sczPath = NULL;
723 BOOL fExists = FALSE;
724
725 +#if !defined(_WIN64)
726 + BURN_FILE_SEARCH bfs = { };
727 +
728 + bfs.pSearch = pSearch;
729 +
730 + hr = FileSystemSearchStart(&bfs);
731 + ExitOnFailure(hr, "Failed to initialize file search.");
732 +#endif
733 +
734 // format path
735 hr = VariableFormatString(pVariables, pSearch->FileSearch.sczPath, &sczPath, NULL);
736 ExitOnFailure(hr, "Failed to format variable string.");
@@ -665,7 +747,7 @@ static HRESULT FileSearchExists(
747 }
748 else
749 {
668 - ExitOnWin32Error(er, hr, "Failed get to file attributes. '%ls'", pSearch->DirectorySearch.sczPath);
750 + ExitOnWin32Error(er, hr, "Failed get to file attributes. '%ls'", pSearch->FileSearch.sczPath);
751 }
752 }
753 else if (FILE_ATTRIBUTE_DIRECTORY != (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
@@ -678,6 +760,10 @@ static HRESULT FileSearchExists(
760 ExitOnFailure(hr, "Failed to set variable.");
761
762 LExit:
763 +#if !defined(_WIN64)
764 + FileSystemSearchEnd(&bfs);
765 +#endif
766 +
767 StrSecureZeroFreeString(sczPath);
768 return hr;
769 }
@@ -692,6 +778,15 @@ static HRESULT FileSearchVersion(
778 LPWSTR sczPath = NULL;
779 VERUTIL_VERSION* pVersion = NULL;
780
781 +#if !defined(_WIN64)
782 + BURN_FILE_SEARCH bfs = { };
783 +
784 + bfs.pSearch = pSearch;
785 +
786 + hr = FileSystemSearchStart(&bfs);
787 + ExitOnFailure(hr, "Failed to initialize file search.");
788 +#endif
789 +
790 // format path
791 hr = VariableFormatString(pVariables, pSearch->FileSearch.sczPath, &sczPath, NULL);
792 ExitOnFailure(hr, "Failed to format path string.");
@@ -714,6 +809,10 @@ static HRESULT FileSearchVersion(
809 ExitOnFailure(hr, "Failed to set variable.");
810
811 LExit:
812 +#if !defined(_WIN64)
813 + FileSystemSearchEnd(&bfs);
814 +#endif
815 +
816 StrSecureZeroFreeString(sczPath);
817 ReleaseVerutilVersion(pVersion);
818 return hr;
@@ -727,6 +826,15 @@ static HRESULT FileSearchPath(
826 HRESULT hr = S_OK;
827 LPWSTR sczPath = NULL;
828
829 +#if !defined(_WIN64)
830 + BURN_FILE_SEARCH bfs = { };
831 +
832 + bfs.pSearch = pSearch;
833 +
834 + hr = FileSystemSearchStart(&bfs);
835 + ExitOnFailure(hr, "Failed to initialize file search.");
836 +#endif
837 +
838 // format path
839 hr = VariableFormatString(pVariables, pSearch->FileSearch.sczPath, &sczPath, NULL);
840 ExitOnFailure(hr, "Failed to format variable string.");
@@ -755,6 +863,10 @@ static HRESULT FileSearchPath(
863 ExitOnFailure(hr, "Failed while searching file search: %ls, for path: %ls", pSearch->sczKey, sczPath);
864
865 LExit:
866 +#if !defined(_WIN64)
867 + FileSystemSearchEnd(&bfs);
868 +#endif
869 +
870 StrSecureZeroFreeString(sczPath);
871
872 return hr;
src/burn/engine/search.h
+1
@@ -88,6 +88,7 @@ typedef struct _BURN_SEARCH
88 {
89 BURN_FILE_SEARCH_TYPE Type;
90 LPWSTR sczPath;
91 + BOOL fDisableFileRedirection;
92 } FileSearch;
93 struct
94 {
src/burn/test/BurnUnitTest/SearchTest.cpp
+12
@@ -129,6 +129,9 @@ namespace Bootstrapper
129 L" <FileSearch Id='Search1' Type='exists' Path='[File1]' Variable='Variable1' />"
130 L" <FileSearch Id='Search2' Type='exists' Path='[File2]' Variable='Variable2' />"
131 L" <FileSearch Id='Search3' Type='version' Path='[File2]' Variable='Variable3' />"
132 + L" <FileSearch Id='Search4' Type='exists' Path='[SystemFolder]\\consent.exe' Variable='Variable4' />"
133 + L" <FileSearch Id='Search5' Type='exists' Path='[System64Folder]\\consent.exe' Variable='Variable5' DisableFileRedirection='no' />"
134 + L" <FileSearch Id='Search6' Type='exists' Path='[System64Folder]\\consent.exe' Variable='Variable6' DisableFileRedirection='yes' />"
135 L"</Bundle>";
136
137 // load XML document
@@ -145,6 +148,15 @@ namespace Bootstrapper
148 Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable1"));
149 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable2"));
150 Assert::Equal<String^>(gcnew String(pVersion->sczVersion), VariableGetVersionHelper(&variables, L"Variable3"));
151 +
152 + // Assume that consent.exe continues to only exist in 64-bit system folder.
153 + Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable4"));
154 +#if !defined(_WIN64)
155 + Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable5"));
156 +#else
157 + Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable5"));
158 +#endif
159 + Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable6"));
160 }
161 finally
162 {
src/ext/Util/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs
+5
@@ -7,6 +7,7 @@
7 <util:RegistrySearchRef Id="RegistrySearchId" />
8 <util:RegistrySearchRef Id="RegistrySearchId64" />
9 <util:ProductSearchRef Id="ProductSearchId" />
10 + <util:DirectorySearchRef Id="DirectorySearchId" />
11 <util:FileSearchRef Id="FileSearchId" />
12 <util:WindowsFeatureSearchRef Id="DetectSHA2SupportId" />
13
@@ -42,6 +43,10 @@
43 <util:ProductSearch Id="ProductSearchId" Variable="ProductSearchVariable" UpgradeCode="738D02BF-E231-4370-8209-E9FD4E1BE2A1" Condition="1 &amp; 2 &lt; 3" Result="version" />
44 </Fragment>
45
46 + <Fragment>
47 + <util:DirectorySearch Id="DirectorySearchId" Variable="DirectorySearchVariable" Path="%windir%\System32" Result="exists" DisableFileRedirection="yes" />
48 + </Fragment>
49 +
50 <Fragment>
51 <util:FileSearch Id="FileSearchId" Variable="FileSearchVariable" Path="%windir%\System32\mscoree.dll" Result="exists" />
52 </Fragment>
src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
+14 -12
@@ -4,6 +4,7 @@ namespace WixToolsetTest.Util
4 {
5 using System.IO;
6 using System.Linq;
7 + using System.Xml;
8 using WixBuildTools.TestSupport;
9 using WixToolset.Core.TestPackage;
10 using WixToolset.Util;
@@ -279,18 +280,19 @@ namespace WixToolsetTest.Util
280 "<WixWindowsFeatureSearch Id='DetectSHA2SupportId' Type='sha2CodeSigning' />" +
281 "</BundleExtension>", bundleExtensionDatas[0].GetTestXml());
282
282 - var utilSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/*[self::burn:ExtensionSearch or self::burn:FileSearch or self::burn:MsiProductSearch or self::burn:RegistrySearch]");
283 - Assert.Equal(5, utilSearches.Count);
284 - Assert.Equal("<ExtensionSearch Id='DetectSHA2SupportId' Variable='IsSHA2Supported' " +
285 - "ExtensionId='Wix4UtilBundleExtension_X86' />", utilSearches[0].GetTestXml());
286 - Assert.Equal("<FileSearch Id='FileSearchId' Variable='FileSearchVariable' " +
287 - $@"Path='%windir%\System32\mscoree.dll' Type='exists' />", utilSearches[1].GetTestXml());
288 - Assert.Equal("<MsiProductSearch Id='ProductSearchId' Variable='ProductSearchVariable' Condition='1 &amp; 2 &lt; 3' " +
289 - "UpgradeCode='{738D02BF-E231-4370-8209-E9FD4E1BE2A1}' Type='version' />", utilSearches[2].GetTestXml());
290 - Assert.Equal("<RegistrySearch Id='RegistrySearchId' Variable='RegistrySearchVariable' " +
291 - @"Root='HKLM' Key='SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' Value='Release' Type='value' VariableType='string' />", utilSearches[3].GetTestXml());
292 - Assert.Equal("<RegistrySearch Id='RegistrySearchId64' Variable='RegistrySearchVariable64' " +
293 - @"Root='HKLM' Key='SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' Value='Release' Win64='yes' Type='value' VariableType='string' />", utilSearches[4].GetTestXml());
283 + var utilSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/*[self::burn:ExtensionSearch or self::burn:DirectorySearch or self::burn:FileSearch or self::burn:MsiProductSearch or self::burn:RegistrySearch]")
284 + .Cast<XmlElement>()
285 + .Select(e => e.GetTestXml())
286 + .ToArray();
287 + WixAssert.CompareLineByLine(new[]
288 + {
289 + @"<ExtensionSearch Id='DetectSHA2SupportId' Variable='IsSHA2Supported' ExtensionId='Wix4UtilBundleExtension_X86' />",
290 + @"<DirectorySearch Id='DirectorySearchId' Variable='DirectorySearchVariable' Path='%windir%\System32' Type='exists' DisableFileRedirection='yes' />",
291 + @"<FileSearch Id='FileSearchId' Variable='FileSearchVariable' Path='%windir%\System32\mscoree.dll' Type='exists' />",
292 + @"<MsiProductSearch Id='ProductSearchId' Variable='ProductSearchVariable' Condition='1 &amp; 2 &lt; 3' UpgradeCode='{738D02BF-E231-4370-8209-E9FD4E1BE2A1}' Type='version' />",
293 + @"<RegistrySearch Id='RegistrySearchId' Variable='RegistrySearchVariable' Root='HKLM' Key='SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' Value='Release' Type='value' VariableType='string' />",
294 + @"<RegistrySearch Id='RegistrySearchId64' Variable='RegistrySearchVariable64' Root='HKLM' Key='SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' Value='Release' Win64='yes' Type='value' VariableType='string' />"
295 + }, utilSearches);
296 }
297 }
298
src/ext/Util/wixext/UtilCompiler.cs
+12
@@ -999,6 +999,12 @@ namespace WixToolset.Util
999 case "After":
1000 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
1001 break;
1002 + case "DisableFileRedirection":
1003 + if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes)
1004 + {
1005 + attributes |= WixFileSearchAttributes.DisableFileRedirection;
1006 + }
1007 + break;
1008 case "Path":
1009 path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true);
1010 break;
@@ -1104,6 +1110,12 @@ namespace WixToolset.Util
1110 case "After":
1111 this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after);
1112 break;
1113 + case "DisableFileRedirection":
1114 + if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes)
1115 + {
1116 + attributes |= WixFileSearchAttributes.DisableFileRedirection;
1117 + }
1118 + break;
1119 case "Path":
1120 path = this.ParseHelper.GetAttributeLongFilename(sourceLineNumbers, attrib, false, true);
1121 break;
src/wix/WixToolset.Core.Burn/Bind/LegacySearchFacade.cs
+5
@@ -98,6 +98,11 @@ namespace WixToolset.Core.Burn
98 throw new NotImplementedException();
99 }
100
101 + if (searchSymbol.DisableFileRedirection)
102 + {
103 + writer.WriteAttributeString("DisableFileRedirection", "yes");
104 + }
105 +
106 writer.WriteEndElement();
107 }
108