diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2020-03-30 19:46:56 +1000 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2020-03-30 21:57:49 +1000 |
| commit | 0afd76e4c5d46f237591d860e7d445e267522187 (patch) | |
| tree | 9f3b648da7733464c83ba6e253a65a18d17f5583 /src | |
| parent | d74e3dd4bcc573d0c4b1fb5c36c8bf0115cc21a1 (diff) | |
| download | wix-0afd76e4c5d46f237591d860e7d445e267522187.tar.gz wix-0afd76e4c5d46f237591d860e7d445e267522187.tar.bz2 wix-0afd76e4c5d46f237591d860e7d445e267522187.zip | |
Add DetectSHA2Support "search".
Diffstat (limited to 'src')
| -rw-r--r-- | src/be/UtilBundleExtension.cpp | 87 | ||||
| -rw-r--r-- | src/be/UtilBundleExtension.h | 16 | ||||
| -rw-r--r-- | src/be/detectsha2support.cpp | 58 | ||||
| -rw-r--r-- | src/be/detectsha2support.h | 8 | ||||
| -rw-r--r-- | src/be/packages.config | 1 | ||||
| -rw-r--r-- | src/be/precomp.h | 23 | ||||
| -rw-r--r-- | src/be/utilbe.cpp | 28 | ||||
| -rw-r--r-- | src/be/utilbe.vcxproj | 20 | ||||
| -rw-r--r-- | src/be/utilsearch.cpp | 137 | ||||
| -rw-r--r-- | src/be/utilsearch.h | 52 | ||||
| -rw-r--r-- | src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs | 5 | ||||
| -rw-r--r-- | src/test/WixToolsetTest.Util/UtilExtensionFixture.cs | 55 | ||||
| -rw-r--r-- | src/wixext/Tuples/UtilTupleDefinitions.cs | 10 | ||||
| -rw-r--r-- | src/wixext/Tuples/WixDetectSHA2SupportTuple.cs | 33 | ||||
| -rw-r--r-- | src/wixext/UtilBinder.cs | 347 | ||||
| -rw-r--r-- | src/wixext/UtilCompiler.cs | 198 | ||||
| -rw-r--r-- | src/wixext/UtilConstants.cs | 2 | ||||
| -rw-r--r-- | src/wixext/UtilErrors.cs | 6 | ||||
| -rw-r--r-- | src/wixext/util.xsd | 24 |
19 files changed, 609 insertions, 501 deletions
diff --git a/src/be/UtilBundleExtension.cpp b/src/be/UtilBundleExtension.cpp new file mode 100644 index 00000000..2ac842a5 --- /dev/null +++ b/src/be/UtilBundleExtension.cpp | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | #include "BextBaseBundleExtension.h" | ||
| 5 | |||
| 6 | class CWixUtilBundleExtension : public CBextBaseBundleExtension | ||
| 7 | { | ||
| 8 | public: // IBundleExtension | ||
| 9 | virtual STDMETHODIMP Search( | ||
| 10 | __in LPCWSTR wzId, | ||
| 11 | __in LPCWSTR wzVariable | ||
| 12 | ) | ||
| 13 | { | ||
| 14 | HRESULT hr = S_OK; | ||
| 15 | |||
| 16 | hr = UtilSearchExecute(&m_searches, wzId, wzVariable, m_pEngine); | ||
| 17 | |||
| 18 | return hr; | ||
| 19 | } | ||
| 20 | |||
| 21 | public: //CBextBaseBundleExtension | ||
| 22 | virtual STDMETHODIMP Initialize( | ||
| 23 | __in const BUNDLE_EXTENSION_CREATE_ARGS* pCreateArgs | ||
| 24 | ) | ||
| 25 | { | ||
| 26 | HRESULT hr = S_OK; | ||
| 27 | IXMLDOMDocument* pixdManifest = NULL; | ||
| 28 | IXMLDOMNode* pixnBundleExtension = NULL; | ||
| 29 | |||
| 30 | hr = CBextBaseBundleExtension::Initialize(pCreateArgs); | ||
| 31 | ExitOnFailure(hr, "CBextBaseBundleExtension initialization failed."); | ||
| 32 | |||
| 33 | hr = XmlLoadDocumentFromFile(m_sczBundleExtensionDataPath, &pixdManifest); | ||
| 34 | ExitOnFailure(hr, "Failed to load bundle extension manifest from path: %ls", m_sczBundleExtensionDataPath); | ||
| 35 | |||
| 36 | hr = BextGetBundleExtensionDataNode(pixdManifest, UTIL_BUNDLE_EXTENSION_ID, &pixnBundleExtension); | ||
| 37 | ExitOnFailure(hr, "Failed to get BundleExtension '%ls'", UTIL_BUNDLE_EXTENSION_ID); | ||
| 38 | |||
| 39 | hr = UtilSearchParseFromXml(&m_searches, pixnBundleExtension); | ||
| 40 | ExitOnFailure(hr, "Failed to parse searches from bundle extension manifest."); | ||
| 41 | |||
| 42 | LExit: | ||
| 43 | ReleaseObject(pixnBundleExtension); | ||
| 44 | ReleaseObject(pixdManifest); | ||
| 45 | |||
| 46 | return hr; | ||
| 47 | } | ||
| 48 | |||
| 49 | public: | ||
| 50 | CWixUtilBundleExtension( | ||
| 51 | __in IBundleExtensionEngine* pEngine | ||
| 52 | ) : CBextBaseBundleExtension(pEngine) | ||
| 53 | { | ||
| 54 | m_searches = { }; | ||
| 55 | } | ||
| 56 | |||
| 57 | ~CWixUtilBundleExtension() | ||
| 58 | { | ||
| 59 | UtilSearchUninitialize(&m_searches); | ||
| 60 | } | ||
| 61 | |||
| 62 | private: | ||
| 63 | UTIL_SEARCHES m_searches; | ||
| 64 | }; | ||
| 65 | |||
| 66 | HRESULT UtilBundleExtensionCreate( | ||
| 67 | __in IBundleExtensionEngine* pEngine, | ||
| 68 | __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, | ||
| 69 | __out IBundleExtension** ppBundleExtension | ||
| 70 | ) | ||
| 71 | { | ||
| 72 | HRESULT hr = S_OK; | ||
| 73 | CWixUtilBundleExtension* pExtension = NULL; | ||
| 74 | |||
| 75 | pExtension = new CWixUtilBundleExtension(pEngine); | ||
| 76 | ExitOnNull(pExtension, hr, E_OUTOFMEMORY, "Failed to create new CWixUtilBundleExtension."); | ||
| 77 | |||
| 78 | hr = pExtension->Initialize(pArgs); | ||
| 79 | ExitOnFailure(hr, "CWixUtilBundleExtension initialization failed"); | ||
| 80 | |||
| 81 | *ppBundleExtension = pExtension; | ||
| 82 | pExtension = NULL; | ||
| 83 | |||
| 84 | LExit: | ||
| 85 | ReleaseObject(pExtension); | ||
| 86 | return hr; | ||
| 87 | } | ||
diff --git a/src/be/UtilBundleExtension.h b/src/be/UtilBundleExtension.h new file mode 100644 index 00000000..16c5b346 --- /dev/null +++ b/src/be/UtilBundleExtension.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | // constants | ||
| 6 | |||
| 7 | #define UTIL_BUNDLE_EXTENSION_ID L"WixUtilBundleExtension" | ||
| 8 | |||
| 9 | |||
| 10 | // function declarations | ||
| 11 | |||
| 12 | HRESULT UtilBundleExtensionCreate( | ||
| 13 | __in IBundleExtensionEngine* pEngine, | ||
| 14 | __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, | ||
| 15 | __out IBundleExtension** ppBundleExtension | ||
| 16 | ); | ||
diff --git a/src/be/detectsha2support.cpp b/src/be/detectsha2support.cpp new file mode 100644 index 00000000..f1f3637e --- /dev/null +++ b/src/be/detectsha2support.cpp | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // https://gist.github.com/navossoc/7572c7d82243e9f818989e2765e7793a | ||
| 6 | HRESULT DetectSHA2Support( | ||
| 7 | __out BOOL* pfSupported | ||
| 8 | ) | ||
| 9 | { | ||
| 10 | HRESULT hr = S_OK; | ||
| 11 | HMODULE hModule = NULL; | ||
| 12 | FARPROC pfn = NULL; | ||
| 13 | DWORD er = ERROR_SUCCESS; | ||
| 14 | |||
| 15 | hr = LoadSystemLibrary(L"wintrust.dll", &hModule); | ||
| 16 | ExitOnFailure(hr, "Failed to load wintrust.dll"); | ||
| 17 | |||
| 18 | pfn = ::GetProcAddress(hModule, "CryptCATAdminAcquireContext2"); | ||
| 19 | if (pfn) | ||
| 20 | { | ||
| 21 | *pfSupported = TRUE; | ||
| 22 | ExitFunction1(hr = S_OK); | ||
| 23 | } | ||
| 24 | |||
| 25 | er = ::GetLastError(); | ||
| 26 | if (er == ERROR_PROC_NOT_FOUND) | ||
| 27 | { | ||
| 28 | *pfSupported = FALSE; | ||
| 29 | ExitFunction1(hr = S_OK); | ||
| 30 | } | ||
| 31 | |||
| 32 | hr = HRESULT_FROM_WIN32(er); | ||
| 33 | ExitOnFailure(hr, "Failed to probe for CryptCATAdminAcquireContext2 in wintrust.dll"); | ||
| 34 | |||
| 35 | LExit: | ||
| 36 | ::FreeLibrary(hModule); | ||
| 37 | |||
| 38 | return hr; | ||
| 39 | } | ||
| 40 | |||
| 41 | HRESULT UtilPerformDetectSHA2Support( | ||
| 42 | __in LPCWSTR wzVariable, | ||
| 43 | __in UTIL_SEARCH* /*pSearch*/, | ||
| 44 | __in IBundleExtensionEngine* pEngine | ||
| 45 | ) | ||
| 46 | { | ||
| 47 | HRESULT hr = S_OK; | ||
| 48 | BOOL fSupported = FALSE; | ||
| 49 | |||
| 50 | hr = DetectSHA2Support(&fSupported); | ||
| 51 | ExitOnFailure(hr, "DetectSHA2Support failed."); | ||
| 52 | |||
| 53 | hr = pEngine->SetVariableNumeric(wzVariable, fSupported ? 1 : 0); | ||
| 54 | ExitOnFailure(hr, "Failed to set variable '%ls'", wzVariable); | ||
| 55 | |||
| 56 | LExit: | ||
| 57 | return hr; | ||
| 58 | } | ||
diff --git a/src/be/detectsha2support.h b/src/be/detectsha2support.h new file mode 100644 index 00000000..7f1f6031 --- /dev/null +++ b/src/be/detectsha2support.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | HRESULT UtilPerformDetectSHA2Support( | ||
| 5 | __in LPCWSTR wzVariable, | ||
| 6 | __in UTIL_SEARCH* pSearch, | ||
| 7 | __in IBundleExtensionEngine* pEngine | ||
| 8 | ); \ No newline at end of file | ||
diff --git a/src/be/packages.config b/src/be/packages.config index f05546c5..ca23641f 100644 --- a/src/be/packages.config +++ b/src/be/packages.config | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <packages> | 2 | <packages> |
| 3 | <package id="WixToolset.BextUtil" version="4.0.16" targetFramework="native" /> | ||
| 3 | <package id="WixToolset.BootstrapperCore.Native" version="4.0.13" targetFramework="native" /> | 4 | <package id="WixToolset.BootstrapperCore.Native" version="4.0.13" targetFramework="native" /> |
| 4 | <package id="WixToolset.DUtil" version="4.0.18" targetFramework="native" /> | 5 | <package id="WixToolset.DUtil" version="4.0.18" targetFramework="native" /> |
| 5 | </packages> \ No newline at end of file | 6 | </packages> \ No newline at end of file |
diff --git a/src/be/precomp.h b/src/be/precomp.h index 9dc3c468..a4ab7abf 100644 --- a/src/be/precomp.h +++ b/src/be/precomp.h | |||
| @@ -17,9 +17,20 @@ | |||
| 17 | 17 | ||
| 18 | #define MAXUINT USHRT_MAX | 18 | #define MAXUINT USHRT_MAX |
| 19 | 19 | ||
| 20 | #include "dutil.h" | 20 | #include <dutil.h> |
| 21 | #include "memutil.h" | 21 | #include <memutil.h> |
| 22 | 22 | #include <strutil.h> | |
| 23 | #include "BootstrapperEngine.h" | 23 | #include <pathutil.h> |
| 24 | #include "BundleExtensionEngine.h" | 24 | #include <xmlutil.h> |
| 25 | #include "BundleExtension.h" | 25 | |
| 26 | #include <BundleExtensionEngine.h> | ||
| 27 | #include <BundleExtension.h> | ||
| 28 | |||
| 29 | #include <IBundleExtensionEngine.h> | ||
| 30 | #include <IBundleExtension.h> | ||
| 31 | #include <bextutil.h> | ||
| 32 | #include <BextBundleExtensionEngine.h> | ||
| 33 | |||
| 34 | #include "utilsearch.h" | ||
| 35 | #include "detectsha2support.h" | ||
| 36 | #include "UtilBundleExtension.h" | ||
diff --git a/src/be/utilbe.cpp b/src/be/utilbe.cpp index 370669dd..d9816dc7 100644 --- a/src/be/utilbe.cpp +++ b/src/be/utilbe.cpp | |||
| @@ -1,19 +1,41 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | #include "precomp.h" | 3 | #include "precomp.h" |
| 4 | #include "BextBaseBundleExtensionProc.h" | ||
| 5 | |||
| 6 | static IBundleExtension* vpBundleExtension = NULL; | ||
| 4 | 7 | ||
| 5 | // function definitions | 8 | // function definitions |
| 6 | 9 | ||
| 7 | extern "C" HRESULT WINAPI BundleExtensionCreate( | 10 | extern "C" HRESULT WINAPI BundleExtensionCreate( |
| 8 | __in const BUNDLE_EXTENSION_CREATE_ARGS* /*pArgs*/, | 11 | __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, |
| 9 | __inout BUNDLE_EXTENSION_CREATE_RESULTS* /*pResults*/ | 12 | __inout BUNDLE_EXTENSION_CREATE_RESULTS* pResults |
| 10 | ) | 13 | ) |
| 11 | { | 14 | { |
| 12 | HRESULT hr = S_OK; | 15 | HRESULT hr = S_OK; |
| 16 | IBundleExtensionEngine* pEngine = NULL; | ||
| 17 | |||
| 18 | hr = XmlInitialize(); | ||
| 19 | ExitOnFailure(hr, "Failed to initialize XML."); | ||
| 20 | |||
| 21 | hr = BextInitializeFromCreateArgs(pArgs, &pEngine); | ||
| 22 | ExitOnFailure(hr, "Failed to initialize bext"); | ||
| 23 | |||
| 24 | hr = UtilBundleExtensionCreate(pEngine, pArgs, &vpBundleExtension); | ||
| 25 | BextExitOnFailure(hr, "Failed to create WixUtilBundleExtension"); | ||
| 26 | |||
| 27 | pResults->pfnBundleExtensionProc = BextBaseBundleExtensionProc; | ||
| 28 | pResults->pvBundleExtensionProcContext = vpBundleExtension; | ||
| 29 | |||
| 30 | LExit: | ||
| 31 | ReleaseObject(pEngine); | ||
| 13 | 32 | ||
| 14 | return hr; | 33 | return hr; |
| 15 | } | 34 | } |
| 16 | 35 | ||
| 17 | extern "C" void WINAPI BundleExtensionDestroy() | 36 | extern "C" void WINAPI BundleExtensionDestroy() |
| 18 | { | 37 | { |
| 38 | BextUninitialize(); | ||
| 39 | ReleaseNullObject(vpBundleExtension); | ||
| 40 | XmlUninitialize(); | ||
| 19 | } \ No newline at end of file | 41 | } \ No newline at end of file |
diff --git a/src/be/utilbe.vcxproj b/src/be/utilbe.vcxproj index 963eac7f..e64d113e 100644 --- a/src/be/utilbe.vcxproj +++ b/src/be/utilbe.vcxproj | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> |
| 3 | |||
| 4 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | 3 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| 4 | <Import Project="..\..\packages\WixToolset.BextUtil.4.0.16\build\WixToolset.BextUtil.props" Condition="Exists('..\..\packages\WixToolset.BextUtil.4.0.16\build\WixToolset.BextUtil.props')" /> | ||
| 5 | <Import Project="..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props" Condition="Exists('..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props')" /> | 5 | <Import Project="..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props" Condition="Exists('..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props')" /> |
| 6 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props')" /> | 6 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props')" /> |
| 7 | |||
| 8 | <ItemGroup Label="ProjectConfigurations"> | 7 | <ItemGroup Label="ProjectConfigurations"> |
| 9 | <ProjectConfiguration Include="Debug|Win32"> | 8 | <ProjectConfiguration Include="Debug|Win32"> |
| 10 | <Configuration>Debug</Configuration> | 9 | <Configuration>Debug</Configuration> |
| @@ -15,7 +14,6 @@ | |||
| 15 | <Platform>Win32</Platform> | 14 | <Platform>Win32</Platform> |
| 16 | </ProjectConfiguration> | 15 | </ProjectConfiguration> |
| 17 | </ItemGroup> | 16 | </ItemGroup> |
| 18 | |||
| 19 | <PropertyGroup Label="Globals"> | 17 | <PropertyGroup Label="Globals"> |
| 20 | <ProjectGuid>{630C1EE7-2517-4A8C-83E3-DA1150308B58}</ProjectGuid> | 18 | <ProjectGuid>{630C1EE7-2517-4A8C-83E3-DA1150308B58}</ProjectGuid> |
| 21 | <ConfigurationType>DynamicLibrary</ConfigurationType> | 19 | <ConfigurationType>DynamicLibrary</ConfigurationType> |
| @@ -25,37 +23,37 @@ | |||
| 25 | <ProjectModuleDefinitionFile>utilbe.def</ProjectModuleDefinitionFile> | 23 | <ProjectModuleDefinitionFile>utilbe.def</ProjectModuleDefinitionFile> |
| 26 | <Description>WiX Toolset Util BundleExtension</Description> | 24 | <Description>WiX Toolset Util BundleExtension</Description> |
| 27 | </PropertyGroup> | 25 | </PropertyGroup> |
| 28 | |||
| 29 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | 26 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
| 30 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | 27 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
| 31 | |||
| 32 | <PropertyGroup> | 28 | <PropertyGroup> |
| 33 | <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries> | 29 | <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries> |
| 34 | </PropertyGroup> | 30 | </PropertyGroup> |
| 35 | |||
| 36 | <ItemGroup> | 31 | <ItemGroup> |
| 32 | <ClCompile Include="detectsha2support.cpp" /> | ||
| 37 | <ClCompile Include="precomp.cpp"> | 33 | <ClCompile Include="precomp.cpp"> |
| 38 | <PrecompiledHeader>Create</PrecompiledHeader> | 34 | <PrecompiledHeader>Create</PrecompiledHeader> |
| 39 | </ClCompile> | 35 | </ClCompile> |
| 40 | <ClCompile Include="utilbe.cpp" /> | 36 | <ClCompile Include="utilbe.cpp" /> |
| 37 | <ClCompile Include="UtilBundleExtension.cpp" /> | ||
| 38 | <ClCompile Include="utilsearch.cpp" /> | ||
| 41 | </ItemGroup> | 39 | </ItemGroup> |
| 42 | |||
| 43 | <ItemGroup> | 40 | <ItemGroup> |
| 41 | <ClInclude Include="detectsha2support.h" /> | ||
| 44 | <ClInclude Include="precomp.h" /> | 42 | <ClInclude Include="precomp.h" /> |
| 43 | <ClInclude Include="UtilBundleExtension.h" /> | ||
| 44 | <ClInclude Include="utilsearch.h" /> | ||
| 45 | </ItemGroup> | 45 | </ItemGroup> |
| 46 | |||
| 47 | <ItemGroup> | 46 | <ItemGroup> |
| 48 | <None Include="packages.config" /> | 47 | <None Include="packages.config" /> |
| 49 | <None Include="utilbe.def" /> | 48 | <None Include="utilbe.def" /> |
| 50 | </ItemGroup> | 49 | </ItemGroup> |
| 51 | |||
| 52 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | 50 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
| 53 | |||
| 54 | <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | 51 | <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
| 55 | <PropertyGroup> | 52 | <PropertyGroup> |
| 56 | <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> | 53 | <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> |
| 57 | </PropertyGroup> | 54 | </PropertyGroup> |
| 55 | <Error Condition="!Exists('..\..\packages\WixToolset.BextUtil.4.0.16\build\WixToolset.BextUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.BextUtil.4.0.16\build\WixToolset.BextUtil.props'))" /> | ||
| 58 | <Error Condition="!Exists('..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props'))" /> | 56 | <Error Condition="!Exists('..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.BootstrapperCore.Native.4.0.13\build\WixToolset.BootstrapperCore.Native.props'))" /> |
| 59 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props'))" /> | 57 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props'))" /> |
| 60 | </Target> | 58 | </Target> |
| 61 | </Project> | 59 | </Project> \ No newline at end of file |
diff --git a/src/be/utilsearch.cpp b/src/be/utilsearch.cpp new file mode 100644 index 00000000..4e9d86a1 --- /dev/null +++ b/src/be/utilsearch.cpp | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | STDMETHODIMP UtilSearchParseFromXml( | ||
| 7 | __in UTIL_SEARCHES* pSearches, | ||
| 8 | __in IXMLDOMNode* pixnBundleExtension | ||
| 9 | ) | ||
| 10 | { | ||
| 11 | HRESULT hr = S_OK; | ||
| 12 | IXMLDOMNodeList* pixnNodes = NULL; | ||
| 13 | IXMLDOMNode* pixnNode = NULL; | ||
| 14 | DWORD cNodes = 0; | ||
| 15 | BSTR bstrNodeName = NULL; | ||
| 16 | |||
| 17 | // Select Util search nodes. | ||
| 18 | hr = XmlSelectNodes(pixnBundleExtension, L"WixDetectSHA2Support", &pixnNodes); | ||
| 19 | ExitOnFailure(hr, "Failed to select Util search nodes."); | ||
| 20 | |||
| 21 | // Get Util search node count. | ||
| 22 | hr = pixnNodes->get_length((long*)&cNodes); | ||
| 23 | ExitOnFailure(hr, "Failed to get Util search node count."); | ||
| 24 | |||
| 25 | if (!cNodes) | ||
| 26 | { | ||
| 27 | ExitFunction(); | ||
| 28 | } | ||
| 29 | |||
| 30 | // Allocate memory for searches. | ||
| 31 | pSearches->rgSearches = (UTIL_SEARCH*)MemAlloc(sizeof(UTIL_SEARCH) * cNodes, TRUE); | ||
| 32 | ExitOnNull(pSearches->rgSearches, hr, E_OUTOFMEMORY, "Failed to allocate memory for search structs."); | ||
| 33 | |||
| 34 | pSearches->cSearches = cNodes; | ||
| 35 | |||
| 36 | // Parse search elements. | ||
| 37 | for (DWORD i = 0; i < cNodes; ++i) | ||
| 38 | { | ||
| 39 | UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; | ||
| 40 | |||
| 41 | hr = XmlNextElement(pixnNodes, &pixnNode, &bstrNodeName); | ||
| 42 | ExitOnFailure(hr, "Failed to get next node."); | ||
| 43 | |||
| 44 | // @Id | ||
| 45 | hr = XmlGetAttributeEx(pixnNode, L"Id", &pSearch->sczId); | ||
| 46 | ExitOnFailure(hr, "Failed to get @Id."); | ||
| 47 | |||
| 48 | // Read type specific attributes. | ||
| 49 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"WixDetectSHA2Support", -1)) | ||
| 50 | { | ||
| 51 | pSearch->Type = UTIL_SEARCH_TYPE_DETECT_SHA2_SUPPORT; | ||
| 52 | } | ||
| 53 | else | ||
| 54 | { | ||
| 55 | hr = E_UNEXPECTED; | ||
| 56 | ExitOnFailure(hr, "Unexpected element name: %ls", bstrNodeName); | ||
| 57 | } | ||
| 58 | |||
| 59 | // prepare next iteration | ||
| 60 | ReleaseNullObject(pixnNode); | ||
| 61 | ReleaseNullBSTR(bstrNodeName); | ||
| 62 | } | ||
| 63 | |||
| 64 | LExit: | ||
| 65 | ReleaseBSTR(bstrNodeName); | ||
| 66 | ReleaseObject(pixnNode); | ||
| 67 | ReleaseObject(pixnNodes); | ||
| 68 | |||
| 69 | return hr; | ||
| 70 | } | ||
| 71 | |||
| 72 | void UtilSearchUninitialize( | ||
| 73 | __in UTIL_SEARCHES* pSearches | ||
| 74 | ) | ||
| 75 | { | ||
| 76 | if (pSearches->rgSearches) | ||
| 77 | { | ||
| 78 | for (DWORD i = 0; i < pSearches->cSearches; ++i) | ||
| 79 | { | ||
| 80 | UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; | ||
| 81 | |||
| 82 | ReleaseStr(pSearch->sczId); | ||
| 83 | } | ||
| 84 | MemFree(pSearches->rgSearches); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | STDMETHODIMP UtilSearchExecute( | ||
| 89 | __in UTIL_SEARCHES* pSearches, | ||
| 90 | __in LPCWSTR wzSearchId, | ||
| 91 | __in LPCWSTR wzVariable, | ||
| 92 | __in IBundleExtensionEngine* pEngine | ||
| 93 | ) | ||
| 94 | { | ||
| 95 | HRESULT hr = S_OK; | ||
| 96 | UTIL_SEARCH* pSearch = NULL; | ||
| 97 | |||
| 98 | hr = UtilSearchFindById(pSearches, wzSearchId, &pSearch); | ||
| 99 | ExitOnFailure(hr, "Search id '%ls' is unknown to the util extension."); | ||
| 100 | |||
| 101 | switch (pSearch->Type) | ||
| 102 | { | ||
| 103 | case UTIL_SEARCH_TYPE_DETECT_SHA2_SUPPORT: | ||
| 104 | hr = UtilPerformDetectSHA2Support(wzVariable, pSearch, pEngine); | ||
| 105 | break; | ||
| 106 | default: | ||
| 107 | hr = E_UNEXPECTED; | ||
| 108 | } | ||
| 109 | |||
| 110 | LExit: | ||
| 111 | return hr; | ||
| 112 | } | ||
| 113 | |||
| 114 | STDMETHODIMP UtilSearchFindById( | ||
| 115 | __in UTIL_SEARCHES* pSearches, | ||
| 116 | __in LPCWSTR wzId, | ||
| 117 | __out UTIL_SEARCH** ppSearch | ||
| 118 | ) | ||
| 119 | { | ||
| 120 | HRESULT hr = S_OK; | ||
| 121 | |||
| 122 | for (DWORD i = 0; i < pSearches->cSearches; ++i) | ||
| 123 | { | ||
| 124 | UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; | ||
| 125 | |||
| 126 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pSearch->sczId, -1, wzId, -1)) | ||
| 127 | { | ||
| 128 | *ppSearch = pSearch; | ||
| 129 | ExitFunction1(hr = S_OK); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | hr = E_NOTFOUND; | ||
| 134 | |||
| 135 | LExit: | ||
| 136 | return hr; | ||
| 137 | } | ||
diff --git a/src/be/utilsearch.h b/src/be/utilsearch.h new file mode 100644 index 00000000..1e0ca96d --- /dev/null +++ b/src/be/utilsearch.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | // constants | ||
| 6 | |||
| 7 | enum UTIL_SEARCH_TYPE | ||
| 8 | { | ||
| 9 | UTIL_SEARCH_TYPE_NONE, | ||
| 10 | UTIL_SEARCH_TYPE_DETECT_SHA2_SUPPORT, | ||
| 11 | }; | ||
| 12 | |||
| 13 | |||
| 14 | // structs | ||
| 15 | |||
| 16 | typedef struct _UTIL_SEARCH | ||
| 17 | { | ||
| 18 | LPWSTR sczId; | ||
| 19 | |||
| 20 | UTIL_SEARCH_TYPE Type; | ||
| 21 | } UTIL_SEARCH; | ||
| 22 | |||
| 23 | typedef struct _UTIL_SEARCHES | ||
| 24 | { | ||
| 25 | UTIL_SEARCH* rgSearches; | ||
| 26 | DWORD cSearches; | ||
| 27 | } UTIL_SEARCHES; | ||
| 28 | |||
| 29 | |||
| 30 | // function declarations | ||
| 31 | |||
| 32 | STDMETHODIMP UtilSearchParseFromXml( | ||
| 33 | __in UTIL_SEARCHES* pSearches, | ||
| 34 | __in IXMLDOMNode* pixnBundleExtension | ||
| 35 | ); | ||
| 36 | |||
| 37 | void UtilSearchUninitialize( | ||
| 38 | __in UTIL_SEARCHES* pSearches | ||
| 39 | ); | ||
| 40 | |||
| 41 | STDMETHODIMP UtilSearchExecute( | ||
| 42 | __in UTIL_SEARCHES* pSearches, | ||
| 43 | __in LPCWSTR wzSearchId, | ||
| 44 | __in LPCWSTR wzVariable, | ||
| 45 | __in IBundleExtensionEngine* pEngine | ||
| 46 | ); | ||
| 47 | |||
| 48 | STDMETHODIMP UtilSearchFindById( | ||
| 49 | __in UTIL_SEARCHES* pSearches, | ||
| 50 | __in LPCWSTR wzId, | ||
| 51 | __out UTIL_SEARCH** ppSearch | ||
| 52 | ); | ||
diff --git a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs index cafd4255..82646b37 100644 --- a/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs +++ b/src/test/WixToolsetTest.Util/TestData/BundleWithSearches/Bundle.wxs | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | <util:RegistrySearchRef Id="RegistrySearchId" /> | 7 | <util:RegistrySearchRef Id="RegistrySearchId" /> |
| 8 | <util:ProductSearchRef Id="ProductSearchId" /> | 8 | <util:ProductSearchRef Id="ProductSearchId" /> |
| 9 | <util:FileSearchRef Id="FileSearchId" /> | 9 | <util:FileSearchRef Id="FileSearchId" /> |
| 10 | <util:DetectSHA2SupportRef Id="DetectSHA2SupportId" /> | ||
| 10 | 11 | ||
| 11 | <Chain> | 12 | <Chain> |
| 12 | <MsiPackage SourceFile="test.msi"> | 13 | <MsiPackage SourceFile="test.msi"> |
| @@ -32,4 +33,8 @@ | |||
| 32 | <Fragment> | 33 | <Fragment> |
| 33 | <util:FileSearch Id="FileSearchId" Variable="FileSearchVariable" Path="%windir%\System32\mscoree.dll" Result="exists" /> | 34 | <util:FileSearch Id="FileSearchId" Variable="FileSearchVariable" Path="%windir%\System32\mscoree.dll" Result="exists" /> |
| 34 | </Fragment> | 35 | </Fragment> |
| 36 | |||
| 37 | <Fragment> | ||
| 38 | <util:DetectSHA2Support Id="DetectSHA2SupportId" Variable="IsSHA2Supported" /> | ||
| 39 | </Fragment> | ||
| 35 | </Wix> | 40 | </Wix> |
diff --git a/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs index 8f33eff5..c5b370ac 100644 --- a/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs +++ b/src/test/WixToolsetTest.Util/UtilExtensionFixture.cs | |||
| @@ -146,6 +146,9 @@ namespace WixToolsetTest.Util | |||
| 146 | { | 146 | { |
| 147 | var baseFolder = fs.GetFolder(); | 147 | var baseFolder = fs.GetFolder(); |
| 148 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | 148 | var intermediateFolder = Path.Combine(baseFolder, "obj"); |
| 149 | var bundlePath = Path.Combine(baseFolder, @"bin\test.exe"); | ||
| 150 | var baFolderPath = Path.Combine(baseFolder, "ba"); | ||
| 151 | var extractFolderPath = Path.Combine(baseFolder, "extract"); | ||
| 149 | 152 | ||
| 150 | var result = WixRunner.Execute(new[] | 153 | var result = WixRunner.Execute(new[] |
| 151 | { | 154 | { |
| @@ -156,45 +159,35 @@ namespace WixToolsetTest.Util | |||
| 156 | "-bindpath", Path.Combine(folder, "data"), | 159 | "-bindpath", Path.Combine(folder, "data"), |
| 157 | "-intermediateFolder", intermediateFolder, | 160 | "-intermediateFolder", intermediateFolder, |
| 158 | "-burnStub", burnStubPath, | 161 | "-burnStub", burnStubPath, |
| 159 | "-o", Path.Combine(baseFolder, @"bin\test.exe") | 162 | "-o", bundlePath |
| 160 | }); | 163 | }); |
| 161 | 164 | ||
| 162 | result.AssertSuccess(); | 165 | result.AssertSuccess(); |
| 163 | 166 | ||
| 164 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.exe"))); | 167 | Assert.True(File.Exists(bundlePath)); |
| 165 | #if TODO | 168 | #if TODO |
| 166 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); | 169 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); |
| 167 | #endif | 170 | #endif |
| 168 | 171 | ||
| 169 | var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"test.wir")); | 172 | var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); |
| 170 | var section = intermediate.Sections.Single(); | 173 | extractResult.AssertSuccess(); |
| 171 | 174 | ||
| 172 | var searchTuples = section.Tuples.OfType<WixSearchTuple>().OrderBy(t => t.Id.Id).ToList(); | 175 | var bundleExtensionDatas = extractResult.SelectBundleExtensionDataNodes("/be:BundleExtensionData/be:BundleExtension[@Id='WixUtilBundleExtension']"); |
| 173 | Assert.Equal(3, searchTuples.Count); | 176 | Assert.Equal(1, bundleExtensionDatas.Count); |
| 174 | Assert.Equal("FileSearchId", searchTuples[0].Id.Id); | 177 | Assert.Equal("<BundleExtension Id='WixUtilBundleExtension'>" + |
| 175 | Assert.Equal("FileSearchVariable", searchTuples[0].Variable); | 178 | "<WixDetectSHA2Support Id='DetectSHA2SupportId' />" + |
| 176 | Assert.Equal("ProductSearchId", searchTuples[1].Id.Id); | 179 | "</BundleExtension>", bundleExtensionDatas[0].GetTestXml()); |
| 177 | Assert.Equal("ProductSearchVariable", searchTuples[1].Variable); | 180 | |
| 178 | Assert.Equal("1 & 2 < 3", searchTuples[1].Condition); | 181 | var utilSearches = extractResult.SelectManifestNodes("/burn:BurnManifest/*[self::burn:ExtensionSearch or self::burn:FileSearch or self::burn:MsiProductSearch or self::burn:RegistrySearch]"); |
| 179 | Assert.Equal("RegistrySearchId", searchTuples[2].Id.Id); | 182 | Assert.Equal(4, utilSearches.Count); |
| 180 | Assert.Equal("RegistrySearchVariable", searchTuples[2].Variable); | 183 | Assert.Equal("<ExtensionSearch Id='DetectSHA2SupportId' Variable='IsSHA2Supported' " + |
| 181 | 184 | "ExtensionId='WixUtilBundleExtension' />", utilSearches[0].GetTestXml()); | |
| 182 | var fileSearchTuple = section.Tuples.OfType<WixFileSearchTuple>().Single(); | 185 | Assert.Equal("<FileSearch Id='FileSearchId' Variable='FileSearchVariable' " + |
| 183 | Assert.Equal("FileSearchId", fileSearchTuple.Id.Id); | 186 | $@"Path='%windir%\System32\mscoree.dll' Type='exists' />", utilSearches[1].GetTestXml()); |
| 184 | Assert.Equal(@"%windir%\System32\mscoree.dll", fileSearchTuple.Path); | 187 | Assert.Equal("<MsiProductSearch Id='ProductSearchId' Variable='ProductSearchVariable' Condition='1 & 2 < 3' " + |
| 185 | Assert.Equal(WixFileSearchAttributes.Default | WixFileSearchAttributes.WantExists, fileSearchTuple.Attributes); | 188 | "UpgradeCode='{738D02BF-E231-4370-8209-E9FD4E1BE2A1}' Type='version' />", utilSearches[2].GetTestXml()); |
| 186 | 189 | Assert.Equal("<RegistrySearch Id='RegistrySearchId' Variable='RegistrySearchVariable' " + | |
| 187 | var productSearchTuple = section.Tuples.OfType<WixProductSearchTuple>().Single(); | 190 | @"Root='HKLM' Key='SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' Value='Release' Type='value' VariableType='string' />", utilSearches[3].GetTestXml()); |
| 188 | Assert.Equal("ProductSearchId", productSearchTuple.Id.Id); | ||
| 189 | Assert.Equal("{738D02BF-E231-4370-8209-E9FD4E1BE2A1}", productSearchTuple.Guid); | ||
| 190 | Assert.Equal(WixProductSearchAttributes.Version | WixProductSearchAttributes.UpgradeCode, productSearchTuple.Attributes); | ||
| 191 | |||
| 192 | var registrySearchTuple = section.Tuples.OfType<WixRegistrySearchTuple>().Single(); | ||
| 193 | Assert.Equal("RegistrySearchId", registrySearchTuple.Id.Id); | ||
| 194 | Assert.Equal(RegistryRootType.LocalMachine, registrySearchTuple.Root); | ||
| 195 | Assert.Equal(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", registrySearchTuple.Key); | ||
| 196 | Assert.Equal("Release", registrySearchTuple.Value); | ||
| 197 | Assert.Equal(WixRegistrySearchAttributes.WantValue | WixRegistrySearchAttributes.Raw, registrySearchTuple.Attributes); | ||
| 198 | } | 191 | } |
| 199 | } | 192 | } |
| 200 | 193 | ||
diff --git a/src/wixext/Tuples/UtilTupleDefinitions.cs b/src/wixext/Tuples/UtilTupleDefinitions.cs index 00c98337..ece64502 100644 --- a/src/wixext/Tuples/UtilTupleDefinitions.cs +++ b/src/wixext/Tuples/UtilTupleDefinitions.cs | |||
| @@ -4,6 +4,7 @@ namespace WixToolset.Util | |||
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using WixToolset.Data; | 6 | using WixToolset.Data; |
| 7 | using WixToolset.Data.Burn; | ||
| 7 | 8 | ||
| 8 | public enum UtilTupleDefinitionType | 9 | public enum UtilTupleDefinitionType |
| 9 | { | 10 | { |
| @@ -19,6 +20,7 @@ namespace WixToolset.Util | |||
| 19 | User, | 20 | User, |
| 20 | UserGroup, | 21 | UserGroup, |
| 21 | WixCloseApplication, | 22 | WixCloseApplication, |
| 23 | WixDetectSHA2Support, | ||
| 22 | WixFormatFiles, | 24 | WixFormatFiles, |
| 23 | WixInternetShortcut, | 25 | WixInternetShortcut, |
| 24 | WixRemoveFolderEx, | 26 | WixRemoveFolderEx, |
| @@ -82,6 +84,9 @@ namespace WixToolset.Util | |||
| 82 | case UtilTupleDefinitionType.WixCloseApplication: | 84 | case UtilTupleDefinitionType.WixCloseApplication: |
| 83 | return UtilTupleDefinitions.WixCloseApplication; | 85 | return UtilTupleDefinitions.WixCloseApplication; |
| 84 | 86 | ||
| 87 | case UtilTupleDefinitionType.WixDetectSHA2Support: | ||
| 88 | return UtilTupleDefinitions.WixDetectSHA2Support; | ||
| 89 | |||
| 85 | case UtilTupleDefinitionType.WixFormatFiles: | 90 | case UtilTupleDefinitionType.WixFormatFiles: |
| 86 | return UtilTupleDefinitions.WixFormatFiles; | 91 | return UtilTupleDefinitions.WixFormatFiles; |
| 87 | 92 | ||
| @@ -107,5 +112,10 @@ namespace WixToolset.Util | |||
| 107 | throw new ArgumentOutOfRangeException(nameof(type)); | 112 | throw new ArgumentOutOfRangeException(nameof(type)); |
| 108 | } | 113 | } |
| 109 | } | 114 | } |
| 115 | |||
| 116 | static UtilTupleDefinitions() | ||
| 117 | { | ||
| 118 | WixDetectSHA2Support.AddTag(BurnConstants.BundleExtensionSearchTupleDefinitionTag); | ||
| 119 | } | ||
| 110 | } | 120 | } |
| 111 | } | 121 | } |
diff --git a/src/wixext/Tuples/WixDetectSHA2SupportTuple.cs b/src/wixext/Tuples/WixDetectSHA2SupportTuple.cs new file mode 100644 index 00000000..38b76ff2 --- /dev/null +++ b/src/wixext/Tuples/WixDetectSHA2SupportTuple.cs | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Util | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | using WixToolset.Util.Tuples; | ||
| 7 | |||
| 8 | public static partial class UtilTupleDefinitions | ||
| 9 | { | ||
| 10 | public static readonly IntermediateTupleDefinition WixDetectSHA2Support = new IntermediateTupleDefinition( | ||
| 11 | UtilTupleDefinitionType.WixDetectSHA2Support.ToString(), | ||
| 12 | new IntermediateFieldDefinition[0], | ||
| 13 | typeof(WixDetectSHA2SupportTuple)); | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace WixToolset.Util.Tuples | ||
| 18 | { | ||
| 19 | using WixToolset.Data; | ||
| 20 | |||
| 21 | public class WixDetectSHA2SupportTuple : IntermediateTuple | ||
| 22 | { | ||
| 23 | public WixDetectSHA2SupportTuple() : base(UtilTupleDefinitions.WixDetectSHA2Support, null, null) | ||
| 24 | { | ||
| 25 | } | ||
| 26 | |||
| 27 | public WixDetectSHA2SupportTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(UtilTupleDefinitions.WixDetectSHA2Support, sourceLineNumber, id) | ||
| 28 | { | ||
| 29 | } | ||
| 30 | |||
| 31 | public IntermediateField this[GroupTupleFields index] => this.Fields[(int)index]; | ||
| 32 | } | ||
| 33 | } | ||
diff --git a/src/wixext/UtilBinder.cs b/src/wixext/UtilBinder.cs deleted file mode 100644 index ef80a876..00000000 --- a/src/wixext/UtilBinder.cs +++ /dev/null | |||
| @@ -1,347 +0,0 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Extensions | ||
| 4 | { | ||
| 5 | #if TODO_BRINGBACK_FOR_BUNDLES | ||
| 6 | using System; | ||
| 7 | using System.Collections.Generic; | ||
| 8 | using System.Globalization; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Extensibility; | ||
| 11 | |||
| 12 | /// <summary> | ||
| 13 | /// The binder for the WiX Toolset Utility Extension. | ||
| 14 | /// </summary> | ||
| 15 | public sealed class UtilBinder : BinderExtension | ||
| 16 | { | ||
| 17 | // TODO: When WixSearch is supported in Product, etc, we may need to call | ||
| 18 | // ReorderWixSearch() from each of those initializers. | ||
| 19 | |||
| 20 | // TODO: A general-purpose "reorder this table given these constraints" | ||
| 21 | // mechanism may end up being helpful. This could be declaratively stated | ||
| 22 | // in the table definitions, or exposed from the core Wix.dll and called | ||
| 23 | // as-needed by any extensions. | ||
| 24 | |||
| 25 | /// <summary> | ||
| 26 | /// Called before bundle binding occurs. | ||
| 27 | /// </summary> | ||
| 28 | public override void Initialize(Output bundle) | ||
| 29 | { | ||
| 30 | if (OutputType.Bundle == bundle.Type) | ||
| 31 | { | ||
| 32 | this.ReorderWixSearch(bundle); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | /// <summary> | ||
| 37 | /// Reorders Any WixSearch items. | ||
| 38 | /// </summary> | ||
| 39 | /// <param name="output">Output containing the tables to process.</param> | ||
| 40 | private void ReorderWixSearch(Output output) | ||
| 41 | { | ||
| 42 | Table wixSearchTable = output.Tables["WixSearch"]; | ||
| 43 | if (null == wixSearchTable || wixSearchTable.Rows.Count == 0) | ||
| 44 | { | ||
| 45 | // nothing to do! | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | RowDictionary rowDictionary = new RowDictionary(); | ||
| 50 | foreach (Row row in wixSearchTable.Rows) | ||
| 51 | { | ||
| 52 | rowDictionary.AddRow(row); | ||
| 53 | } | ||
| 54 | |||
| 55 | Constraints constraints = new Constraints(); | ||
| 56 | Table wixSearchRelationTable = output.Tables["WixSearchRelation"]; | ||
| 57 | if (null != wixSearchRelationTable && wixSearchRelationTable.Rows.Count > 0) | ||
| 58 | { | ||
| 59 | // add relational info to our data... | ||
| 60 | foreach (Row row in wixSearchRelationTable.Rows) | ||
| 61 | { | ||
| 62 | constraints.AddConstraint((string)row[0], (string)row[1]); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | this.FindCircularReference(constraints); | ||
| 67 | |||
| 68 | if (this.Core.EncounteredError) | ||
| 69 | { | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | |||
| 73 | this.FlattenDependentReferences(constraints); | ||
| 74 | |||
| 75 | // Reorder by topographical sort (http://en.wikipedia.org/wiki/Topological_sorting) | ||
| 76 | // We use a variation of Kahn (1962) algorithm as described in | ||
| 77 | // Wikipedia, with the additional criteria that start nodes are sorted | ||
| 78 | // lexicographically at each step to ensure a deterministic ordering | ||
| 79 | // based on 'after' dependencies and ID. | ||
| 80 | TopologicalSort sorter = new TopologicalSort(); | ||
| 81 | List <string> sortedIds = sorter.Sort(rowDictionary.Keys, constraints); | ||
| 82 | |||
| 83 | // Now, re-write the table with the searches in order... | ||
| 84 | wixSearchTable.Rows.Clear(); | ||
| 85 | foreach (string id in sortedIds) | ||
| 86 | { | ||
| 87 | wixSearchTable.Rows.Add(rowDictionary[id]); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | /// <summary> | ||
| 92 | /// A dictionary of Row items, indexed by their first column. | ||
| 93 | /// </summary> | ||
| 94 | private class RowDictionary : Dictionary<string, Row> | ||
| 95 | { | ||
| 96 | public void AddRow(Row row) | ||
| 97 | { | ||
| 98 | this.Add((string)row[0], row); | ||
| 99 | } | ||
| 100 | |||
| 101 | // TODO: Hide other Add methods? | ||
| 102 | } | ||
| 103 | |||
| 104 | /// <summary> | ||
| 105 | /// A dictionary of constraints, mapping an id to a list of ids. | ||
| 106 | /// </summary> | ||
| 107 | private class Constraints : Dictionary<string, List<string>> | ||
| 108 | { | ||
| 109 | public void AddConstraint(string id, string afterId) | ||
| 110 | { | ||
| 111 | if (!this.ContainsKey(id)) | ||
| 112 | { | ||
| 113 | this.Add(id, new List<string>()); | ||
| 114 | } | ||
| 115 | |||
| 116 | // TODO: Show warning if a constraint is seen twice? | ||
| 117 | if (!this[id].Contains(afterId)) | ||
| 118 | { | ||
| 119 | this[id].Add(afterId); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | // TODO: Hide other Add methods? | ||
| 124 | } | ||
| 125 | |||
| 126 | /// <summary> | ||
| 127 | /// Finds circular references in the constraints. | ||
| 128 | /// </summary> | ||
| 129 | /// <param name="constraints">Constraints to check.</param> | ||
| 130 | /// <remarks>This is not particularly performant, but it works.</remarks> | ||
| 131 | private void FindCircularReference(Constraints constraints) | ||
| 132 | { | ||
| 133 | foreach (string id in constraints.Keys) | ||
| 134 | { | ||
| 135 | List<string> seenIds = new List<string>(); | ||
| 136 | string chain = null; | ||
| 137 | if (FindCircularReference(constraints, id, id, seenIds, out chain)) | ||
| 138 | { | ||
| 139 | // We will show a separate message for every ID that's in | ||
| 140 | // the loop. We could bail after the first one, but then | ||
| 141 | // we wouldn't catch disjoint loops in a single run. | ||
| 142 | this.Core.OnMessage(UtilErrors.CircularSearchReference(chain)); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | /// <summary> | ||
| 148 | /// Recursive function that finds circular references in the constraints. | ||
| 149 | /// </summary> | ||
| 150 | /// <param name="constraints">Constraints to check.</param> | ||
| 151 | /// <param name="checkId">The identifier currently being looking for. (Fixed across a given run.)</param> | ||
| 152 | /// <param name="currentId">The idenifier curently being tested.</param> | ||
| 153 | /// <param name="seenIds">A list of identifiers seen, to ensure each identifier is only expanded once.</param> | ||
| 154 | /// <param name="chain">If a circular reference is found, will contain the chain of references.</param> | ||
| 155 | /// <returns>True if a circular reference is found, false otherwise.</returns> | ||
| 156 | private bool FindCircularReference(Constraints constraints, string checkId, string currentId, List<string> seenIds, out string chain) | ||
| 157 | { | ||
| 158 | chain = null; | ||
| 159 | List<string> afterList = null; | ||
| 160 | if (constraints.TryGetValue(currentId, out afterList)) | ||
| 161 | { | ||
| 162 | foreach (string afterId in afterList) | ||
| 163 | { | ||
| 164 | if (afterId == checkId) | ||
| 165 | { | ||
| 166 | chain = String.Format(CultureInfo.InvariantCulture, "{0} -> {1}", currentId, afterId); | ||
| 167 | return true; | ||
| 168 | } | ||
| 169 | |||
| 170 | if (!seenIds.Contains(afterId)) | ||
| 171 | { | ||
| 172 | seenIds.Add(afterId); | ||
| 173 | if (FindCircularReference(constraints, checkId, afterId, seenIds, out chain)) | ||
| 174 | { | ||
| 175 | chain = String.Format(CultureInfo.InvariantCulture, "{0} -> {1}", currentId, chain); | ||
| 176 | return true; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | return false; | ||
| 183 | } | ||
| 184 | |||
| 185 | /// <summary> | ||
| 186 | /// Flattens any dependency chains to simplify reordering. | ||
| 187 | /// </summary> | ||
| 188 | /// <param name="constraints"></param> | ||
| 189 | private void FlattenDependentReferences(Constraints constraints) | ||
| 190 | { | ||
| 191 | foreach (string id in constraints.Keys) | ||
| 192 | { | ||
| 193 | List<string> flattenedIds = new List<string>(); | ||
| 194 | AddDependentReferences(constraints, id, flattenedIds); | ||
| 195 | List<string> constraintList = constraints[id]; | ||
| 196 | foreach (string flattenedId in flattenedIds) | ||
| 197 | { | ||
| 198 | if (!constraintList.Contains(flattenedId)) | ||
| 199 | { | ||
| 200 | constraintList.Add(flattenedId); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | /// <summary> | ||
| 207 | /// Adds dependent references to a list. | ||
| 208 | /// </summary> | ||
| 209 | /// <param name="constraints"></param> | ||
| 210 | /// <param name="currentId"></param> | ||
| 211 | /// <param name="seenIds"></param> | ||
| 212 | private void AddDependentReferences(Constraints constraints, string currentId, List<string> seenIds) | ||
| 213 | { | ||
| 214 | List<string> afterList = null; | ||
| 215 | if (constraints.TryGetValue(currentId, out afterList)) | ||
| 216 | { | ||
| 217 | foreach (string afterId in afterList) | ||
| 218 | { | ||
| 219 | if (!seenIds.Contains(afterId)) | ||
| 220 | { | ||
| 221 | seenIds.Add(afterId); | ||
| 222 | AddDependentReferences(constraints, afterId, seenIds); | ||
| 223 | } | ||
| 224 | } | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | /// <summary> | ||
| 229 | /// Reorder by topological sort | ||
| 230 | /// </summary> | ||
| 231 | /// <remarks> | ||
| 232 | /// We use a variation of Kahn (1962) algorithm as described in | ||
| 233 | /// Wikipedia (http://en.wikipedia.org/wiki/Topological_sorting), with | ||
| 234 | /// the additional criteria that start nodes are sorted lexicographically | ||
| 235 | /// at each step to ensure a deterministic ordering based on 'after' | ||
| 236 | /// dependencies and ID. | ||
| 237 | /// </remarks> | ||
| 238 | private class TopologicalSort | ||
| 239 | { | ||
| 240 | private List<string> startIds = new List<string>(); | ||
| 241 | private Constraints constraints; | ||
| 242 | |||
| 243 | /// <summary> | ||
| 244 | /// Reorder by topological sort | ||
| 245 | /// </summary> | ||
| 246 | /// <param name="allIds">The complete list of IDs.</param> | ||
| 247 | /// <param name="constraints">Constraints to use.</param> | ||
| 248 | /// <returns>The topologically sorted list of IDs.</returns> | ||
| 249 | internal List<string> Sort(IEnumerable<string> allIds, Constraints constraints) | ||
| 250 | { | ||
| 251 | this.startIds.Clear(); | ||
| 252 | this.CopyConstraints(constraints); | ||
| 253 | |||
| 254 | this.FindInitialStartIds(allIds); | ||
| 255 | |||
| 256 | // We always create a new sortedId list, because we return it | ||
| 257 | // to the caller and don't know what its lifetime may be. | ||
| 258 | List<string> sortedIds = new List<string>(); | ||
| 259 | |||
| 260 | while (this.startIds.Count > 0) | ||
| 261 | { | ||
| 262 | this.SortStartIds(); | ||
| 263 | |||
| 264 | string currentId = this.startIds[0]; | ||
| 265 | sortedIds.Add(currentId); | ||
| 266 | this.startIds.RemoveAt(0); | ||
| 267 | |||
| 268 | this.ResolveConstraint(currentId); | ||
| 269 | } | ||
| 270 | |||
| 271 | return sortedIds; | ||
| 272 | } | ||
| 273 | |||
| 274 | /// <summary> | ||
| 275 | /// Copies a Constraints set (to prevent modifying the incoming data). | ||
| 276 | /// </summary> | ||
| 277 | /// <param name="constraints">Constraints to copy.</param> | ||
| 278 | private void CopyConstraints(Constraints constraints) | ||
| 279 | { | ||
| 280 | this.constraints = new Constraints(); | ||
| 281 | foreach (string id in constraints.Keys) | ||
| 282 | { | ||
| 283 | foreach (string afterId in constraints[id]) | ||
| 284 | { | ||
| 285 | this.constraints.AddConstraint(id, afterId); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | /// <summary> | ||
| 291 | /// Finds initial start IDs. (Those with no constraints.) | ||
| 292 | /// </summary> | ||
| 293 | /// <param name="allIds">The complete list of IDs.</param> | ||
| 294 | private void FindInitialStartIds(IEnumerable<string> allIds) | ||
| 295 | { | ||
| 296 | foreach (string id in allIds) | ||
| 297 | { | ||
| 298 | if (!this.constraints.ContainsKey(id)) | ||
| 299 | { | ||
| 300 | this.startIds.Add(id); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | /// <summary> | ||
| 306 | /// Sorts start IDs. | ||
| 307 | /// </summary> | ||
| 308 | private void SortStartIds() | ||
| 309 | { | ||
| 310 | this.startIds.Sort(); | ||
| 311 | } | ||
| 312 | |||
| 313 | /// <summary> | ||
| 314 | /// Removes the resolved constraint and updates the list of startIds | ||
| 315 | /// with any now-valid (all constraints resolved) IDs. | ||
| 316 | /// </summary> | ||
| 317 | /// <param name="resolvedId">The ID to resolve from the set of constraints.</param> | ||
| 318 | private void ResolveConstraint(string resolvedId) | ||
| 319 | { | ||
| 320 | List<string> newStartIds = new List<string>(); | ||
| 321 | |||
| 322 | foreach (string id in constraints.Keys) | ||
| 323 | { | ||
| 324 | if (this.constraints[id].Contains(resolvedId)) | ||
| 325 | { | ||
| 326 | this.constraints[id].Remove(resolvedId); | ||
| 327 | |||
| 328 | // If we just removed the last constraint for this | ||
| 329 | // ID, it is now a valid start ID. | ||
| 330 | if (0 == this.constraints[id].Count) | ||
| 331 | { | ||
| 332 | newStartIds.Add(id); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | foreach (string id in newStartIds) | ||
| 338 | { | ||
| 339 | this.constraints.Remove(id); | ||
| 340 | } | ||
| 341 | |||
| 342 | this.startIds.AddRange(newStartIds); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | } | ||
| 346 | #endif | ||
| 347 | } | ||
diff --git a/src/wixext/UtilCompiler.cs b/src/wixext/UtilCompiler.cs index 6b359591..6e3c2531 100644 --- a/src/wixext/UtilCompiler.cs +++ b/src/wixext/UtilCompiler.cs | |||
| @@ -230,6 +230,8 @@ namespace WixToolset.Util | |||
| 230 | break; | 230 | break; |
| 231 | case "ComponentSearch": | 231 | case "ComponentSearch": |
| 232 | case "ComponentSearchRef": | 232 | case "ComponentSearchRef": |
| 233 | case "DetectSHA2Support": | ||
| 234 | case "DetectSHA2SupportRef": | ||
| 233 | case "DirectorySearch": | 235 | case "DirectorySearch": |
| 234 | case "DirectorySearchRef": | 236 | case "DirectorySearchRef": |
| 235 | case "FileSearch": | 237 | case "FileSearch": |
| @@ -251,6 +253,12 @@ namespace WixToolset.Util | |||
| 251 | case "ComponentSearchRef": | 253 | case "ComponentSearchRef": |
| 252 | this.ParseComponentSearchRefElement(intermediate, section, element); | 254 | this.ParseComponentSearchRefElement(intermediate, section, element); |
| 253 | break; | 255 | break; |
| 256 | case "DetectSHA2Support": | ||
| 257 | this.ParseDetectSHA2SupportElement(intermediate, section, element); | ||
| 258 | break; | ||
| 259 | case "DetectSHA2SupportRef": | ||
| 260 | this.ParseDetectSHA2SupportRefElement(intermediate, section, element); | ||
| 261 | break; | ||
| 254 | case "DirectorySearch": | 262 | case "DirectorySearch": |
| 255 | this.ParseDirectorySearchElement(intermediate, section, element); | 263 | this.ParseDirectorySearchElement(intermediate, section, element); |
| 256 | break; | 264 | break; |
| @@ -422,11 +430,6 @@ namespace WixToolset.Util | |||
| 422 | } | 430 | } |
| 423 | } | 431 | } |
| 424 | 432 | ||
| 425 | if (null == variable) | ||
| 426 | { | ||
| 427 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Variable")); | ||
| 428 | } | ||
| 429 | |||
| 430 | if (null == guid) | 433 | if (null == guid) |
| 431 | { | 434 | { |
| 432 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Guid")); | 435 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Guid")); |
| @@ -439,16 +442,10 @@ namespace WixToolset.Util | |||
| 439 | 442 | ||
| 440 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | 443 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); |
| 441 | 444 | ||
| 445 | this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); | ||
| 446 | |||
| 442 | if (!this.Messaging.EncounteredError) | 447 | if (!this.Messaging.EncounteredError) |
| 443 | { | 448 | { |
| 444 | this.CreateWixSearchRow(section, sourceLineNumbers, id, variable, condition); | ||
| 445 | if (after != null) | ||
| 446 | { | ||
| 447 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixSearch", after); | ||
| 448 | // TODO: We're currently defaulting to "always run after", which we will need to change... | ||
| 449 | this.CreateWixSearchRelationRow(section, sourceLineNumbers, id, after, 2); | ||
| 450 | } | ||
| 451 | |||
| 452 | WixComponentSearchAttributes attributes = WixComponentSearchAttributes.KeyPath; | 449 | WixComponentSearchAttributes attributes = WixComponentSearchAttributes.KeyPath; |
| 453 | switch (result) | 450 | switch (result) |
| 454 | { | 451 | { |
| @@ -506,6 +503,89 @@ namespace WixToolset.Util | |||
| 506 | } | 503 | } |
| 507 | 504 | ||
| 508 | /// <summary> | 505 | /// <summary> |
| 506 | /// Parses a DetectSHA2Support element. | ||
| 507 | /// </summary> | ||
| 508 | /// <param name="element">Element to parse.</param> | ||
| 509 | private void ParseDetectSHA2SupportElement(Intermediate intermediate, IntermediateSection section, XElement element) | ||
| 510 | { | ||
| 511 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 512 | Identifier id = null; | ||
| 513 | string variable = null; | ||
| 514 | string condition = null; | ||
| 515 | string after = null; | ||
| 516 | |||
| 517 | foreach (var attrib in element.Attributes()) | ||
| 518 | { | ||
| 519 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 520 | { | ||
| 521 | switch (attrib.Name.LocalName) | ||
| 522 | { | ||
| 523 | case "Id": | ||
| 524 | case "Variable": | ||
| 525 | case "Condition": | ||
| 526 | case "After": | ||
| 527 | this.ParseCommonSearchAttributes(sourceLineNumbers, attrib, ref id, ref variable, ref condition, ref after); | ||
| 528 | break; | ||
| 529 | default: | ||
| 530 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | else | ||
| 535 | { | ||
| 536 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | if (id == null) | ||
| 541 | { | ||
| 542 | id = this.ParseHelper.CreateIdentifier("wds2s", variable, condition, after); | ||
| 543 | } | ||
| 544 | |||
| 545 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 546 | |||
| 547 | this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, UtilConstants.UtilBundleExtensionId); | ||
| 548 | |||
| 549 | if (!this.Messaging.EncounteredError) | ||
| 550 | { | ||
| 551 | section.Tuples.Add(new WixDetectSHA2SupportTuple(sourceLineNumbers, id)); | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | /// <summary> | ||
| 556 | /// Parses a DetectSHA2SupportRef element | ||
| 557 | /// </summary> | ||
| 558 | /// <param name="element">Element to parse.</param> | ||
| 559 | private void ParseDetectSHA2SupportRefElement(Intermediate intermediate, IntermediateSection section, XElement element) | ||
| 560 | { | ||
| 561 | var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); | ||
| 562 | string refId = null; | ||
| 563 | |||
| 564 | foreach (var attrib in element.Attributes()) | ||
| 565 | { | ||
| 566 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 567 | { | ||
| 568 | switch (attrib.Name.LocalName) | ||
| 569 | { | ||
| 570 | case "Id": | ||
| 571 | refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 572 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixDetectSHA2Support", refId); | ||
| 573 | break; | ||
| 574 | default: | ||
| 575 | this.ParseHelper.UnexpectedAttribute(element, attrib); | ||
| 576 | break; | ||
| 577 | } | ||
| 578 | } | ||
| 579 | else | ||
| 580 | { | ||
| 581 | this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | ||
| 586 | } | ||
| 587 | |||
| 588 | /// <summary> | ||
| 509 | /// Parses an event source element. | 589 | /// Parses an event source element. |
| 510 | /// </summary> | 590 | /// </summary> |
| 511 | /// <param name="element">Element to parse.</param> | 591 | /// <param name="element">Element to parse.</param> |
| @@ -868,11 +948,6 @@ namespace WixToolset.Util | |||
| 868 | } | 948 | } |
| 869 | } | 949 | } |
| 870 | 950 | ||
| 871 | if (null == variable) | ||
| 872 | { | ||
| 873 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Variable")); | ||
| 874 | } | ||
| 875 | |||
| 876 | if (null == path) | 951 | if (null == path) |
| 877 | { | 952 | { |
| 878 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); | 953 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path")); |
| @@ -885,16 +960,10 @@ namespace WixToolset.Util | |||
| 885 | 960 | ||
| 886 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | 961 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); |
| 887 | 962 | ||
| 963 | this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); | ||
| 964 | |||
| 888 | if (!this.Messaging.EncounteredError) | 965 | if (!this.Messaging.EncounteredError) |
| 889 | { | 966 | { |
| 890 | this.CreateWixSearchRow(section, sourceLineNumbers, id, variable, condition); | ||
| 891 | if (after != null) | ||
| 892 | { | ||
| 893 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixSearch", after); | ||
| 894 | // TODO: We're currently defaulting to "always run after", which we will need to change... | ||
| 895 | this.CreateWixSearchRelationRow(section, sourceLineNumbers, id, after, 2); | ||
| 896 | } | ||
| 897 | |||
| 898 | WixFileSearchAttributes attributes = WixFileSearchAttributes.IsDirectory; | 967 | WixFileSearchAttributes attributes = WixFileSearchAttributes.IsDirectory; |
| 899 | switch (result) | 968 | switch (result) |
| 900 | { | 969 | { |
| @@ -990,11 +1059,6 @@ namespace WixToolset.Util | |||
| 990 | } | 1059 | } |
| 991 | } | 1060 | } |
| 992 | 1061 | ||
| 993 | if (null == variable) | ||
| 994 | { | ||
| 995 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Variable")); | ||
| 996 | } | ||
| 997 | |||
| 998 | if (null == path) | 1062 | if (null == path) |
| 999 | { | 1063 | { |
| 1000 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Path")); | 1064 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Path")); |
| @@ -1007,16 +1071,10 @@ namespace WixToolset.Util | |||
| 1007 | 1071 | ||
| 1008 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); | 1072 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); |
| 1009 | 1073 | ||
| 1074 | this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, node.Name.LocalName, id, variable, condition, after, null); | ||
| 1075 | |||
| 1010 | if (!this.Messaging.EncounteredError) | 1076 | if (!this.Messaging.EncounteredError) |
| 1011 | { | 1077 | { |
| 1012 | this.CreateWixSearchRow(section, sourceLineNumbers, id, variable, condition); | ||
| 1013 | if (after != null) | ||
| 1014 | { | ||
| 1015 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixSearch", after); | ||
| 1016 | // TODO: We're currently defaulting to "always run after", which we will need to change... | ||
| 1017 | this.CreateWixSearchRelationRow(section, sourceLineNumbers, id, after, 2); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | WixFileSearchAttributes attributes = WixFileSearchAttributes.Default; | 1078 | WixFileSearchAttributes attributes = WixFileSearchAttributes.Default; |
| 1021 | switch (result) | 1079 | switch (result) |
| 1022 | { | 1080 | { |
| @@ -1049,38 +1107,6 @@ namespace WixToolset.Util | |||
| 1049 | } | 1107 | } |
| 1050 | 1108 | ||
| 1051 | /// <summary> | 1109 | /// <summary> |
| 1052 | /// Creates a row in the WixSearch table. | ||
| 1053 | /// </summary> | ||
| 1054 | /// <param name="sourceLineNumbers">Source line number for the parent element.</param> | ||
| 1055 | /// <param name="id">Identifier of the search.</param> | ||
| 1056 | /// <param name="variable">The Burn variable to store the result into.</param> | ||
| 1057 | /// <param name="condition">A condition to test before evaluating the search.</param> | ||
| 1058 | private void CreateWixSearchRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string variable, string condition) | ||
| 1059 | { | ||
| 1060 | section.Tuples.Add(new WixSearchTuple(sourceLineNumbers, id) | ||
| 1061 | { | ||
| 1062 | Variable = variable, | ||
| 1063 | Condition = condition, | ||
| 1064 | }); | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | /// <summary> | ||
| 1068 | /// | ||
| 1069 | /// </summary> | ||
| 1070 | /// <param name="sourceLineNumbers">Source line number for the parent element.</param> | ||
| 1071 | /// <param name="id">Identifier of the search (key into the WixSearch table)</param> | ||
| 1072 | /// <param name="parentId">Identifier of the search that comes before (key into the WixSearch table)</param> | ||
| 1073 | /// <param name="attributes">Further details about the relation between id and parentId.</param> | ||
| 1074 | private void CreateWixSearchRelationRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, int attributes) | ||
| 1075 | { | ||
| 1076 | section.Tuples.Add(new WixSearchRelationTuple(sourceLineNumbers, id) | ||
| 1077 | { | ||
| 1078 | ParentSearchRef = parentId, | ||
| 1079 | Attributes = attributes, | ||
| 1080 | }); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | /// <summary> | ||
| 1084 | /// Parses a file share element. | 1110 | /// Parses a file share element. |
| 1085 | /// </summary> | 1111 | /// </summary> |
| 1086 | /// <param name="element">Element to parse.</param> | 1112 | /// <param name="element">Element to parse.</param> |
| @@ -2523,11 +2549,6 @@ namespace WixToolset.Util | |||
| 2523 | } | 2549 | } |
| 2524 | } | 2550 | } |
| 2525 | 2551 | ||
| 2526 | if (null == variable) | ||
| 2527 | { | ||
| 2528 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Variable")); | ||
| 2529 | } | ||
| 2530 | |||
| 2531 | if (null == upgradeCode && null == productCode) | 2552 | if (null == upgradeCode && null == productCode) |
| 2532 | { | 2553 | { |
| 2533 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ProductCode", "UpgradeCode", true)); | 2554 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ProductCode", "UpgradeCode", true)); |
| @@ -2545,16 +2566,10 @@ namespace WixToolset.Util | |||
| 2545 | 2566 | ||
| 2546 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | 2567 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); |
| 2547 | 2568 | ||
| 2569 | this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); | ||
| 2570 | |||
| 2548 | if (!this.Messaging.EncounteredError) | 2571 | if (!this.Messaging.EncounteredError) |
| 2549 | { | 2572 | { |
| 2550 | this.CreateWixSearchRow(section, sourceLineNumbers, id, variable, condition); | ||
| 2551 | if (after != null) | ||
| 2552 | { | ||
| 2553 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixSearch", after); | ||
| 2554 | // TODO: We're currently defaulting to "always run after", which we will need to change... | ||
| 2555 | this.CreateWixSearchRelationRow(section, sourceLineNumbers, id, after, 2); | ||
| 2556 | } | ||
| 2557 | |||
| 2558 | WixProductSearchAttributes attributes = WixProductSearchAttributes.Version; | 2573 | WixProductSearchAttributes attributes = WixProductSearchAttributes.Version; |
| 2559 | switch (result) | 2574 | switch (result) |
| 2560 | { | 2575 | { |
| @@ -2662,11 +2677,6 @@ namespace WixToolset.Util | |||
| 2662 | } | 2677 | } |
| 2663 | } | 2678 | } |
| 2664 | 2679 | ||
| 2665 | if (null == variable) | ||
| 2666 | { | ||
| 2667 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Variable")); | ||
| 2668 | } | ||
| 2669 | |||
| 2670 | if (!root.HasValue) | 2680 | if (!root.HasValue) |
| 2671 | { | 2681 | { |
| 2672 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root")); | 2682 | this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Root")); |
| @@ -2726,16 +2736,10 @@ namespace WixToolset.Util | |||
| 2726 | 2736 | ||
| 2727 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); | 2737 | this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); |
| 2728 | 2738 | ||
| 2739 | this.ParseHelper.CreateWixSearchTuple(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, null); | ||
| 2740 | |||
| 2729 | if (!this.Messaging.EncounteredError) | 2741 | if (!this.Messaging.EncounteredError) |
| 2730 | { | 2742 | { |
| 2731 | this.CreateWixSearchRow(section, sourceLineNumbers, id, variable, condition); | ||
| 2732 | if (after != null) | ||
| 2733 | { | ||
| 2734 | this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixSearch", after); | ||
| 2735 | // TODO: We're currently defaulting to "always run after", which we will need to change... | ||
| 2736 | this.CreateWixSearchRelationRow(section, sourceLineNumbers, id, after, 2); | ||
| 2737 | } | ||
| 2738 | |||
| 2739 | section.Tuples.Add(new WixRegistrySearchTuple(sourceLineNumbers, id) | 2743 | section.Tuples.Add(new WixRegistrySearchTuple(sourceLineNumbers, id) |
| 2740 | { | 2744 | { |
| 2741 | Root = (RegistryRootType)root, | 2745 | Root = (RegistryRootType)root, |
diff --git a/src/wixext/UtilConstants.cs b/src/wixext/UtilConstants.cs index 28ff368f..d9ad460f 100644 --- a/src/wixext/UtilConstants.cs +++ b/src/wixext/UtilConstants.cs | |||
| @@ -13,5 +13,7 @@ namespace WixToolset.Util | |||
| 13 | internal static readonly string[] RegistryPermissions = { "Read", "Write", "CreateSubkeys", "EnumerateSubkeys", "Notify", "CreateLink" }; | 13 | internal static readonly string[] RegistryPermissions = { "Read", "Write", "CreateSubkeys", "EnumerateSubkeys", "Notify", "CreateLink" }; |
| 14 | internal static readonly string[] ServicePermissions = { "ServiceQueryConfig", "ServiceChangeConfig", "ServiceQueryStatus", "ServiceEnumerateDependents", "ServiceStart", "ServiceStop", "ServicePauseContinue", "ServiceInterrogate", "ServiceUserDefinedControl" }; | 14 | internal static readonly string[] ServicePermissions = { "ServiceQueryConfig", "ServiceChangeConfig", "ServiceQueryStatus", "ServiceEnumerateDependents", "ServiceStart", "ServiceStop", "ServicePauseContinue", "ServiceInterrogate", "ServiceUserDefinedControl" }; |
| 15 | internal static readonly string[] StandardPermissions = { "Delete", "ReadPermission", "ChangePermission", "TakeOwnership", "Synchronize" }; | 15 | internal static readonly string[] StandardPermissions = { "Delete", "ReadPermission", "ChangePermission", "TakeOwnership", "Synchronize" }; |
| 16 | |||
| 17 | internal const string UtilBundleExtensionId = "WixUtilBundleExtension"; | ||
| 16 | } | 18 | } |
| 17 | } | 19 | } |
diff --git a/src/wixext/UtilErrors.cs b/src/wixext/UtilErrors.cs index 988b8321..c04f0449 100644 --- a/src/wixext/UtilErrors.cs +++ b/src/wixext/UtilErrors.cs | |||
| @@ -13,11 +13,6 @@ namespace WixToolset.Util | |||
| 13 | return Message(null, Ids.ArgumentRequiresValue, "The argument '{0}' does not have a value specified and it is required.", argument); | 13 | return Message(null, Ids.ArgumentRequiresValue, "The argument '{0}' does not have a value specified and it is required.", argument); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | public static Message CircularSearchReference(string chain) | ||
| 17 | { | ||
| 18 | return Message(null, Ids.CircularSearchReference, "A circular reference of search ordering constraints was detected: {0}. Search ordering references must form a directed acyclic graph.", chain); | ||
| 19 | } | ||
| 20 | |||
| 21 | public static Message DirectoryNotFound(string directory) | 16 | public static Message DirectoryNotFound(string directory) |
| 22 | { | 17 | { |
| 23 | return Message(null, Ids.DirectoryNotFound, "The directory '{0}' could not be found.", directory); | 18 | return Message(null, Ids.DirectoryNotFound, "The directory '{0}' could not be found.", directory); |
| @@ -102,7 +97,6 @@ namespace WixToolset.Util | |||
| 102 | FileNotFound = 5059, | 97 | FileNotFound = 5059, |
| 103 | PerformanceCategoryNotFound = 5060, | 98 | PerformanceCategoryNotFound = 5060, |
| 104 | UnsupportedPerformanceCounterType = 5061, | 99 | UnsupportedPerformanceCounterType = 5061, |
| 105 | CircularSearchReference = 5062, | ||
| 106 | InvalidRegistryObject = 5063, | 100 | InvalidRegistryObject = 5063, |
| 107 | } | 101 | } |
| 108 | } | 102 | } |
diff --git a/src/wixext/util.xsd b/src/wixext/util.xsd index fb8d8032..a8c3d208 100644 --- a/src/wixext/util.xsd +++ b/src/wixext/util.xsd | |||
| @@ -172,6 +172,30 @@ | |||
| 172 | <xs:attribute name="Id" type="xs:string" use="required" /> | 172 | <xs:attribute name="Id" type="xs:string" use="required" /> |
| 173 | </xs:complexType> | 173 | </xs:complexType> |
| 174 | </xs:element> | 174 | </xs:element> |
| 175 | <xs:element name="DetectSHA2Support"> | ||
| 176 | <xs:annotation> | ||
| 177 | <xs:documentation>Detects support for SHA2.</xs:documentation> | ||
| 178 | <xs:appinfo> | ||
| 179 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Bundle" /> | ||
| 180 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
| 181 | </xs:appinfo> | ||
| 182 | </xs:annotation> | ||
| 183 | <xs:complexType> | ||
| 184 | <xs:attributeGroup ref="SearchCommonAttributes" /> | ||
| 185 | </xs:complexType> | ||
| 186 | </xs:element> | ||
| 187 | <xs:element name="DetectSHA2SupportRef"> | ||
| 188 | <xs:annotation> | ||
| 189 | <xs:documentation>References a DetectSHA2Support.</xs:documentation> | ||
| 190 | <xs:appinfo> | ||
| 191 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Bundle" /> | ||
| 192 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
| 193 | </xs:appinfo> | ||
| 194 | </xs:annotation> | ||
| 195 | <xs:complexType> | ||
| 196 | <xs:attribute name="Id" type="xs:string" use="required" /> | ||
| 197 | </xs:complexType> | ||
| 198 | </xs:element> | ||
| 175 | <xs:element name="DirectorySearch"> | 199 | <xs:element name="DirectorySearch"> |
| 176 | <xs:annotation> | 200 | <xs:annotation> |
| 177 | <xs:documentation>Describes a directory search.</xs:documentation> | 201 | <xs:documentation>Describes a directory search.</xs:documentation> |
