From 51af2090a7c911d0ae1b8232b11ca67613adf3ef Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 30 Mar 2020 18:52:22 +1000 Subject: Add bextutil. --- appveyor.cmd | 1 + balutil.sln | 10 + src/bextutil/BextBundleExtensionEngine.cpp | 331 +++++++++++++++++++++++++ src/bextutil/bextutil.cpp | 179 +++++++++++++ src/bextutil/bextutil.nuspec | 26 ++ src/bextutil/bextutil.vcxproj | 86 +++++++ src/bextutil/build/WixToolset.BextUtil.props | 23 ++ src/bextutil/inc/BextBaseBundleExtension.h | 120 +++++++++ src/bextutil/inc/BextBaseBundleExtensionProc.h | 48 ++++ src/bextutil/inc/BextBundleExtensionEngine.h | 17 ++ src/bextutil/inc/IBundleExtension.h | 20 ++ src/bextutil/inc/IBundleExtensionEngine.h | 64 +++++ src/bextutil/inc/bextutil.h | 76 ++++++ src/bextutil/packages.config | 6 + src/bextutil/precomp.cpp | 3 + src/bextutil/precomp.h | 22 ++ 16 files changed, 1032 insertions(+) create mode 100644 src/bextutil/BextBundleExtensionEngine.cpp create mode 100644 src/bextutil/bextutil.cpp create mode 100644 src/bextutil/bextutil.nuspec create mode 100644 src/bextutil/bextutil.vcxproj create mode 100644 src/bextutil/build/WixToolset.BextUtil.props create mode 100644 src/bextutil/inc/BextBaseBundleExtension.h create mode 100644 src/bextutil/inc/BextBaseBundleExtensionProc.h create mode 100644 src/bextutil/inc/BextBundleExtensionEngine.h create mode 100644 src/bextutil/inc/IBundleExtension.h create mode 100644 src/bextutil/inc/IBundleExtensionEngine.h create mode 100644 src/bextutil/inc/bextutil.h create mode 100644 src/bextutil/packages.config create mode 100644 src/bextutil/precomp.cpp create mode 100644 src/bextutil/precomp.h diff --git a/appveyor.cmd b/appveyor.cmd index 1aceb3b0..8a7782de 100644 --- a/appveyor.cmd +++ b/appveyor.cmd @@ -8,6 +8,7 @@ msbuild -p:Configuration=Release;Platform=x86;PlatformToolset=v140_xp msbuild -p:Configuration=Release;Platform=x86;PlatformToolset=v141_xp msbuild -p:Configuration=Release -t:Pack src\balutil\balutil.vcxproj +msbuild -p:Configuration=Release -t:Pack src\bextutil\bextutil.vcxproj msbuild -p:Configuration=Release -t:Pack src\WixToolset.Mba.Core\WixToolset.Mba.Core.csproj @popd diff --git a/balutil.sln b/balutil.sln index 37d391fc..73df2292 100644 --- a/balutil.sln +++ b/balutil.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29503.13 MinimumVisualStudioVersion = 15.0.26124.0 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "balutil", "src\balutil\balutil.vcxproj", "{EDCB8095-0E6A-43E0-BC33-C4F762FC5CDB}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bextutil", "src\bextutil\bextutil.vcxproj", "{06027492-1CB9-48BC-B31E-C1F9356ED07E}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixToolset.Mba.Core", "src\WixToolset.Mba.Core\WixToolset.Mba.Core.csproj", "{E7E1841E-A58E-4901-B9CA-4845B807D45F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbanative", "src\mbanative\mbanative.vcxproj", "{665E0441-17F9-4105-B202-EDF274657F6E}" @@ -27,6 +29,14 @@ Global {EDCB8095-0E6A-43E0-BC33-C4F762FC5CDB}.Release|x64.Build.0 = Release|x64 {EDCB8095-0E6A-43E0-BC33-C4F762FC5CDB}.Release|x86.ActiveCfg = Release|Win32 {EDCB8095-0E6A-43E0-BC33-C4F762FC5CDB}.Release|x86.Build.0 = Release|Win32 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Debug|x64.ActiveCfg = Debug|x64 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Debug|x64.Build.0 = Debug|x64 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Debug|x86.ActiveCfg = Debug|Win32 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Debug|x86.Build.0 = Debug|Win32 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Release|x64.ActiveCfg = Release|x64 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Release|x64.Build.0 = Release|x64 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Release|x86.ActiveCfg = Release|Win32 + {06027492-1CB9-48BC-B31E-C1F9356ED07E}.Release|x86.Build.0 = Release|Win32 {E7E1841E-A58E-4901-B9CA-4845B807D45F}.Debug|x64.ActiveCfg = Debug|Any CPU {E7E1841E-A58E-4901-B9CA-4845B807D45F}.Debug|x64.Build.0 = Debug|Any CPU {E7E1841E-A58E-4901-B9CA-4845B807D45F}.Debug|x86.ActiveCfg = Debug|Any CPU diff --git a/src/bextutil/BextBundleExtensionEngine.cpp b/src/bextutil/BextBundleExtensionEngine.cpp new file mode 100644 index 00000000..02070a6f --- /dev/null +++ b/src/bextutil/BextBundleExtensionEngine.cpp @@ -0,0 +1,331 @@ +// 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" + + +class CBextBundleExtensionEngine : public IBundleExtensionEngine +{ +public: // IUnknown + virtual STDMETHODIMP QueryInterface( + __in REFIID riid, + __out LPVOID *ppvObject + ) + { + if (!ppvObject) + { + return E_INVALIDARG; + } + + *ppvObject = NULL; + + if (::IsEqualIID(__uuidof(IBundleExtensionEngine), riid)) + { + *ppvObject = static_cast(this); + } + else if (::IsEqualIID(IID_IUnknown, riid)) + { + *ppvObject = reinterpret_cast(this); + } + else // no interface for requested iid + { + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; + } + + virtual STDMETHODIMP_(ULONG) AddRef() + { + return ::InterlockedIncrement(&this->m_cReferences); + } + + virtual STDMETHODIMP_(ULONG) Release() + { + long l = ::InterlockedDecrement(&this->m_cReferences); + if (0 < l) + { + return l; + } + + delete this; + return 0; + } + +public: // IBundleExtensionEngine + virtual STDMETHODIMP EscapeString( + __in_z LPCWSTR wzIn, + __out_ecount_opt(*pcchOut) LPWSTR wzOut, + __inout DWORD* pcchOut + ) + { + HRESULT hr = S_OK; + BUNDLE_EXTENSION_ENGINE_ESCAPESTRING_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_ESCAPESTRING_RESULTS results = { }; + + ExitOnNull(pcchOut, hr, E_INVALIDARG, "pcchOut is required"); + + args.cbSize = sizeof(args); + args.wzIn = wzIn; + + results.cbSize = sizeof(results); + results.wzOut = wzOut; + results.cchOut = *pcchOut; + + hr = m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_ESCAPESTRING, &args, &results, m_pvBundleExtensionEngineProcContext); + + *pcchOut = results.cchOut; + + LExit: + return hr; + } + + virtual STDMETHODIMP EvaluateCondition( + __in_z LPCWSTR wzCondition, + __out BOOL* pf + ) + { + HRESULT hr = S_OK; + BUNDLE_EXTENSION_ENGINE_EVALUATECONDITION_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_EVALUATECONDITION_RESULTS results = { }; + + ExitOnNull(pf, hr, E_INVALIDARG, "pf is required"); + + args.cbSize = sizeof(args); + args.wzCondition = wzCondition; + + results.cbSize = sizeof(results); + + hr = m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_EVALUATECONDITION, &args, &results, m_pvBundleExtensionEngineProcContext); + + *pf = results.f; + + LExit: + return hr; + } + + virtual STDMETHODIMP FormatString( + __in_z LPCWSTR wzIn, + __out_ecount_opt(*pcchOut) LPWSTR wzOut, + __inout DWORD* pcchOut + ) + { + HRESULT hr = S_OK; + BUNDLE_EXTENSION_ENGINE_FORMATSTRING_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_FORMATSTRING_RESULTS results = { }; + + ExitOnNull(pcchOut, hr, E_INVALIDARG, "pcchOut is required"); + + args.cbSize = sizeof(args); + args.wzIn = wzIn; + + results.cbSize = sizeof(results); + results.wzOut = wzOut; + results.cchOut = *pcchOut; + + hr = m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_FORMATSTRING, &args, &results, m_pvBundleExtensionEngineProcContext); + + *pcchOut = results.cchOut; + + LExit: + return hr; + } + + virtual STDMETHODIMP GetVariableNumeric( + __in_z LPCWSTR wzVariable, + __out LONGLONG* pllValue + ) + { + HRESULT hr = S_OK; + BUNDLE_EXTENSION_ENGINE_GETVARIABLENUMERIC_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_GETVARIABLENUMERIC_RESULTS results = { }; + + ExitOnNull(pllValue, hr, E_INVALIDARG, "pllValue is required"); + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + + results.cbSize = sizeof(results); + + hr = m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_GETVARIABLENUMERIC, &args, &results, m_pvBundleExtensionEngineProcContext); + + *pllValue = results.llValue; + + LExit: + SecureZeroMemory(&results, sizeof(results)); + return hr; + } + + virtual STDMETHODIMP GetVariableString( + __in_z LPCWSTR wzVariable, + __out_ecount_opt(*pcchValue) LPWSTR wzValue, + __inout DWORD* pcchValue + ) + { + HRESULT hr = S_OK; + BUNDLE_EXTENSION_ENGINE_GETVARIABLESTRING_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_GETVARIABLESTRING_RESULTS results = { }; + + ExitOnNull(pcchValue, hr, E_INVALIDARG, "pcchValue is required"); + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + + results.cbSize = sizeof(results); + results.wzValue = wzValue; + results.cchValue = *pcchValue; + + hr = m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_GETVARIABLESTRING, &args, &results, m_pvBundleExtensionEngineProcContext); + + *pcchValue = results.cchValue; + + LExit: + return hr; + } + + virtual STDMETHODIMP GetVariableVersion( + __in_z LPCWSTR wzVariable, + __out DWORD64* pqwValue + ) + { + HRESULT hr = S_OK; + BUNDLE_EXTENSION_ENGINE_GETVARIABLEVERSION_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_GETVARIABLEVERSION_RESULTS results = { }; + + ExitOnNull(pqwValue, hr, E_INVALIDARG, "pqwValue is required"); + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + + results.cbSize = sizeof(results); + + hr = m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_GETVARIABLEVERSION, &args, &results, m_pvBundleExtensionEngineProcContext); + + *pqwValue = results.qwValue; + + LExit: + SecureZeroMemory(&results, sizeof(results)); + return hr; + } + + virtual STDMETHODIMP Log( + __in BUNDLE_EXTENSION_LOG_LEVEL level, + __in_z LPCWSTR wzMessage + ) + { + BUNDLE_EXTENSION_ENGINE_LOG_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_LOG_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.level = level; + args.wzMessage = wzMessage; + + results.cbSize = sizeof(results); + + return m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_LOG, &args, &results, m_pvBundleExtensionEngineProcContext); + } + + virtual STDMETHODIMP SetVariableLiteralString( + __in_z LPCWSTR wzVariable, + __in_z_opt LPCWSTR wzValue + ) + { + BUNDLE_EXTENSION_ENGINE_SETVARIABLELITERALSTRING_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_SETVARIABLELITERALSTRING_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + args.wzValue = wzValue; + + results.cbSize = sizeof(results); + + return m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_SETVARIABLELITERALSTRING, &args, &results, m_pvBundleExtensionEngineProcContext); + } + + virtual STDMETHODIMP SetVariableNumeric( + __in_z LPCWSTR wzVariable, + __in LONGLONG llValue + ) + { + BUNDLE_EXTENSION_ENGINE_SETVARIABLENUMERIC_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_SETVARIABLENUMERIC_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + args.llValue = llValue; + + results.cbSize = sizeof(results); + + return m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_SETVARIABLENUMERIC, &args, &results, m_pvBundleExtensionEngineProcContext); + } + + virtual STDMETHODIMP SetVariableString( + __in_z LPCWSTR wzVariable, + __in_z_opt LPCWSTR wzValue + ) + { + BUNDLE_EXTENSION_ENGINE_SETVARIABLESTRING_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_SETVARIABLESTRING_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + args.wzValue = wzValue; + + results.cbSize = sizeof(results); + + return m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_SETVARIABLESTRING, &args, &results, m_pvBundleExtensionEngineProcContext); + } + + virtual STDMETHODIMP SetVariableVersion( + __in_z LPCWSTR wzVariable, + __in DWORD64 qwValue + ) + { + BUNDLE_EXTENSION_ENGINE_SETVARIABLEVERSION_ARGS args = { }; + BUNDLE_EXTENSION_ENGINE_SETVARIABLEVERSION_RESULTS results = { }; + + args.cbSize = sizeof(args); + args.wzVariable = wzVariable; + args.qwValue = qwValue; + + results.cbSize = sizeof(results); + + return m_pfnBundleExtensionEngineProc(BUNDLE_EXTENSION_ENGINE_MESSAGE_SETVARIABLEVERSION, &args, &results, m_pvBundleExtensionEngineProcContext); + } + +public: + CBextBundleExtensionEngine( + __in PFN_BUNDLE_EXTENSION_ENGINE_PROC pfnBundleExtensionEngineProc, + __in_opt LPVOID pvBundleExtensionEngineProcContext + ) + { + m_cReferences = 1; + m_pfnBundleExtensionEngineProc = pfnBundleExtensionEngineProc; + m_pvBundleExtensionEngineProcContext = pvBundleExtensionEngineProcContext; + } + +private: + long m_cReferences; + PFN_BUNDLE_EXTENSION_ENGINE_PROC m_pfnBundleExtensionEngineProc; + LPVOID m_pvBundleExtensionEngineProcContext; +}; + +HRESULT BextBundleExtensionEngineCreate( + __in PFN_BUNDLE_EXTENSION_ENGINE_PROC pfnBundleExtensionEngineProc, + __in_opt LPVOID pvBundleExtensionEngineProcContext, + __out IBundleExtensionEngine** ppEngineForExtension + ) +{ + HRESULT hr = S_OK; + CBextBundleExtensionEngine* pBundleExtensionEngine = NULL; + + pBundleExtensionEngine = new CBextBundleExtensionEngine(pfnBundleExtensionEngineProc, pvBundleExtensionEngineProcContext); + ExitOnNull(pBundleExtensionEngine, hr, E_OUTOFMEMORY, "Failed to allocate new BextBundleExtensionEngine object."); + + hr = pBundleExtensionEngine->QueryInterface(IID_PPV_ARGS(ppEngineForExtension)); + ExitOnFailure(hr, "Failed to QI for IBundleExtensionEngine from BextBundleExtensionEngine object."); + +LExit: + ReleaseObject(pBundleExtensionEngine); + return hr; +} diff --git a/src/bextutil/bextutil.cpp b/src/bextutil/bextutil.cpp new file mode 100644 index 00000000..baf35591 --- /dev/null +++ b/src/bextutil/bextutil.cpp @@ -0,0 +1,179 @@ +// 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" + +static IBundleExtensionEngine* vpEngine = NULL; + +// prototypes + +DAPI_(void) BextInitialize( + __in IBundleExtensionEngine* pEngine + ) +{ + pEngine->AddRef(); + + ReleaseObject(vpEngine); + vpEngine = pEngine; +} + +DAPI_(HRESULT) BextInitializeFromCreateArgs( + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __out_opt IBundleExtensionEngine** ppEngine + ) +{ + HRESULT hr = S_OK; + IBundleExtensionEngine* pEngine = NULL; + + hr = BextBundleExtensionEngineCreate(pArgs->pfnBundleExtensionEngineProc, pArgs->pvBundleExtensionEngineProcContext, &pEngine); + ExitOnFailure(hr, "Failed to create BextBundleExtensionEngine."); + + BextInitialize(pEngine); + + if (ppEngine) + { + *ppEngine = pEngine; + } + pEngine = NULL; + +LExit: + ReleaseObject(pEngine); + + return hr; +} + + +DAPI_(void) BextUninitialize() +{ + ReleaseNullObject(vpEngine); +} + +DAPI_(HRESULT) BextGetBundleExtensionDataNode( + __in IXMLDOMDocument* pixdManifest, + __in LPCWSTR wzExtensionId, + __out IXMLDOMNode** ppixnBundleExtension + ) +{ + HRESULT hr = S_OK; + IXMLDOMElement* pixeBundleExtensionData = NULL; + IXMLDOMNodeList* pixnNodes = NULL; + IXMLDOMNode* pixnNode = NULL; + DWORD cNodes = 0; + LPWSTR sczId = NULL; + + // Get BundleExtensionData element. + hr = pixdManifest->get_documentElement(&pixeBundleExtensionData); + ExitOnFailure(hr, "Failed to get BundleExtensionData element."); + + // Select BundleExtension nodes. + hr = XmlSelectNodes(pixeBundleExtensionData, L"BundleExtension", &pixnNodes); + ExitOnFailure(hr, "Failed to select BundleExtension nodes."); + + // Get BundleExtension node count. + hr = pixnNodes->get_length((long*)&cNodes); + ExitOnFailure(hr, "Failed to get BundleExtension node count."); + + if (!cNodes) + { + ExitFunction(); + } + + // Find requested extension. + for (DWORD i = 0; i < cNodes; ++i) + { + hr = XmlNextElement(pixnNodes, &pixnNode, NULL); + ExitOnFailure(hr, "Failed to get next node."); + + // @Id + hr = XmlGetAttributeEx(pixnNode, L"Id", &sczId); + ExitOnFailure(hr, "Failed to get @Id."); + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczId, -1, wzExtensionId, -1)) + { + *ppixnBundleExtension = pixnNode; + pixnNode = NULL; + + ExitFunction1(hr = S_OK); + } + + // Prepare next iteration. + ReleaseNullObject(pixnNode); + } + + hr = E_NOTFOUND; + +LExit: + ReleaseStr(sczId); + ReleaseObject(pixnNode); + ReleaseObject(pixnNodes); + ReleaseObject(pixeBundleExtensionData); + + return hr; +} + + +DAPIV_(HRESULT) BextLog( + __in BUNDLE_EXTENSION_LOG_LEVEL level, + __in_z __format_string LPCSTR szFormat, + ... + ) +{ + HRESULT hr = S_OK; + va_list args; + LPSTR sczFormattedAnsi = NULL; + LPWSTR sczMessage = NULL; + + if (!vpEngine) + { + hr = E_POINTER; + ExitOnRootFailure(hr, "BextInitialize() must be called first."); + } + + va_start(args, szFormat); + hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args); + va_end(args); + ExitOnFailure(hr, "Failed to format log string."); + + hr = StrAllocStringAnsi(&sczMessage, sczFormattedAnsi, 0, CP_UTF8); + ExitOnFailure(hr, "Failed to convert log string to Unicode."); + + hr = vpEngine->Log(level, sczMessage); + +LExit: + ReleaseStr(sczMessage); + ReleaseStr(sczFormattedAnsi); + return hr; +} + + +DAPIV_(HRESULT) BextLogError( + __in HRESULT hrError, + __in_z __format_string LPCSTR szFormat, + ... + ) +{ + HRESULT hr = S_OK; + va_list args; + LPSTR sczFormattedAnsi = NULL; + LPWSTR sczMessage = NULL; + + if (!vpEngine) + { + hr = E_POINTER; + ExitOnRootFailure(hr, "BextInitialize() must be called first."); + } + + va_start(args, szFormat); + hr = StrAnsiAllocFormattedArgs(&sczFormattedAnsi, szFormat, args); + va_end(args); + ExitOnFailure(hr, "Failed to format error log string."); + + hr = StrAllocFormatted(&sczMessage, L"Error 0x%08x: %S", hrError, sczFormattedAnsi); + ExitOnFailure(hr, "Failed to prepend error number to error log string."); + + hr = vpEngine->Log(BUNDLE_EXTENSION_LOG_LEVEL_ERROR, sczMessage); + +LExit: + ReleaseStr(sczMessage); + ReleaseStr(sczFormattedAnsi); + return hr; +} diff --git a/src/bextutil/bextutil.nuspec b/src/bextutil/bextutil.nuspec new file mode 100644 index 00000000..30e0871d --- /dev/null +++ b/src/bextutil/bextutil.nuspec @@ -0,0 +1,26 @@ + + + + $id$ + $version$ + $authors$ + $authors$ + + https://licenses.nuget.org/MS-RL + https://github.com/wixtoolset/balutil + false + $description$ + $copyright$ + + + + + + + + + + + + + diff --git a/src/bextutil/bextutil.vcxproj b/src/bextutil/bextutil.vcxproj new file mode 100644 index 00000000..3deb3317 --- /dev/null +++ b/src/bextutil/bextutil.vcxproj @@ -0,0 +1,86 @@ + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + {06027492-1CB9-48BC-B31E-C1F9356ED07E} + StaticLibrary + bextutil + v141 + MultiByte + WiX Toolset Bundle Extension native utility library + + + + + + + + + + + + + + + $(ProjectDir)..\inc + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + 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}. + + + + + + diff --git a/src/bextutil/build/WixToolset.BextUtil.props b/src/bextutil/build/WixToolset.BextUtil.props new file mode 100644 index 00000000..3e2980ec --- /dev/null +++ b/src/bextutil/build/WixToolset.BextUtil.props @@ -0,0 +1,23 @@ + + + + + + + $(MSBuildThisFileDirectory)native\include\;%(AdditionalIncludeDirectories) + + + $(MSBuildThisFileDirectory)native\include\;%(AdditionalIncludeDirectories) + + + + + $(MSBuildThisFileDirectory)native\v140\$(PlatformTarget)\bextutil.lib;%(AdditionalDependencies) + + + + + $(MSBuildThisFileDirectory)native\v141\$(PlatformTarget)\bextutil.lib;%(AdditionalDependencies) + + + diff --git a/src/bextutil/inc/BextBaseBundleExtension.h b/src/bextutil/inc/BextBaseBundleExtension.h new file mode 100644 index 00000000..69c338e4 --- /dev/null +++ b/src/bextutil/inc/BextBaseBundleExtension.h @@ -0,0 +1,120 @@ +// 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 + +#include "BundleExtensionEngine.h" +#include "BundleExtension.h" +#include "IBundleExtensionEngine.h" +#include "IBundleExtension.h" + +#include "bextutil.h" + +class CBextBaseBundleExtension : public IBundleExtension +{ +public: // IUnknown + virtual STDMETHODIMP QueryInterface( + __in REFIID riid, + __out LPVOID *ppvObject + ) + { + if (!ppvObject) + { + return E_INVALIDARG; + } + + *ppvObject = NULL; + + if (::IsEqualIID(__uuidof(IBundleExtension), riid)) + { + *ppvObject = static_cast(this); + } + else if (::IsEqualIID(IID_IUnknown, riid)) + { + *ppvObject = static_cast(this); + } + else // no interface for requested iid + { + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; + } + + virtual STDMETHODIMP_(ULONG) AddRef() + { + return ::InterlockedIncrement(&this->m_cReferences); + } + + virtual STDMETHODIMP_(ULONG) Release() + { + long l = ::InterlockedDecrement(&this->m_cReferences); + if (0 < l) + { + return l; + } + + delete this; + return 0; + } + +public: // IBundleExtension + virtual STDMETHODIMP Search( + __in LPCWSTR /*wzId*/, + __in LPCWSTR /*wzVariable*/ + ) + { + return E_NOTIMPL; + } + + virtual STDMETHODIMP BundleExtensionProc( + __in BUNDLE_EXTENSION_MESSAGE /*message*/, + __in const LPVOID /*pvArgs*/, + __inout LPVOID /*pvResults*/, + __in_opt LPVOID /*pvContext*/ + ) + { + return E_NOTIMPL; + } + +public: //CBextBaseBundleExtension + virtual STDMETHODIMP Initialize( + __in const BUNDLE_EXTENSION_CREATE_ARGS* pCreateArgs + ) + { + HRESULT hr = S_OK; + + hr = StrAllocString(&m_sczBundleExtensionDataPath, pCreateArgs->wzBundleExtensionDataPath, 0); + ExitOnFailure(hr, "Failed to copy BundleExtensionDataPath."); + + LExit: + return hr; + } + +protected: + + CBextBaseBundleExtension( + __in IBundleExtensionEngine* pEngine + ) + { + m_cReferences = 1; + + pEngine->AddRef(); + m_pEngine = pEngine; + + m_sczBundleExtensionDataPath = NULL; + } + + virtual ~CBextBaseBundleExtension() + { + ReleaseNullObject(m_pEngine); + ReleaseStr(m_sczBundleExtensionDataPath); + } + +protected: + IBundleExtensionEngine* m_pEngine; + LPWSTR m_sczBundleExtensionDataPath; + +private: + long m_cReferences; +}; diff --git a/src/bextutil/inc/BextBaseBundleExtensionProc.h b/src/bextutil/inc/BextBaseBundleExtensionProc.h new file mode 100644 index 00000000..f71e3b92 --- /dev/null +++ b/src/bextutil/inc/BextBaseBundleExtensionProc.h @@ -0,0 +1,48 @@ +#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. + + +#include + +#include "BundleExtensionEngine.h" +#include "BundleExtension.h" +#include "IBundleExtensionEngine.h" +#include "IBundleExtension.h" + +static HRESULT BextBaseBEProcSearch( + __in IBundleExtension* pBE, + __in BUNDLE_EXTENSION_SEARCH_ARGS* pArgs, + __inout BUNDLE_EXTENSION_SEARCH_RESULTS* /*pResults*/ + ) +{ + return pBE->Search(pArgs->wzId, pArgs->wzVariable); +} + +/******************************************************************* +BextBaseBundleExtensionProc - requires pvContext to be of type IBundleExtension. + Provides a default mapping between the message based + BundleExtension interface and the COM-based BundleExtension interface. + +*******************************************************************/ +static HRESULT WINAPI BextBaseBundleExtensionProc( + __in BUNDLE_EXTENSION_MESSAGE message, + __in const LPVOID pvArgs, + __inout LPVOID pvResults, + __in_opt LPVOID pvContext + ) +{ + IBundleExtension* pBE = reinterpret_cast(pvContext); + HRESULT hr = pBE->BundleExtensionProc(message, pvArgs, pvResults, pvContext); + + if (E_NOTIMPL == hr) + { + switch (message) + { + case BUNDLE_EXTENSION_MESSAGE_SEARCH: + hr = BextBaseBEProcSearch(pBE, reinterpret_cast(pvArgs), reinterpret_cast(pvResults)); + break; + } + } + + return hr; +} diff --git a/src/bextutil/inc/BextBundleExtensionEngine.h b/src/bextutil/inc/BextBundleExtensionEngine.h new file mode 100644 index 00000000..9fdcb700 --- /dev/null +++ b/src/bextutil/inc/BextBundleExtensionEngine.h @@ -0,0 +1,17 @@ +// 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. + +#ifdef __cplusplus +extern "C" { +#endif + +// function declarations + +HRESULT BextBundleExtensionEngineCreate( + __in PFN_BUNDLE_EXTENSION_ENGINE_PROC pfnBundleExtensionEngineProc, + __in_opt LPVOID pvBundleExtensionEngineProcContext, + __out IBundleExtensionEngine** ppEngineForExtension + ); + +#ifdef __cplusplus +} +#endif diff --git a/src/bextutil/inc/IBundleExtension.h b/src/bextutil/inc/IBundleExtension.h new file mode 100644 index 00000000..7516c11b --- /dev/null +++ b/src/bextutil/inc/IBundleExtension.h @@ -0,0 +1,20 @@ +#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. + + +DECLARE_INTERFACE_IID_(IBundleExtension, IUnknown, "93123C9D-796B-4FCD-A507-6EDEF9A925FD") +{ + STDMETHOD(Search)( + __in LPCWSTR wzId, + __in LPCWSTR wzVariable + ) = 0; + + // BundleExtensionProc - The PFN_BUNDLE_EXTENSION_PROC can call this method to give the BundleExtension raw access to the callback from the engine. + // This might be used to help the BundleExtension support more than one version of the engine. + STDMETHOD(BundleExtensionProc)( + __in BUNDLE_EXTENSION_MESSAGE message, + __in const LPVOID pvArgs, + __inout LPVOID pvResults, + __in_opt LPVOID pvContext + ) = 0; +}; diff --git a/src/bextutil/inc/IBundleExtensionEngine.h b/src/bextutil/inc/IBundleExtensionEngine.h new file mode 100644 index 00000000..869c6695 --- /dev/null +++ b/src/bextutil/inc/IBundleExtensionEngine.h @@ -0,0 +1,64 @@ +#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. + + +DECLARE_INTERFACE_IID_(IBundleExtensionEngine, IUnknown, "9D027A39-F6B6-42CC-9737-C185089EB263") +{ + STDMETHOD(EscapeString)( + __in_z LPCWSTR wzIn, + __out_ecount_opt(*pcchOut) LPWSTR wzOut, + __inout DWORD * pcchOut + ) = 0; + + STDMETHOD(EvaluateCondition)( + __in_z LPCWSTR wzCondition, + __out BOOL * pf + ) = 0; + + STDMETHOD(FormatString)( + __in_z LPCWSTR wzIn, + __out_ecount_opt(*pcchOut) LPWSTR wzOut, + __inout DWORD * pcchOut + ) = 0; + + STDMETHOD(GetVariableNumeric)( + __in_z LPCWSTR wzVariable, + __out LONGLONG* pllValue + ) = 0; + + STDMETHOD(GetVariableString)( + __in_z LPCWSTR wzVariable, + __out_ecount_opt(*pcchValue) LPWSTR wzValue, + __inout DWORD* pcchValue + ) = 0; + + STDMETHOD(GetVariableVersion)( + __in_z LPCWSTR wzVariable, + __out DWORD64* pqwValue + ) = 0; + + STDMETHOD(Log)( + __in BUNDLE_EXTENSION_LOG_LEVEL level, + __in_z LPCWSTR wzMessage + ) = 0; + + STDMETHOD(SetVariableLiteralString)( + __in_z LPCWSTR wzVariable, + __in_z_opt LPCWSTR wzValue + ) = 0; + + STDMETHOD(SetVariableNumeric)( + __in_z LPCWSTR wzVariable, + __in LONGLONG llValue + ) = 0; + + STDMETHOD(SetVariableString)( + __in_z LPCWSTR wzVariable, + __in_z_opt LPCWSTR wzValue + ) = 0; + + STDMETHOD(SetVariableVersion)( + __in_z LPCWSTR wzVariable, + __in DWORD64 qwValue + ) = 0; +}; diff --git a/src/bextutil/inc/bextutil.h b/src/bextutil/inc/bextutil.h new file mode 100644 index 00000000..0472f854 --- /dev/null +++ b/src/bextutil/inc/bextutil.h @@ -0,0 +1,76 @@ +#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. + + +#include "dutil.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define BextExitOnFailure(x, f, ...) if (FAILED(x)) { BextLogError(x, f, __VA_ARGS__); ExitTrace(x, f, __VA_ARGS__); goto LExit; } +#define BextExitOnRootFailure(x, f, ...) if (FAILED(x)) { BextLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTrace(x, f, __VA_ARGS__); goto LExit; } +#define BextExitOnNullWithLastError(p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); ExitTrace(x, f, __VA_ARGS__); goto LExit; } + +const LPCWSTR BUNDLE_EXTENSION_MANIFEST_FILENAME = L"BundleExtensionData.xml"; + + +/******************************************************************* + BextInitialize - remembers the engine interface to enable logging and + other functions. + +********************************************************************/ +DAPI_(void) BextInitialize( + __in IBundleExtensionEngine* pEngine + ); + +/******************************************************************* + BextInitializeFromCreateArgs - convenience function to call BextBundleExtensionEngineCreate + then pass it along to BextInitialize. + +********************************************************************/ +DAPI_(HRESULT) BextInitializeFromCreateArgs( + __in const BUNDLE_EXTENSION_CREATE_ARGS* pArgs, + __out IBundleExtensionEngine** ppEngine + ); + +/******************************************************************* + BextUninitialize - cleans up utility layer internals. + +********************************************************************/ +DAPI_(void) BextUninitialize(); + +/******************************************************************* + BextGetBundleExtensionDataNode - gets the requested BundleExtension node. + +********************************************************************/ +DAPI_(HRESULT) BextGetBundleExtensionDataNode( + __in IXMLDOMDocument* pixdManifest, + __in LPCWSTR wzExtensionId, + __out IXMLDOMNode** ppixnBundleExtension + ); + +/******************************************************************* + BextLog - logs a message with the engine. + +********************************************************************/ +DAPIV_(HRESULT) BextLog( + __in BUNDLE_EXTENSION_LOG_LEVEL level, + __in_z __format_string LPCSTR szFormat, + ... + ); + +/******************************************************************* + BextLogError - logs an error message with the engine. + +********************************************************************/ +DAPIV_(HRESULT) BextLogError( + __in HRESULT hr, + __in_z __format_string LPCSTR szFormat, + ... + ); + +#ifdef __cplusplus +} +#endif diff --git a/src/bextutil/packages.config b/src/bextutil/packages.config new file mode 100644 index 00000000..75a6476b --- /dev/null +++ b/src/bextutil/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/bextutil/precomp.cpp b/src/bextutil/precomp.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/bextutil/precomp.cpp @@ -0,0 +1,3 @@ +// 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" diff --git a/src/bextutil/precomp.h b/src/bextutil/precomp.h new file mode 100644 index 00000000..5d1dd20b --- /dev/null +++ b/src/bextutil/precomp.h @@ -0,0 +1,22 @@ +#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. + + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "IBundleExtensionEngine.h" +#include "IBundleExtension.h" + +#include "bextutil.h" +#include "BextBundleExtensionEngine.h" -- cgit v1.2.3-55-g6feb