From 0afd76e4c5d46f237591d860e7d445e267522187 Mon Sep 17 00:00:00 2001 From: Sean Hall <r.sean.hall@gmail.com> Date: Mon, 30 Mar 2020 19:46:56 +1000 Subject: Add DetectSHA2Support "search". --- src/be/UtilBundleExtension.cpp | 87 ++++++++++++++++++++++++++ src/be/UtilBundleExtension.h | 16 +++++ src/be/detectsha2support.cpp | 58 +++++++++++++++++ src/be/detectsha2support.h | 8 +++ src/be/packages.config | 1 + src/be/precomp.h | 23 +++++-- src/be/utilbe.cpp | 28 ++++++++- src/be/utilbe.vcxproj | 20 +++--- src/be/utilsearch.cpp | 137 +++++++++++++++++++++++++++++++++++++++++ src/be/utilsearch.h | 52 ++++++++++++++++ 10 files changed, 410 insertions(+), 20 deletions(-) create mode 100644 src/be/UtilBundleExtension.cpp create mode 100644 src/be/UtilBundleExtension.h create mode 100644 src/be/detectsha2support.cpp create mode 100644 src/be/detectsha2support.h create mode 100644 src/be/utilsearch.cpp create mode 100644 src/be/utilsearch.h (limited to 'src/be') 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 @@ +// 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. + +#include "precomp.h" +#include "BextBaseBundleExtension.h" + +class CWixUtilBundleExtension : public CBextBaseBundleExtension +{ +public: // IBundleExtension + virtual STDMETHODIMP Search( + __in LPCWSTR wzId, + __in LPCWSTR wzVariable + ) + { + HRESULT hr = S_OK; + + hr = UtilSearchExecute(&m_searches, wzId, wzVariable, m_pEngine); + + return hr; + } + +public: //CBextBaseBundleExtension + virtual STDMETHODIMP Initialize( + __in const BUNDLE_EXTENSION_CREATE_ARGS* pCreateArgs + ) + { + HRESULT hr = S_OK; + IXMLDOMDocument* pixdManifest = NULL; + IXMLDOMNode* pixnBundleExtension = NULL; + + hr = CBextBaseBundleExtension::Initialize(pCreateArgs); + ExitOnFailure(hr, "CBextBaseBundleExtension initialization failed."); + + hr = XmlLoadDocumentFromFile(m_sczBundleExtensionDataPath, &pixdManifest); + ExitOnFailure(hr, "Failed to load bundle extension manifest from path: %ls", m_sczBundleExtensionDataPath); + + hr = BextGetBundleExtensionDataNode(pixdManifest, UTIL_BUNDLE_EXTENSION_ID, &pixnBundleExtension); + ExitOnFailure(hr, "Failed to get BundleExtension '%ls'", UTIL_BUNDLE_EXTENSION_ID); + + hr = UtilSearchParseFromXml(&m_searches, pixnBundleExtension); + ExitOnFailure(hr, "Failed to parse searches from bundle extension manifest."); + + LExit: + ReleaseObject(pixnBundleExtension); + ReleaseObject(pixdManifest); + + return hr; + } + +public: + CWixUtilBundleExtension( + __in IBundleExtensionEngine* pEngine + ) : CBextBaseBundleExtension(pEngine) + { + m_searches = { }; + } + + ~CWixUtilBundleExtension() + { + UtilSearchUninitialize(&m_searches); + } + +private: + UTIL_SEARCHES m_searches; +}; + +HRESULT UtilBundleExtensionCreate( + __in IBundleExtensionEngine* pEngine, + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __out IBundleExtension** ppBundleExtension + ) +{ + HRESULT hr = S_OK; + CWixUtilBundleExtension* pExtension = NULL; + + pExtension = new CWixUtilBundleExtension(pEngine); + ExitOnNull(pExtension, hr, E_OUTOFMEMORY, "Failed to create new CWixUtilBundleExtension."); + + hr = pExtension->Initialize(pArgs); + ExitOnFailure(hr, "CWixUtilBundleExtension initialization failed"); + + *ppBundleExtension = pExtension; + pExtension = NULL; + +LExit: + ReleaseObject(pExtension); + return hr; +} 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 @@ +#pragma once +// 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. + + +// constants + +#define UTIL_BUNDLE_EXTENSION_ID L"WixUtilBundleExtension" + + +// function declarations + +HRESULT UtilBundleExtensionCreate( + __in IBundleExtensionEngine* pEngine, + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __out IBundleExtension** ppBundleExtension + ); 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 @@ +// 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. + +#include "precomp.h" + +// https://gist.github.com/navossoc/7572c7d82243e9f818989e2765e7793a +HRESULT DetectSHA2Support( + __out BOOL* pfSupported + ) +{ + HRESULT hr = S_OK; + HMODULE hModule = NULL; + FARPROC pfn = NULL; + DWORD er = ERROR_SUCCESS; + + hr = LoadSystemLibrary(L"wintrust.dll", &hModule); + ExitOnFailure(hr, "Failed to load wintrust.dll"); + + pfn = ::GetProcAddress(hModule, "CryptCATAdminAcquireContext2"); + if (pfn) + { + *pfSupported = TRUE; + ExitFunction1(hr = S_OK); + } + + er = ::GetLastError(); + if (er == ERROR_PROC_NOT_FOUND) + { + *pfSupported = FALSE; + ExitFunction1(hr = S_OK); + } + + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "Failed to probe for CryptCATAdminAcquireContext2 in wintrust.dll"); + +LExit: + ::FreeLibrary(hModule); + + return hr; +} + +HRESULT UtilPerformDetectSHA2Support( + __in LPCWSTR wzVariable, + __in UTIL_SEARCH* /*pSearch*/, + __in IBundleExtensionEngine* pEngine + ) +{ + HRESULT hr = S_OK; + BOOL fSupported = FALSE; + + hr = DetectSHA2Support(&fSupported); + ExitOnFailure(hr, "DetectSHA2Support failed."); + + hr = pEngine->SetVariableNumeric(wzVariable, fSupported ? 1 : 0); + ExitOnFailure(hr, "Failed to set variable '%ls'", wzVariable); + +LExit: + return hr; +} 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 @@ +#pragma once +// 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. + +HRESULT UtilPerformDetectSHA2Support( + __in LPCWSTR wzVariable, + __in UTIL_SEARCH* pSearch, + __in IBundleExtensionEngine* pEngine + ); \ 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 @@ <?xml version="1.0" encoding="utf-8"?> <packages> + <package id="WixToolset.BextUtil" version="4.0.16" targetFramework="native" /> <package id="WixToolset.BootstrapperCore.Native" version="4.0.13" targetFramework="native" /> <package id="WixToolset.DUtil" version="4.0.18" targetFramework="native" /> </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 @@ #define MAXUINT USHRT_MAX -#include "dutil.h" -#include "memutil.h" - -#include "BootstrapperEngine.h" -#include "BundleExtensionEngine.h" -#include "BundleExtension.h" +#include <dutil.h> +#include <memutil.h> +#include <strutil.h> +#include <pathutil.h> +#include <xmlutil.h> + +#include <BundleExtensionEngine.h> +#include <BundleExtension.h> + +#include <IBundleExtensionEngine.h> +#include <IBundleExtension.h> +#include <bextutil.h> +#include <BextBundleExtensionEngine.h> + +#include "utilsearch.h" +#include "detectsha2support.h" +#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 @@ // 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. #include "precomp.h" +#include "BextBaseBundleExtensionProc.h" + +static IBundleExtension* vpBundleExtension = NULL; // function definitions extern "C" HRESULT WINAPI BundleExtensionCreate( - __in const BUNDLE_EXTENSION_CREATE_ARGS* /*pArgs*/, - __inout BUNDLE_EXTENSION_CREATE_RESULTS* /*pResults*/ + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __inout BUNDLE_EXTENSION_CREATE_RESULTS* pResults ) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; + IBundleExtensionEngine* pEngine = NULL; + + hr = XmlInitialize(); + ExitOnFailure(hr, "Failed to initialize XML."); + + hr = BextInitializeFromCreateArgs(pArgs, &pEngine); + ExitOnFailure(hr, "Failed to initialize bext"); + + hr = UtilBundleExtensionCreate(pEngine, pArgs, &vpBundleExtension); + BextExitOnFailure(hr, "Failed to create WixUtilBundleExtension"); + + pResults->pfnBundleExtensionProc = BextBaseBundleExtensionProc; + pResults->pvBundleExtensionProcContext = vpBundleExtension; + +LExit: + ReleaseObject(pEngine); return hr; } extern "C" void WINAPI BundleExtensionDestroy() { + BextUninitialize(); + ReleaseNullObject(vpBundleExtension); + XmlUninitialize(); } \ 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 @@ <?xml version="1.0" encoding="utf-8"?> <!-- 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. --> - <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="..\..\packages\WixToolset.BextUtil.4.0.16\build\WixToolset.BextUtil.props" Condition="Exists('..\..\packages\WixToolset.BextUtil.4.0.16\build\WixToolset.BextUtil.props')" /> <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')" /> <Import Project="..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.18\build\WixToolset.DUtil.props')" /> - <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -15,7 +14,6 @@ <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> - <PropertyGroup Label="Globals"> <ProjectGuid>{630C1EE7-2517-4A8C-83E3-DA1150308B58}</ProjectGuid> <ConfigurationType>DynamicLibrary</ConfigurationType> @@ -25,37 +23,37 @@ <ProjectModuleDefinitionFile>utilbe.def</ProjectModuleDefinitionFile> <Description>WiX Toolset Util BundleExtension</Description> </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <PropertyGroup> <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries> </PropertyGroup> - <ItemGroup> + <ClCompile Include="detectsha2support.cpp" /> <ClCompile Include="precomp.cpp"> <PrecompiledHeader>Create</PrecompiledHeader> </ClCompile> <ClCompile Include="utilbe.cpp" /> + <ClCompile Include="UtilBundleExtension.cpp" /> + <ClCompile Include="utilsearch.cpp" /> </ItemGroup> - <ItemGroup> + <ClInclude Include="detectsha2support.h" /> <ClInclude Include="precomp.h" /> + <ClInclude Include="UtilBundleExtension.h" /> + <ClInclude Include="utilsearch.h" /> </ItemGroup> - <ItemGroup> <None Include="packages.config" /> <None Include="utilbe.def" /> </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <PropertyGroup> <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> </PropertyGroup> + <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'))" /> <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'))" /> <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'))" /> </Target> -</Project> +</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 @@ +// 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. + +#include "precomp.h" + + +STDMETHODIMP UtilSearchParseFromXml( + __in UTIL_SEARCHES* pSearches, + __in IXMLDOMNode* pixnBundleExtension + ) +{ + HRESULT hr = S_OK; + IXMLDOMNodeList* pixnNodes = NULL; + IXMLDOMNode* pixnNode = NULL; + DWORD cNodes = 0; + BSTR bstrNodeName = NULL; + + // Select Util search nodes. + hr = XmlSelectNodes(pixnBundleExtension, L"WixDetectSHA2Support", &pixnNodes); + ExitOnFailure(hr, "Failed to select Util search nodes."); + + // Get Util search node count. + hr = pixnNodes->get_length((long*)&cNodes); + ExitOnFailure(hr, "Failed to get Util search node count."); + + if (!cNodes) + { + ExitFunction(); + } + + // Allocate memory for searches. + pSearches->rgSearches = (UTIL_SEARCH*)MemAlloc(sizeof(UTIL_SEARCH) * cNodes, TRUE); + ExitOnNull(pSearches->rgSearches, hr, E_OUTOFMEMORY, "Failed to allocate memory for search structs."); + + pSearches->cSearches = cNodes; + + // Parse search elements. + for (DWORD i = 0; i < cNodes; ++i) + { + UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; + + hr = XmlNextElement(pixnNodes, &pixnNode, &bstrNodeName); + ExitOnFailure(hr, "Failed to get next node."); + + // @Id + hr = XmlGetAttributeEx(pixnNode, L"Id", &pSearch->sczId); + ExitOnFailure(hr, "Failed to get @Id."); + + // Read type specific attributes. + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"WixDetectSHA2Support", -1)) + { + pSearch->Type = UTIL_SEARCH_TYPE_DETECT_SHA2_SUPPORT; + } + else + { + hr = E_UNEXPECTED; + ExitOnFailure(hr, "Unexpected element name: %ls", bstrNodeName); + } + + // prepare next iteration + ReleaseNullObject(pixnNode); + ReleaseNullBSTR(bstrNodeName); + } + +LExit: + ReleaseBSTR(bstrNodeName); + ReleaseObject(pixnNode); + ReleaseObject(pixnNodes); + + return hr; +} + +void UtilSearchUninitialize( + __in UTIL_SEARCHES* pSearches + ) +{ + if (pSearches->rgSearches) + { + for (DWORD i = 0; i < pSearches->cSearches; ++i) + { + UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; + + ReleaseStr(pSearch->sczId); + } + MemFree(pSearches->rgSearches); + } +} + +STDMETHODIMP UtilSearchExecute( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzSearchId, + __in LPCWSTR wzVariable, + __in IBundleExtensionEngine* pEngine + ) +{ + HRESULT hr = S_OK; + UTIL_SEARCH* pSearch = NULL; + + hr = UtilSearchFindById(pSearches, wzSearchId, &pSearch); + ExitOnFailure(hr, "Search id '%ls' is unknown to the util extension."); + + switch (pSearch->Type) + { + case UTIL_SEARCH_TYPE_DETECT_SHA2_SUPPORT: + hr = UtilPerformDetectSHA2Support(wzVariable, pSearch, pEngine); + break; + default: + hr = E_UNEXPECTED; + } + +LExit: + return hr; +} + +STDMETHODIMP UtilSearchFindById( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzId, + __out UTIL_SEARCH** ppSearch + ) +{ + HRESULT hr = S_OK; + + for (DWORD i = 0; i < pSearches->cSearches; ++i) + { + UTIL_SEARCH* pSearch = &pSearches->rgSearches[i]; + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pSearch->sczId, -1, wzId, -1)) + { + *ppSearch = pSearch; + ExitFunction1(hr = S_OK); + } + } + + hr = E_NOTFOUND; + +LExit: + return hr; +} 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 @@ +#pragma once +// 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. + + +// constants + +enum UTIL_SEARCH_TYPE +{ + UTIL_SEARCH_TYPE_NONE, + UTIL_SEARCH_TYPE_DETECT_SHA2_SUPPORT, +}; + + +// structs + +typedef struct _UTIL_SEARCH +{ + LPWSTR sczId; + + UTIL_SEARCH_TYPE Type; +} UTIL_SEARCH; + +typedef struct _UTIL_SEARCHES +{ + UTIL_SEARCH* rgSearches; + DWORD cSearches; +} UTIL_SEARCHES; + + +// function declarations + +STDMETHODIMP UtilSearchParseFromXml( + __in UTIL_SEARCHES* pSearches, + __in IXMLDOMNode* pixnBundleExtension + ); + +void UtilSearchUninitialize( + __in UTIL_SEARCHES* pSearches + ); + +STDMETHODIMP UtilSearchExecute( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzSearchId, + __in LPCWSTR wzVariable, + __in IBundleExtensionEngine* pEngine + ); + +STDMETHODIMP UtilSearchFindById( + __in UTIL_SEARCHES* pSearches, + __in LPCWSTR wzId, + __out UTIL_SEARCH** ppSearch + ); -- cgit v1.2.3-55-g6feb