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 & 2 < 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 & 2 < 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 & 2 < 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